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