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.26 (Sleepycat) 5/23/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
;
49 /* Allocate space for the global statistics. */
53 if ((*gspp
= db_malloc
== NULL
?
54 (DB_MPOOL_STAT
*)__db_malloc(sizeof(**gspp
)) :
55 (DB_MPOOL_STAT
*)db_malloc(sizeof(**gspp
))) == NULL
)
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
;
78 /* Count the MPOOLFILE structures. */
80 mfp
= SH_TAILQ_FIRST(&dbmp
->mp
->mpfq
, __mpoolfile
);
82 ++len
, mfp
= SH_TAILQ_NEXT(mfp
, q
, __mpoolfile
))
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
)
99 /* Build each individual entry. */
101 mfp
= SH_TAILQ_FIRST(&dbmp
->mp
->mpfq
, __mpoolfile
);
103 ++tfsp
, mfp
= SH_TAILQ_NEXT(mfp
, q
, __mpoolfile
)) {
104 name
= __memp_fns(dbmp
, mfp
);
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
)
112 (*tfsp
)->file_name
= (char *)
113 (u_int8_t
*)*tfsp
+ sizeof(DB_MPOOL_FSTAT
);
114 memcpy((*tfsp
)->file_name
, name
, nlen
+ 1);
125 * On errors we print whatever is available as the file name.
127 * PUBLIC: char * __memp_fn __P((DB_MPOOLFILE *));
133 return (__memp_fns(dbmfp
->dbmp
, dbmfp
->mfp
));
138 * On errors we print whatever is available as the file name.
140 * PUBLIC: char * __memp_fns __P((DB_MPOOL *, MPOOLFILE *));
144 __memp_fns(dbmp
, 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 *));
169 __memp_dump_region(dbmp
, area
, fp
)
179 size_t bucket
, fmap
[FMAP_ENTRIES
+ 1];
183 /* Make it easy to call from the debugger. */
187 for (flags
= 0; *area
!= '\0'; ++area
)
190 LF_SET(MPOOL_DUMP_ALL
);
193 LF_SET(MPOOL_DUMP_HASH
);
196 LF_SET(MPOOL_DUMP_LRU
);
199 LF_SET(MPOOL_DUMP_MEM
);
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. */
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
)
233 fmap
[FMAP_ENTRIES
] = INVALID
;
235 /* Display the hash table list of BH's. */
236 if (LF_ISSET(MPOOL_DUMP_HASH
)) {
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
);
264 /* Flush in case we're debugging. */
270 * Display a BH structure.
273 __memp_pbh(dbmp
, bhp
, fmap
, 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" },
290 for (i
= 0; i
< FMAP_ENTRIES
; ++i
)
291 if (fmap
[i
] == INVALID
|| fmap
[i
] == bhp
->mf_offset
)
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
));
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");