db

db_rec.c

Go to the documentation of this file.
00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996, 1997, 1998, 1999, 2000
00005  * Sleepycat Software. All rights reserved.
00006  */
00007 
00008 #include "config.h"
00009 
00010 #ifndef lint
00011 static const char revid[] = "$Id: db__rec_8c-source.html,v 1.1 2008年06月08日 10:18:14 sebdiaz Exp $";
00012 #endif /* not lint */
00013 
00014 #ifndef NO_SYSTEM_INCLUDES
00015 #include <sys/types.h>
00016 
00017 #include <string.h>
00018 #endif
00019 
00020 #include "db_int.h"
00021 #include "db_page.h"
00022 #include "log.h"
00023 #include "hash.h"
00024 
00025 /*
00026  * PUBLIC: int CDB___db_addrem_recover
00027  * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
00028  *
00029  * This log message is generated whenever we add or remove a duplicate
00030  * to/from a duplicate page. On recover, we just do the opposite.
00031  */
00032 int
00033 CDB___db_addrem_recover(dbenv, dbtp, lsnp, op, info)
00034 DB_ENV *dbenv;
00035 DBT *dbtp;
00036 DB_LSN *lsnp;
00037 db_recops op;
00038 void *info;
00039 {
00040 __db_addrem_args *argp;
00041 DB *file_dbp;
00042 DBC *dbc;
00043 DB_MPOOLFILE *mpf;
00044 PAGE *pagep;
00045 u_int32_t change;
00046 int cmp_n, cmp_p, ret;
00047 
00048 COMPQUIET(info, NULL);
00049 REC_PRINT(CDB___db_addrem_print);
00050 REC_INTRO(CDB___db_addrem_read, 1);
00051 
00052 if ((ret = CDB_memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
00053 if (DB_UNDO(op)) {
00054 /*
00055  * We are undoing and the page doesn't exist. That
00056  * is equivalent to having a pagelsn of 0, so we
00057  * would not have to undo anything. In this case,
00058  * don't bother creating a page.
00059  */
00060 goto done;
00061 } else
00062 if ((ret = CDB_memp_fget(mpf,
00063 &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
00064 goto out;
00065 }
00066 
00067 cmp_n = CDB_log_compare(lsnp, &LSN(pagep));
00068 cmp_p = CDB_log_compare(&LSN(pagep), &argp->pagelsn);
00069 CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->pagelsn);
00070 change = 0;
00071 if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_DUP) ||
00072 (cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_REM_DUP)) {
00073 
00074 /* Need to redo an add, or undo a delete. */
00075 if ((ret = CDB___db_pitem(dbc, pagep, argp->indx, argp->nbytes,
00076 argp->hdr.size == 0 ? NULL : &argp->hdr,
00077 argp->dbt.size == 0 ? NULL : &argp->dbt)) != 0)
00078 goto out;
00079 
00080 change = DB_MPOOL_DIRTY;
00081 
00082 } else if ((cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_ADD_DUP) ||
00083 (cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_REM_DUP)) {
00084 /* Need to undo an add, or redo a delete. */
00085 if ((ret = CDB___db_ditem(dbc,
00086 pagep, argp->indx, argp->nbytes)) != 0)
00087 goto out;
00088 change = DB_MPOOL_DIRTY;
00089 }
00090 
00091 if (change) {
00092 if (DB_REDO(op))
00093 LSN(pagep) = *lsnp;
00094 else
00095 LSN(pagep) = argp->pagelsn;
00096 }
00097 
00098 if ((ret = CDB_memp_fput(mpf, pagep, change)) != 0)
00099 goto out;
00100 
00101 done: *lsnp = argp->prev_lsn;
00102 ret = 0;
00103 
00104 out: REC_CLOSE;
00105 }
00106 
00107 /*
00108  * PUBLIC: int CDB___db_big_recover
00109  * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
00110  */
00111 int
00112 CDB___db_big_recover(dbenv, dbtp, lsnp, op, info)
00113 DB_ENV *dbenv;
00114 DBT *dbtp;
00115 DB_LSN *lsnp;
00116 db_recops op;
00117 void *info;
00118 {
00119 __db_big_args *argp;
00120 DB *file_dbp;
00121 DBC *dbc;
00122 DB_MPOOLFILE *mpf;
00123 PAGE *pagep;
00124 u_int32_t change;
00125 int cmp_n, cmp_p, ret;
00126 
00127 COMPQUIET(info, NULL);
00128 REC_PRINT(CDB___db_big_print);
00129 REC_INTRO(CDB___db_big_read, 1);
00130 
00131 if ((ret = CDB_memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
00132 if (DB_UNDO(op)) {
00133 /*
00134  * We are undoing and the page doesn't exist. That
00135  * is equivalent to having a pagelsn of 0, so we
00136  * would not have to undo anything. In this case,
00137  * don't bother creating a page.
00138  */
00139 ret = 0;
00140 goto ppage;
00141 } else
00142 if ((ret = CDB_memp_fget(mpf,
00143 &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0)
00144 goto out;
00145 }
00146 
00147 /*
00148  * There are three pages we need to check. The one on which we are
00149  * adding data, the previous one whose next_pointer may have
00150  * been updated, and the next one whose prev_pointer may have
00151  * been updated.
00152  */
00153 cmp_n = CDB_log_compare(lsnp, &LSN(pagep));
00154 cmp_p = CDB_log_compare(&LSN(pagep), &argp->pagelsn);
00155 CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->pagelsn);
00156 change = 0;
00157 if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_BIG) ||
00158 (cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_REM_BIG)) {
00159 /* We are either redo-ing an add, or undoing a delete. */
00160 P_INIT(pagep, file_dbp->pgsize, argp->pgno, argp->prev_pgno,
00161 argp->next_pgno, 0, P_OVERFLOW, TAGS(argp));
00162 OV_LEN(pagep) = argp->dbt.size;
00163 OV_REF(pagep) = 1;
00164 memcpy((u_int8_t *)pagep + P_OVERHEAD, argp->dbt.data,
00165 argp->dbt.size);
00166 PREV_PGNO(pagep) = argp->prev_pgno;
00167 change = DB_MPOOL_DIRTY;
00168 } else if ((cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_ADD_BIG) ||
00169 (cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_REM_BIG)) {
00170 /*
00171  * We are either undo-ing an add or redo-ing a delete.
00172  * The page is about to be reclaimed in either case, so
00173  * there really isn't anything to do here.
00174  */
00175 change = DB_MPOOL_DIRTY;
00176 }
00177 if (change)
00178 LSN(pagep) = DB_REDO(op) ? *lsnp : argp->pagelsn;
00179 
00180 if ((ret = CDB_memp_fput(mpf, pagep, change)) != 0)
00181 goto out;
00182 
00183 /* Now check the previous page. */
00184 ppage: if (argp->prev_pgno != PGNO_INVALID) {
00185 change = 0;
00186 if ((ret = CDB_memp_fget(mpf, &argp->prev_pgno, 0, &pagep)) != 0) {
00187 if (DB_UNDO(op)) {
00188 /*
00189  * We are undoing and the page doesn't exist.
00190  * That is equivalent to having a pagelsn of 0,
00191  * so we would not have to undo anything. In
00192  * this case, don't bother creating a page.
00193  */
00194 *lsnp = argp->prev_lsn;
00195 ret = 0;
00196 goto npage;
00197 } else
00198 if ((ret = CDB_memp_fget(mpf, &argp->prev_pgno,
00199 DB_MPOOL_CREATE, &pagep)) != 0)
00200 goto out;
00201 }
00202 
00203 cmp_n = CDB_log_compare(lsnp, &LSN(pagep));
00204 cmp_p = CDB_log_compare(&LSN(pagep), &argp->prevlsn);
00205 CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->prevlsn);
00206 
00207 if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_BIG) ||
00208 (cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_REM_BIG)) {
00209 /* Redo add, undo delete. */
00210 NEXT_PGNO(pagep) = argp->pgno;
00211 change = DB_MPOOL_DIRTY;
00212 } else if ((cmp_n == 0 &&
00213 DB_UNDO(op) && argp->opcode == DB_ADD_BIG) ||
00214 (cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_REM_BIG)) {
00215 /* Redo delete, undo add. */
00216 NEXT_PGNO(pagep) = argp->next_pgno;
00217 change = DB_MPOOL_DIRTY;
00218 }
00219 if (change)
00220 LSN(pagep) = DB_REDO(op) ? *lsnp : argp->prevlsn;
00221 if ((ret = CDB_memp_fput(mpf, pagep, change)) != 0)
00222 goto out;
00223 }
00224 
00225 /* Now check the next page. Can only be set on a delete. */
00226 npage: if (argp->next_pgno != PGNO_INVALID) {
00227 change = 0;
00228 if ((ret = CDB_memp_fget(mpf, &argp->next_pgno, 0, &pagep)) != 0) {
00229 if (DB_UNDO(op)) {
00230 /*
00231  * We are undoing and the page doesn't exist.
00232  * That is equivalent to having a pagelsn of 0,
00233  * so we would not have to undo anything. In
00234  * this case, don't bother creating a page.
00235  */
00236 goto done;
00237 } else
00238 if ((ret = CDB_memp_fget(mpf, &argp->next_pgno,
00239 DB_MPOOL_CREATE, &pagep)) != 0)
00240 goto out;
00241 }
00242 
00243 cmp_n = CDB_log_compare(lsnp, &LSN(pagep));
00244 cmp_p = CDB_log_compare(&LSN(pagep), &argp->nextlsn);
00245 CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->nextlsn);
00246 if (cmp_p == 0 && DB_REDO(op)) {
00247 PREV_PGNO(pagep) = PGNO_INVALID;
00248 change = DB_MPOOL_DIRTY;
00249 } else if (cmp_n == 0 && DB_UNDO(op)) {
00250 PREV_PGNO(pagep) = argp->pgno;
00251 change = DB_MPOOL_DIRTY;
00252 }
00253 if (change)
00254 LSN(pagep) = DB_REDO(op) ? *lsnp : argp->nextlsn;
00255 if ((ret = CDB_memp_fput(mpf, pagep, change)) != 0)
00256 goto out;
00257 }
00258 
00259 done: *lsnp = argp->prev_lsn;
00260 ret = 0;
00261 
00262 out: REC_CLOSE;
00263 }
00264 
00265 /*
00266  * CDB___db_ovref_recover --
00267  * Recovery function for CDB___db_ovref().
00268  *
00269  * PUBLIC: int CDB___db_ovref_recover __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
00270  */
00271 int
00272 CDB___db_ovref_recover(dbenv, dbtp, lsnp, op, info)
00273 DB_ENV *dbenv;
00274 DBT *dbtp;
00275 DB_LSN *lsnp;
00276 db_recops op;
00277 void *info;
00278 {
00279 __db_ovref_args *argp;
00280 DB *file_dbp;
00281 DBC *dbc;
00282 DB_MPOOLFILE *mpf;
00283 PAGE *pagep;
00284 int cmp, modified, ret;
00285 
00286 COMPQUIET(info, NULL);
00287 REC_PRINT(CDB___db_ovref_print);
00288 REC_INTRO(CDB___db_ovref_read, 1);
00289 
00290 if ((ret = CDB_memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
00291 (void)CDB___db_pgerr(file_dbp, argp->pgno);
00292 goto out;
00293 }
00294 
00295 modified = 0;
00296 cmp = CDB_log_compare(&LSN(pagep), &argp->lsn);
00297 CHECK_LSN(op, cmp, &LSN(pagep), &argp->lsn);
00298 if (cmp == 0 && DB_REDO(op)) {
00299 /* Need to redo update described. */
00300 OV_REF(pagep) += argp->adjust;
00301 
00302 pagep->lsn = *lsnp;
00303 modified = 1;
00304 } else if (CDB_log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
00305 /* Need to undo update described. */
00306 OV_REF(pagep) -= argp->adjust;
00307 
00308 pagep->lsn = argp->lsn;
00309 modified = 1;
00310 }
00311 if ((ret = CDB_memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
00312 goto out;
00313 
00314 done: *lsnp = argp->prev_lsn;
00315 ret = 0;
00316 
00317 out: REC_CLOSE;
00318 }
00319 
00320 /*
00321  * CDB___db_relink_recover --
00322  * Recovery function for relink.
00323  *
00324  * PUBLIC: int CDB___db_relink_recover
00325  * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
00326  */
00327 int
00328 CDB___db_relink_recover(dbenv, dbtp, lsnp, op, info)
00329 DB_ENV *dbenv;
00330 DBT *dbtp;
00331 DB_LSN *lsnp;
00332 db_recops op;
00333 void *info;
00334 {
00335 __db_relink_args *argp;
00336 DB *file_dbp;
00337 DBC *dbc;
00338 DB_MPOOLFILE *mpf;
00339 PAGE *pagep;
00340 int cmp_n, cmp_p, modified, ret;
00341 
00342 COMPQUIET(info, NULL);
00343 REC_PRINT(CDB___db_relink_print);
00344 REC_INTRO(CDB___db_relink_read, 1);
00345 
00346 /*
00347  * There are up to three pages we need to check -- the page, and the
00348  * previous and next pages, if they existed. For a page add operation,
00349  * the current page is the result of a split and is being recovered
00350  * elsewhere, so all we need do is recover the next page.
00351  */
00352 if ((ret = CDB_memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
00353 if (DB_REDO(op)) {
00354 (void)CDB___db_pgerr(file_dbp, argp->pgno);
00355 goto out;
00356 }
00357 goto next2;
00358 }
00359 modified = 0;
00360 if (argp->opcode == DB_ADD_PAGE)
00361 goto next1;
00362 
00363 cmp_p = CDB_log_compare(&LSN(pagep), &argp->lsn);
00364 CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn);
00365 if (cmp_p == 0 && DB_REDO(op)) {
00366 /* Redo the relink. */
00367 pagep->lsn = *lsnp;
00368 modified = 1;
00369 } else if (CDB_log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
00370 /* Undo the relink. */
00371 pagep->next_pgno = argp->next;
00372 pagep->prev_pgno = argp->prev;
00373 
00374 pagep->lsn = argp->lsn;
00375 modified = 1;
00376 }
00377 next1: if ((ret = CDB_memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
00378 goto out;
00379 
00380 next2: if ((ret = CDB_memp_fget(mpf, &argp->next, 0, &pagep)) != 0) {
00381 if (DB_REDO(op)) {
00382 (void)CDB___db_pgerr(file_dbp, argp->next);
00383 goto out;
00384 }
00385 goto prev;
00386 }
00387 modified = 0;
00388 cmp_n = CDB_log_compare(lsnp, &LSN(pagep));
00389 cmp_p = CDB_log_compare(&LSN(pagep), &argp->lsn_next);
00390 CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn_next);
00391 if ((argp->opcode == DB_REM_PAGE && cmp_p == 0 && DB_REDO(op)) ||
00392 (argp->opcode == DB_ADD_PAGE && cmp_n == 0 && DB_UNDO(op))) {
00393 /* Redo the remove or undo the add. */
00394 pagep->prev_pgno = argp->prev;
00395 
00396 modified = 1;
00397 } else if ((argp->opcode == DB_REM_PAGE && cmp_n == 0 && DB_UNDO(op)) ||
00398 (argp->opcode == DB_ADD_PAGE && cmp_p == 0 && DB_REDO(op))) {
00399 /* Undo the remove or redo the add. */
00400 pagep->prev_pgno = argp->pgno;
00401 
00402 modified = 1;
00403 }
00404 if (modified == 1) {
00405 if (DB_UNDO(op))
00406 pagep->lsn = argp->lsn_next;
00407 else
00408 pagep->lsn = *lsnp;
00409 }
00410 if ((ret = CDB_memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
00411 goto out;
00412 if (argp->opcode == DB_ADD_PAGE)
00413 goto done;
00414 
00415 prev: if ((ret = CDB_memp_fget(mpf, &argp->prev, 0, &pagep)) != 0) {
00416 if (DB_REDO(op)) {
00417 (void)CDB___db_pgerr(file_dbp, argp->prev);
00418 goto out;
00419 }
00420 goto done;
00421 }
00422 modified = 0;
00423 cmp_p = CDB_log_compare(&LSN(pagep), &argp->lsn_prev);
00424 CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn_prev);
00425 if (cmp_p == 0 && DB_REDO(op)) {
00426 /* Redo the relink. */
00427 pagep->next_pgno = argp->next;
00428 
00429 modified = 1;
00430 } else if (CDB_log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
00431 /* Undo the relink. */
00432 pagep->next_pgno = argp->pgno;
00433 
00434 modified = 1;
00435 }
00436 if (modified == 1) {
00437 if (DB_UNDO(op))
00438 pagep->lsn = argp->lsn_prev;
00439 else
00440 pagep->lsn = *lsnp;
00441 }
00442 if ((ret = CDB_memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
00443 goto out;
00444 
00445 done: *lsnp = argp->prev_lsn;
00446 ret = 0;
00447 
00448 out: REC_CLOSE;
00449 }
00450 
00451 /*
00452  * CDB___db_debug_recover --
00453  * Recovery function for debug.
00454  *
00455  * PUBLIC: int CDB___db_debug_recover __P((DB_ENV *,
00456  * PUBLIC: DBT *, DB_LSN *, db_recops, void *));
00457  */
00458 int
00459 CDB___db_debug_recover(dbenv, dbtp, lsnp, op, info)
00460 DB_ENV *dbenv;
00461 DBT *dbtp;
00462 DB_LSN *lsnp;
00463 db_recops op;
00464 void *info;
00465 {
00466 __db_debug_args *argp;
00467 int ret;
00468 
00469 COMPQUIET(op, 0);
00470 COMPQUIET(dbenv, NULL);
00471 COMPQUIET(info, NULL);
00472 
00473 REC_PRINT(CDB___db_debug_print);
00474 REC_NOOP_INTRO(CDB___db_debug_read);
00475 
00476 *lsnp = argp->prev_lsn;
00477 ret = 0;
00478 
00479 REC_NOOP_CLOSE;
00480 }
00481 
00482 /*
00483  * CDB___db_noop_recover --
00484  * Recovery function for noop.
00485  *
00486  * PUBLIC: int CDB___db_noop_recover __P((DB_ENV *,
00487  * PUBLIC: DBT *, DB_LSN *, db_recops, void *));
00488  */
00489 int
00490 CDB___db_noop_recover(dbenv, dbtp, lsnp, op, info)
00491 DB_ENV *dbenv;
00492 DBT *dbtp;
00493 DB_LSN *lsnp;
00494 db_recops op;
00495 void *info;
00496 {
00497 __db_noop_args *argp;
00498 DB *file_dbp;
00499 DBC *dbc;
00500 DB_MPOOLFILE *mpf;
00501 PAGE *pagep;
00502 u_int32_t change;
00503 int cmp_n, cmp_p, ret;
00504 
00505 COMPQUIET(info, NULL);
00506 REC_PRINT(CDB___db_noop_print);
00507 REC_INTRO(CDB___db_noop_read, 0);
00508 
00509 if ((ret = CDB_memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0)
00510 goto out;
00511 
00512 cmp_n = CDB_log_compare(lsnp, &LSN(pagep));
00513 cmp_p = CDB_log_compare(&LSN(pagep), &argp->prevlsn);
00514 CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->prevlsn);
00515 change = 0;
00516 if (cmp_p == 0 && DB_REDO(op)) {
00517 LSN(pagep) = *lsnp;
00518 change = DB_MPOOL_DIRTY;
00519 } else if (cmp_n == 0 && DB_UNDO(op)) {
00520 LSN(pagep) = argp->prevlsn;
00521 change = DB_MPOOL_DIRTY;
00522 }
00523 ret = CDB_memp_fput(mpf, pagep, change);
00524 
00525 done: *lsnp = argp->prev_lsn;
00526 out: REC_CLOSE;
00527 }

Generated on Sun Jun 8 10:56:36 2008 for GNUmifluz by doxygen 1.5.5

AltStyle によって変換されたページ (->オリジナル) /