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