xref: /csrg-svn/lib/libc/db/btree/bt_debug.c (revision 50990)
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