1/*
2 * $Id: bench.h,v 1.24 2008/02/04 14:13:05 bostic Exp $
3 */
4#ifndef _BENCH_H_
5#define	_BENCH_H_
6#include "db_config.h"
7
8#include "db_int.h"
9
10#if DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 5
11/*
12 * Older releases of Berkeley DB don't include standard include files in
13 * db_int.h.
14 */
15#ifdef DB_WIN32
16#define	WIN32_LEAN_AND_MEAN	1
17#include <windows.h>
18#include <direct.h>
19#include <sys/timeb.h>
20#else
21#include <sys/stat.h>
22#include <sys/time.h>
23
24#include <limits.h>
25#include <stdlib.h>
26#include <string.h>
27#include <unistd.h>
28#endif
29#endif
30
31#define	TESTDIR		"TESTDIR"
32#define	TESTFILE	"test_micro.db"
33
34/*
35 * Implement a custom assert to allow consistent behavior across builds and
36 * platforms.
37 *
38 * The BDB library DB_ASSERT implementation is only enabled in diagnostic
39 * builds -- so is not suitable here.
40 */
41#define	DB_BENCH_ASSERT(e) do {						\
42	(e) ? (void)0 :							\
43	    (fprintf(stderr,						\
44	    "assert failure: %s/%d: \"%s\"\n", __FILE__, __LINE__, #e),	\
45	    b_util_abort());						\
46} while (0)
47
48#ifndef	NS_PER_SEC
49#define	NS_PER_SEC	1000000000	/* Nanoseconds in a second */
50#endif
51#ifndef	NS_PER_US
52#define	NS_PER_US	1000		/* Nanoseconds in a microsecond */
53#endif
54#ifndef	MS_PER_NS
55#define	MS_PER_NS	1000000		/* Milliseconds in a nanosecond */
56#endif
57
58#ifdef DB_TIMEOUT_TO_TIMESPEC
59/*
60 * We have the timer routines in the Berkeley DB library after their conversion
61 * to the POSIX timespec interfaces.  We'd rather use something that gives us
62 * better information than elapsed wallclock time, so use getrusage instead if
63 * it's available.
64 */
65#ifdef HAVE_GETRUSAGE
66#include <sys/resource.h>
67
68#define	SET_TIMER_FROM_GETRUSAGE(tp) do {				\
69	struct rusage __usage;						\
70	DB_BENCH_ASSERT(getrusage(RUSAGE_SELF, &__usage) == 0);		\
71	(tp)->tv_sec =							\
72	    __usage.ru_utime.tv_sec + __usage.ru_stime.tv_sec;		\
73	(tp)->tv_nsec = NS_PER_US *					\
74	    (__usage.ru_utime.tv_usec + __usage.ru_stime.tv_usec);	\
75} while (0);
76
77#define	TIMER_START	SET_TIMER_FROM_GETRUSAGE(&__start_time);
78#define	TIMER_STOP	SET_TIMER_FROM_GETRUSAGE(&__end_time);
79
80#elif defined(DB_WIN32) && !defined(DB_WINCE)
81
82#define	SET_TIMER_FROM_GETPROCESSTIMES(tp) do {				\
83	FILETIME lpCreationTime, lpExitTime, lpKernelTime, lpUserTIme;	\
84	LARGE_INTEGER large_int;					\
85	LONGLONG __ns_since_epoch;					\
86	DB_BENCH_ASSERT(						\
87	    GetProcessTimes(GetCurrentProcess(), &lpCreationTime,	\
88	    &lpExitTime, &lpKernelTime, &lpUserTIme) != 0);		\
89	memcpy(&large_int, &lpKernelTime, sizeof(lpKernelTime));	\
90	__ns_since_epoch = (large_int.QuadPart * 100);			\
91	(tp)->tv_sec = (time_t)(__ns_since_epoch / NS_PER_SEC);		\
92	(tp)->tv_nsec = (long)(__ns_since_epoch % NS_PER_SEC);		\
93	memcpy(&large_int, &lpUserTIme, sizeof(lpUserTIme));		\
94	__ns_since_epoch = (large_int.QuadPart * 100);			\
95	(tp)->tv_sec += (time_t)(__ns_since_epoch / NS_PER_SEC);	\
96	(tp)->tv_nsec += (long)(__ns_since_epoch % NS_PER_SEC);		\
97} while (0);
98
99#define	TIMER_START	SET_TIMER_FROM_GETPROCESSTIMES(&__start_time);
100#define	TIMER_STOP	SET_TIMER_FROM_GETPROCESSTIMES(&__end_time);
101
102#else /* !HAVEGETRUSAGE && !DB_WIN32 */
103
104#if DB_VERSION_MAJOR > 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 6
105#define	TIMER_START	__os_gettime(NULL, &__start_time, 1)
106#define	TIMER_STOP	__os_gettime(NULL, &__end_time, 1)
107#else
108#define	TIMER_START	__os_gettime(NULL, &__start_time)
109#define	TIMER_STOP	__os_gettime(NULL, &__end_time)
110#endif
111#endif /* !HAVE_GETRUSAGE */
112
113#else /* !DB_TIMEOUT_TO_TIMESPEC */
114
115#if defined(HAVE_CLOCK_GETTIME)
116typedef struct timespec db_timespec;
117#else
118typedef struct {
119	time_t	tv_sec;				/* seconds */
120	long	tv_nsec;			/* nanoseconds */
121} db_timespec;
122#endif
123
124#define	timespecadd(vvp, uvp)						\
125	do {								\
126		(vvp)->tv_sec += (uvp)->tv_sec;				\
127		(vvp)->tv_nsec += (uvp)->tv_nsec;			\
128		if ((vvp)->tv_nsec >= NS_PER_SEC) {			\
129			(vvp)->tv_sec++;				\
130			(vvp)->tv_nsec -= NS_PER_SEC;			\
131		}							\
132	} while (0)
133#define	timespecsub(vvp, uvp)						\
134	do {								\
135		(vvp)->tv_sec -= (uvp)->tv_sec;				\
136		(vvp)->tv_nsec -= (uvp)->tv_nsec;			\
137		if ((vvp)->tv_nsec < 0) {				\
138			(vvp)->tv_sec--;				\
139			(vvp)->tv_nsec += NS_PER_SEC;			\
140		}							\
141	} while (0)
142
143#define	TIMER_START	CLOCK(__start_time)
144#define	TIMER_STOP	CLOCK(__end_time)
145
146#if defined(HAVE_CLOCK_GETTIME)
147#define	CLOCK(tm) do {							\
148	DB_BENCH_ASSERT(clock_gettime(					\
149	    CLOCK_REALTIME, (struct timespec *)&(tm)) == 0);		\
150} while (0)
151#elif defined(DB_WIN32)
152#define	CLOCK(tm) do {							\
153	struct _timeb __now;						\
154	_ftime(&__now);							\
155	(tm).tv_sec = __now.time;					\
156	(tm).tv_nsec = __now.millitm * MS_PER_NS;			\
157} while (0)
158#else
159#define	CLOCK(tm) do {							\
160	struct timeval __tp;						\
161	DB_BENCH_ASSERT(gettimeofday(&__tp, NULL) == 0);		\
162	(tm).tv_sec = __tp.tv_sec;					\
163	(tm).tv_nsec = __tp.tv_usec * NS_PER_US;			\
164} while (0)
165#endif
166#endif /* !DB_TIMEOUT_TO_TIMESPEC */
167
168db_timespec __start_time, __end_time;
169
170#define	TIMER_GET(tm) do {						\
171	tm = __end_time;						\
172	timespecsub(&(tm), &__start_time);				\
173} while (0)
174#define	TIMER_DISPLAY(ops) do {						\
175	db_timespec __tmp_time;						\
176	__tmp_time = __end_time;					\
177	timespecsub(&__tmp_time, &__start_time);			\
178	TIME_DISPLAY(ops, __tmp_time);					\
179} while (0)
180#define	TIME_DISPLAY(ops, tm) do {					\
181	double __secs;							\
182	int __major, __minor, __patch;					\
183	__secs = (tm).tv_sec + (double)(tm).tv_nsec / NS_PER_SEC;	\
184	(void)db_version(&__major, &__minor, &__patch);			\
185	printf("%d.%d.%d\t%.2f\n", __major, __minor, __patch,		\
186	    (__secs == 0) ? 0.0 : (ops) / __secs);			\
187} while (0)
188
189extern char *progname;					/* program name */
190
191int  b_curalloc __P((int, char *[]));
192int  b_curwalk __P((int, char *[]));
193int  b_del __P((int, char *[]));
194int  b_get __P((int, char *[]));
195int  b_inmem __P((int, char *[]));
196int  b_load __P((int, char *[]));
197int  b_open __P((int, char *[]));
198int  b_put __P((int, char *[]));
199int  b_recover __P((int, char *[]));
200int  b_txn __P((int, char *[]));
201int  b_txn_write __P((int, char *[]));
202int  b_uname __P((void));
203void b_util_abort __P((void));
204int  b_util_dir_setup __P((void));
205int  b_util_dir_teardown __P((void));
206int  b_util_have_hash __P((void));
207int  b_util_have_queue __P((void));
208int  b_util_unlink __P((char *));
209int  b_workload __P((int, char *[]));
210
211#endif /* !_BENCH_H_ */
212