Update.
[glibc.git] / db2 / mp / mp_pr.c
blobe83e0f44fa0d99d86ae77a47ef898e42f872938c
1 /*-
2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 1996, 1997, 1998
5 * Sleepycat Software. All rights reserved.
6 */
7 #include "config.h"
9 #ifndef lint
10 static const char sccsid[] = "@(#)mp_pr.c 10.26 (Sleepycat) 5/23/98";
11 #endif /* not lint */
13 #ifndef NO_SYSTEM_INCLUDES
14 #include <sys/types.h>
16 #include <errno.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <unistd.h>
20 #endif
22 #include "db_int.h"
23 #include "db_page.h"
24 #include "shqueue.h"
25 #include "db_shash.h"
26 #include "mp.h"
27 #include "db_auto.h"
28 #include "db_ext.h"
29 #include "common_ext.h"
31 static void __memp_pbh __P((DB_MPOOL *, BH *, size_t *, FILE *));
34 * memp_stat --
35 * Display MPOOL statistics.
37 int
38 memp_stat(dbmp, gspp, fspp, db_malloc)
39 DB_MPOOL *dbmp;
40 DB_MPOOL_STAT **gspp;
41 DB_MPOOL_FSTAT ***fspp;
42 void *(*db_malloc) __P((size_t));
44 DB_MPOOL_FSTAT **tfsp;
45 MPOOLFILE *mfp;
46 size_t len, nlen;
47 char *name;
49 /* Allocate space for the global statistics. */
50 if (gspp != NULL) {
51 *gspp = NULL;
53 if ((*gspp = db_malloc == NULL ?
54 (DB_MPOOL_STAT *)__db_malloc(sizeof(**gspp)) :
55 (DB_MPOOL_STAT *)db_malloc(sizeof(**gspp))) == NULL)
56 return (ENOMEM);
58 LOCKREGION(dbmp);
60 /* Copy out the global statistics. */
61 **gspp = dbmp->mp->stat;
62 (*gspp)->st_hash_buckets = dbmp->mp->htab_buckets;
63 (*gspp)->st_region_wait =
64 dbmp->mp->rlayout.lock.mutex_set_wait;
65 (*gspp)->st_region_nowait =
66 dbmp->mp->rlayout.lock.mutex_set_nowait;
67 (*gspp)->st_refcnt = dbmp->mp->rlayout.refcnt;
68 (*gspp)->st_regsize = dbmp->mp->rlayout.size;
70 UNLOCKREGION(dbmp);
73 if (fspp != NULL) {
74 *fspp = NULL;
76 LOCKREGION(dbmp);
78 /* Count the MPOOLFILE structures. */
79 for (len = 0,
80 mfp = SH_TAILQ_FIRST(&dbmp->mp->mpfq, __mpoolfile);
81 mfp != NULL;
82 ++len, mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile))
85 UNLOCKREGION(dbmp);
87 if (len == 0)
88 return (0);
90 /* Allocate space for the pointers. */
91 len = (len + 1) * sizeof(DB_MPOOL_FSTAT *);
92 if ((*fspp = db_malloc == NULL ?
93 (DB_MPOOL_FSTAT **)__db_malloc(len) :
94 (DB_MPOOL_FSTAT **)db_malloc(len)) == NULL)
95 return (ENOMEM);
97 LOCKREGION(dbmp);
99 /* Build each individual entry. */
100 for (tfsp = *fspp,
101 mfp = SH_TAILQ_FIRST(&dbmp->mp->mpfq, __mpoolfile);
102 mfp != NULL;
103 ++tfsp, mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile)) {
104 name = __memp_fns(dbmp, mfp);
105 nlen = strlen(name);
106 len = sizeof(DB_MPOOL_FSTAT) + nlen + 1;
107 if ((*tfsp = db_malloc == NULL ?
108 (DB_MPOOL_FSTAT *)__db_malloc(len) :
109 (DB_MPOOL_FSTAT *)db_malloc(len)) == NULL)
110 return (ENOMEM);
111 **tfsp = mfp->stat;
112 (*tfsp)->file_name = (char *)
113 (u_int8_t *)*tfsp + sizeof(DB_MPOOL_FSTAT);
114 memcpy((*tfsp)->file_name, name, nlen + 1);
116 *tfsp = NULL;
118 UNLOCKREGION(dbmp);
120 return (0);
124 * __memp_fn --
125 * On errors we print whatever is available as the file name.
127 * PUBLIC: char * __memp_fn __P((DB_MPOOLFILE *));
129 char *
130 __memp_fn(dbmfp)
131 DB_MPOOLFILE *dbmfp;
133 return (__memp_fns(dbmfp->dbmp, dbmfp->mfp));
137 * __memp_fns --
138 * On errors we print whatever is available as the file name.
140 * PUBLIC: char * __memp_fns __P((DB_MPOOL *, MPOOLFILE *));
143 char *
144 __memp_fns(dbmp, mfp)
145 DB_MPOOL *dbmp;
146 MPOOLFILE *mfp;
148 if (mfp->path_off == 0)
149 return ((char *)"temporary");
151 return ((char *)R_ADDR(dbmp, mfp->path_off));
154 #define FMAP_ENTRIES 200 /* Files we map. */
156 #define MPOOL_DUMP_HASH 0x01 /* Debug hash chains. */
157 #define MPOOL_DUMP_LRU 0x02 /* Debug LRU chains. */
158 #define MPOOL_DUMP_MEM 0x04 /* Debug region memory. */
159 #define MPOOL_DUMP_ALL 0x07 /* Debug all. */
163 * __memp_dump_region --
164 * Display MPOOL structures.
166 * PUBLIC: void __memp_dump_region __P((DB_MPOOL *, char *, FILE *));
168 void
169 __memp_dump_region(dbmp, area, fp)
170 DB_MPOOL *dbmp;
171 char *area;
172 FILE *fp;
174 BH *bhp;
175 DB_HASHTAB *htabp;
176 DB_MPOOLFILE *dbmfp;
177 MPOOL *mp;
178 MPOOLFILE *mfp;
179 size_t bucket, fmap[FMAP_ENTRIES + 1];
180 u_int32_t flags;
181 int cnt;
183 /* Make it easy to call from the debugger. */
184 if (fp == NULL)
185 fp = stderr;
187 for (flags = 0; *area != '\0'; ++area)
188 switch (*area) {
189 case 'A':
190 LF_SET(MPOOL_DUMP_ALL);
191 break;
192 case 'h':
193 LF_SET(MPOOL_DUMP_HASH);
194 break;
195 case 'l':
196 LF_SET(MPOOL_DUMP_LRU);
197 break;
198 case 'm':
199 LF_SET(MPOOL_DUMP_MEM);
200 break;
203 LOCKREGION(dbmp);
205 mp = dbmp->mp;
207 /* Display MPOOL structures. */
208 (void)fprintf(fp, "%s\nPool (region addr 0x%lx, alloc addr 0x%lx)\n",
209 DB_LINE, (u_long)dbmp->reginfo.addr, (u_long)dbmp->addr);
211 /* Display the MPOOLFILE structures. */
212 cnt = 0;
213 for (mfp = SH_TAILQ_FIRST(&dbmp->mp->mpfq, __mpoolfile);
214 mfp != NULL; mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile), ++cnt) {
215 (void)fprintf(fp, "file #%d: %s: %lu references: %s\n",
216 cnt + 1, __memp_fns(dbmp, mfp), (u_long)mfp->ref,
217 F_ISSET(mfp, MP_CAN_MMAP) ? "mmap" : "read/write");
218 if (cnt < FMAP_ENTRIES)
219 fmap[cnt] = R_OFFSET(dbmp, mfp);
222 for (dbmfp = TAILQ_FIRST(&dbmp->dbmfq);
223 dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q), ++cnt) {
224 (void)fprintf(fp, "file #%d: %s: fd: %d: per-process, %s\n",
225 cnt + 1, __memp_fn(dbmfp), dbmfp->fd,
226 F_ISSET(dbmfp, MP_READONLY) ? "readonly" : "read/write");
227 if (cnt < FMAP_ENTRIES)
228 fmap[cnt] = R_OFFSET(dbmp, mfp);
230 if (cnt < FMAP_ENTRIES)
231 fmap[cnt] = INVALID;
232 else
233 fmap[FMAP_ENTRIES] = INVALID;
235 /* Display the hash table list of BH's. */
236 if (LF_ISSET(MPOOL_DUMP_HASH)) {
237 (void)fprintf(fp,
238 "%s\nBH hash table (%lu hash slots)\npageno, file, ref, address\n",
239 DB_LINE, (u_long)mp->htab_buckets);
240 for (htabp = dbmp->htab,
241 bucket = 0; bucket < mp->htab_buckets; ++htabp, ++bucket) {
242 if (SH_TAILQ_FIRST(&dbmp->htab[bucket], __bh) != NULL)
243 (void)fprintf(fp, "%lu:\n", (u_long)bucket);
244 for (bhp = SH_TAILQ_FIRST(&dbmp->htab[bucket], __bh);
245 bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh))
246 __memp_pbh(dbmp, bhp, fmap, fp);
250 /* Display the LRU list of BH's. */
251 if (LF_ISSET(MPOOL_DUMP_LRU)) {
252 (void)fprintf(fp, "%s\nBH LRU list\n", DB_LINE);
253 (void)fprintf(fp, "pageno, file, ref, address\n");
254 for (bhp = SH_TAILQ_FIRST(&dbmp->mp->bhq, __bh);
255 bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, q, __bh))
256 __memp_pbh(dbmp, bhp, fmap, fp);
259 if (LF_ISSET(MPOOL_DUMP_MEM))
260 __db_shalloc_dump(dbmp->addr, fp);
262 UNLOCKREGION(dbmp);
264 /* Flush in case we're debugging. */
265 (void)fflush(fp);
269 * __memp_pbh --
270 * Display a BH structure.
272 static void
273 __memp_pbh(dbmp, bhp, fmap, fp)
274 DB_MPOOL *dbmp;
275 BH *bhp;
276 size_t *fmap;
277 FILE *fp;
279 static const FN fn[] = {
280 { BH_CALLPGIN, "callpgin" },
281 { BH_DIRTY, "dirty" },
282 { BH_DISCARD, "discard" },
283 { BH_LOCKED, "locked" },
284 { BH_TRASH, "trash" },
285 { BH_WRITE, "write" },
286 { 0 },
288 int i;
290 for (i = 0; i < FMAP_ENTRIES; ++i)
291 if (fmap[i] == INVALID || fmap[i] == bhp->mf_offset)
292 break;
294 if (fmap[i] == INVALID)
295 (void)fprintf(fp, " %4lu, %lu, %2lu, %lu",
296 (u_long)bhp->pgno, (u_long)bhp->mf_offset,
297 (u_long)bhp->ref, (u_long)R_OFFSET(dbmp, bhp));
298 else
299 (void)fprintf(fp, " %4lu, #%d, %2lu, %lu",
300 (u_long)bhp->pgno, i + 1,
301 (u_long)bhp->ref, (u_long)R_OFFSET(dbmp, bhp));
303 __db_prflags(bhp->flags, fn, fp);
305 (void)fprintf(fp, "\n");