📄 db_pr.c
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1996-2004 * Sleepycat Software. All rights reserved. * * $Id: db_pr.c,v 11.121 2004/10/28 14:48:43 bostic Exp $ */#include "db_config.h"#ifndef NO_SYSTEM_INCLUDES#include <sys/types.h>#include <ctype.h>#include <stdlib.h>#include <string.h>#endif#include "db_int.h"#include "dbinc/db_page.h"#include "dbinc/db_shash.h"#include "dbinc/btree.h"#include "dbinc/hash.h"#include "dbinc/mp.h"#include "dbinc/qam.h"#include "dbinc/db_verify.h"/* * __db_loadme -- * A nice place to put a breakpoint. * * PUBLIC: void __db_loadme __P((void)); */void__db_loadme(){ u_int32_t id; __os_id(&id);}#ifdef HAVE_STATISTICSstatic int __db_bmeta __P((DB *, BTMETA *, u_int32_t));static int __db_hmeta __P((DB *, HMETA *, u_int32_t));static void __db_meta __P((DB *, DBMETA *, FN const *, u_int32_t));static const char *__db_pagetype_to_string __P((u_int32_t));static void __db_prdb __P((DB *, u_int32_t));static void __db_proff __P((DB_ENV *, DB_MSGBUF *, void *));static int __db_prtree __P((DB *, u_int32_t));static int __db_qmeta __P((DB *, QMETA *, u_int32_t));/* * __db_dumptree -- * Dump the tree to a file. * * PUBLIC: int __db_dumptree __P((DB *, char *, char *)); */int__db_dumptree(dbp, op, name) DB *dbp; char *op, *name;{ DB_ENV *dbenv; FILE *fp, *orig_fp; u_int32_t flags; int ret; dbenv = dbp->dbenv; for (flags = 0; *op != '\0'; ++op) switch (*op) { case 'a': LF_SET(DB_PR_PAGE); break; case 'h': break; case 'r': LF_SET(DB_PR_RECOVERYTEST); break; default: return (EINVAL); } if (name != NULL) { if ((fp = fopen(name, "w")) == NULL) return (__os_get_errno()); orig_fp = dbenv->db_msgfile; dbenv->db_msgfile = fp; } else fp = orig_fp = NULL; __db_prdb(dbp, flags); __db_msg(dbenv, "%s", DB_GLOBAL(db_line)); ret = __db_prtree(dbp, flags); if (fp != NULL) { (void)fclose(fp); dbenv->db_msgfile = orig_fp; } return (ret);}static const FN __db_flags_fn[] = { { DB_AM_CHKSUM, "checksumming" }, { DB_AM_CL_WRITER, "client replica writer" }, { DB_AM_COMPENSATE, "created by compensating transaction" }, { DB_AM_CREATED, "database created" }, { DB_AM_CREATED_MSTR, "encompassing file created" }, { DB_AM_DBM_ERROR, "dbm/ndbm error" }, { DB_AM_DELIMITER, "variable length" }, { DB_AM_DIRTY, "dirty reads" }, { DB_AM_DISCARD, "discard cached pages" }, { DB_AM_DUP, "duplicates" }, { DB_AM_DUPSORT, "sorted duplicates" }, { DB_AM_ENCRYPT, "encrypted" }, { DB_AM_FIXEDLEN, "fixed-length records" }, { DB_AM_INMEM, "in-memory" }, { DB_AM_IN_RENAME, "file is being renamed" }, { DB_AM_NOT_DURABLE, "changes not logged" }, { DB_AM_OPEN_CALLED, "open called" }, { DB_AM_PAD, "pad value" }, { DB_AM_PGDEF, "default page size" }, { DB_AM_RDONLY, "read-only" }, { DB_AM_RECNUM, "Btree record numbers" }, { DB_AM_RECOVER, "opened for recovery" }, { DB_AM_RENUMBER, "renumber" }, { DB_AM_REPLICATION, "replication file" }, { DB_AM_REVSPLITOFF, "no reverse splits" }, { DB_AM_SECONDARY, "secondary" }, { DB_AM_SNAPSHOT, "load on open" }, { DB_AM_SUBDB, "subdatabases" }, { DB_AM_SWAP, "needswap" }, { DB_AM_TXN, "transactional" }, { DB_AM_VERIFYING, "verifier" }, { 0, NULL }};/* * __db_get_flags_fn -- * Return the __db_flags_fn array. * * PUBLIC: const FN * __db_get_flags_fn __P((void)); */const FN *__db_get_flags_fn(){ return (__db_flags_fn);}/* * __db_prdb -- * Print out the DB structure information. */static void__db_prdb(dbp, flags) DB *dbp; u_int32_t flags;{ DB_MSGBUF mb; DB_ENV *dbenv; BTREE *bt; HASH *h; QUEUE *q; dbenv = dbp->dbenv; DB_MSGBUF_INIT(&mb); __db_msg(dbenv, "In-memory DB structure:"); __db_msgadd(dbenv, &mb, "%s: %#lx", __db_dbtype_to_string(dbp->type), (u_long)dbp->flags); __db_prflags(dbenv, &mb, dbp->flags, __db_flags_fn, " (", ")"); DB_MSGBUF_FLUSH(dbenv, &mb); switch (dbp->type) { case DB_BTREE: case DB_RECNO: bt = dbp->bt_internal; __db_msg(dbenv, "bt_meta: %lu bt_root: %lu", (u_long)bt->bt_meta, (u_long)bt->bt_root); __db_msg(dbenv, "bt_maxkey: %lu bt_minkey: %lu", (u_long)bt->bt_maxkey, (u_long)bt->bt_minkey); if (!LF_ISSET(DB_PR_RECOVERYTEST)) __db_msg(dbenv, "bt_compare: %#lx bt_prefix: %#lx", P_TO_ULONG(bt->bt_compare), P_TO_ULONG(bt->bt_prefix)); __db_msg(dbenv, "bt_lpgno: %lu", (u_long)bt->bt_lpgno); if (dbp->type == DB_RECNO) { __db_msg(dbenv, "re_pad: %#lx re_delim: %#lx re_len: %lu re_source: %s", (u_long)bt->re_pad, (u_long)bt->re_delim, (u_long)bt->re_len, bt->re_source == NULL ? "" : bt->re_source); __db_msg(dbenv, "re_modified: %d re_eof: %d re_last: %lu", bt->re_modified, bt->re_eof, (u_long)bt->re_last); } break; case DB_HASH: h = dbp->h_internal; __db_msg(dbenv, "meta_pgno: %lu", (u_long)h->meta_pgno); __db_msg(dbenv, "h_ffactor: %lu", (u_long)h->h_ffactor); __db_msg(dbenv, "h_nelem: %lu", (u_long)h->h_nelem); if (!LF_ISSET(DB_PR_RECOVERYTEST)) __db_msg(dbenv, "h_hash: %#lx", P_TO_ULONG(h->h_hash)); break; case DB_QUEUE: q = dbp->q_internal; __db_msg(dbenv, "q_meta: %lu", (u_long)q->q_meta); __db_msg(dbenv, "q_root: %lu", (u_long)q->q_root); __db_msg(dbenv, "re_pad: %#lx re_len: %lu", (u_long)q->re_pad, (u_long)q->re_len); __db_msg(dbenv, "rec_page: %lu", (u_long)q->rec_page); __db_msg(dbenv, "page_ext: %lu", (u_long)q->page_ext); break; case DB_UNKNOWN: default: break; }}/* * __db_prtree -- * Print out the entire tree. */static int__db_prtree(dbp, flags) DB *dbp; u_int32_t flags;{ DB_MPOOLFILE *mpf; PAGE *h; db_pgno_t i, last; int ret; mpf = dbp->mpf; if (dbp->type == DB_QUEUE) return (__db_prqueue(dbp, flags)); /* * Find out the page number of the last page in the database, then * dump each page. */ __memp_last_pgno(mpf, &last); for (i = 0; i <= last; ++i) { if ((ret = __memp_fget(mpf, &i, 0, &h)) != 0) return (ret); (void)__db_prpage(dbp, h, flags); if ((ret = __memp_fput(mpf, h, 0)) != 0) return (ret); } return (0);}/* * __db_meta -- * Print out common metadata information. */static void__db_meta(dbp, dbmeta, fn, flags) DB *dbp; DBMETA *dbmeta; FN const *fn; u_int32_t flags;{ DB_MSGBUF mb; DB_ENV *dbenv; DB_MPOOLFILE *mpf; PAGE *h; db_pgno_t pgno; u_int8_t *p; int cnt, ret; const char *sep; dbenv = dbp->dbenv; mpf = dbp->mpf; DB_MSGBUF_INIT(&mb); __db_msg(dbenv, "\tmagic: %#lx", (u_long)dbmeta->magic); __db_msg(dbenv, "\tversion: %lu", (u_long)dbmeta->version); __db_msg(dbenv, "\tpagesize: %lu", (u_long)dbmeta->pagesize); __db_msg(dbenv, "\ttype: %lu", (u_long)dbmeta->type); __db_msg(dbenv, "\tkeys: %lu\trecords: %lu", (u_long)dbmeta->key_count, (u_long)dbmeta->record_count); /* * If we're doing recovery testing, don't display the free list, * it may have changed and that makes the dump diff not work. */ if (!LF_ISSET(DB_PR_RECOVERYTEST)) { __db_msgadd( dbenv, &mb, "\tfree list: %lu", (u_long)dbmeta->free); for (pgno = dbmeta->free, cnt = 0, sep = ", "; pgno != PGNO_INVALID;) { if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0) { DB_MSGBUF_FLUSH(dbenv, &mb); __db_msg(dbenv, "Unable to retrieve free-list page: %lu: %s", (u_long)pgno, db_strerror(ret)); break; } pgno = h->next_pgno; (void)__memp_fput(mpf, h, 0); __db_msgadd(dbenv, &mb, "%s%lu", sep, (u_long)pgno); if (++cnt % 10 == 0) { DB_MSGBUF_FLUSH(dbenv, &mb); cnt = 0; sep = "\t"; } else sep = ", "; } DB_MSGBUF_FLUSH(dbenv, &mb); __db_msg(dbenv, "\tlast_pgno: %lu", (u_long)dbmeta->last_pgno); } if (fn != NULL) { DB_MSGBUF_FLUSH(dbenv, &mb); __db_msgadd(dbenv, &mb, "\tflags: %#lx", (u_long)dbmeta->flags); __db_prflags(dbenv, &mb, dbmeta->flags, fn, " (", ")"); } DB_MSGBUF_FLUSH(dbenv, &mb); __db_msgadd(dbenv, &mb, "\tuid: "); for (p = (u_int8_t *)dbmeta->uid, cnt = 0; cnt < DB_FILE_ID_LEN; ++cnt) { __db_msgadd(dbenv, &mb, "%x", *p++); if (cnt < DB_FILE_ID_LEN - 1) __db_msgadd(dbenv, &mb, " "); } DB_MSGBUF_FLUSH(dbenv, &mb);}/* * __db_bmeta -- * Print out the btree meta-data page. */static int__db_bmeta(dbp, h, flags) DB *dbp; BTMETA *h; u_int32_t flags;{ static const FN fn[] = { { BTM_DUP, "duplicates" }, { BTM_RECNO, "recno" }, { BTM_RECNUM, "btree:recnum" }, { BTM_FIXEDLEN, "recno:fixed-length" }, { BTM_RENUMBER, "recno:renumber" }, { BTM_SUBDB, "multiple-databases" }, { BTM_DUPSORT, "sorted duplicates" }, { 0, NULL } }; DB_ENV *dbenv; dbenv = dbp->dbenv; __db_meta(dbp, (DBMETA *)h, fn, flags); __db_msg(dbenv, "\tmaxkey: %lu minkey: %lu", (u_long)h->maxkey, (u_long)h->minkey); if (dbp->type == DB_RECNO) __db_msg(dbenv, "\tre_len: %#lx re_pad: %#lx", (u_long)h->re_len, (u_long)h->re_pad); __db_msg(dbenv, "\troot: %lu", (u_long)h->root); return (0);}/* * __db_hmeta -- * Print out the hash meta-data page. */static int__db_hmeta(dbp, h, flags) DB *dbp; HMETA *h; u_int32_t flags;{ DB_MSGBUF mb; static const FN fn[] = { { DB_HASH_DUP, "duplicates" }, { DB_HASH_SUBDB, "multiple-databases" }, { DB_HASH_DUPSORT, "sorted duplicates" }, { 0, NULL } }; DB_ENV *dbenv; int i; dbenv = dbp->dbenv; DB_MSGBUF_INIT(&mb); __db_meta(dbp, (DBMETA *)h, fn, flags); __db_msg(dbenv, "\tmax_bucket: %lu", (u_long)h->max_bucket); __db_msg(dbenv, "\thigh_mask: %#lx", (u_long)h->high_mask); __db_msg(dbenv, "\tlow_mask: %#lx", (u_long)h->low_mask); __db_msg(dbenv, "\tffactor: %lu", (u_long)h->ffactor); __db_msg(dbenv, "\tnelem: %lu", (u_long)h->nelem); __db_msg(dbenv, "\th_charkey: %#lx", (u_long)h->h_charkey); __db_msgadd(dbenv, &mb, "\tspare points: "); for (i = 0; i < NCACHED; i++) __db_msgadd(dbenv, &mb, "%lu ", (u_long)h->spares[i]); DB_MSGBUF_FLUSH(dbenv, &mb); return (0);}/* * __db_qmeta -- * Print out the queue meta-data page. */static int__db_qmeta(dbp, h, flags) DB *dbp; QMETA *h; u_int32_t flags;{ DB_ENV *dbenv; dbenv = dbp->dbenv; __db_meta(dbp, (DBMETA *)h, NULL, flags); __db_msg(dbenv, "\tfirst_recno: %lu", (u_long)h->first_recno); __db_msg(dbenv, "\tcur_recno: %lu", (u_long)h->cur_recno); __db_msg(dbenv, "\tre_len: %#lx re_pad: %lu", (u_long)h->re_len, (u_long)h->re_pad); __db_msg(dbenv, "\trec_page: %lu", (u_long)h->rec_page); __db_msg(dbenv, "\tpage_ext: %lu", (u_long)h->page_ext); return (0);}/* * __db_prnpage * -- Print out a specific page. * * PUBLIC: int __db_prnpage __P((DB *, db_pgno_t)); */int__db_prnpage(dbp, pgno) DB *dbp; db_pgno_t pgno;{ DB_MPOOLFILE *mpf; PAGE *h; int ret, t_ret; mpf = dbp->mpf; if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0) return (ret); ret = __db_prpage(dbp, h, DB_PR_PAGE); if ((t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0) ret = t_ret; return (ret);}/* * __db_prpage * -- Print out a page. * * PUBLIC: int __db_prpage __P((DB *, PAGE *, u_int32_t)); */int__db_prpage(dbp, h, flags) DB *dbp; PAGE *h; u_int32_t flags;{ BINTERNAL *bi; BKEYDATA *bk; DB_ENV *dbenv; DB_MSGBUF mb; HOFFPAGE a_hkd; QAMDATA *qp, *qep; RINTERNAL *ri; db_indx_t dlen, len, i, *inp; db_pgno_t pgno; db_recno_t recno; u_int32_t pagesize, qlen; u_int8_t *ep, *hk, *p; int deleted, ret; const char *s; void *sp; dbenv = dbp->dbenv; DB_MSGBUF_INIT(&mb); /* * If we're doing recovery testing and this page is P_INVALID, * assume it's a page that's on the free list, and don't display it. */ if (LF_ISSET(DB_PR_RECOVERYTEST) && TYPE(h) == P_INVALID) return (0); if ((s = __db_pagetype_to_string(TYPE(h))) == NULL) { __db_msg(dbenv, "ILLEGAL PAGE TYPE: page: %lu type: %lu", (u_long)h->pgno, (u_long)TYPE(h)); return (1); } /* * !!! * Find out the page size. We don't want to do it the "right" way, * by reading the value from the meta-data page, that's going to be * slow. Reach down into the mpool region. */ pagesize = (u_int32_t)dbp->mpf->mfp->stat.st_pagesize; /* Page number, page type. */ __db_msgadd(dbenv, &mb, "page %lu: %s level: %lu", (u_long)h->pgno, s, (u_long)h->level); /* Record count. */ if (TYPE(h) == P_IBTREE || TYPE(h) == P_IRECNO || (TYPE(h) == P_LRECNO && h->pgno == ((BTREE *)dbp->bt_internal)->bt_root)) __db_msgadd(dbenv, &mb, " records: %lu", (u_long)RE_NREC(h)); /* LSN. */ if (!LF_ISSET(DB_PR_RECOVERYTEST)) __db_msgadd(dbenv, &mb, " (lsn.file: %lu lsn.offset: %lu)", (u_long)LSN(h).file, (u_long)LSN(h).offset);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -