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 #include "config.h" 9*7c478bd9Sstevel@tonic-gate 10*7c478bd9Sstevel@tonic-gate #ifndef lint 11*7c478bd9Sstevel@tonic-gate static const char sccsid[] = "@(#)bt_rec.c 10.28 (Sleepycat) 9/27/98"; 12*7c478bd9Sstevel@tonic-gate #endif /* not lint */ 13*7c478bd9Sstevel@tonic-gate 14*7c478bd9Sstevel@tonic-gate #ifndef NO_SYSTEM_INCLUDES 15*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 16*7c478bd9Sstevel@tonic-gate 17*7c478bd9Sstevel@tonic-gate #include <errno.h> 18*7c478bd9Sstevel@tonic-gate #include <string.h> 19*7c478bd9Sstevel@tonic-gate #endif 20*7c478bd9Sstevel@tonic-gate 21*7c478bd9Sstevel@tonic-gate #include "db_int.h" 22*7c478bd9Sstevel@tonic-gate #include "db_page.h" 23*7c478bd9Sstevel@tonic-gate #include "shqueue.h" 24*7c478bd9Sstevel@tonic-gate #include "hash.h" 25*7c478bd9Sstevel@tonic-gate #include "btree.h" 26*7c478bd9Sstevel@tonic-gate #include "log.h" 27*7c478bd9Sstevel@tonic-gate #include "common_ext.h" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * __bam_pg_alloc_recover -- 31*7c478bd9Sstevel@tonic-gate * Recovery function for pg_alloc. 32*7c478bd9Sstevel@tonic-gate * 33*7c478bd9Sstevel@tonic-gate * PUBLIC: int __bam_pg_alloc_recover 34*7c478bd9Sstevel@tonic-gate * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); 35*7c478bd9Sstevel@tonic-gate */ 36*7c478bd9Sstevel@tonic-gate int 37*7c478bd9Sstevel@tonic-gate __bam_pg_alloc_recover(logp, dbtp, lsnp, redo, info) 38*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 39*7c478bd9Sstevel@tonic-gate DBT *dbtp; 40*7c478bd9Sstevel@tonic-gate DB_LSN *lsnp; 41*7c478bd9Sstevel@tonic-gate int redo; 42*7c478bd9Sstevel@tonic-gate void *info; 43*7c478bd9Sstevel@tonic-gate { 44*7c478bd9Sstevel@tonic-gate __bam_pg_alloc_args *argp; 45*7c478bd9Sstevel@tonic-gate BTMETA *meta; 46*7c478bd9Sstevel@tonic-gate DB_MPOOLFILE *mpf; 47*7c478bd9Sstevel@tonic-gate PAGE *pagep; 48*7c478bd9Sstevel@tonic-gate DB *file_dbp; 49*7c478bd9Sstevel@tonic-gate DBC *dbc; 50*7c478bd9Sstevel@tonic-gate db_pgno_t pgno; 51*7c478bd9Sstevel@tonic-gate int cmp_n, cmp_p, modified, ret; 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate REC_PRINT(__bam_pg_alloc_print); 54*7c478bd9Sstevel@tonic-gate REC_INTRO(__bam_pg_alloc_read); 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate /* 57*7c478bd9Sstevel@tonic-gate * Fix up the allocated page. If we're redoing the operation, we have 58*7c478bd9Sstevel@tonic-gate * to get the page (creating it if it doesn't exist), and update its 59*7c478bd9Sstevel@tonic-gate * LSN. If we're undoing the operation, we have to reset the page's 60*7c478bd9Sstevel@tonic-gate * LSN and put it on the free list. 61*7c478bd9Sstevel@tonic-gate * 62*7c478bd9Sstevel@tonic-gate * Fix up the metadata page. If we're redoing the operation, we have 63*7c478bd9Sstevel@tonic-gate * to get the metadata page and update its LSN and its free pointer. 64*7c478bd9Sstevel@tonic-gate * If we're undoing the operation and the page was ever created, we put 65*7c478bd9Sstevel@tonic-gate * it on the freelist. 66*7c478bd9Sstevel@tonic-gate */ 67*7c478bd9Sstevel@tonic-gate pgno = PGNO_METADATA; 68*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(mpf, &pgno, 0, &meta)) != 0) { 69*7c478bd9Sstevel@tonic-gate /* The metadata page must always exist. */ 70*7c478bd9Sstevel@tonic-gate (void)__db_pgerr(file_dbp, pgno); 71*7c478bd9Sstevel@tonic-gate goto out; 72*7c478bd9Sstevel@tonic-gate } 73*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) { 74*7c478bd9Sstevel@tonic-gate /* 75*7c478bd9Sstevel@tonic-gate * We specify creation and check for it later, because this 76*7c478bd9Sstevel@tonic-gate * operation was supposed to create the page, and even in 77*7c478bd9Sstevel@tonic-gate * the undo case it's going to get linked onto the freelist 78*7c478bd9Sstevel@tonic-gate * which we're also fixing up. 79*7c478bd9Sstevel@tonic-gate */ 80*7c478bd9Sstevel@tonic-gate (void)__db_pgerr(file_dbp, argp->pgno); 81*7c478bd9Sstevel@tonic-gate (void)memp_fput(mpf, meta, 0); 82*7c478bd9Sstevel@tonic-gate goto out; 83*7c478bd9Sstevel@tonic-gate } 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate /* Fix up the allocated page. */ 86*7c478bd9Sstevel@tonic-gate modified = 0; 87*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &LSN(pagep)); 88*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&LSN(pagep), &argp->page_lsn); 89*7c478bd9Sstevel@tonic-gate if (cmp_p == 0 && redo) { 90*7c478bd9Sstevel@tonic-gate /* Need to redo update described. */ 91*7c478bd9Sstevel@tonic-gate P_INIT(pagep, file_dbp->pgsize, 92*7c478bd9Sstevel@tonic-gate argp->pgno, PGNO_INVALID, PGNO_INVALID, 0, argp->ptype); 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate pagep->lsn = *lsnp; 95*7c478bd9Sstevel@tonic-gate modified = 1; 96*7c478bd9Sstevel@tonic-gate } else if (cmp_n == 0 && !redo) { 97*7c478bd9Sstevel@tonic-gate /* Need to undo update described. */ 98*7c478bd9Sstevel@tonic-gate P_INIT(pagep, file_dbp->pgsize, 99*7c478bd9Sstevel@tonic-gate argp->pgno, PGNO_INVALID, meta->free, 0, P_INVALID); 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate pagep->lsn = argp->page_lsn; 102*7c478bd9Sstevel@tonic-gate modified = 1; 103*7c478bd9Sstevel@tonic-gate } 104*7c478bd9Sstevel@tonic-gate if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) { 105*7c478bd9Sstevel@tonic-gate (void)memp_fput(mpf, meta, 0); 106*7c478bd9Sstevel@tonic-gate goto out; 107*7c478bd9Sstevel@tonic-gate } 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate /* Fix up the metadata page. */ 110*7c478bd9Sstevel@tonic-gate modified = 0; 111*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &LSN(meta)); 112*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&LSN(meta), &argp->meta_lsn); 113*7c478bd9Sstevel@tonic-gate if (cmp_p == 0 && redo) { 114*7c478bd9Sstevel@tonic-gate /* Need to redo update described. */ 115*7c478bd9Sstevel@tonic-gate meta->lsn = *lsnp; 116*7c478bd9Sstevel@tonic-gate meta->free = argp->next; 117*7c478bd9Sstevel@tonic-gate modified = 1; 118*7c478bd9Sstevel@tonic-gate } else if (cmp_n == 0 && !redo) { 119*7c478bd9Sstevel@tonic-gate /* Need to undo update described. */ 120*7c478bd9Sstevel@tonic-gate meta->lsn = argp->meta_lsn; 121*7c478bd9Sstevel@tonic-gate meta->free = argp->pgno; 122*7c478bd9Sstevel@tonic-gate modified = 1; 123*7c478bd9Sstevel@tonic-gate } 124*7c478bd9Sstevel@tonic-gate if ((ret = memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0) 125*7c478bd9Sstevel@tonic-gate goto out; 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate done: *lsnp = argp->prev_lsn; 128*7c478bd9Sstevel@tonic-gate ret = 0; 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate out: REC_CLOSE; 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate /* 134*7c478bd9Sstevel@tonic-gate * __bam_pg_free_recover -- 135*7c478bd9Sstevel@tonic-gate * Recovery function for pg_free. 136*7c478bd9Sstevel@tonic-gate * 137*7c478bd9Sstevel@tonic-gate * PUBLIC: int __bam_pg_free_recover 138*7c478bd9Sstevel@tonic-gate * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); 139*7c478bd9Sstevel@tonic-gate */ 140*7c478bd9Sstevel@tonic-gate int 141*7c478bd9Sstevel@tonic-gate __bam_pg_free_recover(logp, dbtp, lsnp, redo, info) 142*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 143*7c478bd9Sstevel@tonic-gate DBT *dbtp; 144*7c478bd9Sstevel@tonic-gate DB_LSN *lsnp; 145*7c478bd9Sstevel@tonic-gate int redo; 146*7c478bd9Sstevel@tonic-gate void *info; 147*7c478bd9Sstevel@tonic-gate { 148*7c478bd9Sstevel@tonic-gate __bam_pg_free_args *argp; 149*7c478bd9Sstevel@tonic-gate BTMETA *meta; 150*7c478bd9Sstevel@tonic-gate DB *file_dbp; 151*7c478bd9Sstevel@tonic-gate DBC *dbc; 152*7c478bd9Sstevel@tonic-gate DB_MPOOLFILE *mpf; 153*7c478bd9Sstevel@tonic-gate PAGE *pagep; 154*7c478bd9Sstevel@tonic-gate db_pgno_t pgno; 155*7c478bd9Sstevel@tonic-gate int cmp_n, cmp_p, modified, ret; 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate REC_PRINT(__bam_pg_free_print); 158*7c478bd9Sstevel@tonic-gate REC_INTRO(__bam_pg_free_read); 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate /* 161*7c478bd9Sstevel@tonic-gate * Fix up the freed page. If we're redoing the operation we get the 162*7c478bd9Sstevel@tonic-gate * page and explicitly discard its contents, then update its LSN. If 163*7c478bd9Sstevel@tonic-gate * we're undoing the operation, we get the page and restore its header. 164*7c478bd9Sstevel@tonic-gate */ 165*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { 166*7c478bd9Sstevel@tonic-gate /* 167*7c478bd9Sstevel@tonic-gate * We don't automatically create the page. The only way the 168*7c478bd9Sstevel@tonic-gate * page might not exist is if the alloc never happened, and 169*7c478bd9Sstevel@tonic-gate * the only way the alloc might never have happened is if we 170*7c478bd9Sstevel@tonic-gate * are undoing, in which case there's no reason to create the 171*7c478bd9Sstevel@tonic-gate * page. 172*7c478bd9Sstevel@tonic-gate */ 173*7c478bd9Sstevel@tonic-gate if (!redo) 174*7c478bd9Sstevel@tonic-gate goto done; 175*7c478bd9Sstevel@tonic-gate (void)__db_pgerr(file_dbp, argp->pgno); 176*7c478bd9Sstevel@tonic-gate goto out; 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate modified = 0; 179*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &LSN(pagep)); 180*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&LSN(pagep), &LSN(argp->header.data)); 181*7c478bd9Sstevel@tonic-gate if (cmp_p == 0 && redo) { 182*7c478bd9Sstevel@tonic-gate /* Need to redo update described. */ 183*7c478bd9Sstevel@tonic-gate P_INIT(pagep, file_dbp->pgsize, 184*7c478bd9Sstevel@tonic-gate pagep->pgno, PGNO_INVALID, argp->next, 0, P_INVALID); 185*7c478bd9Sstevel@tonic-gate pagep->lsn = *lsnp; 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate modified = 1; 188*7c478bd9Sstevel@tonic-gate } else if (cmp_n == 0 && !redo) { 189*7c478bd9Sstevel@tonic-gate /* Need to undo update described. */ 190*7c478bd9Sstevel@tonic-gate memcpy(pagep, argp->header.data, argp->header.size); 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate modified = 1; 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) 195*7c478bd9Sstevel@tonic-gate goto out; 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate /* 198*7c478bd9Sstevel@tonic-gate * Fix up the metadata page. If we're redoing or undoing the operation 199*7c478bd9Sstevel@tonic-gate * we get the page and update its LSN and free pointer. 200*7c478bd9Sstevel@tonic-gate */ 201*7c478bd9Sstevel@tonic-gate pgno = PGNO_METADATA; 202*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(mpf, &pgno, 0, &meta)) != 0) { 203*7c478bd9Sstevel@tonic-gate /* The metadata page must always exist. */ 204*7c478bd9Sstevel@tonic-gate (void)__db_pgerr(file_dbp, pgno); 205*7c478bd9Sstevel@tonic-gate goto out; 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate modified = 0; 209*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &LSN(meta)); 210*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&LSN(meta), &argp->meta_lsn); 211*7c478bd9Sstevel@tonic-gate if (cmp_p == 0 && redo) { 212*7c478bd9Sstevel@tonic-gate /* Need to redo update described. */ 213*7c478bd9Sstevel@tonic-gate meta->free = argp->pgno; 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate meta->lsn = *lsnp; 216*7c478bd9Sstevel@tonic-gate modified = 1; 217*7c478bd9Sstevel@tonic-gate } else if (cmp_n == 0 && !redo) { 218*7c478bd9Sstevel@tonic-gate /* Need to undo update described. */ 219*7c478bd9Sstevel@tonic-gate meta->free = argp->next; 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate meta->lsn = argp->meta_lsn; 222*7c478bd9Sstevel@tonic-gate modified = 1; 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate if ((ret = memp_fput(mpf, meta, modified ? DB_MPOOL_DIRTY : 0)) != 0) 225*7c478bd9Sstevel@tonic-gate goto out; 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate done: *lsnp = argp->prev_lsn; 228*7c478bd9Sstevel@tonic-gate ret = 0; 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate out: REC_CLOSE; 231*7c478bd9Sstevel@tonic-gate } 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate /* 234*7c478bd9Sstevel@tonic-gate * __bam_split_recover -- 235*7c478bd9Sstevel@tonic-gate * Recovery function for split. 236*7c478bd9Sstevel@tonic-gate * 237*7c478bd9Sstevel@tonic-gate * PUBLIC: int __bam_split_recover 238*7c478bd9Sstevel@tonic-gate * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); 239*7c478bd9Sstevel@tonic-gate */ 240*7c478bd9Sstevel@tonic-gate int 241*7c478bd9Sstevel@tonic-gate __bam_split_recover(logp, dbtp, lsnp, redo, info) 242*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 243*7c478bd9Sstevel@tonic-gate DBT *dbtp; 244*7c478bd9Sstevel@tonic-gate DB_LSN *lsnp; 245*7c478bd9Sstevel@tonic-gate int redo; 246*7c478bd9Sstevel@tonic-gate void *info; 247*7c478bd9Sstevel@tonic-gate { 248*7c478bd9Sstevel@tonic-gate __bam_split_args *argp; 249*7c478bd9Sstevel@tonic-gate DB *file_dbp; 250*7c478bd9Sstevel@tonic-gate DBC *dbc; 251*7c478bd9Sstevel@tonic-gate DB_MPOOLFILE *mpf; 252*7c478bd9Sstevel@tonic-gate PAGE *_lp, *lp, *np, *pp, *_rp, *rp, *sp; 253*7c478bd9Sstevel@tonic-gate db_pgno_t pgno; 254*7c478bd9Sstevel@tonic-gate int l_update, p_update, r_update, ret, rootsplit, t_ret; 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate REC_PRINT(__bam_split_print); 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate mpf = NULL; 259*7c478bd9Sstevel@tonic-gate _lp = lp = np = pp = _rp = rp = NULL; 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate REC_INTRO(__bam_split_read); 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate /* 264*7c478bd9Sstevel@tonic-gate * There are two kinds of splits that we have to recover from. The 265*7c478bd9Sstevel@tonic-gate * first is a root-page split, where the root page is split from a 266*7c478bd9Sstevel@tonic-gate * leaf page into an internal page and two new leaf pages are created. 267*7c478bd9Sstevel@tonic-gate * The second is where a page is split into two pages, and a new key 268*7c478bd9Sstevel@tonic-gate * is inserted into the parent page. 269*7c478bd9Sstevel@tonic-gate */ 270*7c478bd9Sstevel@tonic-gate sp = argp->pg.data; 271*7c478bd9Sstevel@tonic-gate pgno = PGNO(sp); 272*7c478bd9Sstevel@tonic-gate rootsplit = pgno == PGNO_ROOT; 273*7c478bd9Sstevel@tonic-gate if (memp_fget(mpf, &argp->left, 0, &lp) != 0) 274*7c478bd9Sstevel@tonic-gate lp = NULL; 275*7c478bd9Sstevel@tonic-gate if (memp_fget(mpf, &argp->right, 0, &rp) != 0) 276*7c478bd9Sstevel@tonic-gate rp = NULL; 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate if (redo) { 279*7c478bd9Sstevel@tonic-gate l_update = r_update = p_update = 0; 280*7c478bd9Sstevel@tonic-gate /* 281*7c478bd9Sstevel@tonic-gate * Decide if we need to resplit the page. 282*7c478bd9Sstevel@tonic-gate * 283*7c478bd9Sstevel@tonic-gate * If this is a root split, then the root has to exist, it's 284*7c478bd9Sstevel@tonic-gate * the page we're splitting and it gets modified. If this is 285*7c478bd9Sstevel@tonic-gate * not a root split, then the left page has to exist, for the 286*7c478bd9Sstevel@tonic-gate * same reason. 287*7c478bd9Sstevel@tonic-gate */ 288*7c478bd9Sstevel@tonic-gate if (rootsplit) { 289*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(mpf, &pgno, 0, &pp)) != 0) { 290*7c478bd9Sstevel@tonic-gate (void)__db_pgerr(file_dbp, pgno); 291*7c478bd9Sstevel@tonic-gate pp = NULL; 292*7c478bd9Sstevel@tonic-gate goto out; 293*7c478bd9Sstevel@tonic-gate } 294*7c478bd9Sstevel@tonic-gate p_update = 295*7c478bd9Sstevel@tonic-gate log_compare(&LSN(pp), &LSN(argp->pg.data)) == 0; 296*7c478bd9Sstevel@tonic-gate } else 297*7c478bd9Sstevel@tonic-gate if (lp == NULL) { 298*7c478bd9Sstevel@tonic-gate (void)__db_pgerr(file_dbp, argp->left); 299*7c478bd9Sstevel@tonic-gate goto out; 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate if (lp == NULL || log_compare(&LSN(lp), &argp->llsn) == 0) 302*7c478bd9Sstevel@tonic-gate l_update = 1; 303*7c478bd9Sstevel@tonic-gate if (rp == NULL || log_compare(&LSN(rp), &argp->rlsn) == 0) 304*7c478bd9Sstevel@tonic-gate r_update = 1; 305*7c478bd9Sstevel@tonic-gate if (!p_update && !l_update && !r_update) 306*7c478bd9Sstevel@tonic-gate goto done; 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate /* Allocate and initialize new left/right child pages. */ 309*7c478bd9Sstevel@tonic-gate if ((ret = __os_malloc(file_dbp->pgsize, NULL, &_lp)) != 0 || 310*7c478bd9Sstevel@tonic-gate (ret = __os_malloc(file_dbp->pgsize, NULL, &_rp)) != 0) 311*7c478bd9Sstevel@tonic-gate goto out; 312*7c478bd9Sstevel@tonic-gate if (rootsplit) { 313*7c478bd9Sstevel@tonic-gate P_INIT(_lp, file_dbp->pgsize, argp->left, 314*7c478bd9Sstevel@tonic-gate PGNO_INVALID, 315*7c478bd9Sstevel@tonic-gate ISINTERNAL(sp) ? PGNO_INVALID : argp->right, 316*7c478bd9Sstevel@tonic-gate LEVEL(sp), TYPE(sp)); 317*7c478bd9Sstevel@tonic-gate P_INIT(_rp, file_dbp->pgsize, argp->right, 318*7c478bd9Sstevel@tonic-gate ISINTERNAL(sp) ? PGNO_INVALID : argp->left, 319*7c478bd9Sstevel@tonic-gate PGNO_INVALID, LEVEL(sp), TYPE(sp)); 320*7c478bd9Sstevel@tonic-gate } else { 321*7c478bd9Sstevel@tonic-gate P_INIT(_lp, file_dbp->pgsize, PGNO(sp), 322*7c478bd9Sstevel@tonic-gate ISINTERNAL(sp) ? PGNO_INVALID : PREV_PGNO(sp), 323*7c478bd9Sstevel@tonic-gate ISINTERNAL(sp) ? PGNO_INVALID : argp->right, 324*7c478bd9Sstevel@tonic-gate LEVEL(sp), TYPE(sp)); 325*7c478bd9Sstevel@tonic-gate P_INIT(_rp, file_dbp->pgsize, argp->right, 326*7c478bd9Sstevel@tonic-gate ISINTERNAL(sp) ? PGNO_INVALID : sp->pgno, 327*7c478bd9Sstevel@tonic-gate ISINTERNAL(sp) ? PGNO_INVALID : NEXT_PGNO(sp), 328*7c478bd9Sstevel@tonic-gate LEVEL(sp), TYPE(sp)); 329*7c478bd9Sstevel@tonic-gate } 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate /* Split the page. */ 332*7c478bd9Sstevel@tonic-gate if ((ret = __bam_copy(file_dbp, sp, _lp, 0, argp->indx)) != 0 || 333*7c478bd9Sstevel@tonic-gate (ret = __bam_copy(file_dbp, sp, _rp, argp->indx, 334*7c478bd9Sstevel@tonic-gate NUM_ENT(sp))) != 0) 335*7c478bd9Sstevel@tonic-gate goto out; 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate /* If the left child is wrong, update it. */ 338*7c478bd9Sstevel@tonic-gate if (lp == NULL && (ret = 339*7c478bd9Sstevel@tonic-gate memp_fget(mpf, &argp->left, DB_MPOOL_CREATE, &lp)) != 0) { 340*7c478bd9Sstevel@tonic-gate (void)__db_pgerr(file_dbp, argp->left); 341*7c478bd9Sstevel@tonic-gate lp = NULL; 342*7c478bd9Sstevel@tonic-gate goto out; 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate if (l_update) { 345*7c478bd9Sstevel@tonic-gate memcpy(lp, _lp, file_dbp->pgsize); 346*7c478bd9Sstevel@tonic-gate lp->lsn = *lsnp; 347*7c478bd9Sstevel@tonic-gate if ((ret = memp_fput(mpf, lp, DB_MPOOL_DIRTY)) != 0) 348*7c478bd9Sstevel@tonic-gate goto out; 349*7c478bd9Sstevel@tonic-gate lp = NULL; 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate /* If the right child is wrong, update it. */ 353*7c478bd9Sstevel@tonic-gate if (rp == NULL && (ret = memp_fget(mpf, 354*7c478bd9Sstevel@tonic-gate &argp->right, DB_MPOOL_CREATE, &rp)) != 0) { 355*7c478bd9Sstevel@tonic-gate (void)__db_pgerr(file_dbp, argp->right); 356*7c478bd9Sstevel@tonic-gate rp = NULL; 357*7c478bd9Sstevel@tonic-gate goto out; 358*7c478bd9Sstevel@tonic-gate } 359*7c478bd9Sstevel@tonic-gate if (r_update) { 360*7c478bd9Sstevel@tonic-gate memcpy(rp, _rp, file_dbp->pgsize); 361*7c478bd9Sstevel@tonic-gate rp->lsn = *lsnp; 362*7c478bd9Sstevel@tonic-gate if ((ret = memp_fput(mpf, rp, DB_MPOOL_DIRTY)) != 0) 363*7c478bd9Sstevel@tonic-gate goto out; 364*7c478bd9Sstevel@tonic-gate rp = NULL; 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate /* 368*7c478bd9Sstevel@tonic-gate * If the parent page is wrong, update it. This is of interest 369*7c478bd9Sstevel@tonic-gate * only if it was a root split, since root splits create parent 370*7c478bd9Sstevel@tonic-gate * pages. All other splits modify a parent page, but those are 371*7c478bd9Sstevel@tonic-gate * separately logged and recovered. 372*7c478bd9Sstevel@tonic-gate */ 373*7c478bd9Sstevel@tonic-gate if (rootsplit && p_update) { 374*7c478bd9Sstevel@tonic-gate if (file_dbp->type == DB_BTREE) 375*7c478bd9Sstevel@tonic-gate P_INIT(pp, file_dbp->pgsize, 376*7c478bd9Sstevel@tonic-gate PGNO_ROOT, PGNO_INVALID, PGNO_INVALID, 377*7c478bd9Sstevel@tonic-gate _lp->level + 1, P_IBTREE); 378*7c478bd9Sstevel@tonic-gate else 379*7c478bd9Sstevel@tonic-gate P_INIT(pp, file_dbp->pgsize, 380*7c478bd9Sstevel@tonic-gate PGNO_ROOT, PGNO_INVALID, PGNO_INVALID, 381*7c478bd9Sstevel@tonic-gate _lp->level + 1, P_IRECNO); 382*7c478bd9Sstevel@tonic-gate RE_NREC_SET(pp, 383*7c478bd9Sstevel@tonic-gate file_dbp->type == DB_RECNO || 384*7c478bd9Sstevel@tonic-gate F_ISSET(file_dbp, DB_BT_RECNUM) ? 385*7c478bd9Sstevel@tonic-gate __bam_total(_lp) + __bam_total(_rp) : 0); 386*7c478bd9Sstevel@tonic-gate pp->lsn = *lsnp; 387*7c478bd9Sstevel@tonic-gate if ((ret = memp_fput(mpf, pp, DB_MPOOL_DIRTY)) != 0) 388*7c478bd9Sstevel@tonic-gate goto out; 389*7c478bd9Sstevel@tonic-gate pp = NULL; 390*7c478bd9Sstevel@tonic-gate } 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate /* 393*7c478bd9Sstevel@tonic-gate * Finally, redo the next-page link if necessary. This is of 394*7c478bd9Sstevel@tonic-gate * interest only if it wasn't a root split -- inserting a new 395*7c478bd9Sstevel@tonic-gate * page in the tree requires that any following page have its 396*7c478bd9Sstevel@tonic-gate * previous-page pointer updated to our new page. The next 397*7c478bd9Sstevel@tonic-gate * page must exist because we're redoing the operation. 398*7c478bd9Sstevel@tonic-gate */ 399*7c478bd9Sstevel@tonic-gate if (!rootsplit && !IS_ZERO_LSN(argp->nlsn)) { 400*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(mpf, &argp->npgno, 0, &np)) != 0) { 401*7c478bd9Sstevel@tonic-gate (void)__db_pgerr(file_dbp, argp->npgno); 402*7c478bd9Sstevel@tonic-gate np = NULL; 403*7c478bd9Sstevel@tonic-gate goto out; 404*7c478bd9Sstevel@tonic-gate } 405*7c478bd9Sstevel@tonic-gate if (log_compare(&LSN(np), &argp->nlsn) == 0) { 406*7c478bd9Sstevel@tonic-gate PREV_PGNO(np) = argp->right; 407*7c478bd9Sstevel@tonic-gate np->lsn = *lsnp; 408*7c478bd9Sstevel@tonic-gate if ((ret = 409*7c478bd9Sstevel@tonic-gate memp_fput(mpf, np, DB_MPOOL_DIRTY)) != 0) 410*7c478bd9Sstevel@tonic-gate goto out; 411*7c478bd9Sstevel@tonic-gate np = NULL; 412*7c478bd9Sstevel@tonic-gate } 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate } else { 415*7c478bd9Sstevel@tonic-gate /* 416*7c478bd9Sstevel@tonic-gate * If the split page is wrong, replace its contents with the 417*7c478bd9Sstevel@tonic-gate * logged page contents. If the page doesn't exist, it means 418*7c478bd9Sstevel@tonic-gate * that the create of the page never happened, nor did any of 419*7c478bd9Sstevel@tonic-gate * the adds onto the page that caused the split, and there's 420*7c478bd9Sstevel@tonic-gate * really no undo-ing to be done. 421*7c478bd9Sstevel@tonic-gate */ 422*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(mpf, &pgno, 0, &pp)) != 0) { 423*7c478bd9Sstevel@tonic-gate pp = NULL; 424*7c478bd9Sstevel@tonic-gate goto lrundo; 425*7c478bd9Sstevel@tonic-gate } 426*7c478bd9Sstevel@tonic-gate if (log_compare(lsnp, &LSN(pp)) == 0) { 427*7c478bd9Sstevel@tonic-gate memcpy(pp, argp->pg.data, argp->pg.size); 428*7c478bd9Sstevel@tonic-gate if ((ret = memp_fput(mpf, pp, DB_MPOOL_DIRTY)) != 0) 429*7c478bd9Sstevel@tonic-gate goto out; 430*7c478bd9Sstevel@tonic-gate pp = NULL; 431*7c478bd9Sstevel@tonic-gate } 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate /* 434*7c478bd9Sstevel@tonic-gate * If it's a root split and the left child ever existed, update 435*7c478bd9Sstevel@tonic-gate * its LSN. (If it's not a root split, we've updated the left 436*7c478bd9Sstevel@tonic-gate * page already -- it's the same as the split page.) If the 437*7c478bd9Sstevel@tonic-gate * right child ever existed, root split or not, update its LSN. 438*7c478bd9Sstevel@tonic-gate * The undo of the page allocation(s) will restore them to the 439*7c478bd9Sstevel@tonic-gate * free list. 440*7c478bd9Sstevel@tonic-gate */ 441*7c478bd9Sstevel@tonic-gate lrundo: if ((rootsplit && lp != NULL) || rp != NULL) { 442*7c478bd9Sstevel@tonic-gate if (rootsplit && lp != NULL && 443*7c478bd9Sstevel@tonic-gate log_compare(lsnp, &LSN(lp)) == 0) { 444*7c478bd9Sstevel@tonic-gate lp->lsn = argp->llsn; 445*7c478bd9Sstevel@tonic-gate if ((ret = 446*7c478bd9Sstevel@tonic-gate memp_fput(mpf, lp, DB_MPOOL_DIRTY)) != 0) 447*7c478bd9Sstevel@tonic-gate goto out; 448*7c478bd9Sstevel@tonic-gate lp = NULL; 449*7c478bd9Sstevel@tonic-gate } 450*7c478bd9Sstevel@tonic-gate if (rp != NULL && 451*7c478bd9Sstevel@tonic-gate log_compare(lsnp, &LSN(rp)) == 0) { 452*7c478bd9Sstevel@tonic-gate rp->lsn = argp->rlsn; 453*7c478bd9Sstevel@tonic-gate if ((ret = 454*7c478bd9Sstevel@tonic-gate memp_fput(mpf, rp, DB_MPOOL_DIRTY)) != 0) 455*7c478bd9Sstevel@tonic-gate goto out; 456*7c478bd9Sstevel@tonic-gate rp = NULL; 457*7c478bd9Sstevel@tonic-gate } 458*7c478bd9Sstevel@tonic-gate } 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate /* 461*7c478bd9Sstevel@tonic-gate * Finally, undo the next-page link if necessary. This is of 462*7c478bd9Sstevel@tonic-gate * interest only if it wasn't a root split -- inserting a new 463*7c478bd9Sstevel@tonic-gate * page in the tree requires that any following page have its 464*7c478bd9Sstevel@tonic-gate * previous-page pointer updated to our new page. Since it's 465*7c478bd9Sstevel@tonic-gate * possible that the next-page never existed, we ignore it as 466*7c478bd9Sstevel@tonic-gate * if there's nothing to undo. 467*7c478bd9Sstevel@tonic-gate */ 468*7c478bd9Sstevel@tonic-gate if (!rootsplit && !IS_ZERO_LSN(argp->nlsn)) { 469*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(mpf, &argp->npgno, 0, &np)) != 0) { 470*7c478bd9Sstevel@tonic-gate np = NULL; 471*7c478bd9Sstevel@tonic-gate goto done; 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate if (log_compare(lsnp, &LSN(np)) == 0) { 474*7c478bd9Sstevel@tonic-gate PREV_PGNO(np) = argp->left; 475*7c478bd9Sstevel@tonic-gate np->lsn = argp->nlsn; 476*7c478bd9Sstevel@tonic-gate if (memp_fput(mpf, np, DB_MPOOL_DIRTY)) 477*7c478bd9Sstevel@tonic-gate goto out; 478*7c478bd9Sstevel@tonic-gate np = NULL; 479*7c478bd9Sstevel@tonic-gate } 480*7c478bd9Sstevel@tonic-gate } 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate done: *lsnp = argp->prev_lsn; 484*7c478bd9Sstevel@tonic-gate ret = 0; 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate out: /* Free any pages that weren't dirtied. */ 487*7c478bd9Sstevel@tonic-gate if (pp != NULL && (t_ret = memp_fput(mpf, pp, 0)) != 0 && ret == 0) 488*7c478bd9Sstevel@tonic-gate ret = t_ret; 489*7c478bd9Sstevel@tonic-gate if (lp != NULL && (t_ret = memp_fput(mpf, lp, 0)) != 0 && ret == 0) 490*7c478bd9Sstevel@tonic-gate ret = t_ret; 491*7c478bd9Sstevel@tonic-gate if (np != NULL && (t_ret = memp_fput(mpf, np, 0)) != 0 && ret == 0) 492*7c478bd9Sstevel@tonic-gate ret = t_ret; 493*7c478bd9Sstevel@tonic-gate if (rp != NULL && (t_ret = memp_fput(mpf, rp, 0)) != 0 && ret == 0) 494*7c478bd9Sstevel@tonic-gate ret = t_ret; 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate /* Free any allocated space. */ 497*7c478bd9Sstevel@tonic-gate if (_lp != NULL) 498*7c478bd9Sstevel@tonic-gate __os_free(_lp, file_dbp->pgsize); 499*7c478bd9Sstevel@tonic-gate if (_rp != NULL) 500*7c478bd9Sstevel@tonic-gate __os_free(_rp, file_dbp->pgsize); 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate REC_CLOSE; 503*7c478bd9Sstevel@tonic-gate } 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate /* 506*7c478bd9Sstevel@tonic-gate * __bam_rsplit_recover -- 507*7c478bd9Sstevel@tonic-gate * Recovery function for a reverse split. 508*7c478bd9Sstevel@tonic-gate * 509*7c478bd9Sstevel@tonic-gate * PUBLIC: int __bam_rsplit_recover 510*7c478bd9Sstevel@tonic-gate * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); 511*7c478bd9Sstevel@tonic-gate */ 512*7c478bd9Sstevel@tonic-gate int 513*7c478bd9Sstevel@tonic-gate __bam_rsplit_recover(logp, dbtp, lsnp, redo, info) 514*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 515*7c478bd9Sstevel@tonic-gate DBT *dbtp; 516*7c478bd9Sstevel@tonic-gate DB_LSN *lsnp; 517*7c478bd9Sstevel@tonic-gate int redo; 518*7c478bd9Sstevel@tonic-gate void *info; 519*7c478bd9Sstevel@tonic-gate { 520*7c478bd9Sstevel@tonic-gate __bam_rsplit_args *argp; 521*7c478bd9Sstevel@tonic-gate DB *file_dbp; 522*7c478bd9Sstevel@tonic-gate DBC *dbc; 523*7c478bd9Sstevel@tonic-gate DB_MPOOLFILE *mpf; 524*7c478bd9Sstevel@tonic-gate PAGE *pagep; 525*7c478bd9Sstevel@tonic-gate db_pgno_t pgno; 526*7c478bd9Sstevel@tonic-gate int cmp_n, cmp_p, modified, ret; 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate REC_PRINT(__bam_rsplit_print); 529*7c478bd9Sstevel@tonic-gate REC_INTRO(__bam_rsplit_read); 530*7c478bd9Sstevel@tonic-gate 531*7c478bd9Sstevel@tonic-gate /* Fix the root page. */ 532*7c478bd9Sstevel@tonic-gate pgno = PGNO_ROOT; 533*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(mpf, &pgno, 0, &pagep)) != 0) { 534*7c478bd9Sstevel@tonic-gate /* The root page must always exist. */ 535*7c478bd9Sstevel@tonic-gate __db_pgerr(file_dbp, pgno); 536*7c478bd9Sstevel@tonic-gate goto out; 537*7c478bd9Sstevel@tonic-gate } 538*7c478bd9Sstevel@tonic-gate modified = 0; 539*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &LSN(pagep)); 540*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&LSN(pagep), &argp->rootlsn); 541*7c478bd9Sstevel@tonic-gate if (cmp_p == 0 && redo) { 542*7c478bd9Sstevel@tonic-gate /* Need to redo update described. */ 543*7c478bd9Sstevel@tonic-gate memcpy(pagep, argp->pgdbt.data, argp->pgdbt.size); 544*7c478bd9Sstevel@tonic-gate pagep->pgno = PGNO_ROOT; 545*7c478bd9Sstevel@tonic-gate pagep->lsn = *lsnp; 546*7c478bd9Sstevel@tonic-gate modified = 1; 547*7c478bd9Sstevel@tonic-gate } else if (cmp_n == 0 && !redo) { 548*7c478bd9Sstevel@tonic-gate /* Need to undo update described. */ 549*7c478bd9Sstevel@tonic-gate P_INIT(pagep, file_dbp->pgsize, PGNO_ROOT, 550*7c478bd9Sstevel@tonic-gate argp->nrec, PGNO_INVALID, pagep->level + 1, 551*7c478bd9Sstevel@tonic-gate file_dbp->type == DB_BTREE ? P_IBTREE : P_IRECNO); 552*7c478bd9Sstevel@tonic-gate if ((ret = __db_pitem(dbc, pagep, 0, 553*7c478bd9Sstevel@tonic-gate argp->rootent.size, &argp->rootent, NULL)) != 0) 554*7c478bd9Sstevel@tonic-gate goto out; 555*7c478bd9Sstevel@tonic-gate pagep->lsn = argp->rootlsn; 556*7c478bd9Sstevel@tonic-gate modified = 1; 557*7c478bd9Sstevel@tonic-gate } 558*7c478bd9Sstevel@tonic-gate if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) 559*7c478bd9Sstevel@tonic-gate goto out; 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate /* 562*7c478bd9Sstevel@tonic-gate * Fix the page copied over the root page. It's possible that the 563*7c478bd9Sstevel@tonic-gate * page never made it to disk, so if we're undo-ing and the page 564*7c478bd9Sstevel@tonic-gate * doesn't exist, it's okay and there's nothing further to do. 565*7c478bd9Sstevel@tonic-gate */ 566*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { 567*7c478bd9Sstevel@tonic-gate if (!redo) 568*7c478bd9Sstevel@tonic-gate goto done; 569*7c478bd9Sstevel@tonic-gate (void)__db_pgerr(file_dbp, argp->pgno); 570*7c478bd9Sstevel@tonic-gate goto out; 571*7c478bd9Sstevel@tonic-gate } 572*7c478bd9Sstevel@tonic-gate modified = 0; 573*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &LSN(pagep)); 574*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&LSN(pagep), &LSN(argp->pgdbt.data)); 575*7c478bd9Sstevel@tonic-gate if (cmp_p == 0 && redo) { 576*7c478bd9Sstevel@tonic-gate /* Need to redo update described. */ 577*7c478bd9Sstevel@tonic-gate pagep->lsn = *lsnp; 578*7c478bd9Sstevel@tonic-gate modified = 1; 579*7c478bd9Sstevel@tonic-gate } else if (cmp_n == 0 && !redo) { 580*7c478bd9Sstevel@tonic-gate /* Need to undo update described. */ 581*7c478bd9Sstevel@tonic-gate memcpy(pagep, argp->pgdbt.data, argp->pgdbt.size); 582*7c478bd9Sstevel@tonic-gate modified = 1; 583*7c478bd9Sstevel@tonic-gate } 584*7c478bd9Sstevel@tonic-gate if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) 585*7c478bd9Sstevel@tonic-gate goto out; 586*7c478bd9Sstevel@tonic-gate 587*7c478bd9Sstevel@tonic-gate done: *lsnp = argp->prev_lsn; 588*7c478bd9Sstevel@tonic-gate ret = 0; 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate out: REC_CLOSE; 591*7c478bd9Sstevel@tonic-gate } 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate /* 594*7c478bd9Sstevel@tonic-gate * __bam_adj_recover -- 595*7c478bd9Sstevel@tonic-gate * Recovery function for adj. 596*7c478bd9Sstevel@tonic-gate * 597*7c478bd9Sstevel@tonic-gate * PUBLIC: int __bam_adj_recover 598*7c478bd9Sstevel@tonic-gate * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); 599*7c478bd9Sstevel@tonic-gate */ 600*7c478bd9Sstevel@tonic-gate int 601*7c478bd9Sstevel@tonic-gate __bam_adj_recover(logp, dbtp, lsnp, redo, info) 602*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 603*7c478bd9Sstevel@tonic-gate DBT *dbtp; 604*7c478bd9Sstevel@tonic-gate DB_LSN *lsnp; 605*7c478bd9Sstevel@tonic-gate int redo; 606*7c478bd9Sstevel@tonic-gate void *info; 607*7c478bd9Sstevel@tonic-gate { 608*7c478bd9Sstevel@tonic-gate __bam_adj_args *argp; 609*7c478bd9Sstevel@tonic-gate DB *file_dbp; 610*7c478bd9Sstevel@tonic-gate DBC *dbc; 611*7c478bd9Sstevel@tonic-gate DB_MPOOLFILE *mpf; 612*7c478bd9Sstevel@tonic-gate PAGE *pagep; 613*7c478bd9Sstevel@tonic-gate int cmp_n, cmp_p, modified, ret; 614*7c478bd9Sstevel@tonic-gate 615*7c478bd9Sstevel@tonic-gate REC_PRINT(__bam_adj_print); 616*7c478bd9Sstevel@tonic-gate REC_INTRO(__bam_adj_read); 617*7c478bd9Sstevel@tonic-gate 618*7c478bd9Sstevel@tonic-gate /* Get the page; if it never existed and we're undoing, we're done. */ 619*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { 620*7c478bd9Sstevel@tonic-gate if (!redo) 621*7c478bd9Sstevel@tonic-gate goto done; 622*7c478bd9Sstevel@tonic-gate (void)__db_pgerr(file_dbp, argp->pgno); 623*7c478bd9Sstevel@tonic-gate goto out; 624*7c478bd9Sstevel@tonic-gate } 625*7c478bd9Sstevel@tonic-gate 626*7c478bd9Sstevel@tonic-gate modified = 0; 627*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &LSN(pagep)); 628*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&LSN(pagep), &argp->lsn); 629*7c478bd9Sstevel@tonic-gate if (cmp_p == 0 && redo) { 630*7c478bd9Sstevel@tonic-gate /* Need to redo update described. */ 631*7c478bd9Sstevel@tonic-gate if ((ret = __bam_adjindx(dbc, 632*7c478bd9Sstevel@tonic-gate pagep, argp->indx, argp->indx_copy, argp->is_insert)) != 0) 633*7c478bd9Sstevel@tonic-gate goto err; 634*7c478bd9Sstevel@tonic-gate 635*7c478bd9Sstevel@tonic-gate LSN(pagep) = *lsnp; 636*7c478bd9Sstevel@tonic-gate modified = 1; 637*7c478bd9Sstevel@tonic-gate } else if (cmp_n == 0 && !redo) { 638*7c478bd9Sstevel@tonic-gate /* Need to undo update described. */ 639*7c478bd9Sstevel@tonic-gate if ((ret = __bam_adjindx(dbc, 640*7c478bd9Sstevel@tonic-gate pagep, argp->indx, argp->indx_copy, !argp->is_insert)) != 0) 641*7c478bd9Sstevel@tonic-gate goto err; 642*7c478bd9Sstevel@tonic-gate 643*7c478bd9Sstevel@tonic-gate LSN(pagep) = argp->lsn; 644*7c478bd9Sstevel@tonic-gate modified = 1; 645*7c478bd9Sstevel@tonic-gate } 646*7c478bd9Sstevel@tonic-gate if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) 647*7c478bd9Sstevel@tonic-gate goto out; 648*7c478bd9Sstevel@tonic-gate 649*7c478bd9Sstevel@tonic-gate done: *lsnp = argp->prev_lsn; 650*7c478bd9Sstevel@tonic-gate ret = 0; 651*7c478bd9Sstevel@tonic-gate 652*7c478bd9Sstevel@tonic-gate if (0) { 653*7c478bd9Sstevel@tonic-gate err: (void)memp_fput(mpf, pagep, 0); 654*7c478bd9Sstevel@tonic-gate } 655*7c478bd9Sstevel@tonic-gate out: REC_CLOSE; 656*7c478bd9Sstevel@tonic-gate } 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate /* 659*7c478bd9Sstevel@tonic-gate * __bam_cadjust_recover -- 660*7c478bd9Sstevel@tonic-gate * Recovery function for the adjust of a count change in an internal 661*7c478bd9Sstevel@tonic-gate * page. 662*7c478bd9Sstevel@tonic-gate * 663*7c478bd9Sstevel@tonic-gate * PUBLIC: int __bam_cadjust_recover 664*7c478bd9Sstevel@tonic-gate * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); 665*7c478bd9Sstevel@tonic-gate */ 666*7c478bd9Sstevel@tonic-gate int 667*7c478bd9Sstevel@tonic-gate __bam_cadjust_recover(logp, dbtp, lsnp, redo, info) 668*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 669*7c478bd9Sstevel@tonic-gate DBT *dbtp; 670*7c478bd9Sstevel@tonic-gate DB_LSN *lsnp; 671*7c478bd9Sstevel@tonic-gate int redo; 672*7c478bd9Sstevel@tonic-gate void *info; 673*7c478bd9Sstevel@tonic-gate { 674*7c478bd9Sstevel@tonic-gate __bam_cadjust_args *argp; 675*7c478bd9Sstevel@tonic-gate DB *file_dbp; 676*7c478bd9Sstevel@tonic-gate DBC *dbc; 677*7c478bd9Sstevel@tonic-gate DB_MPOOLFILE *mpf; 678*7c478bd9Sstevel@tonic-gate PAGE *pagep; 679*7c478bd9Sstevel@tonic-gate int cmp_n, cmp_p, modified, ret; 680*7c478bd9Sstevel@tonic-gate 681*7c478bd9Sstevel@tonic-gate REC_PRINT(__bam_cadjust_print); 682*7c478bd9Sstevel@tonic-gate REC_INTRO(__bam_cadjust_read); 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate /* Get the page; if it never existed and we're undoing, we're done. */ 685*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { 686*7c478bd9Sstevel@tonic-gate if (!redo) 687*7c478bd9Sstevel@tonic-gate goto done; 688*7c478bd9Sstevel@tonic-gate (void)__db_pgerr(file_dbp, argp->pgno); 689*7c478bd9Sstevel@tonic-gate goto out; 690*7c478bd9Sstevel@tonic-gate } 691*7c478bd9Sstevel@tonic-gate 692*7c478bd9Sstevel@tonic-gate modified = 0; 693*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &LSN(pagep)); 694*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&LSN(pagep), &argp->lsn); 695*7c478bd9Sstevel@tonic-gate if (cmp_p == 0 && redo) { 696*7c478bd9Sstevel@tonic-gate /* Need to redo update described. */ 697*7c478bd9Sstevel@tonic-gate if (file_dbp->type == DB_BTREE && 698*7c478bd9Sstevel@tonic-gate F_ISSET(file_dbp, DB_BT_RECNUM)) { 699*7c478bd9Sstevel@tonic-gate GET_BINTERNAL(pagep, argp->indx)->nrecs += argp->adjust; 700*7c478bd9Sstevel@tonic-gate if (argp->total && PGNO(pagep) == PGNO_ROOT) 701*7c478bd9Sstevel@tonic-gate RE_NREC_ADJ(pagep, argp->adjust); 702*7c478bd9Sstevel@tonic-gate } 703*7c478bd9Sstevel@tonic-gate if (file_dbp->type == DB_RECNO) { 704*7c478bd9Sstevel@tonic-gate GET_RINTERNAL(pagep, argp->indx)->nrecs += argp->adjust; 705*7c478bd9Sstevel@tonic-gate if (argp->total && PGNO(pagep) == PGNO_ROOT) 706*7c478bd9Sstevel@tonic-gate RE_NREC_ADJ(pagep, argp->adjust); 707*7c478bd9Sstevel@tonic-gate } 708*7c478bd9Sstevel@tonic-gate 709*7c478bd9Sstevel@tonic-gate LSN(pagep) = *lsnp; 710*7c478bd9Sstevel@tonic-gate modified = 1; 711*7c478bd9Sstevel@tonic-gate } else if (cmp_n == 0 && !redo) { 712*7c478bd9Sstevel@tonic-gate /* Need to undo update described. */ 713*7c478bd9Sstevel@tonic-gate if (file_dbp->type == DB_BTREE && 714*7c478bd9Sstevel@tonic-gate F_ISSET(file_dbp, DB_BT_RECNUM)) { 715*7c478bd9Sstevel@tonic-gate GET_BINTERNAL(pagep, argp->indx)->nrecs -= argp->adjust; 716*7c478bd9Sstevel@tonic-gate if (argp->total && PGNO(pagep) == PGNO_ROOT) 717*7c478bd9Sstevel@tonic-gate RE_NREC_ADJ(pagep, argp->adjust); 718*7c478bd9Sstevel@tonic-gate } 719*7c478bd9Sstevel@tonic-gate if (file_dbp->type == DB_RECNO) { 720*7c478bd9Sstevel@tonic-gate GET_RINTERNAL(pagep, argp->indx)->nrecs -= argp->adjust; 721*7c478bd9Sstevel@tonic-gate if (argp->total && PGNO(pagep) == PGNO_ROOT) 722*7c478bd9Sstevel@tonic-gate RE_NREC_ADJ(pagep, -(argp->adjust)); 723*7c478bd9Sstevel@tonic-gate } 724*7c478bd9Sstevel@tonic-gate LSN(pagep) = argp->lsn; 725*7c478bd9Sstevel@tonic-gate modified = 1; 726*7c478bd9Sstevel@tonic-gate } 727*7c478bd9Sstevel@tonic-gate if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) 728*7c478bd9Sstevel@tonic-gate goto out; 729*7c478bd9Sstevel@tonic-gate 730*7c478bd9Sstevel@tonic-gate done: *lsnp = argp->prev_lsn; 731*7c478bd9Sstevel@tonic-gate ret = 0; 732*7c478bd9Sstevel@tonic-gate 733*7c478bd9Sstevel@tonic-gate out: REC_CLOSE; 734*7c478bd9Sstevel@tonic-gate } 735*7c478bd9Sstevel@tonic-gate 736*7c478bd9Sstevel@tonic-gate /* 737*7c478bd9Sstevel@tonic-gate * __bam_cdel_recover -- 738*7c478bd9Sstevel@tonic-gate * Recovery function for the intent-to-delete of a cursor record. 739*7c478bd9Sstevel@tonic-gate * 740*7c478bd9Sstevel@tonic-gate * PUBLIC: int __bam_cdel_recover 741*7c478bd9Sstevel@tonic-gate * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); 742*7c478bd9Sstevel@tonic-gate */ 743*7c478bd9Sstevel@tonic-gate int 744*7c478bd9Sstevel@tonic-gate __bam_cdel_recover(logp, dbtp, lsnp, redo, info) 745*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 746*7c478bd9Sstevel@tonic-gate DBT *dbtp; 747*7c478bd9Sstevel@tonic-gate DB_LSN *lsnp; 748*7c478bd9Sstevel@tonic-gate int redo; 749*7c478bd9Sstevel@tonic-gate void *info; 750*7c478bd9Sstevel@tonic-gate { 751*7c478bd9Sstevel@tonic-gate __bam_cdel_args *argp; 752*7c478bd9Sstevel@tonic-gate DB *file_dbp; 753*7c478bd9Sstevel@tonic-gate DBC *dbc; 754*7c478bd9Sstevel@tonic-gate DB_MPOOLFILE *mpf; 755*7c478bd9Sstevel@tonic-gate PAGE *pagep; 756*7c478bd9Sstevel@tonic-gate int cmp_n, cmp_p, modified, ret; 757*7c478bd9Sstevel@tonic-gate 758*7c478bd9Sstevel@tonic-gate REC_PRINT(__bam_cdel_print); 759*7c478bd9Sstevel@tonic-gate REC_INTRO(__bam_cdel_read); 760*7c478bd9Sstevel@tonic-gate 761*7c478bd9Sstevel@tonic-gate /* Get the page; if it never existed and we're undoing, we're done. */ 762*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { 763*7c478bd9Sstevel@tonic-gate if (!redo) 764*7c478bd9Sstevel@tonic-gate goto done; 765*7c478bd9Sstevel@tonic-gate (void)__db_pgerr(file_dbp, argp->pgno); 766*7c478bd9Sstevel@tonic-gate goto out; 767*7c478bd9Sstevel@tonic-gate } 768*7c478bd9Sstevel@tonic-gate 769*7c478bd9Sstevel@tonic-gate modified = 0; 770*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &LSN(pagep)); 771*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&LSN(pagep), &argp->lsn); 772*7c478bd9Sstevel@tonic-gate if (cmp_p == 0 && redo) { 773*7c478bd9Sstevel@tonic-gate /* Need to redo update described. */ 774*7c478bd9Sstevel@tonic-gate if (pagep->type == P_DUPLICATE) 775*7c478bd9Sstevel@tonic-gate B_DSET(GET_BKEYDATA(pagep, argp->indx)->type); 776*7c478bd9Sstevel@tonic-gate else 777*7c478bd9Sstevel@tonic-gate B_DSET(GET_BKEYDATA(pagep, argp->indx + O_INDX)->type); 778*7c478bd9Sstevel@tonic-gate 779*7c478bd9Sstevel@tonic-gate LSN(pagep) = *lsnp; 780*7c478bd9Sstevel@tonic-gate modified = 1; 781*7c478bd9Sstevel@tonic-gate } else if (cmp_n == 0 && !redo) { 782*7c478bd9Sstevel@tonic-gate /* Need to undo update described. */ 783*7c478bd9Sstevel@tonic-gate if (pagep->type == P_DUPLICATE) 784*7c478bd9Sstevel@tonic-gate B_DCLR(GET_BKEYDATA(pagep, argp->indx)->type); 785*7c478bd9Sstevel@tonic-gate else 786*7c478bd9Sstevel@tonic-gate B_DCLR(GET_BKEYDATA(pagep, argp->indx + O_INDX)->type); 787*7c478bd9Sstevel@tonic-gate 788*7c478bd9Sstevel@tonic-gate LSN(pagep) = argp->lsn; 789*7c478bd9Sstevel@tonic-gate modified = 1; 790*7c478bd9Sstevel@tonic-gate } 791*7c478bd9Sstevel@tonic-gate if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) 792*7c478bd9Sstevel@tonic-gate goto out; 793*7c478bd9Sstevel@tonic-gate 794*7c478bd9Sstevel@tonic-gate done: *lsnp = argp->prev_lsn; 795*7c478bd9Sstevel@tonic-gate ret = 0; 796*7c478bd9Sstevel@tonic-gate 797*7c478bd9Sstevel@tonic-gate out: REC_CLOSE; 798*7c478bd9Sstevel@tonic-gate } 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate /* 801*7c478bd9Sstevel@tonic-gate * __bam_repl_recover -- 802*7c478bd9Sstevel@tonic-gate * Recovery function for page item replacement. 803*7c478bd9Sstevel@tonic-gate * 804*7c478bd9Sstevel@tonic-gate * PUBLIC: int __bam_repl_recover 805*7c478bd9Sstevel@tonic-gate * PUBLIC: __P((DB_LOG *, DBT *, DB_LSN *, int, void *)); 806*7c478bd9Sstevel@tonic-gate */ 807*7c478bd9Sstevel@tonic-gate int 808*7c478bd9Sstevel@tonic-gate __bam_repl_recover(logp, dbtp, lsnp, redo, info) 809*7c478bd9Sstevel@tonic-gate DB_LOG *logp; 810*7c478bd9Sstevel@tonic-gate DBT *dbtp; 811*7c478bd9Sstevel@tonic-gate DB_LSN *lsnp; 812*7c478bd9Sstevel@tonic-gate int redo; 813*7c478bd9Sstevel@tonic-gate void *info; 814*7c478bd9Sstevel@tonic-gate { 815*7c478bd9Sstevel@tonic-gate __bam_repl_args *argp; 816*7c478bd9Sstevel@tonic-gate BKEYDATA *bk; 817*7c478bd9Sstevel@tonic-gate DB *file_dbp; 818*7c478bd9Sstevel@tonic-gate DBC *dbc; 819*7c478bd9Sstevel@tonic-gate DBT dbt; 820*7c478bd9Sstevel@tonic-gate DB_MPOOLFILE *mpf; 821*7c478bd9Sstevel@tonic-gate PAGE *pagep; 822*7c478bd9Sstevel@tonic-gate int cmp_n, cmp_p, modified, ret; 823*7c478bd9Sstevel@tonic-gate u_int8_t *p; 824*7c478bd9Sstevel@tonic-gate 825*7c478bd9Sstevel@tonic-gate REC_PRINT(__bam_repl_print); 826*7c478bd9Sstevel@tonic-gate REC_INTRO(__bam_repl_read); 827*7c478bd9Sstevel@tonic-gate 828*7c478bd9Sstevel@tonic-gate /* Get the page; if it never existed and we're undoing, we're done. */ 829*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { 830*7c478bd9Sstevel@tonic-gate if (!redo) 831*7c478bd9Sstevel@tonic-gate goto done; 832*7c478bd9Sstevel@tonic-gate (void)__db_pgerr(file_dbp, argp->pgno); 833*7c478bd9Sstevel@tonic-gate goto out; 834*7c478bd9Sstevel@tonic-gate } 835*7c478bd9Sstevel@tonic-gate bk = GET_BKEYDATA(pagep, argp->indx); 836*7c478bd9Sstevel@tonic-gate 837*7c478bd9Sstevel@tonic-gate modified = 0; 838*7c478bd9Sstevel@tonic-gate cmp_n = log_compare(lsnp, &LSN(pagep)); 839*7c478bd9Sstevel@tonic-gate cmp_p = log_compare(&LSN(pagep), &argp->lsn); 840*7c478bd9Sstevel@tonic-gate if (cmp_p == 0 && redo) { 841*7c478bd9Sstevel@tonic-gate /* 842*7c478bd9Sstevel@tonic-gate * Need to redo update described. 843*7c478bd9Sstevel@tonic-gate * 844*7c478bd9Sstevel@tonic-gate * Re-build the replacement item. 845*7c478bd9Sstevel@tonic-gate */ 846*7c478bd9Sstevel@tonic-gate memset(&dbt, 0, sizeof(dbt)); 847*7c478bd9Sstevel@tonic-gate dbt.size = argp->prefix + argp->suffix + argp->repl.size; 848*7c478bd9Sstevel@tonic-gate if ((ret = __os_malloc(dbt.size, NULL, &dbt.data)) != 0) 849*7c478bd9Sstevel@tonic-gate goto err; 850*7c478bd9Sstevel@tonic-gate p = dbt.data; 851*7c478bd9Sstevel@tonic-gate memcpy(p, bk->data, argp->prefix); 852*7c478bd9Sstevel@tonic-gate p += argp->prefix; 853*7c478bd9Sstevel@tonic-gate memcpy(p, argp->repl.data, argp->repl.size); 854*7c478bd9Sstevel@tonic-gate p += argp->repl.size; 855*7c478bd9Sstevel@tonic-gate memcpy(p, bk->data + (bk->len - argp->suffix), argp->suffix); 856*7c478bd9Sstevel@tonic-gate 857*7c478bd9Sstevel@tonic-gate ret = __bam_ritem(dbc, pagep, argp->indx, &dbt); 858*7c478bd9Sstevel@tonic-gate __os_free(dbt.data, dbt.size); 859*7c478bd9Sstevel@tonic-gate if (ret != 0) 860*7c478bd9Sstevel@tonic-gate goto err; 861*7c478bd9Sstevel@tonic-gate 862*7c478bd9Sstevel@tonic-gate LSN(pagep) = *lsnp; 863*7c478bd9Sstevel@tonic-gate modified = 1; 864*7c478bd9Sstevel@tonic-gate } else if (cmp_n == 0 && !redo) { 865*7c478bd9Sstevel@tonic-gate /* 866*7c478bd9Sstevel@tonic-gate * Need to undo update described. 867*7c478bd9Sstevel@tonic-gate * 868*7c478bd9Sstevel@tonic-gate * Re-build the original item. 869*7c478bd9Sstevel@tonic-gate */ 870*7c478bd9Sstevel@tonic-gate memset(&dbt, 0, sizeof(dbt)); 871*7c478bd9Sstevel@tonic-gate dbt.size = argp->prefix + argp->suffix + argp->orig.size; 872*7c478bd9Sstevel@tonic-gate if ((ret = __os_malloc(dbt.size, NULL, &dbt.data)) != 0) 873*7c478bd9Sstevel@tonic-gate goto err; 874*7c478bd9Sstevel@tonic-gate p = dbt.data; 875*7c478bd9Sstevel@tonic-gate memcpy(p, bk->data, argp->prefix); 876*7c478bd9Sstevel@tonic-gate p += argp->prefix; 877*7c478bd9Sstevel@tonic-gate memcpy(p, argp->orig.data, argp->orig.size); 878*7c478bd9Sstevel@tonic-gate p += argp->orig.size; 879*7c478bd9Sstevel@tonic-gate memcpy(p, bk->data + (bk->len - argp->suffix), argp->suffix); 880*7c478bd9Sstevel@tonic-gate 881*7c478bd9Sstevel@tonic-gate ret = __bam_ritem(dbc, pagep, argp->indx, &dbt); 882*7c478bd9Sstevel@tonic-gate __os_free(dbt.data, dbt.size); 883*7c478bd9Sstevel@tonic-gate if (ret != 0) 884*7c478bd9Sstevel@tonic-gate goto err; 885*7c478bd9Sstevel@tonic-gate 886*7c478bd9Sstevel@tonic-gate /* Reset the deleted flag, if necessary. */ 887*7c478bd9Sstevel@tonic-gate if (argp->isdeleted) 888*7c478bd9Sstevel@tonic-gate B_DSET(GET_BKEYDATA(pagep, argp->indx)->type); 889*7c478bd9Sstevel@tonic-gate 890*7c478bd9Sstevel@tonic-gate LSN(pagep) = argp->lsn; 891*7c478bd9Sstevel@tonic-gate modified = 1; 892*7c478bd9Sstevel@tonic-gate } 893*7c478bd9Sstevel@tonic-gate if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) 894*7c478bd9Sstevel@tonic-gate goto out; 895*7c478bd9Sstevel@tonic-gate 896*7c478bd9Sstevel@tonic-gate done: *lsnp = argp->prev_lsn; 897*7c478bd9Sstevel@tonic-gate ret = 0; 898*7c478bd9Sstevel@tonic-gate 899*7c478bd9Sstevel@tonic-gate if (0) { 900*7c478bd9Sstevel@tonic-gate err: (void)memp_fput(mpf, pagep, 0); 901*7c478bd9Sstevel@tonic-gate } 902*7c478bd9Sstevel@tonic-gate out: REC_CLOSE; 903*7c478bd9Sstevel@tonic-gate } 904