00001 // 00002 // NAME 00003 // 00004 // displays statistics for Berkeley DB environments. 00005 // 00006 // SYNOPSIS 00007 // 00008 // htdb_stat [-celmNtzW] [-C Acfhlmo] [-d file [-s file]] [-h home] [-M Ahlm] 00009 // 00010 // DESCRIPTION 00011 // 00012 // htdb_stat is a slightly modified version of the standard Berkeley 00013 // DB db_stat utility which displays statistics for Berkeley DB 00014 // environments. 00015 // 00016 // OPTIONS 00017 // 00018 // <dl> 00019 // 00020 // <dt><b>-W</b> 00021 // <dd>Initialize WordContext(3) before gathering statistics. With the <b>-z</b> 00022 // flag allows to gather statistics on inverted indexes generated 00023 // with the mifluz(3) specific 00024 // compression scheme. The MIFLUZ_CONFIG environment variable must be 00025 // set to a file containing the mifluz(3) configuration. 00026 // 00027 // <dt><b>-z</b> 00028 // <dd>The <b>file</b> is compressed. If <b>-W</b> is given the 00029 // mifluz(3) specific compression scheme is used. Otherwise the default 00030 // gzip compression scheme is used. 00031 // 00032 // <dt><b>-C</b> 00033 // <dd>Display internal information about the lock region. 00034 // (The output from this option is often both voluminous and meaningless, 00035 // and is intended only for debugging.) 00036 // <dl> 00037 // <dt><b>A</b> 00038 // <dd>Display all information. 00039 // <dt><b>c</b> 00040 // <dd>Display lock conflict matrix. 00041 // <dt><b>f</b> 00042 // <dd>Display lock and object free lists. 00043 // <dt><b>l</b> 00044 // <dd>Display lockers within hash chains. 00045 // <dt><b>m</b> 00046 // <dd>Display region memory information. 00047 // <dt><b>o</b> 00048 // <dd>Display objects within hash chains. 00049 // </dl> 00050 // 00051 // <dt><b>-c</b> 00052 // <dd>Display lock region statistics. 00053 // 00054 // <dt><b>-d</b> 00055 // <dd>Display database statistics for the specified database. 00056 // If the database contains subdatabases, the statistics 00057 // are for the database or subdatabase specified, and not for the database 00058 // as a whole. 00059 // 00060 // <dt><b>-e</b> 00061 // <dd>Display current environment statistics. 00062 // 00063 // <dt><b>-h</b> 00064 // <dd>Specify a home directory for the database. 00065 // 00066 // <dt><b>-l</b> 00067 // <dd>Display log region statistics. 00068 // 00069 // <dt><b>-M</b> 00070 // <dd>Display internal information about the shared memory buffer pool. 00071 // (The output from this option is often both voluminous and meaningless, 00072 // and is intended only for debugging.) 00073 // <dl> 00074 // <dt><b>A</b> 00075 // <dd>Display all information. 00076 // <dt><b>h</b> 00077 // <dd>Display buffers within hash chains. 00078 // <dt><b>l</b> 00079 // <dd>Display buffers within LRU chains. 00080 // <dt><b>m</b> 00081 // <dd>Display region memory information. 00082 // </dl> 00083 // 00084 // <dt><b>-m</b> 00085 // <dd>Display shared memory buffer pool statistics. 00086 // 00087 // <dt><b>-N</b> 00088 // <dd>Do not acquire shared region locks while running. Other problems such 00089 // as potentially fatal errors in Berkeley DB will be ignored as well. This option 00090 // is intended only for debugging errors and should not be used under any 00091 // other circumstances. 00092 // 00093 // <dt><b>-s</b> 00094 // <dd>Display database statistics for the specified subdatabase of the 00095 // database specified with the <b>-d</b> flag. 00096 // 00097 // <dt><b>-t</b><dd>Display transaction region statistics. 00098 // 00099 // <dt><b>-V</b> 00100 // <dd>Write the version number to the standard output and exit. 00101 // 00102 // </dl> 00103 // 00104 // Only one set of statistics is displayed for each run, and the last option 00105 // specifying a set of statistics takes precedence. 00106 // 00107 // Values smaller than 10 million are generally displayed without any special 00108 // notation. Values larger than 10 million are normally displayed as 00109 // <b><number>M</b>. 00110 // 00111 // The htdb_stat utility attaches to one or more of the Berkeley DB shared memory 00112 // regions. In order to avoid region corruption, it should always be given 00113 // the chance to detach and exit gracefully. To cause htdb_stat to clean up 00114 // after itself and exit, send it an interrupt signal (SIGINT). 00115 // 00116 // ENVIRONMENT 00117 // 00118 // <b>DB_HOME</b> 00119 // If the <b>-h</b> option is not specified and the environment variable 00120 // DB_HOME is set, it is used as the path of the database home. 00121 // <br> 00122 // <b>MIFLUZ_CONFIG</b> 00123 // file name of configuration file read by WordContext(3). Defaults to 00124 // <b>~/.mifluz.</b> 00125 // 00126 // AUTHORS 00127 // 00128 // Sleepycat Software http://www.sleepycat.com/ 00129 // 00130 // 00131 // END 00132 /*- 00133 * See the file LICENSE for redistribution information. 00134 * 00135 * Copyright (c) 1996, 1997, 1998, 1999, 2000 00136 * Sleepycat Software. All rights reserved. 00137 */ 00138 00139 #ifdef HAVE_CONFIG_H 00140 #include "config.h" 00141 #endif /* HAVE_CONFIG_H */ 00142 00143 #ifndef lint 00144 static const char copyright[] = 00145 "Copyright (c) 1996-2000\nSleepycat Software Inc. All rights reserved.\n"; 00146 static const char revid[] = 00147 "$Id: htdb__stat_8cc-source.html,v 1.1 2008年06月08日 10:19:47 sebdiaz Exp $"; 00148 #endif 00149 00150 #ifndef NO_SYSTEM_INCLUDES 00151 #include <sys/types.h> 00152 00153 #if TIME_WITH_SYS_TIME 00154 #include <sys/time.h> 00155 #include <time.h> 00156 #else 00157 #if HAVE_SYS_TIME_H 00158 #include <sys/time.h> 00159 #else 00160 #include <time.h> 00161 #endif 00162 #endif 00163 00164 #include <ctype.h> 00165 #include <errno.h> 00166 #include <stdlib.h> 00167 #include <string.h> 00168 #include <unistd.h> 00169 #endif 00170 00171 #ifdef HAVE_GETOPT_H 00172 #include <getopt.h> 00173 #endif /* HAVE_GETOPT_H */ 00174 00175 extern "C" { 00176 #include "db_int.h" 00177 #include "db_page.h" 00178 #include "db_shash.h" 00179 #include "lock.h" 00180 #include "mp.h" 00181 } 00182 00183 #include "util_sig.h" 00184 00185 #include "WordDBInfo.h" 00186 #include "WordDBCompress.h" 00187 #include "WordContext.h" 00188 00189 #define PCT(f, t, pgsize) \ 00190 ((t) == 0 ? 0 : \ 00191 (((double)(((t) * (pgsize)) - (f)) / ((t) * (pgsize))) * 100)) 00192 00193 typedef enum { T_NOTSET, T_DB, T_ENV, T_LOCK, T_LOG, T_MPOOL, T_TXN } test_t; 00194 00195 int argcheck __P((char *, const char *)); 00196 int btree_stats __P((DB_ENV *, DB *)); 00197 int db_init __P((char *, test_t)); 00198 void dl __P((const char *, u_long)); 00199 void dl_bytes __P((const char *, u_long, u_long, u_long)); 00200 int env_stats __P((DB_ENV *)); 00201 int hash_stats __P((DB_ENV *, DB *)); 00202 int lock_ok __P((char *)); 00203 int lock_stats __P((DB_ENV *)); 00204 int log_stats __P((DB_ENV *)); 00205 int main __P((int, char *[])); 00206 int mpool_ok __P((char *)); 00207 int mpool_stats __P((DB_ENV *)); 00208 void prflags __P((u_int32_t, const FN *)); 00209 int queue_stats __P((DB_ENV *, DB *)); 00210 int txn_compare __P((const void *, const void *)); 00211 int txn_stats __P((DB_ENV *)); 00212 void usage __P((void)); 00213 00214 DB_ENV *dbenv; 00215 char *internal; 00216 const char 00217 *progname = "htdb_stat"; /* Program name. */ 00218 00219 int 00220 main(int argc, char *argv[]) 00221 { 00222 extern char *optarg; 00223 extern int optind; 00224 DB *dbp; 00225 test_t ttype; 00226 int ch, d_close, e_close, exitval, ret; 00227 char *db, *home, *subdb; 00228 int compress = 0; 00229 int wordlist = 0; 00230 WordContext *context = 0; 00231 00232 dbp = NULL; 00233 ttype = T_NOTSET; 00234 d_close = e_close = exitval = 0; 00235 db = home = subdb = NULL; 00236 while ((ch = getopt(argc, argv, "C:cd:eh:lM:mNs:tVzW")) != EOF) 00237 switch (ch) { 00238 case 'C': 00239 ttype = T_LOCK; 00240 if (!argcheck(internal = optarg, "Acflmo")) 00241 usage(); 00242 break; 00243 case 'c': 00244 ttype = T_LOCK; 00245 break; 00246 case 'd': 00247 db = optarg; 00248 ttype = T_DB; 00249 break; 00250 case 'e': 00251 ttype = T_ENV; 00252 break; 00253 case 'h': 00254 home = optarg; 00255 break; 00256 case 'l': 00257 ttype = T_LOG; 00258 break; 00259 case 'M': 00260 ttype = T_MPOOL; 00261 if (!argcheck(internal = optarg, "Ahlm")) 00262 usage(); 00263 break; 00264 case 'm': 00265 ttype = T_MPOOL; 00266 break; 00267 case 'N': 00268 if ((ret = CDB_db_env_set_mutexlocks(0)) != 0) { 00269 fprintf(stderr, 00270 "%s: db_env_set_mutexlocks: %s\n", 00271 progname, CDB_db_strerror(ret)); 00272 return (1); 00273 } 00274 if ((ret = CDB_db_env_set_panicstate(0)) != 0) { 00275 fprintf(stderr, 00276 "%s: db_env_set_panicstate: %s\n", 00277 progname, CDB_db_strerror(ret)); 00278 return (1); 00279 } 00280 break; 00281 case 's': 00282 subdb = optarg; 00283 ttype = T_DB; 00284 break; 00285 case 't': 00286 ttype = T_TXN; 00287 break; 00288 case 'V': 00289 printf("%s\n", CDB_db_version(NULL, NULL, NULL)); 00290 exit(0); 00291 case 'z': 00292 compress = DB_COMPRESS; 00293 break; 00294 case 'W': 00295 wordlist = 1; 00296 break; 00297 case '?': 00298 default: 00299 usage(); 00300 } 00301 argc -= optind; 00302 argv += optind; 00303 00304 switch (ttype) { 00305 case T_DB: 00306 if (db == NULL) 00307 usage(); 00308 break; 00309 case T_NOTSET: 00310 usage(); 00311 /* NOTREACHED */ 00312 default: 00313 break; 00314 } 00315 00316 /* Handle possible interruptions. */ 00317 __db_util_siginit(); 00318 00319 if(wordlist && compress) { 00320 static ConfigDefaults defaults[] = { 00321 { "wordlist_wordkey_description", "Word 24/DocID 32/Flag 8/Location 16"}, 00322 { "wordlist_env_skip", "true"}, 00323 { 0, 0, 0 } 00324 }; 00325 context = new WordContext(defaults); 00326 } 00327 00328 /* 00329 * Create an environment object and initialize it for error 00330 * reporting. 00331 */ 00332 if ((ret = CDB_db_env_create(&dbenv, 0)) != 0) { 00333 fprintf(stderr, 00334 "%s: CDB_db_env_create: %s\n", progname, CDB_db_strerror(ret)); 00335 goto shutdown; 00336 } 00337 e_close = 1; 00338 00339 dbenv->set_errfile(dbenv, stderr); 00340 dbenv->set_errpfx(dbenv, progname); 00341 if(wordlist && compress) dbenv->mp_cmpr_info = (new WordDBCompress(context))->CmprInfo(); 00342 00343 /* Initialize the environment. */ 00344 if (db_init(home, ttype) != 0) 00345 goto shutdown; 00346 00347 switch (ttype) { 00348 case T_DB: 00349 /* Create the DB object and open the file. */ 00350 if ((ret = CDB_db_create(&dbp, dbenv, 0)) != 0) { 00351 dbenv->err(dbenv, ret, "CDB_db_create"); 00352 goto shutdown; 00353 } 00354 00355 if ((ret = 00356 dbp->open(dbp, db, subdb, DB_UNKNOWN, compress, 0)) != 0 00357 && (ret = 00358 dbp->open(dbp, db, subdb, DB_UNKNOWN, (DB_RDONLY | compress), 0)) != 0) { 00359 dbp->err(dbp, ret, "open: %s", db); 00360 goto shutdown; 00361 } 00362 00363 d_close = 1; 00364 switch (dbp->type) { 00365 case DB_BTREE: 00366 case DB_RECNO: 00367 if (btree_stats(dbenv, dbp)) 00368 goto shutdown; 00369 break; 00370 case DB_HASH: 00371 if (hash_stats(dbenv, dbp)) 00372 goto shutdown; 00373 break; 00374 case DB_QUEUE: 00375 if (queue_stats(dbenv, dbp)) 00376 goto shutdown; 00377 break; 00378 case DB_UNKNOWN: 00379 abort(); /* Impossible. */ 00380 /* NOTREACHED */ 00381 } 00382 break; 00383 case T_ENV: 00384 if (env_stats(dbenv)) 00385 exitval = 1; 00386 break; 00387 case T_LOCK: 00388 if (lock_stats(dbenv)) 00389 exitval = 1; 00390 break; 00391 case T_LOG: 00392 if (log_stats(dbenv)) 00393 exitval = 1; 00394 break; 00395 case T_MPOOL: 00396 if (mpool_stats(dbenv)) 00397 exitval = 1; 00398 break; 00399 case T_TXN: 00400 if (txn_stats(dbenv)) 00401 exitval = 1; 00402 break; 00403 case T_NOTSET: 00404 abort(); /* Impossible. */ 00405 /* NOTREACHED */ 00406 } 00407 00408 if (0) { 00409 shutdown: exitval = 1; 00410 } 00411 if (d_close && (ret = dbp->close(dbp, 0)) != 0) { 00412 exitval = 1; 00413 dbp->err(dbp, ret, "close"); 00414 } 00415 if(wordlist && compress) { 00416 delete (WordDBCompress*)dbenv->mp_cmpr_info->user_data; 00417 delete dbenv->mp_cmpr_info; 00418 } 00419 if (e_close && (ret = dbenv->close(dbenv, 0)) != 0) { 00420 exitval = 1; 00421 fprintf(stderr, 00422 "%s: dbenv->close: %s\n", progname, CDB_db_strerror(ret)); 00423 } 00424 00425 if(context) delete context; 00426 00427 /* Resend any caught signal. */ 00428 __db_util_sigresend(); 00429 00430 return (exitval); 00431 } 00432 00433 /* 00434 * env_stats -- 00435 * Display environment statistics. 00436 */ 00437 int 00438 env_stats(DB_ENV *dbenvp) 00439 { 00440 REGENV renv; 00441 REGION *rp, regs[1024]; 00442 int n, ret; 00443 const char *lable; 00444 00445 n = sizeof(regs) / sizeof(regs[0]); 00446 if ((ret = CDB___db_e_stat(dbenvp, &renv, regs, &n)) != 0) { 00447 dbenvp->err(dbenvp, ret, "CDB___db_e_stat"); 00448 return (1); 00449 } 00450 00451 printf("%d.%d.%d\tEnvironment version.\n", 00452 renv.majver, renv.minver, renv.patch); 00453 printf("%lx\tMagic number.\n", (u_long)renv.magic); 00454 printf("%d\tPanic value.\n", renv.panic); 00455 00456 /* Adjust the reference count for us... */ 00457 printf("%d\tReferences.\n", renv.refcnt - 1); 00458 00459 dl("Locks granted without waiting.\n", 00460 (u_long)renv.mutex.mutex_set_nowait); 00461 dl("Locks granted after waiting.\n", 00462 (u_long)renv.mutex.mutex_set_wait); 00463 00464 while (n > 0) { 00465 printf("%s\n", DB_LINE); 00466 rp = ®s[--n]; 00467 switch (rp->id) { 00468 case REG_ID_ENV: 00469 lable = "Environment"; 00470 break; 00471 case REG_ID_LOCK: 00472 lable = "Lock"; 00473 break; 00474 case REG_ID_LOG: 00475 lable = "Log"; 00476 break; 00477 case REG_ID_MPOOL: 00478 lable = "Mpool"; 00479 break; 00480 case REG_ID_TXN: 00481 lable = "Txn"; 00482 break; 00483 default: 00484 lable = "Unknown"; 00485 break; 00486 } 00487 printf("%s Region: %d.\n", lable, rp->id); 00488 dl_bytes("Size", (u_long)0, (u_long)0, (u_long)rp->size); 00489 printf("%ld\tSegment ID.\n", rp->segid); 00490 dl("Locks granted without waiting.\n", 00491 (u_long)rp->mutex.mutex_set_nowait); 00492 dl("Locks granted after waiting.\n", 00493 (u_long)rp->mutex.mutex_set_wait); 00494 } 00495 00496 return (0); 00497 } 00498 00499 /* 00500 * btree_stats -- 00501 * Display btree/recno statistics. 00502 */ 00503 int 00504 btree_stats(DB_ENV *dbenvp, DB *dbp) 00505 { 00506 static const FN fn[] = { 00507 { BTM_DUP, "duplicates" }, 00508 { BTM_FIXEDLEN, "fixed-length" }, 00509 { BTM_RECNO, "recno" }, 00510 { BTM_RECNUM, "record-numbers" }, 00511 { BTM_RENUMBER, "renumber" }, 00512 { BTM_SUBDB, "multiple-databases" }, 00513 { 0, NULL } 00514 }; 00515 DB_BTREE_STAT *sp; 00516 int ret; 00517 00518 COMPQUIET(dbenvp, NULL); 00519 00520 if ((ret = dbp->stat(dbp, &sp, NULL, 0)) != 0) { 00521 dbp->err(dbp, ret, "dbp->stat"); 00522 return (1); 00523 } 00524 00525 printf("%lx\tBtree magic number.\n", (u_long)sp->bt_magic); 00526 printf("%lu\tBtree version number.\n", (u_long)sp->bt_version); 00527 prflags(sp->bt_metaflags, fn); 00528 if (dbp->type == DB_BTREE) { 00529 #ifdef NOT_IMPLEMENTED 00530 dl("Maximum keys per-page.\n", (u_long)sp->bt_maxkey); 00531 #endif 00532 dl("Minimum keys per-page.\n", (u_long)sp->bt_minkey); 00533 } 00534 if (dbp->type == DB_RECNO) { 00535 dl("Fixed-length record size.\n", (u_long)sp->bt_re_len); 00536 if (isprint(sp->bt_re_pad)) 00537 printf("%c\tFixed-length record pad.\n", 00538 (int)sp->bt_re_pad); 00539 else 00540 printf("0x%x\tFixed-length record pad.\n", 00541 (int)sp->bt_re_pad); 00542 } 00543 dl("Underlying database page size.\n", (u_long)sp->bt_pagesize); 00544 dl("Number of levels in the tree.\n", (u_long)sp->bt_levels); 00545 dl("Number of unique keys in the tree.\n", (u_long)sp->bt_nkeys); 00546 dl("Number of data items in the tree.\n", (u_long)sp->bt_ndata); 00547 00548 dl("Number of tree internal pages.\n", (u_long)sp->bt_int_pg); 00549 dl("Number of bytes free in tree internal pages", 00550 (u_long)sp->bt_int_pgfree); 00551 printf(" (%.0f%% ff).\n", 00552 PCT(sp->bt_int_pgfree, sp->bt_int_pg, sp->bt_pagesize)); 00553 00554 dl("Number of tree leaf pages.\n", (u_long)sp->bt_leaf_pg); 00555 dl("Number of bytes free in tree leaf pages", 00556 (u_long)sp->bt_leaf_pgfree); 00557 printf(" (%.0f%% ff).\n", 00558 PCT(sp->bt_leaf_pgfree, sp->bt_leaf_pg, sp->bt_pagesize)); 00559 00560 dl("Number of tree duplicate pages.\n", (u_long)sp->bt_dup_pg); 00561 dl("Number of bytes free in tree duplicate pages", 00562 (u_long)sp->bt_dup_pgfree); 00563 printf(" (%.0f%% ff).\n", 00564 PCT(sp->bt_dup_pgfree, sp->bt_dup_pg, sp->bt_pagesize)); 00565 00566 dl("Number of tree overflow pages.\n", (u_long)sp->bt_over_pg); 00567 dl("Number of bytes free in tree overflow pages", 00568 (u_long)sp->bt_over_pgfree); 00569 printf(" (%.0f%% ff).\n", 00570 PCT(sp->bt_over_pgfree, sp->bt_over_pg, sp->bt_pagesize)); 00571 00572 dl("Number of pages on the free list.\n", (u_long)sp->bt_free); 00573 00574 free(sp); 00575 00576 return (0); 00577 } 00578 00579 /* 00580 * hash_stats -- 00581 * Display hash statistics. 00582 */ 00583 int 00584 hash_stats(DB_ENV *dbenvp, DB *dbp) 00585 { 00586 static const FN fn[] = { 00587 { DB_HASH_DUP, "duplicates" }, 00588 { DB_HASH_SUBDB,"multiple-databases" }, 00589 { 0, NULL } 00590 }; 00591 DB_HASH_STAT *sp; 00592 int ret; 00593 00594 COMPQUIET(dbenvp, NULL); 00595 00596 if ((ret = dbp->stat(dbp, &sp, NULL, 0)) != 0) { 00597 dbp->err(dbp, ret, "dbp->stat"); 00598 return (1); 00599 } 00600 00601 printf("%lx\tHash magic number.\n", (u_long)sp->hash_magic); 00602 printf("%lu\tHash version number.\n", (u_long)sp->hash_version); 00603 prflags(sp->hash_metaflags, fn); 00604 dl("Underlying database page size.\n", (u_long)sp->hash_pagesize); 00605 dl("Number of keys in the database.\n", (u_long)sp->hash_nkeys); 00606 dl("Number of data items in the database.\n", (u_long)sp->hash_ndata); 00607 00608 dl("Number of hash buckets.\n", (u_long)sp->hash_buckets); 00609 dl("Number of bytes free on bucket pages", (u_long)sp->hash_bfree); 00610 printf(" (%.0f%% ff).\n", 00611 PCT(sp->hash_bfree, sp->hash_buckets, sp->hash_pagesize)); 00612 00613 dl("Number of overflow pages.\n", (u_long)sp->hash_bigpages); 00614 dl("Number of bytes free in overflow pages", 00615 (u_long)sp->hash_big_bfree); 00616 printf(" (%.0f%% ff).\n", 00617 PCT(sp->hash_big_bfree, sp->hash_bigpages, sp->hash_pagesize)); 00618 00619 dl("Number of bucket overflow pages.\n", (u_long)sp->hash_overflows); 00620 dl("Number of bytes free in bucket overflow pages", 00621 (u_long)sp->hash_ovfl_free); 00622 printf(" (%.0f%% ff).\n", 00623 PCT(sp->hash_ovfl_free, sp->hash_overflows, sp->hash_pagesize)); 00624 00625 dl("Number of duplicate pages.\n", (u_long)sp->hash_dup); 00626 dl("Number of bytes free in duplicate pages", 00627 (u_long)sp->hash_dup_free); 00628 printf(" (%.0f%% ff).\n", 00629 PCT(sp->hash_dup_free, sp->hash_dup, sp->hash_pagesize)); 00630 00631 dl("Number of pages on the free list.\n", (u_long)sp->hash_free); 00632 00633 return (0); 00634 } 00635 00636 /* 00637 * queue_stats -- 00638 * Display queue statistics. 00639 */ 00640 int 00641 queue_stats(DB_ENV *dbenvp, DB *dbp) 00642 { 00643 DB_QUEUE_STAT *sp; 00644 int ret; 00645 00646 COMPQUIET(dbenvp, NULL); 00647 00648 if ((ret = dbp->stat(dbp, &sp, NULL, 0)) != 0) { 00649 dbp->err(dbp, ret, "dbp->stat"); 00650 return (1); 00651 } 00652 00653 printf("%lx\tQueue magic number.\n", (u_long)sp->qs_magic); 00654 printf("%lu\tQueue version number.\n", (u_long)sp->qs_version); 00655 dl("Fixed-length record size.\n", (u_long)sp->qs_re_len); 00656 if (isprint(sp->qs_re_pad)) 00657 printf("%c\tFixed-length record pad.\n", (int)sp->qs_re_pad); 00658 else 00659 printf("0x%x\tFixed-length record pad.\n", (int)sp->qs_re_pad); 00660 dl("Underlying tree page size.\n", (u_long)sp->qs_pagesize); 00661 dl("Number of records in the database.\n", (u_long)sp->qs_nkeys); 00662 dl("Number of database pages.\n", (u_long)sp->qs_pages); 00663 dl("Number of bytes free in database pages", (u_long)sp->qs_pgfree); 00664 printf(" (%.0f%% ff).\n", 00665 PCT(sp->qs_pgfree, sp->qs_pages, sp->qs_pagesize)); 00666 printf("%lu\tFirst undeleted record.\n", (u_long)sp->qs_first_recno); 00667 printf( 00668 "%lu\tLast allocated record number.\n", (u_long)sp->qs_cur_recno); 00669 printf("%lu\tStart offset.\n", (u_long)sp->qs_start); 00670 00671 return (0); 00672 } 00673 00674 /* 00675 * lock_stats -- 00676 * Display lock statistics. 00677 */ 00678 int 00679 lock_stats(DB_ENV *dbenvp) 00680 { 00681 DB_LOCK_STAT *sp; 00682 int ret; 00683 00684 if (internal != NULL) { 00685 CDB___lock_dump_region(dbenvp, internal, stdout); 00686 return (0); 00687 } 00688 00689 if ((ret = CDB_lock_stat(dbenvp, &sp, NULL)) != 0) { 00690 dbenvp->err(dbenvp, ret, NULL); 00691 return (1); 00692 } 00693 00694 dl("Last allocated locker ID.\n", (u_long)sp->st_lastid); 00695 dl("Number of lock modes.\n", (u_long)sp->st_nmodes); 00696 dl("Maximum number of locks possible.\n", (u_long)sp->st_maxlocks); 00697 dl("Current lockers.\n", (u_long)sp->st_nlockers); 00698 dl("Maximum current lockers.\n", (u_long)sp->st_nlockers); 00699 dl("Number of lock requests.\n", (u_long)sp->st_nrequests); 00700 dl("Number of lock releases.\n", (u_long)sp->st_nreleases); 00701 dl("Number of lock requests that would have waited.\n", 00702 (u_long)sp->st_nnowaits); 00703 dl("Number of lock conflicts.\n", (u_long)sp->st_nconflicts); 00704 dl("Number of deadlocks.\n", (u_long)sp->st_ndeadlocks); 00705 dl_bytes("Lock region size", 00706 (u_long)0, (u_long)0, (u_long)sp->st_regsize); 00707 dl("The number of region locks granted without waiting.\n", 00708 (u_long)sp->st_region_nowait); 00709 dl("The number of region locks granted after waiting.\n", 00710 (u_long)sp->st_region_wait); 00711 00712 return (0); 00713 } 00714 00715 /* 00716 * log_stats -- 00717 * Display log statistics. 00718 */ 00719 int 00720 log_stats(DB_ENV *dbenvp) 00721 { 00722 DB_LOG_STAT *sp; 00723 int ret; 00724 00725 if ((ret = CDB_log_stat(dbenvp, &sp, NULL)) != 0) { 00726 dbenvp->err(dbenvp, ret, NULL); 00727 return (1); 00728 } 00729 00730 printf("%lx\tLog magic number.\n", (u_long)sp->st_magic); 00731 printf("%lu\tLog version number.\n", (u_long)sp->st_version); 00732 dl_bytes("Log region size", 00733 (u_long)0, (u_long)0, (u_long)sp->st_regsize); 00734 dl_bytes("Log record cache size", 00735 (u_long)0, (u_long)0, (u_long)sp->st_lg_bsize); 00736 printf("%#o\tLog file mode.\n", sp->st_mode); 00737 if (sp->st_lg_max % MEGABYTE == 0) 00738 printf("%luMb\tLog file size.\n", 00739 (u_long)sp->st_lg_max / MEGABYTE); 00740 else if (sp->st_lg_max % 1024 == 0) 00741 printf("%luKb\tLog file size.\n", (u_long)sp->st_lg_max / 1024); 00742 else 00743 printf("%lu\tLog file size.\n", (u_long)sp->st_lg_max); 00744 dl_bytes("Log bytes written", 00745 (u_long)0, (u_long)sp->st_w_mbytes, (u_long)sp->st_w_bytes); 00746 dl_bytes("Log bytes written since last checkpoint", 00747 (u_long)0, (u_long)sp->st_wc_mbytes, (u_long)sp->st_wc_bytes); 00748 dl("Total log file writes.\n", (u_long)sp->st_wcount); 00749 dl("Total log file write due to overflow.\n", 00750 (u_long)sp->st_wcount_fill); 00751 dl("Total log file flushes.\n", (u_long)sp->st_scount); 00752 printf("%lu\tCurrent log file number.\n", (u_long)sp->st_cur_file); 00753 printf("%lu\tCurrent log file offset.\n", (u_long)sp->st_cur_offset); 00754 dl("The number of region locks granted without waiting.\n", 00755 (u_long)sp->st_region_nowait); 00756 dl("The number of region locks granted after waiting.\n", 00757 (u_long)sp->st_region_wait); 00758 00759 return (0); 00760 } 00761 00762 /* 00763 * mpool_stats -- 00764 * Display mpool statistics. 00765 */ 00766 int 00767 mpool_stats(DB_ENV *dbenvp) 00768 { 00769 DB_MPOOL_FSTAT **fsp; 00770 DB_MPOOL_STAT *gsp; 00771 int ret; 00772 00773 if (internal != NULL) { 00774 CDB___memp_dump_region(dbenvp, internal, stdout); 00775 return (1); 00776 } 00777 00778 if ((ret = CDB_memp_stat(dbenvp, &gsp, &fsp, NULL)) != 0) { 00779 dbenvp->err(dbenvp, ret, NULL); 00780 return (1); 00781 } 00782 00783 dl_bytes("Total cache size", 00784 (u_long)gsp->st_gbytes, (u_long)0, (u_long)gsp->st_bytes); 00785 dl("Number of caches.\n", (u_long)gsp->st_ncache); 00786 dl("Pool individual cache size.\n", (u_long)gsp->st_regsize); 00787 dl("Requested pages found in the cache", (u_long)gsp->st_cache_hit); 00788 if (gsp->st_cache_hit + gsp->st_cache_miss != 0) 00789 printf(" (%.0f%%)", ((double)gsp->st_cache_hit / 00790 (gsp->st_cache_hit + gsp->st_cache_miss)) * 100); 00791 printf(".\n"); 00792 dl("Requested pages mapped into the process' address space.\n", 00793 (u_long)gsp->st_map); 00794 dl("Requested pages not found in the cache.\n", 00795 (u_long)gsp->st_cache_miss); 00796 dl("Pages created in the cache.\n", (u_long)gsp->st_page_create); 00797 dl("Pages read into the cache.\n", (u_long)gsp->st_page_in); 00798 dl("Pages written from the cache to the backing file.\n", 00799 (u_long)gsp->st_page_out); 00800 dl("Clean pages forced from the cache.\n", 00801 (u_long)gsp->st_ro_evict); 00802 dl("Dirty pages forced from the cache.\n", 00803 (u_long)gsp->st_rw_evict); 00804 dl("Dirty buffers written by trickle-sync thread.\n", 00805 (u_long)gsp->st_page_trickle); 00806 dl("Current clean buffer count.\n", 00807 (u_long)gsp->st_page_clean); 00808 dl("Current dirty buffer count.\n", 00809 (u_long)gsp->st_page_dirty); 00810 dl("Number of hash buckets used for page location.\n", 00811 (u_long)gsp->st_hash_buckets); 00812 dl("Total number of times hash chains searched for a page.\n", 00813 (u_long)gsp->st_hash_searches); 00814 dl("The longest hash chain searched for a page.\n", 00815 (u_long)gsp->st_hash_longest); 00816 dl("Total number of hash buckets examined for page location.\n", 00817 (u_long)gsp->st_hash_examined); 00818 dl("The number of region locks granted without waiting.\n", 00819 (u_long)gsp->st_region_nowait); 00820 dl("The number of region locks granted after waiting.\n", 00821 (u_long)gsp->st_region_wait); 00822 00823 for (; fsp != NULL && *fsp != NULL; ++fsp) { 00824 printf("%s\n", DB_LINE); 00825 printf("Pool File: %s\n", (*fsp)->file_name); 00826 dl("Page size.\n", (u_long)(*fsp)->st_pagesize); 00827 dl("Requested pages found in the cache", 00828 (u_long)(*fsp)->st_cache_hit); 00829 if ((*fsp)->st_cache_hit + (*fsp)->st_cache_miss != 0) 00830 printf(" (%.0f%%)", ((double)(*fsp)->st_cache_hit / 00831 ((*fsp)->st_cache_hit + (*fsp)->st_cache_miss)) * 00832 100); 00833 printf(".\n"); 00834 dl("Requested pages mapped into the process' address space.\n", 00835 (u_long)(*fsp)->st_map); 00836 dl("Requested pages not found in the cache.\n", 00837 (u_long)(*fsp)->st_cache_miss); 00838 dl("Pages created in the cache.\n", 00839 (u_long)(*fsp)->st_page_create); 00840 dl("Pages read into the cache.\n", 00841 (u_long)(*fsp)->st_page_in); 00842 dl("Pages written from the cache to the backing file.\n", 00843 (u_long)(*fsp)->st_page_out); 00844 } 00845 00846 return (0); 00847 } 00848 00849 /* 00850 * txn_stats -- 00851 * Display transaction statistics. 00852 */ 00853 int 00854 txn_stats(DB_ENV *dbenvp) 00855 { 00856 DB_TXN_STAT *sp; 00857 u_int32_t i; 00858 int ret; 00859 const char *p; 00860 00861 if ((ret = CDB_txn_stat(dbenvp, &sp, NULL)) != 0) { 00862 dbenvp->err(dbenvp, ret, NULL); 00863 return (1); 00864 } 00865 00866 p = sp->st_last_ckp.file == 0 ? 00867 "No checkpoint LSN." : "File/offset for last checkpoint LSN."; 00868 printf("%lu/%lu\t%s\n", 00869 (u_long)sp->st_last_ckp.file, (u_long)sp->st_last_ckp.offset, p); 00870 p = sp->st_pending_ckp.file == 0 ? 00871 "No pending checkpoint LSN." : 00872 "File/offset for last pending checkpoint LSN."; 00873 printf("%lu/%lu\t%s\n", 00874 (u_long)sp->st_pending_ckp.file, 00875 (u_long)sp->st_pending_ckp.offset, p); 00876 if (sp->st_time_ckp == 0) 00877 printf("0\tNo checkpoint timestamp.\n"); 00878 else 00879 printf("%.24s\tCheckpoint timestamp.\n", 00880 ctime(&sp->st_time_ckp)); 00881 printf("%lx\tLast transaction ID allocated.\n", 00882 (u_long)sp->st_last_txnid); 00883 dl("Maximum number of active transactions possible.\n", 00884 (u_long)sp->st_maxtxns); 00885 dl("Active transactions.\n", (u_long)sp->st_nactive); 00886 dl("Maximum active transactions.\n", (u_long)sp->st_maxnactive); 00887 dl("Number of transactions begun.\n", (u_long)sp->st_nbegins); 00888 dl("Number of transactions aborted.\n", (u_long)sp->st_naborts); 00889 dl("Number of transactions committed.\n", (u_long)sp->st_ncommits); 00890 dl_bytes("Transaction region size", 00891 (u_long)0, (u_long)0, (u_long)sp->st_regsize); 00892 dl("The number of region locks granted without waiting.\n", 00893 (u_long)sp->st_region_nowait); 00894 dl("The number of region locks granted after waiting.\n", 00895 (u_long)sp->st_region_wait); 00896 qsort(sp->st_txnarray, 00897 sp->st_nactive, sizeof(sp->st_txnarray[0]), txn_compare); 00898 for (i = 0; i < sp->st_nactive; ++i) 00899 printf("\tid: %lx; initial LSN file/offest %lu/%lu\n", 00900 (u_long)sp->st_txnarray[i].txnid, 00901 (u_long)sp->st_txnarray[i].lsn.file, 00902 (u_long)sp->st_txnarray[i].lsn.offset); 00903 00904 return (0); 00905 } 00906 00907 int 00908 txn_compare(const void *a1, const void *b1) 00909 { 00910 const DB_TXN_ACTIVE *a, *b; 00911 00912 a = (DB_TXN_ACTIVE*)a1; 00913 b = (DB_TXN_ACTIVE*)b1; 00914 00915 if (a->txnid > b->txnid) 00916 return (1); 00917 if (a->txnid < b->txnid) 00918 return (-1); 00919 return (0); 00920 } 00921 00922 /* 00923 * dl -- 00924 * Display a big value. 00925 */ 00926 void 00927 dl(const char *msg, u_long value) 00928 { 00929 /* 00930 * Two formats: if less than 10 million, display as the number, if 00931 * greater than 10 million display as ###M. 00932 */ 00933 if (value < 10000000) 00934 printf("%lu\t%s", value, msg); 00935 else 00936 printf("%luM\t%s", value / 1000000, msg); 00937 } 00938 00939 /* 00940 * dl_bytes -- 00941 * Display a big number of bytes. 00942 */ 00943 void 00944 dl_bytes(const char *msg, u_long gbytes, u_long mbytes, u_long bytes) 00945 { 00946 const char *sep; 00947 u_long sbytes; 00948 int showbytes; 00949 00950 sbytes = bytes; 00951 while (bytes > MEGABYTE) { 00952 ++mbytes; 00953 bytes -= MEGABYTE; 00954 } 00955 while (mbytes > GIGABYTE / MEGABYTE) { 00956 ++gbytes; 00957 --mbytes; 00958 } 00959 00960 sep = ""; 00961 showbytes = 0; 00962 if (gbytes > 0) { 00963 printf("%luGB", gbytes); 00964 sep = " "; 00965 showbytes = 1; 00966 } 00967 if (mbytes > 0) { 00968 printf("%s%luMB", sep, mbytes); 00969 sep = " "; 00970 showbytes = 1; 00971 } 00972 if (bytes > 1024) { 00973 printf("%s%luKB", sep, bytes / 1024); 00974 bytes %= 1024; 00975 sep = " "; 00976 showbytes = 1; 00977 } 00978 if (bytes > 0) 00979 printf("%s%luB", sep, bytes); 00980 printf("\t%s", msg); 00981 if (showbytes) 00982 printf(" (%lu bytes)", sbytes); 00983 printf(".\n"); 00984 } 00985 00986 /* 00987 * prflags -- 00988 * Print out flag values. 00989 */ 00990 void 00991 prflags(u_int32_t flags, const FN *fnp) 00992 { 00993 const char *sep; 00994 00995 sep = "\t"; 00996 printf("Flags:"); 00997 for (; fnp->mask != 0; ++fnp) 00998 if (fnp->mask & flags) { 00999 printf("%s%s", sep, fnp->name); 01000 sep = ", "; 01001 } 01002 printf("\n"); 01003 } 01004 01005 /* 01006 * db_init -- 01007 * Initialize the environment. 01008 */ 01009 int 01010 db_init(char *home, test_t ttype) 01011 { 01012 u_int32_t flags; 01013 int ret; 01014 01015 /* 01016 * Try and use the shared memory pool region when reporting statistics 01017 * on the DB databases, so our information is as up-to-date as possible, 01018 * even if the mpool cache hasn't been flushed. 01019 */ 01020 ret = 0; 01021 flags = DB_USE_ENVIRON; 01022 switch (ttype) { 01023 case T_ENV: 01024 break; 01025 case T_DB: 01026 case T_MPOOL: 01027 LF_SET(DB_INIT_MPOOL); 01028 break; 01029 case T_LOCK: 01030 LF_SET(DB_INIT_LOCK); 01031 break; 01032 case T_LOG: 01033 LF_SET(DB_INIT_LOG); 01034 break; 01035 case T_TXN: 01036 LF_SET(DB_INIT_TXN); 01037 break; 01038 case T_NOTSET: 01039 abort(); 01040 /* NOTREACHED */ 01041 } 01042 01043 /* 01044 * If that fails, and we're trying to look at a shared region, it's 01045 * a hard failure. 01046 */ 01047 if ((ret = dbenv->open(dbenv, home, flags, 0)) == 0) 01048 return (0); 01049 if (ttype != T_DB) { 01050 if (ret == 0) 01051 ret = EINVAL; 01052 dbenv->err(dbenv, ret, "open"); 01053 return (1); 01054 } 01055 01056 /* 01057 * We're trying to look at a database. 01058 * 01059 * An environment is required because we may be trying to look at 01060 * databases in directories other than the current one. We could 01061 * avoid using an environment iff the -h option wasn't specified, 01062 * but that seems like more work than it's worth. 01063 * 01064 * 01065 * No environment exists (or, at least no environment that includes 01066 * an mpool region exists). Create one, but make it private so that 01067 * no files are actually created. 01068 */ 01069 LF_SET(DB_CREATE | DB_PRIVATE); 01070 if ((ret = dbenv->open(dbenv, home, flags, 0)) == 0) 01071 return (0); 01072 01073 /* An environment is required. */ 01074 dbenv->err(dbenv, ret, "open"); 01075 return (1); 01076 } 01077 01078 /* 01079 * argcheck -- 01080 * Return if argument flags are okay. 01081 */ 01082 int 01083 argcheck(char *arg, const char *ok_args) 01084 { 01085 for (; *arg != '0円'; ++arg) 01086 if (strchr(ok_args, *arg) == NULL) 01087 return (0); 01088 return (1); 01089 } 01090 01091 void 01092 usage() 01093 { 01094 fprintf(stderr, "usage: htdb_stat %s\n", 01095 "[-celmNtVzW] [-C Acflmo] [-d file [-s file]] [-h home] [-M Ahlm]"); 01096 exit (1); 01097 }