lock_stat.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:9k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1996-2002
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: lock_stat.c,v 11.32 2002/08/14 20:08:51 bostic Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #include <string.h>
  14. #if TIME_WITH_SYS_TIME
  15. #include <sys/time.h>
  16. #include <time.h>
  17. #else
  18. #if HAVE_SYS_TIME_H
  19. #include <sys/time.h>
  20. #else
  21. #include <time.h>
  22. #endif
  23. #endif
  24. #include <ctype.h>
  25. #endif
  26. #include "db_int.h"
  27. #include "dbinc/db_shash.h"
  28. #include "dbinc/db_page.h"
  29. #include "dbinc/lock.h"
  30. #include "dbinc/log.h"
  31. #include "dbinc/db_am.h"
  32. static void __lock_dump_locker __P((DB_LOCKTAB *, DB_LOCKER *, FILE *));
  33. static void __lock_dump_object __P((DB_LOCKTAB *, DB_LOCKOBJ *, FILE *));
  34. static void __lock_printheader __P((void));
  35. /*
  36.  * __lock_stat --
  37.  * Return LOCK statistics.
  38.  *
  39.  * PUBLIC: int __lock_stat __P((DB_ENV *, DB_LOCK_STAT **, u_int32_t));
  40.  */
  41. int
  42. __lock_stat(dbenv, statp, flags)
  43. DB_ENV *dbenv;
  44. DB_LOCK_STAT **statp;
  45. u_int32_t flags;
  46. {
  47. DB_LOCKREGION *region;
  48. DB_LOCKTAB *lt;
  49. DB_LOCK_STAT *stats, tmp;
  50. int ret;
  51. PANIC_CHECK(dbenv);
  52. ENV_REQUIRES_CONFIG(dbenv,
  53.     dbenv->lk_handle, "DB_ENV->lock_stat", DB_INIT_LOCK);
  54. *statp = NULL;
  55. if ((ret = __db_fchk(dbenv,
  56.     "DB_ENV->lock_stat", flags, DB_STAT_CLEAR)) != 0)
  57. return (ret);
  58. lt = dbenv->lk_handle;
  59. if ((ret = __os_umalloc(dbenv, sizeof(*stats), &stats)) != 0)
  60. return (ret);
  61. /* Copy out the global statistics. */
  62. R_LOCK(dbenv, &lt->reginfo);
  63. region = lt->reginfo.primary;
  64. memcpy(stats, &region->stat, sizeof(*stats));
  65. stats->st_locktimeout = region->lk_timeout;
  66. stats->st_txntimeout = region->tx_timeout;
  67. stats->st_region_wait = lt->reginfo.rp->mutex.mutex_set_wait;
  68. stats->st_region_nowait = lt->reginfo.rp->mutex.mutex_set_nowait;
  69. stats->st_regsize = lt->reginfo.rp->size;
  70. if (LF_ISSET(DB_STAT_CLEAR)) {
  71. tmp = region->stat;
  72. memset(&region->stat, 0, sizeof(region->stat));
  73. lt->reginfo.rp->mutex.mutex_set_wait = 0;
  74. lt->reginfo.rp->mutex.mutex_set_nowait = 0;
  75. region->stat.st_id = tmp.st_id;
  76. region->stat.st_cur_maxid = tmp.st_cur_maxid;
  77. region->stat.st_maxlocks = tmp.st_maxlocks;
  78. region->stat.st_maxlockers = tmp.st_maxlockers;
  79. region->stat.st_maxobjects = tmp.st_maxobjects;
  80. region->stat.st_nlocks =
  81.     region->stat.st_maxnlocks = tmp.st_nlocks;
  82. region->stat.st_nlockers =
  83.     region->stat.st_maxnlockers = tmp.st_nlockers;
  84. region->stat.st_nobjects =
  85.     region->stat.st_maxnobjects = tmp.st_nobjects;
  86. region->stat.st_nmodes = tmp.st_nmodes;
  87. }
  88. R_UNLOCK(dbenv, &lt->reginfo);
  89. *statp = stats;
  90. return (0);
  91. }
  92. #define LOCK_DUMP_CONF 0x001 /* Conflict matrix. */
  93. #define LOCK_DUMP_LOCKERS 0x002 /* Display lockers. */
  94. #define LOCK_DUMP_MEM 0x004 /* Display region memory. */
  95. #define LOCK_DUMP_OBJECTS 0x008 /* Display objects. */
  96. #define LOCK_DUMP_PARAMS 0x010 /* Display params. */
  97. #define LOCK_DUMP_ALL /* All */
  98. (LOCK_DUMP_CONF | LOCK_DUMP_LOCKERS | LOCK_DUMP_MEM |
  99. LOCK_DUMP_OBJECTS | LOCK_DUMP_PARAMS)
  100. /*
  101.  * __lock_dump_region --
  102.  *
  103.  * PUBLIC: int __lock_dump_region __P((DB_ENV *, char *, FILE *));
  104.  */
  105. int
  106. __lock_dump_region(dbenv, area, fp)
  107. DB_ENV *dbenv;
  108. char *area;
  109. FILE *fp;
  110. {
  111. DB_LOCKER *lip;
  112. DB_LOCKOBJ *op;
  113. DB_LOCKREGION *lrp;
  114. DB_LOCKTAB *lt;
  115. u_int32_t flags, i, j;
  116. PANIC_CHECK(dbenv);
  117. ENV_REQUIRES_CONFIG(dbenv,
  118.     dbenv->lk_handle, "lock_dump_region", DB_INIT_LOCK);
  119. /* Make it easy to call from the debugger. */
  120. if (fp == NULL)
  121. fp = stderr;
  122. for (flags = 0; *area != ''; ++area)
  123. switch (*area) {
  124. case 'A':
  125. LF_SET(LOCK_DUMP_ALL);
  126. break;
  127. case 'c':
  128. LF_SET(LOCK_DUMP_CONF);
  129. break;
  130. case 'l':
  131. LF_SET(LOCK_DUMP_LOCKERS);
  132. break;
  133. case 'm':
  134. LF_SET(LOCK_DUMP_MEM);
  135. break;
  136. case 'o':
  137. LF_SET(LOCK_DUMP_OBJECTS);
  138. break;
  139. case 'p':
  140. LF_SET(LOCK_DUMP_PARAMS);
  141. break;
  142. }
  143. lt = dbenv->lk_handle;
  144. lrp = lt->reginfo.primary;
  145. LOCKREGION(dbenv, lt);
  146. if (LF_ISSET(LOCK_DUMP_PARAMS)) {
  147. fprintf(fp, "%snLock region parametersn", DB_LINE);
  148. fprintf(fp,
  149.     "%s: %lu, %s: %lu, %s: %lu,n%s: %lu, %s: %lu, %s: %lu, %s: %lun",
  150.     "locker table size", (u_long)lrp->locker_t_size,
  151.     "object table size", (u_long)lrp->object_t_size,
  152.     "obj_off", (u_long)lrp->obj_off,
  153.     "osynch_off", (u_long)lrp->osynch_off,
  154.     "locker_off", (u_long)lrp->locker_off,
  155.     "lsynch_off", (u_long)lrp->lsynch_off,
  156.     "need_dd", (u_long)lrp->need_dd);
  157. }
  158. if (LF_ISSET(LOCK_DUMP_CONF)) {
  159. fprintf(fp, "n%snConflict matrixn", DB_LINE);
  160. for (i = 0; i < lrp->stat.st_nmodes; i++) {
  161. for (j = 0; j < lrp->stat.st_nmodes; j++)
  162. fprintf(fp, "%lut", (u_long)
  163.     lt->conflicts[i * lrp->stat.st_nmodes + j]);
  164. fprintf(fp, "n");
  165. }
  166. }
  167. if (LF_ISSET(LOCK_DUMP_LOCKERS)) {
  168. fprintf(fp, "%snLocks grouped by lockersn", DB_LINE);
  169. __lock_printheader();
  170. for (i = 0; i < lrp->locker_t_size; i++)
  171. for (lip =
  172.     SH_TAILQ_FIRST(&lt->locker_tab[i], __db_locker);
  173.     lip != NULL;
  174.     lip = SH_TAILQ_NEXT(lip, links, __db_locker)) {
  175. __lock_dump_locker(lt, lip, fp);
  176. }
  177. }
  178. if (LF_ISSET(LOCK_DUMP_OBJECTS)) {
  179. fprintf(fp, "%snLocks grouped by objectn", DB_LINE);
  180. __lock_printheader();
  181. for (i = 0; i < lrp->object_t_size; i++) {
  182. for (op = SH_TAILQ_FIRST(&lt->obj_tab[i], __db_lockobj);
  183.     op != NULL;
  184.     op = SH_TAILQ_NEXT(op, links, __db_lockobj))
  185. __lock_dump_object(lt, op, fp);
  186. }
  187. }
  188. if (LF_ISSET(LOCK_DUMP_MEM))
  189. __db_shalloc_dump(lt->reginfo.addr, fp);
  190. UNLOCKREGION(dbenv, lt);
  191. return (0);
  192. }
  193. static void
  194. __lock_dump_locker(lt, lip, fp)
  195. DB_LOCKTAB *lt;
  196. DB_LOCKER *lip;
  197. FILE *fp;
  198. {
  199. struct __db_lock *lp;
  200. time_t s;
  201. char buf[64];
  202. fprintf(fp, "%8lx dd=%2ld locks held %-4d write locks %-4d",
  203.     (u_long)lip->id, (long)lip->dd_id, lip->nlocks, lip->nwrites);
  204. fprintf(fp, " %s ", F_ISSET(lip, DB_LOCKER_DELETED) ? "(D)" : "   ");
  205. if (LOCK_TIME_ISVALID(&lip->tx_expire)) {
  206. s = lip->tx_expire.tv_sec;
  207. strftime(buf, sizeof(buf), "%m-%d-%H:%M:%S", localtime(&s));
  208. fprintf(fp,
  209.     " expires %s.%lu", buf, (u_long)lip->tx_expire.tv_usec);
  210. }
  211. if (F_ISSET(lip, DB_LOCKER_TIMEOUT))
  212. fprintf(fp, " lk timeout %u", lip->lk_timeout);
  213. if (LOCK_TIME_ISVALID(&lip->lk_expire)) {
  214. s = lip->lk_expire.tv_sec;
  215. strftime(buf, sizeof(buf), "%m-%d-%H:%M:%S", localtime(&s));
  216. fprintf(fp,
  217.     " lk expires %s.%lu", buf, (u_long)lip->lk_expire.tv_usec);
  218. }
  219. fprintf(fp, "n");
  220. lp = SH_LIST_FIRST(&lip->heldby, __db_lock);
  221. if (lp != NULL) {
  222. for (; lp != NULL;
  223.     lp = SH_LIST_NEXT(lp, locker_links, __db_lock))
  224. __lock_printlock(lt, lp, 1);
  225. fprintf(fp, "n");
  226. }
  227. }
  228. static void
  229. __lock_dump_object(lt, op, fp)
  230. DB_LOCKTAB *lt;
  231. DB_LOCKOBJ *op;
  232. FILE *fp;
  233. {
  234. struct __db_lock *lp;
  235. for (lp =
  236.     SH_TAILQ_FIRST(&op->holders, __db_lock);
  237.     lp != NULL;
  238.     lp = SH_TAILQ_NEXT(lp, links, __db_lock))
  239. __lock_printlock(lt, lp, 1);
  240. for (lp =
  241.     SH_TAILQ_FIRST(&op->waiters, __db_lock);
  242.     lp != NULL;
  243.     lp = SH_TAILQ_NEXT(lp, links, __db_lock))
  244. __lock_printlock(lt, lp, 1);
  245. fprintf(fp, "n");
  246. }
  247. /*
  248.  * __lock_printheader --
  249.  */
  250. static void
  251. __lock_printheader()
  252. {
  253. printf("%-8s  %-6s  %-6s  %-10s  %sn",
  254.     "Locker", "Mode",
  255.     "Count", "Status", "----------- Object ----------");
  256. }
  257. /*
  258.  * __lock_printlock --
  259.  *
  260.  * PUBLIC: void __lock_printlock __P((DB_LOCKTAB *, struct __db_lock *, int));
  261.  */
  262. void
  263. __lock_printlock(lt, lp, ispgno)
  264. DB_LOCKTAB *lt;
  265. struct __db_lock *lp;
  266. int ispgno;
  267. {
  268. DB_LOCKOBJ *lockobj;
  269. db_pgno_t pgno;
  270. u_int32_t *fidp, type;
  271. u_int8_t *ptr;
  272. char *namep;
  273. const char *mode, *status;
  274. switch (lp->mode) {
  275. case DB_LOCK_DIRTY:
  276. mode = "DIRTY_READ";
  277. break;
  278. case DB_LOCK_IREAD:
  279. mode = "IREAD";
  280. break;
  281. case DB_LOCK_IWR:
  282. mode = "IWR";
  283. break;
  284. case DB_LOCK_IWRITE:
  285. mode = "IWRITE";
  286. break;
  287. case DB_LOCK_NG:
  288. mode = "NG";
  289. break;
  290. case DB_LOCK_READ:
  291. mode = "READ";
  292. break;
  293. case DB_LOCK_WRITE:
  294. mode = "WRITE";
  295. break;
  296. case DB_LOCK_WWRITE:
  297. mode = "WAS_WRITE";
  298. break;
  299. case DB_LOCK_WAIT:
  300. mode = "WAIT";
  301. break;
  302. default:
  303. mode = "UNKNOWN";
  304. break;
  305. }
  306. switch (lp->status) {
  307. case DB_LSTAT_ABORTED:
  308. status = "ABORT";
  309. break;
  310. case DB_LSTAT_ERR:
  311. status = "ERROR";
  312. break;
  313. case DB_LSTAT_FREE:
  314. status = "FREE";
  315. break;
  316. case DB_LSTAT_HELD:
  317. status = "HELD";
  318. break;
  319. case DB_LSTAT_WAITING:
  320. status = "WAIT";
  321. break;
  322. case DB_LSTAT_PENDING:
  323. status = "PENDING";
  324. break;
  325. case DB_LSTAT_EXPIRED:
  326. status = "EXPIRED";
  327. break;
  328. default:
  329. status = "UNKNOWN";
  330. break;
  331. }
  332. printf("%8lx  %-6s  %6lu  %-10s  ",
  333.     (u_long)lp->holder, mode, (u_long)lp->refcount, status);
  334. lockobj = (DB_LOCKOBJ *)((u_int8_t *)lp + lp->obj);
  335. ptr = SH_DBT_PTR(&lockobj->lockobj);
  336. if (ispgno && lockobj->lockobj.size == sizeof(struct __db_ilock)) {
  337. /* Assume this is a DBT lock. */
  338. memcpy(&pgno, ptr, sizeof(db_pgno_t));
  339. fidp = (u_int32_t *)(ptr + sizeof(db_pgno_t));
  340. type = *(u_int32_t *)(ptr + sizeof(db_pgno_t) + DB_FILE_ID_LEN);
  341. if (__dbreg_get_name(lt->dbenv, (u_int8_t *)fidp, &namep) != 0)
  342. namep = NULL;
  343. if (namep == NULL)
  344. printf("(%lx %lx %lx %lx %lx)",
  345. (u_long)fidp[0], (u_long)fidp[1], (u_long)fidp[2],
  346. (u_long)fidp[3], (u_long)fidp[4]);
  347. else
  348. printf("%-20s", namep);
  349. printf("%-7s  %lun",
  350. type == DB_PAGE_LOCK ? "page" :
  351. type == DB_RECORD_LOCK ? "record" : "handle",
  352. (u_long)pgno);
  353. } else {
  354. printf("0x%lx ", (u_long)R_OFFSET(&lt->reginfo, lockobj));
  355. __db_pr(ptr, lockobj->lockobj.size, stdout);
  356. printf("n");
  357. }
  358. }