r4466: rather than defining "STANDALONE" for building tdb, ldb and talloc
[samba.git] / source4 / lib / tdb / tools / tdbtest.c
1 /* a test program for tdb - the trivial database */
2
3 #ifndef _SAMBA_BUILD_
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <fcntl.h>
7 #include <unistd.h>
8 #include <string.h>
9 #include <fcntl.h>
10 #include <stdarg.h>
11 #include <sys/mman.h>
12 #include <sys/stat.h>
13 #include <sys/time.h>
14 #include <signal.h>
15 #include "tdb.h"
16 #else
17
18 #include "includes.h"
19
20 #endif
21
22 #include <gdbm.h>
23
24
25 #define DELETE_PROB 7
26 #define STORE_PROB 5
27
28 static TDB_CONTEXT *db;
29 static GDBM_FILE gdbm;
30
31 struct timeval tp1,tp2;
32
33 static void _start_timer(void)
34 {
35         gettimeofday(&tp1,NULL);
36 }
37
38 static double _end_timer(void)
39 {
40         gettimeofday(&tp2,NULL);
41         return((tp2.tv_sec - tp1.tv_sec) + 
42                (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
43 }
44
45 static void fatal(const char *why)
46 {
47         perror(why);
48         exit(1);
49 }
50
51 #ifdef PRINTF_ATTRIBUTE
52 static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4);
53 #endif
54 static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...)
55 {
56         va_list ap;
57     
58         va_start(ap, format);
59         vfprintf(stdout, format, ap);
60         va_end(ap);
61         fflush(stdout);
62 }
63
64 static void compare_db(void)
65 {
66         TDB_DATA d, key, nextkey;
67         datum gd, gkey, gnextkey;
68
69         key = tdb_firstkey(db);
70         while (key.dptr) {
71                 d = tdb_fetch(db, key);
72                 gkey.dptr = key.dptr;
73                 gkey.dsize = key.dsize;
74
75                 gd = gdbm_fetch(gdbm, gkey);
76
77                 if (!gd.dptr) fatal("key not in gdbm");
78                 if (gd.dsize != d.dsize) fatal("data sizes differ");
79                 if (memcmp(gd.dptr, d.dptr, d.dsize)) {
80                         fatal("data differs");
81                 }
82
83                 nextkey = tdb_nextkey(db, key);
84                 free(key.dptr);
85                 free(d.dptr);
86                 free(gd.dptr);
87                 key = nextkey;
88         }
89
90         gkey = gdbm_firstkey(gdbm);
91         while (gkey.dptr) {
92                 gd = gdbm_fetch(gdbm, gkey);
93                 key.dptr = gkey.dptr;
94                 key.dsize = gkey.dsize;
95
96                 d = tdb_fetch(db, key);
97
98                 if (!d.dptr) fatal("key not in db");
99                 if (d.dsize != gd.dsize) fatal("data sizes differ");
100                 if (memcmp(d.dptr, gd.dptr, gd.dsize)) {
101                         fatal("data differs");
102                 }
103
104                 gnextkey = gdbm_nextkey(gdbm, gkey);
105                 free(gkey.dptr);
106                 free(gd.dptr);
107                 free(d.dptr);
108                 gkey = gnextkey;
109         }
110 }
111
112 static char *randbuf(int len)
113 {
114         char *buf;
115         int i;
116         buf = (char *)malloc(len+1);
117
118         for (i=0;i<len;i++) {
119                 buf[i] = 'a' + (rand() % 26);
120         }
121         buf[i] = 0;
122         return buf;
123 }
124
125 static void addrec_db(void)
126 {
127         int klen, dlen;
128         char *k, *d;
129         TDB_DATA key, data;
130
131         klen = 1 + (rand() % 4);
132         dlen = 1 + (rand() % 100);
133
134         k = randbuf(klen);
135         d = randbuf(dlen);
136
137         key.dptr = k;
138         key.dsize = klen+1;
139
140         data.dptr = d;
141         data.dsize = dlen+1;
142
143         if (rand() % DELETE_PROB == 0) {
144                 tdb_delete(db, key);
145         } else if (rand() % STORE_PROB == 0) {
146                 if (tdb_store(db, key, data, TDB_REPLACE) != 0) {
147                         fatal("tdb_store failed");
148                 }
149         } else {
150                 data = tdb_fetch(db, key);
151                 if (data.dptr) free(data.dptr);
152         }
153
154         free(k);
155         free(d);
156 }
157
158 static void addrec_gdbm(void)
159 {
160         int klen, dlen;
161         char *k, *d;
162         datum key, data;
163
164         klen = 1 + (rand() % 4);
165         dlen = 1 + (rand() % 100);
166
167         k = randbuf(klen);
168         d = randbuf(dlen);
169
170         key.dptr = k;
171         key.dsize = klen+1;
172
173         data.dptr = d;
174         data.dsize = dlen+1;
175
176         if (rand() % DELETE_PROB == 0) {
177                 gdbm_delete(gdbm, key);
178         } else if (rand() % STORE_PROB == 0) {
179                 if (gdbm_store(gdbm, key, data, GDBM_REPLACE) != 0) {
180                         fatal("gdbm_store failed");
181                 }
182         } else {
183                 data = gdbm_fetch(gdbm, key);
184                 if (data.dptr) free(data.dptr);
185         }
186
187         free(k);
188         free(d);
189 }
190
191 static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
192 {
193 #if 0
194         printf("[%s] [%s]\n", key.dptr, dbuf.dptr);
195 #endif
196         tdb_delete(tdb, key);
197         return 0;
198 }
199
200 static void merge_test(void)
201 {
202         int i;
203         char keys[5][2];
204         char tdata[] = "test";
205         TDB_DATA key, data;
206         
207         for (i = 0; i < 5; i++) {
208                 snprintf(keys[i],2, "%d", i);
209                 key.dptr = keys[i];
210                 key.dsize = 2;
211                 
212                 data.dptr = tdata;
213                 data.dsize = 4;
214                 
215                 if (tdb_store(db, key, data, TDB_REPLACE) != 0) {
216                         fatal("tdb_store failed");
217                 }
218         }
219
220         key.dptr = keys[0];
221         tdb_delete(db, key);
222         key.dptr = keys[4];
223         tdb_delete(db, key);
224         key.dptr = keys[2];
225         tdb_delete(db, key);
226         key.dptr = keys[1];
227         tdb_delete(db, key);
228         key.dptr = keys[3];
229         tdb_delete(db, key);
230 }
231         
232  int main(int argc, const char *argv[])
233 {
234         int i, seed=0;
235         int loops = 10000;
236         char test_gdbm[] = "test.gdbm";
237
238         unlink("test.gdbm");
239
240         db = tdb_open("test.tdb", 0, TDB_CLEAR_IF_FIRST, 
241                       O_RDWR | O_CREAT | O_TRUNC, 0600);
242         gdbm = gdbm_open(test_gdbm, 512, GDBM_WRITER|GDBM_NEWDB|GDBM_FAST, 
243                          0600, NULL);
244
245         if (!db || !gdbm) {
246                 fatal("db open failed");
247         }
248
249         tdb_logging_function(db, tdb_log);
250         
251 #if 1
252         srand(seed);
253         _start_timer();
254         for (i=0;i<loops;i++) addrec_gdbm();
255         printf("gdbm got %.2f ops/sec\n", i/_end_timer());
256 #endif
257
258         merge_test();
259
260         srand(seed);
261         _start_timer();
262         for (i=0;i<loops;i++) addrec_db();
263         printf("tdb got %.2f ops/sec\n", i/_end_timer());
264
265         compare_db();
266
267         printf("traversed %d records\n", tdb_traverse(db, traverse_fn, NULL));
268         printf("traversed %d records\n", tdb_traverse(db, traverse_fn, NULL));
269
270         tdb_close(db);
271         gdbm_close(gdbm);
272
273         return 0;
274 }