summaryrefslogtreecommitdiff
path: root/util/db_stat.c
diff options
context:
space:
mode:
authorLorry <lorry@roadtrain.codethink.co.uk>2012-07-20 20:00:05 +0100
committerLorry <lorry@roadtrain.codethink.co.uk>2012-07-20 20:00:05 +0100
commit3ef782d3745ea8f25a3151561a3cfb882190210e (patch)
tree86b9c2f5fde051dd0bced99b3fc9f5a3ba08db69 /util/db_stat.c
downloadberkeleydb-3ef782d3745ea8f25a3151561a3cfb882190210e.tar.gz
Tarball conversion
Diffstat (limited to 'util/db_stat.c')
-rw-r--r--util/db_stat.c483
1 files changed, 483 insertions, 0 deletions
diff --git a/util/db_stat.c b/util/db_stat.c
new file mode 100644
index 00000000..a12e1122
--- /dev/null
+++ b/util/db_stat.c
@@ -0,0 +1,483 @@
+/*-
+ * See the file LICENSE for redistribution information.
+ *
+ * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved.
+ *
+ * $Id$
+ */
+
+#include "db_config.h"
+
+#include "db_int.h"
+
+#ifndef lint
+static const char copyright[] =
+ "Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved.\n";
+#endif
+
+typedef enum { T_NOTSET, T_DB,
+ T_ENV, T_LOCK, T_LOG, T_MPOOL, T_MUTEX, T_REP, T_TXN } test_t;
+
+int db_init __P((DB_ENV *, char *, test_t, u_int32_t, int *));
+int main __P((int, char *[]));
+int usage __P((void));
+int version_check __P((void));
+
+const char *progname;
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ extern char *optarg;
+ extern int optind;
+ DB_ENV *dbenv;
+ DB *dbp;
+ test_t ttype;
+ u_int32_t cache, flags;
+ int ch, exitval;
+ int nflag, private, resize, ret;
+ char *db, *home, *p, *passwd, *subdb;
+
+ if ((progname = __db_rpath(argv[0])) == NULL)
+ progname = argv[0];
+ else
+ ++progname;
+
+ if ((ret = version_check()) != 0)
+ return (ret);
+
+ dbenv = NULL;
+ dbp = NULL;
+ ttype = T_NOTSET;
+ cache = MEGABYTE;
+ exitval = flags = nflag = private = 0;
+ db = home = passwd = subdb = NULL;
+
+ while ((ch = getopt(argc,
+ argv, "aC:cd:Eefgh:L:lM:mNP:R:rs:tVxX:Z")) != EOF)
+ switch (ch) {
+ case 'a':
+ LF_SET(DB_STAT_ALLOC);
+ break;
+ case 'C': case 'c':
+ if (ttype != T_NOTSET && ttype != T_LOCK)
+ goto argcombo;
+ ttype = T_LOCK;
+ if (ch != 'c')
+ for (p = optarg; *p; ++p)
+ switch (*p) {
+ case 'A':
+ LF_SET(DB_STAT_ALL);
+ break;
+ case 'c':
+ LF_SET(DB_STAT_LOCK_CONF);
+ break;
+ case 'l':
+ LF_SET(DB_STAT_LOCK_LOCKERS);
+ break;
+ case 'm': /* Backward compatible. */
+ break;
+ case 'o':
+ LF_SET(DB_STAT_LOCK_OBJECTS);
+ break;
+ case 'p':
+ LF_SET(DB_STAT_LOCK_PARAMS);
+ break;
+ default:
+ return (usage());
+ }
+ break;
+ case 'd':
+ if (ttype != T_NOTSET && ttype != T_DB)
+ goto argcombo;
+ ttype = T_DB;
+ db = optarg;
+ break;
+ case 'E': case 'e':
+ if (ttype != T_NOTSET && ttype != T_ENV)
+ goto argcombo;
+ ttype = T_ENV;
+ LF_SET(DB_STAT_SUBSYSTEM);
+ if (ch == 'E')
+ LF_SET(DB_STAT_ALL);
+ break;
+ case 'f':
+ if (ttype != T_NOTSET && ttype != T_DB)
+ goto argcombo;
+ ttype = T_DB;
+ LF_SET(DB_FAST_STAT);
+ break;
+ case 'h':
+ home = optarg;
+ break;
+ case 'L': case 'l':
+ if (ttype != T_NOTSET && ttype != T_LOG)
+ goto argcombo;
+ ttype = T_LOG;
+ if (ch != 'l')
+ for (p = optarg; *p; ++p)
+ switch (*p) {
+ case 'A':
+ LF_SET(DB_STAT_ALL);
+ break;
+ default:
+ return (usage());
+ }
+ break;
+ case 'M': case 'm':
+ if (ttype != T_NOTSET && ttype != T_MPOOL)
+ goto argcombo;
+ ttype = T_MPOOL;
+ if (ch != 'm')
+ for (p = optarg; *p; ++p)
+ switch (*p) {
+ case 'A':
+ LF_SET(DB_STAT_ALL);
+ break;
+ case 'h':
+ LF_SET(DB_STAT_MEMP_HASH);
+ break;
+ case 'm': /* Backward compatible. */
+ break;
+ default:
+ return (usage());
+ }
+ break;
+ case 'N':
+ nflag = 1;
+ break;
+ case 'P':
+ if (passwd != NULL) {
+ fprintf(stderr, DB_STR("5139",
+ "Password may not be specified twice"));
+ free(passwd);
+ return (EXIT_FAILURE);
+ }
+ passwd = strdup(optarg);
+ memset(optarg, 0, strlen(optarg));
+ if (passwd == NULL) {
+ fprintf(stderr, DB_STR_A("5005",
+ "%s: strdup: %s\n", "%s %s\n"),
+ progname, strerror(errno));
+ return (EXIT_FAILURE);
+ }
+ break;
+ case 'R': case 'r':
+ if (ttype != T_NOTSET && ttype != T_REP)
+ goto argcombo;
+ ttype = T_REP;
+ if (ch != 'r')
+ for (p = optarg; *p; ++p)
+ switch (*p) {
+ case 'A':
+ LF_SET(DB_STAT_ALL);
+ break;
+ default:
+ return (usage());
+ }
+ break;
+ case 's':
+ if (ttype != T_NOTSET && ttype != T_DB)
+ goto argcombo;
+ ttype = T_DB;
+ subdb = optarg;
+ break;
+ case 't':
+ if (ttype != T_NOTSET) {
+argcombo: fprintf(stderr, DB_STR_A("5006",
+ "%s: illegal option combination\n",
+ "%s\n"), progname);
+ return (usage());
+ }
+ ttype = T_TXN;
+ break;
+ case 'V':
+ printf("%s\n", db_version(NULL, NULL, NULL));
+ return (EXIT_SUCCESS);
+ case 'X': case 'x':
+ if (ttype != T_NOTSET && ttype != T_MUTEX)
+ goto argcombo;
+ ttype = T_MUTEX;
+ if (ch != 'x')
+ for (p = optarg; *p; ++p)
+ switch (*p) {
+ case 'A':
+ LF_SET(DB_STAT_ALL);
+ break;
+ default:
+ return (usage());
+ }
+ break;
+ case 'Z':
+ LF_SET(DB_STAT_CLEAR);
+ break;
+ case '?':
+ default:
+ return (usage());
+ }
+ argc -= optind;
+ argv += optind;
+
+ switch (ttype) {
+ case T_DB:
+ if (db == NULL)
+ return (usage());
+ break;
+ case T_ENV:
+ case T_LOCK:
+ case T_LOG:
+ case T_MPOOL:
+ case T_MUTEX:
+ case T_REP:
+ case T_TXN:
+ break;
+ case T_NOTSET:
+ return (usage());
+ }
+
+ if (LF_ISSET(DB_STAT_ALL | DB_STAT_ALLOC) == DB_STAT_ALLOC)
+ return (usage());
+
+ /* Handle possible interruptions. */
+ __db_util_siginit();
+
+ /*
+ * Create an environment object and initialize it for error
+ * reporting.
+ */
+retry: if ((ret = db_env_create(&dbenv, 0)) != 0) {
+ fprintf(stderr,
+ "%s: db_env_create: %s\n", progname, db_strerror(ret));
+ goto err;
+ }
+
+ dbenv->set_errfile(dbenv, stderr);
+ dbenv->set_errpfx(dbenv, progname);
+
+ if (nflag) {
+ if ((ret = dbenv->set_flags(dbenv, DB_NOLOCKING, 1)) != 0) {
+ dbenv->err(dbenv, ret, "set_flags: DB_NOLOCKING");
+ goto err;
+ }
+ if ((ret = dbenv->set_flags(dbenv, DB_NOPANIC, 1)) != 0) {
+ dbenv->err(dbenv, ret, "set_flags: DB_NOPANIC");
+ goto err;
+ }
+ }
+
+ if (passwd != NULL &&
+ (ret = dbenv->set_encrypt(dbenv, passwd, DB_ENCRYPT_AES)) != 0) {
+ dbenv->err(dbenv, ret, "set_passwd");
+ goto err;
+ }
+
+ /* Initialize the environment. */
+ if (db_init(dbenv, home, ttype, cache, &private) != 0)
+ goto err;
+
+ switch (ttype) {
+ case T_DB:
+ /* Create the DB object and open the file. */
+ if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
+ dbenv->err(dbenv, ret, "db_create");
+ goto err;
+ }
+
+ /*
+ * We open the database for writing so we can update the cached
+ * statistics, but it's OK to fail, we can open read-only and
+ * proceed.
+ *
+ * Turn off error messages for now -- we can't open lots of
+ * databases read-write (for example, master databases and
+ * hash databases for which we don't know the hash function).
+ */
+ dbenv->set_errfile(dbenv, NULL);
+ ret = dbp->open(dbp, NULL, db, subdb, DB_UNKNOWN, 0, 0);
+ dbenv->set_errfile(dbenv, stderr);
+ if (ret != 0) {
+ /* Handles cannot be reused after a failed DB->open. */
+ (void)dbp->close(dbp, 0);
+ if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
+ dbenv->err(dbenv, ret, "db_create");
+ goto err;
+ }
+
+ if ((ret = dbp->open(dbp,
+ NULL, db, subdb, DB_UNKNOWN, DB_RDONLY, 0)) != 0) {
+ dbenv->err(dbenv, ret, "DB->open: %s", db);
+ goto err;
+ }
+ }
+
+ /* Check if cache is too small for this DB's pagesize. */
+ if (private) {
+ if ((ret = __db_util_cache(dbp, &cache, &resize)) != 0)
+ goto err;
+ if (resize) {
+ (void)dbp->close(dbp, DB_NOSYNC);
+ dbp = NULL;
+
+ (void)dbenv->close(dbenv, 0);
+ dbenv = NULL;
+ goto retry;
+ }
+ }
+
+ if (dbp->stat_print(dbp, flags))
+ goto err;
+ break;
+ case T_ENV:
+ if (dbenv->stat_print(dbenv, flags))
+ goto err;
+ break;
+ case T_LOCK:
+ if (dbenv->lock_stat_print(dbenv, flags))
+ goto err;
+ break;
+ case T_LOG:
+ if (dbenv->log_stat_print(dbenv, flags))
+ goto err;
+ break;
+ case T_MPOOL:
+ if (dbenv->memp_stat_print(dbenv, flags))
+ goto err;
+ break;
+ case T_MUTEX:
+ if (dbenv->mutex_stat_print(dbenv, flags))
+ goto err;
+ break;
+ case T_REP:
+#ifdef HAVE_REPLICATION_THREADS
+ if (dbenv->repmgr_stat_print(dbenv, flags))
+ goto err;
+#endif
+ if (dbenv->rep_stat_print(dbenv, flags))
+ goto err;
+ break;
+ case T_TXN:
+ if (dbenv->txn_stat_print(dbenv, flags))
+ goto err;
+ break;
+ case T_NOTSET:
+ dbenv->errx(dbenv, DB_STR("5007",
+ "Unknown statistics flag"));
+ goto err;
+ }
+
+ if (0) {
+err: exitval = 1;
+ }
+ if (dbp != NULL && (ret = dbp->close(dbp, DB_NOSYNC)) != 0) {
+ exitval = 1;
+ dbenv->err(dbenv, ret, DB_STR("5008", "close"));
+ }
+ if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0) {
+ exitval = 1;
+ fprintf(stderr,
+ "%s: dbenv->close: %s\n", progname, db_strerror(ret));
+ }
+
+ if (passwd != NULL)
+ free(passwd);
+
+ /* Resend any caught signal. */
+ __db_util_sigresend();
+
+ return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
+}
+
+/*
+ * db_init --
+ * Initialize the environment.
+ */
+int
+db_init(dbenv, home, ttype, cache, is_private)
+ DB_ENV *dbenv;
+ char *home;
+ test_t ttype;
+ u_int32_t cache;
+ int *is_private;
+{
+ u_int32_t oflags;
+ int ret;
+
+ /*
+ * If our environment open fails, and we're trying to look at a
+ * shared region, it's a hard failure.
+ *
+ * We will probably just drop core if the environment we join does
+ * not include a memory pool. This is probably acceptable; trying
+ * to use an existing environment that does not contain a memory
+ * pool to look at a database can be safely construed as operator
+ * error, I think.
+ */
+ *is_private = 0;
+ if ((ret = dbenv->open(dbenv, home, DB_USE_ENVIRON, 0)) == 0)
+ return (0);
+ if (ret == DB_VERSION_MISMATCH)
+ goto err;
+ if (ttype != T_DB && ttype != T_LOG) {
+ dbenv->err(dbenv, ret, "DB_ENV->open%s%s",
+ home == NULL ? "" : ": ", home == NULL ? "" : home);
+ return (1);
+ }
+
+ /*
+ * We're looking at a database or set of log files and no environment
+ * exists. Create one, but make it private so no files are actually
+ * created. Declare a reasonably large cache so that we don't fail
+ * when reporting statistics on large databases.
+ *
+ * An environment is required to look at databases because we may be
+ * trying to look at databases in directories other than the current
+ * one.
+ */
+ if ((ret = dbenv->set_cachesize(dbenv, 0, cache, 1)) != 0) {
+ dbenv->err(dbenv, ret, "set_cachesize");
+ return (1);
+ }
+ *is_private = 1;
+ oflags = DB_CREATE | DB_PRIVATE | DB_USE_ENVIRON;
+ if (ttype == T_DB)
+ oflags |= DB_INIT_MPOOL;
+ if (ttype == T_LOG)
+ oflags |= DB_INIT_LOG;
+ if ((ret = dbenv->open(dbenv, home, oflags, 0)) == 0)
+ return (0);
+
+ /* An environment is required. */
+err: dbenv->err(dbenv, ret, "DB_ENV->open");
+ return (1);
+}
+
+int
+usage()
+{
+ fprintf(stderr, "usage: %s %s\n", progname,
+ "-d file [-fN] [-h home] [-P password] [-s database]");
+ fprintf(stderr, "usage: %s %s\n\t%s\n", progname,
+ "[-cEelmrtVx] [-C Aclop]",
+ "[-h home] [-L A] [-M A] [-P password] [-R A] [-X A] [-aNZ]");
+ return (EXIT_FAILURE);
+}
+
+int
+version_check()
+{
+ int v_major, v_minor, v_patch;
+
+ /* Make sure we're loaded with the right version of the DB library. */
+ (void)db_version(&v_major, &v_minor, &v_patch);
+ if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
+ fprintf(stderr, DB_STR_A("5009",
+ "%s: version %d.%d doesn't match library version %d.%d\n",
+ "%s %d %d %d %d\n"), progname,
+ DB_VERSION_MAJOR, DB_VERSION_MINOR,
+ v_major, v_minor);
+ return (EXIT_FAILURE);
+ }
+ return (0);
+}