1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1996,2008 Oracle. All rights reserved. 5 * 6 * $Id: crdel_rec.c,v 12.28 2008/02/18 04:46:42 mjc Exp $ 7 */ 8 9#include "db_config.h" 10 11#include "db_int.h" 12#include "dbinc/db_page.h" 13#include "dbinc/fop.h" 14#include "dbinc/hash.h" 15#include "dbinc/log.h" 16#include "dbinc/mp.h" 17#include "dbinc/txn.h" 18 19/* 20 * __crdel_metasub_recover -- 21 * Recovery function for metasub. 22 * 23 * PUBLIC: int __crdel_metasub_recover 24 * PUBLIC: __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); 25 */ 26int 27__crdel_metasub_recover(env, dbtp, lsnp, op, info) 28 ENV *env; 29 DBT *dbtp; 30 DB_LSN *lsnp; 31 db_recops op; 32 void *info; 33{ 34 __crdel_metasub_args *argp; 35 DB_THREAD_INFO *ip; 36 DB *file_dbp; 37 DBC *dbc; 38 DB_MPOOLFILE *mpf; 39 PAGE *pagep; 40 int cmp_p, ret, t_ret; 41 42 ip = ((DB_TXNHEAD *)info)->thread_info; 43 pagep = NULL; 44 REC_PRINT(__crdel_metasub_print); 45 REC_INTRO(__crdel_metasub_read, ip, 0); 46 47 if ((ret = __memp_fget(mpf, &argp->pgno, 48 ip, NULL, 0, &pagep)) != 0) { 49 /* If this is an in-memory file, this might be OK. */ 50 if (F_ISSET(file_dbp, DB_AM_INMEM) && 51 (ret = __memp_fget(mpf, &argp->pgno, ip, NULL, 52 DB_MPOOL_CREATE | DB_MPOOL_DIRTY, &pagep)) == 0) { 53 LSN_NOT_LOGGED(LSN(pagep)); 54 } else { 55 *lsnp = argp->prev_lsn; 56 ret = 0; 57 goto out; 58 } 59 } 60 61 cmp_p = LOG_COMPARE(&LSN(pagep), &argp->lsn); 62 CHECK_LSN(env, op, cmp_p, &LSN(pagep), &argp->lsn); 63 64 if (cmp_p == 0 && DB_REDO(op)) { 65 REC_DIRTY(mpf, ip, file_dbp->priority, &pagep); 66 memcpy(pagep, argp->page.data, argp->page.size); 67 LSN(pagep) = *lsnp; 68 69 /* 70 * If this was an in-memory database and we are re-creating 71 * and this is the meta-data page, then we need to set up a 72 * bunch of fields in the dbo as well. 73 */ 74 if (F_ISSET(file_dbp, DB_AM_INMEM) && 75 argp->pgno == PGNO_BASE_MD && 76 (ret = __db_meta_setup(file_dbp->env, file_dbp, 77 file_dbp->dname, (DBMETA *)pagep, 0, DB_CHK_META)) != 0) 78 goto out; 79 } else if (DB_UNDO(op)) { 80 /* 81 * We want to undo this page creation. The page creation 82 * happened in two parts. First, we called __bam_new which 83 * was logged separately. Then we wrote the meta-data onto 84 * the page. So long as we restore the LSN, then the recovery 85 * for __bam_new will do everything else. 86 * 87 * Don't bother checking the lsn on the page. If we are 88 * rolling back the next thing is that this page will get 89 * freed. Opening the subdb will have reinitialized the 90 * page, but not the lsn. 91 */ 92 REC_DIRTY(mpf, ip, file_dbp->priority, &pagep); 93 LSN(pagep) = argp->lsn; 94 } 95 96done: *lsnp = argp->prev_lsn; 97 ret = 0; 98 99out: if (pagep != NULL && (t_ret = __memp_fput(mpf, 100 ip, pagep, file_dbp->priority)) != 0 && 101 ret == 0) 102 ret = t_ret; 103 104 REC_CLOSE; 105} 106 107/* 108 * __crdel_inmem_create_recover -- 109 * Recovery function for inmem_create. 110 * 111 * PUBLIC: int __crdel_inmem_create_recover 112 * PUBLIC: __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); 113 */ 114int 115__crdel_inmem_create_recover(env, dbtp, lsnp, op, info) 116 ENV *env; 117 DBT *dbtp; 118 DB_LSN *lsnp; 119 db_recops op; 120 void *info; 121{ 122 __crdel_inmem_create_args *argp; 123 DB *dbp; 124 int do_close, ret, t_ret; 125 126 COMPQUIET(info, NULL); 127 128 dbp = NULL; 129 do_close = 0; 130 REC_PRINT(__crdel_inmem_create_print); 131 REC_NOOP_INTRO(__crdel_inmem_create_read); 132 133 /* First, see if the DB handle already exists. */ 134 if (argp->fileid == DB_LOGFILEID_INVALID) { 135 if (DB_REDO(op)) 136 ret = ENOENT; 137 else 138 ret = 0; 139 } else 140 ret = __dbreg_id_to_db(env, argp->txnp, &dbp, argp->fileid, 0); 141 142 if (DB_REDO(op)) { 143 /* 144 * If the dbreg failed, that means that we're creating a 145 * tmp file. 146 */ 147 if (ret != 0) { 148 if ((ret = __db_create_internal(&dbp, env, 0)) != 0) 149 goto out; 150 151 F_SET(dbp, DB_AM_RECOVER | DB_AM_INMEM); 152 memcpy(dbp->fileid, argp->fid.data, DB_FILE_ID_LEN); 153 if (((ret = __os_strdup(env, 154 argp->name.data, &dbp->dname)) != 0)) 155 goto out; 156 157 /* 158 * This DBP is never going to be entered into the 159 * dbentry table, so if we leave it open here, 160 * then we're going to lose it. 161 */ 162 do_close = 1; 163 } 164 165 /* Now, set the fileid. */ 166 memcpy(dbp->fileid, argp->fid.data, argp->fid.size); 167 if ((ret = __memp_set_fileid(dbp->mpf, dbp->fileid)) != 0) 168 goto out; 169 dbp->preserve_fid = 1; 170 MAKE_INMEM(dbp); 171 if ((ret = __env_setup(dbp, 172 NULL, NULL, argp->name.data, TXN_INVALID, 0)) != 0) 173 goto out; 174 ret = __env_mpool(dbp, argp->name.data, 0); 175 176 if (ret == ENOENT) { 177 dbp->pgsize = argp->pgsize; 178 if ((ret = __env_mpool(dbp, 179 argp->name.data, DB_CREATE)) != 0) 180 goto out; 181 } else if (ret != 0) 182 goto out; 183 } 184 185 if (DB_UNDO(op)) { 186 if (ret == 0) 187 ret = __memp_nameop(env, argp->fid.data, NULL, 188 (const char *)argp->name.data, NULL, 1); 189 190 if (ret == ENOENT || ret == DB_DELETED) 191 ret = 0; 192 else 193 goto out; 194 } 195 196 *lsnp = argp->prev_lsn; 197 198out: if (dbp != NULL) { 199 t_ret = 0; 200 201 if (do_close || ret != 0) 202 t_ret = __db_close(dbp, NULL, DB_NOSYNC); 203 if (t_ret != 0 && ret == 0) 204 ret = t_ret; 205 } 206 REC_NOOP_CLOSE; 207} 208 209/* 210 * __crdel_inmem_rename_recover -- 211 * Recovery function for inmem_rename. 212 * 213 * PUBLIC: int __crdel_inmem_rename_recover 214 * PUBLIC: __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); 215 */ 216int 217__crdel_inmem_rename_recover(env, dbtp, lsnp, op, info) 218 ENV *env; 219 DBT *dbtp; 220 DB_LSN *lsnp; 221 db_recops op; 222 void *info; 223{ 224 __crdel_inmem_rename_args *argp; 225 u_int8_t *fileid; 226 int ret; 227 228 COMPQUIET(info, NULL); 229 230 REC_PRINT(__crdel_inmem_rename_print); 231 REC_NOOP_INTRO(__crdel_inmem_rename_read); 232 fileid = argp->fid.data; 233 234 /* Void out errors because the files may or may not still exist. */ 235 if (DB_REDO(op)) 236 (void)__memp_nameop(env, fileid, 237 (const char *)argp->newname.data, 238 (const char *)argp->oldname.data, 239 (const char *)argp->newname.data, 1); 240 241 if (DB_UNDO(op)) 242 (void)__memp_nameop(env, fileid, 243 (const char *)argp->oldname.data, 244 (const char *)argp->newname.data, 245 (const char *)argp->oldname.data, 1); 246 247 *lsnp = argp->prev_lsn; 248 ret = 0; 249 250 REC_NOOP_CLOSE; 251} 252 253/* 254 * __crdel_inmem_remove_recover -- 255 * Recovery function for inmem_remove. 256 * 257 * PUBLIC: int __crdel_inmem_remove_recover 258 * PUBLIC: __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); 259 */ 260int 261__crdel_inmem_remove_recover(env, dbtp, lsnp, op, info) 262 ENV *env; 263 DBT *dbtp; 264 DB_LSN *lsnp; 265 db_recops op; 266 void *info; 267{ 268 __crdel_inmem_remove_args *argp; 269 int ret; 270 271 COMPQUIET(info, NULL); 272 273 REC_PRINT(__crdel_inmem_remove_print); 274 REC_NOOP_INTRO(__crdel_inmem_remove_read); 275 276 /* 277 * Since removes are delayed; there is no undo for a remove; only redo. 278 * The remove may fail, which is OK. 279 */ 280 if (DB_REDO(op)) { 281 (void)__memp_nameop(env, 282 argp->fid.data, NULL, argp->name.data, NULL, 1); 283 } 284 285 *lsnp = argp->prev_lsn; 286 ret = 0; 287 288 REC_NOOP_CLOSE; 289} 290