db

mp_stat.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 #include "config.h"
00008 
00009 #ifndef lint
00010 static const char revid[] = "$Id: mp__stat_8c-source.html,v 1.1 2008年06月08日 10:20:50 sebdiaz Exp $";
00011 #endif /* not lint */
00012 
00013 #ifndef NO_SYSTEM_INCLUDES
00014 #include <sys/types.h>
00015 
00016 #include <errno.h>
00017 #include <stdio.h>
00018 #include <string.h>
00019 #include <unistd.h>
00020 #endif
00021 
00022 #ifdef HAVE_RPC
00023 #include "db_server.h"
00024 #endif
00025 
00026 #include "db_int.h"
00027 #include "db_page.h"
00028 #include "db_shash.h"
00029 #include "db_am.h"
00030 #include "mp.h"
00031 
00032 #ifdef HAVE_RPC
00033 #include "gen_client_ext.h"
00034 #include "rpc_client_ext.h"
00035 #endif
00036 
00037 static void __memp_dumpcache
00038 __P((DB_MPOOL *, REGINFO *, size_t *, FILE *, u_int32_t));
00039 static void __memp_pbh __P((DB_MPOOL *, BH *, size_t *, FILE *));
00040 
00041 /*
00042  * CDB_memp_stat --
00043  * Display MPOOL statistics.
00044  */
00045 int
00046 CDB_memp_stat(dbenv, gspp, fspp, db_malloc)
00047 DB_ENV *dbenv;
00048 DB_MPOOL_STAT **gspp;
00049 DB_MPOOL_FSTAT ***fspp;
00050 void *(*db_malloc) __P((size_t));
00051 {
00052 DB_MPOOL *dbmp;
00053 DB_MPOOL_FSTAT **tfsp;
00054 DB_MPOOL_STAT *sp;
00055 MPOOL *c_mp, *mp;
00056 MPOOLFILE *mfp;
00057 size_t len, nlen;
00058 u_int32_t i;
00059 int ret;
00060 char *name;
00061 
00062 #ifdef HAVE_RPC
00063 if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
00064 return (__dbcl_memp_stat(dbenv, gspp, fspp, db_malloc));
00065 #endif
00066 
00067 PANIC_CHECK(dbenv);
00068 ENV_REQUIRES_CONFIG(dbenv, dbenv->mp_handle, DB_INIT_MPOOL);
00069 
00070 dbmp = dbenv->mp_handle;
00071 sp = NULL;
00072 
00073 /* Global statistics. */
00074 mp = dbmp->reginfo[0].primary;
00075 if (gspp != NULL) {
00076 *gspp = NULL;
00077 
00078 if ((ret = CDB___os_calloc(dbenv, 1, sizeof(**gspp), gspp)) != 0)
00079 return (ret);
00080 sp = *gspp;
00081 
00082 /*
00083  * Initialization and information that is not maintained on
00084  * a per-cache basis.
00085  */
00086 sp->st_hash_longest = 0;
00087 sp->st_region_wait = dbmp->reginfo[0].rp->mutex.mutex_set_wait;
00088 sp->st_region_nowait =
00089 dbmp->reginfo[0].rp->mutex.mutex_set_nowait;
00090 sp->st_gbytes = dbenv->mp_gbytes;
00091 sp->st_bytes = dbenv->mp_bytes;
00092 sp->st_ncache = dbmp->nreg;
00093 sp->st_regsize = dbmp->reginfo[0].rp->size;
00094 
00095 R_LOCK(dbenv, dbmp->reginfo);
00096 
00097 /* Walk the cache list and accumulate the global information. */
00098 for (i = 0; i < mp->nreg; ++i) {
00099 c_mp = dbmp->reginfo[i].primary;
00100 sp->st_cache_hit += c_mp->stat.st_cache_hit;
00101 sp->st_cache_miss += c_mp->stat.st_cache_miss;
00102 sp->st_map += c_mp->stat.st_map;
00103 sp->st_page_create += c_mp->stat.st_page_create;
00104 sp->st_page_in += c_mp->stat.st_page_in;
00105 sp->st_page_out += c_mp->stat.st_page_out;
00106 sp->st_ro_evict += c_mp->stat.st_ro_evict;
00107 sp->st_rw_evict += c_mp->stat.st_rw_evict;
00108 sp->st_hash_buckets += c_mp->stat.st_hash_buckets;
00109 sp->st_hash_searches += c_mp->stat.st_hash_searches;
00110 if (c_mp->stat.st_hash_longest > sp->st_hash_longest)
00111 sp->st_hash_longest =
00112 c_mp->stat.st_hash_longest;
00113 sp->st_hash_examined += c_mp->stat.st_hash_examined;
00114 sp->st_page_clean += c_mp->stat.st_page_clean;
00115 sp->st_page_dirty += c_mp->stat.st_page_dirty;
00116 sp->st_page_trickle += c_mp->stat.st_page_trickle;
00117 sp->st_region_wait += c_mp->stat.st_region_wait;
00118 sp->st_region_nowait += c_mp->stat.st_region_nowait;
00119 }
00120 
00121 R_UNLOCK(dbenv, dbmp->reginfo);
00122 }
00123 
00124 /* Per-file statistics. */
00125 if (fspp != NULL) {
00126 *fspp = NULL;
00127 
00128 R_LOCK(dbenv, dbmp->reginfo);
00129 
00130 /* Count the MPOOLFILE structures. */
00131 for (len = 0,
00132 mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
00133 mfp != NULL;
00134 ++len, mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile))
00135 ;
00136 
00137 R_UNLOCK(dbenv, dbmp->reginfo);
00138 
00139 if (len == 0)
00140 return (0);
00141 
00142 /* Allocate space for the pointers. */
00143 len = (len + 1) * sizeof(DB_MPOOL_FSTAT *);
00144 if ((ret = CDB___os_malloc(dbenv, len, db_malloc, fspp)) != 0)
00145 return (ret);
00146 
00147 R_LOCK(dbenv, dbmp->reginfo);
00148 
00149 /* Build each individual entry. */
00150 for (tfsp = *fspp,
00151 mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
00152 mfp != NULL;
00153 ++tfsp, mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
00154 name = CDB___memp_fns(dbmp, mfp);
00155 nlen = strlen(name);
00156 len = sizeof(DB_MPOOL_FSTAT) + nlen + 1;
00157 if ((ret =
00158 CDB___os_malloc(dbenv, len, db_malloc, tfsp)) != 0)
00159 return (ret);
00160 **tfsp = mfp->stat;
00161 (*tfsp)->file_name = (char *)
00162 (u_int8_t *)*tfsp + sizeof(DB_MPOOL_FSTAT);
00163 memcpy((*tfsp)->file_name, name, nlen + 1);
00164 
00165 /*
00166  * We have duplicate statistics fields in the cache
00167  * and per-file structures. The counters are only
00168  * incremented in the per-file structures, though.
00169  * The intent is that if we ever flush files from
00170  * the pool we can save their last known totals in
00171  * the cache structure.
00172  */
00173 if (sp != NULL) {
00174 sp->st_cache_hit += mfp->stat.st_cache_hit;
00175 sp->st_cache_miss += mfp->stat.st_cache_miss;
00176 sp->st_map += mfp->stat.st_map;
00177 sp->st_page_create += mfp->stat.st_page_create;
00178 sp->st_page_in += mfp->stat.st_page_in;
00179 sp->st_page_out += mfp->stat.st_page_out;
00180 }
00181 }
00182 *tfsp = NULL;
00183 
00184 R_UNLOCK(dbenv, dbmp->reginfo);
00185 }
00186 return (0);
00187 }
00188 
00189 #define FMAP_ENTRIES 200 /* Files we map. */
00190 
00191 #define MPOOL_DUMP_HASH 0x01 /* Debug hash chains. */
00192 #define MPOOL_DUMP_LRU 0x02 /* Debug LRU chains. */
00193 #define MPOOL_DUMP_MEM 0x04 /* Debug region memory. */
00194 #define MPOOL_DUMP_ALL 0x07 /* Debug all. */
00195 
00196 /*
00197  * CDB___memp_dump_region --
00198  * Display MPOOL structures.
00199  *
00200  * PUBLIC: void CDB___memp_dump_region __P((DB_ENV *, char *, FILE *));
00201  */
00202 void
00203 CDB___memp_dump_region(dbenv, area, fp)
00204 DB_ENV *dbenv;
00205 char *area;
00206 FILE *fp;
00207 {
00208 DB_MPOOL *dbmp;
00209 DB_MPOOLFILE *dbmfp;
00210 MPOOL *mp;
00211 MPOOLFILE *mfp;
00212 size_t fmap[FMAP_ENTRIES + 1];
00213 u_int32_t i, flags;
00214 int cnt;
00215 u_int8_t *p;
00216 
00217 dbmp = dbenv->mp_handle;
00218 
00219 /* Make it easy to call from the debugger. */
00220 if (fp == NULL)
00221 fp = stderr;
00222 
00223 for (flags = 0; *area != '0円'; ++area)
00224 switch (*area) {
00225 case 'A':
00226 LF_SET(MPOOL_DUMP_ALL);
00227 break;
00228 case 'h':
00229 LF_SET(MPOOL_DUMP_HASH);
00230 break;
00231 case 'l':
00232 LF_SET(MPOOL_DUMP_LRU);
00233 break;
00234 case 'm':
00235 LF_SET(MPOOL_DUMP_MEM);
00236 break;
00237 }
00238 
00239 R_LOCK(dbenv, dbmp->reginfo);
00240 
00241 mp = dbmp->reginfo[0].primary;
00242 
00243 /* Display MPOOL structures. */
00244 (void)fprintf(fp, "%s\nPool (region addr 0x%lx)\n",
00245 DB_LINE, (u_long)dbmp->reginfo[0].addr);
00246 
00247 /* Display the MPOOLFILE structures. */
00248 cnt = 0;
00249 for (mfp = SH_TAILQ_FIRST(&mp->mpfq, __mpoolfile);
00250 mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile), ++cnt) {
00251 (void)fprintf(fp, "File #%d: %s: type %ld, %s\n\t [UID: ",
00252 cnt + 1, CDB___memp_fns(dbmp, mfp), (long)mfp->ftype,
00253 F_ISSET(mfp, MP_CAN_MMAP) ? "mmap" : "read/write");
00254 p = R_ADDR(dbmp->reginfo, mfp->fileid_off);
00255 for (i = 0; i < DB_FILE_ID_LEN; ++i) {
00256 (void)fprintf(fp, "%x", *p++);
00257 if (i < DB_FILE_ID_LEN - 1)
00258 (void)fprintf(fp, " ");
00259 }
00260 (void)fprintf(fp, "]\n");
00261 if (cnt < FMAP_ENTRIES)
00262 fmap[cnt] = R_OFFSET(dbmp->reginfo, mfp);
00263 }
00264 
00265 for (dbmfp = TAILQ_FIRST(&dbmp->dbmfq);
00266 dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q), ++cnt) {
00267 (void)fprintf(fp, "File #%d: %s: per-process, %s\n",
00268 cnt + 1, CDB___memp_fn(dbmfp),
00269 F_ISSET(dbmfp, MP_READONLY) ? "readonly" : "read/write");
00270 if (cnt < FMAP_ENTRIES)
00271 fmap[cnt] = R_OFFSET(dbmp->reginfo, mfp);
00272 }
00273 if (cnt < FMAP_ENTRIES)
00274 fmap[cnt] = INVALID_ROFF;
00275 else
00276 fmap[FMAP_ENTRIES] = INVALID_ROFF;
00277 
00278 /* Dump the memory pools. */
00279 for (i = 0; i < mp->nreg; ++i) {
00280 (void)fprintf(fp, "%s\nCache #%d:\n", DB_LINE, i + 1);
00281 __memp_dumpcache(dbmp, &dbmp->reginfo[i], fmap, fp, flags);
00282 }
00283 
00284 R_UNLOCK(dbenv, dbmp->reginfo);
00285 
00286 /* Flush in case we're debugging. */
00287 (void)fflush(fp);
00288 }
00289 
00290 /*
00291  * __memp_dumpcache --
00292  * Display statistics for a cache.
00293  */
00294 static void
00295 __memp_dumpcache(dbmp, reginfo, fmap, fp, flags)
00296 DB_MPOOL *dbmp;
00297 REGINFO *reginfo;
00298 size_t *fmap;
00299 FILE *fp;
00300 u_int32_t flags;
00301 {
00302 BH *bhp;
00303 DB_HASHTAB *dbht;
00304 MPOOL *c_mp;
00305 int bucket;
00306 
00307 c_mp = reginfo->primary;
00308 
00309 /* Display the hash table list of BH's. */
00310 if (LF_ISSET(MPOOL_DUMP_HASH)) {
00311 (void)fprintf(fp,
00312 "%s\nBH hash table (%lu hash slots)\npageno, file, ref, address\n",
00313 DB_LINE, (u_long)c_mp->htab_buckets);
00314 for (dbht = R_ADDR(reginfo, c_mp->htab),
00315 bucket = 0; bucket < c_mp->htab_buckets; ++dbht, ++bucket) {
00316 if (SH_TAILQ_FIRST(dbht, __bh) != NULL)
00317 (void)fprintf(fp, "%lu:\n", (u_long)bucket);
00318 for (bhp = SH_TAILQ_FIRST(dbht, __bh);
00319 bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh))
00320 __memp_pbh(dbmp, bhp, fmap, fp);
00321 }
00322 }
00323 
00324 /* Display the LRU list of BH's. */
00325 if (LF_ISSET(MPOOL_DUMP_LRU)) {
00326 (void)fprintf(fp, "%s\nBH LRU list\n", DB_LINE);
00327 (void)fprintf(fp, "pageno, file, ref, address\n");
00328 for (bhp = SH_TAILQ_FIRST(&c_mp->bhq, __bh);
00329 bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, q, __bh))
00330 __memp_pbh(dbmp, bhp, fmap, fp);
00331 }
00332 
00333 /* Dump the memory pool. */
00334 if (LF_ISSET(MPOOL_DUMP_MEM))
00335 CDB___db_shalloc_dump(reginfo->addr, fp);
00336 }
00337 
00338 /*
00339  * __memp_pbh --
00340  * Display a BH structure.
00341  */
00342 static void
00343 __memp_pbh(dbmp, bhp, fmap, fp)
00344 DB_MPOOL *dbmp;
00345 BH *bhp;
00346 size_t *fmap;
00347 FILE *fp;
00348 {
00349 static const FN fn[] = {
00350 { BH_CALLPGIN, "callpgin" },
00351 { BH_DIRTY, "dirty" },
00352 { BH_DISCARD, "discard" },
00353 { BH_LOCKED, "locked" },
00354 { BH_TRASH, "trash" },
00355 { BH_WRITE, "write" },
00356 { 0, NULL }
00357 };
00358 int i;
00359 
00360 for (i = 0; i < FMAP_ENTRIES; ++i)
00361 if (fmap[i] == INVALID_ROFF || fmap[i] == bhp->mf_offset)
00362 break;
00363 
00364 if (fmap[i] == INVALID_ROFF)
00365 (void)fprintf(fp, " %4lu, %lu, %2lu, %lu",
00366 (u_long)bhp->pgno, (u_long)bhp->mf_offset,
00367 (u_long)bhp->ref, (u_long)R_OFFSET(dbmp->reginfo, bhp));
00368 else
00369 (void)fprintf(fp, " %4lu, #%d, %2lu, %lu",
00370 (u_long)bhp->pgno, i + 1,
00371 (u_long)bhp->ref, (u_long)R_OFFSET(dbmp->reginfo, bhp));
00372 
00373 CDB___db_prflags(bhp->flags, fn, fp);
00374 
00375 (void)fprintf(fp, "\n");
00376 }

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

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