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