htdb_stat.cc

Go to the documentation of this file.
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>&lt;number&gt;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 = &regs[--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 }

Generated on Sun Jun 8 10:56:39 2008 for GNUmifluz by  doxygen 1.5.5