1*7c478bd9Sstevel@tonic-gate /*- 2*7c478bd9Sstevel@tonic-gate * See the file LICENSE for redistribution information. 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * Copyright (c) 1996, 1997, 1998 5*7c478bd9Sstevel@tonic-gate * Sleepycat Software. All rights reserved. 6*7c478bd9Sstevel@tonic-gate */ 7*7c478bd9Sstevel@tonic-gate /* 8*7c478bd9Sstevel@tonic-gate * Copyright (c) 1995, 1996 9*7c478bd9Sstevel@tonic-gate * Margo Seltzer. All rights reserved. 10*7c478bd9Sstevel@tonic-gate */ 11*7c478bd9Sstevel@tonic-gate /* 12*7c478bd9Sstevel@tonic-gate * Copyright (c) 1995, 1996 13*7c478bd9Sstevel@tonic-gate * The President and Fellows of Harvard University. All rights reserved. 14*7c478bd9Sstevel@tonic-gate * 15*7c478bd9Sstevel@tonic-gate * This code is derived from software contributed to Berkeley by 16*7c478bd9Sstevel@tonic-gate * Margo Seltzer. 17*7c478bd9Sstevel@tonic-gate * 18*7c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 19*7c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions 20*7c478bd9Sstevel@tonic-gate * are met: 21*7c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 22*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 23*7c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 24*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 25*7c478bd9Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 26*7c478bd9Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 27*7c478bd9Sstevel@tonic-gate * must display the following acknowledgement: 28*7c478bd9Sstevel@tonic-gate * This product includes software developed by the University of 29*7c478bd9Sstevel@tonic-gate * California, Berkeley and its contributors. 30*7c478bd9Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors 31*7c478bd9Sstevel@tonic-gate * may be used to endorse or promote products derived from this software 32*7c478bd9Sstevel@tonic-gate * without specific prior written permission. 33*7c478bd9Sstevel@tonic-gate * 34*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 35*7c478bd9Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 36*7c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 37*7c478bd9Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 38*7c478bd9Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 39*7c478bd9Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 40*7c478bd9Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 41*7c478bd9Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 42*7c478bd9Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 43*7c478bd9Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 44*7c478bd9Sstevel@tonic-gate * SUCH DAMAGE. 45*7c478bd9Sstevel@tonic-gate */ 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate #include "config.h" 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate #ifndef lint 50*7c478bd9Sstevel@tonic-gate static const char sccsid[] = "@(#)hash_rec.c 10.22 (Sleepycat) 10/21/98"; 51*7c478bd9Sstevel@tonic-gate #endif /* not lint */ 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate #ifndef NO_SYSTEM_INCLUDES 54*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate #include <errno.h> 57*7c478bd9Sstevel@tonic-gate #include <string.h> 58*7c478bd9Sstevel@tonic-gate #endif 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate #include "db_int.h" 61*7c478bd9Sstevel@tonic-gate #include "shqueue.h" 62*7c478bd9Sstevel@tonic-gate #include "db_page.h" 63*7c478bd9Sstevel@tonic-gate #include "hash.h" 64*7c478bd9Sstevel@tonic-gate #include "btree.h" 65*7c478bd9Sstevel@tonic-gate #include "log.h" 66*7c478bd9Sstevel@tonic-gate #include "common_ext.h" 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate /* 69*7c478bd9Sstevel@tonic-gate * __ham_insdel_recover -- 70*7c478bd9Sstevel@tonic-gate * 71*7c478bd9Sstevel@tonic-gate * PUBLIC: int __ham_insdel_recover 72*7c478bd9Sstevel@tonic-gate * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); 73*7c478bd9Sstevel@tonic-gate */ 74*7c478bd9Sstevel@tonic-gate int 75*7c478bd9Sstevel@tonic-gate __ham_insdel_recover(logp, dbtp, lsnp, redo, info) 76*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 77*7c478bd9Sstevel@tonic-gate DBT *dbtp; 78*7c478bd9Sstevel@tonic-gate DB_LSN *lsnp; 79*7c478bd9Sstevel@tonic-gate int redo; 80*7c478bd9Sstevel@tonic-gate void *info; 81*7c478bd9Sstevel@tonic-gate { 82*7c478bd9Sstevel@tonic-gate __ham_insdel_args *argp; 83*7c478bd9Sstevel@tonic-gate DB *file_dbp; 84*7c478bd9Sstevel@tonic-gate DBC *dbc; 85*7c478bd9Sstevel@tonic-gate HASH_CURSOR *hcp; 86*7c478bd9Sstevel@tonic-gate DB_MPOOLFILE *mpf; 87*7c478bd9Sstevel@tonic-gate PAGE *pagep; 88*7c478bd9Sstevel@tonic-gate u_int32_t op; 89*7c478bd9Sstevel@tonic-gate int cmp_n, cmp_p, getmeta, ret; 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate getmeta = 0; 92*7c478bd9Sstevel@tonic-gate hcp = NULL; 93*7c478bd9Sstevel@tonic-gate REC_PRINT(__ham_insdel_print); 94*7c478bd9Sstevel@tonic-gate REC_INTRO(__ham_insdel_read); 95*7c478bd9Sstevel@tonic-gate hcp = (HASH_CURSOR *)dbc->internal; 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate ret = memp_fget(mpf, &argp->pgno, 0, &pagep); 98*7c478bd9Sstevel@tonic-gate if (ret != 0) 99*7c478bd9Sstevel@tonic-gate if (!redo) { 100*7c478bd9Sstevel@tonic-gate /* 101*7c478bd9Sstevel@tonic-gate * We are undoing and the page doesn't exist. That 102*7c478bd9Sstevel@tonic-gate * is equivalent to having a pagelsn of 0, so we 103*7c478bd9Sstevel@tonic-gate * would not have to undo anything. In this case, 104*7c478bd9Sstevel@tonic-gate * don't bother creating a page. 105*7c478bd9Sstevel@tonic-gate */ 106*7c478bd9Sstevel@tonic-gate goto done; 107*7c478bd9Sstevel@tonic-gate } else if ((ret = memp_fget(mpf, &argp->pgno, 108*7c478bd9Sstevel@tonic-gate DB_MPOOL_CREATE, &pagep)) != 0) 109*7c478bd9Sstevel@tonic-gate goto out; 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate GET_META(file_dbp, hcp, ret); 113*7c478bd9Sstevel@tonic-gate if (ret != 0) 114*7c478bd9Sstevel@tonic-gate goto out; 115*7c478bd9Sstevel@tonic-gate getmeta = 1; 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &LSN(pagep)); 118*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); 119*7c478bd9Sstevel@tonic-gate /* 120*7c478bd9Sstevel@tonic-gate * Two possible things going on: 121*7c478bd9Sstevel@tonic-gate * redo a delete/undo a put: delete the item from the page. 122*7c478bd9Sstevel@tonic-gate * redo a put/undo a delete: add the item to the page. 123*7c478bd9Sstevel@tonic-gate * If we are undoing a delete, then the information logged is the 124*7c478bd9Sstevel@tonic-gate * entire entry off the page, not just the data of a dbt. In 125*7c478bd9Sstevel@tonic-gate * this case, we want to copy it back onto the page verbatim. 126*7c478bd9Sstevel@tonic-gate * We do this by calling __putitem with the type H_OFFPAGE instead 127*7c478bd9Sstevel@tonic-gate * of H_KEYDATA. 128*7c478bd9Sstevel@tonic-gate */ 129*7c478bd9Sstevel@tonic-gate op = OPCODE_OF(argp->opcode); 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate if ((op == DELPAIR && cmp_n == 0 && !redo) || 132*7c478bd9Sstevel@tonic-gate (op == PUTPAIR && cmp_p == 0 && redo)) { 133*7c478bd9Sstevel@tonic-gate /* 134*7c478bd9Sstevel@tonic-gate * Need to redo a PUT or undo a delete. If we are undoing a 135*7c478bd9Sstevel@tonic-gate * delete, we've got to restore the item back to its original 136*7c478bd9Sstevel@tonic-gate * position. That's a royal pain in the butt (because we do 137*7c478bd9Sstevel@tonic-gate * not store item lengths on the page), but there's no choice. 138*7c478bd9Sstevel@tonic-gate */ 139*7c478bd9Sstevel@tonic-gate if (op != DELPAIR || 140*7c478bd9Sstevel@tonic-gate argp->ndx == (u_int32_t)H_NUMPAIRS(pagep)) { 141*7c478bd9Sstevel@tonic-gate __ham_putitem(pagep, &argp->key, 142*7c478bd9Sstevel@tonic-gate !redo || PAIR_ISKEYBIG(argp->opcode) ? 143*7c478bd9Sstevel@tonic-gate H_OFFPAGE : H_KEYDATA); 144*7c478bd9Sstevel@tonic-gate __ham_putitem(pagep, &argp->data, 145*7c478bd9Sstevel@tonic-gate !redo || PAIR_ISDATABIG(argp->opcode) ? 146*7c478bd9Sstevel@tonic-gate H_OFFPAGE : H_KEYDATA); 147*7c478bd9Sstevel@tonic-gate } else 148*7c478bd9Sstevel@tonic-gate (void) __ham_reputpair(pagep, hcp->hdr->pagesize, 149*7c478bd9Sstevel@tonic-gate argp->ndx, &argp->key, &argp->data); 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate LSN(pagep) = redo ? *lsnp : argp->pagelsn; 152*7c478bd9Sstevel@tonic-gate if ((ret = __ham_put_page(file_dbp, pagep, 1)) != 0) 153*7c478bd9Sstevel@tonic-gate goto out; 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate } else if ((op == DELPAIR && cmp_p == 0 && redo) 156*7c478bd9Sstevel@tonic-gate || (op == PUTPAIR && cmp_n == 0 && !redo)) { 157*7c478bd9Sstevel@tonic-gate /* Need to undo a put or redo a delete. */ 158*7c478bd9Sstevel@tonic-gate __ham_dpair(file_dbp, pagep, argp->ndx); 159*7c478bd9Sstevel@tonic-gate LSN(pagep) = redo ? *lsnp : argp->pagelsn; 160*7c478bd9Sstevel@tonic-gate if ((ret = __ham_put_page(file_dbp, (PAGE *)pagep, 1)) != 0) 161*7c478bd9Sstevel@tonic-gate goto out; 162*7c478bd9Sstevel@tonic-gate } else 163*7c478bd9Sstevel@tonic-gate if ((ret = __ham_put_page(file_dbp, (PAGE *)pagep, 0)) != 0) 164*7c478bd9Sstevel@tonic-gate goto out; 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate /* Return the previous LSN. */ 167*7c478bd9Sstevel@tonic-gate done: *lsnp = argp->prev_lsn; 168*7c478bd9Sstevel@tonic-gate ret = 0; 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate out: if (getmeta) 171*7c478bd9Sstevel@tonic-gate RELEASE_META(file_dbp, hcp); 172*7c478bd9Sstevel@tonic-gate REC_CLOSE; 173*7c478bd9Sstevel@tonic-gate } 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate /* 176*7c478bd9Sstevel@tonic-gate * __ham_newpage_recover -- 177*7c478bd9Sstevel@tonic-gate * This log message is used when we add/remove overflow pages. This 178*7c478bd9Sstevel@tonic-gate * message takes care of the pointer chains, not the data on the pages. 179*7c478bd9Sstevel@tonic-gate * 180*7c478bd9Sstevel@tonic-gate * PUBLIC: int __ham_newpage_recover 181*7c478bd9Sstevel@tonic-gate * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); 182*7c478bd9Sstevel@tonic-gate */ 183*7c478bd9Sstevel@tonic-gate int 184*7c478bd9Sstevel@tonic-gate __ham_newpage_recover(logp, dbtp, lsnp, redo, info) 185*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 186*7c478bd9Sstevel@tonic-gate DBT *dbtp; 187*7c478bd9Sstevel@tonic-gate DB_LSN *lsnp; 188*7c478bd9Sstevel@tonic-gate int redo; 189*7c478bd9Sstevel@tonic-gate void *info; 190*7c478bd9Sstevel@tonic-gate { 191*7c478bd9Sstevel@tonic-gate __ham_newpage_args *argp; 192*7c478bd9Sstevel@tonic-gate DB *file_dbp; 193*7c478bd9Sstevel@tonic-gate DBC *dbc; 194*7c478bd9Sstevel@tonic-gate HASH_CURSOR *hcp; 195*7c478bd9Sstevel@tonic-gate DB_MPOOLFILE *mpf; 196*7c478bd9Sstevel@tonic-gate PAGE *pagep; 197*7c478bd9Sstevel@tonic-gate int cmp_n, cmp_p, change, getmeta, ret; 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate getmeta = 0; 200*7c478bd9Sstevel@tonic-gate hcp = NULL; 201*7c478bd9Sstevel@tonic-gate REC_PRINT(__ham_newpage_print); 202*7c478bd9Sstevel@tonic-gate REC_INTRO(__ham_newpage_read); 203*7c478bd9Sstevel@tonic-gate hcp = (HASH_CURSOR *)dbc->internal; 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate ret = memp_fget(mpf, &argp->new_pgno, 0, &pagep); 206*7c478bd9Sstevel@tonic-gate if (ret != 0) 207*7c478bd9Sstevel@tonic-gate if (!redo) { 208*7c478bd9Sstevel@tonic-gate /* 209*7c478bd9Sstevel@tonic-gate * We are undoing and the page doesn't exist. That 210*7c478bd9Sstevel@tonic-gate * is equivalent to having a pagelsn of 0, so we 211*7c478bd9Sstevel@tonic-gate * would not have to undo anything. In this case, 212*7c478bd9Sstevel@tonic-gate * don't bother creating a page. 213*7c478bd9Sstevel@tonic-gate */ 214*7c478bd9Sstevel@tonic-gate ret = 0; 215*7c478bd9Sstevel@tonic-gate goto ppage; 216*7c478bd9Sstevel@tonic-gate } else if ((ret = memp_fget(mpf, &argp->new_pgno, 217*7c478bd9Sstevel@tonic-gate DB_MPOOL_CREATE, &pagep)) != 0) 218*7c478bd9Sstevel@tonic-gate goto out; 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); 221*7c478bd9Sstevel@tonic-gate if (ret != 0) 222*7c478bd9Sstevel@tonic-gate goto out; 223*7c478bd9Sstevel@tonic-gate getmeta = 1; 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate /* 226*7c478bd9Sstevel@tonic-gate * There are potentially three pages we need to check: the one 227*7c478bd9Sstevel@tonic-gate * that we created/deleted, the one before it and the one after 228*7c478bd9Sstevel@tonic-gate * it. 229*7c478bd9Sstevel@tonic-gate */ 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &LSN(pagep)); 232*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); 233*7c478bd9Sstevel@tonic-gate change = 0; 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate if ((cmp_p == 0 && redo && argp->opcode == PUTOVFL) || 236*7c478bd9Sstevel@tonic-gate (cmp_n == 0 && !redo && argp->opcode == DELOVFL)) { 237*7c478bd9Sstevel@tonic-gate /* Redo a create new page or undo a delete new page. */ 238*7c478bd9Sstevel@tonic-gate P_INIT(pagep, file_dbp->pgsize, argp->new_pgno, 239*7c478bd9Sstevel@tonic-gate argp->prev_pgno, argp->next_pgno, 0, P_HASH); 240*7c478bd9Sstevel@tonic-gate change = 1; 241*7c478bd9Sstevel@tonic-gate } else if ((cmp_p == 0 && redo && argp->opcode == DELOVFL) || 242*7c478bd9Sstevel@tonic-gate (cmp_n == 0 && !redo && argp->opcode == PUTOVFL)) { 243*7c478bd9Sstevel@tonic-gate /* 244*7c478bd9Sstevel@tonic-gate * Redo a delete or undo a create new page. All we 245*7c478bd9Sstevel@tonic-gate * really need to do is change the LSN. 246*7c478bd9Sstevel@tonic-gate */ 247*7c478bd9Sstevel@tonic-gate change = 1; 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate if (!change) { 251*7c478bd9Sstevel@tonic-gate if ((ret = __ham_put_page(file_dbp, (PAGE *)pagep, 0)) != 0) 252*7c478bd9Sstevel@tonic-gate goto out; 253*7c478bd9Sstevel@tonic-gate } else { 254*7c478bd9Sstevel@tonic-gate LSN(pagep) = redo ? *lsnp : argp->pagelsn; 255*7c478bd9Sstevel@tonic-gate if ((ret = __ham_put_page(file_dbp, (PAGE *)pagep, 1)) != 0) 256*7c478bd9Sstevel@tonic-gate goto out; 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate /* Now do the prev page. */ 260*7c478bd9Sstevel@tonic-gate ppage: if (argp->prev_pgno != PGNO_INVALID) { 261*7c478bd9Sstevel@tonic-gate ret = memp_fget(mpf, &argp->prev_pgno, 0, &pagep); 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate if (ret != 0) 264*7c478bd9Sstevel@tonic-gate if (!redo) { 265*7c478bd9Sstevel@tonic-gate /* 266*7c478bd9Sstevel@tonic-gate * We are undoing and the page doesn't exist. 267*7c478bd9Sstevel@tonic-gate * That is equivalent to having a pagelsn of 0, 268*7c478bd9Sstevel@tonic-gate * so we would not have to undo anything. In 269*7c478bd9Sstevel@tonic-gate * this case, don't bother creating a page. 270*7c478bd9Sstevel@tonic-gate */ 271*7c478bd9Sstevel@tonic-gate ret = 0; 272*7c478bd9Sstevel@tonic-gate goto npage; 273*7c478bd9Sstevel@tonic-gate } else if ((ret = 274*7c478bd9Sstevel@tonic-gate memp_fget(mpf, &argp->prev_pgno, 275*7c478bd9Sstevel@tonic-gate DB_MPOOL_CREATE, &pagep)) != 0) 276*7c478bd9Sstevel@tonic-gate goto out; 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &LSN(pagep)); 279*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&LSN(pagep), &argp->prevlsn); 280*7c478bd9Sstevel@tonic-gate change = 0; 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate if ((cmp_p == 0 && redo && argp->opcode == PUTOVFL) || 283*7c478bd9Sstevel@tonic-gate (cmp_n == 0 && !redo && argp->opcode == DELOVFL)) { 284*7c478bd9Sstevel@tonic-gate /* Redo a create new page or undo a delete new page. */ 285*7c478bd9Sstevel@tonic-gate pagep->next_pgno = argp->new_pgno; 286*7c478bd9Sstevel@tonic-gate change = 1; 287*7c478bd9Sstevel@tonic-gate } else if ((cmp_p == 0 && redo && argp->opcode == DELOVFL) || 288*7c478bd9Sstevel@tonic-gate (cmp_n == 0 && !redo && argp->opcode == PUTOVFL)) { 289*7c478bd9Sstevel@tonic-gate /* Redo a delete or undo a create new page. */ 290*7c478bd9Sstevel@tonic-gate pagep->next_pgno = argp->next_pgno; 291*7c478bd9Sstevel@tonic-gate change = 1; 292*7c478bd9Sstevel@tonic-gate } 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate if (!change) { 295*7c478bd9Sstevel@tonic-gate if ((ret = 296*7c478bd9Sstevel@tonic-gate __ham_put_page(file_dbp, (PAGE *)pagep, 0)) != 0) 297*7c478bd9Sstevel@tonic-gate goto out; 298*7c478bd9Sstevel@tonic-gate } else { 299*7c478bd9Sstevel@tonic-gate LSN(pagep) = redo ? *lsnp : argp->prevlsn; 300*7c478bd9Sstevel@tonic-gate if ((ret = 301*7c478bd9Sstevel@tonic-gate __ham_put_page(file_dbp, (PAGE *)pagep, 1)) != 0) 302*7c478bd9Sstevel@tonic-gate goto out; 303*7c478bd9Sstevel@tonic-gate } 304*7c478bd9Sstevel@tonic-gate } 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate /* Now time to do the next page */ 307*7c478bd9Sstevel@tonic-gate npage: if (argp->next_pgno != PGNO_INVALID) { 308*7c478bd9Sstevel@tonic-gate ret = memp_fget(mpf, &argp->next_pgno, 0, &pagep); 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate if (ret != 0) 311*7c478bd9Sstevel@tonic-gate if (!redo) { 312*7c478bd9Sstevel@tonic-gate /* 313*7c478bd9Sstevel@tonic-gate * We are undoing and the page doesn't exist. 314*7c478bd9Sstevel@tonic-gate * That is equivalent to having a pagelsn of 0, 315*7c478bd9Sstevel@tonic-gate * so we would not have to undo anything. In 316*7c478bd9Sstevel@tonic-gate * this case, don't bother creating a page. 317*7c478bd9Sstevel@tonic-gate */ 318*7c478bd9Sstevel@tonic-gate goto done; 319*7c478bd9Sstevel@tonic-gate } else if ((ret = 320*7c478bd9Sstevel@tonic-gate memp_fget(mpf, &argp->next_pgno, 321*7c478bd9Sstevel@tonic-gate DB_MPOOL_CREATE, &pagep)) != 0) 322*7c478bd9Sstevel@tonic-gate goto out; 323*7c478bd9Sstevel@tonic-gate 324*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &LSN(pagep)); 325*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&LSN(pagep), &argp->nextlsn); 326*7c478bd9Sstevel@tonic-gate change = 0; 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate if ((cmp_p == 0 && redo && argp->opcode == PUTOVFL) || 329*7c478bd9Sstevel@tonic-gate (cmp_n == 0 && !redo && argp->opcode == DELOVFL)) { 330*7c478bd9Sstevel@tonic-gate /* Redo a create new page or undo a delete new page. */ 331*7c478bd9Sstevel@tonic-gate pagep->prev_pgno = argp->new_pgno; 332*7c478bd9Sstevel@tonic-gate change = 1; 333*7c478bd9Sstevel@tonic-gate } else if ((cmp_p == 0 && redo && argp->opcode == DELOVFL) || 334*7c478bd9Sstevel@tonic-gate (cmp_n == 0 && !redo && argp->opcode == PUTOVFL)) { 335*7c478bd9Sstevel@tonic-gate /* Redo a delete or undo a create new page. */ 336*7c478bd9Sstevel@tonic-gate pagep->prev_pgno = argp->prev_pgno; 337*7c478bd9Sstevel@tonic-gate change = 1; 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate if (!change) { 341*7c478bd9Sstevel@tonic-gate if ((ret = 342*7c478bd9Sstevel@tonic-gate __ham_put_page(file_dbp, (PAGE *)pagep, 0)) != 0) 343*7c478bd9Sstevel@tonic-gate goto out; 344*7c478bd9Sstevel@tonic-gate } else { 345*7c478bd9Sstevel@tonic-gate LSN(pagep) = redo ? *lsnp : argp->nextlsn; 346*7c478bd9Sstevel@tonic-gate if ((ret = 347*7c478bd9Sstevel@tonic-gate __ham_put_page(file_dbp, (PAGE *)pagep, 1)) != 0) 348*7c478bd9Sstevel@tonic-gate goto out; 349*7c478bd9Sstevel@tonic-gate } 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate done: *lsnp = argp->prev_lsn; 352*7c478bd9Sstevel@tonic-gate ret = 0; 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate out: if (getmeta) 355*7c478bd9Sstevel@tonic-gate RELEASE_META(file_dbp, hcp); 356*7c478bd9Sstevel@tonic-gate REC_CLOSE; 357*7c478bd9Sstevel@tonic-gate } 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate /* 361*7c478bd9Sstevel@tonic-gate * __ham_replace_recover -- 362*7c478bd9Sstevel@tonic-gate * This log message refers to partial puts that are local to a single 363*7c478bd9Sstevel@tonic-gate * page. You can think of them as special cases of the more general 364*7c478bd9Sstevel@tonic-gate * insdel log message. 365*7c478bd9Sstevel@tonic-gate * 366*7c478bd9Sstevel@tonic-gate * PUBLIC: int __ham_replace_recover 367*7c478bd9Sstevel@tonic-gate * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); 368*7c478bd9Sstevel@tonic-gate */ 369*7c478bd9Sstevel@tonic-gate int 370*7c478bd9Sstevel@tonic-gate __ham_replace_recover(logp, dbtp, lsnp, redo, info) 371*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 372*7c478bd9Sstevel@tonic-gate DBT *dbtp; 373*7c478bd9Sstevel@tonic-gate DB_LSN *lsnp; 374*7c478bd9Sstevel@tonic-gate int redo; 375*7c478bd9Sstevel@tonic-gate void *info; 376*7c478bd9Sstevel@tonic-gate { 377*7c478bd9Sstevel@tonic-gate __ham_replace_args *argp; 378*7c478bd9Sstevel@tonic-gate DB *file_dbp; 379*7c478bd9Sstevel@tonic-gate DBC *dbc; 380*7c478bd9Sstevel@tonic-gate HASH_CURSOR *hcp; 381*7c478bd9Sstevel@tonic-gate DB_MPOOLFILE *mpf; 382*7c478bd9Sstevel@tonic-gate DBT dbt; 383*7c478bd9Sstevel@tonic-gate PAGE *pagep; 384*7c478bd9Sstevel@tonic-gate int32_t grow; 385*7c478bd9Sstevel@tonic-gate int change, cmp_n, cmp_p, getmeta, ret; 386*7c478bd9Sstevel@tonic-gate u_int8_t *hk; 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate getmeta = 0; 389*7c478bd9Sstevel@tonic-gate hcp = NULL; 390*7c478bd9Sstevel@tonic-gate REC_PRINT(__ham_replace_print); 391*7c478bd9Sstevel@tonic-gate REC_INTRO(__ham_replace_read); 392*7c478bd9Sstevel@tonic-gate hcp = (HASH_CURSOR *)dbc->internal; 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate ret = memp_fget(mpf, &argp->pgno, 0, &pagep); 395*7c478bd9Sstevel@tonic-gate if (ret != 0) 396*7c478bd9Sstevel@tonic-gate if (!redo) { 397*7c478bd9Sstevel@tonic-gate /* 398*7c478bd9Sstevel@tonic-gate * We are undoing and the page doesn't exist. That 399*7c478bd9Sstevel@tonic-gate * is equivalent to having a pagelsn of 0, so we 400*7c478bd9Sstevel@tonic-gate * would not have to undo anything. In this case, 401*7c478bd9Sstevel@tonic-gate * don't bother creating a page. 402*7c478bd9Sstevel@tonic-gate */ 403*7c478bd9Sstevel@tonic-gate goto done; 404*7c478bd9Sstevel@tonic-gate } else if ((ret = memp_fget(mpf, &argp->pgno, 405*7c478bd9Sstevel@tonic-gate DB_MPOOL_CREATE, &pagep)) != 0) 406*7c478bd9Sstevel@tonic-gate goto out; 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); 409*7c478bd9Sstevel@tonic-gate if (ret != 0) 410*7c478bd9Sstevel@tonic-gate goto out; 411*7c478bd9Sstevel@tonic-gate getmeta = 1; 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &LSN(pagep)); 414*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate if (cmp_p == 0 && redo) { 417*7c478bd9Sstevel@tonic-gate change = 1; 418*7c478bd9Sstevel@tonic-gate /* Reapply the change as specified. */ 419*7c478bd9Sstevel@tonic-gate dbt.data = argp->newitem.data; 420*7c478bd9Sstevel@tonic-gate dbt.size = argp->newitem.size; 421*7c478bd9Sstevel@tonic-gate grow = argp->newitem.size - argp->olditem.size; 422*7c478bd9Sstevel@tonic-gate LSN(pagep) = *lsnp; 423*7c478bd9Sstevel@tonic-gate } else if (cmp_n == 0 && !redo) { 424*7c478bd9Sstevel@tonic-gate change = 1; 425*7c478bd9Sstevel@tonic-gate /* Undo the already applied change. */ 426*7c478bd9Sstevel@tonic-gate dbt.data = argp->olditem.data; 427*7c478bd9Sstevel@tonic-gate dbt.size = argp->olditem.size; 428*7c478bd9Sstevel@tonic-gate grow = argp->olditem.size - argp->newitem.size; 429*7c478bd9Sstevel@tonic-gate LSN(pagep) = argp->pagelsn; 430*7c478bd9Sstevel@tonic-gate } else { 431*7c478bd9Sstevel@tonic-gate change = 0; 432*7c478bd9Sstevel@tonic-gate grow = 0; 433*7c478bd9Sstevel@tonic-gate } 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate if (change) { 436*7c478bd9Sstevel@tonic-gate __ham_onpage_replace(pagep, 437*7c478bd9Sstevel@tonic-gate file_dbp->pgsize, argp->ndx, argp->off, grow, &dbt); 438*7c478bd9Sstevel@tonic-gate if (argp->makedup) { 439*7c478bd9Sstevel@tonic-gate hk = P_ENTRY(pagep, argp->ndx); 440*7c478bd9Sstevel@tonic-gate if (redo) 441*7c478bd9Sstevel@tonic-gate HPAGE_PTYPE(hk) = H_DUPLICATE; 442*7c478bd9Sstevel@tonic-gate else 443*7c478bd9Sstevel@tonic-gate HPAGE_PTYPE(hk) = H_KEYDATA; 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate } 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate if ((ret = __ham_put_page(file_dbp, pagep, change)) != 0) 448*7c478bd9Sstevel@tonic-gate goto out; 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate done: *lsnp = argp->prev_lsn; 451*7c478bd9Sstevel@tonic-gate ret = 0; 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate out: if (getmeta) 454*7c478bd9Sstevel@tonic-gate RELEASE_META(file_dbp, hcp); 455*7c478bd9Sstevel@tonic-gate REC_CLOSE; 456*7c478bd9Sstevel@tonic-gate } 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate /* 459*7c478bd9Sstevel@tonic-gate * __ham_newpgno_recover -- 460*7c478bd9Sstevel@tonic-gate * This log message is used when allocating or deleting an overflow 461*7c478bd9Sstevel@tonic-gate * page. It takes care of modifying the meta data. 462*7c478bd9Sstevel@tonic-gate * 463*7c478bd9Sstevel@tonic-gate * PUBLIC: int __ham_newpgno_recover 464*7c478bd9Sstevel@tonic-gate * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); 465*7c478bd9Sstevel@tonic-gate */ 466*7c478bd9Sstevel@tonic-gate int 467*7c478bd9Sstevel@tonic-gate __ham_newpgno_recover(logp, dbtp, lsnp, redo, info) 468*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 469*7c478bd9Sstevel@tonic-gate DBT *dbtp; 470*7c478bd9Sstevel@tonic-gate DB_LSN *lsnp; 471*7c478bd9Sstevel@tonic-gate int redo; 472*7c478bd9Sstevel@tonic-gate void *info; 473*7c478bd9Sstevel@tonic-gate { 474*7c478bd9Sstevel@tonic-gate __ham_newpgno_args *argp; 475*7c478bd9Sstevel@tonic-gate DB *file_dbp; 476*7c478bd9Sstevel@tonic-gate DBC *dbc; 477*7c478bd9Sstevel@tonic-gate HASH_CURSOR *hcp; 478*7c478bd9Sstevel@tonic-gate DB_MPOOLFILE *mpf; 479*7c478bd9Sstevel@tonic-gate PAGE *pagep; 480*7c478bd9Sstevel@tonic-gate int change, cmp_n, cmp_p, getmeta, ret; 481*7c478bd9Sstevel@tonic-gate 482*7c478bd9Sstevel@tonic-gate getmeta = 0; 483*7c478bd9Sstevel@tonic-gate hcp = NULL; 484*7c478bd9Sstevel@tonic-gate REC_PRINT(__ham_newpgno_print); 485*7c478bd9Sstevel@tonic-gate REC_INTRO(__ham_newpgno_read); 486*7c478bd9Sstevel@tonic-gate hcp = (HASH_CURSOR *)dbc->internal; 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); 489*7c478bd9Sstevel@tonic-gate if (ret != 0) 490*7c478bd9Sstevel@tonic-gate goto out; 491*7c478bd9Sstevel@tonic-gate getmeta = 1; 492*7c478bd9Sstevel@tonic-gate 493*7c478bd9Sstevel@tonic-gate /* 494*7c478bd9Sstevel@tonic-gate * There are two phases to the recovery here. First we need 495*7c478bd9Sstevel@tonic-gate * to update the meta data; then we need to update the page. 496*7c478bd9Sstevel@tonic-gate * We'll do the meta-data first. 497*7c478bd9Sstevel@tonic-gate */ 498*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &hcp->hdr->lsn); 499*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&hcp->hdr->lsn, &argp->metalsn); 500*7c478bd9Sstevel@tonic-gate 501*7c478bd9Sstevel@tonic-gate change = 0; 502*7c478bd9Sstevel@tonic-gate if ((cmp_p == 0 && redo && argp->opcode == ALLOCPGNO) || 503*7c478bd9Sstevel@tonic-gate (cmp_n == 0 && !redo && argp->opcode == DELPGNO)) { 504*7c478bd9Sstevel@tonic-gate /* Need to redo an allocation or undo a deletion. */ 505*7c478bd9Sstevel@tonic-gate hcp->hdr->last_freed = argp->free_pgno; 506*7c478bd9Sstevel@tonic-gate if (redo && argp->old_pgno != 0) /* Must be ALLOCPGNO */ 507*7c478bd9Sstevel@tonic-gate hcp->hdr->spares[hcp->hdr->ovfl_point]++; 508*7c478bd9Sstevel@tonic-gate change = 1; 509*7c478bd9Sstevel@tonic-gate } else if (cmp_p == 0 && redo && argp->opcode == DELPGNO) { 510*7c478bd9Sstevel@tonic-gate /* Need to redo a deletion */ 511*7c478bd9Sstevel@tonic-gate hcp->hdr->last_freed = argp->pgno; 512*7c478bd9Sstevel@tonic-gate change = 1; 513*7c478bd9Sstevel@tonic-gate } else if (cmp_n == 0 && !redo && argp->opcode == ALLOCPGNO) { 514*7c478bd9Sstevel@tonic-gate /* undo an allocation. */ 515*7c478bd9Sstevel@tonic-gate if (argp->old_pgno == 0) 516*7c478bd9Sstevel@tonic-gate hcp->hdr->last_freed = argp->pgno; 517*7c478bd9Sstevel@tonic-gate else { 518*7c478bd9Sstevel@tonic-gate hcp->hdr->spares[hcp->hdr->ovfl_point]--; 519*7c478bd9Sstevel@tonic-gate hcp->hdr->last_freed = 0; 520*7c478bd9Sstevel@tonic-gate } 521*7c478bd9Sstevel@tonic-gate change = 1; 522*7c478bd9Sstevel@tonic-gate } 523*7c478bd9Sstevel@tonic-gate if (change) { 524*7c478bd9Sstevel@tonic-gate hcp->hdr->lsn = redo ? *lsnp : argp->metalsn; 525*7c478bd9Sstevel@tonic-gate F_SET(hcp, H_DIRTY); 526*7c478bd9Sstevel@tonic-gate } 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate /* Now check the newly allocated/freed page. */ 530*7c478bd9Sstevel@tonic-gate ret = memp_fget(mpf, &argp->pgno, 0, &pagep); 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate if (ret != 0) 533*7c478bd9Sstevel@tonic-gate if (!redo) { 534*7c478bd9Sstevel@tonic-gate /* 535*7c478bd9Sstevel@tonic-gate * We are undoing and the page doesn't exist. That 536*7c478bd9Sstevel@tonic-gate * is equivalent to having a pagelsn of 0, so we 537*7c478bd9Sstevel@tonic-gate * would not have to undo anything. In this case, 538*7c478bd9Sstevel@tonic-gate * don't bother creating a page. 539*7c478bd9Sstevel@tonic-gate */ 540*7c478bd9Sstevel@tonic-gate goto done; 541*7c478bd9Sstevel@tonic-gate } else if ((ret = memp_fget(mpf, &argp->pgno, 542*7c478bd9Sstevel@tonic-gate DB_MPOOL_CREATE, &pagep)) != 0) 543*7c478bd9Sstevel@tonic-gate goto out; 544*7c478bd9Sstevel@tonic-gate 545*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &LSN(pagep)); 546*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate change = 0; 549*7c478bd9Sstevel@tonic-gate if (cmp_p == 0 && redo && argp->opcode == ALLOCPGNO) { 550*7c478bd9Sstevel@tonic-gate /* Need to redo an allocation. */ 551*7c478bd9Sstevel@tonic-gate P_INIT(pagep, file_dbp->pgsize, argp->pgno, PGNO_INVALID, 552*7c478bd9Sstevel@tonic-gate PGNO_INVALID, 0, argp->new_type); 553*7c478bd9Sstevel@tonic-gate change = 1; 554*7c478bd9Sstevel@tonic-gate } else if (cmp_n == 0 && !redo && argp->opcode == DELPGNO) { 555*7c478bd9Sstevel@tonic-gate /* Undoing a delete. */ 556*7c478bd9Sstevel@tonic-gate P_INIT(pagep, file_dbp->pgsize, argp->pgno, PGNO_INVALID, 557*7c478bd9Sstevel@tonic-gate argp->old_pgno, 0, argp->old_type); 558*7c478bd9Sstevel@tonic-gate change = 1; 559*7c478bd9Sstevel@tonic-gate } else if ((cmp_p == 0 && redo && argp->opcode == DELPGNO) || 560*7c478bd9Sstevel@tonic-gate (cmp_n == 0 && !redo && argp->opcode == ALLOCPGNO)) { 561*7c478bd9Sstevel@tonic-gate /* Need to redo a deletion or undo an allocation. */ 562*7c478bd9Sstevel@tonic-gate NEXT_PGNO(pagep) = argp->free_pgno; 563*7c478bd9Sstevel@tonic-gate TYPE(pagep) = P_INVALID; 564*7c478bd9Sstevel@tonic-gate change = 1; 565*7c478bd9Sstevel@tonic-gate } 566*7c478bd9Sstevel@tonic-gate if (change) 567*7c478bd9Sstevel@tonic-gate LSN(pagep) = redo ? *lsnp : argp->pagelsn; 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate if ((ret = __ham_put_page(file_dbp, pagep, change)) != 0) 570*7c478bd9Sstevel@tonic-gate goto out; 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate done: *lsnp = argp->prev_lsn; 573*7c478bd9Sstevel@tonic-gate ret = 0; 574*7c478bd9Sstevel@tonic-gate 575*7c478bd9Sstevel@tonic-gate out: if (getmeta) 576*7c478bd9Sstevel@tonic-gate RELEASE_META(file_dbp, hcp); 577*7c478bd9Sstevel@tonic-gate REC_CLOSE; 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate } 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate /* 582*7c478bd9Sstevel@tonic-gate * __ham_splitmeta_recover -- 583*7c478bd9Sstevel@tonic-gate * This is the meta-data part of the split. Records the new and old 584*7c478bd9Sstevel@tonic-gate * bucket numbers and the new/old mask information. 585*7c478bd9Sstevel@tonic-gate * 586*7c478bd9Sstevel@tonic-gate * PUBLIC: int __ham_splitmeta_recover 587*7c478bd9Sstevel@tonic-gate * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); 588*7c478bd9Sstevel@tonic-gate */ 589*7c478bd9Sstevel@tonic-gate int 590*7c478bd9Sstevel@tonic-gate __ham_splitmeta_recover(logp, dbtp, lsnp, redo, info) 591*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 592*7c478bd9Sstevel@tonic-gate DBT *dbtp; 593*7c478bd9Sstevel@tonic-gate DB_LSN *lsnp; 594*7c478bd9Sstevel@tonic-gate int redo; 595*7c478bd9Sstevel@tonic-gate void *info; 596*7c478bd9Sstevel@tonic-gate { 597*7c478bd9Sstevel@tonic-gate __ham_splitmeta_args *argp; 598*7c478bd9Sstevel@tonic-gate DB *file_dbp; 599*7c478bd9Sstevel@tonic-gate DBC *dbc; 600*7c478bd9Sstevel@tonic-gate HASH_CURSOR *hcp; 601*7c478bd9Sstevel@tonic-gate DB_MPOOLFILE *mpf; 602*7c478bd9Sstevel@tonic-gate int change, cmp_n, cmp_p, getmeta, ret; 603*7c478bd9Sstevel@tonic-gate u_int32_t pow; 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate getmeta = 0; 606*7c478bd9Sstevel@tonic-gate hcp = NULL; 607*7c478bd9Sstevel@tonic-gate REC_PRINT(__ham_splitmeta_print); 608*7c478bd9Sstevel@tonic-gate REC_INTRO(__ham_splitmeta_read); 609*7c478bd9Sstevel@tonic-gate hcp = (HASH_CURSOR *)dbc->internal; 610*7c478bd9Sstevel@tonic-gate 611*7c478bd9Sstevel@tonic-gate GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); 612*7c478bd9Sstevel@tonic-gate if (ret != 0) 613*7c478bd9Sstevel@tonic-gate goto out; 614*7c478bd9Sstevel@tonic-gate getmeta = 1; 615*7c478bd9Sstevel@tonic-gate 616*7c478bd9Sstevel@tonic-gate /* 617*7c478bd9Sstevel@tonic-gate * There are two phases to the recovery here. First we need 618*7c478bd9Sstevel@tonic-gate * to update the meta data; then we need to update the page. 619*7c478bd9Sstevel@tonic-gate * We'll do the meta-data first. 620*7c478bd9Sstevel@tonic-gate */ 621*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &hcp->hdr->lsn); 622*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&hcp->hdr->lsn, &argp->metalsn); 623*7c478bd9Sstevel@tonic-gate 624*7c478bd9Sstevel@tonic-gate change = 0; 625*7c478bd9Sstevel@tonic-gate if (cmp_p == 0 && redo) { 626*7c478bd9Sstevel@tonic-gate /* Need to redo the split information. */ 627*7c478bd9Sstevel@tonic-gate hcp->hdr->max_bucket = argp->bucket + 1; 628*7c478bd9Sstevel@tonic-gate pow = __db_log2(hcp->hdr->max_bucket + 1); 629*7c478bd9Sstevel@tonic-gate if (pow > hcp->hdr->ovfl_point) { 630*7c478bd9Sstevel@tonic-gate hcp->hdr->spares[pow] = 631*7c478bd9Sstevel@tonic-gate hcp->hdr->spares[hcp->hdr->ovfl_point]; 632*7c478bd9Sstevel@tonic-gate hcp->hdr->ovfl_point = pow; 633*7c478bd9Sstevel@tonic-gate } 634*7c478bd9Sstevel@tonic-gate if (hcp->hdr->max_bucket > hcp->hdr->high_mask) { 635*7c478bd9Sstevel@tonic-gate hcp->hdr->low_mask = hcp->hdr->high_mask; 636*7c478bd9Sstevel@tonic-gate hcp->hdr->high_mask = 637*7c478bd9Sstevel@tonic-gate hcp->hdr->max_bucket | hcp->hdr->low_mask; 638*7c478bd9Sstevel@tonic-gate } 639*7c478bd9Sstevel@tonic-gate change = 1; 640*7c478bd9Sstevel@tonic-gate } else if (cmp_n == 0 && !redo) { 641*7c478bd9Sstevel@tonic-gate /* Need to undo the split information. */ 642*7c478bd9Sstevel@tonic-gate hcp->hdr->max_bucket = argp->bucket; 643*7c478bd9Sstevel@tonic-gate hcp->hdr->ovfl_point = argp->ovflpoint; 644*7c478bd9Sstevel@tonic-gate hcp->hdr->spares[hcp->hdr->ovfl_point] = argp->spares; 645*7c478bd9Sstevel@tonic-gate pow = 1 << __db_log2(hcp->hdr->max_bucket + 1); 646*7c478bd9Sstevel@tonic-gate hcp->hdr->high_mask = pow - 1; 647*7c478bd9Sstevel@tonic-gate hcp->hdr->low_mask = (pow >> 1) - 1; 648*7c478bd9Sstevel@tonic-gate change = 1; 649*7c478bd9Sstevel@tonic-gate } 650*7c478bd9Sstevel@tonic-gate if (change) { 651*7c478bd9Sstevel@tonic-gate hcp->hdr->lsn = redo ? *lsnp : argp->metalsn; 652*7c478bd9Sstevel@tonic-gate F_SET(hcp, H_DIRTY); 653*7c478bd9Sstevel@tonic-gate } 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate done: *lsnp = argp->prev_lsn; 656*7c478bd9Sstevel@tonic-gate ret = 0; 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate out: if (getmeta) 659*7c478bd9Sstevel@tonic-gate RELEASE_META(file_dbp, hcp); 660*7c478bd9Sstevel@tonic-gate REC_CLOSE; 661*7c478bd9Sstevel@tonic-gate } 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate /* 664*7c478bd9Sstevel@tonic-gate * __ham_splitdata_recover -- 665*7c478bd9Sstevel@tonic-gate * 666*7c478bd9Sstevel@tonic-gate * PUBLIC: int __ham_splitdata_recover 667*7c478bd9Sstevel@tonic-gate * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); 668*7c478bd9Sstevel@tonic-gate */ 669*7c478bd9Sstevel@tonic-gate int 670*7c478bd9Sstevel@tonic-gate __ham_splitdata_recover(logp, dbtp, lsnp, redo, info) 671*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 672*7c478bd9Sstevel@tonic-gate DBT *dbtp; 673*7c478bd9Sstevel@tonic-gate DB_LSN *lsnp; 674*7c478bd9Sstevel@tonic-gate int redo; 675*7c478bd9Sstevel@tonic-gate void *info; 676*7c478bd9Sstevel@tonic-gate { 677*7c478bd9Sstevel@tonic-gate __ham_splitdata_args *argp; 678*7c478bd9Sstevel@tonic-gate DB *file_dbp; 679*7c478bd9Sstevel@tonic-gate DBC *dbc; 680*7c478bd9Sstevel@tonic-gate HASH_CURSOR *hcp; 681*7c478bd9Sstevel@tonic-gate DB_MPOOLFILE *mpf; 682*7c478bd9Sstevel@tonic-gate PAGE *pagep; 683*7c478bd9Sstevel@tonic-gate int change, cmp_n, cmp_p, getmeta, ret; 684*7c478bd9Sstevel@tonic-gate 685*7c478bd9Sstevel@tonic-gate getmeta = 0; 686*7c478bd9Sstevel@tonic-gate hcp = NULL; 687*7c478bd9Sstevel@tonic-gate REC_PRINT(__ham_splitdata_print); 688*7c478bd9Sstevel@tonic-gate REC_INTRO(__ham_splitdata_read); 689*7c478bd9Sstevel@tonic-gate hcp = (HASH_CURSOR *)dbc->internal; 690*7c478bd9Sstevel@tonic-gate 691*7c478bd9Sstevel@tonic-gate ret = memp_fget(mpf, &argp->pgno, 0, &pagep); 692*7c478bd9Sstevel@tonic-gate if (ret != 0) 693*7c478bd9Sstevel@tonic-gate if (!redo) { 694*7c478bd9Sstevel@tonic-gate /* 695*7c478bd9Sstevel@tonic-gate * We are undoing and the page doesn't exist. That 696*7c478bd9Sstevel@tonic-gate * is equivalent to having a pagelsn of 0, so we 697*7c478bd9Sstevel@tonic-gate * would not have to undo anything. In this case, 698*7c478bd9Sstevel@tonic-gate * don't bother creating a page. 699*7c478bd9Sstevel@tonic-gate */ 700*7c478bd9Sstevel@tonic-gate goto done; 701*7c478bd9Sstevel@tonic-gate } else if ((ret = memp_fget(mpf, &argp->pgno, 702*7c478bd9Sstevel@tonic-gate DB_MPOOL_CREATE, &pagep)) != 0) 703*7c478bd9Sstevel@tonic-gate goto out; 704*7c478bd9Sstevel@tonic-gate 705*7c478bd9Sstevel@tonic-gate GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); 706*7c478bd9Sstevel@tonic-gate if (ret != 0) 707*7c478bd9Sstevel@tonic-gate goto out; 708*7c478bd9Sstevel@tonic-gate getmeta = 1; 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &LSN(pagep)); 711*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); 712*7c478bd9Sstevel@tonic-gate 713*7c478bd9Sstevel@tonic-gate /* 714*7c478bd9Sstevel@tonic-gate * There are two types of log messages here, one for the old page 715*7c478bd9Sstevel@tonic-gate * and one for the new pages created. The original image in the 716*7c478bd9Sstevel@tonic-gate * SPLITOLD record is used for undo. The image in the SPLITNEW 717*7c478bd9Sstevel@tonic-gate * is used for redo. We should never have a case where there is 718*7c478bd9Sstevel@tonic-gate * a redo operation and the SPLITOLD record is on disk, but not 719*7c478bd9Sstevel@tonic-gate * the SPLITNEW record. Therefore, we only have work to do when 720*7c478bd9Sstevel@tonic-gate * redo NEW messages and undo OLD messages, but we have to update 721*7c478bd9Sstevel@tonic-gate * LSNs in both cases. 722*7c478bd9Sstevel@tonic-gate */ 723*7c478bd9Sstevel@tonic-gate change = 0; 724*7c478bd9Sstevel@tonic-gate if (cmp_p == 0 && redo) { 725*7c478bd9Sstevel@tonic-gate if (argp->opcode == SPLITNEW) 726*7c478bd9Sstevel@tonic-gate /* Need to redo the split described. */ 727*7c478bd9Sstevel@tonic-gate memcpy(pagep, argp->pageimage.data, 728*7c478bd9Sstevel@tonic-gate argp->pageimage.size); 729*7c478bd9Sstevel@tonic-gate LSN(pagep) = *lsnp; 730*7c478bd9Sstevel@tonic-gate change = 1; 731*7c478bd9Sstevel@tonic-gate } else if (cmp_n == 0 && !redo) { 732*7c478bd9Sstevel@tonic-gate if (argp->opcode == SPLITOLD) { 733*7c478bd9Sstevel@tonic-gate /* Put back the old image. */ 734*7c478bd9Sstevel@tonic-gate memcpy(pagep, argp->pageimage.data, 735*7c478bd9Sstevel@tonic-gate argp->pageimage.size); 736*7c478bd9Sstevel@tonic-gate } else 737*7c478bd9Sstevel@tonic-gate P_INIT(pagep, file_dbp->pgsize, argp->pgno, 738*7c478bd9Sstevel@tonic-gate PGNO_INVALID, PGNO_INVALID, 0, P_HASH); 739*7c478bd9Sstevel@tonic-gate LSN(pagep) = argp->pagelsn; 740*7c478bd9Sstevel@tonic-gate change = 1; 741*7c478bd9Sstevel@tonic-gate } 742*7c478bd9Sstevel@tonic-gate if ((ret = __ham_put_page(file_dbp, pagep, change)) != 0) 743*7c478bd9Sstevel@tonic-gate goto out; 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate done: *lsnp = argp->prev_lsn; 746*7c478bd9Sstevel@tonic-gate ret = 0; 747*7c478bd9Sstevel@tonic-gate 748*7c478bd9Sstevel@tonic-gate out: if (getmeta) 749*7c478bd9Sstevel@tonic-gate RELEASE_META(file_dbp, hcp); 750*7c478bd9Sstevel@tonic-gate REC_CLOSE; 751*7c478bd9Sstevel@tonic-gate } 752*7c478bd9Sstevel@tonic-gate 753*7c478bd9Sstevel@tonic-gate /* 754*7c478bd9Sstevel@tonic-gate * __ham_ovfl_recover -- 755*7c478bd9Sstevel@tonic-gate * This message is generated when we initialize a set of overflow pages. 756*7c478bd9Sstevel@tonic-gate * 757*7c478bd9Sstevel@tonic-gate * PUBLIC: int __ham_ovfl_recover 758*7c478bd9Sstevel@tonic-gate * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); 759*7c478bd9Sstevel@tonic-gate */ 760*7c478bd9Sstevel@tonic-gate int 761*7c478bd9Sstevel@tonic-gate __ham_ovfl_recover(logp, dbtp, lsnp, redo, info) 762*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 763*7c478bd9Sstevel@tonic-gate DBT *dbtp; 764*7c478bd9Sstevel@tonic-gate DB_LSN *lsnp; 765*7c478bd9Sstevel@tonic-gate int redo; 766*7c478bd9Sstevel@tonic-gate void *info; 767*7c478bd9Sstevel@tonic-gate { 768*7c478bd9Sstevel@tonic-gate __ham_ovfl_args *argp; 769*7c478bd9Sstevel@tonic-gate DB *file_dbp; 770*7c478bd9Sstevel@tonic-gate DBC *dbc; 771*7c478bd9Sstevel@tonic-gate HASH_CURSOR *hcp; 772*7c478bd9Sstevel@tonic-gate DB_MPOOLFILE *mpf; 773*7c478bd9Sstevel@tonic-gate PAGE *pagep; 774*7c478bd9Sstevel@tonic-gate db_pgno_t max_pgno, pgno; 775*7c478bd9Sstevel@tonic-gate int cmp_n, cmp_p, getmeta, ret; 776*7c478bd9Sstevel@tonic-gate 777*7c478bd9Sstevel@tonic-gate getmeta = 0; 778*7c478bd9Sstevel@tonic-gate hcp = NULL; 779*7c478bd9Sstevel@tonic-gate REC_PRINT(__ham_ovfl_print); 780*7c478bd9Sstevel@tonic-gate REC_INTRO(__ham_ovfl_read); 781*7c478bd9Sstevel@tonic-gate hcp = (HASH_CURSOR *)dbc->internal; 782*7c478bd9Sstevel@tonic-gate 783*7c478bd9Sstevel@tonic-gate GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); 784*7c478bd9Sstevel@tonic-gate if (ret != 0) 785*7c478bd9Sstevel@tonic-gate goto out; 786*7c478bd9Sstevel@tonic-gate getmeta = 1; 787*7c478bd9Sstevel@tonic-gate 788*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &hcp->hdr->lsn); 789*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&hcp->hdr->lsn, &argp->metalsn); 790*7c478bd9Sstevel@tonic-gate 791*7c478bd9Sstevel@tonic-gate if (cmp_p == 0 && redo) { 792*7c478bd9Sstevel@tonic-gate /* Redo the allocation. */ 793*7c478bd9Sstevel@tonic-gate hcp->hdr->last_freed = argp->start_pgno; 794*7c478bd9Sstevel@tonic-gate hcp->hdr->spares[argp->ovflpoint] += argp->npages; 795*7c478bd9Sstevel@tonic-gate hcp->hdr->lsn = *lsnp; 796*7c478bd9Sstevel@tonic-gate F_SET(hcp, H_DIRTY); 797*7c478bd9Sstevel@tonic-gate } else if (cmp_n == 0 && !redo) { 798*7c478bd9Sstevel@tonic-gate hcp->hdr->last_freed = argp->free_pgno; 799*7c478bd9Sstevel@tonic-gate hcp->hdr->spares[argp->ovflpoint] -= argp->npages; 800*7c478bd9Sstevel@tonic-gate hcp->hdr->lsn = argp->metalsn; 801*7c478bd9Sstevel@tonic-gate F_SET(hcp, H_DIRTY); 802*7c478bd9Sstevel@tonic-gate } 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate max_pgno = argp->start_pgno + argp->npages - 1; 805*7c478bd9Sstevel@tonic-gate ret = 0; 806*7c478bd9Sstevel@tonic-gate for (pgno = argp->start_pgno; pgno <= max_pgno; pgno++) { 807*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(mpf, &pgno, 0, &pagep)) != 0) { 808*7c478bd9Sstevel@tonic-gate if (!redo) { 809*7c478bd9Sstevel@tonic-gate ret = 0; 810*7c478bd9Sstevel@tonic-gate continue; 811*7c478bd9Sstevel@tonic-gate } 812*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(mpf, 813*7c478bd9Sstevel@tonic-gate &pgno, DB_MPOOL_CREATE, &pagep)) != 0) 814*7c478bd9Sstevel@tonic-gate goto out; 815*7c478bd9Sstevel@tonic-gate } 816*7c478bd9Sstevel@tonic-gate if (redo && log_compare((const DB_LSN *)lsnp, 817*7c478bd9Sstevel@tonic-gate (const DB_LSN *)&LSN(pagep)) > 0) { 818*7c478bd9Sstevel@tonic-gate P_INIT(pagep, file_dbp->pgsize, pgno, PGNO_INVALID, 819*7c478bd9Sstevel@tonic-gate pgno == max_pgno ? argp->free_pgno : pgno + 1, 820*7c478bd9Sstevel@tonic-gate 0, P_HASH); 821*7c478bd9Sstevel@tonic-gate LSN(pagep) = *lsnp; 822*7c478bd9Sstevel@tonic-gate ret = __ham_put_page(file_dbp, pagep, 1); 823*7c478bd9Sstevel@tonic-gate } else if (!redo) { 824*7c478bd9Sstevel@tonic-gate ZERO_LSN(pagep->lsn); 825*7c478bd9Sstevel@tonic-gate ret = __ham_put_page(file_dbp, pagep, 1); 826*7c478bd9Sstevel@tonic-gate } else 827*7c478bd9Sstevel@tonic-gate ret = __ham_put_page(file_dbp, pagep, 0); 828*7c478bd9Sstevel@tonic-gate if (ret) 829*7c478bd9Sstevel@tonic-gate goto out; 830*7c478bd9Sstevel@tonic-gate } 831*7c478bd9Sstevel@tonic-gate 832*7c478bd9Sstevel@tonic-gate done: *lsnp = argp->prev_lsn; 833*7c478bd9Sstevel@tonic-gate ret = 0; 834*7c478bd9Sstevel@tonic-gate 835*7c478bd9Sstevel@tonic-gate out: if (getmeta) 836*7c478bd9Sstevel@tonic-gate RELEASE_META(file_dbp, hcp); 837*7c478bd9Sstevel@tonic-gate REC_CLOSE; 838*7c478bd9Sstevel@tonic-gate } 839*7c478bd9Sstevel@tonic-gate 840*7c478bd9Sstevel@tonic-gate /* 841*7c478bd9Sstevel@tonic-gate * __ham_copypage_recover -- 842*7c478bd9Sstevel@tonic-gate * Recovery function for copypage. 843*7c478bd9Sstevel@tonic-gate * 844*7c478bd9Sstevel@tonic-gate * PUBLIC: int __ham_copypage_recover 845*7c478bd9Sstevel@tonic-gate * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); 846*7c478bd9Sstevel@tonic-gate */ 847*7c478bd9Sstevel@tonic-gate int 848*7c478bd9Sstevel@tonic-gate __ham_copypage_recover(logp, dbtp, lsnp, redo, info) 849*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 850*7c478bd9Sstevel@tonic-gate DBT *dbtp; 851*7c478bd9Sstevel@tonic-gate DB_LSN *lsnp; 852*7c478bd9Sstevel@tonic-gate int redo; 853*7c478bd9Sstevel@tonic-gate void *info; 854*7c478bd9Sstevel@tonic-gate { 855*7c478bd9Sstevel@tonic-gate __ham_copypage_args *argp; 856*7c478bd9Sstevel@tonic-gate DB *file_dbp; 857*7c478bd9Sstevel@tonic-gate DBC *dbc; 858*7c478bd9Sstevel@tonic-gate HASH_CURSOR *hcp; 859*7c478bd9Sstevel@tonic-gate DB_MPOOLFILE *mpf; 860*7c478bd9Sstevel@tonic-gate PAGE *pagep; 861*7c478bd9Sstevel@tonic-gate int cmp_n, cmp_p, getmeta, modified, ret; 862*7c478bd9Sstevel@tonic-gate 863*7c478bd9Sstevel@tonic-gate getmeta = 0; 864*7c478bd9Sstevel@tonic-gate hcp = NULL; 865*7c478bd9Sstevel@tonic-gate REC_PRINT(__ham_copypage_print); 866*7c478bd9Sstevel@tonic-gate REC_INTRO(__ham_copypage_read); 867*7c478bd9Sstevel@tonic-gate hcp = (HASH_CURSOR *)dbc->internal; 868*7c478bd9Sstevel@tonic-gate 869*7c478bd9Sstevel@tonic-gate GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret); 870*7c478bd9Sstevel@tonic-gate if (ret != 0) 871*7c478bd9Sstevel@tonic-gate goto out; 872*7c478bd9Sstevel@tonic-gate getmeta = 1; 873*7c478bd9Sstevel@tonic-gate modified = 0; 874*7c478bd9Sstevel@tonic-gate 875*7c478bd9Sstevel@tonic-gate /* This is the bucket page. */ 876*7c478bd9Sstevel@tonic-gate ret = memp_fget(mpf, &argp->pgno, 0, &pagep); 877*7c478bd9Sstevel@tonic-gate if (ret != 0) 878*7c478bd9Sstevel@tonic-gate if (!redo) { 879*7c478bd9Sstevel@tonic-gate /* 880*7c478bd9Sstevel@tonic-gate * We are undoing and the page doesn't exist. That 881*7c478bd9Sstevel@tonic-gate * is equivalent to having a pagelsn of 0, so we 882*7c478bd9Sstevel@tonic-gate * would not have to undo anything. In this case, 883*7c478bd9Sstevel@tonic-gate * don't bother creating a page. 884*7c478bd9Sstevel@tonic-gate */ 885*7c478bd9Sstevel@tonic-gate ret = 0; 886*7c478bd9Sstevel@tonic-gate goto donext; 887*7c478bd9Sstevel@tonic-gate } else if ((ret = memp_fget(mpf, &argp->pgno, 888*7c478bd9Sstevel@tonic-gate DB_MPOOL_CREATE, &pagep)) != 0) 889*7c478bd9Sstevel@tonic-gate goto out; 890*7c478bd9Sstevel@tonic-gate 891*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &LSN(pagep)); 892*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&LSN(pagep), &argp->pagelsn); 893*7c478bd9Sstevel@tonic-gate 894*7c478bd9Sstevel@tonic-gate if (cmp_p == 0 && redo) { 895*7c478bd9Sstevel@tonic-gate /* Need to redo update described. */ 896*7c478bd9Sstevel@tonic-gate memcpy(pagep, argp->page.data, argp->page.size); 897*7c478bd9Sstevel@tonic-gate LSN(pagep) = *lsnp; 898*7c478bd9Sstevel@tonic-gate modified = 1; 899*7c478bd9Sstevel@tonic-gate } else if (cmp_n == 0 && !redo) { 900*7c478bd9Sstevel@tonic-gate /* Need to undo update described. */ 901*7c478bd9Sstevel@tonic-gate P_INIT(pagep, hcp->hdr->pagesize, argp->pgno, PGNO_INVALID, 902*7c478bd9Sstevel@tonic-gate argp->next_pgno, 0, P_HASH); 903*7c478bd9Sstevel@tonic-gate LSN(pagep) = argp->pagelsn; 904*7c478bd9Sstevel@tonic-gate modified = 1; 905*7c478bd9Sstevel@tonic-gate } 906*7c478bd9Sstevel@tonic-gate if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) 907*7c478bd9Sstevel@tonic-gate goto out; 908*7c478bd9Sstevel@tonic-gate 909*7c478bd9Sstevel@tonic-gate /* Now fix up the "next" page. */ 910*7c478bd9Sstevel@tonic-gate donext: ret = memp_fget(mpf, &argp->next_pgno, 0, &pagep); 911*7c478bd9Sstevel@tonic-gate if (ret != 0) 912*7c478bd9Sstevel@tonic-gate if (!redo) { 913*7c478bd9Sstevel@tonic-gate /* 914*7c478bd9Sstevel@tonic-gate * We are undoing and the page doesn't exist. That 915*7c478bd9Sstevel@tonic-gate * is equivalent to having a pagelsn of 0, so we 916*7c478bd9Sstevel@tonic-gate * would not have to undo anything. In this case, 917*7c478bd9Sstevel@tonic-gate * don't bother creating a page. 918*7c478bd9Sstevel@tonic-gate */ 919*7c478bd9Sstevel@tonic-gate ret = 0; 920*7c478bd9Sstevel@tonic-gate goto do_nn; 921*7c478bd9Sstevel@tonic-gate } else if ((ret = memp_fget(mpf, &argp->next_pgno, 922*7c478bd9Sstevel@tonic-gate DB_MPOOL_CREATE, &pagep)) != 0) 923*7c478bd9Sstevel@tonic-gate goto out; 924*7c478bd9Sstevel@tonic-gate 925*7c478bd9Sstevel@tonic-gate /* There is nothing to do in the REDO case; only UNDO. */ 926*7c478bd9Sstevel@tonic-gate 927*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &LSN(pagep)); 928*7c478bd9Sstevel@tonic-gate if (cmp_n == 0 && !redo) { 929*7c478bd9Sstevel@tonic-gate /* Need to undo update described. */ 930*7c478bd9Sstevel@tonic-gate memcpy(pagep, argp->page.data, argp->page.size); 931*7c478bd9Sstevel@tonic-gate modified = 1; 932*7c478bd9Sstevel@tonic-gate } 933*7c478bd9Sstevel@tonic-gate if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) 934*7c478bd9Sstevel@tonic-gate goto out; 935*7c478bd9Sstevel@tonic-gate 936*7c478bd9Sstevel@tonic-gate /* Now fix up the next's next page. */ 937*7c478bd9Sstevel@tonic-gate do_nn: if (argp->nnext_pgno == PGNO_INVALID) 938*7c478bd9Sstevel@tonic-gate goto done; 939*7c478bd9Sstevel@tonic-gate 940*7c478bd9Sstevel@tonic-gate ret = memp_fget(mpf, &argp->nnext_pgno, 0, &pagep); 941*7c478bd9Sstevel@tonic-gate if (ret != 0) 942*7c478bd9Sstevel@tonic-gate if (!redo) { 943*7c478bd9Sstevel@tonic-gate /* 944*7c478bd9Sstevel@tonic-gate * We are undoing and the page doesn't exist. That 945*7c478bd9Sstevel@tonic-gate * is equivalent to having a pagelsn of 0, so we 946*7c478bd9Sstevel@tonic-gate * would not have to undo anything. In this case, 947*7c478bd9Sstevel@tonic-gate * don't bother creating a page. 948*7c478bd9Sstevel@tonic-gate */ 949*7c478bd9Sstevel@tonic-gate goto done; 950*7c478bd9Sstevel@tonic-gate } else if ((ret = memp_fget(mpf, &argp->nnext_pgno, 951*7c478bd9Sstevel@tonic-gate DB_MPOOL_CREATE, &pagep)) != 0) 952*7c478bd9Sstevel@tonic-gate goto out; 953*7c478bd9Sstevel@tonic-gate 954*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &LSN(pagep)); 955*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&LSN(pagep), &argp->nnextlsn); 956*7c478bd9Sstevel@tonic-gate 957*7c478bd9Sstevel@tonic-gate if (cmp_p == 0 && redo) { 958*7c478bd9Sstevel@tonic-gate /* Need to redo update described. */ 959*7c478bd9Sstevel@tonic-gate PREV_PGNO(pagep) = argp->pgno; 960*7c478bd9Sstevel@tonic-gate LSN(pagep) = *lsnp; 961*7c478bd9Sstevel@tonic-gate modified = 1; 962*7c478bd9Sstevel@tonic-gate } else if (cmp_n == 0 && !redo) { 963*7c478bd9Sstevel@tonic-gate /* Need to undo update described. */ 964*7c478bd9Sstevel@tonic-gate PREV_PGNO(pagep) = argp->next_pgno; 965*7c478bd9Sstevel@tonic-gate LSN(pagep) = argp->nnextlsn; 966*7c478bd9Sstevel@tonic-gate modified = 1; 967*7c478bd9Sstevel@tonic-gate } 968*7c478bd9Sstevel@tonic-gate if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) 969*7c478bd9Sstevel@tonic-gate goto out; 970*7c478bd9Sstevel@tonic-gate 971*7c478bd9Sstevel@tonic-gate done: *lsnp = argp->prev_lsn; 972*7c478bd9Sstevel@tonic-gate ret = 0; 973*7c478bd9Sstevel@tonic-gate 974*7c478bd9Sstevel@tonic-gate out: if (getmeta) 975*7c478bd9Sstevel@tonic-gate RELEASE_META(file_dbp, hcp); 976*7c478bd9Sstevel@tonic-gate REC_CLOSE; 977*7c478bd9Sstevel@tonic-gate } 978