db_pr.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:29k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1996, 1997, 1998, 1999, 2000
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: db_pr.c,v 11.46 2001/01/22 17:25:06 krinsky Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #include <ctype.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <unistd.h>
  17. #endif
  18. #include "db_int.h"
  19. #include "db_page.h"
  20. #include "btree.h"
  21. #include "hash.h"
  22. #include "qam.h"
  23. #include "db_am.h"
  24. #include "db_verify.h"
  25. static int  __db_bmeta __P((DB *, FILE *, BTMETA *, u_int32_t));
  26. static int  __db_hmeta __P((DB *, FILE *, HMETA *, u_int32_t));
  27. static void  __db_meta __P((DB *, DBMETA *, FILE *, FN const *, u_int32_t));
  28. static const char *__db_dbtype_to_string __P((DB *));
  29. static void  __db_prdb __P((DB *, FILE *, u_int32_t));
  30. static FILE *__db_prinit __P((FILE *));
  31. static void  __db_proff __P((void *));
  32. static int  __db_prtree __P((DB *, u_int32_t));
  33. static void  __db_psize __P((DB *));
  34. static int  __db_qmeta __P((DB *, FILE *, QMETA *, u_int32_t));
  35. /*
  36.  * 64K is the maximum page size, so by default we check for offsets larger
  37.  * than that, and, where possible, we refine the test.
  38.  */
  39. #define PSIZE_BOUNDARY (64 * 1024 + 1)
  40. static size_t set_psize = PSIZE_BOUNDARY;
  41. static FILE *set_fp; /* Output file descriptor. */
  42. /*
  43.  * __db_loadme --
  44.  * A nice place to put a breakpoint.
  45.  *
  46.  * PUBLIC: void __db_loadme __P((void));
  47.  */
  48. void
  49. __db_loadme()
  50. {
  51. getpid();
  52. }
  53. /*
  54.  * __db_dump --
  55.  * Dump the tree to a file.
  56.  *
  57.  * PUBLIC: int __db_dump __P((DB *, char *, char *));
  58.  */
  59. int
  60. __db_dump(dbp, op, name)
  61. DB *dbp;
  62. char *op, *name;
  63. {
  64. FILE *fp, *save_fp;
  65. u_int32_t flags;
  66. COMPQUIET(save_fp, NULL);
  67. if (set_psize == PSIZE_BOUNDARY)
  68. __db_psize(dbp);
  69. if (name != NULL) {
  70. if ((fp = fopen(name, "w")) == NULL)
  71. return (__os_get_errno());
  72. save_fp = set_fp;
  73. set_fp = fp;
  74. } else
  75. fp = __db_prinit(NULL);
  76. for (flags = 0; *op != ''; ++op)
  77. switch (*op) {
  78. case 'a':
  79. LF_SET(DB_PR_PAGE);
  80. break;
  81. case 'h':
  82. break;
  83. case 'r':
  84. LF_SET(DB_PR_RECOVERYTEST);
  85. break;
  86. default:
  87. return (EINVAL);
  88. }
  89. __db_prdb(dbp, fp, flags);
  90. fprintf(fp, "%sn", DB_LINE);
  91. (void)__db_prtree(dbp, flags);
  92. fflush(fp);
  93. if (name != NULL) {
  94. fclose(fp);
  95. set_fp = save_fp;
  96. }
  97. return (0);
  98. }
  99. /*
  100.  * __db_prdb --
  101.  * Print out the DB structure information.
  102.  */
  103. static void
  104. __db_prdb(dbp, fp, flags)
  105. DB *dbp;
  106. FILE *fp;
  107. u_int32_t flags;
  108. {
  109. static const FN fn[] = {
  110. { DB_AM_DISCARD, "discard cached pages" },
  111. { DB_AM_DUP, "duplicates" },
  112. { DB_AM_INMEM, "in-memory" },
  113. { DB_AM_PGDEF, "default page size" },
  114. { DB_AM_RDONLY, "read-only" },
  115. { DB_AM_SUBDB, "multiple-databases" },
  116. { DB_AM_SWAP, "needswap" },
  117. { DB_BT_RECNUM, "btree:recnum" },
  118. { DB_BT_REVSPLIT, "btree:no reverse split" },
  119. { DB_DBM_ERROR, "dbm/ndbm error" },
  120. { DB_OPEN_CALLED, "DB->open called" },
  121. { DB_RE_DELIMITER, "recno:delimiter" },
  122. { DB_RE_FIXEDLEN, "recno:fixed-length" },
  123. { DB_RE_PAD, "recno:pad" },
  124. { DB_RE_RENUMBER, "recno:renumber" },
  125. { DB_RE_SNAPSHOT, "recno:snapshot" },
  126. { 0, NULL }
  127. };
  128. BTREE *bt;
  129. HASH *h;
  130. QUEUE *q;
  131. COMPQUIET(flags, 0);
  132. fprintf(fp,
  133.     "In-memory DB structure:n%s: %#lx",
  134.     __db_dbtype_to_string(dbp), (u_long)dbp->flags);
  135. __db_prflags(dbp->flags, fn, fp);
  136. fprintf(fp, "n");
  137. switch (dbp->type) {
  138. case DB_BTREE:
  139. case DB_RECNO:
  140. bt = dbp->bt_internal;
  141. fprintf(fp, "bt_meta: %lu bt_root: %lun",
  142.     (u_long)bt->bt_meta, (u_long)bt->bt_root);
  143. fprintf(fp, "bt_maxkey: %lu bt_minkey: %lun",
  144.     (u_long)bt->bt_maxkey, (u_long)bt->bt_minkey);
  145. fprintf(fp, "bt_compare: %#lx bt_prefix: %#lxn",
  146.     (u_long)bt->bt_compare, (u_long)bt->bt_prefix);
  147. fprintf(fp, "bt_lpgno: %lun", (u_long)bt->bt_lpgno);
  148. if (dbp->type == DB_RECNO) {
  149. fprintf(fp,
  150.     "re_pad: %#lx re_delim: %#lx re_len: %lu re_source: %sn",
  151.     (u_long)bt->re_pad, (u_long)bt->re_delim,
  152.     (u_long)bt->re_len,
  153.     bt->re_source == NULL ? "" : bt->re_source);
  154. fprintf(fp, "re_modified: %d re_eof: %d re_last: %lun",
  155.     bt->re_modified, bt->re_eof, (u_long)bt->re_last);
  156. }
  157. break;
  158. case DB_HASH:
  159. h = dbp->h_internal;
  160. fprintf(fp, "meta_pgno: %lun", (u_long)h->meta_pgno);
  161. fprintf(fp, "h_ffactor: %lun", (u_long)h->h_ffactor);
  162. fprintf(fp, "h_nelem: %lun", (u_long)h->h_nelem);
  163. fprintf(fp, "h_hash: %#lxn", (u_long)h->h_hash);
  164. break;
  165. case DB_QUEUE:
  166. q = dbp->q_internal;
  167. fprintf(fp, "q_meta: %lun", (u_long)q->q_meta);
  168. fprintf(fp, "q_root: %lun", (u_long)q->q_root);
  169. fprintf(fp, "re_pad: %#lx re_len: %lun",
  170.     (u_long)q->re_pad, (u_long)q->re_len);
  171. fprintf(fp, "rec_page: %lun", (u_long)q->rec_page);
  172. fprintf(fp, "page_ext: %lun", (u_long)q->page_ext);
  173. break;
  174. default:
  175. break;
  176. }
  177. }
  178. /*
  179.  * __db_prtree --
  180.  * Print out the entire tree.
  181.  */
  182. static int
  183. __db_prtree(dbp, flags)
  184. DB *dbp;
  185. u_int32_t flags;
  186. {
  187. PAGE *h;
  188. db_pgno_t i, last;
  189. int ret;
  190. if (set_psize == PSIZE_BOUNDARY)
  191. __db_psize(dbp);
  192. if (dbp->type == DB_QUEUE) {
  193. ret = __db_prqueue(dbp, flags);
  194. goto done;
  195. }
  196. /* Find out the page number of the last page in the database. */
  197. if ((ret = memp_fget(dbp->mpf, &last, DB_MPOOL_LAST, &h)) != 0)
  198. return (ret);
  199. if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
  200. return (ret);
  201. /* Dump each page. */
  202. for (i = 0; i <= last; ++i) {
  203. if ((ret = memp_fget(dbp->mpf, &i, 0, &h)) != 0)
  204. return (ret);
  205. (void)__db_prpage(dbp, h, flags);
  206. if ((ret = memp_fput(dbp->mpf, h, 0)) != 0)
  207. return (ret);
  208. }
  209. done:
  210. (void)fflush(__db_prinit(NULL));
  211. return (0);
  212. }
  213. /*
  214.  * __db_meta --
  215.  * Print out common metadata information.
  216.  */
  217. static void
  218. __db_meta(dbp, dbmeta, fp, fn, flags)
  219. DB *dbp;
  220. DBMETA *dbmeta;
  221. FILE *fp;
  222. FN const *fn;
  223. u_int32_t flags;
  224. {
  225. PAGE *h;
  226. int cnt;
  227. db_pgno_t pgno;
  228. u_int8_t *p;
  229. int ret;
  230. const char *sep;
  231. fprintf(fp, "tmagic: %#lxn", (u_long)dbmeta->magic);
  232. fprintf(fp, "tversion: %lun", (u_long)dbmeta->version);
  233. fprintf(fp, "tpagesize: %lun", (u_long)dbmeta->pagesize);
  234. fprintf(fp, "ttype: %lun", (u_long)dbmeta->type);
  235. fprintf(fp, "tkeys: %lutrecords: %lun",
  236.     (u_long)dbmeta->key_count, (u_long)dbmeta->record_count);
  237. if (!LF_ISSET(DB_PR_RECOVERYTEST)) {
  238. /*
  239.  * If we're doing recovery testing, don't display the free
  240.  * list, it may have changed and that makes the dump diff
  241.  * not work.
  242.  */
  243. fprintf(fp, "tfree list: %lu", (u_long)dbmeta->free);
  244. for (pgno = dbmeta->free,
  245.     cnt = 0, sep = ", "; pgno != PGNO_INVALID;) {
  246. if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0) {
  247. fprintf(fp,
  248.     "Unable to retrieve free-list page: %lu: %sn",
  249.     (u_long)pgno, db_strerror(ret));
  250. break;
  251. }
  252. pgno = h->next_pgno;
  253. (void)memp_fput(dbp->mpf, h, 0);
  254. fprintf(fp, "%s%lu", sep, (u_long)pgno);
  255. if (++cnt % 10 == 0) {
  256. fprintf(fp, "n");
  257. cnt = 0;
  258. sep = "t";
  259. } else
  260. sep = ", ";
  261. }
  262. fprintf(fp, "n");
  263. }
  264. if (fn != NULL) {
  265. fprintf(fp, "tflags: %#lx", (u_long)dbmeta->flags);
  266. __db_prflags(dbmeta->flags, fn, fp);
  267. fprintf(fp, "n");
  268. }
  269. fprintf(fp, "tuid: ");
  270. for (p = (u_int8_t *)dbmeta->uid,
  271.     cnt = 0; cnt < DB_FILE_ID_LEN; ++cnt) {
  272. fprintf(fp, "%x", *p++);
  273. if (cnt < DB_FILE_ID_LEN - 1)
  274. fprintf(fp, " ");
  275. }
  276. fprintf(fp, "n");
  277. }
  278. /*
  279.  * __db_bmeta --
  280.  * Print out the btree meta-data page.
  281.  */
  282. static int
  283. __db_bmeta(dbp, fp, h, flags)
  284. DB *dbp;
  285. FILE *fp;
  286. BTMETA *h;
  287. u_int32_t flags;
  288. {
  289. static const FN mfn[] = {
  290. { BTM_DUP, "duplicates" },
  291. { BTM_RECNO, "recno" },
  292. { BTM_RECNUM, "btree:recnum" },
  293. { BTM_FIXEDLEN, "recno:fixed-length" },
  294. { BTM_RENUMBER, "recno:renumber" },
  295. { BTM_SUBDB, "multiple-databases" },
  296. { 0, NULL }
  297. };
  298. __db_meta(dbp, (DBMETA *)h, fp, mfn, flags);
  299. fprintf(fp, "tmaxkey: %lu minkey: %lun",
  300.     (u_long)h->maxkey, (u_long)h->minkey);
  301. if (dbp->type == DB_RECNO)
  302. fprintf(fp, "tre_len: %#lx re_pad: %lun",
  303.     (u_long)h->re_len, (u_long)h->re_pad);
  304. fprintf(fp, "troot: %lun", (u_long)h->root);
  305. return (0);
  306. }
  307. /*
  308.  * __db_hmeta --
  309.  * Print out the hash meta-data page.
  310.  */
  311. static int
  312. __db_hmeta(dbp, fp, h, flags)
  313. DB *dbp;
  314. FILE *fp;
  315. HMETA *h;
  316. u_int32_t flags;
  317. {
  318. static const FN mfn[] = {
  319. { DB_HASH_DUP,  "duplicates" },
  320. { DB_HASH_SUBDB, "multiple-databases" },
  321. { 0,  NULL }
  322. };
  323. int i;
  324. __db_meta(dbp, (DBMETA *)h, fp, mfn, flags);
  325. fprintf(fp, "tmax_bucket: %lun", (u_long)h->max_bucket);
  326. fprintf(fp, "thigh_mask: %#lxn", (u_long)h->high_mask);
  327. fprintf(fp, "tlow_mask:  %#lxn", (u_long)h->low_mask);
  328. fprintf(fp, "tffactor: %lun", (u_long)h->ffactor);
  329. fprintf(fp, "tnelem: %lun", (u_long)h->nelem);
  330. fprintf(fp, "th_charkey: %#lxn", (u_long)h->h_charkey);
  331. fprintf(fp, "tspare points: ");
  332. for (i = 0; i < NCACHED; i++)
  333. fprintf(fp, "%lu ", (u_long)h->spares[i]);
  334. fprintf(fp, "n");
  335. return (0);
  336. }
  337. /*
  338.  * __db_qmeta --
  339.  * Print out the queue meta-data page.
  340.  */
  341. static int
  342. __db_qmeta(dbp, fp, h, flags)
  343. DB *dbp;
  344. FILE *fp;
  345. QMETA *h;
  346. u_int32_t flags;
  347. {
  348. __db_meta(dbp, (DBMETA *)h, fp, NULL, flags);
  349. fprintf(fp, "tfirst_recno: %lun", (u_long)h->first_recno);
  350. fprintf(fp, "tcur_recno: %lun", (u_long)h->cur_recno);
  351. fprintf(fp, "tre_len: %#lx re_pad: %lun",
  352.     (u_long)h->re_len, (u_long)h->re_pad);
  353. fprintf(fp, "trec_page: %lun", (u_long)h->rec_page);
  354. fprintf(fp, "tpage_ext: %lun", (u_long)h->page_ext);
  355. return (0);
  356. }
  357. /*
  358.  * __db_prnpage
  359.  * -- Print out a specific page.
  360.  *
  361.  * PUBLIC: int __db_prnpage __P((DB *, db_pgno_t));
  362.  */
  363. int
  364. __db_prnpage(dbp, pgno)
  365. DB *dbp;
  366. db_pgno_t pgno;
  367. {
  368. PAGE *h;
  369. int ret;
  370. if (set_psize == PSIZE_BOUNDARY)
  371. __db_psize(dbp);
  372. if ((ret = memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
  373. return (ret);
  374. ret = __db_prpage(dbp, h, DB_PR_PAGE);
  375. (void)fflush(__db_prinit(NULL));
  376. (void)memp_fput(dbp->mpf, h, 0);
  377. return (ret);
  378. }
  379. /*
  380.  * __db_prpage
  381.  * -- Print out a page.
  382.  *
  383.  * PUBLIC: int __db_prpage __P((DB *, PAGE *, u_int32_t));
  384.  */
  385. int
  386. __db_prpage(dbp, h, flags)
  387. DB *dbp;
  388. PAGE *h;
  389. u_int32_t flags;
  390. {
  391. BINTERNAL *bi;
  392. BKEYDATA *bk;
  393. BTREE *t;
  394. FILE *fp;
  395. HOFFPAGE a_hkd;
  396. QAMDATA *qp, *qep;
  397. RINTERNAL *ri;
  398. db_indx_t dlen, len, i;
  399. db_pgno_t pgno;
  400. db_recno_t recno;
  401. int deleted, ret;
  402. const char *s;
  403. u_int32_t qlen;
  404. u_int8_t *ep, *hk, *p;
  405. void *sp;
  406. fp = __db_prinit(NULL);
  407. /*
  408.  * If we're doing recovery testing and this page is P_INVALID,
  409.  * assume it's a page that's on the free list, and don't display it.
  410.  */
  411. if (LF_ISSET(DB_PR_RECOVERYTEST) && TYPE(h) == P_INVALID)
  412. return (0);
  413. s = __db_pagetype_to_string(TYPE(h));
  414. if (s == NULL) {
  415. fprintf(fp, "ILLEGAL PAGE TYPE: page: %lu type: %lun",
  416.     (u_long)h->pgno, (u_long)TYPE(h));
  417. return (1);
  418. }
  419. /* Page number, page type. */
  420. fprintf(fp, "page %lu: %s level: %lu",
  421.     (u_long)h->pgno, s, (u_long)h->level);
  422. /* Record count. */
  423. if (TYPE(h) == P_IBTREE ||
  424.     TYPE(h) == P_IRECNO || (TYPE(h) == P_LRECNO &&
  425.     h->pgno == ((BTREE *)dbp->bt_internal)->bt_root))
  426. fprintf(fp, " records: %lu", (u_long)RE_NREC(h));
  427. /* LSN. */
  428. if (!LF_ISSET(DB_PR_RECOVERYTEST))
  429. fprintf(fp, " (lsn.file: %lu lsn.offset: %lu)n",
  430.     (u_long)LSN(h).file, (u_long)LSN(h).offset);
  431. switch (TYPE(h)) {
  432. case P_BTREEMETA:
  433. return (__db_bmeta(dbp, fp, (BTMETA *)h, flags));
  434. case P_HASHMETA:
  435. return (__db_hmeta(dbp, fp, (HMETA *)h, flags));
  436. case P_QAMMETA:
  437. return (__db_qmeta(dbp, fp, (QMETA *)h, flags));
  438. case P_QAMDATA: /* Should be meta->start. */
  439. if (!LF_ISSET(DB_PR_PAGE))
  440. return (0);
  441. qlen = ((QUEUE *)dbp->q_internal)->re_len;
  442. recno = (h->pgno - 1) * QAM_RECNO_PER_PAGE(dbp) + 1;
  443. i = 0;
  444. qep = (QAMDATA *)((u_int8_t *)h + set_psize - qlen);
  445. for (qp = QAM_GET_RECORD(dbp, h, i); qp < qep;
  446.     recno++, i++, qp = QAM_GET_RECORD(dbp, h, i)) {
  447. if (!F_ISSET(qp, QAM_SET))
  448. continue;
  449. fprintf(fp, "%s",
  450.     F_ISSET(qp, QAM_VALID) ? "t" : "       D");
  451. fprintf(fp, "[%03lu] %4lu ",
  452.     (u_long)recno, (u_long)qp - (u_long)h);
  453. __db_pr(qp->data, qlen);
  454. }
  455. return (0);
  456. }
  457. /* LSN. */
  458. if (LF_ISSET(DB_PR_RECOVERYTEST))
  459. fprintf(fp, " (lsn.file: %lu lsn.offset: %lu)n",
  460.     (u_long)LSN(h).file, (u_long)LSN(h).offset);
  461. t = dbp->bt_internal;
  462. s = "t";
  463. if (TYPE(h) != P_IBTREE && TYPE(h) != P_IRECNO) {
  464. fprintf(fp, "%sprev: %4lu next: %4lu",
  465.     s, (u_long)PREV_PGNO(h), (u_long)NEXT_PGNO(h));
  466. s = " ";
  467. }
  468. if (TYPE(h) == P_OVERFLOW) {
  469. fprintf(fp, "%sref cnt: %4lu ", s, (u_long)OV_REF(h));
  470. __db_pr((u_int8_t *)h + P_OVERHEAD, OV_LEN(h));
  471. return (0);
  472. }
  473. fprintf(fp, "%sentries: %4lu", s, (u_long)NUM_ENT(h));
  474. fprintf(fp, " offset: %4lun", (u_long)HOFFSET(h));
  475. if (TYPE(h) == P_INVALID || !LF_ISSET(DB_PR_PAGE))
  476. return (0);
  477. ret = 0;
  478. for (i = 0; i < NUM_ENT(h); i++) {
  479. if (P_ENTRY(h, i) - (u_int8_t *)h < P_OVERHEAD ||
  480.     (size_t)(P_ENTRY(h, i) - (u_int8_t *)h) >= set_psize) {
  481. fprintf(fp,
  482.     "ILLEGAL PAGE OFFSET: indx: %lu of %lun",
  483.     (u_long)i, (u_long)h->inp[i]);
  484. ret = EINVAL;
  485. continue;
  486. }
  487. deleted = 0;
  488. switch (TYPE(h)) {
  489. case P_HASH:
  490. case P_IBTREE:
  491. case P_IRECNO:
  492. sp = P_ENTRY(h, i);
  493. break;
  494. case P_LBTREE:
  495. sp = P_ENTRY(h, i);
  496. deleted = i % 2 == 0 &&
  497.     B_DISSET(GET_BKEYDATA(h, i + O_INDX)->type);
  498. break;
  499. case P_LDUP:
  500. case P_LRECNO:
  501. sp = P_ENTRY(h, i);
  502. deleted = B_DISSET(GET_BKEYDATA(h, i)->type);
  503. break;
  504. default:
  505. fprintf(fp,
  506.     "ILLEGAL PAGE ITEM: %lun", (u_long)TYPE(h));
  507. ret = EINVAL;
  508. continue;
  509. }
  510. fprintf(fp, "%s", deleted ? "       D" : "t");
  511. fprintf(fp, "[%03lu] %4lu ", (u_long)i, (u_long)h->inp[i]);
  512. switch (TYPE(h)) {
  513. case P_HASH:
  514. hk = sp;
  515. switch (HPAGE_PTYPE(hk)) {
  516. case H_OFFDUP:
  517. memcpy(&pgno,
  518.     HOFFDUP_PGNO(hk), sizeof(db_pgno_t));
  519. fprintf(fp,
  520.     "%4lu [offpage dups]n", (u_long)pgno);
  521. break;
  522. case H_DUPLICATE:
  523. /*
  524.  * If this is the first item on a page, then
  525.  * we cannot figure out how long it is, so
  526.  * we only print the first one in the duplicate
  527.  * set.
  528.  */
  529. if (i != 0)
  530. len = LEN_HKEYDATA(h, 0, i);
  531. else
  532. len = 1;
  533. fprintf(fp, "Duplicates:n");
  534. for (p = HKEYDATA_DATA(hk),
  535.     ep = p + len; p < ep;) {
  536. memcpy(&dlen, p, sizeof(db_indx_t));
  537. p += sizeof(db_indx_t);
  538. fprintf(fp, "tt");
  539. __db_pr(p, dlen);
  540. p += sizeof(db_indx_t) + dlen;
  541. }
  542. break;
  543. case H_KEYDATA:
  544. __db_pr(HKEYDATA_DATA(hk),
  545.     LEN_HKEYDATA(h, i == 0 ? set_psize : 0, i));
  546. break;
  547. case H_OFFPAGE:
  548. memcpy(&a_hkd, hk, HOFFPAGE_SIZE);
  549. fprintf(fp,
  550.     "overflow: total len: %4lu page: %4lun",
  551.     (u_long)a_hkd.tlen, (u_long)a_hkd.pgno);
  552. break;
  553. }
  554. break;
  555. case P_IBTREE:
  556. bi = sp;
  557. fprintf(fp, "count: %4lu pgno: %4lu type: %4lu",
  558.     (u_long)bi->nrecs, (u_long)bi->pgno,
  559.     (u_long)bi->type);
  560. switch (B_TYPE(bi->type)) {
  561. case B_KEYDATA:
  562. __db_pr(bi->data, bi->len);
  563. break;
  564. case B_DUPLICATE:
  565. case B_OVERFLOW:
  566. __db_proff(bi->data);
  567. break;
  568. default:
  569. fprintf(fp, "ILLEGAL BINTERNAL TYPE: %lun",
  570.     (u_long)B_TYPE(bi->type));
  571. ret = EINVAL;
  572. break;
  573. }
  574. break;
  575. case P_IRECNO:
  576. ri = sp;
  577. fprintf(fp, "entries %4lu pgno %4lun",
  578.     (u_long)ri->nrecs, (u_long)ri->pgno);
  579. break;
  580. case P_LBTREE:
  581. case P_LDUP:
  582. case P_LRECNO:
  583. bk = sp;
  584. switch (B_TYPE(bk->type)) {
  585. case B_KEYDATA:
  586. __db_pr(bk->data, bk->len);
  587. break;
  588. case B_DUPLICATE:
  589. case B_OVERFLOW:
  590. __db_proff(bk);
  591. break;
  592. default:
  593. fprintf(fp,
  594.     "ILLEGAL DUPLICATE/LBTREE/LRECNO TYPE: %lun",
  595.     (u_long)B_TYPE(bk->type));
  596. ret = EINVAL;
  597. break;
  598. }
  599. break;
  600. }
  601. }
  602. (void)fflush(fp);
  603. return (ret);
  604. }
  605. /*
  606.  * __db_pr --
  607.  * Print out a data element.
  608.  *
  609.  * PUBLIC: void __db_pr __P((u_int8_t *, u_int32_t));
  610.  */
  611. void
  612. __db_pr(p, len)
  613. u_int8_t *p;
  614. u_int32_t len;
  615. {
  616. FILE *fp;
  617. u_int lastch;
  618. int i;
  619. fp = __db_prinit(NULL);
  620. fprintf(fp, "len: %3lu", (u_long)len);
  621. lastch = '.';
  622. if (len != 0) {
  623. fprintf(fp, " data: ");
  624. for (i = len <= 20 ? len : 20; i > 0; --i, ++p) {
  625. lastch = *p;
  626. if (isprint((int)*p) || *p == 'n')
  627. fprintf(fp, "%c", *p);
  628. else
  629. fprintf(fp, "0x%.2x", (u_int)*p);
  630. }
  631. if (len > 20) {
  632. fprintf(fp, "...");
  633. lastch = '.';
  634. }
  635. }
  636. if (lastch != 'n')
  637. fprintf(fp, "n");
  638. }
  639. /*
  640.  * __db_prdbt --
  641.  * Print out a DBT data element.
  642.  *
  643.  * PUBLIC: int __db_prdbt __P((DBT *, int, const char *, void *,
  644.  * PUBLIC:     int (*)(void *, const void *), int, VRFY_DBINFO *));
  645.  */
  646. int
  647. __db_prdbt(dbtp, checkprint, prefix, handle, callback, is_recno, vdp)
  648. DBT *dbtp;
  649. int checkprint;
  650. const char *prefix;
  651. void *handle;
  652. int (*callback) __P((void *, const void *));
  653. int is_recno;
  654. VRFY_DBINFO *vdp;
  655. {
  656. static const char hex[] = "0123456789abcdef";
  657. db_recno_t recno;
  658. u_int32_t len;
  659. int ret;
  660. #define DBTBUFLEN 100
  661. char *p, *hp, buf[DBTBUFLEN], hbuf[DBTBUFLEN];
  662. if (vdp != NULL) {
  663. /*
  664.  * If vdp is non-NULL, we might be the first key in the
  665.  * "fake" subdatabase used for key/data pairs we can't
  666.  * associate with a known subdb.
  667.  *
  668.  * Check and clear the SALVAGE_PRINTHEADER flag;  if
  669.  * it was set, print a subdatabase header.
  670.  */
  671. if (F_ISSET(vdp, SALVAGE_PRINTHEADER))
  672. (void)__db_prheader(NULL, "__OTHER__", 0, 0,
  673.     handle, callback, vdp, 0);
  674. F_CLR(vdp, SALVAGE_PRINTHEADER);
  675. F_SET(vdp, SALVAGE_PRINTFOOTER);
  676. }
  677. /*
  678.  * !!!
  679.  * This routine is the routine that dumps out items in the format
  680.  * used by db_dump(1) and db_load(1).  This means that the format
  681.  * cannot change.
  682.  */
  683. if (prefix != NULL && (ret = callback(handle, prefix)) != 0)
  684. return (ret);
  685. if (is_recno) {
  686. /*
  687.  * We're printing a record number, and this has to be done
  688.  * in a platform-independent way.  So we use the numeral in
  689.  * straight ASCII.
  690.  */
  691. __ua_memcpy(&recno, dbtp->data, sizeof(recno));
  692. snprintf(buf, DBTBUFLEN, "%lu", (u_long)recno);
  693. /* If we're printing data as hex, print keys as hex too. */
  694. if (!checkprint) {
  695. for (len = strlen(buf), p = buf, hp = hbuf;
  696.     len-- > 0; ++p) {
  697. *hp++ = hex[(u_int8_t)(*p & 0xf0) >> 4];
  698. *hp++ = hex[*p & 0x0f];
  699. }
  700. *hp = '';
  701. ret = callback(handle, hbuf);
  702. } else
  703. ret = callback(handle, buf);
  704. if (ret != 0)
  705. return (ret);
  706. } else if (checkprint) {
  707. for (len = dbtp->size, p = dbtp->data; len--; ++p)
  708. if (isprint((int)*p)) {
  709. if (*p == '\' &&
  710.     (ret = callback(handle, "\")) != 0)
  711. return (ret);
  712. snprintf(buf, DBTBUFLEN, "%c", *p);
  713. if ((ret = callback(handle, buf)) != 0)
  714. return (ret);
  715. } else {
  716. snprintf(buf, DBTBUFLEN, "\%c%c",
  717.     hex[(u_int8_t)(*p & 0xf0) >> 4],
  718.     hex[*p & 0x0f]);
  719. if ((ret = callback(handle, buf)) != 0)
  720. return (ret);
  721. }
  722. } else
  723. for (len = dbtp->size, p = dbtp->data; len--; ++p) {
  724. snprintf(buf, DBTBUFLEN, "%c%c",
  725.     hex[(u_int8_t)(*p & 0xf0) >> 4],
  726.     hex[*p & 0x0f]);
  727. if ((ret = callback(handle, buf)) != 0)
  728. return (ret);
  729. }
  730. return (callback(handle, "n"));
  731. }
  732. /*
  733.  * __db_proff --
  734.  * Print out an off-page element.
  735.  */
  736. static void
  737. __db_proff(vp)
  738. void *vp;
  739. {
  740. FILE *fp;
  741. BOVERFLOW *bo;
  742. fp = __db_prinit(NULL);
  743. bo = vp;
  744. switch (B_TYPE(bo->type)) {
  745. case B_OVERFLOW:
  746. fprintf(fp, "overflow: total len: %4lu page: %4lun",
  747.     (u_long)bo->tlen, (u_long)bo->pgno);
  748. break;
  749. case B_DUPLICATE:
  750. fprintf(fp, "duplicate: page: %4lun", (u_long)bo->pgno);
  751. break;
  752. }
  753. }
  754. /*
  755.  * __db_prflags --
  756.  * Print out flags values.
  757.  *
  758.  * PUBLIC: void __db_prflags __P((u_int32_t, const FN *, FILE *));
  759.  */
  760. void
  761. __db_prflags(flags, fn, fp)
  762. u_int32_t flags;
  763. FN const *fn;
  764. FILE *fp;
  765. {
  766. const FN *fnp;
  767. int found;
  768. const char *sep;
  769. sep = " (";
  770. for (found = 0, fnp = fn; fnp->mask != 0; ++fnp)
  771. if (LF_ISSET(fnp->mask)) {
  772. fprintf(fp, "%s%s", sep, fnp->name);
  773. sep = ", ";
  774. found = 1;
  775. }
  776. if (found)
  777. fprintf(fp, ")");
  778. }
  779. /*
  780.  * __db_prinit --
  781.  * Initialize tree printing routines.
  782.  */
  783. static FILE *
  784. __db_prinit(fp)
  785. FILE *fp;
  786. {
  787. if (set_fp == NULL)
  788. set_fp = fp == NULL ? stdout : fp;
  789. return (set_fp);
  790. }
  791. /*
  792.  * __db_psize --
  793.  * Get the page size.
  794.  */
  795. static void
  796. __db_psize(dbp)
  797. DB *dbp;
  798. {
  799. DBMETA *mp;
  800. db_pgno_t pgno;
  801. set_psize = PSIZE_BOUNDARY - 1;
  802. pgno = PGNO_BASE_MD;
  803. if (memp_fget(dbp->mpf, &pgno, 0, &mp) != 0)
  804. return;
  805. switch (mp->magic) {
  806. case DB_BTREEMAGIC:
  807. case DB_HASHMAGIC:
  808. case DB_QAMMAGIC:
  809. set_psize = mp->pagesize;
  810. break;
  811. }
  812. (void)memp_fput(dbp->mpf, mp, 0);
  813. }
  814. /*
  815.  * __db_dbtype_to_string --
  816.  * Return the name of the database type.
  817.  */
  818. static const char *
  819. __db_dbtype_to_string(dbp)
  820. DB *dbp;
  821. {
  822. switch (dbp->type) {
  823. case DB_BTREE:
  824. return ("btree");
  825. case DB_HASH:
  826. return ("hash");
  827. break;
  828. case DB_RECNO:
  829. return ("recno");
  830. break;
  831. case DB_QUEUE:
  832. return ("queue");
  833. default:
  834. return ("UNKNOWN TYPE");
  835. }
  836. /* NOTREACHED */
  837. }
  838. /*
  839.  * __db_pagetype_to_string --
  840.  * Return the name of the specified page type.
  841.  *
  842.  * PUBLIC: const char *__db_pagetype_to_string __P((u_int32_t));
  843.  */
  844. const char *
  845. __db_pagetype_to_string(type)
  846. u_int32_t type;
  847. {
  848. char *s;
  849. s = NULL;
  850. switch (type) {
  851. case P_BTREEMETA:
  852. s = "btree metadata";
  853. break;
  854. case P_LDUP:
  855. s = "duplicate";
  856. break;
  857. case P_HASH:
  858. s = "hash";
  859. break;
  860. case P_HASHMETA:
  861. s = "hash metadata";
  862. break;
  863. case P_IBTREE:
  864. s = "btree internal";
  865. break;
  866. case P_INVALID:
  867. s = "invalid";
  868. break;
  869. case P_IRECNO:
  870. s = "recno internal";
  871. break;
  872. case P_LBTREE:
  873. s = "btree leaf";
  874. break;
  875. case P_LRECNO:
  876. s = "recno leaf";
  877. break;
  878. case P_OVERFLOW:
  879. s = "overflow";
  880. break;
  881. case P_QAMMETA:
  882. s = "queue metadata";
  883. break;
  884. case P_QAMDATA:
  885. s = "queue";
  886. break;
  887. default:
  888. /* Just return a NULL. */
  889. break;
  890. }
  891. return (s);
  892. }
  893. /*
  894.  * __db_prheader --
  895.  * Write out header information in the format expected by db_load.
  896.  *
  897.  * PUBLIC: int __db_prheader __P((DB *, char *, int, int, void *,
  898.  * PUBLIC:     int (*)(void *, const void *), VRFY_DBINFO *, db_pgno_t));
  899.  */
  900. int
  901. __db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno)
  902. DB *dbp;
  903. char *subname;
  904. int pflag, keyflag;
  905. void *handle;
  906. int (*callback) __P((void *, const void *));
  907. VRFY_DBINFO *vdp;
  908. db_pgno_t meta_pgno;
  909. {
  910. DB_BTREE_STAT *btsp;
  911. DB_ENV *dbenv;
  912. DB_HASH_STAT *hsp;
  913. DB_QUEUE_STAT *qsp;
  914. VRFY_PAGEINFO *pip;
  915. char *buf;
  916. int buflen, ret, t_ret;
  917. u_int32_t dbtype;
  918. btsp = NULL;
  919. hsp = NULL;
  920. qsp = NULL;
  921. ret = 0;
  922. buf = NULL;
  923. COMPQUIET(buflen, 0);
  924. if (dbp == NULL)
  925. dbenv = NULL;
  926. else
  927. dbenv = dbp->dbenv;
  928. /*
  929.  * If we've been passed a verifier statistics object, use
  930.  * that;  we're being called in a context where dbp->stat
  931.  * is unsafe.
  932.  */
  933. if (vdp != NULL) {
  934. if ((ret = __db_vrfy_getpageinfo(vdp, meta_pgno, &pip)) != 0)
  935. return (ret);
  936. } else
  937. pip = NULL;
  938. /*
  939.  * If dbp is NULL, we're being called from inside __db_prdbt,
  940.  * and this is a special subdatabase for "lost" items.  Make it a btree.
  941.  * Otherwise, set dbtype to the appropriate type for the specified
  942.  * meta page, or the type of the dbp.
  943.  */
  944. if (dbp == NULL)
  945. dbtype = DB_BTREE;
  946. else if (pip != NULL)
  947. switch (pip->type) {
  948. case P_BTREEMETA:
  949. if (F_ISSET(pip, VRFY_IS_RECNO))
  950. dbtype = DB_RECNO;
  951. else
  952. dbtype = DB_BTREE;
  953. break;
  954. case P_HASHMETA:
  955. dbtype = DB_HASH;
  956. break;
  957. default:
  958. /*
  959.  * If the meta page is of a bogus type, it's
  960.  * because we have a badly corrupt database.
  961.  * (We must be in the verifier for pip to be non-NULL.)
  962.  * Pretend we're a Btree and salvage what we can.
  963.  */
  964. DB_ASSERT(F_ISSET(dbp, DB_AM_VERIFYING));
  965. dbtype = DB_BTREE;
  966. break;
  967. }
  968. else
  969. dbtype = dbp->type;
  970. if ((ret = callback(handle, "VERSION=3n")) != 0)
  971. goto err;
  972. if (pflag) {
  973. if ((ret = callback(handle, "format=printn")) != 0)
  974. goto err;
  975. } else if ((ret = callback(handle, "format=bytevaluen")) != 0)
  976. goto err;
  977. /*
  978.  * 64 bytes is long enough, as a minimum bound, for any of the
  979.  * fields besides subname.  Subname can be anything, and so
  980.  * 64 + subname is big enough for all the things we need to print here.
  981.  */
  982. buflen = 64 + ((subname != NULL) ? strlen(subname) : 0);
  983. if ((ret = __os_malloc(dbenv, buflen, NULL, &buf)) != 0)
  984. goto err;
  985. if (subname != NULL) {
  986. snprintf(buf, buflen, "database=%sn", subname);
  987. if ((ret = callback(handle, buf)) != 0)
  988. goto err;
  989. }
  990. switch (dbtype) {
  991. case DB_BTREE:
  992. if ((ret = callback(handle, "type=btreen")) != 0)
  993. goto err;
  994. if (pip != NULL) {
  995. if (F_ISSET(pip, VRFY_HAS_RECNUMS))
  996. if ((ret =
  997.     callback(handle, "recnum=1n")) != 0)
  998. goto err;
  999. if (pip->bt_maxkey != 0) {
  1000. snprintf(buf, buflen,
  1001.     "bt_maxkey=%lun", (u_long)pip->bt_maxkey);
  1002. if ((ret = callback(handle, buf)) != 0)
  1003. goto err;
  1004. }
  1005. if (pip->bt_minkey != 0 &&
  1006.     pip->bt_minkey != DEFMINKEYPAGE) {
  1007. snprintf(buf, buflen,
  1008.     "bt_minkey=%lun", (u_long)pip->bt_minkey);
  1009. if ((ret = callback(handle, buf)) != 0)
  1010. goto err;
  1011. }
  1012. break;
  1013. }
  1014. if ((ret = dbp->stat(dbp, &btsp, NULL, 0)) != 0) {
  1015. dbp->err(dbp, ret, "DB->stat");
  1016. goto err;
  1017. }
  1018. if (F_ISSET(dbp, DB_BT_RECNUM))
  1019. if ((ret = callback(handle, "recnum=1n")) != 0)
  1020. goto err;
  1021. if (btsp->bt_maxkey != 0) {
  1022. snprintf(buf, buflen,
  1023.     "bt_maxkey=%lun", (u_long)btsp->bt_maxkey);
  1024. if ((ret = callback(handle, buf)) != 0)
  1025. goto err;
  1026. }
  1027. if (btsp->bt_minkey != 0 && btsp->bt_minkey != DEFMINKEYPAGE) {
  1028. snprintf(buf, buflen,
  1029.     "bt_minkey=%lun", (u_long)btsp->bt_minkey);
  1030. if ((ret = callback(handle, buf)) != 0)
  1031. goto err;
  1032. }
  1033. break;
  1034. case DB_HASH:
  1035. if ((ret = callback(handle, "type=hashn")) != 0)
  1036. goto err;
  1037. if (pip != NULL) {
  1038. if (pip->h_ffactor != 0) {
  1039. snprintf(buf, buflen,
  1040.     "h_ffactor=%lun", (u_long)pip->h_ffactor);
  1041. if ((ret = callback(handle, buf)) != 0)
  1042. goto err;
  1043. }
  1044. if (pip->h_nelem != 0) {
  1045. snprintf(buf, buflen,
  1046.     "h_nelem=%lun", (u_long)pip->h_nelem);
  1047. if ((ret = callback(handle, buf)) != 0)
  1048. goto err;
  1049. }
  1050. break;
  1051. }
  1052. if ((ret = dbp->stat(dbp, &hsp, NULL, 0)) != 0) {
  1053. dbp->err(dbp, ret, "DB->stat");
  1054. goto err;
  1055. }
  1056. if (hsp->hash_ffactor != 0) {
  1057. snprintf(buf, buflen,
  1058.     "h_ffactor=%lun", (u_long)hsp->hash_ffactor);
  1059. if ((ret = callback(handle, buf)) != 0)
  1060. goto err;
  1061. }
  1062. if (hsp->hash_nelem != 0 || hsp->hash_nkeys != 0) {
  1063. snprintf(buf, buflen, "h_nelem=%lun",
  1064.     hsp->hash_nelem > hsp->hash_nkeys ?
  1065.     (u_long)hsp->hash_nelem : (u_long)hsp->hash_nkeys);
  1066. if ((ret = callback(handle, buf)) != 0)
  1067. goto err;
  1068. }
  1069. break;
  1070. case DB_QUEUE:
  1071. if ((ret = callback(handle, "type=queuen")) != 0)
  1072. goto err;
  1073. if (vdp != NULL) {
  1074. snprintf(buf,
  1075.     buflen, "re_len=%lun", (u_long)vdp->re_len);
  1076. if ((ret = callback(handle, buf)) != 0)
  1077. goto err;
  1078. break;
  1079. }
  1080. if ((ret = dbp->stat(dbp, &qsp, NULL, 0)) != 0) {
  1081. dbp->err(dbp, ret, "DB->stat");
  1082. goto err;
  1083. }
  1084. snprintf(buf, buflen, "re_len=%lun", (u_long)qsp->qs_re_len);
  1085. if (qsp->qs_re_pad != 0 && qsp->qs_re_pad != ' ')
  1086. snprintf(buf, buflen, "re_pad=%#xn", qsp->qs_re_pad);
  1087. if ((ret = callback(handle, buf)) != 0)
  1088. goto err;
  1089. break;
  1090. case DB_RECNO:
  1091. if ((ret = callback(handle, "type=recnon")) != 0)
  1092. goto err;
  1093. if (pip != NULL) {
  1094. if (F_ISSET(pip, VRFY_IS_RRECNO))
  1095. if ((ret =
  1096.     callback(handle, "renumber=1n")) != 0)
  1097. goto err;
  1098. if (pip->re_len > 0) {
  1099. snprintf(buf, buflen,
  1100.     "re_len=%lun", (u_long)pip->re_len);
  1101. if ((ret = callback(handle, buf)) != 0)
  1102. goto err;
  1103. }
  1104. break;
  1105. }
  1106. if ((ret = dbp->stat(dbp, &btsp, NULL, 0)) != 0) {
  1107. dbp->err(dbp, ret, "DB->stat");
  1108. goto err;
  1109. }
  1110. if (F_ISSET(dbp, DB_RE_RENUMBER))
  1111. if ((ret = callback(handle, "renumber=1n")) != 0)
  1112. goto err;
  1113. if (F_ISSET(dbp, DB_RE_FIXEDLEN)) {
  1114. snprintf(buf, buflen,
  1115.     "re_len=%lun", (u_long)btsp->bt_re_len);
  1116. if ((ret = callback(handle, buf)) != 0)
  1117. goto err;
  1118. }
  1119. if (btsp->bt_re_pad != 0 && btsp->bt_re_pad != ' ') {
  1120. snprintf(buf, buflen, "re_pad=%#xn", btsp->bt_re_pad);
  1121. if ((ret = callback(handle, buf)) != 0)
  1122. goto err;
  1123. }
  1124. break;
  1125. case DB_UNKNOWN:
  1126. DB_ASSERT(0); /* Impossible. */
  1127. __db_err(dbp->dbenv, "Impossible DB type in __db_prheader");
  1128. ret = EINVAL;
  1129. goto err;
  1130. }
  1131. if (pip != NULL) {
  1132. if (F_ISSET(pip, VRFY_HAS_DUPS))
  1133. if ((ret = callback(handle, "duplicates=1n")) != 0)
  1134. goto err;
  1135. if (F_ISSET(pip, VRFY_HAS_DUPSORT))
  1136. if ((ret = callback(handle, "dupsort=1n")) != 0)
  1137. goto err;
  1138. /* We should handle page size. XXX */
  1139. } else {
  1140. if (F_ISSET(dbp, DB_AM_DUP))
  1141. if ((ret = callback(handle, "duplicates=1n")) != 0)
  1142. goto err;
  1143. if (F_ISSET(dbp, DB_AM_DUPSORT))
  1144. if ((ret = callback(handle, "dupsort=1n")) != 0)
  1145. goto err;
  1146. if (!F_ISSET(dbp, DB_AM_PGDEF)) {
  1147. snprintf(buf, buflen,
  1148.     "db_pagesize=%lun", (u_long)dbp->pgsize);
  1149. if ((ret = callback(handle, buf)) != 0)
  1150. goto err;
  1151. }
  1152. }
  1153. if (keyflag && (ret = callback(handle, "keys=1n")) != 0)
  1154. goto err;
  1155. ret = callback(handle, "HEADER=ENDn");
  1156. err: if (pip != NULL &&
  1157.     (t_ret = __db_vrfy_putpageinfo(vdp, pip)) != 0 && ret == 0)
  1158. ret = t_ret;
  1159. if (btsp != NULL)
  1160. __os_free(btsp, 0);
  1161. if (hsp != NULL)
  1162. __os_free(hsp, 0);
  1163. if (qsp != NULL)
  1164. __os_free(qsp, 0);
  1165. if (buf != NULL)
  1166. __os_free(buf, buflen);
  1167. return (ret);
  1168. }
  1169. /*
  1170.  * __db_prfooter --
  1171.  * Print the footer that marks the end of a DB dump.  This is trivial,
  1172.  * but for consistency's sake we don't want to put its literal contents
  1173.  * in multiple places.
  1174.  *
  1175.  * PUBLIC: int __db_prfooter __P((void *, int (*)(void *, const void *)));
  1176.  */
  1177. int
  1178. __db_prfooter(handle, callback)
  1179. void *handle;
  1180. int (*callback) __P((void *, const void *));
  1181. {
  1182. return (callback(handle, "DATA=ENDn"));
  1183. }