00001
00002
00003
00004
00005
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
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
00043
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
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
00084
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
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
00125 if (fspp != NULL) {
00126 *fspp = NULL;
00127
00128 R_LOCK(dbenv, dbmp->reginfo);
00129
00130
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
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
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
00167
00168
00169
00170
00171
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
00190
00191 #define MPOOL_DUMP_HASH 0x01
00192 #define MPOOL_DUMP_LRU 0x02
00193 #define MPOOL_DUMP_MEM 0x04
00194 #define MPOOL_DUMP_ALL 0x07
00195
00196
00197
00198
00199
00200
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
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
00244 (void)fprintf(fp, "%s\nPool (region addr 0x%lx)\n",
00245 DB_LINE, (u_long)dbmp->reginfo[0].addr);
00246
00247
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
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
00287 (void)fflush(fp);
00288 }
00289
00290
00291
00292
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
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
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
00334 if (LF_ISSET(MPOOL_DUMP_MEM))
00335 CDB___db_shalloc_dump(reginfo->addr, fp);
00336 }
00337
00338
00339
00340
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 }