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