📄 hash_rec.c
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1996-2002 * Sleepycat Software. All rights reserved. *//* * Copyright (c) 1995, 1996 * Margo Seltzer. All rights reserved. *//* * Copyright (c) 1995, 1996 * The President and Fellows of Harvard University. All rights reserved. * * This code is derived from software contributed to Berkeley by * Margo Seltzer. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include "db_config.h"#ifndef lintstatic const char revid[] = "$Id: hash_rec.c,v 11.69 2002/09/03 14:12:49 margo Exp $";#endif /* not lint */#ifndef NO_SYSTEM_INCLUDES#include <sys/types.h>#include <string.h>#endif#include "db_int.h"#include "dbinc/db_page.h"#include "dbinc/btree.h"#include "dbinc/hash.h"#include "dbinc/log.h"static int __ham_alloc_pages __P((DB *, __ham_groupalloc_args *, DB_LSN *));/* * __ham_insdel_recover -- * * PUBLIC: int __ham_insdel_recover * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); */int__ham_insdel_recover(dbenv, dbtp, lsnp, op, info) DB_ENV *dbenv; DBT *dbtp; DB_LSN *lsnp; db_recops op; void *info;{ __ham_insdel_args *argp; DB *file_dbp; DBC *dbc; DB_MPOOLFILE *mpf; PAGE *pagep; u_int32_t flags, opcode; int cmp_n, cmp_p, ret, type; pagep = NULL; COMPQUIET(info, NULL); REC_PRINT(__ham_insdel_print); REC_INTRO(__ham_insdel_read, 1); if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) { if (DB_UNDO(op)) { /* * We are undoing and the page doesn't exist. That * is equivalent to having a pagelsn of 0, so we * would not have to undo anything. In this case, * don't bother creating a page. */ goto done; } else if ((ret = mpf->get(mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) goto out; } cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->pagelsn); /* * Two possible things going on: * redo a delete/undo a put: delete the item from the page. * redo a put/undo a delete: add the item to the page. * If we are undoing a delete, then the information logged is the * entire entry off the page, not just the data of a dbt. In * this case, we want to copy it back onto the page verbatim. * We do this by calling __putitem with the type H_OFFPAGE instead * of H_KEYDATA. */ opcode = OPCODE_OF(argp->opcode); flags = 0; if ((opcode == DELPAIR && cmp_n == 0 && DB_UNDO(op)) || (opcode == PUTPAIR && cmp_p == 0 && DB_REDO(op))) { /* * Need to redo a PUT or undo a delete. If we are undoing a * delete, we've got to restore the item back to its original * position. That's a royal pain in the butt (because we do * not store item lengths on the page), but there's no choice. */ if (opcode != DELPAIR || argp->ndx == (u_int32_t)NUM_ENT(pagep)) { __ham_putitem(file_dbp, pagep, &argp->key, DB_UNDO(op) || PAIR_ISKEYBIG(argp->opcode) ? H_OFFPAGE : H_KEYDATA); if (PAIR_ISDATADUP(argp->opcode)) type = H_DUPLICATE; else if (DB_UNDO(op) || PAIR_ISDATABIG(argp->opcode)) type = H_OFFPAGE; else type = H_KEYDATA; __ham_putitem(file_dbp, pagep, &argp->data, type); } else (void)__ham_reputpair(file_dbp, pagep, argp->ndx, &argp->key, &argp->data); LSN(pagep) = DB_REDO(op) ? *lsnp : argp->pagelsn; flags = DB_MPOOL_DIRTY; } else if ((opcode == DELPAIR && cmp_p == 0 && DB_REDO(op)) || (opcode == PUTPAIR && cmp_n == 0 && DB_UNDO(op))) { /* Need to undo a put or redo a delete. */ __ham_dpair(file_dbp, pagep, argp->ndx); LSN(pagep) = DB_REDO(op) ? *lsnp : argp->pagelsn; flags = DB_MPOOL_DIRTY; } if ((ret = mpf->put(mpf, pagep, flags)) != 0) goto out; pagep = NULL; /* Return the previous LSN. */done: *lsnp = argp->prev_lsn; ret = 0;out: if (pagep != NULL) (void)mpf->put(mpf, pagep, 0); REC_CLOSE;}/* * __ham_newpage_recover -- * This log message is used when we add/remove overflow pages. This * message takes care of the pointer chains, not the data on the pages. * * PUBLIC: int __ham_newpage_recover * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); */int__ham_newpage_recover(dbenv, dbtp, lsnp, op, info) DB_ENV *dbenv; DBT *dbtp; DB_LSN *lsnp; db_recops op; void *info;{ __ham_newpage_args *argp; DB *file_dbp; DBC *dbc; DB_MPOOLFILE *mpf; PAGE *pagep; u_int32_t flags; int cmp_n, cmp_p, ret; pagep = NULL; COMPQUIET(info, NULL); REC_PRINT(__ham_newpage_print); REC_INTRO(__ham_newpage_read, 1); if ((ret = mpf->get(mpf, &argp->new_pgno, 0, &pagep)) != 0) { if (DB_UNDO(op)) { /* * We are undoing and the page doesn't exist. That * is equivalent to having a pagelsn of 0, so we * would not have to undo anything. In this case, * don't bother creating a page. */ ret = 0; goto ppage; } else if ((ret = mpf->get(mpf, &argp->new_pgno, DB_MPOOL_CREATE, &pagep)) != 0) goto out; } /* * There are potentially three pages we need to check: the one * that we created/deleted, the one before it and the one after * it. */ cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->pagelsn); flags = 0; if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == PUTOVFL) || (cmp_n == 0 && DB_UNDO(op) && argp->opcode == DELOVFL)) { /* Redo a create new page or undo a delete new page. */ P_INIT(pagep, file_dbp->pgsize, argp->new_pgno, argp->prev_pgno, argp->next_pgno, 0, P_HASH); flags = DB_MPOOL_DIRTY; } else if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DELOVFL) || (cmp_n == 0 && DB_UNDO(op) && argp->opcode == PUTOVFL)) { /* * Redo a delete or undo a create new page. All we * really need to do is change the LSN. */ flags = DB_MPOOL_DIRTY; } if (flags) LSN(pagep) = DB_REDO(op) ? *lsnp : argp->pagelsn; if ((ret = mpf->put(mpf, pagep, flags)) != 0) goto out; pagep = NULL; /* Now do the prev page. */ppage: if (argp->prev_pgno != PGNO_INVALID) { if ((ret = mpf->get(mpf, &argp->prev_pgno, 0, &pagep)) != 0) { if (DB_UNDO(op)) { /* * We are undoing and the page doesn't exist. * That is equivalent to having a pagelsn of 0, * so we would not have to undo anything. In * this case, don't bother creating a page. */ ret = 0; goto npage; } else if ((ret = mpf->get(mpf, &argp->prev_pgno, DB_MPOOL_CREATE, &pagep)) != 0) goto out; } cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_p = log_compare(&LSN(pagep), &argp->prevlsn); CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->prevlsn); flags = 0; if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == PUTOVFL) || (cmp_n == 0 && DB_UNDO(op) && argp->opcode == DELOVFL)) { /* Redo a create new page or undo a delete new page. */ pagep->next_pgno = argp->new_pgno; flags = DB_MPOOL_DIRTY; } else if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DELOVFL) || (cmp_n == 0 && DB_UNDO(op) && argp->opcode == PUTOVFL)) { /* Redo a delete or undo a create new page. */ pagep->next_pgno = argp->next_pgno; flags = DB_MPOOL_DIRTY; } if (flags) LSN(pagep) = DB_REDO(op) ? *lsnp : argp->prevlsn; if ((ret = mpf->put(mpf, pagep, flags)) != 0) goto out; pagep = NULL; } /* Now time to do the next page */npage: if (argp->next_pgno != PGNO_INVALID) { if ((ret = mpf->get(mpf, &argp->next_pgno, 0, &pagep)) != 0) { if (DB_UNDO(op)) { /* * We are undoing and the page doesn't exist. * That is equivalent to having a pagelsn of 0, * so we would not have to undo anything. In * this case, don't bother creating a page. */ goto done; } else if ((ret = mpf->get(mpf, &argp->next_pgno, DB_MPOOL_CREATE, &pagep)) != 0) goto out; } cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_p = log_compare(&LSN(pagep), &argp->nextlsn); CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->nextlsn); flags = 0; if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == PUTOVFL) || (cmp_n == 0 && DB_UNDO(op) && argp->opcode == DELOVFL)) { /* Redo a create new page or undo a delete new page. */ pagep->prev_pgno = argp->new_pgno; flags = DB_MPOOL_DIRTY; } else if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DELOVFL) || (cmp_n == 0 && DB_UNDO(op) && argp->opcode == PUTOVFL)) { /* Redo a delete or undo a create new page. */ pagep->prev_pgno = argp->prev_pgno; flags = DB_MPOOL_DIRTY; } if (flags) LSN(pagep) = DB_REDO(op) ? *lsnp : argp->nextlsn; if ((ret = mpf->put(mpf, pagep, flags)) != 0) goto out; pagep = NULL; }done: *lsnp = argp->prev_lsn; ret = 0;out: if (pagep != NULL) (void)mpf->put(mpf, pagep, 0); REC_CLOSE;}/* * __ham_replace_recover -- * This log message refers to partial puts that are local to a single * page. You can think of them as special cases of the more general * insdel log message. * * PUBLIC: int __ham_replace_recover * PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); */int__ham_replace_recover(dbenv, dbtp, lsnp, op, info) DB_ENV *dbenv; DBT *dbtp; DB_LSN *lsnp; db_recops op; void *info;{ __ham_replace_args *argp; DB *file_dbp; DBC *dbc; DB_MPOOLFILE *mpf; DBT dbt; PAGE *pagep; u_int32_t flags; int32_t grow; int cmp_n, cmp_p, ret; u_int8_t *hk; pagep = NULL; COMPQUIET(info, NULL); REC_PRINT(__ham_replace_print); REC_INTRO(__ham_replace_read, 1); if ((ret = mpf->get(mpf, &argp->pgno, 0, &pagep)) != 0) { if (DB_UNDO(op)) { /* * We are undoing and the page doesn't exist. That * is equivalent to having a pagelsn of 0, so we * would not have to undo anything. In this case, * don't bother creating a page. */ goto done; } else if ((ret = mpf->get(mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) goto out; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -