1*50990Sbostic /*- 2*50990Sbostic * Copyright (c) 1990 The Regents of the University of California. 3*50990Sbostic * All rights reserved. 4*50990Sbostic * 5*50990Sbostic * This code is derived from software contributed to Berkeley by 6*50990Sbostic * Mike Olson. 7*50990Sbostic * 8*50990Sbostic * %sccs.include.redist.c% 9*50990Sbostic */ 10*50990Sbostic 11*50990Sbostic #if defined(LIBC_SCCS) && !defined(lint) 12*50990Sbostic static char sccsid[] = "@(#)bt_debug.c 5.1 (Berkeley) 09/04/91"; 13*50990Sbostic #endif /* LIBC_SCCS and not lint */ 14*50990Sbostic 15*50990Sbostic #include <sys/param.h> 16*50990Sbostic #include <db.h> 17*50990Sbostic #include <stdio.h> 18*50990Sbostic #include <stdlib.h> 19*50990Sbostic #include <string.h> 20*50990Sbostic #include "btree.h" 21*50990Sbostic 22*50990Sbostic #ifdef DEBUG 23*50990Sbostic /* 24*50990Sbostic * BT_DUMP -- Dump the tree 25*50990Sbostic * 26*50990Sbostic * Parameters: 27*50990Sbostic * dbp: pointer to the DB 28*50990Sbostic */ 29*50990Sbostic void 30*50990Sbostic __bt_dump(dbp) 31*50990Sbostic DB *dbp; 32*50990Sbostic { 33*50990Sbostic BTREE *t; 34*50990Sbostic PAGE *h; 35*50990Sbostic pgno_t i; 36*50990Sbostic char *sep; 37*50990Sbostic 38*50990Sbostic t = dbp->internal; 39*50990Sbostic (void)fprintf(stderr, "%s: pgsz %d", 40*50990Sbostic ISSET(t, BTF_INMEM) ? "memory" : "disk", t->bt_psize); 41*50990Sbostic if (ISSET(t, BTF_RECNO)) 42*50990Sbostic (void)fprintf(stderr, " keys %lu", t->bt_nrecs); 43*50990Sbostic #define X(flag, name) \ 44*50990Sbostic if (ISSET(t, flag)) { \ 45*50990Sbostic (void)fprintf(stderr, "%s%s", sep, name); \ 46*50990Sbostic sep = ", "; \ 47*50990Sbostic } 48*50990Sbostic if (t->bt_flags) { 49*50990Sbostic sep = " flags ("; 50*50990Sbostic X(BTF_DELCRSR, "DELCRSR"); 51*50990Sbostic X(BTF_FIXEDLEN, "FIXEDLEN"); 52*50990Sbostic X(BTF_INMEM, "INMEM"); 53*50990Sbostic X(BTF_NODUPS, "NODUPS"); 54*50990Sbostic X(BTF_RDONLY, "RDONLY"); 55*50990Sbostic X(BTF_RECNO, "RECNO"); 56*50990Sbostic X(BTF_SEQINIT, "SEQINIT"); 57*50990Sbostic X(BTF_METADIRTY,"METADIRTY"); 58*50990Sbostic (void)fprintf(stderr, ")\n"); 59*50990Sbostic } 60*50990Sbostic #undef X 61*50990Sbostic 62*50990Sbostic for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) { 63*50990Sbostic __bt_dpage(h); 64*50990Sbostic (void)mpool_put(t->bt_mp, h, 0); 65*50990Sbostic } 66*50990Sbostic } 67*50990Sbostic 68*50990Sbostic /* 69*50990Sbostic * BT_DPAGE -- Dump the page 70*50990Sbostic * 71*50990Sbostic * Parameters: 72*50990Sbostic * h: pointer to the PAGE 73*50990Sbostic */ 74*50990Sbostic void 75*50990Sbostic __bt_dpage(h) 76*50990Sbostic PAGE *h; 77*50990Sbostic { 78*50990Sbostic BINTERNAL *bi; 79*50990Sbostic BLEAF *bl; 80*50990Sbostic RINTERNAL *ri; 81*50990Sbostic RLEAF *rl; 82*50990Sbostic index_t cur, top; 83*50990Sbostic char *sep; 84*50990Sbostic 85*50990Sbostic (void)fprintf(stderr, " page %d: (", h->pgno); 86*50990Sbostic #define X(flag, name) \ 87*50990Sbostic if (h->flags & flag) { \ 88*50990Sbostic (void)fprintf(stderr, "%s%s", sep, name); \ 89*50990Sbostic sep = ", "; \ 90*50990Sbostic } 91*50990Sbostic sep = ""; 92*50990Sbostic X(P_BINTERNAL, "BINTERNAL") /* types */ 93*50990Sbostic X(P_BLEAF, "BLEAF") 94*50990Sbostic X(P_RINTERNAL, "RINTERNAL") /* types */ 95*50990Sbostic X(P_RLEAF, "RLEAF") 96*50990Sbostic X(P_OVERFLOW, "OVERFLOW") 97*50990Sbostic X(P_PRESERVE, "PRESERVE"); 98*50990Sbostic (void)fprintf(stderr, ")\n"); 99*50990Sbostic #undef X 100*50990Sbostic 101*50990Sbostic (void)fprintf(stderr, "\tprev %2d next %2d", h->prevpg, h->nextpg); 102*50990Sbostic if (h->flags & P_OVERFLOW) 103*50990Sbostic return; 104*50990Sbostic 105*50990Sbostic top = NEXTINDEX(h); 106*50990Sbostic (void)fprintf(stderr, " lower %3d upper %3d nextind %d\n", 107*50990Sbostic h->lower, h->upper, top); 108*50990Sbostic for (cur = 0; cur < top; cur++) { 109*50990Sbostic (void)fprintf(stderr, "\t[%03d] %4d ", cur, h->linp[cur]); 110*50990Sbostic switch(h->flags & P_TYPE) { 111*50990Sbostic case P_BINTERNAL: 112*50990Sbostic bi = GETBINTERNAL(h, cur); 113*50990Sbostic (void)fprintf(stderr, 114*50990Sbostic "size %2d pgno %2d", bi->ksize, bi->pgno); 115*50990Sbostic if (bi->flags & P_BIGKEY) 116*50990Sbostic (void)fprintf(stderr, " (indirect)"); 117*50990Sbostic else if (bi->ksize) 118*50990Sbostic (void)fprintf(stderr, " {%s}", bi->bytes); 119*50990Sbostic break; 120*50990Sbostic case P_RINTERNAL: 121*50990Sbostic ri = GETRINTERNAL(h, cur); 122*50990Sbostic (void)fprintf(stderr, "entries %2d pgno %2d", 123*50990Sbostic ri->nrecs, ri->pgno); 124*50990Sbostic break; 125*50990Sbostic case P_BLEAF: 126*50990Sbostic bl = GETBLEAF(h, cur); 127*50990Sbostic if (bl->flags & P_BIGKEY) 128*50990Sbostic (void)fprintf(stderr, 129*50990Sbostic "big key page %lu size %u/", 130*50990Sbostic *(pgno_t *)bl->bytes, 131*50990Sbostic *(size_t *)(bl->bytes + sizeof(pgno_t))); 132*50990Sbostic else if (bl->ksize) 133*50990Sbostic (void)fprintf(stderr, "%s/", bl->bytes); 134*50990Sbostic if (bl->flags & P_BIGDATA) 135*50990Sbostic (void)fprintf(stderr, 136*50990Sbostic "big data page %lu size %u", 137*50990Sbostic *(pgno_t *)(bl->bytes + bl->ksize), 138*50990Sbostic *(size_t *)(bl->bytes + bl->ksize + 139*50990Sbostic sizeof(pgno_t))); 140*50990Sbostic else if (bl->dsize) 141*50990Sbostic (void)fprintf(stderr, 142*50990Sbostic "%s", bl->bytes + bl->ksize); 143*50990Sbostic break; 144*50990Sbostic case P_RLEAF: 145*50990Sbostic rl = GETRLEAF(h, cur); 146*50990Sbostic if (rl->flags & P_BIGDATA) 147*50990Sbostic (void)fprintf(stderr, 148*50990Sbostic "big data page %lu size %u", 149*50990Sbostic *(pgno_t *)rl->bytes, 150*50990Sbostic *(size_t *)(rl->bytes + sizeof(pgno_t))); 151*50990Sbostic else if (rl->dsize) 152*50990Sbostic (void)fprintf(stderr, "%s", rl->bytes); 153*50990Sbostic break; 154*50990Sbostic } 155*50990Sbostic (void)fprintf(stderr, "\n"); 156*50990Sbostic } 157*50990Sbostic } 158*50990Sbostic #endif 159*50990Sbostic 160*50990Sbostic #ifdef STATISTICS 161*50990Sbostic /* 162*50990Sbostic * BT_STAT -- Gather/print the tree statistics 163*50990Sbostic * 164*50990Sbostic * Parameters: 165*50990Sbostic * dbp: pointer to the DB 166*50990Sbostic */ 167*50990Sbostic void 168*50990Sbostic __bt_stat(dbp) 169*50990Sbostic DB *dbp; 170*50990Sbostic { 171*50990Sbostic extern u_long bt_cache_hit, bt_cache_miss; 172*50990Sbostic extern u_long bt_rootsplit, bt_split, bt_sortsplit; 173*50990Sbostic extern u_long bt_pfxsaved; 174*50990Sbostic BTREE *t; 175*50990Sbostic PAGE *h; 176*50990Sbostic pgno_t i, pcont, pinternal, pleaf; 177*50990Sbostic u_long ifree, lfree, nkeys; 178*50990Sbostic int levels; 179*50990Sbostic 180*50990Sbostic t = dbp->internal; 181*50990Sbostic pcont = pinternal = pleaf = 0; 182*50990Sbostic nkeys = ifree = lfree = 0; 183*50990Sbostic for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) { 184*50990Sbostic switch(h->flags & P_TYPE) { 185*50990Sbostic case P_BINTERNAL: 186*50990Sbostic case P_RINTERNAL: 187*50990Sbostic ++pinternal; 188*50990Sbostic ifree += h->upper - h->lower; 189*50990Sbostic break; 190*50990Sbostic case P_BLEAF: 191*50990Sbostic case P_RLEAF: 192*50990Sbostic ++pleaf; 193*50990Sbostic lfree += h->upper - h->lower; 194*50990Sbostic nkeys += NEXTINDEX(h); 195*50990Sbostic break; 196*50990Sbostic case P_OVERFLOW: 197*50990Sbostic ++pcont; 198*50990Sbostic break; 199*50990Sbostic } 200*50990Sbostic (void)mpool_put(t->bt_mp, h, 0); 201*50990Sbostic } 202*50990Sbostic 203*50990Sbostic /* Count the levels of the tree. */ 204*50990Sbostic for (i = P_ROOT, levels = 0 ;; ++levels) { 205*50990Sbostic h = mpool_get(t->bt_mp, i, 0); 206*50990Sbostic if (h->flags & (P_BLEAF|P_RLEAF)) { 207*50990Sbostic if (levels == 0) 208*50990Sbostic levels = 1; 209*50990Sbostic (void)mpool_put(t->bt_mp, h, 0); 210*50990Sbostic break; 211*50990Sbostic } 212*50990Sbostic i = ISSET(t, BTF_RECNO) ? 213*50990Sbostic GETRINTERNAL(h, 0)->pgno : 214*50990Sbostic GETBINTERNAL(h, 0)->pgno; 215*50990Sbostic (void)mpool_put(t->bt_mp, h, 0); 216*50990Sbostic } 217*50990Sbostic 218*50990Sbostic (void)fprintf(stderr, "%d level%s with %ld keys", 219*50990Sbostic levels, levels == 1 ? "" : "s", nkeys); 220*50990Sbostic if (ISSET(t, BTF_RECNO)) 221*50990Sbostic (void)fprintf(stderr, " (%ld header count)", t->bt_nrecs); 222*50990Sbostic (void)fprintf(stderr, 223*50990Sbostic "\n%lu pages (leaf %ld, internal %ld, overflow %ld)\n", 224*50990Sbostic pinternal + pleaf + pcont, pleaf, pinternal, pcont); 225*50990Sbostic (void)fprintf(stderr, "%ld cache hits, %ld cache misses\n", 226*50990Sbostic bt_cache_hit, bt_cache_miss); 227*50990Sbostic (void)fprintf(stderr, "%ld splits (%ld root splits, %ld sort splits)\n", 228*50990Sbostic bt_split, bt_rootsplit, bt_sortsplit); 229*50990Sbostic pleaf *= t->bt_psize - BTDATAOFF; 230*50990Sbostic if (pleaf) 231*50990Sbostic (void)fprintf(stderr, 232*50990Sbostic "%.0f%% leaf fill (%ld bytes used, %ld bytes free)\n", 233*50990Sbostic ((double)(pleaf - lfree) / pleaf) * 100, 234*50990Sbostic pleaf - lfree, lfree); 235*50990Sbostic pinternal *= t->bt_psize - BTDATAOFF; 236*50990Sbostic if (pinternal) 237*50990Sbostic (void)fprintf(stderr, 238*50990Sbostic "%.0f%% internal fill (%ld bytes used, %ld bytes free\n", 239*50990Sbostic ((double)(pinternal - ifree) / pinternal) * 100, 240*50990Sbostic pinternal - ifree, ifree); 241*50990Sbostic if (bt_pfxsaved) 242*50990Sbostic (void)fprintf(stderr, "prefix checking removed %lu bytes.\n", 243*50990Sbostic bt_pfxsaved); 244*50990Sbostic } 245*50990Sbostic #endif 246