summaryrefslogtreecommitdiff
path: root/bdb/lock/lock_stat.c
diff options
context:
space:
mode:
Diffstat (limited to 'bdb/lock/lock_stat.c')
-rw-r--r--bdb/lock/lock_stat.c370
1 files changed, 230 insertions, 140 deletions
diff --git a/bdb/lock/lock_stat.c b/bdb/lock/lock_stat.c
index ed5b60d0d7a..0bef3e18021 100644
--- a/bdb/lock/lock_stat.c
+++ b/bdb/lock/lock_stat.c
@@ -1,94 +1,105 @@
/*-
* See the file LICENSE for redistribution information.
*
- * Copyright (c) 1996, 1997, 1998, 1999, 2000
+ * Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
-static const char revid[] = "$Id: lock_stat.c,v 11.4 2000/12/08 20:15:31 ubell Exp $";
+static const char revid[] = "$Id: lock_stat.c,v 11.32 2002/08/14 20:08:51 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
-
-#include <ctype.h>
+#include <string.h>
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
#endif
-#ifdef HAVE_RPC
-#include "db_server.h"
+#include <ctype.h>
#endif
#include "db_int.h"
-#include "db_shash.h"
-#include "lock.h"
-
-#ifdef HAVE_RPC
-#include "gen_client_ext.h"
-#include "rpc_client_ext.h"
-#endif
+#include "dbinc/db_shash.h"
+#include "dbinc/db_page.h"
+#include "dbinc/lock.h"
+#include "dbinc/log.h"
+#include "dbinc/db_am.h"
static void __lock_dump_locker __P((DB_LOCKTAB *, DB_LOCKER *, FILE *));
static void __lock_dump_object __P((DB_LOCKTAB *, DB_LOCKOBJ *, FILE *));
-static const char *
- __lock_dump_status __P((db_status_t));
+static void __lock_printheader __P((void));
/*
- * lock_stat --
+ * __lock_stat --
* Return LOCK statistics.
+ *
+ * PUBLIC: int __lock_stat __P((DB_ENV *, DB_LOCK_STAT **, u_int32_t));
*/
int
-lock_stat(dbenv, statp, db_malloc)
+__lock_stat(dbenv, statp, flags)
DB_ENV *dbenv;
DB_LOCK_STAT **statp;
- void *(*db_malloc) __P((size_t));
+ u_int32_t flags;
{
DB_LOCKREGION *region;
DB_LOCKTAB *lt;
- DB_LOCK_STAT *stats;
+ DB_LOCK_STAT *stats, tmp;
int ret;
-#ifdef HAVE_RPC
- if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
- return (__dbcl_lock_stat(dbenv, statp, db_malloc));
-#endif
-
PANIC_CHECK(dbenv);
- ENV_REQUIRES_CONFIG(dbenv, dbenv->lk_handle, DB_INIT_LOCK);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->lk_handle, "DB_ENV->lock_stat", DB_INIT_LOCK);
*statp = NULL;
+ if ((ret = __db_fchk(dbenv,
+ "DB_ENV->lock_stat", flags, DB_STAT_CLEAR)) != 0)
+ return (ret);
lt = dbenv->lk_handle;
- if ((ret = __os_malloc(dbenv, sizeof(*stats), db_malloc, &stats)) != 0)
+ if ((ret = __os_umalloc(dbenv, sizeof(*stats), &stats)) != 0)
return (ret);
/* Copy out the global statistics. */
R_LOCK(dbenv, &lt->reginfo);
region = lt->reginfo.primary;
- stats->st_lastid = region->id;
- stats->st_maxlocks = region->maxlocks;
- stats->st_maxlockers = region->maxlockers;
- stats->st_maxobjects = region->maxobjects;
- stats->st_nmodes = region->nmodes;
- stats->st_nlockers = region->nlockers;
- stats->st_maxnlockers = region->maxnlockers;
- stats->st_nobjects = region->nobjects;
- stats->st_maxnobjects = region->maxnobjects;
- stats->st_nlocks = region->nlocks;
- stats->st_maxnlocks = region->maxnlocks;
- stats->st_nconflicts = region->nconflicts;
- stats->st_nrequests = region->nrequests;
- stats->st_nreleases = region->nreleases;
- stats->st_nnowaits = region->nnowaits;
- stats->st_ndeadlocks = region->ndeadlocks;
+ memcpy(stats, &region->stat, sizeof(*stats));
+ stats->st_locktimeout = region->lk_timeout;
+ stats->st_txntimeout = region->tx_timeout;
stats->st_region_wait = lt->reginfo.rp->mutex.mutex_set_wait;
stats->st_region_nowait = lt->reginfo.rp->mutex.mutex_set_nowait;
stats->st_regsize = lt->reginfo.rp->size;
+ if (LF_ISSET(DB_STAT_CLEAR)) {
+ tmp = region->stat;
+ memset(&region->stat, 0, sizeof(region->stat));
+ lt->reginfo.rp->mutex.mutex_set_wait = 0;
+ lt->reginfo.rp->mutex.mutex_set_nowait = 0;
+
+ region->stat.st_id = tmp.st_id;
+ region->stat.st_cur_maxid = tmp.st_cur_maxid;
+ region->stat.st_maxlocks = tmp.st_maxlocks;
+ region->stat.st_maxlockers = tmp.st_maxlockers;
+ region->stat.st_maxobjects = tmp.st_maxobjects;
+ region->stat.st_nlocks =
+ region->stat.st_maxnlocks = tmp.st_nlocks;
+ region->stat.st_nlockers =
+ region->stat.st_maxnlockers = tmp.st_nlockers;
+ region->stat.st_nobjects =
+ region->stat.st_maxnobjects = tmp.st_nobjects;
+ region->stat.st_nmodes = tmp.st_nmodes;
+ }
R_UNLOCK(dbenv, &lt->reginfo);
@@ -97,30 +108,34 @@ lock_stat(dbenv, statp, db_malloc)
}
#define LOCK_DUMP_CONF 0x001 /* Conflict matrix. */
-#define LOCK_DUMP_FREE 0x002 /* Display lock free list. */
-#define LOCK_DUMP_LOCKERS 0x004 /* Display lockers. */
-#define LOCK_DUMP_MEM 0x008 /* Display region memory. */
-#define LOCK_DUMP_OBJECTS 0x010 /* Display objects. */
-#define LOCK_DUMP_ALL 0x01f /* Display all. */
+#define LOCK_DUMP_LOCKERS 0x002 /* Display lockers. */
+#define LOCK_DUMP_MEM 0x004 /* Display region memory. */
+#define LOCK_DUMP_OBJECTS 0x008 /* Display objects. */
+#define LOCK_DUMP_PARAMS 0x010 /* Display params. */
+#define LOCK_DUMP_ALL /* All */ \
+ (LOCK_DUMP_CONF | LOCK_DUMP_LOCKERS | LOCK_DUMP_MEM | \
+ LOCK_DUMP_OBJECTS | LOCK_DUMP_PARAMS)
/*
* __lock_dump_region --
*
- * PUBLIC: void __lock_dump_region __P((DB_ENV *, char *, FILE *));
+ * PUBLIC: int __lock_dump_region __P((DB_ENV *, char *, FILE *));
*/
-void
+int
__lock_dump_region(dbenv, area, fp)
DB_ENV *dbenv;
char *area;
FILE *fp;
{
- struct __db_lock *lp;
DB_LOCKER *lip;
DB_LOCKOBJ *op;
DB_LOCKREGION *lrp;
DB_LOCKTAB *lt;
u_int32_t flags, i, j;
- int label;
+
+ PANIC_CHECK(dbenv);
+ ENV_REQUIRES_CONFIG(dbenv,
+ dbenv->lk_handle, "lock_dump_region", DB_INIT_LOCK);
/* Make it easy to call from the debugger. */
if (fp == NULL)
@@ -134,9 +149,6 @@ __lock_dump_region(dbenv, area, fp)
case 'c':
LF_SET(LOCK_DUMP_CONF);
break;
- case 'f':
- LF_SET(LOCK_DUMP_FREE);
- break;
case 'l':
LF_SET(LOCK_DUMP_LOCKERS);
break;
@@ -146,91 +158,67 @@ __lock_dump_region(dbenv, area, fp)
case 'o':
LF_SET(LOCK_DUMP_OBJECTS);
break;
+ case 'p':
+ LF_SET(LOCK_DUMP_PARAMS);
+ break;
}
lt = dbenv->lk_handle;
lrp = lt->reginfo.primary;
LOCKREGION(dbenv, lt);
- fprintf(fp, "%s\nLock region parameters\n", DB_LINE);
- fprintf(fp, "%s: %lu, %s: %lu, %s: %lu, %s: %lu, %s: %lu, %s: %lu, %s: %lu\n",
- "locker table size", (u_long)lrp->locker_t_size,
- "object table size", (u_long)lrp->object_t_size,
- "obj_off", (u_long)lrp->obj_off,
- "osynch_off", (u_long)lrp->osynch_off,
- "locker_off", (u_long)lrp->locker_off,
- "lsynch_off", (u_long)lrp->lsynch_off,
- "need_dd", (u_long)lrp->need_dd);
+ if (LF_ISSET(LOCK_DUMP_PARAMS)) {
+ fprintf(fp, "%s\nLock region parameters\n", DB_LINE);
+ fprintf(fp,
+ "%s: %lu, %s: %lu, %s: %lu,\n%s: %lu, %s: %lu, %s: %lu, %s: %lu\n",
+ "locker table size", (u_long)lrp->locker_t_size,
+ "object table size", (u_long)lrp->object_t_size,
+ "obj_off", (u_long)lrp->obj_off,
+ "osynch_off", (u_long)lrp->osynch_off,
+ "locker_off", (u_long)lrp->locker_off,
+ "lsynch_off", (u_long)lrp->lsynch_off,
+ "need_dd", (u_long)lrp->need_dd);
+ }
if (LF_ISSET(LOCK_DUMP_CONF)) {
fprintf(fp, "\n%s\nConflict matrix\n", DB_LINE);
- for (i = 0; i < lrp->nmodes; i++) {
- for (j = 0; j < lrp->nmodes; j++)
- fprintf(fp, "%lu\t",
- (u_long)lt->conflicts[i * lrp->nmodes + j]);
+ for (i = 0; i < lrp->stat.st_nmodes; i++) {
+ for (j = 0; j < lrp->stat.st_nmodes; j++)
+ fprintf(fp, "%lu\t", (u_long)
+ lt->conflicts[i * lrp->stat.st_nmodes + j]);
fprintf(fp, "\n");
}
}
if (LF_ISSET(LOCK_DUMP_LOCKERS)) {
- fprintf(fp, "%s\nLocker hash buckets\n", DB_LINE);
- for (i = 0; i < lrp->locker_t_size; i++) {
- label = 1;
+ fprintf(fp, "%s\nLocks grouped by lockers\n", DB_LINE);
+ __lock_printheader();
+ for (i = 0; i < lrp->locker_t_size; i++)
for (lip =
SH_TAILQ_FIRST(&lt->locker_tab[i], __db_locker);
lip != NULL;
lip = SH_TAILQ_NEXT(lip, links, __db_locker)) {
- if (label) {
- fprintf(fp, "Bucket %lu:\n", (u_long)i);
- label = 0;
- }
__lock_dump_locker(lt, lip, fp);
}
- }
}
if (LF_ISSET(LOCK_DUMP_OBJECTS)) {
- fprintf(fp, "%s\nObject hash buckets\n", DB_LINE);
+ fprintf(fp, "%s\nLocks grouped by object\n", DB_LINE);
+ __lock_printheader();
for (i = 0; i < lrp->object_t_size; i++) {
- label = 1;
for (op = SH_TAILQ_FIRST(&lt->obj_tab[i], __db_lockobj);
op != NULL;
- op = SH_TAILQ_NEXT(op, links, __db_lockobj)) {
- if (label) {
- fprintf(fp, "Bucket %lu:\n", (u_long)i);
- label = 0;
- }
+ op = SH_TAILQ_NEXT(op, links, __db_lockobj))
__lock_dump_object(lt, op, fp);
- }
}
}
- if (LF_ISSET(LOCK_DUMP_FREE)) {
- fprintf(fp, "%s\nLock free list\n", DB_LINE);
- for (lp = SH_TAILQ_FIRST(&lrp->free_locks, __db_lock);
- lp != NULL;
- lp = SH_TAILQ_NEXT(lp, links, __db_lock))
- fprintf(fp, "0x%lx: %lu\t%lu\t%s\t0x%lx\n", (u_long)lp,
- (u_long)lp->holder, (u_long)lp->mode,
- __lock_dump_status(lp->status), (u_long)lp->obj);
-
- fprintf(fp, "%s\nObject free list\n", DB_LINE);
- for (op = SH_TAILQ_FIRST(&lrp->free_objs, __db_lockobj);
- op != NULL;
- op = SH_TAILQ_NEXT(op, links, __db_lockobj))
- fprintf(fp, "0x%lx\n", (u_long)op);
-
- fprintf(fp, "%s\nLocker free list\n", DB_LINE);
- for (lip = SH_TAILQ_FIRST(&lrp->free_lockers, __db_locker);
- lip != NULL;
- lip = SH_TAILQ_NEXT(lip, links, __db_locker))
- fprintf(fp, "0x%lx\n", (u_long)lip);
- }
-
if (LF_ISSET(LOCK_DUMP_MEM))
__db_shalloc_dump(lt->reginfo.addr, fp);
UNLOCKREGION(dbenv, lt);
+
+ return (0);
}
static void
@@ -240,16 +228,35 @@ __lock_dump_locker(lt, lip, fp)
FILE *fp;
{
struct __db_lock *lp;
+ time_t s;
+ char buf[64];
- fprintf(fp, "L %lx [%ld]", (u_long)lip->id, (long)lip->dd_id);
+ fprintf(fp, "%8lx dd=%2ld locks held %-4d write locks %-4d",
+ (u_long)lip->id, (long)lip->dd_id, lip->nlocks, lip->nwrites);
fprintf(fp, " %s ", F_ISSET(lip, DB_LOCKER_DELETED) ? "(D)" : " ");
+ if (LOCK_TIME_ISVALID(&lip->tx_expire)) {
+ s = lip->tx_expire.tv_sec;
+ strftime(buf, sizeof(buf), "%m-%d-%H:%M:%S", localtime(&s));
+ fprintf(fp,
+ " expires %s.%lu", buf, (u_long)lip->tx_expire.tv_usec);
+ }
+ if (F_ISSET(lip, DB_LOCKER_TIMEOUT))
+ fprintf(fp, " lk timeout %u", lip->lk_timeout);
+ if (LOCK_TIME_ISVALID(&lip->lk_expire)) {
+ s = lip->lk_expire.tv_sec;
+ strftime(buf, sizeof(buf), "%m-%d-%H:%M:%S", localtime(&s));
+ fprintf(fp,
+ " lk expires %s.%lu", buf, (u_long)lip->lk_expire.tv_usec);
+ }
+ fprintf(fp, "\n");
- if ((lp = SH_LIST_FIRST(&lip->heldby, __db_lock)) == NULL)
- fprintf(fp, "\n");
- else
+ lp = SH_LIST_FIRST(&lip->heldby, __db_lock);
+ if (lp != NULL) {
for (; lp != NULL;
lp = SH_LIST_NEXT(lp, locker_links, __db_lock))
__lock_printlock(lt, lp, 1);
+ fprintf(fp, "\n");
+ }
}
static void
@@ -259,50 +266,133 @@ __lock_dump_object(lt, op, fp)
FILE *fp;
{
struct __db_lock *lp;
- u_int32_t j;
- u_int8_t *ptr;
- u_int ch;
-
- ptr = SH_DBT_PTR(&op->lockobj);
- for (j = 0; j < op->lockobj.size; ptr++, j++) {
- ch = *ptr;
- fprintf(fp, isprint(ch) ? "%c" : "\\%o", ch);
- }
- fprintf(fp, "\n");
- fprintf(fp, "H:");
for (lp =
SH_TAILQ_FIRST(&op->holders, __db_lock);
lp != NULL;
lp = SH_TAILQ_NEXT(lp, links, __db_lock))
__lock_printlock(lt, lp, 1);
- lp = SH_TAILQ_FIRST(&op->waiters, __db_lock);
- if (lp != NULL) {
- fprintf(fp, "\nW:");
- for (; lp != NULL; lp = SH_TAILQ_NEXT(lp, links, __db_lock))
- __lock_printlock(lt, lp, 1);
- }
+ for (lp =
+ SH_TAILQ_FIRST(&op->waiters, __db_lock);
+ lp != NULL;
+ lp = SH_TAILQ_NEXT(lp, links, __db_lock))
+ __lock_printlock(lt, lp, 1);
+
+ fprintf(fp, "\n");
}
-static const char *
-__lock_dump_status(status)
- db_status_t status;
+/*
+ * __lock_printheader --
+ */
+static void
+__lock_printheader()
{
- switch (status) {
+ printf("%-8s %-6s %-6s %-10s %s\n",
+ "Locker", "Mode",
+ "Count", "Status", "----------- Object ----------");
+}
+
+/*
+ * __lock_printlock --
+ *
+ * PUBLIC: void __lock_printlock __P((DB_LOCKTAB *, struct __db_lock *, int));
+ */
+void
+__lock_printlock(lt, lp, ispgno)
+ DB_LOCKTAB *lt;
+ struct __db_lock *lp;
+ int ispgno;
+{
+ DB_LOCKOBJ *lockobj;
+ db_pgno_t pgno;
+ u_int32_t *fidp, type;
+ u_int8_t *ptr;
+ char *namep;
+ const char *mode, *status;
+
+ switch (lp->mode) {
+ case DB_LOCK_DIRTY:
+ mode = "DIRTY_READ";
+ break;
+ case DB_LOCK_IREAD:
+ mode = "IREAD";
+ break;
+ case DB_LOCK_IWR:
+ mode = "IWR";
+ break;
+ case DB_LOCK_IWRITE:
+ mode = "IWRITE";
+ break;
+ case DB_LOCK_NG:
+ mode = "NG";
+ break;
+ case DB_LOCK_READ:
+ mode = "READ";
+ break;
+ case DB_LOCK_WRITE:
+ mode = "WRITE";
+ break;
+ case DB_LOCK_WWRITE:
+ mode = "WAS_WRITE";
+ break;
+ case DB_LOCK_WAIT:
+ mode = "WAIT";
+ break;
+ default:
+ mode = "UNKNOWN";
+ break;
+ }
+ switch (lp->status) {
case DB_LSTAT_ABORTED:
- return ("aborted");
+ status = "ABORT";
+ break;
case DB_LSTAT_ERR:
- return ("err");
+ status = "ERROR";
+ break;
case DB_LSTAT_FREE:
- return ("free");
+ status = "FREE";
+ break;
case DB_LSTAT_HELD:
- return ("held");
- case DB_LSTAT_NOGRANT:
- return ("nogrant");
- case DB_LSTAT_PENDING:
- return ("pending");
+ status = "HELD";
+ break;
case DB_LSTAT_WAITING:
- return ("waiting");
+ status = "WAIT";
+ break;
+ case DB_LSTAT_PENDING:
+ status = "PENDING";
+ break;
+ case DB_LSTAT_EXPIRED:
+ status = "EXPIRED";
+ break;
+ default:
+ status = "UNKNOWN";
+ break;
+ }
+ printf("%8lx %-6s %6lu %-10s ",
+ (u_long)lp->holder, mode, (u_long)lp->refcount, status);
+
+ lockobj = (DB_LOCKOBJ *)((u_int8_t *)lp + lp->obj);
+ ptr = SH_DBT_PTR(&lockobj->lockobj);
+ if (ispgno && lockobj->lockobj.size == sizeof(struct __db_ilock)) {
+ /* Assume this is a DBT lock. */
+ memcpy(&pgno, ptr, sizeof(db_pgno_t));
+ fidp = (u_int32_t *)(ptr + sizeof(db_pgno_t));
+ type = *(u_int32_t *)(ptr + sizeof(db_pgno_t) + DB_FILE_ID_LEN);
+ if (__dbreg_get_name(lt->dbenv, (u_int8_t *)fidp, &namep) != 0)
+ namep = NULL;
+ if (namep == NULL)
+ printf("(%lx %lx %lx %lx %lx)",
+ (u_long)fidp[0], (u_long)fidp[1], (u_long)fidp[2],
+ (u_long)fidp[3], (u_long)fidp[4]);
+ else
+ printf("%-20s", namep);
+ printf("%-7s %lu\n",
+ type == DB_PAGE_LOCK ? "page" :
+ type == DB_RECORD_LOCK ? "record" : "handle",
+ (u_long)pgno);
+ } else {
+ printf("0x%lx ", (u_long)R_OFFSET(&lt->reginfo, lockobj));
+ __db_pr(ptr, lockobj->lockobj.size, stdout);
+ printf("\n");
}
- return ("unknown status");
}