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