1/*
2 * $Id: b_workload.h,v 1.9 2008/04/14 02:21:47 david Exp $
3 */
4
5/*
6 * Macros to help with initializing/assigning key dbts
7 */
8
9#define KBUF_LEN 12
10#define	INIT_KEY(key, config) do {				\
11	memset(&key, 0, sizeof(key));				\
12	if (config->orderedkeys) {				\
13		key.size = sizeof (u_int32_t);			\
14	} else if (config->ksize != 0) {			\
15		DB_BENCH_ASSERT(				\
16		    (key.data = malloc(key.size = config->ksize)) != NULL); \
17	} else {						\
18		key.data = kbuf;				\
19		key.size = 10;					\
20	}							\
21	} while (0)
22
23#define	GET_KEY_NEXT(key, config, kbuf, i) do {			\
24	size_t tmp_int;						\
25	if (config->orderedkeys) {				\
26		/* Will be sorted on little-endian system. */	\
27		tmp_int = i;					\
28		M_32_SWAP(tmp_int);				\
29		key.data = &tmp_int;				\
30	} else if (config->ksize == 0) {			\
31		/*						\
32		 * This will produce duplicate keys.		\
33		 * That is not such a big deal, since we are	\
34		 * using the same seed to srand each time,	\
35		 * the scenario is reproducible.		\
36		 */						\
37		(void)snprintf(kbuf, sizeof(kbuf), "%10d", rand()); \
38	} else {						\
39		/* TODO: Not sure of the best approach here. */	\
40		(void)snprintf(key.data, config->ksize, "%10lu", (u_long)i); \
41	}							\
42	} while (0)
43
44/* Taken from dbinc/db_swap.h */
45#undef	M_32_SWAP
46#define	M_32_SWAP(a) {							\
47	u_int32_t _tmp;							\
48	_tmp = (u_int32_t)a;						\
49	((u_int8_t *)&a)[0] = ((u_int8_t *)&_tmp)[3];			\
50	((u_int8_t *)&a)[1] = ((u_int8_t *)&_tmp)[2];			\
51	((u_int8_t *)&a)[2] = ((u_int8_t *)&_tmp)[1];			\
52	((u_int8_t *)&a)[3] = ((u_int8_t *)&_tmp)[0];			\
53}
54
55/*
56 * A singly linked list, that maintains a pointer
57 * to the start and the end of the queue.
58 * Should be possible to use a STAILQ, but this seemed easier
59 */
60typedef struct bench_qentry {
61	char data[KBUF_LEN];
62	struct bench_qentry *next;
63}bench_qentry;
64typedef struct bench_q {
65	struct bench_qentry *head;
66	struct bench_qentry *tail;
67} bench_q;
68#define	BENCH_Q_TAIL_INSERT(queue, buf) do {		\
69	struct bench_qentry *entry;				\
70	DB_BENCH_ASSERT(				\
71	    (entry = malloc(sizeof(struct bench_qentry))) != NULL); \
72	memcpy(entry->data, buf, sizeof(entry->data));	\
73	if (queue.head == NULL)				\
74		queue.head = queue.tail = entry;	\
75	else {						\
76		queue.tail->next = entry;		\
77		queue.tail = entry;			\
78	}						\
79} while (0)
80
81#define	BENCH_Q_POP(queue, buf) do {			\
82	struct bench_qentry *popped = queue.head;	\
83	if (popped == NULL)				\
84		break;					\
85	if (queue.head->next == NULL)			\
86		queue.head = queue.tail = NULL;		\
87	else						\
88		queue.head = queue.head->next;		\
89	memcpy(buf, popped->data, sizeof(buf));	\
90	free(popped);					\
91} while (0)
92
93/*
94 * Retrieve the head of the queue, save the data into user
95 * buffer, and push the item back onto the end of the list.
96 * Same functionality as pop/insert, but saves a malloc/free
97 */
98#define	BENCH_Q_POP_PUSH(queue, buf) do {		\
99	struct bench_qentry *popped = queue.head;	\
100	if (popped == NULL)				\
101		break;					\
102	if (queue.head->next == NULL)			\
103		queue.head = queue.tail = NULL;		\
104	else						\
105		queue.head = queue.head->next;		\
106	memcpy(buf, popped->data, sizeof(buf));	\
107	if (queue.head == NULL)				\
108		queue.head = queue.tail = popped;	\
109	else {						\
110		queue.tail->next = popped;		\
111		queue.tail = popped;			\
112	}						\
113} while (0)
114
115typedef enum {
116	T_PUT,
117	T_GET,
118	T_DELETE,
119	T_PUT_GET,
120	T_PUT_DELETE,
121	T_PUT_GET_DELETE,
122	T_GET_DELETE,
123	T_MIXED
124} test_type;
125
126typedef struct
127{
128	size_t ksize;
129	size_t dsize;
130	size_t orderedkeys;
131	size_t num_dups;
132	size_t pagesz;
133	size_t cachesz;
134	size_t pcount;
135	size_t gcount;
136	size_t cursor_del;
137	size_t verbose;
138	test_type workload;
139	size_t seed;
140	size_t presize;
141	DBTYPE type;
142	char   *ts;
143	char   *message;
144	/* Fields used to store timing information */
145	db_timespec put_time;
146	db_timespec get_time;
147	db_timespec del_time;
148	db_timespec tot_time;
149} CONFIG;
150