📄 hash_rec.c
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1996-2004 * 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. * * $Id: hash_rec.c,v 11.83 2004/10/25 16:52:13 ubell 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/hash.h"#include "dbinc/log.h"#include "dbinc/mp.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 = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { if (DB_UNDO(op)) { if (ret == DB_PAGE_NOTFOUND) goto done; else { ret = __db_pgerr(file_dbp, argp->pgno, ret); goto out; } }#ifdef HAVE_FTRUNCATE /* If the page is not here then it was later truncated. */ if (!IS_ZERO_LSN(argp->pagelsn)) goto done;#endif /* * This page was created by a group allocation and * the file may not have been extend yet. * Create the page if necessary. */ if ((ret = __memp_fget(mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) { ret = __db_pgerr(file_dbp, argp->pgno, ret); 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 __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 = __memp_fput(mpf, pagep, flags)) != 0) goto out; pagep = NULL; /* Return the previous LSN. */done: *lsnp = argp->prev_lsn; ret = 0;out: if (pagep != NULL) (void)__memp_fput(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); REC_FGET(mpf, argp->new_pgno, &pagep, ppage); /* * 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 = __memp_fput(mpf, pagep, flags)) != 0) goto out; pagep = NULL; /* Now do the prev page. */ppage: if (argp->prev_pgno != PGNO_INVALID) { REC_FGET(mpf, argp->prev_pgno, &pagep, npage); 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 = __memp_fput(mpf, pagep, flags)) != 0) goto out; pagep = NULL; } /* Now time to do the next page */npage: if (argp->next_pgno != PGNO_INVALID) { REC_FGET(mpf, argp->next_pgno, &pagep, done); 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 = __memp_fput(mpf, pagep, flags)) != 0) goto out; pagep = NULL; }done: *lsnp = argp->prev_lsn; ret = 0;out: if (pagep != NULL) (void)__memp_fput(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; u_int32_t change; int cmp_n, cmp_p, is_plus, ret; u_int8_t *hk; pagep = NULL; COMPQUIET(info, NULL); REC_PRINT(__ham_replace_print); REC_INTRO(__ham_replace_read, 1); REC_FGET(mpf, argp->pgno, &pagep, done); cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->pagelsn); memset(&dbt, 0, sizeof(dbt)); flags = 0; /* * Before we know the direction of the transformation we will * determine the size differential; then once we know if we are * redoing or undoing, we'll adjust the sign (is_plus) appropriately. */ if (argp->newitem.size > argp->olditem.size) { change = argp->newitem.size - argp->olditem.size; is_plus = 1; } else { change = argp->olditem.size - argp->newitem.size; is_plus = 0; } if (cmp_p == 0 && DB_REDO(op)) { /* Reapply the change as specified. */ dbt.data = argp->newitem.data; dbt.size = argp->newitem.size; LSN(pagep) = *lsnp; /* * The is_plus flag is set properly to reflect * newitem.size - olditem.size. */ flags = DB_MPOOL_DIRTY; } else if (cmp_n == 0 && DB_UNDO(op)) { /* Undo the already applied change. */ dbt.data = argp->olditem.data; dbt.size = argp->olditem.size; /* * Invert is_plus to reflect sign of * olditem.size - newitem.size. */ is_plus = !is_plus; LSN(pagep) = argp->pagelsn; flags = DB_MPOOL_DIRTY; } if (flags) { __ham_onpage_replace(file_dbp, pagep, argp->ndx, argp->off, change, is_plus, &dbt); if (argp->makedup) { hk = P_ENTRY(file_dbp, pagep, argp->ndx); if (DB_REDO(op)) HPAGE_PTYPE(hk) = H_DUPLICATE; else HPAGE_PTYPE(hk) = H_KEYDATA; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -