db

lock_region.c

Go to the documentation of this file.
00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996, 1997, 1998, 1999, 2000
00005  * Sleepycat Software. All rights reserved.
00006  */
00007 
00008 #include "config.h"
00009 
00010 #ifndef lint
00011 static const char revid[] = "$Id: lock__region_8c-source.html,v 1.1 2008年06月08日 10:20:00 sebdiaz Exp $";
00012 #endif /* not lint */
00013 
00014 #ifndef NO_SYSTEM_INCLUDES
00015 #include <sys/types.h>
00016 
00017 #include <ctype.h>
00018 #include <errno.h>
00019 #include <string.h>
00020 #endif
00021 
00022 #ifdef HAVE_RPC
00023 #include "db_server.h"
00024 #endif
00025 
00026 #include "db_int.h"
00027 #include "db_shash.h"
00028 #include "lock.h"
00029 
00030 #ifdef HAVE_RPC
00031 #include "gen_client_ext.h"
00032 #include "rpc_client_ext.h"
00033 #endif
00034 #undef __lock_init
00035 
00036 static void __lock_dump_locker (DB_LOCKTAB *, DB_LOCKER *, FILE *);
00037 static void __lock_dump_object (DB_LOCKTAB *, DB_LOCKOBJ *, FILE *);
00038 static const char *
00039 __lock_dump_status __P((db_status_t));
00040 
00041 static int __lock_init __P((DB_ENV *, DB_LOCKTAB *));
00042 static size_t
00043 __lock_region_size __P((DB_ENV *));
00044 static int __lock_set_lk_conflicts __P((DB_ENV *, u_int8_t *, int));
00045 static int __lock_set_lk_detect __P((DB_ENV *, u_int32_t));
00046 static int __lock_set_lk_max __P((DB_ENV *, u_int32_t));
00047 
00048 /*
00049  * This conflict array is used for concurrent db access (CDB). It
00050  * uses the same locks as the db_rw_conflict array, but adds an IW
00051  * mode to be used for write cursors.
00052  */
00053 static u_int8_t const db_cdb_conflicts[] = {
00054 /* N R W IW */
00055 /* N */ 0, 0, 0, 0,
00056 /* R */ 0, 0, 1, 0,
00057 /* W */ 0, 1, 1, 1,
00058 /* IW */ 0, 0, 1, 1
00059 };
00060 
00061 /*
00062  * CDB___lock_dbenv_create --
00063  * Lock specific creation of the DB_ENV structure.
00064  *
00065  * PUBLIC: void CDB___lock_dbenv_create __P((DB_ENV *));
00066  */
00067 void
00068 CDB___lock_dbenv_create(dbenv)
00069 DB_ENV *dbenv;
00070 {
00071 dbenv->lk_max = DB_LOCK_DEFAULT_N;
00072 
00073 dbenv->set_lk_conflicts = __lock_set_lk_conflicts;
00074 dbenv->set_lk_detect = __lock_set_lk_detect;
00075 dbenv->set_lk_max = __lock_set_lk_max;
00076 
00077 #ifdef HAVE_RPC
00078 /*
00079  * If we have a client, overwrite what we just set up to point
00080  * to the client functions.
00081  */
00082 if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) {
00083 dbenv->set_lk_conflicts = __dbcl_set_lk_conflict;
00084 dbenv->set_lk_detect = __dbcl_set_lk_detect;
00085 dbenv->set_lk_max = __dbcl_set_lk_max;
00086 }
00087 #endif
00088 }
00089 
00090 /*
00091  * CDB___lock_dbenv_close --
00092  * Lock specific destruction of the DB_ENV structure.
00093  *
00094  * PUBLIC: void CDB___lock_dbenv_close __P((DB_ENV *));
00095  */
00096 void
00097 CDB___lock_dbenv_close(dbenv)
00098 DB_ENV *dbenv;
00099 {
00100 if (!F_ISSET(dbenv, DB_ENV_USER_ALLOC) && dbenv->lk_conflicts != NULL) {
00101 CDB___os_free(dbenv->lk_conflicts,
00102 dbenv->lk_modes * dbenv->lk_modes);
00103 dbenv->lk_conflicts = NULL;
00104 }
00105 }
00106 
00107 /*
00108  * __lock_set_lk_conflicts
00109  * Set the conflicts matrix.
00110  */
00111 static int
00112 __lock_set_lk_conflicts(dbenv, lk_conflicts, lk_modes)
00113 DB_ENV *dbenv;
00114 u_int8_t *lk_conflicts;
00115 int lk_modes;
00116 {
00117 int ret;
00118 
00119 ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_lk_conflicts");
00120 
00121 if (dbenv->lk_conflicts != NULL) {
00122 CDB___os_free(dbenv->lk_conflicts,
00123 dbenv->lk_modes * dbenv->lk_modes);
00124 dbenv->lk_conflicts = NULL;
00125 }
00126 if ((ret = CDB___os_malloc(dbenv,
00127 lk_modes * lk_modes, NULL, &dbenv->lk_conflicts)) != 0)
00128 return (ret);
00129 memcpy(dbenv->lk_conflicts, lk_conflicts, lk_modes * lk_modes);
00130 dbenv->lk_modes = lk_modes;
00131 
00132 return (0);
00133 }
00134 
00135 /*
00136  * __lock_set_lk_detect
00137  * Set the automatic deadlock detection.
00138  */
00139 static int
00140 __lock_set_lk_detect(dbenv, lk_detect)
00141 DB_ENV *dbenv;
00142 u_int32_t lk_detect;
00143 {
00144 ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_lk_detect");
00145 
00146 switch (lk_detect) {
00147 case DB_LOCK_DEFAULT:
00148 case DB_LOCK_OLDEST:
00149 case DB_LOCK_RANDOM:
00150 case DB_LOCK_YOUNGEST:
00151 break;
00152 default:
00153 return (EINVAL);
00154 }
00155 dbenv->lk_detect = lk_detect;
00156 return (0);
00157 }
00158 
00159 /*
00160  * __lock_set_lk_max
00161  * Set the lock table size.
00162  */
00163 static int
00164 __lock_set_lk_max(dbenv, lk_max)
00165 DB_ENV *dbenv;
00166 u_int32_t lk_max;
00167 {
00168 ENV_ILLEGAL_AFTER_OPEN(dbenv, "set_lk_max");
00169 
00170 dbenv->lk_max = lk_max;
00171 return (0);
00172 }
00173 
00174 /*
00175  * CDB___lock_open --
00176  * Internal version of lock_open: only called from DB_ENV->open.
00177  *
00178  * PUBLIC: int CDB___lock_open __P((DB_ENV *));
00179  */
00180 int
00181 CDB___lock_open(dbenv)
00182 DB_ENV *dbenv;
00183 {
00184 DB_LOCKREGION *region;
00185 DB_LOCKTAB *lt;
00186 size_t size;
00187 int ret;
00188 
00189 /* Create the lock table structure. */
00190 if ((ret = CDB___os_calloc(dbenv, 1, sizeof(DB_LOCKTAB), &lt)) != 0)
00191 return (ret);
00192 lt->dbenv = dbenv;
00193 
00194 /* Join/create the lock region. */
00195 lt->reginfo.id = REG_ID_LOCK;
00196 lt->reginfo.mode = dbenv->db_mode;
00197 if (F_ISSET(dbenv, DB_ENV_CREATE))
00198 F_SET(&lt->reginfo, REGION_CREATE_OK);
00199 size = __lock_region_size(dbenv);
00200 if ((ret = CDB___db_r_attach(dbenv, &lt->reginfo, size)) != 0)
00201 goto err;
00202 
00203 /* If we created the region, initialize it. */
00204 if (F_ISSET(&lt->reginfo, REGION_CREATE))
00205 if ((ret = __lock_init(dbenv, lt)) != 0)
00206 goto err;
00207 
00208 /* Set the local addresses. */
00209 region = lt->reginfo.primary =
00210 R_ADDR(&lt->reginfo, lt->reginfo.rp->primary);
00211 
00212 /* Check for incompatible automatic deadlock detection requests. */
00213 if (dbenv->lk_detect != DB_LOCK_NORUN) {
00214 if (region->detect != DB_LOCK_NORUN &&
00215 dbenv->lk_detect != DB_LOCK_DEFAULT &&
00216 region->detect != dbenv->lk_detect) {
00217 CDB___db_err(dbenv,
00218 "lock_open: incompatible deadlock detector mode");
00219 ret = EINVAL;
00220 goto err;
00221 }
00222 
00223 /*
00224  * Upgrade if our caller wants automatic detection, and it
00225  * was not currently being done, whether or not we created
00226  * the region.
00227  */
00228 if (region->detect == DB_LOCK_NORUN)
00229 region->detect = dbenv->lk_detect;
00230 }
00231 
00232 /* Set remaining pointers into region. */
00233 lt->conflicts = (u_int8_t *)R_ADDR(&lt->reginfo, region->conf_off);
00234 lt->obj_tab = (DB_HASHTAB *)R_ADDR(&lt->reginfo, region->obj_off);
00235 lt->locker_tab = (DB_HASHTAB *)R_ADDR(&lt->reginfo, region->locker_off);
00236 
00237 R_UNLOCK(dbenv, &lt->reginfo);
00238 
00239 dbenv->lk_handle = lt;
00240 return (0);
00241 
00242 err: if (lt->reginfo.addr != NULL) {
00243 if (F_ISSET(&lt->reginfo, REGION_CREATE))
00244 F_SET(lt->reginfo.rp, REG_DEAD);
00245 R_UNLOCK(dbenv, &lt->reginfo);
00246 (void)CDB___db_r_detach(dbenv, &lt->reginfo, 0);
00247 }
00248 CDB___os_free(lt, sizeof(*lt));
00249 return (ret);
00250 };
00251 
00252 /*
00253  * __lock_init --
00254  * Initialize the lock region.
00255  */
00256 static int
00257 __lock_init(dbenv, lt)
00258 DB_ENV *dbenv;
00259 DB_LOCKTAB *lt;
00260 {
00261 const u_int8_t *lk_conflicts;
00262 struct __db_lock *lp;
00263 DB_LOCKER *lidp;
00264 DB_LOCKOBJ *op;
00265 DB_LOCKREGION *region;
00266 u_int32_t i, lk_modes, nelements;
00267 u_int8_t *addr;
00268 int ret;
00269 
00270 if ((ret = CDB___db_shalloc(lt->reginfo.addr,
00271 sizeof(DB_LOCKREGION), 0, &lt->reginfo.primary)) != 0)
00272 goto mem_err;
00273 lt->reginfo.rp->primary = R_OFFSET(&lt->reginfo, lt->reginfo.primary);
00274 region = lt->reginfo.primary;
00275 memset(region, 0, sizeof(*region));
00276 
00277 /* Select a conflict matrix if none specified. */
00278 if (dbenv->lk_modes == 0)
00279 if (LOCKING(dbenv)) {
00280 lk_modes = DB_LOCK_RW_N + 1;
00281 lk_conflicts = db_cdb_conflicts;
00282 } else {
00283 lk_modes = DB_LOCK_RW_N;
00284 lk_conflicts = CDB_db_rw_conflicts;
00285 }
00286 else {
00287 lk_modes = dbenv->lk_modes;
00288 lk_conflicts = dbenv->lk_conflicts;
00289 }
00290 
00291 region->id = 0;
00292 region->need_dd = 0;
00293 region->detect = DB_LOCK_NORUN;
00294 region->maxlocks = dbenv->lk_max;
00295 region->table_size = CDB___db_tablesize(dbenv->lk_max);
00296 region->nmodes = lk_modes;
00297 region->nlockers = 0;
00298 region->maxnlockers = 0;
00299 region->nconflicts = 0;
00300 region->nrequests = 0;
00301 region->nreleases = 0;
00302 region->ndeadlocks = 0;
00303 
00304 nelements = region->table_size;
00305 
00306 /* Allocate room for the conflict matrix and initialize it. */
00307 if ((ret =
00308 CDB___db_shalloc(lt->reginfo.addr, lk_modes * lk_modes, 0, &addr)) != 0)
00309 goto mem_err;
00310 memcpy(addr, lk_conflicts, lk_modes * lk_modes);
00311 region->conf_off = R_OFFSET(&lt->reginfo, addr);
00312 
00313 /* Allocate room for the object hash table and initialize it. */
00314 if ((ret = CDB___db_shalloc(lt->reginfo.addr,
00315 nelements * sizeof(DB_HASHTAB), 0, &addr)) != 0)
00316 goto mem_err;
00317 CDB___db_hashinit(addr, nelements);
00318 region->obj_off = R_OFFSET(&lt->reginfo, addr);
00319 
00320 /* Allocate room for the locker hash table and initialize it. */
00321 if ((ret = CDB___db_shalloc(lt->reginfo.addr,
00322 nelements * sizeof(DB_HASHTAB), 0, &addr)) != 0)
00323 goto mem_err;
00324 CDB___db_hashinit(addr, nelements);
00325 region->locker_off = R_OFFSET(&lt->reginfo, addr);
00326 
00327 /*
00328  * Initialize locks onto a free list. Initialize and lock the mutex
00329  * so that when we need to block, all we need do is try to acquire
00330  * the mutex.
00331  */
00332 SH_TAILQ_INIT(&region->free_locks);
00333 for (i = 0; i < region->maxlocks; ++i) {
00334 if ((ret = CDB___db_shalloc(lt->reginfo.addr,
00335 sizeof(struct __db_lock), MUTEX_ALIGN, &lp)) != 0)
00336 goto mem_err;
00337 lp->status = DB_LSTAT_FREE;
00338 if ((ret = __db_mutex_init(dbenv, &lp->mutex,
00339 R_OFFSET(&lt->reginfo, &lp->mutex) + DB_FCNTL_OFF_LOCK,
00340 MUTEX_SELF_BLOCK)) != 0)
00341 return (ret);
00342 MUTEX_LOCK(&lp->mutex, lt->dbenv->lockfhp);
00343 SH_TAILQ_INSERT_HEAD(&region->free_locks, lp, links, __db_lock);
00344 }
00345 
00346 /* Initialize objects onto a free list. */
00347 SH_TAILQ_INIT(&region->dd_objs);
00348 SH_TAILQ_INIT(&region->free_objs);
00349 for (i = 0; i < region->maxlocks; ++i) {
00350 if ((ret = CDB___db_shalloc(lt->reginfo.addr,
00351 sizeof(DB_LOCKOBJ), 0, &op)) != 0)
00352 goto mem_err;
00353 SH_TAILQ_INSERT_HEAD(
00354 &region->free_objs, op, links, __db_lockobj);
00355 }
00356 
00357 /* Initialize lockers onto a free list. */
00358 SH_TAILQ_INIT(&region->free_lockers);
00359 for (i = 0; i < region->maxlocks; ++i) {
00360 if ((ret = CDB___db_shalloc(lt->reginfo.addr,
00361 sizeof(DB_LOCKER), 0, &lidp)) != 0) {
00362 mem_err: CDB___db_err(dbenv, "Unable to allocate memory for the lock table");
00363 return (ret);
00364 }
00365 SH_TAILQ_INSERT_HEAD(
00366 &region->free_lockers, lidp, links, __db_locker);
00367 }
00368 
00369 return (0);
00370 }
00371 
00372 /*
00373  * CDB___lock_close --
00374  * Internal version of lock_close: only called from db_appinit.
00375  *
00376  * PUBLIC: int CDB___lock_close __P((DB_ENV *));
00377  */
00378 int
00379 CDB___lock_close(dbenv)
00380 DB_ENV *dbenv;
00381 {
00382 DB_LOCKTAB *lt;
00383 int ret;
00384 
00385 lt = dbenv->lk_handle;
00386 
00387 /* Detach from the region. */
00388 ret = CDB___db_r_detach(dbenv, &lt->reginfo, 0);
00389 
00390 CDB___os_free(lt, sizeof(*lt));
00391 
00392 dbenv->lk_handle = NULL;
00393 return (ret);
00394 }
00395 
00396 /*
00397  * CDB_lock_stat --
00398  * Return LOCK statistics.
00399  */
00400 int
00401 CDB_lock_stat(dbenv, statp, db_malloc)
00402 DB_ENV *dbenv;
00403 DB_LOCK_STAT **statp;
00404 void *(*db_malloc) __P((size_t));
00405 {
00406 DB_LOCKREGION *region;
00407 DB_LOCKTAB *lt;
00408 DB_LOCK_STAT *stats;
00409 int ret;
00410 
00411 #ifdef HAVE_RPC
00412 if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
00413 return (__dbcl_lock_stat(dbenv, statp, db_malloc));
00414 #endif
00415 
00416 PANIC_CHECK(dbenv);
00417 ENV_REQUIRES_CONFIG(dbenv, dbenv->lk_handle, DB_INIT_LOCK);
00418 
00419 *statp = NULL;
00420 
00421 lt = dbenv->lk_handle;
00422 
00423 if ((ret = CDB___os_malloc(dbenv, sizeof(*stats), db_malloc, &stats)) != 0)
00424 return (ret);
00425 
00426 /* Copy out the global statistics. */
00427 R_LOCK(dbenv, &lt->reginfo);
00428 
00429 region = lt->reginfo.primary;
00430 stats->st_lastid = region->id;
00431 stats->st_maxlocks = region->maxlocks;
00432 stats->st_nmodes = region->nmodes;
00433 stats->st_nlockers = region->nlockers;
00434 stats->st_maxnlockers = region->maxnlockers;
00435 stats->st_nconflicts = region->nconflicts;
00436 stats->st_nrequests = region->nrequests;
00437 stats->st_nreleases = region->nreleases;
00438 stats->st_nnowaits = region->nnowaits;
00439 stats->st_ndeadlocks = region->ndeadlocks;
00440 
00441 stats->st_region_wait = lt->reginfo.rp->mutex.mutex_set_wait;
00442 stats->st_region_nowait = lt->reginfo.rp->mutex.mutex_set_nowait;
00443 stats->st_regsize = lt->reginfo.rp->size;
00444 
00445 R_UNLOCK(dbenv, &lt->reginfo);
00446 
00447 *statp = stats;
00448 return (0);
00449 }
00450 
00451 #define LOCK_DUMP_CONF 0x001 /* Conflict matrix. */
00452 #define LOCK_DUMP_FREE 0x002 /* Display lock free list. */
00453 #define LOCK_DUMP_LOCKERS 0x004 /* Display lockers. */
00454 #define LOCK_DUMP_MEM 0x008 /* Display region memory. */
00455 #define LOCK_DUMP_OBJECTS 0x010 /* Display objects. */
00456 #define LOCK_DUMP_ALL 0x01f /* Display all. */
00457 
00458 /*
00459  * CDB___lock_dump_region --
00460  *
00461  * PUBLIC: void CDB___lock_dump_region __P((DB_ENV *, char *, FILE *));
00462  */
00463 void
00464 CDB___lock_dump_region(dbenv, area, fp)
00465 DB_ENV *dbenv;
00466 char *area;
00467 FILE *fp;
00468 {
00469 struct __db_lock *lp;
00470 DB_LOCKER *lip;
00471 DB_LOCKOBJ *op;
00472 DB_LOCKREGION *lrp;
00473 DB_LOCKTAB *lt;
00474 u_int32_t flags, i, j;
00475 int label;
00476 
00477 /* Make it easy to call from the debugger. */
00478 if (fp == NULL)
00479 fp = stderr;
00480 
00481 for (flags = 0; *area != '0円'; ++area)
00482 switch (*area) {
00483 case 'A':
00484 LF_SET(LOCK_DUMP_ALL);
00485 break;
00486 case 'c':
00487 LF_SET(LOCK_DUMP_CONF);
00488 break;
00489 case 'f':
00490 LF_SET(LOCK_DUMP_FREE);
00491 break;
00492 case 'l':
00493 LF_SET(LOCK_DUMP_LOCKERS);
00494 break;
00495 case 'm':
00496 LF_SET(LOCK_DUMP_MEM);
00497 break;
00498 case 'o':
00499 LF_SET(LOCK_DUMP_OBJECTS);
00500 break;
00501 }
00502 
00503 lt = dbenv->lk_handle;
00504 lrp = lt->reginfo.primary;
00505 LOCKREGION(dbenv, lt);
00506 
00507 fprintf(fp, "%s\nLock region parameters\n", DB_LINE);
00508 fprintf(fp, "%s: %lu, %s: %lu, %s: %lu, %s: %lu, %s: %lu, %s: %lu\n",
00509 "table size", (u_long)lrp->table_size,
00510 "obj_off", (u_long)lrp->obj_off,
00511 "osynch_off", (u_long)lrp->osynch_off,
00512 "locker_off", (u_long)lrp->locker_off,
00513 "lsynch_off", (u_long)lrp->lsynch_off,
00514 "need_dd", (u_long)lrp->need_dd);
00515 
00516 if (LF_ISSET(LOCK_DUMP_CONF)) {
00517 fprintf(fp, "\n%s\nConflict matrix\n", DB_LINE);
00518 for (i = 0; i < lrp->nmodes; i++) {
00519 for (j = 0; j < lrp->nmodes; j++)
00520 fprintf(fp, "%lu\t",
00521 (u_long)lt->conflicts[i * lrp->nmodes + j]);
00522 fprintf(fp, "\n");
00523 }
00524 }
00525 
00526 if (LF_ISSET(LOCK_DUMP_LOCKERS)) {
00527 fprintf(fp, "%s\nLocker hash buckets\n", DB_LINE);
00528 for (i = 0; i < lrp->table_size; i++) {
00529 label = 1;
00530 for (lip =
00531 SH_TAILQ_FIRST(&lt->locker_tab[i], __db_locker);
00532 lip != NULL;
00533 lip = SH_TAILQ_NEXT(lip, links, __db_locker)) {
00534 if (label) {
00535 fprintf(fp, "Bucket %lu:\n", (u_long)i);
00536 label = 0;
00537 }
00538 __lock_dump_locker(lt, lip, fp);
00539 }
00540 }
00541 }
00542 
00543 if (LF_ISSET(LOCK_DUMP_OBJECTS)) {
00544 fprintf(fp, "%s\nObject hash buckets\n", DB_LINE);
00545 for (i = 0; i < lrp->table_size; i++) {
00546 label = 1;
00547 for (op = SH_TAILQ_FIRST(&lt->obj_tab[i], __db_lockobj);
00548 op != NULL;
00549 op = SH_TAILQ_NEXT(op, links, __db_lockobj)) {
00550 if (label) {
00551 fprintf(fp, "Bucket %lu:\n", (u_long)i);
00552 label = 0;
00553 }
00554 __lock_dump_object(lt, op, fp);
00555 }
00556 }
00557 }
00558 
00559 if (LF_ISSET(LOCK_DUMP_FREE)) {
00560 fprintf(fp, "%s\nLock free list\n", DB_LINE);
00561 for (lp = SH_TAILQ_FIRST(&lrp->free_locks, __db_lock);
00562 lp != NULL;
00563 lp = SH_TAILQ_NEXT(lp, links, __db_lock))
00564 fprintf(fp, "0x%lx: %lu\t%lu\t%s\t0x%lx\n", (u_long)lp,
00565 (u_long)lp->holder, (u_long)lp->mode,
00566 __lock_dump_status(lp->status), (u_long)lp->obj);
00567 
00568 fprintf(fp, "%s\nObject free list\n", DB_LINE);
00569 for (op = SH_TAILQ_FIRST(&lrp->free_objs, __db_lockobj);
00570 op != NULL;
00571 op = SH_TAILQ_NEXT(op, links, __db_lockobj))
00572 fprintf(fp, "0x%lx\n", (u_long)op);
00573 
00574 fprintf(fp, "%s\nLocker free list\n", DB_LINE);
00575 for (lip = SH_TAILQ_FIRST(&lrp->free_lockers, __db_locker);
00576 lip != NULL;
00577 lip = SH_TAILQ_NEXT(lip, links, __db_locker))
00578 fprintf(fp, "0x%lx\n", (u_long)lip);
00579 }
00580 
00581 if (LF_ISSET(LOCK_DUMP_MEM))
00582 CDB___db_shalloc_dump(lt->reginfo.addr, fp);
00583 
00584 UNLOCKREGION(dbenv, lt);
00585 }
00586 
00587 static void
00588 __lock_dump_locker(lt, lip, fp)
00589 DB_LOCKTAB *lt;
00590 DB_LOCKER *lip;
00591 FILE *fp;
00592 {
00593 struct __db_lock *lp;
00594 
00595 fprintf(fp, "L %lx [%ld]", (u_long)lip->id, (long)lip->dd_id);
00596 fprintf(fp, " %s ", F_ISSET(lip, DB_LOCKER_DELETED) ? "(D)" : " ");
00597 
00598 if ((lp = SH_LIST_FIRST(&lip->heldby, __db_lock)) == NULL)
00599 fprintf(fp, "\n");
00600 else
00601 for (; lp != NULL;
00602 lp = SH_LIST_NEXT(lp, locker_links, __db_lock))
00603 CDB___lock_printlock(lt, lp, 1);
00604 }
00605 
00606 static void
00607 __lock_dump_object(lt, op, fp)
00608 DB_LOCKTAB *lt;
00609 DB_LOCKOBJ *op;
00610 FILE *fp;
00611 {
00612 struct __db_lock *lp;
00613 u_int32_t j;
00614 u_int8_t *ptr;
00615 u_int ch;
00616 
00617 ptr = SH_DBT_PTR(&op->lockobj);
00618 for (j = 0; j < op->lockobj.size; ptr++, j++) {
00619 ch = *ptr;
00620 fprintf(fp, isprint(ch) ? "%c" : "\\%o", ch);
00621 }
00622 fprintf(fp, "\n");
00623 
00624 fprintf(fp, "H:");
00625 for (lp =
00626 SH_TAILQ_FIRST(&op->holders, __db_lock);
00627 lp != NULL;
00628 lp = SH_TAILQ_NEXT(lp, links, __db_lock))
00629 CDB___lock_printlock(lt, lp, 1);
00630 lp = SH_TAILQ_FIRST(&op->waiters, __db_lock);
00631 if (lp != NULL) {
00632 fprintf(fp, "\nW:");
00633 for (; lp != NULL; lp = SH_TAILQ_NEXT(lp, links, __db_lock))
00634 CDB___lock_printlock(lt, lp, 1);
00635 }
00636 }
00637 
00638 static const char *
00639 __lock_dump_status(status)
00640 db_status_t status;
00641 {
00642 switch (status) {
00643 case DB_LSTAT_ABORTED:
00644 return ("aborted");
00645 case DB_LSTAT_ERR:
00646 return ("err");
00647 case DB_LSTAT_FREE:
00648 return ("free");
00649 case DB_LSTAT_HELD:
00650 return ("held");
00651 case DB_LSTAT_NOGRANT:
00652 return ("nogrant");
00653 case DB_LSTAT_PENDING:
00654 return ("pending");
00655 case DB_LSTAT_WAITING:
00656 return ("waiting");
00657 }
00658 return ("unknown status");
00659 }
00660 
00661 /*
00662  * __lock_region_size --
00663  * Return the region size.
00664  */
00665 static size_t
00666 __lock_region_size(dbenv)
00667 DB_ENV *dbenv;
00668 {
00669 size_t retval;
00670 u_int32_t i, nelements, nlocks;
00671 int gb;
00672 
00673 gb = 0;
00674 #ifdef DIAGNOSTIC
00675 /*
00676  * The below precise calculation doesn't leave enough space for guard
00677  * bytes, of which there is one plus whatever alignment wastage for
00678  * each CDB___db_shalloc. Give ourselves some breathing room.
00679  */
00680 gb = 1;
00681 #endif
00682 
00683 nlocks = dbenv->lk_max;
00684 nelements = CDB___db_tablesize(dbenv->lk_max);
00685 
00686 /*
00687  * Figure out how much space we're going to need. This list should
00688  * map one-to-one with the CDB___db_shalloc calls in __lock_init.
00689  */
00690 retval = 0;
00691 retval += ALIGN(sizeof(DB_LOCKREGION) + gb, 1);
00692 retval += ALIGN(dbenv->lk_modes * dbenv->lk_modes + gb, 1);
00693 retval += ALIGN(nelements * (sizeof(DB_HASHTAB) + gb), 1);
00694 retval += ALIGN(nelements * (sizeof(DB_HASHTAB) + gb), 1);
00695 for (i = 0; i < nlocks; ++i)
00696 retval +=
00697 ALIGN(sizeof(struct __db_lock) + gb , MUTEX_ALIGN);
00698 for (i = 0; i < nlocks; ++i)
00699 retval += ALIGN(sizeof(DB_LOCKOBJ) + gb , 1);
00700 for (i = 0; i < nlocks; ++i)
00701 retval += ALIGN(sizeof(DB_LOCKER) + gb , 1);
00702 
00703 /*
00704  * Aproximate the memory allocation overhead. This breaks the
00705  * abstraction a little, but seems better than a WAG.
00706  */
00707 retval += nlocks * (2 * sizeof(ssize_t) + sizeof(size_t));
00708 
00709 /*
00710  * Include 16 bytes of string space per lock. DB doesn't use it
00711  * because we pre-allocate lock space for DBTs in the structure.
00712  */
00713 retval += ALIGN(nlocks * 16, sizeof(size_t));
00714 
00715 /* And we keep getting this wrong, let's be generous. */
00716 retval += 16 * 1024;
00717 
00718 return (retval);
00719 }

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

AltStyle によって変換されたページ (->オリジナル) /