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_stat.c 10.27 (Sleepycat) 11/25/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 "btree.h" 24*7c478bd9Sstevel@tonic-gate 25*7c478bd9Sstevel@tonic-gate /* 26*7c478bd9Sstevel@tonic-gate * __bam_stat -- 27*7c478bd9Sstevel@tonic-gate * Gather/print the btree statistics 28*7c478bd9Sstevel@tonic-gate * 29*7c478bd9Sstevel@tonic-gate * PUBLIC: int __bam_stat __P((DB *, void *, void *(*)(size_t), u_int32_t)); 30*7c478bd9Sstevel@tonic-gate */ 31*7c478bd9Sstevel@tonic-gate int 32*7c478bd9Sstevel@tonic-gate __bam_stat(dbp, spp, db_malloc, flags) 33*7c478bd9Sstevel@tonic-gate DB *dbp; 34*7c478bd9Sstevel@tonic-gate void *spp; 35*7c478bd9Sstevel@tonic-gate void *(*db_malloc) __P((size_t)); 36*7c478bd9Sstevel@tonic-gate u_int32_t flags; 37*7c478bd9Sstevel@tonic-gate { 38*7c478bd9Sstevel@tonic-gate BTMETA *meta; 39*7c478bd9Sstevel@tonic-gate BTREE *t; 40*7c478bd9Sstevel@tonic-gate DBC *dbc; 41*7c478bd9Sstevel@tonic-gate DB_BTREE_STAT *sp; 42*7c478bd9Sstevel@tonic-gate DB_LOCK lock; 43*7c478bd9Sstevel@tonic-gate PAGE *h; 44*7c478bd9Sstevel@tonic-gate db_pgno_t lastpgno, pgno; 45*7c478bd9Sstevel@tonic-gate int ret, t_ret; 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate DB_PANIC_CHECK(dbp); 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate /* Check for invalid flags. */ 50*7c478bd9Sstevel@tonic-gate if ((ret = __db_statchk(dbp, flags)) != 0) 51*7c478bd9Sstevel@tonic-gate return (ret); 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) 54*7c478bd9Sstevel@tonic-gate return (ret); 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate DEBUG_LWRITE(dbc, NULL, "bam_stat", NULL, NULL, flags); 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate t = dbp->internal; 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate if (spp == NULL) 61*7c478bd9Sstevel@tonic-gate return (0); 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate /* Allocate and clear the structure. */ 64*7c478bd9Sstevel@tonic-gate if ((ret = __os_malloc(sizeof(*sp), db_malloc, &sp)) != 0) 65*7c478bd9Sstevel@tonic-gate goto err; 66*7c478bd9Sstevel@tonic-gate memset(sp, 0, sizeof(*sp)); 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate /* If the app just wants the record count, make it fast. */ 69*7c478bd9Sstevel@tonic-gate if (flags == DB_RECORDCOUNT) { 70*7c478bd9Sstevel@tonic-gate pgno = PGNO_ROOT; 71*7c478bd9Sstevel@tonic-gate if ((ret = __bam_lget(dbc, 0, pgno, DB_LOCK_READ, &lock)) != 0) 72*7c478bd9Sstevel@tonic-gate goto err; 73*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(dbp->mpf, &pgno, 0, (PAGE **)&h)) != 0) 74*7c478bd9Sstevel@tonic-gate goto err; 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate sp->bt_nrecs = RE_NREC(h); 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate (void)memp_fput(dbp->mpf, h, 0); 79*7c478bd9Sstevel@tonic-gate (void)__BT_LPUT(dbc, lock); 80*7c478bd9Sstevel@tonic-gate goto done; 81*7c478bd9Sstevel@tonic-gate } 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate /* Get the meta-data page. */ 84*7c478bd9Sstevel@tonic-gate pgno = PGNO_METADATA; 85*7c478bd9Sstevel@tonic-gate if ((ret = __bam_lget(dbc, 0, pgno, DB_LOCK_READ, &lock)) != 0) 86*7c478bd9Sstevel@tonic-gate goto err; 87*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(dbp->mpf, &pgno, 0, (PAGE **)&meta)) != 0) 88*7c478bd9Sstevel@tonic-gate goto err; 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate /* Translate the metadata flags. */ 91*7c478bd9Sstevel@tonic-gate if (F_ISSET(meta, BTM_DUP)) 92*7c478bd9Sstevel@tonic-gate sp->bt_flags |= DB_DUP; 93*7c478bd9Sstevel@tonic-gate if (F_ISSET(meta, BTM_FIXEDLEN)) 94*7c478bd9Sstevel@tonic-gate sp->bt_flags |= DB_FIXEDLEN; 95*7c478bd9Sstevel@tonic-gate if (F_ISSET(meta, BTM_RECNUM)) 96*7c478bd9Sstevel@tonic-gate sp->bt_flags |= DB_RECNUM; 97*7c478bd9Sstevel@tonic-gate if (F_ISSET(meta, BTM_RENUMBER)) 98*7c478bd9Sstevel@tonic-gate sp->bt_flags |= DB_RENUMBER; 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate /* Get the remaining metadata fields. */ 101*7c478bd9Sstevel@tonic-gate sp->bt_minkey = meta->minkey; 102*7c478bd9Sstevel@tonic-gate sp->bt_maxkey = meta->maxkey; 103*7c478bd9Sstevel@tonic-gate sp->bt_re_len = meta->re_len; 104*7c478bd9Sstevel@tonic-gate sp->bt_re_pad = meta->re_pad; 105*7c478bd9Sstevel@tonic-gate sp->bt_magic = meta->magic; 106*7c478bd9Sstevel@tonic-gate sp->bt_version = meta->version; 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate /* Get the page size from the DB. */ 109*7c478bd9Sstevel@tonic-gate sp->bt_pagesize = dbp->pgsize; 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate /* Walk the free list, counting pages. */ 112*7c478bd9Sstevel@tonic-gate for (sp->bt_free = 0, pgno = meta->free; pgno != PGNO_INVALID;) { 113*7c478bd9Sstevel@tonic-gate ++sp->bt_free; 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) { 116*7c478bd9Sstevel@tonic-gate (void)memp_fput(dbp->mpf, meta, 0); 117*7c478bd9Sstevel@tonic-gate (void)__BT_TLPUT(dbc, lock); 118*7c478bd9Sstevel@tonic-gate goto err; 119*7c478bd9Sstevel@tonic-gate } 120*7c478bd9Sstevel@tonic-gate pgno = h->next_pgno; 121*7c478bd9Sstevel@tonic-gate (void)memp_fput(dbp->mpf, h, 0); 122*7c478bd9Sstevel@tonic-gate } 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate /* Discard the meta-data page. */ 125*7c478bd9Sstevel@tonic-gate (void)memp_fput(dbp->mpf, meta, 0); 126*7c478bd9Sstevel@tonic-gate (void)__BT_TLPUT(dbc, lock); 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate /* Determine the last page of the database. */ 129*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(dbp->mpf, &lastpgno, DB_MPOOL_LAST, &h)) != 0) 130*7c478bd9Sstevel@tonic-gate goto err; 131*7c478bd9Sstevel@tonic-gate (void)memp_fput(dbp->mpf, h, 0); 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate /* Get the root page. */ 134*7c478bd9Sstevel@tonic-gate pgno = PGNO_ROOT; 135*7c478bd9Sstevel@tonic-gate if ((ret = __bam_lget(dbc, 0, PGNO_ROOT, DB_LOCK_READ, &lock)) != 0) 136*7c478bd9Sstevel@tonic-gate goto err; 137*7c478bd9Sstevel@tonic-gate if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) { 138*7c478bd9Sstevel@tonic-gate (void)__BT_LPUT(dbc, lock); 139*7c478bd9Sstevel@tonic-gate goto err; 140*7c478bd9Sstevel@tonic-gate } 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate /* Get the levels from the root page. */ 143*7c478bd9Sstevel@tonic-gate sp->bt_levels = h->level; 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate /* Walk the page list, counting things. */ 146*7c478bd9Sstevel@tonic-gate for (;;) { 147*7c478bd9Sstevel@tonic-gate switch (TYPE(h)) { 148*7c478bd9Sstevel@tonic-gate case P_INVALID: 149*7c478bd9Sstevel@tonic-gate break; 150*7c478bd9Sstevel@tonic-gate case P_IBTREE: 151*7c478bd9Sstevel@tonic-gate case P_IRECNO: 152*7c478bd9Sstevel@tonic-gate ++sp->bt_int_pg; 153*7c478bd9Sstevel@tonic-gate sp->bt_int_pgfree += HOFFSET(h) - LOFFSET(h); 154*7c478bd9Sstevel@tonic-gate break; 155*7c478bd9Sstevel@tonic-gate case P_LBTREE: 156*7c478bd9Sstevel@tonic-gate ++sp->bt_leaf_pg; 157*7c478bd9Sstevel@tonic-gate sp->bt_leaf_pgfree += HOFFSET(h) - LOFFSET(h); 158*7c478bd9Sstevel@tonic-gate sp->bt_nrecs += NUM_ENT(h) / P_INDX; 159*7c478bd9Sstevel@tonic-gate break; 160*7c478bd9Sstevel@tonic-gate case P_LRECNO: 161*7c478bd9Sstevel@tonic-gate ++sp->bt_leaf_pg; 162*7c478bd9Sstevel@tonic-gate sp->bt_leaf_pgfree += HOFFSET(h) - LOFFSET(h); 163*7c478bd9Sstevel@tonic-gate sp->bt_nrecs += NUM_ENT(h); 164*7c478bd9Sstevel@tonic-gate break; 165*7c478bd9Sstevel@tonic-gate case P_DUPLICATE: 166*7c478bd9Sstevel@tonic-gate ++sp->bt_dup_pg; 167*7c478bd9Sstevel@tonic-gate /* XXX MARGO: sp->bt_dup_pgfree; */ 168*7c478bd9Sstevel@tonic-gate break; 169*7c478bd9Sstevel@tonic-gate case P_OVERFLOW: 170*7c478bd9Sstevel@tonic-gate ++sp->bt_over_pg; 171*7c478bd9Sstevel@tonic-gate /* XXX MARGO: sp->bt_over_pgfree; */ 172*7c478bd9Sstevel@tonic-gate break; 173*7c478bd9Sstevel@tonic-gate default: 174*7c478bd9Sstevel@tonic-gate (void)memp_fput(dbp->mpf, h, 0); 175*7c478bd9Sstevel@tonic-gate (void)__BT_LPUT(dbc, lock); 176*7c478bd9Sstevel@tonic-gate return (__db_pgfmt(dbp, pgno)); 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate (void)memp_fput(dbp->mpf, h, 0); 180*7c478bd9Sstevel@tonic-gate (void)__BT_LPUT(dbc, lock); 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate if (++pgno > lastpgno) 183*7c478bd9Sstevel@tonic-gate break; 184*7c478bd9Sstevel@tonic-gate if (__bam_lget(dbc, 0, pgno, DB_LOCK_READ, &lock)) 185*7c478bd9Sstevel@tonic-gate break; 186*7c478bd9Sstevel@tonic-gate if (memp_fget(dbp->mpf, &pgno, 0, &h) != 0) { 187*7c478bd9Sstevel@tonic-gate (void)__BT_LPUT(dbc, lock); 188*7c478bd9Sstevel@tonic-gate break; 189*7c478bd9Sstevel@tonic-gate } 190*7c478bd9Sstevel@tonic-gate } 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate done: *(DB_BTREE_STAT **)spp = sp; 193*7c478bd9Sstevel@tonic-gate ret = 0; 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate err: if ((t_ret = dbc->c_close(dbc)) != 0 && ret == 0) 196*7c478bd9Sstevel@tonic-gate ret = t_ret; 197*7c478bd9Sstevel@tonic-gate return (ret); 198*7c478bd9Sstevel@tonic-gate } 199