diff options
Diffstat (limited to 'db/btree/bt_rec.c')
-rw-r--r-- | db/btree/bt_rec.c | 675 |
1 files changed, 541 insertions, 134 deletions
diff --git a/db/btree/bt_rec.c b/db/btree/bt_rec.c index e3fa7363c..45df8d7c1 100644 --- a/db/btree/bt_rec.c +++ b/db/btree/bt_rec.c @@ -1,23 +1,16 @@ /*- * See the file LICENSE for redistribution information. * - * Copyright (c) 1996-2004 - * Sleepycat Software. All rights reserved. + * Copyright (c) 1996-2006 + * Oracle Corporation. All rights reserved. * - * $Id: bt_rec.c,v 11.70 2004/09/24 00:43:12 bostic Exp $ + * $Id: bt_rec.c,v 12.21 2006/08/24 14:44:44 bostic Exp $ */ #include "db_config.h" -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <string.h> -#endif - #include "db_int.h" #include "dbinc/db_page.h" -#include "dbinc/db_shash.h" #include "dbinc/btree.h" #include "dbinc/lock.h" #include "dbinc/log.h" @@ -58,7 +51,7 @@ __bam_split_recover(dbenv, dbtp, lsnp, op, info) _lp = lp = np = pp = _rp = rp = NULL; sp = NULL; - REC_INTRO(__bam_split_read, 1); + REC_INTRO(__bam_split_read, 1, 0); /* * There are two kinds of splits that we have to recover from. The @@ -95,22 +88,22 @@ redo: if (DB_REDO(op)) { if (rootsplit) { REC_FGET(mpf, root_pgno, &pp, do_left); cmp = - log_compare(&LSN(pp), &LSN(argp->pg.data)); - CHECK_LSN(op, + LOG_COMPARE(&LSN(pp), &LSN(argp->pg.data)); + CHECK_LSN(dbenv, op, cmp, &LSN(pp), &LSN(argp->pg.data)); p_update = cmp == 0; } do_left: if (lp != NULL) { - cmp = log_compare(&LSN(lp), &argp->llsn); - CHECK_LSN(op, cmp, &LSN(lp), &argp->llsn); + cmp = LOG_COMPARE(&LSN(lp), &argp->llsn); + CHECK_LSN(dbenv, op, cmp, &LSN(lp), &argp->llsn); if (cmp == 0) l_update = 1; } if (rp != NULL) { - cmp = log_compare(&LSN(rp), &argp->rlsn); - CHECK_LSN(op, cmp, &LSN(rp), &argp->rlsn); + cmp = LOG_COMPARE(&LSN(rp), &argp->rlsn); + CHECK_LSN(dbenv, op, cmp, &LSN(rp), &argp->rlsn); if (cmp == 0) r_update = 1; } @@ -148,17 +141,19 @@ do_left: if (lp != NULL) { goto out; if (l_update) { + REC_DIRTY(mpf, &lp); memcpy(lp, _lp, file_dbp->pgsize); lp->lsn = *lsnp; - if ((ret = __memp_fput(mpf, lp, DB_MPOOL_DIRTY)) != 0) + if ((ret = __memp_fput(mpf, lp, 0)) != 0) goto out; lp = NULL; } if (r_update) { + REC_DIRTY(mpf, &rp); memcpy(rp, _rp, file_dbp->pgsize); rp->lsn = *lsnp; - if ((ret = __memp_fput(mpf, rp, DB_MPOOL_DIRTY)) != 0) + if ((ret = __memp_fput(mpf, rp, 0)) != 0) goto out; rp = NULL; } @@ -178,13 +173,14 @@ do_left: if (lp != NULL) { rc = 1; } + REC_DIRTY(mpf, &pp); P_INIT(pp, file_dbp->pgsize, root_pgno, PGNO_INVALID, PGNO_INVALID, _lp->level + 1, ptype); RE_NREC_SET(pp, rc ? __bam_total(file_dbp, _lp) + __bam_total(file_dbp, _rp) : 0); pp->lsn = *lsnp; - if ((ret = __memp_fput(mpf, pp, DB_MPOOL_DIRTY)) != 0) + if ((ret = __memp_fput(mpf, pp, 0)) != 0) goto out; pp = NULL; } @@ -197,8 +193,8 @@ check_next: /* * page must exist because we're redoing the operation. */ if (!rootsplit && argp->npgno != PGNO_INVALID) { - if ((ret = - __memp_fget(mpf, &argp->npgno, 0, &np)) != 0) { + if ((ret = __memp_fget(mpf, &argp->npgno, NULL, + 0, &np)) != 0) { if (ret != DB_PAGE_NOTFOUND #ifndef HAVE_FTRUNCATE || DB_REDO(op) @@ -210,13 +206,14 @@ check_next: /* } else goto done; } - cmp = log_compare(&LSN(np), &argp->nlsn); - CHECK_LSN(op, cmp, &LSN(np), &argp->nlsn); + cmp = LOG_COMPARE(&LSN(np), &argp->nlsn); + CHECK_LSN(dbenv, op, cmp, &LSN(np), &argp->nlsn); if (cmp == 0) { + REC_DIRTY(mpf, &np); PREV_PGNO(np) = argp->right; np->lsn = *lsnp; if ((ret = - __memp_fput(mpf, np, DB_MPOOL_DIRTY)) != 0) + __memp_fput(mpf, np, 0)) != 0) goto out; np = NULL; } @@ -229,13 +226,15 @@ check_next: /* * the adds onto the page that caused the split, and there's * really no undo-ing to be done. */ - if ((ret = __memp_fget(mpf, &pgno, 0, &pp)) != 0) { + if ((ret = __memp_fget(mpf, &pgno, NULL, + DB_MPOOL_EDIT, &pp)) != 0) { pp = NULL; goto lrundo; } - if (log_compare(lsnp, &LSN(pp)) == 0) { + if (LOG_COMPARE(lsnp, &LSN(pp)) == 0) { + REC_DIRTY(mpf, &pp); memcpy(pp, argp->pg.data, argp->pg.size); - if ((ret = __memp_fput(mpf, pp, DB_MPOOL_DIRTY)) != 0) + if ((ret = __memp_fput(mpf, pp, 0)) != 0) goto out; pp = NULL; } @@ -250,18 +249,20 @@ check_next: /* */ lrundo: if ((rootsplit && lp != NULL) || rp != NULL) { if (rootsplit && lp != NULL && - log_compare(lsnp, &LSN(lp)) == 0) { + LOG_COMPARE(lsnp, &LSN(lp)) == 0) { + REC_DIRTY(mpf, &lp); lp->lsn = argp->llsn; if ((ret = - __memp_fput(mpf, lp, DB_MPOOL_DIRTY)) != 0) + __memp_fput(mpf, lp, 0)) != 0) goto out; lp = NULL; } if (rp != NULL && - log_compare(lsnp, &LSN(rp)) == 0) { + LOG_COMPARE(lsnp, &LSN(rp)) == 0) { + REC_DIRTY(mpf, &rp); rp->lsn = argp->rlsn; if ((ret = - __memp_fput(mpf, rp, DB_MPOOL_DIRTY)) != 0) + __memp_fput(mpf, rp, 0)) != 0) goto out; rp = NULL; } @@ -276,15 +277,16 @@ lrundo: if ((rootsplit && lp != NULL) || rp != NULL) { * if there's nothing to undo. */ if (!rootsplit && argp->npgno != PGNO_INVALID) { - if ((ret = - __memp_fget(mpf, &argp->npgno, 0, &np)) != 0) { + if ((ret = __memp_fget(mpf, &argp->npgno, NULL, + DB_MPOOL_EDIT, &np)) != 0) { np = NULL; goto done; } - if (log_compare(lsnp, &LSN(np)) == 0) { + if (LOG_COMPARE(lsnp, &LSN(np)) == 0) { + REC_DIRTY(mpf, &np); PREV_PGNO(np) = argp->left; np->lsn = argp->nlsn; - if (__memp_fput(mpf, np, DB_MPOOL_DIRTY)) + if (__memp_fput(mpf, np, 0)) goto out; np = NULL; } @@ -337,16 +339,18 @@ __bam_rsplit_recover(dbenv, dbtp, lsnp, op, info) DB_MPOOLFILE *mpf; PAGE *pagep; db_pgno_t pgno, root_pgno; - int cmp_n, cmp_p, modified, ret; + db_recno_t rcnt; + int cmp_n, cmp_p, ret; pagep = NULL; COMPQUIET(info, NULL); REC_PRINT(__bam_rsplit_print); - REC_INTRO(__bam_rsplit_read, 1); + REC_INTRO(__bam_rsplit_read, 1, 1); /* Fix the root page. */ pgno = root_pgno = argp->root_pgno; - if ((ret = __memp_fget(mpf, &pgno, 0, &pagep)) != 0) { + if ((ret = __memp_fget(mpf, &pgno, NULL, + 0, &pagep)) != 0) { if (ret != DB_PAGE_NOTFOUND #ifndef HAVE_FTRUNCATE || DB_REDO(op) @@ -358,18 +362,27 @@ __bam_rsplit_recover(dbenv, dbtp, lsnp, op, info) goto do_page; } - modified = 0; - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->rootlsn); - CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->rootlsn); + cmp_n = LOG_COMPARE(lsnp, &LSN(pagep)); + cmp_p = LOG_COMPARE(&LSN(pagep), &argp->rootlsn); + CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->rootlsn); if (cmp_p == 0 && DB_REDO(op)) { - /* Need to redo update described. */ + /* + * Copy the new data to the root page. If it is not now a + * leaf page we need to restore the record number. We could + * try to determine if C_RECNUM was set in the btree, but + * that's not really necessary since the field is not used + * otherwise. + */ + REC_DIRTY(mpf, &pagep); + rcnt = RE_NREC(pagep); memcpy(pagep, argp->pgdbt.data, argp->pgdbt.size); + if (LEVEL(pagep) > LEAFLEVEL) + RE_NREC_SET(pagep, rcnt); pagep->pgno = root_pgno; pagep->lsn = *lsnp; - modified = 1; } else if (cmp_n == 0 && DB_UNDO(op)) { /* Need to undo update described. */ + REC_DIRTY(mpf, &pagep); P_INIT(pagep, file_dbp->pgsize, root_pgno, argp->nrec, PGNO_INVALID, pagep->level + 1, IS_BTREE_PAGE(pagep) ? P_IBTREE : P_IRECNO); @@ -377,9 +390,8 @@ __bam_rsplit_recover(dbenv, dbtp, lsnp, op, info) argp->rootent.size, &argp->rootent, NULL)) != 0) goto out; pagep->lsn = argp->rootlsn; - modified = 1; } - if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) + if ((ret = __memp_fput(mpf, pagep, 0)) != 0) goto out; do_page: @@ -388,7 +400,8 @@ do_page: * page never made it to disk, so if we're undo-ing and the page * doesn't exist, it's okay and there's nothing further to do. */ - if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { + if ((ret = __memp_fget(mpf, &argp->pgno, NULL, + 0, &pagep)) != 0) { if (ret != DB_PAGE_NOTFOUND #ifndef HAVE_FTRUNCATE || DB_REDO(op) @@ -399,21 +412,20 @@ do_page: } else goto done; } - modified = 0; (void)__ua_memcpy(©_lsn, &LSN(argp->pgdbt.data), sizeof(DB_LSN)); - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), ©_lsn); - CHECK_LSN(op, cmp_p, &LSN(pagep), ©_lsn); + cmp_n = LOG_COMPARE(lsnp, &LSN(pagep)); + cmp_p = LOG_COMPARE(&LSN(pagep), ©_lsn); + CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), ©_lsn); if (cmp_p == 0 && DB_REDO(op)) { /* Need to redo update described. */ + REC_DIRTY(mpf, &pagep); pagep->lsn = *lsnp; - modified = 1; } else if (cmp_n == 0 && DB_UNDO(op)) { /* Need to undo update described. */ + REC_DIRTY(mpf, &pagep); memcpy(pagep, argp->pgdbt.data, argp->pgdbt.size); - modified = 1; } - if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) + if ((ret = __memp_fput(mpf, pagep, 0)) != 0) goto out; pagep = NULL; @@ -445,15 +457,16 @@ __bam_adj_recover(dbenv, dbtp, lsnp, op, info) DBC *dbc; DB_MPOOLFILE *mpf; PAGE *pagep; - int cmp_n, cmp_p, modified, ret; + int cmp_n, cmp_p, ret; pagep = NULL; COMPQUIET(info, NULL); REC_PRINT(__bam_adj_print); - REC_INTRO(__bam_adj_read, 1); + REC_INTRO(__bam_adj_read, 1, 1); /* Get the page; if it never existed and we're undoing, we're done. */ - if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { + if ((ret = __memp_fget(mpf, &argp->pgno, NULL, + 0, &pagep)) != 0) { if (ret != DB_PAGE_NOTFOUND #ifndef HAVE_FTRUNCATE || DB_REDO(op) @@ -465,28 +478,27 @@ __bam_adj_recover(dbenv, dbtp, lsnp, op, info) goto done; } - modified = 0; - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->lsn); - CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn); + cmp_n = LOG_COMPARE(lsnp, &LSN(pagep)); + cmp_p = LOG_COMPARE(&LSN(pagep), &argp->lsn); + CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn); if (cmp_p == 0 && DB_REDO(op)) { /* Need to redo update described. */ + REC_DIRTY(mpf, &pagep); if ((ret = __bam_adjindx(dbc, pagep, argp->indx, argp->indx_copy, argp->is_insert)) != 0) goto out; LSN(pagep) = *lsnp; - modified = 1; } else if (cmp_n == 0 && DB_UNDO(op)) { /* Need to undo update described. */ + REC_DIRTY(mpf, &pagep); if ((ret = __bam_adjindx(dbc, pagep, argp->indx, argp->indx_copy, !argp->is_insert)) != 0) goto out; LSN(pagep) = argp->lsn; - modified = 1; } - if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) + if ((ret = __memp_fput(mpf, pagep, 0)) != 0) goto out; pagep = NULL; @@ -519,15 +531,16 @@ __bam_cadjust_recover(dbenv, dbtp, lsnp, op, info) DBC *dbc; DB_MPOOLFILE *mpf; PAGE *pagep; - int cmp_n, cmp_p, modified, ret; + int cmp_n, cmp_p, ret; pagep = NULL; COMPQUIET(info, NULL); REC_PRINT(__bam_cadjust_print); - REC_INTRO(__bam_cadjust_read, 1); + REC_INTRO(__bam_cadjust_read, 1, 0); /* Get the page; if it never existed and we're undoing, we're done. */ - if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { + if ((ret = __memp_fget(mpf, &argp->pgno, NULL, + 0, &pagep)) != 0) { if (ret != DB_PAGE_NOTFOUND #ifndef HAVE_FTRUNCATE || DB_REDO(op) @@ -539,12 +552,12 @@ __bam_cadjust_recover(dbenv, dbtp, lsnp, op, info) goto done; } - modified = 0; - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->lsn); - CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn); + cmp_n = LOG_COMPARE(lsnp, &LSN(pagep)); + cmp_p = LOG_COMPARE(&LSN(pagep), &argp->lsn); + CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn); if (cmp_p == 0 && DB_REDO(op)) { /* Need to redo update described. */ + REC_DIRTY(mpf, &pagep); if (IS_BTREE_PAGE(pagep)) { GET_BINTERNAL(file_dbp, pagep, argp->indx)->nrecs += argp->adjust; @@ -558,9 +571,9 @@ __bam_cadjust_recover(dbenv, dbtp, lsnp, op, info) } LSN(pagep) = *lsnp; - modified = 1; } else if (cmp_n == 0 && DB_UNDO(op)) { /* Need to undo update described. */ + REC_DIRTY(mpf, &pagep); if (IS_BTREE_PAGE(pagep)) { GET_BINTERNAL(file_dbp, pagep, argp->indx)->nrecs -= argp->adjust; @@ -573,9 +586,8 @@ __bam_cadjust_recover(dbenv, dbtp, lsnp, op, info) RE_NREC_ADJ(pagep, -(argp->adjust)); } LSN(pagep) = argp->lsn; - modified = 1; } - if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) + if ((ret = __memp_fput(mpf, pagep, 0)) != 0) goto out; pagep = NULL; @@ -608,15 +620,16 @@ __bam_cdel_recover(dbenv, dbtp, lsnp, op, info) DB_MPOOLFILE *mpf; PAGE *pagep; u_int32_t indx; - int cmp_n, cmp_p, modified, ret; + int cmp_n, cmp_p, ret; pagep = NULL; COMPQUIET(info, NULL); REC_PRINT(__bam_cdel_print); - REC_INTRO(__bam_cdel_read, 1); + REC_INTRO(__bam_cdel_read, 1, 0); /* Get the page; if it never existed and we're undoing, we're done. */ - if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { + if ((ret = __memp_fget(mpf, &argp->pgno, NULL, + 0, &pagep)) != 0) { if (ret != DB_PAGE_NOTFOUND #ifndef HAVE_FTRUNCATE || DB_REDO(op) @@ -628,28 +641,29 @@ __bam_cdel_recover(dbenv, dbtp, lsnp, op, info) goto done; } - modified = 0; - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->lsn); - CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn); + cmp_n = LOG_COMPARE(lsnp, &LSN(pagep)); + cmp_p = LOG_COMPARE(&LSN(pagep), &argp->lsn); + CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn); if (cmp_p == 0 && DB_REDO(op)) { /* Need to redo update described. */ + REC_DIRTY(mpf, &pagep); indx = argp->indx + (TYPE(pagep) == P_LBTREE ? O_INDX : 0); B_DSET(GET_BKEYDATA(file_dbp, pagep, indx)->type); LSN(pagep) = *lsnp; - modified = 1; } else if (cmp_n == 0 && DB_UNDO(op)) { /* Need to undo update described. */ + REC_DIRTY(mpf, &pagep); indx = argp->indx + (TYPE(pagep) == P_LBTREE ? O_INDX : 0); B_DCLR(GET_BKEYDATA(file_dbp, pagep, indx)->type); - (void)__bam_ca_delete(file_dbp, argp->pgno, argp->indx, 0); + if ((ret = __bam_ca_delete( + file_dbp, argp->pgno, argp->indx, 0, NULL)) != 0) + goto out; LSN(pagep) = argp->lsn; - modified = 1; } - if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) + if ((ret = __memp_fput(mpf, pagep, 0)) != 0) goto out; pagep = NULL; @@ -683,16 +697,17 @@ __bam_repl_recover(dbenv, dbtp, lsnp, op, info) DBT dbt; DB_MPOOLFILE *mpf; PAGE *pagep; - int cmp_n, cmp_p, modified, ret; + int cmp_n, cmp_p, ret; u_int8_t *p; pagep = NULL; COMPQUIET(info, NULL); REC_PRINT(__bam_repl_print); - REC_INTRO(__bam_repl_read, 1); + REC_INTRO(__bam_repl_read, 1, 1); /* Get the page; if it never existed and we're undoing, we're done. */ - if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { + if ((ret = __memp_fget(mpf, &argp->pgno, NULL, + 0, &pagep)) != 0) { if (ret != DB_PAGE_NOTFOUND #ifndef HAVE_FTRUNCATE || DB_REDO(op) @@ -705,16 +720,16 @@ __bam_repl_recover(dbenv, dbtp, lsnp, op, info) } bk = GET_BKEYDATA(file_dbp, pagep, argp->indx); - modified = 0; - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->lsn); - CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn); + cmp_n = LOG_COMPARE(lsnp, &LSN(pagep)); + cmp_p = LOG_COMPARE(&LSN(pagep), &argp->lsn); + CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn); if (cmp_p == 0 && DB_REDO(op)) { /* * Need to redo update described. * * Re-build the replacement item. */ + REC_DIRTY(mpf, &pagep); memset(&dbt, 0, sizeof(dbt)); dbt.size = argp->prefix + argp->suffix + argp->repl.size; if ((ret = __os_malloc(dbenv, dbt.size, &dbt.data)) != 0) @@ -732,13 +747,13 @@ __bam_repl_recover(dbenv, dbtp, lsnp, op, info) goto out; LSN(pagep) = *lsnp; - modified = 1; } else if (cmp_n == 0 && DB_UNDO(op)) { /* * Need to undo update described. * * Re-build the original item. */ + REC_DIRTY(mpf, &pagep); memset(&dbt, 0, sizeof(dbt)); dbt.size = argp->prefix + argp->suffix + argp->orig.size; if ((ret = __os_malloc(dbenv, dbt.size, &dbt.data)) != 0) @@ -760,9 +775,8 @@ __bam_repl_recover(dbenv, dbtp, lsnp, op, info) B_DSET(GET_BKEYDATA(file_dbp, pagep, argp->indx)->type); LSN(pagep) = argp->lsn; - modified = 1; } - if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) + if ((ret = __memp_fput(mpf, pagep, 0)) != 0) goto out; pagep = NULL; @@ -794,14 +808,15 @@ __bam_root_recover(dbenv, dbtp, lsnp, op, info) DB *file_dbp; DBC *dbc; DB_MPOOLFILE *mpf; - int cmp_n, cmp_p, modified, ret; + int cmp_n, cmp_p, ret; meta = NULL; COMPQUIET(info, NULL); REC_PRINT(__bam_root_print); - REC_INTRO(__bam_root_read, 0); + REC_INTRO(__bam_root_read, 0, 0); - if ((ret = __memp_fget(mpf, &argp->meta_pgno, 0, &meta)) != 0) { + if ((ret = __memp_fget(mpf, &argp->meta_pgno, NULL, + 0, &meta)) != 0) { if (ret != DB_PAGE_NOTFOUND #ifndef HAVE_FTRUNCATE || DB_REDO(op) @@ -813,22 +828,21 @@ __bam_root_recover(dbenv, dbtp, lsnp, op, info) goto done; } - modified = 0; - cmp_n = log_compare(lsnp, &LSN(meta)); - cmp_p = log_compare(&LSN(meta), &argp->meta_lsn); - CHECK_LSN(op, cmp_p, &LSN(meta), &argp->meta_lsn); + cmp_n = LOG_COMPARE(lsnp, &LSN(meta)); + cmp_p = LOG_COMPARE(&LSN(meta), &argp->meta_lsn); + CHECK_LSN(dbenv, op, cmp_p, &LSN(meta), &argp->meta_lsn); if (cmp_p == 0 && DB_REDO(op)) { /* Need to redo update described. */ + REC_DIRTY(mpf, &meta); meta->root = argp->root_pgno; meta->dbmeta.lsn = *lsnp; ((BTREE *)file_dbp->bt_internal)->bt_root = meta->root; - modified = 1; } else if (cmp_n == 0 && DB_UNDO(op)) { /* Nothing to undo except lsn. */ + REC_DIRTY(mpf, &meta); meta->dbmeta.lsn = argp->meta_lsn; - modified = 1; } - if ((ret = __memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0) + if ((ret = __memp_fput(mpf, meta, 0)) != 0) goto out; meta = NULL; @@ -866,7 +880,7 @@ __bam_curadj_recover(dbenv, dbtp, lsnp, op, info) COMPQUIET(mpf, NULL); REC_PRINT(__bam_curadj_print); - REC_INTRO(__bam_curadj_read, 0); + REC_INTRO(__bam_curadj_read, 0, 1); ret = 0; if (op != DB_TXN_ABORT) @@ -891,8 +905,9 @@ __bam_curadj_recover(dbenv, dbtp, lsnp, op, info) break; case DB_CA_SPLIT: - __bam_ca_undosplit(file_dbp, argp->from_pgno, - argp->to_pgno, argp->left_pgno, argp->from_indx); + if ((ret = __bam_ca_undosplit(file_dbp, argp->from_pgno, + argp->to_pgno, argp->left_pgno, argp->from_indx)) != 0) + goto out; break; } @@ -928,7 +943,7 @@ __bam_rcuradj_recover(dbenv, dbtp, lsnp, op, info) rdbc = NULL; REC_PRINT(__bam_rcuradj_print); - REC_INTRO(__bam_rcuradj_read, 0); + REC_INTRO(__bam_rcuradj_read, 0, 1); ret = t_ret = 0; @@ -962,7 +977,8 @@ __bam_rcuradj_recover(dbenv, dbtp, lsnp, op, info) F_SET(cp, C_DELETED); F_SET(cp, C_RENUMBER); /* Just in case. */ cp->order = argp->order; - (void)__ram_ca(rdbc, CA_ICURRENT); + if ((ret = __ram_ca(rdbc, CA_ICURRENT, NULL)) != 0) + goto out; break; case CA_IAFTER: case CA_IBEFORE: @@ -973,7 +989,8 @@ __bam_rcuradj_recover(dbenv, dbtp, lsnp, op, info) */ F_CLR(cp, C_DELETED); cp->order = INVALID_ORDER; - (void)__ram_ca(rdbc, CA_DELETE); + if ((ret = __ram_ca(rdbc, CA_DELETE, NULL)) != 0) + goto out; break; } @@ -1003,12 +1020,12 @@ __bam_relink_recover(dbenv, dbtp, lsnp, op, info) DBC *dbc; DB_MPOOLFILE *mpf; PAGE *pagep; - int cmp_n, cmp_p, modified, ret; + int cmp_n, cmp_p, ret; pagep = NULL; COMPQUIET(info, NULL); REC_PRINT(__bam_relink_print); - REC_INTRO(__bam_relink_read, 1); + REC_INTRO(__bam_relink_read, 1, 0); /* * There are up to three pages we need to check -- the page, and the @@ -1016,7 +1033,397 @@ __bam_relink_recover(dbenv, dbtp, lsnp, op, info) * the current page is the result of a split and is being recovered * elsewhere, so all we need do is recover the next page. */ - if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { + if ((ret = __memp_fget(mpf, &argp->next, NULL, + 0, &pagep)) != 0) { + if (ret != DB_PAGE_NOTFOUND +#ifndef HAVE_FTRUNCATE + || DB_REDO(op) +#endif + ) { + ret = __db_pgerr(file_dbp, argp->next, ret); + goto out; + } else + goto prev; + } + + cmp_n = LOG_COMPARE(lsnp, &LSN(pagep)); + cmp_p = LOG_COMPARE(&LSN(pagep), &argp->lsn_next); + CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn_next); + if (cmp_p == 0 && DB_REDO(op)) { + /* Redo the remove or replace. */ + REC_DIRTY(mpf, &pagep); + if (argp->new_pgno == PGNO_INVALID) + pagep->prev_pgno = argp->prev; + else + pagep->prev_pgno = argp->new_pgno; + + pagep->lsn = *lsnp; + } else if (cmp_n == 0 && DB_UNDO(op)) { + /* Undo the remove or replace. */ + REC_DIRTY(mpf, &pagep); + pagep->prev_pgno = argp->pgno; + + pagep->lsn = argp->lsn_next; + } + + if ((ret = __memp_fput(mpf, pagep, 0)) != 0) + goto out; + pagep = NULL; + +prev: if ((ret = __memp_fget(mpf, &argp->prev, NULL, + 0, &pagep)) != 0) { + if (ret != DB_PAGE_NOTFOUND +#ifndef HAVE_FTRUNCATE + || DB_REDO(op) +#endif + ) { + ret = __db_pgerr(file_dbp, argp->prev, ret); + goto out; + } else + goto done; + } + + cmp_p = LOG_COMPARE(&LSN(pagep), &argp->lsn_prev); + CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn_prev); + if (cmp_p == 0 && DB_REDO(op)) { + /* Redo the relink. */ + REC_DIRTY(mpf, &pagep); + if (argp->new_pgno == PGNO_INVALID) + pagep->next_pgno = argp->next; + else + pagep->next_pgno = argp->new_pgno; + + pagep->lsn = *lsnp; + } else if (LOG_COMPARE(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) { + /* Undo the relink. */ + REC_DIRTY(mpf, &pagep); + pagep->next_pgno = argp->pgno; + pagep->lsn = argp->lsn_prev; + } + + if ((ret = __memp_fput(mpf, pagep, 0)) != 0) + goto out; + pagep = NULL; + +done: *lsnp = argp->prev_lsn; + ret = 0; + +out: if (pagep != NULL) + (void)__memp_fput(mpf, pagep, 0); + REC_CLOSE; +} + +/* + * __bam_merge_recover -- + * Recovery function for merge. + * + * PUBLIC: int __bam_merge_recover + * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + */ +int +__bam_merge_recover(dbenv, dbtp, lsnp, op, info) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops op; + void *info; +{ + __bam_merge_args *argp; + BKEYDATA *bk; + DB *file_dbp; + DBC *dbc; + DB_MPOOLFILE *mpf; + PAGE *pagep; + db_indx_t indx, *ninp, *pinp; + u_int32_t size; + u_int8_t *bp; + int cmp_n, cmp_p, i, ret; + + COMPQUIET(info, NULL); + + REC_PRINT(__bam_merge_print); + REC_INTRO(__bam_merge_read, 1, 1); + + if ((ret = __memp_fget(mpf, &argp->pgno, NULL, + 0, &pagep)) != 0) { + if (ret != DB_PAGE_NOTFOUND +#ifndef HAVE_FTRUNCATE + || DB_REDO(op) +#endif + ) { + ret = __db_pgerr(file_dbp, argp->pgno, ret); + goto out; + } else + goto next; + } + + cmp_n = LOG_COMPARE(lsnp, &LSN(pagep)); + cmp_p = LOG_COMPARE(&LSN(pagep), &argp->lsn); + CHECK_LSN(file_dbp->dbenv, op, cmp_p, &LSN(pagep), &argp->lsn); + + if (cmp_p == 0 && DB_REDO(op)) { + /* + * If the header is provided the page is empty, copy the + * needed data. + */ + DB_ASSERT(dbenv, argp->hdr.size == 0 || NUM_ENT(pagep) == 0); + REC_DIRTY(mpf, &pagep); + if (argp->hdr.size != 0) { + P_INIT(pagep, file_dbp->pgsize, pagep->pgno, + PREV_PGNO(argp->hdr.data), + NEXT_PGNO(argp->hdr.data), + LEVEL(argp->hdr.data), TYPE(argp->hdr.data)); + } + if (TYPE(pagep) == P_OVERFLOW) { + OV_REF(pagep) = OV_REF(argp->hdr.data); + OV_LEN(pagep) = OV_LEN(argp->hdr.data); + bp = (u_int8_t *) pagep + P_OVERHEAD(file_dbp); + memcpy(bp, argp->data.data, argp->data.size); + } else { + /* Copy the data segment. */ + bp = (u_int8_t *)pagep + + (db_indx_t)(HOFFSET(pagep) - argp->data.size); + memcpy(bp, argp->data.data, argp->data.size); + + /* Copy index table offset past the current entries. */ + pinp = P_INP(file_dbp, pagep) + NUM_ENT(pagep); + ninp = argp->ind.data; + for (i = 0; + i < (int)(argp->ind.size / sizeof(*ninp)); i++) + *pinp++ = *ninp++ + - (file_dbp->pgsize - HOFFSET(pagep)); + HOFFSET(pagep) -= argp->data.size; + NUM_ENT(pagep) += i; + } + pagep->lsn = *lsnp; + } else if (cmp_n == 0 && !DB_REDO(op)) { + /* + * Since logging is logical at the page level + * we cannot just truncate the data space. Delete + * the proper number of items from the logical end + * of the page. + */ + REC_DIRTY(mpf, &pagep); + for (i = 0; i < (int)(argp->ind.size / sizeof(*ninp)); i++) { + indx = NUM_ENT(pagep) - 1; + if (P_INP(file_dbp, pagep)[indx] == + P_INP(file_dbp, pagep)[indx - P_INDX]) { + NUM_ENT(pagep)--; + continue; + } + switch (TYPE(pagep)) { + case P_LBTREE: + case P_LRECNO: + case P_LDUP: + bk = GET_BKEYDATA(file_dbp, pagep, indx); + size = BITEM_SIZE(bk); + break; + + case P_IBTREE: + size = BINTERNAL_SIZE( + GET_BINTERNAL(file_dbp, pagep, indx)->len); + break; + case P_IRECNO: + size = RINTERNAL_SIZE; + break; + + default: + ret = __db_pgfmt(dbenv, PGNO(pagep)); + goto out; + } + if ((ret = + __db_ditem(dbc, pagep, indx, size)) != 0) + goto out; + } + if (argp->ind.size == 0) + HOFFSET(pagep) = file_dbp->pgsize; + pagep->lsn = argp->lsn; + } + + if ((ret = __memp_fput(mpf, pagep, 0)) != 0) + goto out; + +next: if ((ret = __memp_fget(mpf, &argp->npgno, NULL, + 0, &pagep)) != 0) { + if (ret != DB_PAGE_NOTFOUND +#ifndef HAVE_FTRUNCATE + || DB_REDO(op) +#endif + ) { + ret = __db_pgerr(file_dbp, argp->pgno, ret); + goto out; + } else + goto done; + } + + cmp_n = LOG_COMPARE(lsnp, &LSN(pagep)); + cmp_p = LOG_COMPARE(&LSN(pagep), &argp->nlsn); + CHECK_LSN(file_dbp->dbenv, op, cmp_p, &LSN(pagep), &argp->nlsn); + + if (cmp_p == 0 && DB_REDO(op)) { + /* Need to truncate the page. */ + REC_DIRTY(mpf, &pagep); + HOFFSET(pagep) = file_dbp->pgsize; + NUM_ENT(pagep) = 0; + pagep->lsn = *lsnp; + } else if (cmp_n == 0 && !DB_REDO(op)) { + /* Need to put the data back on the page. */ + REC_DIRTY(mpf, &pagep); + if (TYPE(pagep) == P_OVERFLOW) { + OV_REF(pagep) = OV_REF(argp->hdr.data); + OV_LEN(pagep) = OV_LEN(argp->hdr.data); + bp = (u_int8_t *) pagep + P_OVERHEAD(file_dbp); + memcpy(bp, argp->data.data, argp->data.size); + } else { + bp = (u_int8_t *)pagep + + (db_indx_t)(HOFFSET(pagep) - argp->data.size); + memcpy(bp, argp->data.data, argp->data.size); + + /* Copy index table. */ + pinp = P_INP(file_dbp, pagep) + NUM_ENT(pagep); + ninp = argp->ind.data; + for (i = 0; + i < (int)(argp->ind.size / sizeof(*ninp)); i++) + *pinp++ = *ninp++; + HOFFSET(pagep) -= argp->data.size; + NUM_ENT(pagep) = i; + } + pagep->lsn = argp->nlsn; + } + + if ((ret = __memp_fput(mpf, pagep, 0)) != 0) + goto out; +done: + *lsnp = argp->prev_lsn; + ret = 0; + +out: REC_CLOSE; +} + +/* + * __bam_pgno_recover -- + * Recovery function for page number replacment. + * + * PUBLIC: int __bam_pgno_recover + * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + */ +int +__bam_pgno_recover(dbenv, dbtp, lsnp, op, info) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops op; + void *info; +{ + BINTERNAL *bi; + __bam_pgno_args *argp; + DB *file_dbp; + DBC *dbc; + DB_MPOOLFILE *mpf; + PAGE *pagep, *npagep; + db_pgno_t *pgnop; + int cmp_n, cmp_p, ret; + + COMPQUIET(info, NULL); + + REC_PRINT(__bam_pgno_print); + REC_INTRO(__bam_pgno_read, 1, 0); + + REC_FGET(mpf, argp->pgno, &pagep, done); + + cmp_n = LOG_COMPARE(lsnp, &LSN(pagep)); + cmp_p = LOG_COMPARE(&LSN(pagep), &argp->lsn); + CHECK_LSN(file_dbp->dbenv, op, cmp_p, &LSN(pagep), &argp->lsn); + + if ((cmp_p == 0 && DB_REDO(op)) || (cmp_n == 0 && !DB_REDO(op))) { + switch (TYPE(pagep)) { + case P_IBTREE: + /* + * An internal record can have both a overflow + * and child pointer. Fetch the page to see + * which it is. + */ + bi = GET_BINTERNAL(file_dbp, pagep, argp->indx); + if (B_TYPE(bi->type) == B_OVERFLOW) { + REC_FGET(mpf, argp->npgno, &npagep, out); + + if (TYPE(npagep) == P_OVERFLOW) + pgnop = + &((BOVERFLOW *)(bi->data))->pgno; + else + pgnop = &bi->pgno; + if ((ret = __memp_fput(mpf, npagep, 0)) != 0) + goto out; + break; + } + pgnop = &bi->pgno; + break; + case P_IRECNO: + pgnop = + &GET_RINTERNAL(file_dbp, pagep, argp->indx)->pgno; + break; + default: + pgnop = + &GET_BOVERFLOW(file_dbp, pagep, argp->indx)->pgno; + break; + } + + if (DB_REDO(op)) { + /* Need to redo update described. */ + REC_DIRTY(mpf, &pagep); + *pgnop = argp->npgno; + pagep->lsn = *lsnp; + } else { + REC_DIRTY(mpf, &pagep); + *pgnop = argp->opgno; + pagep->lsn = argp->lsn; + } + } + + if ((ret = __memp_fput(mpf, pagep, 0)) != 0) + goto out; + +done: + *lsnp = argp->prev_lsn; + ret = 0; + +out: REC_CLOSE; +} + +/* + * __bam_relink_43_recover -- + * Recovery function for relink. + * + * PUBLIC: int __bam_relink_43_recover + * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); + */ +int +__bam_relink_43_recover(dbenv, dbtp, lsnp, op, info) + DB_ENV *dbenv; + DBT *dbtp; + DB_LSN *lsnp; + db_recops op; + void *info; +{ + __bam_relink_43_args *argp; + DB *file_dbp; + DBC *dbc; + DB_MPOOLFILE *mpf; + PAGE *pagep; + int cmp_n, cmp_p, modified, ret; + + pagep = NULL; + COMPQUIET(info, NULL); + REC_PRINT(__bam_relink_43_print); + REC_INTRO(__bam_relink_43_read, 1, 0); + + /* + * There are up to three pages we need to check -- the page, and the + * previous and next pages, if they existed. For a page add operation, + * the current page is the result of a split and is being recovered + * elsewhere, so all we need do is recover the next page. + */ + if ((ret = __memp_fget(mpf, &argp->pgno, NULL, 0, &pagep)) != 0) { if (ret != DB_PAGE_NOTFOUND #ifndef HAVE_FTRUNCATE || DB_REDO(op) @@ -1029,13 +1436,13 @@ __bam_relink_recover(dbenv, dbtp, lsnp, op, info) } modified = 0; - cmp_p = log_compare(&LSN(pagep), &argp->lsn); - CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn); + cmp_p = LOG_COMPARE(&LSN(pagep), &argp->lsn); + CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn); if (cmp_p == 0 && DB_REDO(op)) { /* Redo the relink. */ pagep->lsn = *lsnp; modified = 1; - } else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) { + } else if (LOG_COMPARE(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) { /* Undo the relink. */ pagep->next_pgno = argp->next; pagep->prev_pgno = argp->prev; @@ -1047,7 +1454,7 @@ __bam_relink_recover(dbenv, dbtp, lsnp, op, info) goto out; pagep = NULL; -next2: if ((ret = __memp_fget(mpf, &argp->next, 0, &pagep)) != 0) { +next2: if ((ret = __memp_fget(mpf, &argp->next, NULL, 0, &pagep)) != 0) { if (ret != DB_PAGE_NOTFOUND #ifndef HAVE_FTRUNCATE || DB_REDO(op) @@ -1060,31 +1467,31 @@ next2: if ((ret = __memp_fget(mpf, &argp->next, 0, &pagep)) != 0) { } modified = 0; - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->lsn_next); - CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn_next); + cmp_n = LOG_COMPARE(lsnp, &LSN(pagep)); + cmp_p = LOG_COMPARE(&LSN(pagep), &argp->lsn_next); + CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn_next); if (cmp_p == 0 && DB_REDO(op)) { /* Redo the remove or undo the add. */ + REC_DIRTY(mpf, &pagep); pagep->prev_pgno = argp->prev; - modified = 1; } else if (cmp_n == 0 && DB_UNDO(op)) { /* Undo the remove or redo the add. */ + REC_DIRTY(mpf, &pagep); pagep->prev_pgno = argp->pgno; - modified = 1; } - if (modified == 1) { + if (modified) { if (DB_UNDO(op)) pagep->lsn = argp->lsn_next; else pagep->lsn = *lsnp; } - if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) + if ((ret = __memp_fput(mpf, pagep, 0)) != 0) goto out; pagep = NULL; -prev: if ((ret = __memp_fget(mpf, &argp->prev, 0, &pagep)) != 0) { +prev: if ((ret = __memp_fget(mpf, &argp->prev, NULL, 0, &pagep)) != 0) { if (ret != DB_PAGE_NOTFOUND #ifndef HAVE_FTRUNCATE || DB_REDO(op) @@ -1097,26 +1504,26 @@ prev: if ((ret = __memp_fget(mpf, &argp->prev, 0, &pagep)) != 0) { } modified = 0; - cmp_p = log_compare(&LSN(pagep), &argp->lsn_prev); - CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn_prev); + cmp_p = LOG_COMPARE(&LSN(pagep), &argp->lsn_prev); + CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn_prev); if (cmp_p == 0 && DB_REDO(op)) { /* Redo the relink. */ + REC_DIRTY(mpf, &pagep); pagep->next_pgno = argp->next; - modified = 1; - } else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) { + } else if (LOG_COMPARE(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) { /* Undo the relink. */ + REC_DIRTY(mpf, &pagep); pagep->next_pgno = argp->pgno; - modified = 1; } - if (modified == 1) { + if (modified) { if (DB_UNDO(op)) pagep->lsn = argp->lsn_prev; else pagep->lsn = *lsnp; } - if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) + if ((ret = __memp_fput(mpf, pagep, 0)) != 0) goto out; pagep = NULL; |