diff options
Diffstat (limited to 'db2/hash/hash_rec.c')
-rw-r--r-- | db2/hash/hash_rec.c | 986 |
1 files changed, 0 insertions, 986 deletions
diff --git a/db2/hash/hash_rec.c b/db2/hash/hash_rec.c deleted file mode 100644 index b58f2c6eb7..0000000000 --- a/db2/hash/hash_rec.c +++ /dev/null @@ -1,986 +0,0 @@ -/*- - * See the file LICENSE for redistribution information. - * - * Copyright (c) 1996, 1997, 1998 - * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. 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 "config.h" - -#ifndef lint -static const char sccsid[] = "@(#)hash_rec.c 10.22 (Sleepycat) 10/21/98"; -#endif /* not lint */ - -#ifndef NO_SYSTEM_INCLUDES -#include <sys/types.h> - -#include <errno.h> -#include <string.h> -#endif - -#include "db_int.h" -#include "shqueue.h" -#include "db_page.h" -#include "hash.h" -#include "btree.h" -#include "log.h" -#include "common_ext.h" - -/* - * __ham_insdel_recover -- - * - * PUBLIC: int __ham_insdel_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_insdel_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __ham_insdel_args *argp; - DB *file_dbp; - DBC *dbc; - HASH_CURSOR *hcp; - DB_MPOOLFILE *mpf; - PAGE *pagep; - u_int32_t op; - int cmp_n, cmp_p, getmeta, ret; - - getmeta = 0; - hcp = NULL; - REC_PRINT(__ham_insdel_print); - REC_INTRO(__ham_insdel_read); - hcp = (HASH_CURSOR *)dbc->internal; - - ret = memp_fget(mpf, &argp->pgno, 0, &pagep); - if (ret != 0) { - if (!redo) { - /* - * 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 = memp_fget(mpf, &argp->pgno, - DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - GET_META(file_dbp, hcp, ret); - if (ret != 0) - goto out; - getmeta = 1; - - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&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. - */ - op = OPCODE_OF(argp->opcode); - - if ((op == DELPAIR && cmp_n == 0 && !redo) || - (op == PUTPAIR && cmp_p == 0 && redo)) { - /* - * 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 (op != DELPAIR || - argp->ndx == (u_int32_t)H_NUMPAIRS(pagep)) { - __ham_putitem(pagep, &argp->key, - !redo || PAIR_ISKEYBIG(argp->opcode) ? - H_OFFPAGE : H_KEYDATA); - __ham_putitem(pagep, &argp->data, - !redo || PAIR_ISDATABIG(argp->opcode) ? - H_OFFPAGE : H_KEYDATA); - } else - (void) __ham_reputpair(pagep, hcp->hdr->pagesize, - argp->ndx, &argp->key, &argp->data); - - LSN(pagep) = redo ? *lsnp : argp->pagelsn; - if ((ret = __ham_put_page(file_dbp, pagep, 1)) != 0) - goto out; - - } else if ((op == DELPAIR && cmp_p == 0 && redo) - || (op == PUTPAIR && cmp_n == 0 && !redo)) { - /* Need to undo a put or redo a delete. */ - __ham_dpair(file_dbp, pagep, argp->ndx); - LSN(pagep) = redo ? *lsnp : argp->pagelsn; - if ((ret = __ham_put_page(file_dbp, (PAGE *)pagep, 1)) != 0) - goto out; - } else - if ((ret = __ham_put_page(file_dbp, (PAGE *)pagep, 0)) != 0) - goto out; - - /* Return the previous LSN. */ -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: if (getmeta) - RELEASE_META(file_dbp, hcp); - 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_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_newpage_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __ham_newpage_args *argp; - DB *file_dbp; - DBC *dbc; - HASH_CURSOR *hcp; - DB_MPOOLFILE *mpf; - PAGE *pagep; - int cmp_n, cmp_p, change, getmeta, ret; - - getmeta = 0; - hcp = NULL; - REC_PRINT(__ham_newpage_print); - REC_INTRO(__ham_newpage_read); - hcp = (HASH_CURSOR *)dbc->internal; - - ret = memp_fget(mpf, &argp->new_pgno, 0, &pagep); - if (ret != 0) { - if (!redo) { - /* - * 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 = memp_fget(mpf, &argp->new_pgno, - DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); - if (ret != 0) - goto out; - getmeta = 1; - - /* - * 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); - change = 0; - - if ((cmp_p == 0 && redo && argp->opcode == PUTOVFL) || - (cmp_n == 0 && !redo && 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); - change = 1; - } else if ((cmp_p == 0 && redo && argp->opcode == DELOVFL) || - (cmp_n == 0 && !redo && argp->opcode == PUTOVFL)) { - /* - * Redo a delete or undo a create new page. All we - * really need to do is change the LSN. - */ - change = 1; - } - - if (!change) { - if ((ret = __ham_put_page(file_dbp, (PAGE *)pagep, 0)) != 0) - goto out; - } else { - LSN(pagep) = redo ? *lsnp : argp->pagelsn; - if ((ret = __ham_put_page(file_dbp, (PAGE *)pagep, 1)) != 0) - goto out; - } - - /* Now do the prev page. */ -ppage: if (argp->prev_pgno != PGNO_INVALID) { - ret = memp_fget(mpf, &argp->prev_pgno, 0, &pagep); - - if (ret != 0) { - if (!redo) { - /* - * 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 = - memp_fget(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); - change = 0; - - if ((cmp_p == 0 && redo && argp->opcode == PUTOVFL) || - (cmp_n == 0 && !redo && argp->opcode == DELOVFL)) { - /* Redo a create new page or undo a delete new page. */ - pagep->next_pgno = argp->new_pgno; - change = 1; - } else if ((cmp_p == 0 && redo && argp->opcode == DELOVFL) || - (cmp_n == 0 && !redo && argp->opcode == PUTOVFL)) { - /* Redo a delete or undo a create new page. */ - pagep->next_pgno = argp->next_pgno; - change = 1; - } - - if (!change) { - if ((ret = - __ham_put_page(file_dbp, (PAGE *)pagep, 0)) != 0) - goto out; - } else { - LSN(pagep) = redo ? *lsnp : argp->prevlsn; - if ((ret = - __ham_put_page(file_dbp, (PAGE *)pagep, 1)) != 0) - goto out; - } - } - - /* Now time to do the next page */ -npage: if (argp->next_pgno != PGNO_INVALID) { - ret = memp_fget(mpf, &argp->next_pgno, 0, &pagep); - - if (ret != 0) { - if (!redo) { - /* - * 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 = - memp_fget(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); - change = 0; - - if ((cmp_p == 0 && redo && argp->opcode == PUTOVFL) || - (cmp_n == 0 && !redo && argp->opcode == DELOVFL)) { - /* Redo a create new page or undo a delete new page. */ - pagep->prev_pgno = argp->new_pgno; - change = 1; - } else if ((cmp_p == 0 && redo && argp->opcode == DELOVFL) || - (cmp_n == 0 && !redo && argp->opcode == PUTOVFL)) { - /* Redo a delete or undo a create new page. */ - pagep->prev_pgno = argp->prev_pgno; - change = 1; - } - - if (!change) { - if ((ret = - __ham_put_page(file_dbp, (PAGE *)pagep, 0)) != 0) - goto out; - } else { - LSN(pagep) = redo ? *lsnp : argp->nextlsn; - if ((ret = - __ham_put_page(file_dbp, (PAGE *)pagep, 1)) != 0) - goto out; - } - } -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: if (getmeta) - RELEASE_META(file_dbp, hcp); - 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_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_replace_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __ham_replace_args *argp; - DB *file_dbp; - DBC *dbc; - HASH_CURSOR *hcp; - DB_MPOOLFILE *mpf; - DBT dbt; - PAGE *pagep; - int32_t grow; - int change, cmp_n, cmp_p, getmeta, ret; - u_int8_t *hk; - - getmeta = 0; - hcp = NULL; - REC_PRINT(__ham_replace_print); - REC_INTRO(__ham_replace_read); - hcp = (HASH_CURSOR *)dbc->internal; - - ret = memp_fget(mpf, &argp->pgno, 0, &pagep); - if (ret != 0) { - if (!redo) { - /* - * 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 = memp_fget(mpf, &argp->pgno, - DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); - if (ret != 0) - goto out; - getmeta = 1; - - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); - - if (cmp_p == 0 && redo) { - change = 1; - /* Reapply the change as specified. */ - dbt.data = argp->newitem.data; - dbt.size = argp->newitem.size; - grow = argp->newitem.size - argp->olditem.size; - LSN(pagep) = *lsnp; - } else if (cmp_n == 0 && !redo) { - change = 1; - /* Undo the already applied change. */ - dbt.data = argp->olditem.data; - dbt.size = argp->olditem.size; - grow = argp->olditem.size - argp->newitem.size; - LSN(pagep) = argp->pagelsn; - } else { - change = 0; - grow = 0; - } - - if (change) { - __ham_onpage_replace(pagep, - file_dbp->pgsize, argp->ndx, argp->off, grow, &dbt); - if (argp->makedup) { - hk = P_ENTRY(pagep, argp->ndx); - if (redo) - HPAGE_PTYPE(hk) = H_DUPLICATE; - else - HPAGE_PTYPE(hk) = H_KEYDATA; - } - } - - if ((ret = __ham_put_page(file_dbp, pagep, change)) != 0) - goto out; - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: if (getmeta) - RELEASE_META(file_dbp, hcp); - REC_CLOSE; -} - -/* - * __ham_newpgno_recover -- - * This log message is used when allocating or deleting an overflow - * page. It takes care of modifying the meta data. - * - * PUBLIC: int __ham_newpgno_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_newpgno_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __ham_newpgno_args *argp; - DB *file_dbp; - DBC *dbc; - HASH_CURSOR *hcp; - DB_MPOOLFILE *mpf; - PAGE *pagep; - int change, cmp_n, cmp_p, getmeta, ret; - - getmeta = 0; - hcp = NULL; - REC_PRINT(__ham_newpgno_print); - REC_INTRO(__ham_newpgno_read); - hcp = (HASH_CURSOR *)dbc->internal; - - GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); - if (ret != 0) - goto out; - getmeta = 1; - - /* - * There are two phases to the recovery here. First we need - * to update the meta data; then we need to update the page. - * We'll do the meta-data first. - */ - cmp_n = log_compare(lsnp, &hcp->hdr->lsn); - cmp_p = log_compare(&hcp->hdr->lsn, &argp->metalsn); - - change = 0; - if ((cmp_p == 0 && redo && argp->opcode == ALLOCPGNO) || - (cmp_n == 0 && !redo && argp->opcode == DELPGNO)) { - /* Need to redo an allocation or undo a deletion. */ - hcp->hdr->last_freed = argp->free_pgno; - if (redo && argp->old_pgno != 0) /* Must be ALLOCPGNO */ - hcp->hdr->spares[hcp->hdr->ovfl_point]++; - change = 1; - } else if (cmp_p == 0 && redo && argp->opcode == DELPGNO) { - /* Need to redo a deletion */ - hcp->hdr->last_freed = argp->pgno; - change = 1; - } else if (cmp_n == 0 && !redo && argp->opcode == ALLOCPGNO) { - /* undo an allocation. */ - if (argp->old_pgno == 0) - hcp->hdr->last_freed = argp->pgno; - else { - hcp->hdr->spares[hcp->hdr->ovfl_point]--; - hcp->hdr->last_freed = 0; - } - change = 1; - } - if (change) { - hcp->hdr->lsn = redo ? *lsnp : argp->metalsn; - F_SET(hcp, H_DIRTY); - } - - - /* Now check the newly allocated/freed page. */ - ret = memp_fget(mpf, &argp->pgno, 0, &pagep); - - if (ret != 0) { - if (!redo) { - /* - * 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 = memp_fget(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); - - change = 0; - if (cmp_p == 0 && redo && argp->opcode == ALLOCPGNO) { - /* Need to redo an allocation. */ - P_INIT(pagep, file_dbp->pgsize, argp->pgno, PGNO_INVALID, - PGNO_INVALID, 0, argp->new_type); - change = 1; - } else if (cmp_n == 0 && !redo && argp->opcode == DELPGNO) { - /* Undoing a delete. */ - P_INIT(pagep, file_dbp->pgsize, argp->pgno, PGNO_INVALID, - argp->old_pgno, 0, argp->old_type); - change = 1; - } else if ((cmp_p == 0 && redo && argp->opcode == DELPGNO) || - (cmp_n == 0 && !redo && argp->opcode == ALLOCPGNO)) { - /* Need to redo a deletion or undo an allocation. */ - NEXT_PGNO(pagep) = argp->free_pgno; - TYPE(pagep) = P_INVALID; - change = 1; - } - if (change) - LSN(pagep) = redo ? *lsnp : argp->pagelsn; - - if ((ret = __ham_put_page(file_dbp, pagep, change)) != 0) - goto out; - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: if (getmeta) - RELEASE_META(file_dbp, hcp); - REC_CLOSE; - -} - -/* - * __ham_splitmeta_recover -- - * This is the meta-data part of the split. Records the new and old - * bucket numbers and the new/old mask information. - * - * PUBLIC: int __ham_splitmeta_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_splitmeta_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __ham_splitmeta_args *argp; - DB *file_dbp; - DBC *dbc; - HASH_CURSOR *hcp; - DB_MPOOLFILE *mpf; - int change, cmp_n, cmp_p, getmeta, ret; - u_int32_t pow; - - getmeta = 0; - hcp = NULL; - REC_PRINT(__ham_splitmeta_print); - REC_INTRO(__ham_splitmeta_read); - hcp = (HASH_CURSOR *)dbc->internal; - - GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); - if (ret != 0) - goto out; - getmeta = 1; - - /* - * There are two phases to the recovery here. First we need - * to update the meta data; then we need to update the page. - * We'll do the meta-data first. - */ - cmp_n = log_compare(lsnp, &hcp->hdr->lsn); - cmp_p = log_compare(&hcp->hdr->lsn, &argp->metalsn); - - change = 0; - if (cmp_p == 0 && redo) { - /* Need to redo the split information. */ - hcp->hdr->max_bucket = argp->bucket + 1; - pow = __db_log2(hcp->hdr->max_bucket + 1); - if (pow > hcp->hdr->ovfl_point) { - hcp->hdr->spares[pow] = - hcp->hdr->spares[hcp->hdr->ovfl_point]; - hcp->hdr->ovfl_point = pow; - } - if (hcp->hdr->max_bucket > hcp->hdr->high_mask) { - hcp->hdr->low_mask = hcp->hdr->high_mask; - hcp->hdr->high_mask = - hcp->hdr->max_bucket | hcp->hdr->low_mask; - } - change = 1; - } else if (cmp_n == 0 && !redo) { - /* Need to undo the split information. */ - hcp->hdr->max_bucket = argp->bucket; - hcp->hdr->ovfl_point = argp->ovflpoint; - hcp->hdr->spares[hcp->hdr->ovfl_point] = argp->spares; - pow = 1 << __db_log2(hcp->hdr->max_bucket + 1); - hcp->hdr->high_mask = pow - 1; - hcp->hdr->low_mask = (pow >> 1) - 1; - change = 1; - } - if (change) { - hcp->hdr->lsn = redo ? *lsnp : argp->metalsn; - F_SET(hcp, H_DIRTY); - } - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: if (getmeta) - RELEASE_META(file_dbp, hcp); - REC_CLOSE; -} - -/* - * __ham_splitdata_recover -- - * - * PUBLIC: int __ham_splitdata_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_splitdata_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __ham_splitdata_args *argp; - DB *file_dbp; - DBC *dbc; - HASH_CURSOR *hcp; - DB_MPOOLFILE *mpf; - PAGE *pagep; - int change, cmp_n, cmp_p, getmeta, ret; - - getmeta = 0; - hcp = NULL; - REC_PRINT(__ham_splitdata_print); - REC_INTRO(__ham_splitdata_read); - hcp = (HASH_CURSOR *)dbc->internal; - - ret = memp_fget(mpf, &argp->pgno, 0, &pagep); - if (ret != 0) { - if (!redo) { - /* - * 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 = memp_fget(mpf, &argp->pgno, - DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); - if (ret != 0) - goto out; - getmeta = 1; - - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); - - /* - * There are two types of log messages here, one for the old page - * and one for the new pages created. The original image in the - * SPLITOLD record is used for undo. The image in the SPLITNEW - * is used for redo. We should never have a case where there is - * a redo operation and the SPLITOLD record is on disk, but not - * the SPLITNEW record. Therefore, we only have work to do when - * redo NEW messages and undo OLD messages, but we have to update - * LSNs in both cases. - */ - change = 0; - if (cmp_p == 0 && redo) { - if (argp->opcode == SPLITNEW) - /* Need to redo the split described. */ - memcpy(pagep, argp->pageimage.data, - argp->pageimage.size); - LSN(pagep) = *lsnp; - change = 1; - } else if (cmp_n == 0 && !redo) { - if (argp->opcode == SPLITOLD) { - /* Put back the old image. */ - memcpy(pagep, argp->pageimage.data, - argp->pageimage.size); - } else - P_INIT(pagep, file_dbp->pgsize, argp->pgno, - PGNO_INVALID, PGNO_INVALID, 0, P_HASH); - LSN(pagep) = argp->pagelsn; - change = 1; - } - if ((ret = __ham_put_page(file_dbp, pagep, change)) != 0) - goto out; - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: if (getmeta) - RELEASE_META(file_dbp, hcp); - REC_CLOSE; -} - -/* - * __ham_ovfl_recover -- - * This message is generated when we initialize a set of overflow pages. - * - * PUBLIC: int __ham_ovfl_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_ovfl_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __ham_ovfl_args *argp; - DB *file_dbp; - DBC *dbc; - HASH_CURSOR *hcp; - DB_MPOOLFILE *mpf; - PAGE *pagep; - db_pgno_t max_pgno, pgno; - int cmp_n, cmp_p, getmeta, ret; - - getmeta = 0; - hcp = NULL; - REC_PRINT(__ham_ovfl_print); - REC_INTRO(__ham_ovfl_read); - hcp = (HASH_CURSOR *)dbc->internal; - - GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); - if (ret != 0) - goto out; - getmeta = 1; - - cmp_n = log_compare(lsnp, &hcp->hdr->lsn); - cmp_p = log_compare(&hcp->hdr->lsn, &argp->metalsn); - - if (cmp_p == 0 && redo) { - /* Redo the allocation. */ - hcp->hdr->last_freed = argp->start_pgno; - hcp->hdr->spares[argp->ovflpoint] += argp->npages; - hcp->hdr->lsn = *lsnp; - F_SET(hcp, H_DIRTY); - } else if (cmp_n == 0 && !redo) { - hcp->hdr->last_freed = argp->free_pgno; - hcp->hdr->spares[argp->ovflpoint] -= argp->npages; - hcp->hdr->lsn = argp->metalsn; - F_SET(hcp, H_DIRTY); - } - - max_pgno = argp->start_pgno + argp->npages - 1; - ret = 0; - for (pgno = argp->start_pgno; pgno <= max_pgno; pgno++) { - if ((ret = memp_fget(mpf, &pgno, 0, &pagep)) != 0) { - if (!redo) { - ret = 0; - continue; - } - if ((ret = memp_fget(mpf, - &pgno, DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - if (redo && log_compare((const DB_LSN *)lsnp, - (const DB_LSN *)&LSN(pagep)) > 0) { - P_INIT(pagep, file_dbp->pgsize, pgno, PGNO_INVALID, - pgno == max_pgno ? argp->free_pgno : pgno + 1, - 0, P_HASH); - LSN(pagep) = *lsnp; - ret = __ham_put_page(file_dbp, pagep, 1); - } else if (!redo) { - ZERO_LSN(pagep->lsn); - ret = __ham_put_page(file_dbp, pagep, 1); - } else - ret = __ham_put_page(file_dbp, pagep, 0); - if (ret) - goto out; - } - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: if (getmeta) - RELEASE_META(file_dbp, hcp); - REC_CLOSE; -} - -/* - * __ham_copypage_recover -- - * Recovery function for copypage. - * - * PUBLIC: int __ham_copypage_recover - * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); - */ -int -__ham_copypage_recover(logp, dbtp, lsnp, redo, info) - DB_LOG *logp; - DBT *dbtp; - DB_LSN *lsnp; - int redo; - void *info; -{ - __ham_copypage_args *argp; - DB *file_dbp; - DBC *dbc; - HASH_CURSOR *hcp; - DB_MPOOLFILE *mpf; - PAGE *pagep; - int cmp_n, cmp_p, getmeta, modified, ret; - - getmeta = 0; - hcp = NULL; - REC_PRINT(__ham_copypage_print); - REC_INTRO(__ham_copypage_read); - hcp = (HASH_CURSOR *)dbc->internal; - - GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); - if (ret != 0) - goto out; - getmeta = 1; - modified = 0; - - /* This is the bucket page. */ - ret = memp_fget(mpf, &argp->pgno, 0, &pagep); - if (ret != 0) { - if (!redo) { - /* - * 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 donext; - } else if ((ret = memp_fget(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); - - if (cmp_p == 0 && redo) { - /* Need to redo update described. */ - memcpy(pagep, argp->page.data, argp->page.size); - LSN(pagep) = *lsnp; - modified = 1; - } else if (cmp_n == 0 && !redo) { - /* Need to undo update described. */ - P_INIT(pagep, hcp->hdr->pagesize, argp->pgno, PGNO_INVALID, - argp->next_pgno, 0, P_HASH); - LSN(pagep) = argp->pagelsn; - modified = 1; - } - if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) - goto out; - - /* Now fix up the "next" page. */ -donext: ret = memp_fget(mpf, &argp->next_pgno, 0, &pagep); - if (ret != 0) { - if (!redo) { - /* - * 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 do_nn; - } else if ((ret = memp_fget(mpf, &argp->next_pgno, - DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - /* There is nothing to do in the REDO case; only UNDO. */ - - cmp_n = log_compare(lsnp, &LSN(pagep)); - if (cmp_n == 0 && !redo) { - /* Need to undo update described. */ - memcpy(pagep, argp->page.data, argp->page.size); - modified = 1; - } - if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) - goto out; - - /* Now fix up the next's next page. */ -do_nn: if (argp->nnext_pgno == PGNO_INVALID) - goto done; - - ret = memp_fget(mpf, &argp->nnext_pgno, 0, &pagep); - if (ret != 0) { - if (!redo) { - /* - * 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 = memp_fget(mpf, &argp->nnext_pgno, - DB_MPOOL_CREATE, &pagep)) != 0) - goto out; - } - - cmp_n = log_compare(lsnp, &LSN(pagep)); - cmp_p = log_compare(&LSN(pagep), &argp->nnextlsn); - - if (cmp_p == 0 && redo) { - /* Need to redo update described. */ - PREV_PGNO(pagep) = argp->pgno; - LSN(pagep) = *lsnp; - modified = 1; - } else if (cmp_n == 0 && !redo) { - /* Need to undo update described. */ - PREV_PGNO(pagep) = argp->next_pgno; - LSN(pagep) = argp->nnextlsn; - modified = 1; - } - if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) - goto out; - -done: *lsnp = argp->prev_lsn; - ret = 0; - -out: if (getmeta) - RELEASE_META(file_dbp, hcp); - REC_CLOSE; -} |