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