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 #pragma ident "%Z%%M% %I% %E% SMI" 9*7c478bd9Sstevel@tonic-gate 10*7c478bd9Sstevel@tonic-gate #include "config.h" 11*7c478bd9Sstevel@tonic-gate 12*7c478bd9Sstevel@tonic-gate #ifndef lint 13*7c478bd9Sstevel@tonic-gate static const char sccsid[] = "@(#)bt_curadj.c 10.69 (Sleepycat) 12/2/98"; 14*7c478bd9Sstevel@tonic-gate #endif /* not lint */ 15*7c478bd9Sstevel@tonic-gate 16*7c478bd9Sstevel@tonic-gate #ifndef NO_SYSTEM_INCLUDES 17*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 18*7c478bd9Sstevel@tonic-gate 19*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 20*7c478bd9Sstevel@tonic-gate #endif 21*7c478bd9Sstevel@tonic-gate 22*7c478bd9Sstevel@tonic-gate #include "db_int.h" 23*7c478bd9Sstevel@tonic-gate #include "db_page.h" 24*7c478bd9Sstevel@tonic-gate #include "btree.h" 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 27*7c478bd9Sstevel@tonic-gate /* 28*7c478bd9Sstevel@tonic-gate * __bam_cprint -- 29*7c478bd9Sstevel@tonic-gate * Display the current cursor list. 30*7c478bd9Sstevel@tonic-gate * 31*7c478bd9Sstevel@tonic-gate * PUBLIC: int __bam_cprint __P((DB *)); 32*7c478bd9Sstevel@tonic-gate */ 33*7c478bd9Sstevel@tonic-gate int 34*7c478bd9Sstevel@tonic-gate __bam_cprint(dbp) 35*7c478bd9Sstevel@tonic-gate DB *dbp; 36*7c478bd9Sstevel@tonic-gate { 37*7c478bd9Sstevel@tonic-gate CURSOR *cp; 38*7c478bd9Sstevel@tonic-gate DBC *dbc; 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate DB_THREAD_LOCK(dbp); 41*7c478bd9Sstevel@tonic-gate for (dbc = TAILQ_FIRST(&dbp->active_queue); 42*7c478bd9Sstevel@tonic-gate dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { 43*7c478bd9Sstevel@tonic-gate cp = (CURSOR *)dbc->internal; 44*7c478bd9Sstevel@tonic-gate fprintf(stderr, 45*7c478bd9Sstevel@tonic-gate "%#0x->%#0x: page: %lu index: %lu dpage %lu dindex: %lu recno: %lu", 46*7c478bd9Sstevel@tonic-gate (u_int)dbc, (u_int)cp, (u_long)cp->pgno, (u_long)cp->indx, 47*7c478bd9Sstevel@tonic-gate (u_long)cp->dpgno, (u_long)cp->dindx, (u_long)cp->recno); 48*7c478bd9Sstevel@tonic-gate if (F_ISSET(cp, C_DELETED)) 49*7c478bd9Sstevel@tonic-gate fprintf(stderr, " (deleted)"); 50*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 51*7c478bd9Sstevel@tonic-gate } 52*7c478bd9Sstevel@tonic-gate DB_THREAD_UNLOCK(dbp); 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate return (0); 55*7c478bd9Sstevel@tonic-gate } 56*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate /* 59*7c478bd9Sstevel@tonic-gate * __bam_ca_delete -- 60*7c478bd9Sstevel@tonic-gate * Update the cursors when items are deleted and when already deleted 61*7c478bd9Sstevel@tonic-gate * items are overwritten. Return the number of relevant cursors found. 62*7c478bd9Sstevel@tonic-gate * 63*7c478bd9Sstevel@tonic-gate * PUBLIC: int __bam_ca_delete __P((DB *, db_pgno_t, u_int32_t, int)); 64*7c478bd9Sstevel@tonic-gate */ 65*7c478bd9Sstevel@tonic-gate int 66*7c478bd9Sstevel@tonic-gate __bam_ca_delete(dbp, pgno, indx, delete) 67*7c478bd9Sstevel@tonic-gate DB *dbp; 68*7c478bd9Sstevel@tonic-gate db_pgno_t pgno; 69*7c478bd9Sstevel@tonic-gate u_int32_t indx; 70*7c478bd9Sstevel@tonic-gate int delete; 71*7c478bd9Sstevel@tonic-gate { 72*7c478bd9Sstevel@tonic-gate DBC *dbc; 73*7c478bd9Sstevel@tonic-gate CURSOR *cp; 74*7c478bd9Sstevel@tonic-gate int count; /* !!!: Has to contain max number of cursors. */ 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate /* Recno is responsible for its own adjustments. */ 77*7c478bd9Sstevel@tonic-gate if (dbp->type == DB_RECNO) 78*7c478bd9Sstevel@tonic-gate return (0); 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate /* 81*7c478bd9Sstevel@tonic-gate * Adjust the cursors. We don't have to review the cursors for any 82*7c478bd9Sstevel@tonic-gate * thread of control other than the current one, because we have the 83*7c478bd9Sstevel@tonic-gate * page write locked at this point, and any other thread of control 84*7c478bd9Sstevel@tonic-gate * had better be using a different locker ID, meaning only cursors in 85*7c478bd9Sstevel@tonic-gate * our thread of control can be on the page. 86*7c478bd9Sstevel@tonic-gate * 87*7c478bd9Sstevel@tonic-gate * It's possible for multiple cursors within the thread to have write 88*7c478bd9Sstevel@tonic-gate * locks on the same page, but, cursors within a thread must be single 89*7c478bd9Sstevel@tonic-gate * threaded, so all we're locking here is the cursor linked list. 90*7c478bd9Sstevel@tonic-gate */ 91*7c478bd9Sstevel@tonic-gate DB_THREAD_LOCK(dbp); 92*7c478bd9Sstevel@tonic-gate for (count = 0, dbc = TAILQ_FIRST(&dbp->active_queue); 93*7c478bd9Sstevel@tonic-gate dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { 94*7c478bd9Sstevel@tonic-gate cp = (CURSOR *)dbc->internal; 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate if ((cp->pgno == pgno && cp->indx == indx) || 97*7c478bd9Sstevel@tonic-gate (cp->dpgno == pgno && cp->dindx == indx)) { 98*7c478bd9Sstevel@tonic-gate if (delete) 99*7c478bd9Sstevel@tonic-gate F_SET(cp, C_DELETED); 100*7c478bd9Sstevel@tonic-gate else 101*7c478bd9Sstevel@tonic-gate F_CLR(cp, C_DELETED); 102*7c478bd9Sstevel@tonic-gate ++count; 103*7c478bd9Sstevel@tonic-gate } 104*7c478bd9Sstevel@tonic-gate } 105*7c478bd9Sstevel@tonic-gate DB_THREAD_UNLOCK(dbp); 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate return (count); 108*7c478bd9Sstevel@tonic-gate } 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate /* 111*7c478bd9Sstevel@tonic-gate * __bam_ca_di -- 112*7c478bd9Sstevel@tonic-gate * Adjust the cursors during a delete or insert. 113*7c478bd9Sstevel@tonic-gate * 114*7c478bd9Sstevel@tonic-gate * PUBLIC: void __bam_ca_di __P((DB *, db_pgno_t, u_int32_t, int)); 115*7c478bd9Sstevel@tonic-gate */ 116*7c478bd9Sstevel@tonic-gate void 117*7c478bd9Sstevel@tonic-gate __bam_ca_di(dbp, pgno, indx, adjust) 118*7c478bd9Sstevel@tonic-gate DB *dbp; 119*7c478bd9Sstevel@tonic-gate db_pgno_t pgno; 120*7c478bd9Sstevel@tonic-gate u_int32_t indx; 121*7c478bd9Sstevel@tonic-gate int adjust; 122*7c478bd9Sstevel@tonic-gate { 123*7c478bd9Sstevel@tonic-gate CURSOR *cp; 124*7c478bd9Sstevel@tonic-gate DBC *dbc; 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate /* Recno is responsible for its own adjustments. */ 127*7c478bd9Sstevel@tonic-gate if (dbp->type == DB_RECNO) 128*7c478bd9Sstevel@tonic-gate return; 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate /* 131*7c478bd9Sstevel@tonic-gate * Adjust the cursors. See the comment in __bam_ca_delete(). 132*7c478bd9Sstevel@tonic-gate */ 133*7c478bd9Sstevel@tonic-gate DB_THREAD_LOCK(dbp); 134*7c478bd9Sstevel@tonic-gate for (dbc = TAILQ_FIRST(&dbp->active_queue); 135*7c478bd9Sstevel@tonic-gate dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { 136*7c478bd9Sstevel@tonic-gate cp = (CURSOR *)dbc->internal; 137*7c478bd9Sstevel@tonic-gate if (cp->pgno == pgno && cp->indx >= indx) 138*7c478bd9Sstevel@tonic-gate cp->indx += adjust; 139*7c478bd9Sstevel@tonic-gate if (cp->dpgno == pgno && cp->dindx >= indx) 140*7c478bd9Sstevel@tonic-gate cp->dindx += adjust; 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate DB_THREAD_UNLOCK(dbp); 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate /* 146*7c478bd9Sstevel@tonic-gate * __bam_ca_dup -- 147*7c478bd9Sstevel@tonic-gate * Adjust the cursors when moving items from a leaf page to a duplicates 148*7c478bd9Sstevel@tonic-gate * page. 149*7c478bd9Sstevel@tonic-gate * 150*7c478bd9Sstevel@tonic-gate * PUBLIC: void __bam_ca_dup __P((DB *, 151*7c478bd9Sstevel@tonic-gate * PUBLIC: db_pgno_t, u_int32_t, u_int32_t, db_pgno_t, u_int32_t)); 152*7c478bd9Sstevel@tonic-gate */ 153*7c478bd9Sstevel@tonic-gate void 154*7c478bd9Sstevel@tonic-gate __bam_ca_dup(dbp, fpgno, first, fi, tpgno, ti) 155*7c478bd9Sstevel@tonic-gate DB *dbp; 156*7c478bd9Sstevel@tonic-gate db_pgno_t fpgno, tpgno; 157*7c478bd9Sstevel@tonic-gate u_int32_t first, fi, ti; 158*7c478bd9Sstevel@tonic-gate { 159*7c478bd9Sstevel@tonic-gate CURSOR *cp; 160*7c478bd9Sstevel@tonic-gate DBC *dbc; 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate /* Recno is responsible for its own adjustments. */ 163*7c478bd9Sstevel@tonic-gate if (dbp->type == DB_RECNO) 164*7c478bd9Sstevel@tonic-gate return; 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate /* 167*7c478bd9Sstevel@tonic-gate * Adjust the cursors. See the comment in __bam_ca_delete(). 168*7c478bd9Sstevel@tonic-gate */ 169*7c478bd9Sstevel@tonic-gate DB_THREAD_LOCK(dbp); 170*7c478bd9Sstevel@tonic-gate for (dbc = TAILQ_FIRST(&dbp->active_queue); 171*7c478bd9Sstevel@tonic-gate dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { 172*7c478bd9Sstevel@tonic-gate cp = (CURSOR *)dbc->internal; 173*7c478bd9Sstevel@tonic-gate /* 174*7c478bd9Sstevel@tonic-gate * Ignore matching entries that have already been moved, 175*7c478bd9Sstevel@tonic-gate * we move from the same location on the leaf page more 176*7c478bd9Sstevel@tonic-gate * than once. 177*7c478bd9Sstevel@tonic-gate */ 178*7c478bd9Sstevel@tonic-gate if (cp->dpgno == PGNO_INVALID && 179*7c478bd9Sstevel@tonic-gate cp->pgno == fpgno && cp->indx == fi) { 180*7c478bd9Sstevel@tonic-gate cp->indx = first; 181*7c478bd9Sstevel@tonic-gate cp->dpgno = tpgno; 182*7c478bd9Sstevel@tonic-gate cp->dindx = ti; 183*7c478bd9Sstevel@tonic-gate } 184*7c478bd9Sstevel@tonic-gate } 185*7c478bd9Sstevel@tonic-gate DB_THREAD_UNLOCK(dbp); 186*7c478bd9Sstevel@tonic-gate } 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate /* 189*7c478bd9Sstevel@tonic-gate * __bam_ca_rsplit -- 190*7c478bd9Sstevel@tonic-gate * Adjust the cursors when doing reverse splits. 191*7c478bd9Sstevel@tonic-gate * 192*7c478bd9Sstevel@tonic-gate * PUBLIC: void __bam_ca_rsplit __P((DB *, db_pgno_t, db_pgno_t)); 193*7c478bd9Sstevel@tonic-gate */ 194*7c478bd9Sstevel@tonic-gate void 195*7c478bd9Sstevel@tonic-gate __bam_ca_rsplit(dbp, fpgno, tpgno) 196*7c478bd9Sstevel@tonic-gate DB *dbp; 197*7c478bd9Sstevel@tonic-gate db_pgno_t fpgno, tpgno; 198*7c478bd9Sstevel@tonic-gate { 199*7c478bd9Sstevel@tonic-gate CURSOR *cp; 200*7c478bd9Sstevel@tonic-gate DBC *dbc; 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate /* Recno is responsible for its own adjustments. */ 203*7c478bd9Sstevel@tonic-gate if (dbp->type == DB_RECNO) 204*7c478bd9Sstevel@tonic-gate return; 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate /* 207*7c478bd9Sstevel@tonic-gate * Adjust the cursors. See the comment in __bam_ca_delete(). 208*7c478bd9Sstevel@tonic-gate */ 209*7c478bd9Sstevel@tonic-gate DB_THREAD_LOCK(dbp); 210*7c478bd9Sstevel@tonic-gate for (dbc = TAILQ_FIRST(&dbp->active_queue); 211*7c478bd9Sstevel@tonic-gate dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { 212*7c478bd9Sstevel@tonic-gate cp = (CURSOR *)dbc->internal; 213*7c478bd9Sstevel@tonic-gate if (cp->pgno == fpgno) 214*7c478bd9Sstevel@tonic-gate cp->pgno = tpgno; 215*7c478bd9Sstevel@tonic-gate } 216*7c478bd9Sstevel@tonic-gate DB_THREAD_UNLOCK(dbp); 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate /* 220*7c478bd9Sstevel@tonic-gate * __bam_ca_split -- 221*7c478bd9Sstevel@tonic-gate * Adjust the cursors when splitting a page. 222*7c478bd9Sstevel@tonic-gate * 223*7c478bd9Sstevel@tonic-gate * PUBLIC: void __bam_ca_split __P((DB *, 224*7c478bd9Sstevel@tonic-gate * PUBLIC: db_pgno_t, db_pgno_t, db_pgno_t, u_int32_t, int)); 225*7c478bd9Sstevel@tonic-gate */ 226*7c478bd9Sstevel@tonic-gate void 227*7c478bd9Sstevel@tonic-gate __bam_ca_split(dbp, ppgno, lpgno, rpgno, split_indx, cleft) 228*7c478bd9Sstevel@tonic-gate DB *dbp; 229*7c478bd9Sstevel@tonic-gate db_pgno_t ppgno, lpgno, rpgno; 230*7c478bd9Sstevel@tonic-gate u_int32_t split_indx; 231*7c478bd9Sstevel@tonic-gate int cleft; 232*7c478bd9Sstevel@tonic-gate { 233*7c478bd9Sstevel@tonic-gate DBC *dbc; 234*7c478bd9Sstevel@tonic-gate CURSOR *cp; 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate /* Recno is responsible for its own adjustments. */ 237*7c478bd9Sstevel@tonic-gate if (dbp->type == DB_RECNO) 238*7c478bd9Sstevel@tonic-gate return; 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate /* 241*7c478bd9Sstevel@tonic-gate * Adjust the cursors. See the comment in __bam_ca_delete(). 242*7c478bd9Sstevel@tonic-gate * 243*7c478bd9Sstevel@tonic-gate * If splitting the page that a cursor was on, the cursor has to be 244*7c478bd9Sstevel@tonic-gate * adjusted to point to the same record as before the split. Most 245*7c478bd9Sstevel@tonic-gate * of the time we don't adjust pointers to the left page, because 246*7c478bd9Sstevel@tonic-gate * we're going to copy its contents back over the original page. If 247*7c478bd9Sstevel@tonic-gate * the cursor is on the right page, it is decremented by the number of 248*7c478bd9Sstevel@tonic-gate * records split to the left page. 249*7c478bd9Sstevel@tonic-gate */ 250*7c478bd9Sstevel@tonic-gate DB_THREAD_LOCK(dbp); 251*7c478bd9Sstevel@tonic-gate for (dbc = TAILQ_FIRST(&dbp->active_queue); 252*7c478bd9Sstevel@tonic-gate dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { 253*7c478bd9Sstevel@tonic-gate cp = (CURSOR *)dbc->internal; 254*7c478bd9Sstevel@tonic-gate if (cp->pgno == ppgno) 255*7c478bd9Sstevel@tonic-gate if (cp->indx < split_indx) { 256*7c478bd9Sstevel@tonic-gate if (cleft) 257*7c478bd9Sstevel@tonic-gate cp->pgno = lpgno; 258*7c478bd9Sstevel@tonic-gate } else { 259*7c478bd9Sstevel@tonic-gate cp->pgno = rpgno; 260*7c478bd9Sstevel@tonic-gate cp->indx -= split_indx; 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate if (cp->dpgno == ppgno) 263*7c478bd9Sstevel@tonic-gate if (cp->dindx < split_indx) { 264*7c478bd9Sstevel@tonic-gate if (cleft) 265*7c478bd9Sstevel@tonic-gate cp->dpgno = lpgno; 266*7c478bd9Sstevel@tonic-gate } else { 267*7c478bd9Sstevel@tonic-gate cp->dpgno = rpgno; 268*7c478bd9Sstevel@tonic-gate cp->dindx -= split_indx; 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate } 271*7c478bd9Sstevel@tonic-gate DB_THREAD_UNLOCK(dbp); 272*7c478bd9Sstevel@tonic-gate } 273