2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 1996, 1997, 1998
5 * Sleepycat Software. All rights reserved.
10 static const char sccsid
[] = "@(#)mp_pr.c 10.30 (Sleepycat) 10/1/98";
13 #ifndef NO_SYSTEM_INCLUDES
14 #include <sys/types.h>
29 #include "common_ext.h"
31 static void __memp_pbh
__P((DB_MPOOL
*, BH
*, size_t *, FILE *));
35 * Display MPOOL statistics.
38 memp_stat(dbmp
, gspp
, fspp
, db_malloc
)
41 DB_MPOOL_FSTAT
***fspp
;
42 void *(*db_malloc
) __P((size_t));
44 DB_MPOOL_FSTAT
**tfsp
;
52 /* Allocate space for the global statistics. */
56 if ((ret
= __os_malloc(sizeof(**gspp
), db_malloc
, gspp
)) != 0)
61 /* Copy out the global statistics. */
62 **gspp
= dbmp
->mp
->stat
;
63 (*gspp
)->st_hash_buckets
= dbmp
->mp
->htab_buckets
;
64 (*gspp
)->st_region_wait
=
65 dbmp
->mp
->rlayout
.lock
.mutex_set_wait
;
66 (*gspp
)->st_region_nowait
=
67 dbmp
->mp
->rlayout
.lock
.mutex_set_nowait
;
68 (*gspp
)->st_refcnt
= dbmp
->mp
->rlayout
.refcnt
;
69 (*gspp
)->st_regsize
= dbmp
->mp
->rlayout
.size
;
79 /* Count the MPOOLFILE structures. */
81 mfp
= SH_TAILQ_FIRST(&dbmp
->mp
->mpfq
, __mpoolfile
);
83 ++len
, mfp
= SH_TAILQ_NEXT(mfp
, q
, __mpoolfile
))
91 /* Allocate space for the pointers. */
92 len
= (len
+ 1) * sizeof(DB_MPOOL_FSTAT
*);
93 if ((ret
= __os_malloc(len
, db_malloc
, fspp
)) != 0)
98 /* Build each individual entry. */
100 mfp
= SH_TAILQ_FIRST(&dbmp
->mp
->mpfq
, __mpoolfile
);
102 ++tfsp
, mfp
= SH_TAILQ_NEXT(mfp
, q
, __mpoolfile
)) {
103 name
= __memp_fns(dbmp
, mfp
);
105 len
= sizeof(DB_MPOOL_FSTAT
) + nlen
+ 1;
106 if ((ret
= __os_malloc(len
, db_malloc
, tfsp
)) != 0)
109 (*tfsp
)->file_name
= (char *)
110 (u_int8_t
*)*tfsp
+ sizeof(DB_MPOOL_FSTAT
);
111 memcpy((*tfsp
)->file_name
, name
, nlen
+ 1);
122 * On errors we print whatever is available as the file name.
124 * PUBLIC: char * __memp_fn __P((DB_MPOOLFILE *));
130 return (__memp_fns(dbmfp
->dbmp
, dbmfp
->mfp
));
135 * On errors we print whatever is available as the file name.
137 * PUBLIC: char * __memp_fns __P((DB_MPOOL *, MPOOLFILE *));
141 __memp_fns(dbmp
, mfp
)
145 if (mfp
->path_off
== 0)
146 return ((char *)"temporary");
148 return ((char *)R_ADDR(dbmp
, mfp
->path_off
));
151 #define FMAP_ENTRIES 200 /* Files we map. */
153 #define MPOOL_DUMP_HASH 0x01 /* Debug hash chains. */
154 #define MPOOL_DUMP_LRU 0x02 /* Debug LRU chains. */
155 #define MPOOL_DUMP_MEM 0x04 /* Debug region memory. */
156 #define MPOOL_DUMP_ALL 0x07 /* Debug all. */
160 * __memp_dump_region --
161 * Display MPOOL structures.
163 * PUBLIC: void __memp_dump_region __P((DB_MPOOL *, char *, FILE *));
166 __memp_dump_region(dbmp
, area
, fp
)
176 size_t bucket
, fmap
[FMAP_ENTRIES
+ 1];
180 /* Make it easy to call from the debugger. */
184 for (flags
= 0; *area
!= '\0'; ++area
)
187 LF_SET(MPOOL_DUMP_ALL
);
190 LF_SET(MPOOL_DUMP_HASH
);
193 LF_SET(MPOOL_DUMP_LRU
);
196 LF_SET(MPOOL_DUMP_MEM
);
204 /* Display MPOOL structures. */
205 (void)fprintf(fp
, "%s\nPool (region addr 0x%lx, alloc addr 0x%lx)\n",
206 DB_LINE
, (u_long
)dbmp
->reginfo
.addr
, (u_long
)dbmp
->addr
);
208 /* Display the MPOOLFILE structures. */
210 for (mfp
= SH_TAILQ_FIRST(&dbmp
->mp
->mpfq
, __mpoolfile
);
211 mfp
!= NULL
; mfp
= SH_TAILQ_NEXT(mfp
, q
, __mpoolfile
), ++cnt
) {
212 (void)fprintf(fp
, "file #%d: %s: refs %lu, type %ld, %s\n",
213 cnt
+ 1, __memp_fns(dbmp
, mfp
), (u_long
)mfp
->ref
,
215 F_ISSET(mfp
, MP_CAN_MMAP
) ? "mmap" : "read/write");
216 if (cnt
< FMAP_ENTRIES
)
217 fmap
[cnt
] = R_OFFSET(dbmp
, mfp
);
220 for (dbmfp
= TAILQ_FIRST(&dbmp
->dbmfq
);
221 dbmfp
!= NULL
; dbmfp
= TAILQ_NEXT(dbmfp
, q
), ++cnt
) {
222 (void)fprintf(fp
, "file #%d: %s: fd: %d: per-process, %s\n",
223 cnt
+ 1, __memp_fn(dbmfp
), dbmfp
->fd
,
224 F_ISSET(dbmfp
, MP_READONLY
) ? "readonly" : "read/write");
225 if (cnt
< FMAP_ENTRIES
)
226 fmap
[cnt
] = R_OFFSET(dbmp
, mfp
);
228 if (cnt
< FMAP_ENTRIES
)
231 fmap
[FMAP_ENTRIES
] = INVALID
;
233 /* Display the hash table list of BH's. */
234 if (LF_ISSET(MPOOL_DUMP_HASH
)) {
236 "%s\nBH hash table (%lu hash slots)\npageno, file, ref, address\n",
237 DB_LINE
, (u_long
)mp
->htab_buckets
);
238 for (htabp
= dbmp
->htab
,
239 bucket
= 0; bucket
< mp
->htab_buckets
; ++htabp
, ++bucket
) {
240 if (SH_TAILQ_FIRST(&dbmp
->htab
[bucket
], __bh
) != NULL
)
241 (void)fprintf(fp
, "%lu:\n", (u_long
)bucket
);
242 for (bhp
= SH_TAILQ_FIRST(&dbmp
->htab
[bucket
], __bh
);
243 bhp
!= NULL
; bhp
= SH_TAILQ_NEXT(bhp
, hq
, __bh
))
244 __memp_pbh(dbmp
, bhp
, fmap
, fp
);
248 /* Display the LRU list of BH's. */
249 if (LF_ISSET(MPOOL_DUMP_LRU
)) {
250 (void)fprintf(fp
, "%s\nBH LRU list\n", DB_LINE
);
251 (void)fprintf(fp
, "pageno, file, ref, address\n");
252 for (bhp
= SH_TAILQ_FIRST(&dbmp
->mp
->bhq
, __bh
);
253 bhp
!= NULL
; bhp
= SH_TAILQ_NEXT(bhp
, q
, __bh
))
254 __memp_pbh(dbmp
, bhp
, fmap
, fp
);
257 if (LF_ISSET(MPOOL_DUMP_MEM
))
258 __db_shalloc_dump(dbmp
->addr
, fp
);
262 /* Flush in case we're debugging. */
268 * Display a BH structure.
271 __memp_pbh(dbmp
, bhp
, fmap
, fp
)
277 static const FN fn
[] = {
278 { BH_CALLPGIN
, "callpgin" },
279 { BH_DIRTY
, "dirty" },
280 { BH_DISCARD
, "discard" },
281 { BH_LOCKED
, "locked" },
282 { BH_TRASH
, "trash" },
283 { BH_WRITE
, "write" },
288 for (i
= 0; i
< FMAP_ENTRIES
; ++i
)
289 if (fmap
[i
] == INVALID
|| fmap
[i
] == bhp
->mf_offset
)
292 if (fmap
[i
] == INVALID
)
293 (void)fprintf(fp
, " %4lu, %lu, %2lu, %lu",
294 (u_long
)bhp
->pgno
, (u_long
)bhp
->mf_offset
,
295 (u_long
)bhp
->ref
, (u_long
)R_OFFSET(dbmp
, bhp
));
297 (void)fprintf(fp
, " %4lu, #%d, %2lu, %lu",
298 (u_long
)bhp
->pgno
, i
+ 1,
299 (u_long
)bhp
->ref
, (u_long
)R_OFFSET(dbmp
, bhp
));
301 __db_prflags(bhp
->flags
, fn
, fp
);
303 (void)fprintf(fp
, "\n");