Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

mp_stat.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: mp_stat.c,v 12.10 2005/10/27 01:26:00 mjc Exp $
00008  */
00009 
00010 #include "db_config.h"
00011 
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014 
00015 #include <stdio.h>
00016 #include <string.h>
00017 #endif
00018 
00019 #include "db_int.h"
00020 #include "dbinc/db_page.h"
00021 #include "dbinc/db_shash.h"
00022 #include "dbinc/db_am.h"
00023 #include "dbinc/log.h"
00024 #include "dbinc/mp.h"
00025 
00026 #ifdef HAVE_STATISTICS
00027 static void __memp_print_bh
00028                 __P((DB_ENV *, DB_MPOOL *, BH *, roff_t *, u_int32_t));
00029 static int  __memp_print_all __P((DB_ENV *, u_int32_t));
00030 static int  __memp_print_stats __P((DB_ENV *, u_int32_t));
00031 static int __memp_print_hash __P((DB_ENV *,
00032                 DB_MPOOL *, REGINFO *, roff_t *, u_int32_t));
00033 static int  __memp_stat __P((DB_ENV *,
00034                 DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, u_int32_t));
00035 static void __memp_stat_wait __P((
00036                 DB_ENV *, REGINFO *, MPOOL *, DB_MPOOL_STAT *, u_int32_t));
00037 
00038 /*
00039  * __memp_stat_pp --
00040  *      DB_ENV->memp_stat pre/post processing.
00041  *
00042  * PUBLIC: int __memp_stat_pp
00043  * PUBLIC:     __P((DB_ENV *, DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, u_int32_t));
00044  */
00045 int
00046 __memp_stat_pp(dbenv, gspp, fspp, flags)
00047         DB_ENV *dbenv;
00048         DB_MPOOL_STAT **gspp;
00049         DB_MPOOL_FSTAT ***fspp;
00050         u_int32_t flags;
00051 {
00052         DB_THREAD_INFO *ip;
00053         int ret;
00054 
00055         PANIC_CHECK(dbenv);
00056         ENV_REQUIRES_CONFIG(dbenv,
00057             dbenv->mp_handle, "DB_ENV->memp_stat", DB_INIT_MPOOL);
00058 
00059         if ((ret = __db_fchk(dbenv,
00060             "DB_ENV->memp_stat", flags, DB_STAT_CLEAR)) != 0)
00061                 return (ret);
00062 
00063         ENV_ENTER(dbenv, ip);
00064         REPLICATION_WRAP(dbenv, (__memp_stat(dbenv, gspp, fspp, flags)), ret);
00065         ENV_LEAVE(dbenv, ip);
00066         return (ret);
00067 }
00068 
00069 /*
00070  * __memp_stat --
00071  *      DB_ENV->memp_stat
00072  */
00073 static int
00074 __memp_stat(dbenv, gspp, fspp, flags)
00075         DB_ENV *dbenv;
00076         DB_MPOOL_STAT **gspp;
00077         DB_MPOOL_FSTAT ***fspp;
00078         u_int32_t flags;
00079 {
00080         DB_MPOOL *dbmp;
00081         DB_MPOOL_FSTAT **tfsp, *tstruct;
00082         DB_MPOOL_STAT *sp;
00083         MPOOL *c_mp, *mp;
00084         MPOOLFILE *mfp;
00085         size_t len, nlen;
00086         u_int32_t i, pagesize, st_bytes, st_gbytes, st_hash_buckets, st_pages;
00087         u_int32_t tmp_wait, tmp_nowait;
00088         int ret;
00089         char *name, *tname;
00090 
00091         dbmp = dbenv->mp_handle;
00092         mp = dbmp->reginfo[0].primary;
00093 
00094         /* Global statistics. */
00095         if (gspp != NULL) {
00096                 *gspp = NULL;
00097 
00098                 if ((ret = __os_umalloc(dbenv, sizeof(**gspp), gspp)) != 0)
00099                         return (ret);
00100                 memset(*gspp, 0, sizeof(**gspp));
00101                 sp = *gspp;
00102 
00103                 /*
00104                  * Initialization and information that is not maintained on
00105                  * a per-cache basis.  Note that configuration information
00106                  * may be modified at any time, and so we have to lock.
00107                  */
00108                 c_mp = dbmp->reginfo[0].primary;
00109                 sp->st_gbytes = c_mp->stat.st_gbytes;
00110                 sp->st_bytes = c_mp->stat.st_bytes;
00111                 sp->st_ncache = dbmp->nreg;
00112                 sp->st_regsize = dbmp->reginfo[0].rp->size;
00113 
00114                 MPOOL_SYSTEM_LOCK(dbenv);
00115                 sp->st_mmapsize = mp->mp_mmapsize;
00116                 sp->st_maxopenfd = mp->mp_maxopenfd;
00117                 sp->st_maxwrite = mp->mp_maxwrite;
00118                 sp->st_maxwrite_sleep = mp->mp_maxwrite_sleep;
00119                 MPOOL_SYSTEM_UNLOCK(dbenv);
00120 
00121                 /* Walk the cache list and accumulate the global information. */
00122                 for (i = 0; i < mp->nreg; ++i) {
00123                         c_mp = dbmp->reginfo[i].primary;
00124 
00125                         sp->st_map += c_mp->stat.st_map;
00126                         sp->st_cache_hit += c_mp->stat.st_cache_hit;
00127                         sp->st_cache_miss += c_mp->stat.st_cache_miss;
00128                         sp->st_page_create += c_mp->stat.st_page_create;
00129                         sp->st_page_in += c_mp->stat.st_page_in;
00130                         sp->st_page_out += c_mp->stat.st_page_out;
00131                         sp->st_ro_evict += c_mp->stat.st_ro_evict;
00132                         sp->st_rw_evict += c_mp->stat.st_rw_evict;
00133                         sp->st_page_trickle += c_mp->stat.st_page_trickle;
00134                         sp->st_pages += c_mp->stat.st_pages;
00135                         /*
00136                          * st_page_dirty        calculated by __memp_stat_hash
00137                          * st_page_clean        calculated here
00138                          */
00139                         __memp_stat_hash(
00140                             &dbmp->reginfo[i], c_mp, &sp->st_page_dirty);
00141                         sp->st_page_clean = sp->st_pages - sp->st_page_dirty;
00142                         sp->st_hash_buckets += c_mp->stat.st_hash_buckets;
00143                         sp->st_hash_searches += c_mp->stat.st_hash_searches;
00144                         sp->st_hash_longest += c_mp->stat.st_hash_longest;
00145                         sp->st_hash_examined += c_mp->stat.st_hash_examined;
00146                         /*
00147                          * st_hash_nowait       calculated by __memp_stat_wait
00148                          * st_hash_wait
00149                          */
00150                         __memp_stat_wait(
00151                             dbenv, &dbmp->reginfo[i], c_mp, sp, flags);
00152                         __mutex_set_wait_info(dbenv,
00153                             c_mp->mtx_region, &tmp_wait, &tmp_nowait);
00154                         sp->st_region_nowait += tmp_nowait;
00155                         sp->st_region_wait += tmp_wait;
00156                         sp->st_alloc += c_mp->stat.st_alloc;
00157                         sp->st_alloc_buckets += c_mp->stat.st_alloc_buckets;
00158                         if (sp->st_alloc_max_buckets <
00159                             c_mp->stat.st_alloc_max_buckets)
00160                                 sp->st_alloc_max_buckets =
00161                                     c_mp->stat.st_alloc_max_buckets;
00162                         sp->st_alloc_pages += c_mp->stat.st_alloc_pages;
00163                         if (sp->st_alloc_max_pages <
00164                             c_mp->stat.st_alloc_max_pages)
00165                                 sp->st_alloc_max_pages =
00166                                     c_mp->stat.st_alloc_max_pages;
00167 
00168                         if (LF_ISSET(DB_STAT_CLEAR)) {
00169                                 __mutex_clear(dbenv, c_mp->mtx_region);
00170 
00171                                 MPOOL_SYSTEM_LOCK(dbenv);
00172                                 st_bytes = c_mp->stat.st_bytes;
00173                                 st_gbytes = c_mp->stat.st_gbytes;
00174                                 st_hash_buckets = c_mp->stat.st_hash_buckets;
00175                                 st_pages = c_mp->stat.st_pages;
00176                                 memset(&c_mp->stat, 0, sizeof(c_mp->stat));
00177                                 c_mp->stat.st_bytes = st_bytes;
00178                                 c_mp->stat.st_gbytes = st_gbytes;
00179                                 c_mp->stat.st_hash_buckets = st_hash_buckets;
00180                                 c_mp->stat.st_pages = st_pages;
00181                                 MPOOL_SYSTEM_UNLOCK(dbenv);
00182                         }
00183                 }
00184 
00185                 /*
00186                  * We have duplicate statistics fields in per-file structures
00187                  * and the cache.  The counters are only incremented in the
00188                  * per-file structures, except if a file is flushed from the
00189                  * mpool, at which time we copy its information into the cache
00190                  * statistics.  We added the cache information above, now we
00191                  * add the per-file information.
00192                  */
00193                 MPOOL_SYSTEM_LOCK(dbenv);
00194                 for (mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
00195                     mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
00196                         sp->st_map += mfp->stat.st_map;
00197                         sp->st_cache_hit += mfp->stat.st_cache_hit;
00198                         sp->st_cache_miss += mfp->stat.st_cache_miss;
00199                         sp->st_page_create += mfp->stat.st_page_create;
00200                         sp->st_page_in += mfp->stat.st_page_in;
00201                         sp->st_page_out += mfp->stat.st_page_out;
00202                         if (fspp == NULL && LF_ISSET(DB_STAT_CLEAR)) {
00203                                 pagesize = mfp->stat.st_pagesize;
00204                                 memset(&mfp->stat, 0, sizeof(mfp->stat));
00205                                 mfp->stat.st_pagesize = pagesize;
00206                         }
00207                 }
00208                 MPOOL_SYSTEM_UNLOCK(dbenv);
00209         }
00210 
00211         /* Per-file statistics. */
00212         if (fspp != NULL) {
00213                 *fspp = NULL;
00214 
00215                 /* Count the MPOOLFILE structures. */
00216                 MPOOL_SYSTEM_LOCK(dbenv);
00217                 for (i = 0, len = 0,
00218                     mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
00219                     mfp != NULL;
00220                     ++i, mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile))
00221                         len += sizeof(DB_MPOOL_FSTAT *) +
00222                             sizeof(DB_MPOOL_FSTAT) +
00223                             strlen(__memp_fns(dbmp, mfp)) + 1;
00224                 len += sizeof(DB_MPOOL_FSTAT *);        /* Trailing NULL */
00225                 MPOOL_SYSTEM_UNLOCK(dbenv);
00226 
00227                 if (i == 0)
00228                         return (0);
00229 
00230                 /* Allocate space */
00231                 if ((ret = __os_umalloc(dbenv, len, fspp)) != 0)
00232                         return (ret);
00233 
00234                 /*
00235                  * Build each individual entry.  We assume that an array of
00236                  * pointers are aligned correctly to be followed by an array
00237                  * of structures, which should be safe (in this particular
00238                  * case, the first element of the structure is a pointer, so
00239                  * we're doubly safe).  The array is followed by space for
00240                  * the text file names.
00241                  *
00242                  * Add 1 to i because we need to skip over the NULL.
00243                  */
00244                 tfsp = *fspp;
00245                 tstruct = (DB_MPOOL_FSTAT *)(tfsp + i + 1);
00246                 tname = (char *)(tstruct + i);
00247 
00248                 /*
00249                  * Files may have been opened since we counted, don't walk
00250                  * off the end of the allocated space.
00251                  */
00252                 MPOOL_SYSTEM_LOCK(dbenv);
00253                 for (mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
00254                     mfp != NULL && i-- > 0;
00255                     ++tfsp, ++tstruct, tname += nlen,
00256                     mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
00257                         name = __memp_fns(dbmp, mfp);
00258                         nlen = strlen(name) + 1;
00259                         *tfsp = tstruct;
00260                         *tstruct = mfp->stat;
00261                         if (LF_ISSET(DB_STAT_CLEAR)) {
00262                                 pagesize = mfp->stat.st_pagesize;
00263                                 memset(&mfp->stat, 0, sizeof(mfp->stat));
00264                                 mfp->stat.st_pagesize = pagesize;
00265                         }
00266                         tstruct->file_name = tname;
00267                         memcpy(tname, name, nlen);
00268                 }
00269                 MPOOL_SYSTEM_UNLOCK(dbenv);
00270 
00271                 *tfsp = NULL;
00272         }
00273         return (0);
00274 }
00275 
00276 /*
00277  * __memp_stat_print_pp --
00278  *      DB_ENV->memp_stat_print pre/post processing.
00279  *
00280  * PUBLIC: int __memp_stat_print_pp __P((DB_ENV *, u_int32_t));
00281  */
00282 int
00283 __memp_stat_print_pp(dbenv, flags)
00284         DB_ENV *dbenv;
00285         u_int32_t flags;
00286 {
00287         DB_THREAD_INFO *ip;
00288         int ret;
00289 
00290         PANIC_CHECK(dbenv);
00291         ENV_REQUIRES_CONFIG(dbenv,
00292             dbenv->mp_handle, "DB_ENV->memp_stat_print", DB_INIT_MPOOL);
00293 
00294 #define DB_STAT_MEMP_FLAGS                                              \
00295         (DB_STAT_ALL | DB_STAT_CLEAR | DB_STAT_MEMP_HASH)
00296         if ((ret = __db_fchk(dbenv,
00297             "DB_ENV->memp_stat_print", flags, DB_STAT_MEMP_FLAGS)) != 0)
00298                 return (ret);
00299 
00300         ENV_ENTER(dbenv, ip);
00301         REPLICATION_WRAP(dbenv, (__memp_stat_print(dbenv, flags)), ret);
00302         ENV_LEAVE(dbenv, ip);
00303         return (ret);
00304 }
00305 
00306 #define FMAP_ENTRIES    200                     /* Files we map. */
00307 
00308 /*
00309  * __memp_stat_print --
00310  *      DB_ENV->memp_stat_print method.
00311  *
00312  * PUBLIC: int  __memp_stat_print __P((DB_ENV *, u_int32_t));
00313  */
00314 int
00315 __memp_stat_print(dbenv, flags)
00316         DB_ENV *dbenv;
00317         u_int32_t flags;
00318 {
00319         u_int32_t orig_flags;
00320         int ret;
00321 
00322         orig_flags = flags;
00323         LF_CLR(DB_STAT_CLEAR);
00324         if (flags == 0 || LF_ISSET(DB_STAT_ALL)) {
00325                 ret = __memp_print_stats(dbenv, orig_flags);
00326                 if (flags == 0 || ret != 0)
00327                         return (ret);
00328         }
00329 
00330         if (LF_ISSET(DB_STAT_ALL | DB_STAT_MEMP_HASH) &&
00331             (ret = __memp_print_all(dbenv, orig_flags)) != 0)
00332                 return (ret);
00333 
00334         return (0);
00335 }
00336 
00337 /*
00338  * __memp_print_stats --
00339  *      Display default mpool region statistics.
00340  */
00341 static int
00342 __memp_print_stats(dbenv, flags)
00343         DB_ENV *dbenv;
00344         u_int32_t flags;
00345 {
00346         DB_MPOOL_FSTAT **fsp, **tfsp;
00347         DB_MPOOL_STAT *gsp;
00348         int ret;
00349 
00350         if ((ret = __memp_stat(dbenv, &gsp, &fsp, flags)) != 0)
00351                 return (ret);
00352 
00353         if (LF_ISSET(DB_STAT_ALL))
00354                 __db_msg(dbenv, "Default cache region information:");
00355         __db_dlbytes(dbenv, "Total cache size",
00356             (u_long)gsp->st_gbytes, (u_long)0, (u_long)gsp->st_bytes);
00357         __db_dl(dbenv, "Number of caches", (u_long)gsp->st_ncache);
00358         __db_dlbytes(dbenv, "Pool individual cache size",
00359             (u_long)0, (u_long)0, (u_long)gsp->st_regsize);
00360         __db_dlbytes(dbenv, "Maximum memory-mapped file size",
00361             (u_long)0, (u_long)0, (u_long)gsp->st_mmapsize);
00362         STAT_LONG("Maximum open file descriptors", gsp->st_maxopenfd);
00363         STAT_LONG("Maximum sequential buffer writes", gsp->st_maxwrite);
00364         STAT_LONG("Sleep after writing maximum sequential buffers",
00365             gsp->st_maxwrite_sleep);
00366         __db_dl(dbenv,
00367             "Requested pages mapped into the process' address space",
00368             (u_long)gsp->st_map);
00369         __db_dl_pct(dbenv, "Requested pages found in the cache",
00370             (u_long)gsp->st_cache_hit, DB_PCT(
00371             gsp->st_cache_hit, gsp->st_cache_hit + gsp->st_cache_miss), NULL);
00372         __db_dl(dbenv, "Requested pages not found in the cache",
00373             (u_long)gsp->st_cache_miss);
00374         __db_dl(dbenv,
00375             "Pages created in the cache", (u_long)gsp->st_page_create);
00376         __db_dl(dbenv, "Pages read into the cache", (u_long)gsp->st_page_in);
00377         __db_dl(dbenv, "Pages written from the cache to the backing file",
00378             (u_long)gsp->st_page_out);
00379         __db_dl(dbenv, "Clean pages forced from the cache",
00380             (u_long)gsp->st_ro_evict);
00381         __db_dl(dbenv, "Dirty pages forced from the cache",
00382             (u_long)gsp->st_rw_evict);
00383         __db_dl(dbenv, "Dirty pages written by trickle-sync thread",
00384             (u_long)gsp->st_page_trickle);
00385         __db_dl(dbenv, "Current total page count",
00386             (u_long)gsp->st_pages);
00387         __db_dl(dbenv, "Current clean page count",
00388             (u_long)gsp->st_page_clean);
00389         __db_dl(dbenv, "Current dirty page count",
00390             (u_long)gsp->st_page_dirty);
00391         __db_dl(dbenv, "Number of hash buckets used for page location",
00392             (u_long)gsp->st_hash_buckets);
00393         __db_dl(dbenv,
00394             "Total number of times hash chains searched for a page",
00395             (u_long)gsp->st_hash_searches);
00396         __db_dl(dbenv, "The longest hash chain searched for a page",
00397             (u_long)gsp->st_hash_longest);
00398         __db_dl(dbenv,
00399             "Total number of hash chain entries checked for page",
00400             (u_long)gsp->st_hash_examined);
00401         __db_dl_pct(dbenv,
00402             "The number of hash bucket locks that required waiting",
00403             (u_long)gsp->st_hash_wait, DB_PCT(
00404             gsp->st_hash_wait, gsp->st_hash_wait + gsp->st_hash_nowait), NULL);
00405         __db_dl(dbenv,
00406     "The maximum number of times any hash bucket lock was waited for",
00407             (u_long)gsp->st_hash_max_wait);
00408         __db_dl_pct(dbenv,
00409             "The number of region locks that required waiting",
00410             (u_long)gsp->st_region_wait, DB_PCT(gsp->st_region_wait,
00411             gsp->st_region_wait + gsp->st_region_nowait), NULL);
00412         __db_dl(dbenv, "The number of page allocations", (u_long)gsp->st_alloc);
00413         __db_dl(dbenv,
00414             "The number of hash buckets examined during allocations",
00415             (u_long)gsp->st_alloc_buckets);
00416         __db_dl(dbenv,
00417             "The maximum number of hash buckets examined for an allocation",
00418             (u_long)gsp->st_alloc_max_buckets);
00419         __db_dl(dbenv, "The number of pages examined during allocations",
00420             (u_long)gsp->st_alloc_pages);
00421         __db_dl(dbenv, "The max number of pages examined for an allocation",
00422             (u_long)gsp->st_alloc_max_pages);
00423 
00424         for (tfsp = fsp; fsp != NULL && *tfsp != NULL; ++tfsp) {
00425                 if (LF_ISSET(DB_STAT_ALL))
00426                         __db_msg(dbenv, "%s", DB_GLOBAL(db_line));
00427                 __db_msg(dbenv, "Pool File: %s", (*tfsp)->file_name);
00428                 __db_dl(dbenv, "Page size", (u_long)(*tfsp)->st_pagesize);
00429                 __db_dl(dbenv,
00430                     "Requested pages mapped into the process' address space",
00431                     (u_long)(*tfsp)->st_map);
00432                 __db_dl_pct(dbenv, "Requested pages found in the cache",
00433                     (u_long)(*tfsp)->st_cache_hit, DB_PCT((*tfsp)->st_cache_hit,
00434                     (*tfsp)->st_cache_hit + (*tfsp)->st_cache_miss), NULL);
00435                 __db_dl(dbenv, "Requested pages not found in the cache",
00436                     (u_long)(*tfsp)->st_cache_miss);
00437                 __db_dl(dbenv, "Pages created in the cache",
00438                     (u_long)(*tfsp)->st_page_create);
00439                 __db_dl(dbenv, "Pages read into the cache",
00440                     (u_long)(*tfsp)->st_page_in);
00441                 __db_dl(dbenv,
00442                     "Pages written from the cache to the backing file",
00443                     (u_long)(*tfsp)->st_page_out);
00444         }
00445 
00446         __os_ufree(dbenv, fsp);
00447         __os_ufree(dbenv, gsp);
00448         return (0);
00449 }
00450 
00451 /*
00452  * __memp_print_all --
00453  *      Display debugging mpool region statistics.
00454  */
00455 static int
00456 __memp_print_all(dbenv, flags)
00457         DB_ENV *dbenv;
00458         u_int32_t flags;
00459 {
00460         static const FN fn[] = {
00461                 { MP_CAN_MMAP,          "MP_CAN_MMAP" },
00462                 { MP_DIRECT,            "MP_DIRECT" },
00463                 { MP_EXTENT,            "MP_EXTENT" },
00464                 { MP_FAKE_DEADFILE,     "deadfile" },
00465                 { MP_FAKE_FILEWRITTEN,  "file written" },
00466                 { MP_FAKE_NB,           "no backing file" },
00467                 { MP_FAKE_UOC,          "unlink on close" },
00468                 { MP_NOT_DURABLE,       "not durable" },
00469                 { MP_TEMP,              "MP_TEMP" },
00470                 { 0,                    NULL }
00471         };
00472         static const FN cfn[] = {
00473                 { DB_MPOOL_NOFILE,      "DB_MPOOL_NOFILE" },
00474                 { DB_MPOOL_UNLINK,      "DB_MPOOL_UNLINK" },
00475                 { 0,                    NULL }
00476         };
00477         DB_MPOOL *dbmp;
00478         DB_MPOOLFILE *dbmfp;
00479         MPOOL *mp;
00480         MPOOLFILE *mfp;
00481         roff_t fmap[FMAP_ENTRIES + 1];
00482         u_int32_t i, mfp_flags;
00483         int cnt, ret;
00484 
00485         dbmp = dbenv->mp_handle;
00486         mp = dbmp->reginfo[0].primary;
00487         ret = 0;
00488 
00489         MPOOL_SYSTEM_LOCK(dbenv);
00490 
00491         __db_print_reginfo(dbenv, dbmp->reginfo, "Mpool");
00492         __db_msg(dbenv, "%s", DB_GLOBAL(db_line));
00493 
00494         __db_msg(dbenv, "MPOOL structure:");
00495         __mutex_print_debug_single(
00496             dbenv, "MPOOL region mutex", mp->mtx_region, flags);
00497         STAT_LSN("Maximum checkpoint LSN", &mp->lsn);
00498         STAT_ULONG("Hash table entries", mp->htab_buckets);
00499         STAT_ULONG("Hash table last-checked", mp->last_checked);
00500         STAT_ULONG("Hash table LRU count", mp->lru_count);
00501         STAT_ULONG("Put counter", mp->put_counter);
00502 
00503         __db_msg(dbenv, "%s", DB_GLOBAL(db_line));
00504         __db_msg(dbenv, "DB_MPOOL handle information:");
00505         __mutex_print_debug_single(
00506             dbenv, "DB_MPOOL handle mutex", dbmp->mutex, flags);
00507         STAT_ULONG("Underlying cache regions", dbmp->nreg);
00508 
00509         __db_msg(dbenv, "%s", DB_GLOBAL(db_line));
00510         __db_msg(dbenv, "DB_MPOOLFILE structures:");
00511         for (cnt = 0, dbmfp = TAILQ_FIRST(&dbmp->dbmfq);
00512             dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q), ++cnt) {
00513                 __db_msg(dbenv, "File #%d: %s: per-process, %s",
00514                     cnt + 1, __memp_fn(dbmfp),
00515                     F_ISSET(dbmfp, MP_READONLY) ? "readonly" : "read/write");
00516                 STAT_ULONG("Reference count", dbmfp->ref);
00517                 STAT_ULONG("Pinned block reference count", dbmfp->ref);
00518                 STAT_ULONG("Clear length", dbmfp->clear_len);
00519                 __db_print_fileid(dbenv, dbmfp->fileid, "\tID");
00520                 STAT_ULONG("File type", dbmfp->ftype);
00521                 STAT_ULONG("LSN offset", dbmfp->lsn_offset);
00522                 STAT_ULONG("Max gbytes", dbmfp->gbytes);
00523                 STAT_ULONG("Max bytes", dbmfp->bytes);
00524                 STAT_ULONG("Cache priority", dbmfp->priority);
00525                 STAT_POINTER("mmap address", dbmfp->addr);
00526                 STAT_ULONG("mmap length", dbmfp->len);
00527                 __db_prflags(dbenv, NULL, dbmfp->flags, cfn, NULL, "\tFlags");
00528                 __db_print_fh(dbenv, "File handle", dbmfp->fhp, flags);
00529         }
00530 
00531         __db_msg(dbenv, "%s", DB_GLOBAL(db_line));
00532         __db_msg(dbenv, "MPOOLFILE structures:");
00533         for (cnt = 0, mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
00534             mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile), ++cnt) {
00535                 __db_msg(dbenv, "File #%d: %s", cnt + 1, __memp_fns(dbmp, mfp));
00536                 __mutex_print_debug_single(dbenv, "Mutex", mfp->mutex, flags);
00537 
00538                 MUTEX_LOCK(dbenv, mfp->mutex);
00539                 STAT_ULONG("Reference count", mfp->mpf_cnt);
00540                 STAT_ULONG("Block count", mfp->block_cnt);
00541                 STAT_ULONG("Last page number", mfp->last_pgno);
00542                 STAT_ULONG("Original last page number", mfp->orig_last_pgno);
00543                 STAT_ULONG("Maximum page number", mfp->maxpgno);
00544                 STAT_LONG("Type", mfp->ftype);
00545                 STAT_LONG("Priority", mfp->priority);
00546                 STAT_LONG("Page's LSN offset", mfp->lsn_off);
00547                 STAT_LONG("Page's clear length", mfp->clear_len);
00548 
00549                 __db_print_fileid(dbenv,
00550                     R_ADDR(dbmp->reginfo, mfp->fileid_off), "\tID");
00551 
00552                 mfp_flags = 0;
00553                 if (mfp->deadfile)
00554                         FLD_SET(mfp_flags, MP_FAKE_DEADFILE);
00555                 if (mfp->file_written)
00556                         FLD_SET(mfp_flags, MP_FAKE_FILEWRITTEN);
00557                 if (mfp->no_backing_file)
00558                         FLD_SET(mfp_flags, MP_FAKE_NB);
00559                 if (mfp->unlink_on_close)
00560                         FLD_SET(mfp_flags, MP_FAKE_UOC);
00561                 __db_prflags(dbenv, NULL, mfp_flags, fn, NULL, "\tFlags");
00562 
00563                 if (cnt < FMAP_ENTRIES)
00564                         fmap[cnt] = R_OFFSET(dbmp->reginfo, mfp);
00565                 MUTEX_UNLOCK(dbenv, mfp->mutex);
00566         }
00567         MPOOL_SYSTEM_UNLOCK(dbenv);
00568 
00569         if (cnt < FMAP_ENTRIES)
00570                 fmap[cnt] = INVALID_ROFF;
00571         else
00572                 fmap[FMAP_ENTRIES] = INVALID_ROFF;
00573 
00574         /* Dump the individual caches. */
00575         for (i = 0; i < mp->nreg; ++i) {
00576                 __db_msg(dbenv, "%s", DB_GLOBAL(db_line));
00577                 __db_msg(dbenv, "Cache #%d:", i + 1);
00578                 if ((ret = __memp_print_hash(
00579                     dbenv, dbmp, &dbmp->reginfo[i], fmap, flags)) != 0)
00580                         break;
00581         }
00582 
00583         return (ret);
00584 }
00585 
00586 /*
00587  * __memp_print_hash --
00588  *      Display hash bucket statistics for a cache.
00589  */
00590 static int
00591 __memp_print_hash(dbenv, dbmp, reginfo, fmap, flags)
00592         DB_ENV *dbenv;
00593         DB_MPOOL *dbmp;
00594         REGINFO *reginfo;
00595         roff_t *fmap;
00596         u_int32_t flags;
00597 {
00598         BH *bhp;
00599         DB_MPOOL_HASH *hp;
00600         DB_MSGBUF mb;
00601         MPOOL *c_mp;
00602         u_int32_t bucket;
00603 
00604         c_mp = reginfo->primary;
00605         DB_MSGBUF_INIT(&mb);
00606 
00607         /* Display the hash table list of BH's. */
00608         __db_msg(dbenv,
00609             "BH hash table (%lu hash slots)", (u_long)c_mp->htab_buckets);
00610         __db_msg(dbenv, "bucket #: priority, [mutex]");
00611         __db_msg(dbenv,
00612     "\tpageno, file, ref, LSN, [mutex], address, priority, flags");
00613 
00614         for (hp = R_ADDR(reginfo, c_mp->htab),
00615             bucket = 0; bucket < c_mp->htab_buckets; ++hp, ++bucket) {
00616                 MUTEX_LOCK(dbenv, hp->mtx_hash);
00617                 if ((bhp = SH_TAILQ_FIRST(&hp->hash_bucket, __bh)) != NULL) {
00618                         __db_msgadd(dbenv, &mb, "bucket %lu: %lu, ",
00619                             (u_long)bucket, (u_long)hp->hash_priority);
00620                         __mutex_print_debug_stats(
00621                             dbenv, &mb, hp->mtx_hash, flags);
00622                         DB_MSGBUF_FLUSH(dbenv, &mb);
00623                 }
00624                 for (; bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh))
00625                         __memp_print_bh(dbenv, dbmp, bhp, fmap, flags);
00626 
00627                 MUTEX_UNLOCK(dbenv, hp->mtx_hash);
00628         }
00629 
00630         return (0);
00631 }
00632 
00633 /*
00634  * __memp_print_bh --
00635  *      Display a BH structure.
00636  */
00637 static void
00638 __memp_print_bh(dbenv, dbmp, bhp, fmap, flags)
00639         DB_ENV *dbenv;
00640         DB_MPOOL *dbmp;
00641         BH *bhp;
00642         roff_t *fmap;
00643         u_int32_t flags;
00644 {
00645         static const FN fn[] = {
00646                 { BH_CALLPGIN,          "callpgin" },
00647                 { BH_DIRTY,             "dirty" },
00648                 { BH_DIRTY_CREATE,      "created" },
00649                 { BH_DISCARD,           "discard" },
00650                 { BH_LOCKED,            "locked" },
00651                 { BH_TRASH,             "trash" },
00652                 { 0,                    NULL }
00653         };
00654         DB_MSGBUF mb;
00655         int i;
00656 
00657         DB_MSGBUF_INIT(&mb);
00658 
00659         for (i = 0; i < FMAP_ENTRIES; ++i)
00660                 if (fmap[i] == INVALID_ROFF || fmap[i] == bhp->mf_offset)
00661                         break;
00662 
00663         if (fmap[i] == INVALID_ROFF)
00664                 __db_msgadd(dbenv, &mb, "\t%5lu, %lu, ",
00665                     (u_long)bhp->pgno, (u_long)bhp->mf_offset);
00666         else
00667                 __db_msgadd(
00668                     dbenv, &mb, "\t%5lu, #%d, ", (u_long)bhp->pgno, i + 1);
00669 
00670         __db_msgadd(dbenv, &mb, "%2lu, %lu/%lu, ", (u_long)bhp->ref,
00671             (u_long)LSN(bhp->buf).file, (u_long)LSN(bhp->buf).offset);
00672         __mutex_print_debug_stats(dbenv, &mb, bhp->mtx_bh, flags);
00673         __db_msgadd(dbenv, &mb, ", %#08lx, %lu",
00674             (u_long)R_OFFSET(dbmp->reginfo, bhp), (u_long)bhp->priority);
00675         __db_prflags(dbenv, &mb, bhp->flags, fn, " (", ")");
00676         DB_MSGBUF_FLUSH(dbenv, &mb);
00677 }
00678 
00679 /*
00680  * __memp_stat_wait --
00681  *      Total hash bucket wait stats into the region.
00682  */
00683 static void
00684 __memp_stat_wait(dbenv, reginfo, mp, mstat, flags)
00685         DB_ENV *dbenv;
00686         REGINFO *reginfo;
00687         MPOOL *mp;
00688         DB_MPOOL_STAT *mstat;
00689         u_int32_t flags;
00690 {
00691         DB_MPOOL_HASH *hp;
00692         u_int32_t i, tmp_nowait, tmp_wait;
00693 
00694         mstat->st_hash_max_wait = 0;
00695         hp = R_ADDR(reginfo, mp->htab);
00696         for (i = 0; i < mp->htab_buckets; i++, hp++) {
00697                 __mutex_set_wait_info(
00698                     dbenv, hp->mtx_hash, &tmp_wait, &tmp_nowait);
00699                 mstat->st_hash_nowait += tmp_nowait;
00700                 mstat->st_hash_wait += tmp_wait;
00701                 if (tmp_wait > mstat->st_hash_max_wait)
00702                         mstat->st_hash_max_wait = tmp_wait;
00703 
00704                 if (LF_ISSET(DB_STAT_CLEAR))
00705                         __mutex_clear(dbenv, hp->mtx_hash);
00706         }
00707 }
00708 
00709 #else /* !HAVE_STATISTICS */
00710 
00711 int
00712 __memp_stat_pp(dbenv, gspp, fspp, flags)
00713         DB_ENV *dbenv;
00714         DB_MPOOL_STAT **gspp;
00715         DB_MPOOL_FSTAT ***fspp;
00716         u_int32_t flags;
00717 {
00718         COMPQUIET(gspp, NULL);
00719         COMPQUIET(fspp, NULL);
00720         COMPQUIET(flags, 0);
00721 
00722         return (__db_stat_not_built(dbenv));
00723 }
00724 
00725 int
00726 __memp_stat_print_pp(dbenv, flags)
00727         DB_ENV *dbenv;
00728         u_int32_t flags;
00729 {
00730         COMPQUIET(flags, 0);
00731 
00732         return (__db_stat_not_built(dbenv));
00733 }
00734 #endif
00735 
00736 /*
00737  * __memp_stat_hash --
00738  *      Total hash bucket stats (other than mutex wait) into the region.
00739  *
00740  * PUBLIC: void __memp_stat_hash __P((REGINFO *, MPOOL *, u_int32_t *));
00741  */
00742 void
00743 __memp_stat_hash(reginfo, mp, dirtyp)
00744         REGINFO *reginfo;
00745         MPOOL *mp;
00746         u_int32_t *dirtyp;
00747 {
00748         DB_MPOOL_HASH *hp;
00749         u_int32_t dirty, i;
00750 
00751         hp = R_ADDR(reginfo, mp->htab);
00752         for (i = 0, dirty = 0; i < mp->htab_buckets; i++, hp++)
00753                 dirty += hp->hash_page_dirty;
00754         *dirtyp = dirty;
00755 }

Generated on Sun Dec 25 12:14:41 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2