1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1996,2008 Oracle. All rights reserved. 5 * 6 * $Id: lock_stat.c,v 12.40 2008/04/11 16:13:53 ubell Exp $ 7 */ 8 9#include "db_config.h" 10 11#include "db_int.h" 12#include "dbinc/db_page.h" 13#include "dbinc/lock.h" 14#include "dbinc/log.h" 15#include "dbinc/db_am.h" 16 17#ifdef HAVE_STATISTICS 18static int __lock_dump_locker 19 __P((ENV *, DB_MSGBUF *, DB_LOCKTAB *, DB_LOCKER *)); 20static int __lock_dump_object __P((DB_LOCKTAB *, DB_MSGBUF *, DB_LOCKOBJ *)); 21static int __lock_print_all __P((ENV *, u_int32_t)); 22static int __lock_print_stats __P((ENV *, u_int32_t)); 23static void __lock_print_header __P((ENV *)); 24static int __lock_stat __P((ENV *, DB_LOCK_STAT **, u_int32_t)); 25 26/* 27 * __lock_stat_pp -- 28 * ENV->lock_stat pre/post processing. 29 * 30 * PUBLIC: int __lock_stat_pp __P((DB_ENV *, DB_LOCK_STAT **, u_int32_t)); 31 */ 32int 33__lock_stat_pp(dbenv, statp, flags) 34 DB_ENV *dbenv; 35 DB_LOCK_STAT **statp; 36 u_int32_t flags; 37{ 38 DB_THREAD_INFO *ip; 39 ENV *env; 40 int ret; 41 42 env = dbenv->env; 43 44 ENV_REQUIRES_CONFIG(env, 45 env->lk_handle, "DB_ENV->lock_stat", DB_INIT_LOCK); 46 47 if ((ret = __db_fchk(env, 48 "DB_ENV->lock_stat", flags, DB_STAT_CLEAR)) != 0) 49 return (ret); 50 51 ENV_ENTER(env, ip); 52 REPLICATION_WRAP(env, (__lock_stat(env, statp, flags)), 0, ret); 53 ENV_LEAVE(env, ip); 54 return (ret); 55} 56 57/* 58 * __lock_stat -- 59 * ENV->lock_stat. 60 */ 61static int 62__lock_stat(env, statp, flags) 63 ENV *env; 64 DB_LOCK_STAT **statp; 65 u_int32_t flags; 66{ 67 DB_LOCKREGION *region; 68 DB_LOCKTAB *lt; 69 DB_LOCK_STAT *stats, tmp; 70 DB_LOCK_HSTAT htmp; 71 DB_LOCK_PSTAT ptmp; 72 int ret; 73 u_int32_t i, tmp_wait, tmp_nowait; 74 75 *statp = NULL; 76 lt = env->lk_handle; 77 78 if ((ret = __os_umalloc(env, sizeof(*stats), &stats)) != 0) 79 return (ret); 80 81 /* Copy out the global statistics. */ 82 LOCK_REGION_LOCK(env); 83 84 region = lt->reginfo.primary; 85 memcpy(stats, ®ion->stat, sizeof(*stats)); 86 stats->st_locktimeout = region->lk_timeout; 87 stats->st_txntimeout = region->tx_timeout; 88 89 for (i = 0; i < region->object_t_size; i++) { 90 stats->st_nrequests += lt->obj_stat[i].st_nrequests; 91 stats->st_nreleases += lt->obj_stat[i].st_nreleases; 92 stats->st_nupgrade += lt->obj_stat[i].st_nupgrade; 93 stats->st_ndowngrade += lt->obj_stat[i].st_ndowngrade; 94 stats->st_lock_wait += lt->obj_stat[i].st_lock_wait; 95 stats->st_lock_nowait += lt->obj_stat[i].st_lock_nowait; 96 stats->st_nlocktimeouts += lt->obj_stat[i].st_nlocktimeouts; 97 stats->st_ntxntimeouts += lt->obj_stat[i].st_ntxntimeouts; 98 if (stats->st_maxhlocks < lt->obj_stat[i].st_maxnlocks) 99 stats->st_maxhlocks = lt->obj_stat[i].st_maxnlocks; 100 if (stats->st_maxhobjects < lt->obj_stat[i].st_maxnobjects) 101 stats->st_maxhobjects = lt->obj_stat[i].st_maxnobjects; 102 if (stats->st_hash_len < lt->obj_stat[i].st_hash_len) 103 stats->st_hash_len = lt->obj_stat[i].st_hash_len; 104 if (LF_ISSET(DB_STAT_CLEAR)) { 105 htmp = lt->obj_stat[i]; 106 memset(<->obj_stat[i], 0, sizeof(lt->obj_stat[i])); 107 lt->obj_stat[i].st_nlocks = htmp.st_nlocks; 108 lt->obj_stat[i].st_maxnlocks = htmp.st_nlocks; 109 lt->obj_stat[i].st_nobjects = htmp.st_nobjects; 110 lt->obj_stat[i].st_maxnobjects = htmp.st_nobjects; 111 112 } 113 } 114 115 for (i = 0; i < region->part_t_size; i++) { 116 stats->st_nlocks += lt->part_array[i].part_stat.st_nlocks; 117 stats->st_maxnlocks += 118 lt->part_array[i].part_stat.st_maxnlocks; 119 stats->st_nobjects += lt->part_array[i].part_stat.st_nobjects; 120 stats->st_maxnobjects += 121 lt->part_array[i].part_stat.st_maxnobjects; 122 stats->st_locksteals += 123 lt->part_array[i].part_stat.st_locksteals; 124 if (stats->st_maxlsteals < 125 lt->part_array[i].part_stat.st_locksteals) 126 stats->st_maxlsteals = 127 lt->part_array[i].part_stat.st_locksteals; 128 stats->st_objectsteals += 129 lt->part_array[i].part_stat.st_objectsteals; 130 if (stats->st_maxosteals < 131 lt->part_array[i].part_stat.st_objectsteals) 132 stats->st_maxosteals = 133 lt->part_array[i].part_stat.st_objectsteals; 134 __mutex_set_wait_info(env, 135 lt->part_array[i].mtx_part, &tmp_wait, &tmp_nowait); 136 stats->st_part_nowait += tmp_nowait; 137 stats->st_part_wait += tmp_wait; 138 if (tmp_wait > stats->st_part_max_wait) { 139 stats->st_part_max_nowait = tmp_nowait; 140 stats->st_part_max_wait = tmp_wait; 141 } 142 143 if (LF_ISSET(DB_STAT_CLEAR)) { 144 ptmp = lt->part_array[i].part_stat; 145 memset(<->part_array[i].part_stat, 146 0, sizeof(lt->part_array[i].part_stat)); 147 lt->part_array[i].part_stat.st_nlocks = 148 ptmp.st_nlocks; 149 lt->part_array[i].part_stat.st_maxnlocks = 150 ptmp.st_nlocks; 151 lt->part_array[i].part_stat.st_nobjects = 152 ptmp.st_nobjects; 153 lt->part_array[i].part_stat.st_maxnobjects = 154 ptmp.st_nobjects; 155 } 156 } 157 158 __mutex_set_wait_info(env, region->mtx_region, 159 &stats->st_region_wait, &stats->st_region_nowait); 160 __mutex_set_wait_info(env, region->mtx_dd, 161 &stats->st_objs_wait, &stats->st_objs_nowait); 162 __mutex_set_wait_info(env, region->mtx_lockers, 163 &stats->st_lockers_wait, &stats->st_lockers_nowait); 164 stats->st_regsize = lt->reginfo.rp->size; 165 if (LF_ISSET(DB_STAT_CLEAR)) { 166 tmp = region->stat; 167 memset(®ion->stat, 0, sizeof(region->stat)); 168 if (!LF_ISSET(DB_STAT_SUBSYSTEM)) { 169 __mutex_clear(env, region->mtx_region); 170 __mutex_clear(env, region->mtx_dd); 171 __mutex_clear(env, region->mtx_lockers); 172 for (i = 0; i < region->part_t_size; i++) 173 __mutex_clear(env, lt->part_array[i].mtx_part); 174 } 175 176 region->stat.st_id = tmp.st_id; 177 region->stat.st_cur_maxid = tmp.st_cur_maxid; 178 region->stat.st_maxlocks = tmp.st_maxlocks; 179 region->stat.st_maxlockers = tmp.st_maxlockers; 180 region->stat.st_maxobjects = tmp.st_maxobjects; 181 region->stat.st_nlocks = 182 region->stat.st_maxnlocks = tmp.st_nlocks; 183 region->stat.st_nlockers = 184 region->stat.st_maxnlockers = tmp.st_nlockers; 185 region->stat.st_nobjects = 186 region->stat.st_maxnobjects = tmp.st_nobjects; 187 region->stat.st_nmodes = tmp.st_nmodes; 188 } 189 190 LOCK_REGION_UNLOCK(env); 191 192 *statp = stats; 193 return (0); 194} 195 196/* 197 * __lock_stat_print_pp -- 198 * ENV->lock_stat_print pre/post processing. 199 * 200 * PUBLIC: int __lock_stat_print_pp __P((DB_ENV *, u_int32_t)); 201 */ 202int 203__lock_stat_print_pp(dbenv, flags) 204 DB_ENV *dbenv; 205 u_int32_t flags; 206{ 207 DB_THREAD_INFO *ip; 208 ENV *env; 209 int ret; 210 211 env = dbenv->env; 212 213 ENV_REQUIRES_CONFIG(env, 214 env->lk_handle, "DB_ENV->lock_stat_print", DB_INIT_LOCK); 215 216#define DB_STAT_LOCK_FLAGS \ 217 (DB_STAT_ALL | DB_STAT_CLEAR | DB_STAT_LOCK_CONF | \ 218 DB_STAT_LOCK_LOCKERS | DB_STAT_LOCK_OBJECTS | DB_STAT_LOCK_PARAMS) 219 if ((ret = __db_fchk(env, "DB_ENV->lock_stat_print", 220 flags, DB_STAT_CLEAR | DB_STAT_LOCK_FLAGS)) != 0) 221 return (ret); 222 223 ENV_ENTER(env, ip); 224 REPLICATION_WRAP(env, (__lock_stat_print(env, flags)), 0, ret); 225 ENV_LEAVE(env, ip); 226 return (ret); 227} 228 229/* 230 * __lock_stat_print -- 231 * ENV->lock_stat_print method. 232 * 233 * PUBLIC: int __lock_stat_print __P((ENV *, u_int32_t)); 234 */ 235int 236__lock_stat_print(env, flags) 237 ENV *env; 238 u_int32_t flags; 239{ 240 u_int32_t orig_flags; 241 int ret; 242 243 orig_flags = flags; 244 LF_CLR(DB_STAT_CLEAR | DB_STAT_SUBSYSTEM); 245 if (flags == 0 || LF_ISSET(DB_STAT_ALL)) { 246 ret = __lock_print_stats(env, orig_flags); 247 if (flags == 0 || ret != 0) 248 return (ret); 249 } 250 251 if (LF_ISSET(DB_STAT_ALL | DB_STAT_LOCK_CONF | DB_STAT_LOCK_LOCKERS | 252 DB_STAT_LOCK_OBJECTS | DB_STAT_LOCK_PARAMS) && 253 (ret = __lock_print_all(env, orig_flags)) != 0) 254 return (ret); 255 256 return (0); 257} 258 259/* 260 * __lock_print_stats -- 261 * Display default lock region statistics. 262 */ 263static int 264__lock_print_stats(env, flags) 265 ENV *env; 266 u_int32_t flags; 267{ 268 DB_LOCK_STAT *sp; 269 int ret; 270 271#ifdef LOCK_DIAGNOSTIC 272 DB_LOCKTAB *lt; 273 DB_LOCKREGION *region; 274 u_int32_t i; 275 u_int32_t wait, nowait; 276 277 lt = env->lk_handle; 278 region = lt->reginfo.primary; 279 280 for (i = 0; i < region->object_t_size; i++) { 281 if (lt->obj_stat[i].st_hash_len == 0) 282 continue; 283 __db_dl(env, 284 "Hash bucket", (u_long)i); 285 __db_dl(env, "Partition", (u_long)LOCK_PART(region, i)); 286 __mutex_set_wait_info(env, 287 lt->part_array[LOCK_PART(region, i)].mtx_part, 288 &wait, &nowait); 289 __db_dl_pct(env, 290 "The number of partition mutex requests that required waiting", 291 (u_long)wait, DB_PCT(wait, wait + nowait), NULL); 292 __db_dl(env, 293 "Maximum hash bucket length", 294 (u_long)lt->obj_stat[i].st_hash_len); 295 __db_dl(env, 296 "Total number of locks requested", 297 (u_long)lt->obj_stat[i].st_nrequests); 298 __db_dl(env, 299 "Total number of locks released", 300 (u_long)lt->obj_stat[i].st_nreleases); 301 __db_dl(env, 302 "Total number of locks upgraded", 303 (u_long)lt->obj_stat[i].st_nupgrade); 304 __db_dl(env, 305 "Total number of locks downgraded", 306 (u_long)lt->obj_stat[i].st_ndowngrade); 307 __db_dl(env, 308 "Lock requests not available due to conflicts, for which we waited", 309 (u_long)lt->obj_stat[i].st_lock_wait); 310 __db_dl(env, 311 "Lock requests not available due to conflicts, for which we did not wait", 312 (u_long)lt->obj_stat[i].st_lock_nowait); 313 __db_dl(env, "Number of locks that have timed out", 314 (u_long)lt->obj_stat[i].st_nlocktimeouts); 315 __db_dl(env, "Number of transactions that have timed out", 316 (u_long)lt->obj_stat[i].st_ntxntimeouts); 317 } 318#endif 319 if ((ret = __lock_stat(env, &sp, flags)) != 0) 320 return (ret); 321 322 if (LF_ISSET(DB_STAT_ALL)) 323 __db_msg(env, "Default locking region information:"); 324 __db_dl(env, "Last allocated locker ID", (u_long)sp->st_id); 325 __db_msg(env, "%#lx\tCurrent maximum unused locker ID", 326 (u_long)sp->st_cur_maxid); 327 __db_dl(env, "Number of lock modes", (u_long)sp->st_nmodes); 328 __db_dl(env, 329 "Maximum number of locks possible", (u_long)sp->st_maxlocks); 330 __db_dl(env, 331 "Maximum number of lockers possible", (u_long)sp->st_maxlockers); 332 __db_dl(env, "Maximum number of lock objects possible", 333 (u_long)sp->st_maxobjects); 334 __db_dl(env, "Number of lock object partitions", 335 (u_long)sp->st_partitions); 336 __db_dl(env, "Number of current locks", (u_long)sp->st_nlocks); 337 __db_dl(env, "Maximum number of locks at any one time", 338 (u_long)sp->st_maxnlocks); 339 __db_dl(env, "Maximum number of locks in any one bucket", 340 (u_long)sp->st_maxhlocks); 341 __db_dl(env, "Maximum number of locks stolen by for an empty partition", 342 (u_long)sp->st_locksteals); 343 __db_dl(env, "Maximum number of locks stolen for any one partition", 344 (u_long)sp->st_maxlsteals); 345 __db_dl(env, "Number of current lockers", (u_long)sp->st_nlockers); 346 __db_dl(env, "Maximum number of lockers at any one time", 347 (u_long)sp->st_maxnlockers); 348 __db_dl(env, 349 "Number of current lock objects", (u_long)sp->st_nobjects); 350 __db_dl(env, "Maximum number of lock objects at any one time", 351 (u_long)sp->st_maxnobjects); 352 __db_dl(env, "Maximum number of lock objects in any one bucket", 353 (u_long)sp->st_maxhobjects); 354 __db_dl(env, 355 "Maximum number of objects stolen by for an empty partition", 356 (u_long)sp->st_objectsteals); 357 __db_dl(env, "Maximum number of objects stolen for any one partition", 358 (u_long)sp->st_maxosteals); 359 __db_dl(env, 360 "Total number of locks requested", (u_long)sp->st_nrequests); 361 __db_dl(env, 362 "Total number of locks released", (u_long)sp->st_nreleases); 363 __db_dl(env, 364 "Total number of locks upgraded", (u_long)sp->st_nupgrade); 365 __db_dl(env, 366 "Total number of locks downgraded", (u_long)sp->st_ndowngrade); 367 __db_dl(env, 368 "Lock requests not available due to conflicts, for which we waited", 369 (u_long)sp->st_lock_wait); 370 __db_dl(env, 371 "Lock requests not available due to conflicts, for which we did not wait", 372 (u_long)sp->st_lock_nowait); 373 __db_dl(env, "Number of deadlocks", (u_long)sp->st_ndeadlocks); 374 __db_dl(env, "Lock timeout value", (u_long)sp->st_locktimeout); 375 __db_dl(env, "Number of locks that have timed out", 376 (u_long)sp->st_nlocktimeouts); 377 __db_dl(env, 378 "Transaction timeout value", (u_long)sp->st_txntimeout); 379 __db_dl(env, "Number of transactions that have timed out", 380 (u_long)sp->st_ntxntimeouts); 381 382 __db_dlbytes(env, "The size of the lock region", 383 (u_long)0, (u_long)0, (u_long)sp->st_regsize); 384 __db_dl_pct(env, 385 "The number of partition locks that required waiting", 386 (u_long)sp->st_part_wait, DB_PCT( 387 sp->st_part_wait, sp->st_part_wait + sp->st_part_nowait), NULL); 388 __db_dl_pct(env, 389 "The maximum number of times any partition lock was waited for", 390 (u_long)sp->st_part_max_wait, DB_PCT(sp->st_part_max_wait, 391 sp->st_part_max_wait + sp->st_part_max_nowait), NULL); 392 __db_dl_pct(env, 393 "The number of object queue operations that required waiting", 394 (u_long)sp->st_objs_wait, DB_PCT(sp->st_objs_wait, 395 sp->st_objs_wait + sp->st_objs_nowait), NULL); 396 __db_dl_pct(env, 397 "The number of locker allocations that required waiting", 398 (u_long)sp->st_lockers_wait, DB_PCT(sp->st_lockers_wait, 399 sp->st_lockers_wait + sp->st_lockers_nowait), NULL); 400 __db_dl_pct(env, 401 "The number of region locks that required waiting", 402 (u_long)sp->st_region_wait, DB_PCT(sp->st_region_wait, 403 sp->st_region_wait + sp->st_region_nowait), NULL); 404 __db_dl(env, "Maximum hash bucket length", 405 (u_long)sp->st_hash_len); 406 407 __os_ufree(env, sp); 408 409 return (0); 410} 411 412/* 413 * __lock_print_all -- 414 * Display debugging lock region statistics. 415 */ 416static int 417__lock_print_all(env, flags) 418 ENV *env; 419 u_int32_t flags; 420{ 421 DB_LOCKER *lip; 422 DB_LOCKOBJ *op; 423 DB_LOCKREGION *lrp; 424 DB_LOCKTAB *lt; 425 DB_MSGBUF mb; 426 int i, j; 427 u_int32_t k; 428 429 lt = env->lk_handle; 430 lrp = lt->reginfo.primary; 431 DB_MSGBUF_INIT(&mb); 432 433 LOCK_REGION_LOCK(env); 434 __db_print_reginfo(env, <->reginfo, "Lock", flags); 435 436 if (LF_ISSET(DB_STAT_ALL | DB_STAT_LOCK_PARAMS)) { 437 __db_msg(env, "%s", DB_GLOBAL(db_line)); 438 __db_msg(env, "Lock region parameters:"); 439 __mutex_print_debug_single(env, 440 "Lock region region mutex", lrp->mtx_region, flags); 441 STAT_ULONG("locker table size", lrp->locker_t_size); 442 STAT_ULONG("object table size", lrp->object_t_size); 443 STAT_ULONG("obj_off", lrp->obj_off); 444 STAT_ULONG("locker_off", lrp->locker_off); 445 STAT_ULONG("need_dd", lrp->need_dd); 446 if (timespecisset(&lrp->next_timeout)) { 447#ifdef HAVE_STRFTIME 448 time_t t = (time_t)lrp->next_timeout.tv_sec; 449 char tbuf[64]; 450 if (strftime(tbuf, sizeof(tbuf), 451 "%m-%d-%H:%M:%S", localtime(&t)) != 0) 452 __db_msg(env, "next_timeout: %s.%09lu", 453 tbuf, (u_long)lrp->next_timeout.tv_nsec); 454 else 455#endif 456 __db_msg(env, "next_timeout: %lu.%09lu", 457 (u_long)lrp->next_timeout.tv_sec, 458 (u_long)lrp->next_timeout.tv_nsec); 459 } 460 } 461 462 if (LF_ISSET(DB_STAT_ALL | DB_STAT_LOCK_CONF)) { 463 __db_msg(env, "%s", DB_GLOBAL(db_line)); 464 __db_msg(env, "Lock conflict matrix:"); 465 for (i = 0; i < lrp->stat.st_nmodes; i++) { 466 for (j = 0; j < lrp->stat.st_nmodes; j++) 467 __db_msgadd(env, &mb, "%lu\t", (u_long) 468 lt->conflicts[i * lrp->stat.st_nmodes + j]); 469 DB_MSGBUF_FLUSH(env, &mb); 470 } 471 } 472 LOCK_REGION_UNLOCK(env); 473 474 if (LF_ISSET(DB_STAT_ALL | DB_STAT_LOCK_LOCKERS)) { 475 __db_msg(env, "%s", DB_GLOBAL(db_line)); 476 __db_msg(env, "Locks grouped by lockers:"); 477 __lock_print_header(env); 478 LOCK_LOCKERS(env, lrp); 479 for (k = 0; k < lrp->locker_t_size; k++) 480 SH_TAILQ_FOREACH( 481 lip, <->locker_tab[k], links, __db_locker) 482 (void)__lock_dump_locker(env, &mb, lt, lip); 483 UNLOCK_LOCKERS(env, lrp); 484 } 485 486 if (LF_ISSET(DB_STAT_ALL | DB_STAT_LOCK_OBJECTS)) { 487 __db_msg(env, "%s", DB_GLOBAL(db_line)); 488 __db_msg(env, "Locks grouped by object:"); 489 __lock_print_header(env); 490 for (k = 0; k < lrp->object_t_size; k++) { 491 OBJECT_LOCK_NDX(lt, lrp, k); 492 SH_TAILQ_FOREACH( 493 op, <->obj_tab[k], links, __db_lockobj) { 494 (void)__lock_dump_object(lt, &mb, op); 495 __db_msg(env, "%s", ""); 496 } 497 OBJECT_UNLOCK(lt, lrp, k); 498 } 499 } 500 501 return (0); 502} 503 504static int 505__lock_dump_locker(env, mbp, lt, lip) 506 ENV *env; 507 DB_MSGBUF *mbp; 508 DB_LOCKTAB *lt; 509 DB_LOCKER *lip; 510{ 511 DB_LOCKREGION *lrp; 512 struct __db_lock *lp; 513 char buf[DB_THREADID_STRLEN]; 514 u_int32_t ndx; 515 516 lrp = lt->reginfo.primary; 517 518 __db_msgadd(env, 519 mbp, "%8lx dd=%2ld locks held %-4d write locks %-4d pid/thread %s", 520 (u_long)lip->id, (long)lip->dd_id, lip->nlocks, lip->nwrites, 521 env->dbenv->thread_id_string(env->dbenv, lip->pid, lip->tid, buf)); 522 if (timespecisset(&lip->tx_expire)) { 523#ifdef HAVE_STRFTIME 524 time_t t = (time_t)lip->tx_expire.tv_sec; 525 char tbuf[64]; 526 if (strftime(tbuf, sizeof(tbuf), 527 "%m-%d-%H:%M:%S", localtime(&t)) != 0) 528 __db_msgadd(env, mbp, "expires %s.%09lu", 529 tbuf, (u_long)lip->tx_expire.tv_nsec); 530 else 531#endif 532 __db_msgadd(env, mbp, "expires %lu.%09lu", 533 (u_long)lip->tx_expire.tv_sec, 534 (u_long)lip->tx_expire.tv_nsec); 535 } 536 if (F_ISSET(lip, DB_LOCKER_TIMEOUT)) 537 __db_msgadd( 538 env, mbp, " lk timeout %lu", (u_long)lip->lk_timeout); 539 if (timespecisset(&lip->lk_expire)) { 540#ifdef HAVE_STRFTIME 541 time_t t = (time_t)lip->lk_expire.tv_sec; 542 char tbuf[64]; 543 if (strftime(tbuf, 544 sizeof(tbuf), "%m-%d-%H:%M:%S", localtime(&t)) != 0) 545 __db_msgadd(env, mbp, " lk expires %s.%09lu", 546 tbuf, (u_long)lip->lk_expire.tv_nsec); 547 else 548#endif 549 __db_msgadd(env, mbp, " lk expires %lu.%09lu", 550 (u_long)lip->lk_expire.tv_sec, 551 (u_long)lip->lk_expire.tv_nsec); 552 } 553 DB_MSGBUF_FLUSH(env, mbp); 554 555 /* 556 * We need some care here since the list may change while we 557 * look. 558 */ 559retry: SH_LIST_FOREACH(lp, &lip->heldby, locker_links, __db_lock) { 560 if (!SH_LIST_EMPTY(&lip->heldby) && lp != NULL) { 561 ndx = lp->indx; 562 OBJECT_LOCK_NDX(lt, lrp, ndx); 563 if (lp->indx == ndx) 564 __lock_printlock(lt, mbp, lp, 1); 565 else { 566 OBJECT_UNLOCK(lt, lrp, ndx); 567 goto retry; 568 } 569 OBJECT_UNLOCK(lt, lrp, ndx); 570 } 571 } 572 return (0); 573} 574 575static int 576__lock_dump_object(lt, mbp, op) 577 DB_LOCKTAB *lt; 578 DB_MSGBUF *mbp; 579 DB_LOCKOBJ *op; 580{ 581 struct __db_lock *lp; 582 583 SH_TAILQ_FOREACH(lp, &op->holders, links, __db_lock) 584 __lock_printlock(lt, mbp, lp, 1); 585 SH_TAILQ_FOREACH(lp, &op->waiters, links, __db_lock) 586 __lock_printlock(lt, mbp, lp, 1); 587 return (0); 588} 589 590/* 591 * __lock_print_header -- 592 */ 593static void 594__lock_print_header(env) 595 ENV *env; 596{ 597 __db_msg(env, "%-8s %-10s%-4s %-7s %s", 598 "Locker", "Mode", 599 "Count", "Status", "----------------- Object ---------------"); 600} 601 602/* 603 * __lock_printlock -- 604 * 605 * PUBLIC: void __lock_printlock 606 * PUBLIC: __P((DB_LOCKTAB *, DB_MSGBUF *mbp, struct __db_lock *, int)); 607 */ 608void 609__lock_printlock(lt, mbp, lp, ispgno) 610 DB_LOCKTAB *lt; 611 DB_MSGBUF *mbp; 612 struct __db_lock *lp; 613 int ispgno; 614{ 615 DB_LOCKOBJ *lockobj; 616 DB_MSGBUF mb; 617 ENV *env; 618 db_pgno_t pgno; 619 u_int32_t *fidp, type; 620 u_int8_t *ptr; 621 char *fname, *dname, *p, namebuf[26]; 622 const char *mode, *status; 623 624 env = lt->env; 625 626 if (mbp == NULL) { 627 DB_MSGBUF_INIT(&mb); 628 mbp = &mb; 629 } 630 631 switch (lp->mode) { 632 case DB_LOCK_IREAD: 633 mode = "IREAD"; 634 break; 635 case DB_LOCK_IWR: 636 mode = "IWR"; 637 break; 638 case DB_LOCK_IWRITE: 639 mode = "IWRITE"; 640 break; 641 case DB_LOCK_NG: 642 mode = "NG"; 643 break; 644 case DB_LOCK_READ: 645 mode = "READ"; 646 break; 647 case DB_LOCK_READ_UNCOMMITTED: 648 mode = "READ_UNCOMMITTED"; 649 break; 650 case DB_LOCK_WRITE: 651 mode = "WRITE"; 652 break; 653 case DB_LOCK_WWRITE: 654 mode = "WAS_WRITE"; 655 break; 656 case DB_LOCK_WAIT: 657 mode = "WAIT"; 658 break; 659 default: 660 mode = "UNKNOWN"; 661 break; 662 } 663 switch (lp->status) { 664 case DB_LSTAT_ABORTED: 665 status = "ABORT"; 666 break; 667 case DB_LSTAT_EXPIRED: 668 status = "EXPIRED"; 669 break; 670 case DB_LSTAT_FREE: 671 status = "FREE"; 672 break; 673 case DB_LSTAT_HELD: 674 status = "HELD"; 675 break; 676 case DB_LSTAT_PENDING: 677 status = "PENDING"; 678 break; 679 case DB_LSTAT_WAITING: 680 status = "WAIT"; 681 break; 682 default: 683 status = "UNKNOWN"; 684 break; 685 } 686 __db_msgadd(env, mbp, "%8lx %-10s %4lu %-7s ", 687 (u_long)((DB_LOCKER *)R_ADDR(<->reginfo, lp->holder))->id, 688 mode, (u_long)lp->refcount, status); 689 690 lockobj = (DB_LOCKOBJ *)((u_int8_t *)lp + lp->obj); 691 ptr = SH_DBT_PTR(&lockobj->lockobj); 692 if (ispgno && lockobj->lockobj.size == sizeof(struct __db_ilock)) { 693 /* Assume this is a DBT lock. */ 694 memcpy(&pgno, ptr, sizeof(db_pgno_t)); 695 fidp = (u_int32_t *)(ptr + sizeof(db_pgno_t)); 696 type = *(u_int32_t *)(ptr + sizeof(db_pgno_t) + DB_FILE_ID_LEN); 697 (void)__dbreg_get_name( 698 lt->env, (u_int8_t *)fidp, &fname, &dname); 699 if (fname == NULL && dname == NULL) 700 __db_msgadd(env, mbp, "(%lx %lx %lx %lx %lx) ", 701 (u_long)fidp[0], (u_long)fidp[1], (u_long)fidp[2], 702 (u_long)fidp[3], (u_long)fidp[4]); 703 else { 704 if (fname != NULL && dname != NULL) { 705 (void)snprintf(namebuf, sizeof(namebuf), 706 "%14s:%-10s", fname, dname); 707 p = namebuf; 708 } else if (fname != NULL) 709 p = fname; 710 else 711 p = dname; 712 __db_msgadd(env, mbp, "%-25s ", p); 713 } 714 __db_msgadd(env, mbp, "%-7s %7lu", 715 type == DB_PAGE_LOCK ? "page" : 716 type == DB_RECORD_LOCK ? "record" : "handle", 717 (u_long)pgno); 718 } else { 719 __db_msgadd(env, mbp, "0x%lx ", 720 (u_long)R_OFFSET(<->reginfo, lockobj)); 721 __db_prbytes(env, mbp, ptr, lockobj->lockobj.size); 722 } 723 DB_MSGBUF_FLUSH(env, mbp); 724} 725 726#else /* !HAVE_STATISTICS */ 727 728int 729__lock_stat_pp(dbenv, statp, flags) 730 DB_ENV *dbenv; 731 DB_LOCK_STAT **statp; 732 u_int32_t flags; 733{ 734 COMPQUIET(statp, NULL); 735 COMPQUIET(flags, 0); 736 737 return (__db_stat_not_built(dbenv->env)); 738} 739 740int 741__lock_stat_print_pp(dbenv, flags) 742 DB_ENV *dbenv; 743 u_int32_t flags; 744{ 745 COMPQUIET(flags, 0); 746 747 return (__db_stat_not_built(dbenv->env)); 748} 749#endif 750