1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 1996,2008 Oracle.  All rights reserved.
5 *
6 * $Id: log_stat.c,v 12.22 2008/01/08 20:58:41 bostic Exp $
7 */
8
9#include "db_config.h"
10
11#include "db_int.h"
12#include "dbinc/db_page.h"
13#include "dbinc/db_am.h"
14#include "dbinc/log.h"
15
16#ifdef HAVE_STATISTICS
17static int __log_print_all __P((ENV *, u_int32_t));
18static int __log_print_stats __P((ENV *, u_int32_t));
19static int __log_stat __P((ENV *, DB_LOG_STAT **, u_int32_t));
20
21/*
22 * __log_stat_pp --
23 *	DB_ENV->log_stat pre/post processing.
24 *
25 * PUBLIC: int __log_stat_pp __P((DB_ENV *, DB_LOG_STAT **, u_int32_t));
26 */
27int
28__log_stat_pp(dbenv, statp, flags)
29	DB_ENV *dbenv;
30	DB_LOG_STAT **statp;
31	u_int32_t flags;
32{
33	DB_THREAD_INFO *ip;
34	ENV *env;
35	int ret;
36
37	env = dbenv->env;
38
39	ENV_REQUIRES_CONFIG(env,
40	    env->lg_handle, "DB_ENV->log_stat", DB_INIT_LOG);
41
42	if ((ret = __db_fchk(env,
43	    "DB_ENV->log_stat", flags, DB_STAT_CLEAR)) != 0)
44		return (ret);
45
46	ENV_ENTER(env, ip);
47	REPLICATION_WRAP(env, (__log_stat(env, statp, flags)), 0, ret);
48	ENV_LEAVE(env, ip);
49	return (ret);
50}
51
52/*
53 * __log_stat --
54 *	DB_ENV->log_stat.
55 */
56static int
57__log_stat(env, statp, flags)
58	ENV *env;
59	DB_LOG_STAT **statp;
60	u_int32_t flags;
61{
62	DB_LOG *dblp;
63	DB_LOG_STAT *stats;
64	LOG *lp;
65	int ret;
66
67	*statp = NULL;
68
69	dblp = env->lg_handle;
70	lp = dblp->reginfo.primary;
71
72	if ((ret = __os_umalloc(env, sizeof(DB_LOG_STAT), &stats)) != 0)
73		return (ret);
74
75	/* Copy out the global statistics. */
76	LOG_SYSTEM_LOCK(env);
77	*stats = lp->stat;
78	if (LF_ISSET(DB_STAT_CLEAR))
79		memset(&lp->stat, 0, sizeof(lp->stat));
80
81	stats->st_magic = lp->persist.magic;
82	stats->st_version = lp->persist.version;
83	stats->st_mode = lp->filemode;
84	stats->st_lg_bsize = lp->buffer_size;
85	stats->st_lg_size = lp->log_nsize;
86
87	__mutex_set_wait_info(env, lp->mtx_region,
88	    &stats->st_region_wait, &stats->st_region_nowait);
89	if (LF_ISSET(DB_STAT_CLEAR | DB_STAT_SUBSYSTEM) == DB_STAT_CLEAR)
90		__mutex_clear(env, lp->mtx_region);
91	stats->st_regsize = dblp->reginfo.rp->size;
92
93	stats->st_cur_file = lp->lsn.file;
94	stats->st_cur_offset = lp->lsn.offset;
95	stats->st_disk_file = lp->s_lsn.file;
96	stats->st_disk_offset = lp->s_lsn.offset;
97
98	LOG_SYSTEM_UNLOCK(env);
99
100	*statp = stats;
101	return (0);
102}
103
104/*
105 * __log_stat_print_pp --
106 *	DB_ENV->log_stat_print pre/post processing.
107 *
108 * PUBLIC: int __log_stat_print_pp __P((DB_ENV *, u_int32_t));
109 */
110int
111__log_stat_print_pp(dbenv, flags)
112	DB_ENV *dbenv;
113	u_int32_t flags;
114{
115	DB_THREAD_INFO *ip;
116	ENV *env;
117	int ret;
118
119	env = dbenv->env;
120
121	ENV_REQUIRES_CONFIG(env,
122	    env->lg_handle, "DB_ENV->log_stat_print", DB_INIT_LOG);
123
124	if ((ret = __db_fchk(env, "DB_ENV->log_stat_print",
125	    flags, DB_STAT_ALL | DB_STAT_CLEAR)) != 0)
126		return (ret);
127
128	ENV_ENTER(env, ip);
129	REPLICATION_WRAP(env, (__log_stat_print(env, flags)), 0, ret);
130	ENV_LEAVE(env, ip);
131	return (ret);
132}
133
134/*
135 * __log_stat_print --
136 *	DB_ENV->log_stat_print method.
137 *
138 * PUBLIC: int __log_stat_print __P((ENV *, u_int32_t));
139 */
140int
141__log_stat_print(env, flags)
142	ENV *env;
143	u_int32_t flags;
144{
145	u_int32_t orig_flags;
146	int ret;
147
148	orig_flags = flags;
149	LF_CLR(DB_STAT_CLEAR | DB_STAT_SUBSYSTEM);
150	if (flags == 0 || LF_ISSET(DB_STAT_ALL)) {
151		ret = __log_print_stats(env, orig_flags);
152		if (flags == 0 || ret != 0)
153			return (ret);
154	}
155
156	if (LF_ISSET(DB_STAT_ALL) &&
157	    (ret = __log_print_all(env, orig_flags)) != 0)
158		return (ret);
159
160	return (0);
161}
162
163/*
164 * __log_print_stats --
165 *	Display default log region statistics.
166 */
167static int
168__log_print_stats(env, flags)
169	ENV *env;
170	u_int32_t flags;
171{
172	DB_LOG_STAT *sp;
173	int ret;
174
175	if ((ret = __log_stat(env, &sp, flags)) != 0)
176		return (ret);
177
178	if (LF_ISSET(DB_STAT_ALL))
179		__db_msg(env, "Default logging region information:");
180	STAT_HEX("Log magic number", sp->st_magic);
181	STAT_ULONG("Log version number", sp->st_version);
182	__db_dlbytes(env, "Log record cache size",
183	    (u_long)0, (u_long)0, (u_long)sp->st_lg_bsize);
184	__db_msg(env, "%#o\tLog file mode", sp->st_mode);
185	if (sp->st_lg_size % MEGABYTE == 0)
186		__db_msg(env, "%luMb\tCurrent log file size",
187		    (u_long)sp->st_lg_size / MEGABYTE);
188	else if (sp->st_lg_size % 1024 == 0)
189		__db_msg(env, "%luKb\tCurrent log file size",
190		    (u_long)sp->st_lg_size / 1024);
191	else
192		__db_msg(env, "%lu\tCurrent log file size",
193		    (u_long)sp->st_lg_size);
194	__db_dl(env, "Records entered into the log", (u_long)sp->st_record);
195	__db_dlbytes(env, "Log bytes written",
196	    (u_long)0, (u_long)sp->st_w_mbytes, (u_long)sp->st_w_bytes);
197	__db_dlbytes(env, "Log bytes written since last checkpoint",
198	    (u_long)0, (u_long)sp->st_wc_mbytes, (u_long)sp->st_wc_bytes);
199	__db_dl(env, "Total log file I/O writes", (u_long)sp->st_wcount);
200	__db_dl(env, "Total log file I/O writes due to overflow",
201	    (u_long)sp->st_wcount_fill);
202	__db_dl(env, "Total log file flushes", (u_long)sp->st_scount);
203	__db_dl(env, "Total log file I/O reads", (u_long)sp->st_rcount);
204	STAT_ULONG("Current log file number", sp->st_cur_file);
205	STAT_ULONG("Current log file offset", sp->st_cur_offset);
206	STAT_ULONG("On-disk log file number", sp->st_disk_file);
207	STAT_ULONG("On-disk log file offset", sp->st_disk_offset);
208
209	__db_dl(env,
210	    "Maximum commits in a log flush", (u_long)sp->st_maxcommitperflush);
211	__db_dl(env,
212	    "Minimum commits in a log flush", (u_long)sp->st_mincommitperflush);
213
214	__db_dlbytes(env, "Log region size",
215	    (u_long)0, (u_long)0, (u_long)sp->st_regsize);
216	__db_dl_pct(env,
217	    "The number of region locks that required waiting",
218	    (u_long)sp->st_region_wait, DB_PCT(sp->st_region_wait,
219	    sp->st_region_wait + sp->st_region_nowait), NULL);
220
221	__os_ufree(env, sp);
222
223	return (0);
224}
225
226/*
227 * __log_print_all --
228 *	Display debugging log region statistics.
229 */
230static int
231__log_print_all(env, flags)
232	ENV *env;
233	u_int32_t flags;
234{
235	static const FN fn[] = {
236		{ DBLOG_RECOVER,	"DBLOG_RECOVER" },
237		{ DBLOG_FORCE_OPEN,	"DBLOG_FORCE_OPEN" },
238		{ DBLOG_AUTOREMOVE,	"DBLOG_AUTOREMOVE"},
239		{ DBLOG_DIRECT,		"DBLOG_DIRECT"},
240		{ DBLOG_DSYNC,		"DBLOG_DSYNC"},
241		{ DBLOG_FORCE_OPEN,	"DBLOG_FORCE_OPEN"},
242		{ DBLOG_INMEMORY,	"DBLOG_INMEMORY"},
243		{ DBLOG_OPENFILES,	"DBLOG_OPENFILES"},
244		{ DBLOG_RECOVER,	"DBLOG_RECOVER"},
245		{ DBLOG_ZERO,		"DBLOG_ZERO"},
246		{ 0,			NULL }
247	};
248	DB_LOG *dblp;
249	LOG *lp;
250
251	dblp = env->lg_handle;
252	lp = (LOG *)dblp->reginfo.primary;
253
254	LOG_SYSTEM_LOCK(env);
255
256	__db_print_reginfo(env, &dblp->reginfo, "Log", flags);
257
258	__db_msg(env, "%s", DB_GLOBAL(db_line));
259	__db_msg(env, "DB_LOG handle information:");
260	__mutex_print_debug_single(
261	    env, "DB_LOG handle mutex", dblp->mtx_dbreg, flags);
262	STAT_ULONG("Log file name", dblp->lfname);
263	__db_print_fh(env, "Log file handle", dblp->lfhp, flags);
264	__db_prflags(env, NULL, dblp->flags, fn, NULL, "\tFlags");
265
266	__db_msg(env, "%s", DB_GLOBAL(db_line));
267	__db_msg(env, "LOG handle information:");
268	__mutex_print_debug_single(
269	    env, "LOG region mutex", lp->mtx_region, flags);
270	__mutex_print_debug_single(
271	    env, "File name list mutex", lp->mtx_filelist, flags);
272
273	STAT_HEX("persist.magic", lp->persist.magic);
274	STAT_ULONG("persist.version", lp->persist.version);
275	__db_dlbytes(env,
276	    "persist.log_size", (u_long)0, (u_long)0, lp->persist.log_size);
277	STAT_FMT("log file permissions mode", "%#lo", u_long, lp->filemode);
278	STAT_LSN("current file offset LSN", &lp->lsn);
279	STAT_LSN("first buffer byte LSN", &lp->lsn);
280	STAT_ULONG("current buffer offset", lp->b_off);
281	STAT_ULONG("current file write offset", lp->w_off);
282	STAT_ULONG("length of last record", lp->len);
283	STAT_LONG("log flush in progress", lp->in_flush);
284	__mutex_print_debug_single(
285	    env, "Log flush mutex", lp->mtx_flush, flags);
286
287	STAT_LSN("last sync LSN", &lp->s_lsn);
288
289	/*
290	 * Don't display the replication fields here, they're displayed as part
291	 * of the replication statistics.
292	 */
293
294	STAT_LSN("cached checkpoint LSN", &lp->cached_ckp_lsn);
295
296	__db_dlbytes(env,
297	    "log buffer size", (u_long)0, (u_long)0, lp->buffer_size);
298	__db_dlbytes(env,
299	    "log file size", (u_long)0, (u_long)0, lp->log_size);
300	__db_dlbytes(env,
301	    "next log file size", (u_long)0, (u_long)0, lp->log_nsize);
302
303	STAT_ULONG("transactions waiting to commit", lp->ncommit);
304	STAT_LSN("LSN of first commit", &lp->t_lsn);
305
306	LOG_SYSTEM_UNLOCK(env);
307
308	return (0);
309}
310
311#else /* !HAVE_STATISTICS */
312
313int
314__log_stat_pp(dbenv, statp, flags)
315	DB_ENV *dbenv;
316	DB_LOG_STAT **statp;
317	u_int32_t flags;
318{
319	COMPQUIET(statp, NULL);
320	COMPQUIET(flags, 0);
321
322	return (__db_stat_not_built(dbenv->env));
323}
324
325int
326__log_stat_print_pp(dbenv, flags)
327	DB_ENV *dbenv;
328	u_int32_t flags;
329{
330	COMPQUIET(flags, 0);
331
332	return (__db_stat_not_built(dbenv->env));
333}
334#endif
335