1*2639ae9bSBen Gras /* $NetBSD: bt_debug.c,v 1.15 2008/09/10 17:52:35 joerg Exp $ */ 2*2639ae9bSBen Gras 3*2639ae9bSBen Gras /*- 4*2639ae9bSBen Gras * Copyright (c) 1990, 1993, 1994 5*2639ae9bSBen Gras * The Regents of the University of California. All rights reserved. 6*2639ae9bSBen Gras * 7*2639ae9bSBen Gras * This code is derived from software contributed to Berkeley by 8*2639ae9bSBen Gras * Mike Olson. 9*2639ae9bSBen Gras * 10*2639ae9bSBen Gras * Redistribution and use in source and binary forms, with or without 11*2639ae9bSBen Gras * modification, are permitted provided that the following conditions 12*2639ae9bSBen Gras * are met: 13*2639ae9bSBen Gras * 1. Redistributions of source code must retain the above copyright 14*2639ae9bSBen Gras * notice, this list of conditions and the following disclaimer. 15*2639ae9bSBen Gras * 2. Redistributions in binary form must reproduce the above copyright 16*2639ae9bSBen Gras * notice, this list of conditions and the following disclaimer in the 17*2639ae9bSBen Gras * documentation and/or other materials provided with the distribution. 18*2639ae9bSBen Gras * 3. Neither the name of the University nor the names of its contributors 19*2639ae9bSBen Gras * may be used to endorse or promote products derived from this software 20*2639ae9bSBen Gras * without specific prior written permission. 21*2639ae9bSBen Gras * 22*2639ae9bSBen Gras * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23*2639ae9bSBen Gras * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24*2639ae9bSBen Gras * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25*2639ae9bSBen Gras * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26*2639ae9bSBen Gras * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27*2639ae9bSBen Gras * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28*2639ae9bSBen Gras * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29*2639ae9bSBen Gras * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30*2639ae9bSBen Gras * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31*2639ae9bSBen Gras * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32*2639ae9bSBen Gras * SUCH DAMAGE. 33*2639ae9bSBen Gras */ 34*2639ae9bSBen Gras 35*2639ae9bSBen Gras #if HAVE_NBTOOL_CONFIG_H 36*2639ae9bSBen Gras #include "nbtool_config.h" 37*2639ae9bSBen Gras #endif 38*2639ae9bSBen Gras 39*2639ae9bSBen Gras #include <sys/cdefs.h> 40*2639ae9bSBen Gras #ifndef __minix 41*2639ae9bSBen Gras __RCSID("$NetBSD: bt_debug.c,v 1.15 2008/09/10 17:52:35 joerg Exp $"); 42*2639ae9bSBen Gras #endif 43*2639ae9bSBen Gras 44*2639ae9bSBen Gras #include <assert.h> 45*2639ae9bSBen Gras #include <stdio.h> 46*2639ae9bSBen Gras #include <stdlib.h> 47*2639ae9bSBen Gras #include <string.h> 48*2639ae9bSBen Gras 49*2639ae9bSBen Gras #include <db.h> 50*2639ae9bSBen Gras #include "btree.h" 51*2639ae9bSBen Gras 52*2639ae9bSBen Gras #ifdef DEBUG 53*2639ae9bSBen Gras /* 54*2639ae9bSBen Gras * BT_DUMP -- Dump the tree 55*2639ae9bSBen Gras * 56*2639ae9bSBen Gras * Parameters: 57*2639ae9bSBen Gras * dbp: pointer to the DB 58*2639ae9bSBen Gras */ 59*2639ae9bSBen Gras void 60*2639ae9bSBen Gras __bt_dump(DB *dbp) 61*2639ae9bSBen Gras { 62*2639ae9bSBen Gras BTREE *t; 63*2639ae9bSBen Gras PAGE *h; 64*2639ae9bSBen Gras pgno_t i; 65*2639ae9bSBen Gras const char *sep; 66*2639ae9bSBen Gras 67*2639ae9bSBen Gras t = dbp->internal; 68*2639ae9bSBen Gras (void)fprintf(stderr, "%s: pgsz %d", 69*2639ae9bSBen Gras F_ISSET(t, B_INMEM) ? "memory" : "disk", t->bt_psize); 70*2639ae9bSBen Gras if (F_ISSET(t, R_RECNO)) 71*2639ae9bSBen Gras (void)fprintf(stderr, " keys %lu", (unsigned long) t->bt_nrecs); 72*2639ae9bSBen Gras #undef X 73*2639ae9bSBen Gras #define X(flag, name) \ 74*2639ae9bSBen Gras if (F_ISSET(t, flag)) { \ 75*2639ae9bSBen Gras (void)fprintf(stderr, "%s%s", sep, name); \ 76*2639ae9bSBen Gras sep = ", "; \ 77*2639ae9bSBen Gras } 78*2639ae9bSBen Gras if (t->flags != 0) { 79*2639ae9bSBen Gras sep = " flags ("; 80*2639ae9bSBen Gras X(R_FIXLEN, "FIXLEN"); 81*2639ae9bSBen Gras X(B_INMEM, "INMEM"); 82*2639ae9bSBen Gras X(B_NODUPS, "NODUPS"); 83*2639ae9bSBen Gras X(B_RDONLY, "RDONLY"); 84*2639ae9bSBen Gras X(R_RECNO, "RECNO"); 85*2639ae9bSBen Gras X(B_METADIRTY,"METADIRTY"); 86*2639ae9bSBen Gras (void)fprintf(stderr, ")\n"); 87*2639ae9bSBen Gras } 88*2639ae9bSBen Gras #undef X 89*2639ae9bSBen Gras 90*2639ae9bSBen Gras for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) { 91*2639ae9bSBen Gras __bt_dpage(h); 92*2639ae9bSBen Gras (void)mpool_put(t->bt_mp, h, 0); 93*2639ae9bSBen Gras } 94*2639ae9bSBen Gras } 95*2639ae9bSBen Gras 96*2639ae9bSBen Gras /* 97*2639ae9bSBen Gras * BT_DMPAGE -- Dump the meta page 98*2639ae9bSBen Gras * 99*2639ae9bSBen Gras * Parameters: 100*2639ae9bSBen Gras * h: pointer to the PAGE 101*2639ae9bSBen Gras */ 102*2639ae9bSBen Gras void 103*2639ae9bSBen Gras __bt_dmpage(PAGE *h) 104*2639ae9bSBen Gras { 105*2639ae9bSBen Gras BTMETA *m; 106*2639ae9bSBen Gras const char *sep; 107*2639ae9bSBen Gras 108*2639ae9bSBen Gras m = (BTMETA *)(void *)h; 109*2639ae9bSBen Gras (void)fprintf(stderr, "magic %lx\n", (unsigned long) m->magic); 110*2639ae9bSBen Gras (void)fprintf(stderr, "version %lu\n", (unsigned long) m->version); 111*2639ae9bSBen Gras (void)fprintf(stderr, "psize %lu\n", (unsigned long) m->psize); 112*2639ae9bSBen Gras (void)fprintf(stderr, "free %lu\n", (unsigned long) m->free); 113*2639ae9bSBen Gras (void)fprintf(stderr, "nrecs %lu\n", (unsigned long) m->nrecs); 114*2639ae9bSBen Gras (void)fprintf(stderr, "flags %lu", (unsigned long) m->flags); 115*2639ae9bSBen Gras #undef X 116*2639ae9bSBen Gras #define X(flag, name) \ 117*2639ae9bSBen Gras if (m->flags & flag) { \ 118*2639ae9bSBen Gras (void)fprintf(stderr, "%s%s", sep, name); \ 119*2639ae9bSBen Gras sep = ", "; \ 120*2639ae9bSBen Gras } 121*2639ae9bSBen Gras if (m->flags) { 122*2639ae9bSBen Gras sep = " ("; 123*2639ae9bSBen Gras X(B_NODUPS, "NODUPS"); 124*2639ae9bSBen Gras X(R_RECNO, "RECNO"); 125*2639ae9bSBen Gras (void)fprintf(stderr, ")"); 126*2639ae9bSBen Gras } 127*2639ae9bSBen Gras } 128*2639ae9bSBen Gras 129*2639ae9bSBen Gras /* 130*2639ae9bSBen Gras * BT_DNPAGE -- Dump the page 131*2639ae9bSBen Gras * 132*2639ae9bSBen Gras * Parameters: 133*2639ae9bSBen Gras * n: page number to dump. 134*2639ae9bSBen Gras */ 135*2639ae9bSBen Gras void 136*2639ae9bSBen Gras __bt_dnpage(DB *dbp, pgno_t pgno) 137*2639ae9bSBen Gras { 138*2639ae9bSBen Gras BTREE *t; 139*2639ae9bSBen Gras PAGE *h; 140*2639ae9bSBen Gras 141*2639ae9bSBen Gras t = dbp->internal; 142*2639ae9bSBen Gras if ((h = mpool_get(t->bt_mp, pgno, 0)) != NULL) { 143*2639ae9bSBen Gras __bt_dpage(h); 144*2639ae9bSBen Gras (void)mpool_put(t->bt_mp, h, 0); 145*2639ae9bSBen Gras } 146*2639ae9bSBen Gras } 147*2639ae9bSBen Gras 148*2639ae9bSBen Gras /* 149*2639ae9bSBen Gras * BT_DPAGE -- Dump the page 150*2639ae9bSBen Gras * 151*2639ae9bSBen Gras * Parameters: 152*2639ae9bSBen Gras * h: pointer to the PAGE 153*2639ae9bSBen Gras */ 154*2639ae9bSBen Gras void 155*2639ae9bSBen Gras __bt_dpage(PAGE *h) 156*2639ae9bSBen Gras { 157*2639ae9bSBen Gras BINTERNAL *bi; 158*2639ae9bSBen Gras BLEAF *bl; 159*2639ae9bSBen Gras RINTERNAL *ri; 160*2639ae9bSBen Gras RLEAF *rl; 161*2639ae9bSBen Gras indx_t cur, top; 162*2639ae9bSBen Gras const char *sep; 163*2639ae9bSBen Gras 164*2639ae9bSBen Gras (void)fprintf(stderr, " page %d: (", h->pgno); 165*2639ae9bSBen Gras #undef X 166*2639ae9bSBen Gras #define X(flag, name) \ 167*2639ae9bSBen Gras if (h->flags & flag) { \ 168*2639ae9bSBen Gras (void)fprintf(stderr, "%s%s", sep, name); \ 169*2639ae9bSBen Gras sep = ", "; \ 170*2639ae9bSBen Gras } 171*2639ae9bSBen Gras sep = ""; 172*2639ae9bSBen Gras X(P_BINTERNAL, "BINTERNAL") /* types */ 173*2639ae9bSBen Gras X(P_BLEAF, "BLEAF") 174*2639ae9bSBen Gras X(P_RINTERNAL, "RINTERNAL") /* types */ 175*2639ae9bSBen Gras X(P_RLEAF, "RLEAF") 176*2639ae9bSBen Gras X(P_OVERFLOW, "OVERFLOW") 177*2639ae9bSBen Gras X(P_PRESERVE, "PRESERVE"); 178*2639ae9bSBen Gras (void)fprintf(stderr, ")\n"); 179*2639ae9bSBen Gras #undef X 180*2639ae9bSBen Gras 181*2639ae9bSBen Gras (void)fprintf(stderr, "\tprev %2d next %2d", h->prevpg, h->nextpg); 182*2639ae9bSBen Gras if (h->flags & P_OVERFLOW) 183*2639ae9bSBen Gras return; 184*2639ae9bSBen Gras 185*2639ae9bSBen Gras top = NEXTINDEX(h); 186*2639ae9bSBen Gras (void)fprintf(stderr, " lower %3d upper %3d nextind %d\n", 187*2639ae9bSBen Gras h->lower, h->upper, top); 188*2639ae9bSBen Gras for (cur = 0; cur < top; cur++) { 189*2639ae9bSBen Gras (void)fprintf(stderr, "\t[%03d] %4d ", cur, h->linp[cur]); 190*2639ae9bSBen Gras switch (h->flags & P_TYPE) { 191*2639ae9bSBen Gras case P_BINTERNAL: 192*2639ae9bSBen Gras bi = GETBINTERNAL(h, cur); 193*2639ae9bSBen Gras (void)fprintf(stderr, 194*2639ae9bSBen Gras "size %03d pgno %03d", bi->ksize, bi->pgno); 195*2639ae9bSBen Gras if (bi->flags & P_BIGKEY) 196*2639ae9bSBen Gras (void)fprintf(stderr, " (indirect)"); 197*2639ae9bSBen Gras else if (bi->ksize) 198*2639ae9bSBen Gras (void)fprintf(stderr, 199*2639ae9bSBen Gras " {%.*s}", (int)bi->ksize, bi->bytes); 200*2639ae9bSBen Gras break; 201*2639ae9bSBen Gras case P_RINTERNAL: 202*2639ae9bSBen Gras ri = GETRINTERNAL(h, cur); 203*2639ae9bSBen Gras (void)fprintf(stderr, "entries %03d pgno %03d", 204*2639ae9bSBen Gras ri->nrecs, ri->pgno); 205*2639ae9bSBen Gras break; 206*2639ae9bSBen Gras case P_BLEAF: 207*2639ae9bSBen Gras bl = GETBLEAF(h, cur); 208*2639ae9bSBen Gras if (bl->flags & P_BIGKEY) 209*2639ae9bSBen Gras (void)fprintf(stderr, 210*2639ae9bSBen Gras "big key page %lu size %u/", 211*2639ae9bSBen Gras (unsigned long) *(pgno_t *)(void *)bl->bytes, 212*2639ae9bSBen Gras *(uint32_t *)(void *)(bl->bytes + sizeof(pgno_t))); 213*2639ae9bSBen Gras else if (bl->ksize) 214*2639ae9bSBen Gras (void)fprintf(stderr, "%s/", bl->bytes); 215*2639ae9bSBen Gras if (bl->flags & P_BIGDATA) 216*2639ae9bSBen Gras (void)fprintf(stderr, 217*2639ae9bSBen Gras "big data page %lu size %u", 218*2639ae9bSBen Gras (unsigned long) *(pgno_t *)(void *)(bl->bytes + bl->ksize), 219*2639ae9bSBen Gras *(uint32_t *)(void *)(bl->bytes + bl->ksize + 220*2639ae9bSBen Gras sizeof(pgno_t))); 221*2639ae9bSBen Gras else if (bl->dsize) 222*2639ae9bSBen Gras (void)fprintf(stderr, "%.*s", 223*2639ae9bSBen Gras (int)bl->dsize, bl->bytes + bl->ksize); 224*2639ae9bSBen Gras break; 225*2639ae9bSBen Gras case P_RLEAF: 226*2639ae9bSBen Gras rl = GETRLEAF(h, cur); 227*2639ae9bSBen Gras if (rl->flags & P_BIGDATA) 228*2639ae9bSBen Gras (void)fprintf(stderr, 229*2639ae9bSBen Gras "big data page %lu size %u", 230*2639ae9bSBen Gras (unsigned long) *(pgno_t *)(void *)rl->bytes, 231*2639ae9bSBen Gras *(uint32_t *)(void *)(rl->bytes + sizeof(pgno_t))); 232*2639ae9bSBen Gras else if (rl->dsize) 233*2639ae9bSBen Gras (void)fprintf(stderr, 234*2639ae9bSBen Gras "%.*s", (int)rl->dsize, rl->bytes); 235*2639ae9bSBen Gras break; 236*2639ae9bSBen Gras } 237*2639ae9bSBen Gras (void)fprintf(stderr, "\n"); 238*2639ae9bSBen Gras } 239*2639ae9bSBen Gras } 240*2639ae9bSBen Gras #endif 241*2639ae9bSBen Gras 242*2639ae9bSBen Gras #ifdef STATISTICS 243*2639ae9bSBen Gras /* 244*2639ae9bSBen Gras * BT_STAT -- Gather/print the tree statistics 245*2639ae9bSBen Gras * 246*2639ae9bSBen Gras * Parameters: 247*2639ae9bSBen Gras * dbp: pointer to the DB 248*2639ae9bSBen Gras */ 249*2639ae9bSBen Gras void 250*2639ae9bSBen Gras __bt_stat(DB *dbp) 251*2639ae9bSBen Gras { 252*2639ae9bSBen Gras extern unsigned long bt_cache_hit, bt_cache_miss, bt_pfxsaved, bt_rootsplit; 253*2639ae9bSBen Gras extern unsigned long bt_sortsplit, bt_split; 254*2639ae9bSBen Gras BTREE *t; 255*2639ae9bSBen Gras PAGE *h; 256*2639ae9bSBen Gras pgno_t i, pcont, pinternal, pleaf; 257*2639ae9bSBen Gras unsigned long ifree, lfree, nkeys; 258*2639ae9bSBen Gras int levels; 259*2639ae9bSBen Gras 260*2639ae9bSBen Gras t = dbp->internal; 261*2639ae9bSBen Gras pcont = pinternal = pleaf = 0; 262*2639ae9bSBen Gras nkeys = ifree = lfree = 0; 263*2639ae9bSBen Gras for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) { 264*2639ae9bSBen Gras switch (h->flags & P_TYPE) { 265*2639ae9bSBen Gras case P_BINTERNAL: 266*2639ae9bSBen Gras case P_RINTERNAL: 267*2639ae9bSBen Gras ++pinternal; 268*2639ae9bSBen Gras ifree += h->upper - h->lower; 269*2639ae9bSBen Gras break; 270*2639ae9bSBen Gras case P_BLEAF: 271*2639ae9bSBen Gras case P_RLEAF: 272*2639ae9bSBen Gras ++pleaf; 273*2639ae9bSBen Gras lfree += h->upper - h->lower; 274*2639ae9bSBen Gras nkeys += NEXTINDEX(h); 275*2639ae9bSBen Gras break; 276*2639ae9bSBen Gras case P_OVERFLOW: 277*2639ae9bSBen Gras ++pcont; 278*2639ae9bSBen Gras break; 279*2639ae9bSBen Gras } 280*2639ae9bSBen Gras (void)mpool_put(t->bt_mp, h, 0); 281*2639ae9bSBen Gras } 282*2639ae9bSBen Gras 283*2639ae9bSBen Gras /* Count the levels of the tree. */ 284*2639ae9bSBen Gras for (i = P_ROOT, levels = 0 ;; ++levels) { 285*2639ae9bSBen Gras h = mpool_get(t->bt_mp, i, 0); 286*2639ae9bSBen Gras if (h->flags & (P_BLEAF|P_RLEAF)) { 287*2639ae9bSBen Gras if (levels == 0) 288*2639ae9bSBen Gras levels = 1; 289*2639ae9bSBen Gras (void)mpool_put(t->bt_mp, h, 0); 290*2639ae9bSBen Gras break; 291*2639ae9bSBen Gras } 292*2639ae9bSBen Gras i = F_ISSET(t, R_RECNO) ? 293*2639ae9bSBen Gras GETRINTERNAL(h, 0)->pgno : 294*2639ae9bSBen Gras GETBINTERNAL(h, 0)->pgno; 295*2639ae9bSBen Gras (void)mpool_put(t->bt_mp, h, 0); 296*2639ae9bSBen Gras } 297*2639ae9bSBen Gras 298*2639ae9bSBen Gras (void)fprintf(stderr, "%d level%s with %ld keys", 299*2639ae9bSBen Gras levels, levels == 1 ? "" : "s", nkeys); 300*2639ae9bSBen Gras if (F_ISSET(t, R_RECNO)) 301*2639ae9bSBen Gras (void)fprintf(stderr, " (%ld header count)", (long)t->bt_nrecs); 302*2639ae9bSBen Gras (void)fprintf(stderr, 303*2639ae9bSBen Gras "\n%lu pages (leaf %ld, internal %ld, overflow %ld)\n", 304*2639ae9bSBen Gras (long)pinternal + pleaf + pcont, (long)pleaf, (long)pinternal, 305*2639ae9bSBen Gras (long)pcont); 306*2639ae9bSBen Gras (void)fprintf(stderr, "%ld cache hits, %ld cache misses\n", 307*2639ae9bSBen Gras bt_cache_hit, bt_cache_miss); 308*2639ae9bSBen Gras (void)fprintf(stderr, "%ld splits (%ld root splits, %ld sort splits)\n", 309*2639ae9bSBen Gras bt_split, bt_rootsplit, bt_sortsplit); 310*2639ae9bSBen Gras pleaf *= t->bt_psize - BTDATAOFF; 311*2639ae9bSBen Gras if (pleaf) 312*2639ae9bSBen Gras (void)fprintf(stderr, 313*2639ae9bSBen Gras "%.0f%% leaf fill (%ld bytes used, %ld bytes free)\n", 314*2639ae9bSBen Gras ((double)(pleaf - lfree) / pleaf) * 100, 315*2639ae9bSBen Gras pleaf - lfree, lfree); 316*2639ae9bSBen Gras pinternal *= t->bt_psize - BTDATAOFF; 317*2639ae9bSBen Gras if (pinternal) 318*2639ae9bSBen Gras (void)fprintf(stderr, 319*2639ae9bSBen Gras "%.0f%% internal fill (%ld bytes used, %ld bytes free\n", 320*2639ae9bSBen Gras ((double)(pinternal - ifree) / pinternal) * 100, 321*2639ae9bSBen Gras pinternal - ifree, ifree); 322*2639ae9bSBen Gras if (bt_pfxsaved) 323*2639ae9bSBen Gras (void)fprintf(stderr, "prefix checking removed %lu bytes.\n", 324*2639ae9bSBen Gras bt_pfxsaved); 325*2639ae9bSBen Gras } 326*2639ae9bSBen Gras #endif 327