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) 1990, 1993, 1994, 1995, 1996 9*7c478bd9Sstevel@tonic-gate * Keith Bostic. All rights reserved. 10*7c478bd9Sstevel@tonic-gate */ 11*7c478bd9Sstevel@tonic-gate /* 12*7c478bd9Sstevel@tonic-gate * Copyright (c) 1990, 1993 13*7c478bd9Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 14*7c478bd9Sstevel@tonic-gate * 15*7c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 16*7c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions 17*7c478bd9Sstevel@tonic-gate * are met: 18*7c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 19*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 20*7c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 21*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 22*7c478bd9Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 23*7c478bd9Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 24*7c478bd9Sstevel@tonic-gate * must display the following acknowledgement: 25*7c478bd9Sstevel@tonic-gate * This product includes software developed by the University of 26*7c478bd9Sstevel@tonic-gate * California, Berkeley and its contributors. 27*7c478bd9Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors 28*7c478bd9Sstevel@tonic-gate * may be used to endorse or promote products derived from this software 29*7c478bd9Sstevel@tonic-gate * without specific prior written permission. 30*7c478bd9Sstevel@tonic-gate * 31*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 32*7c478bd9Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 33*7c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34*7c478bd9Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 35*7c478bd9Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36*7c478bd9Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37*7c478bd9Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38*7c478bd9Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 39*7c478bd9Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 40*7c478bd9Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 41*7c478bd9Sstevel@tonic-gate * SUCH DAMAGE. 42*7c478bd9Sstevel@tonic-gate */ 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate #include "config.h" 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate #ifndef lint 47*7c478bd9Sstevel@tonic-gate static const char sccsid[] = "@(#)bt_rsearch.c 10.21 (Sleepycat) 12/2/98"; 48*7c478bd9Sstevel@tonic-gate #endif /* not lint */ 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate #ifndef NO_SYSTEM_INCLUDES 51*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 52*7c478bd9Sstevel@tonic-gate #endif 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate #include "db_int.h" 55*7c478bd9Sstevel@tonic-gate #include "db_page.h" 56*7c478bd9Sstevel@tonic-gate #include "btree.h" 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate /* 59*7c478bd9Sstevel@tonic-gate * __bam_rsearch -- 60*7c478bd9Sstevel@tonic-gate * Search a btree for a record number. 61*7c478bd9Sstevel@tonic-gate * 62*7c478bd9Sstevel@tonic-gate * PUBLIC: int __bam_rsearch __P((DBC *, db_recno_t *, u_int32_t, int, int *)); 63*7c478bd9Sstevel@tonic-gate */ 64*7c478bd9Sstevel@tonic-gate int 65*7c478bd9Sstevel@tonic-gate __bam_rsearch(dbc, recnop, flags, stop, exactp) 66*7c478bd9Sstevel@tonic-gate DBC *dbc; 67*7c478bd9Sstevel@tonic-gate db_recno_t *recnop; 68*7c478bd9Sstevel@tonic-gate u_int32_t flags; 69*7c478bd9Sstevel@tonic-gate int stop, *exactp; 70*7c478bd9Sstevel@tonic-gate { 71*7c478bd9Sstevel@tonic-gate BINTERNAL *bi; 72*7c478bd9Sstevel@tonic-gate CURSOR *cp; 73*7c478bd9Sstevel@tonic-gate DB *dbp; 74*7c478bd9Sstevel@tonic-gate DB_LOCK lock; 75*7c478bd9Sstevel@tonic-gate PAGE *h; 76*7c478bd9Sstevel@tonic-gate RINTERNAL *ri; 77*7c478bd9Sstevel@tonic-gate db_indx_t indx, top; 78*7c478bd9Sstevel@tonic-gate db_pgno_t pg; 79*7c478bd9Sstevel@tonic-gate db_recno_t i, recno, total; 80*7c478bd9Sstevel@tonic-gate int ret, stack; 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate dbp = dbc->dbp; 83*7c478bd9Sstevel@tonic-gate cp = dbc->internal; 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate BT_STK_CLR(cp); 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate /* 88*7c478bd9Sstevel@tonic-gate * There are several ways we search a btree tree. The flags argument 89*7c478bd9Sstevel@tonic-gate * specifies if we're acquiring read or write locks and if we are 90*7c478bd9Sstevel@tonic-gate * locking pairs of pages. In addition, if we're adding or deleting 91*7c478bd9Sstevel@tonic-gate * an item, we have to lock the entire tree, regardless. See btree.h 92*7c478bd9Sstevel@tonic-gate * for more details. 93*7c478bd9Sstevel@tonic-gate * 94*7c478bd9Sstevel@tonic-gate * If write-locking pages, we need to know whether or not to acquire a 95*7c478bd9Sstevel@tonic-gate * write lock on a page before getting it. This depends on how deep it 96*7c478bd9Sstevel@tonic-gate * is in tree, which we don't know until we acquire the root page. So, 97*7c478bd9Sstevel@tonic-gate * if we need to lock the root page we may have to upgrade it later, 98*7c478bd9Sstevel@tonic-gate * because we won't get the correct lock initially. 99*7c478bd9Sstevel@tonic-gate * 100*7c478bd9Sstevel@tonic-gate * Retrieve the root page. 101*7c478bd9Sstevel@tonic-gate */ 102*7c478bd9Sstevel@tonic-gate pg = PGNO_ROOT; 103*7c478bd9Sstevel@tonic-gate stack = LF_ISSET(S_STACK); 104*7c478bd9Sstevel@tonic-gate if ((ret = __bam_lget(dbc, 105*7c478bd9Sstevel@tonic-gate 0, pg, stack ? DB_LOCK_WRITE : DB_LOCK_READ, &lock)) != 0) 106*7c478bd9Sstevel@tonic-gate return (ret); 107*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(dbp->mpf, &pg, 0, &h)) != 0) { 108*7c478bd9Sstevel@tonic-gate (void)__BT_LPUT(dbc, lock); 109*7c478bd9Sstevel@tonic-gate return (ret); 110*7c478bd9Sstevel@tonic-gate } 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate /* 113*7c478bd9Sstevel@tonic-gate * Decide if we need to save this page; if we do, write lock it. 114*7c478bd9Sstevel@tonic-gate * We deliberately don't lock-couple on this call. If the tree 115*7c478bd9Sstevel@tonic-gate * is tiny, i.e., one page, and two threads are busily updating 116*7c478bd9Sstevel@tonic-gate * the root page, we're almost guaranteed deadlocks galore, as 117*7c478bd9Sstevel@tonic-gate * each one gets a read lock and then blocks the other's attempt 118*7c478bd9Sstevel@tonic-gate * for a write lock. 119*7c478bd9Sstevel@tonic-gate */ 120*7c478bd9Sstevel@tonic-gate if (!stack && 121*7c478bd9Sstevel@tonic-gate ((LF_ISSET(S_PARENT) && (u_int8_t)(stop + 1) >= h->level) || 122*7c478bd9Sstevel@tonic-gate (LF_ISSET(S_WRITE) && h->level == LEAFLEVEL))) { 123*7c478bd9Sstevel@tonic-gate (void)memp_fput(dbp->mpf, h, 0); 124*7c478bd9Sstevel@tonic-gate (void)__BT_LPUT(dbc, lock); 125*7c478bd9Sstevel@tonic-gate if ((ret = __bam_lget(dbc, 0, pg, DB_LOCK_WRITE, &lock)) != 0) 126*7c478bd9Sstevel@tonic-gate return (ret); 127*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(dbp->mpf, &pg, 0, &h)) != 0) { 128*7c478bd9Sstevel@tonic-gate (void)__BT_LPUT(dbc, lock); 129*7c478bd9Sstevel@tonic-gate return (ret); 130*7c478bd9Sstevel@tonic-gate } 131*7c478bd9Sstevel@tonic-gate stack = 1; 132*7c478bd9Sstevel@tonic-gate } 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate /* 135*7c478bd9Sstevel@tonic-gate * If appending to the tree, set the record number now -- we have the 136*7c478bd9Sstevel@tonic-gate * root page locked. 137*7c478bd9Sstevel@tonic-gate * 138*7c478bd9Sstevel@tonic-gate * Delete only deletes exact matches, read only returns exact matches. 139*7c478bd9Sstevel@tonic-gate * Note, this is different from __bam_search(), which returns non-exact 140*7c478bd9Sstevel@tonic-gate * matches for read. 141*7c478bd9Sstevel@tonic-gate * 142*7c478bd9Sstevel@tonic-gate * The record may not exist. We can only return the correct location 143*7c478bd9Sstevel@tonic-gate * for the record immediately after the last record in the tree, so do 144*7c478bd9Sstevel@tonic-gate * a fast check now. 145*7c478bd9Sstevel@tonic-gate */ 146*7c478bd9Sstevel@tonic-gate total = RE_NREC(h); 147*7c478bd9Sstevel@tonic-gate if (LF_ISSET(S_APPEND)) { 148*7c478bd9Sstevel@tonic-gate *exactp = 0; 149*7c478bd9Sstevel@tonic-gate *recnop = recno = total + 1; 150*7c478bd9Sstevel@tonic-gate } else { 151*7c478bd9Sstevel@tonic-gate recno = *recnop; 152*7c478bd9Sstevel@tonic-gate if (recno <= total) 153*7c478bd9Sstevel@tonic-gate *exactp = 1; 154*7c478bd9Sstevel@tonic-gate else { 155*7c478bd9Sstevel@tonic-gate *exactp = 0; 156*7c478bd9Sstevel@tonic-gate if (!LF_ISSET(S_PAST_EOF) || recno > total + 1) { 157*7c478bd9Sstevel@tonic-gate (void)memp_fput(dbp->mpf, h, 0); 158*7c478bd9Sstevel@tonic-gate (void)__BT_LPUT(dbc, lock); 159*7c478bd9Sstevel@tonic-gate return (DB_NOTFOUND); 160*7c478bd9Sstevel@tonic-gate } 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate } 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate /* 165*7c478bd9Sstevel@tonic-gate * !!! 166*7c478bd9Sstevel@tonic-gate * Record numbers in the tree are 0-based, but the recno is 167*7c478bd9Sstevel@tonic-gate * 1-based. All of the calculations below have to take this 168*7c478bd9Sstevel@tonic-gate * into account. 169*7c478bd9Sstevel@tonic-gate */ 170*7c478bd9Sstevel@tonic-gate for (total = 0;;) { 171*7c478bd9Sstevel@tonic-gate switch (TYPE(h)) { 172*7c478bd9Sstevel@tonic-gate case P_LBTREE: 173*7c478bd9Sstevel@tonic-gate recno -= total; 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate /* 176*7c478bd9Sstevel@tonic-gate * There may be logically deleted records on the page, 177*7c478bd9Sstevel@tonic-gate * walk the page correcting for them. The record may 178*7c478bd9Sstevel@tonic-gate * not exist if there are enough deleted records in the 179*7c478bd9Sstevel@tonic-gate * page. 180*7c478bd9Sstevel@tonic-gate */ 181*7c478bd9Sstevel@tonic-gate if (recno <= (db_recno_t)NUM_ENT(h) / P_INDX) 182*7c478bd9Sstevel@tonic-gate for (i = recno - 1;; --i) { 183*7c478bd9Sstevel@tonic-gate if (B_DISSET(GET_BKEYDATA(h, 184*7c478bd9Sstevel@tonic-gate i * P_INDX + O_INDX)->type)) 185*7c478bd9Sstevel@tonic-gate ++recno; 186*7c478bd9Sstevel@tonic-gate if (i == 0) 187*7c478bd9Sstevel@tonic-gate break; 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate if (recno > (db_recno_t)NUM_ENT(h) / P_INDX) { 190*7c478bd9Sstevel@tonic-gate *exactp = 0; 191*7c478bd9Sstevel@tonic-gate if (!LF_ISSET(S_PAST_EOF) || recno > 192*7c478bd9Sstevel@tonic-gate (db_recno_t)(NUM_ENT(h) / P_INDX + 1)) { 193*7c478bd9Sstevel@tonic-gate ret = DB_NOTFOUND; 194*7c478bd9Sstevel@tonic-gate goto err; 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate /* Correct from 1-based to 0-based for a page offset. */ 200*7c478bd9Sstevel@tonic-gate --recno; 201*7c478bd9Sstevel@tonic-gate BT_STK_ENTER(cp, h, recno * P_INDX, lock, ret); 202*7c478bd9Sstevel@tonic-gate return (ret); 203*7c478bd9Sstevel@tonic-gate case P_IBTREE: 204*7c478bd9Sstevel@tonic-gate for (indx = 0, top = NUM_ENT(h);;) { 205*7c478bd9Sstevel@tonic-gate bi = GET_BINTERNAL(h, indx); 206*7c478bd9Sstevel@tonic-gate if (++indx == top || total + bi->nrecs >= recno) 207*7c478bd9Sstevel@tonic-gate break; 208*7c478bd9Sstevel@tonic-gate total += bi->nrecs; 209*7c478bd9Sstevel@tonic-gate } 210*7c478bd9Sstevel@tonic-gate pg = bi->pgno; 211*7c478bd9Sstevel@tonic-gate break; 212*7c478bd9Sstevel@tonic-gate case P_LRECNO: 213*7c478bd9Sstevel@tonic-gate recno -= total; 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate /* Correct from 1-based to 0-based for a page offset. */ 216*7c478bd9Sstevel@tonic-gate --recno; 217*7c478bd9Sstevel@tonic-gate BT_STK_ENTER(cp, h, recno, lock, ret); 218*7c478bd9Sstevel@tonic-gate return (ret); 219*7c478bd9Sstevel@tonic-gate case P_IRECNO: 220*7c478bd9Sstevel@tonic-gate for (indx = 0, top = NUM_ENT(h);;) { 221*7c478bd9Sstevel@tonic-gate ri = GET_RINTERNAL(h, indx); 222*7c478bd9Sstevel@tonic-gate if (++indx == top || total + ri->nrecs >= recno) 223*7c478bd9Sstevel@tonic-gate break; 224*7c478bd9Sstevel@tonic-gate total += ri->nrecs; 225*7c478bd9Sstevel@tonic-gate } 226*7c478bd9Sstevel@tonic-gate pg = ri->pgno; 227*7c478bd9Sstevel@tonic-gate break; 228*7c478bd9Sstevel@tonic-gate default: 229*7c478bd9Sstevel@tonic-gate return (__db_pgfmt(dbp, h->pgno)); 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate --indx; 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate if (stack) { 234*7c478bd9Sstevel@tonic-gate /* Return if this is the lowest page wanted. */ 235*7c478bd9Sstevel@tonic-gate if (LF_ISSET(S_PARENT) && stop == h->level) { 236*7c478bd9Sstevel@tonic-gate BT_STK_ENTER(cp, h, indx, lock, ret); 237*7c478bd9Sstevel@tonic-gate return (ret); 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate BT_STK_PUSH(cp, h, indx, lock, ret); 240*7c478bd9Sstevel@tonic-gate if (ret != 0) 241*7c478bd9Sstevel@tonic-gate goto err; 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate if ((ret = 244*7c478bd9Sstevel@tonic-gate __bam_lget(dbc, 0, pg, DB_LOCK_WRITE, &lock)) != 0) 245*7c478bd9Sstevel@tonic-gate goto err; 246*7c478bd9Sstevel@tonic-gate } else { 247*7c478bd9Sstevel@tonic-gate /* 248*7c478bd9Sstevel@tonic-gate * Decide if we want to return a pointer to the next 249*7c478bd9Sstevel@tonic-gate * page in the stack. If we do, write lock it and 250*7c478bd9Sstevel@tonic-gate * never unlock it. 251*7c478bd9Sstevel@tonic-gate */ 252*7c478bd9Sstevel@tonic-gate if ((LF_ISSET(S_PARENT) && 253*7c478bd9Sstevel@tonic-gate (u_int8_t)(stop + 1) >= (u_int8_t)(h->level - 1)) || 254*7c478bd9Sstevel@tonic-gate (h->level - 1) == LEAFLEVEL) 255*7c478bd9Sstevel@tonic-gate stack = 1; 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate (void)memp_fput(dbp->mpf, h, 0); 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate if ((ret = 260*7c478bd9Sstevel@tonic-gate __bam_lget(dbc, 1, pg, stack && LF_ISSET(S_WRITE) ? 261*7c478bd9Sstevel@tonic-gate DB_LOCK_WRITE : DB_LOCK_READ, &lock)) != 0) 262*7c478bd9Sstevel@tonic-gate goto err; 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(dbp->mpf, &pg, 0, &h)) != 0) 266*7c478bd9Sstevel@tonic-gate goto err; 267*7c478bd9Sstevel@tonic-gate } 268*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate err: BT_STK_POP(cp); 271*7c478bd9Sstevel@tonic-gate __bam_stkrel(dbc, 0); 272*7c478bd9Sstevel@tonic-gate return (ret); 273*7c478bd9Sstevel@tonic-gate } 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate /* 276*7c478bd9Sstevel@tonic-gate * __bam_adjust -- 277*7c478bd9Sstevel@tonic-gate * Adjust the tree after adding or deleting a record. 278*7c478bd9Sstevel@tonic-gate * 279*7c478bd9Sstevel@tonic-gate * PUBLIC: int __bam_adjust __P((DBC *, int32_t)); 280*7c478bd9Sstevel@tonic-gate */ 281*7c478bd9Sstevel@tonic-gate int 282*7c478bd9Sstevel@tonic-gate __bam_adjust(dbc, adjust) 283*7c478bd9Sstevel@tonic-gate DBC *dbc; 284*7c478bd9Sstevel@tonic-gate int32_t adjust; 285*7c478bd9Sstevel@tonic-gate { 286*7c478bd9Sstevel@tonic-gate CURSOR *cp; 287*7c478bd9Sstevel@tonic-gate DB *dbp; 288*7c478bd9Sstevel@tonic-gate EPG *epg; 289*7c478bd9Sstevel@tonic-gate PAGE *h; 290*7c478bd9Sstevel@tonic-gate int ret; 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate dbp = dbc->dbp; 293*7c478bd9Sstevel@tonic-gate cp = dbc->internal; 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate /* Update the record counts for the tree. */ 296*7c478bd9Sstevel@tonic-gate for (epg = cp->sp; epg <= cp->csp; ++epg) { 297*7c478bd9Sstevel@tonic-gate h = epg->page; 298*7c478bd9Sstevel@tonic-gate if (TYPE(h) == P_IBTREE || TYPE(h) == P_IRECNO) { 299*7c478bd9Sstevel@tonic-gate if (DB_LOGGING(dbc) && 300*7c478bd9Sstevel@tonic-gate (ret = __bam_cadjust_log(dbp->dbenv->lg_info, 301*7c478bd9Sstevel@tonic-gate dbc->txn, &LSN(h), 0, dbp->log_fileid, 302*7c478bd9Sstevel@tonic-gate PGNO(h), &LSN(h), (u_int32_t)epg->indx, 303*7c478bd9Sstevel@tonic-gate adjust, 1)) != 0) 304*7c478bd9Sstevel@tonic-gate return (ret); 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate if (TYPE(h) == P_IBTREE) 307*7c478bd9Sstevel@tonic-gate GET_BINTERNAL(h, epg->indx)->nrecs += adjust; 308*7c478bd9Sstevel@tonic-gate else 309*7c478bd9Sstevel@tonic-gate GET_RINTERNAL(h, epg->indx)->nrecs += adjust; 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate if (PGNO(h) == PGNO_ROOT) 312*7c478bd9Sstevel@tonic-gate RE_NREC_ADJ(h, adjust); 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate if ((ret = memp_fset(dbp->mpf, h, DB_MPOOL_DIRTY)) != 0) 315*7c478bd9Sstevel@tonic-gate return (ret); 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate return (0); 319*7c478bd9Sstevel@tonic-gate } 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate /* 322*7c478bd9Sstevel@tonic-gate * __bam_nrecs -- 323*7c478bd9Sstevel@tonic-gate * Return the number of records in the tree. 324*7c478bd9Sstevel@tonic-gate * 325*7c478bd9Sstevel@tonic-gate * PUBLIC: int __bam_nrecs __P((DBC *, db_recno_t *)); 326*7c478bd9Sstevel@tonic-gate */ 327*7c478bd9Sstevel@tonic-gate int 328*7c478bd9Sstevel@tonic-gate __bam_nrecs(dbc, rep) 329*7c478bd9Sstevel@tonic-gate DBC *dbc; 330*7c478bd9Sstevel@tonic-gate db_recno_t *rep; 331*7c478bd9Sstevel@tonic-gate { 332*7c478bd9Sstevel@tonic-gate DB *dbp; 333*7c478bd9Sstevel@tonic-gate DB_LOCK lock; 334*7c478bd9Sstevel@tonic-gate PAGE *h; 335*7c478bd9Sstevel@tonic-gate db_pgno_t pgno; 336*7c478bd9Sstevel@tonic-gate int ret; 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate dbp = dbc->dbp; 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate pgno = PGNO_ROOT; 341*7c478bd9Sstevel@tonic-gate if ((ret = __bam_lget(dbc, 0, pgno, DB_LOCK_READ, &lock)) != 0) 342*7c478bd9Sstevel@tonic-gate return (ret); 343*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) 344*7c478bd9Sstevel@tonic-gate return (ret); 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate *rep = RE_NREC(h); 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate (void)memp_fput(dbp->mpf, h, 0); 349*7c478bd9Sstevel@tonic-gate (void)__BT_TLPUT(dbc, lock); 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate return (0); 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate /* 355*7c478bd9Sstevel@tonic-gate * __bam_total -- 356*7c478bd9Sstevel@tonic-gate * Return the number of records below a page. 357*7c478bd9Sstevel@tonic-gate * 358*7c478bd9Sstevel@tonic-gate * PUBLIC: db_recno_t __bam_total __P((PAGE *)); 359*7c478bd9Sstevel@tonic-gate */ 360*7c478bd9Sstevel@tonic-gate db_recno_t 361*7c478bd9Sstevel@tonic-gate __bam_total(h) 362*7c478bd9Sstevel@tonic-gate PAGE *h; 363*7c478bd9Sstevel@tonic-gate { 364*7c478bd9Sstevel@tonic-gate db_recno_t nrecs; 365*7c478bd9Sstevel@tonic-gate db_indx_t indx, top; 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate nrecs = 0; 368*7c478bd9Sstevel@tonic-gate top = NUM_ENT(h); 369*7c478bd9Sstevel@tonic-gate 370*7c478bd9Sstevel@tonic-gate switch (TYPE(h)) { 371*7c478bd9Sstevel@tonic-gate case P_LBTREE: 372*7c478bd9Sstevel@tonic-gate /* Check for logically deleted records. */ 373*7c478bd9Sstevel@tonic-gate for (indx = 0; indx < top; indx += P_INDX) 374*7c478bd9Sstevel@tonic-gate if (!B_DISSET(GET_BKEYDATA(h, indx + O_INDX)->type)) 375*7c478bd9Sstevel@tonic-gate ++nrecs; 376*7c478bd9Sstevel@tonic-gate break; 377*7c478bd9Sstevel@tonic-gate case P_IBTREE: 378*7c478bd9Sstevel@tonic-gate for (indx = 0; indx < top; indx += O_INDX) 379*7c478bd9Sstevel@tonic-gate nrecs += GET_BINTERNAL(h, indx)->nrecs; 380*7c478bd9Sstevel@tonic-gate break; 381*7c478bd9Sstevel@tonic-gate case P_LRECNO: 382*7c478bd9Sstevel@tonic-gate nrecs = NUM_ENT(h); 383*7c478bd9Sstevel@tonic-gate break; 384*7c478bd9Sstevel@tonic-gate case P_IRECNO: 385*7c478bd9Sstevel@tonic-gate for (indx = 0; indx < top; indx += O_INDX) 386*7c478bd9Sstevel@tonic-gate nrecs += GET_RINTERNAL(h, indx)->nrecs; 387*7c478bd9Sstevel@tonic-gate break; 388*7c478bd9Sstevel@tonic-gate } 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate return (nrecs); 391*7c478bd9Sstevel@tonic-gate } 392