00001
00002
00003 #include "replace.h"
00004 #include "tdb.h"
00005 #include "system/filesys.h"
00006 #include "system/time.h"
00007
00008 #include <gdbm.h>
00009
00010
00011 #define DELETE_PROB 7
00012 #define STORE_PROB 5
00013
00014 static struct tdb_context *db;
00015 static GDBM_FILE gdbm;
00016
00017 struct timeval tp1,tp2;
00018
00019 static void _start_timer(void)
00020 {
00021 gettimeofday(&tp1,NULL);
00022 }
00023
00024 static double _end_timer(void)
00025 {
00026 gettimeofday(&tp2,NULL);
00027 return((tp2.tv_sec - tp1.tv_sec) +
00028 (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
00029 }
00030
00031 static void fatal(const char *why)
00032 {
00033 perror(why);
00034 exit(1);
00035 }
00036
00037 #ifdef PRINTF_ATTRIBUTE
00038 static void tdb_log(struct tdb_context *tdb, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4);
00039 #endif
00040 static void tdb_log(struct tdb_context *tdb, int level, const char *format, ...)
00041 {
00042 va_list ap;
00043
00044 va_start(ap, format);
00045 vfprintf(stdout, format, ap);
00046 va_end(ap);
00047 fflush(stdout);
00048 }
00049
00050 static void compare_db(void)
00051 {
00052 TDB_DATA d, key, nextkey;
00053 datum gd, gkey, gnextkey;
00054
00055 key = tdb_firstkey(db);
00056 while (key.dptr) {
00057 d = tdb_fetch(db, key);
00058 gkey.dptr = key.dptr;
00059 gkey.dsize = key.dsize;
00060
00061 gd = gdbm_fetch(gdbm, gkey);
00062
00063 if (!gd.dptr) fatal("key not in gdbm");
00064 if (gd.dsize != d.dsize) fatal("data sizes differ");
00065 if (memcmp(gd.dptr, d.dptr, d.dsize)) {
00066 fatal("data differs");
00067 }
00068
00069 nextkey = tdb_nextkey(db, key);
00070 free(key.dptr);
00071 free(d.dptr);
00072 free(gd.dptr);
00073 key = nextkey;
00074 }
00075
00076 gkey = gdbm_firstkey(gdbm);
00077 while (gkey.dptr) {
00078 gd = gdbm_fetch(gdbm, gkey);
00079 key.dptr = gkey.dptr;
00080 key.dsize = gkey.dsize;
00081
00082 d = tdb_fetch(db, key);
00083
00084 if (!d.dptr) fatal("key not in db");
00085 if (d.dsize != gd.dsize) fatal("data sizes differ");
00086 if (memcmp(d.dptr, gd.dptr, gd.dsize)) {
00087 fatal("data differs");
00088 }
00089
00090 gnextkey = gdbm_nextkey(gdbm, gkey);
00091 free(gkey.dptr);
00092 free(gd.dptr);
00093 free(d.dptr);
00094 gkey = gnextkey;
00095 }
00096 }
00097
00098 static char *randbuf(int len)
00099 {
00100 char *buf;
00101 int i;
00102 buf = (char *)malloc(len+1);
00103
00104 for (i=0;i<len;i++) {
00105 buf[i] = 'a' + (rand() % 26);
00106 }
00107 buf[i] = 0;
00108 return buf;
00109 }
00110
00111 static void addrec_db(void)
00112 {
00113 int klen, dlen;
00114 char *k, *d;
00115 TDB_DATA key, data;
00116
00117 klen = 1 + (rand() % 4);
00118 dlen = 1 + (rand() % 100);
00119
00120 k = randbuf(klen);
00121 d = randbuf(dlen);
00122
00123 key.dptr = k;
00124 key.dsize = klen+1;
00125
00126 data.dptr = d;
00127 data.dsize = dlen+1;
00128
00129 if (rand() % DELETE_PROB == 0) {
00130 tdb_delete(db, key);
00131 } else if (rand() % STORE_PROB == 0) {
00132 if (tdb_store(db, key, data, TDB_REPLACE) != 0) {
00133 fatal("tdb_store failed");
00134 }
00135 } else {
00136 data = tdb_fetch(db, key);
00137 if (data.dptr) free(data.dptr);
00138 }
00139
00140 free(k);
00141 free(d);
00142 }
00143
00144 static void addrec_gdbm(void)
00145 {
00146 int klen, dlen;
00147 char *k, *d;
00148 datum key, data;
00149
00150 klen = 1 + (rand() % 4);
00151 dlen = 1 + (rand() % 100);
00152
00153 k = randbuf(klen);
00154 d = randbuf(dlen);
00155
00156 key.dptr = k;
00157 key.dsize = klen+1;
00158
00159 data.dptr = d;
00160 data.dsize = dlen+1;
00161
00162 if (rand() % DELETE_PROB == 0) {
00163 gdbm_delete(gdbm, key);
00164 } else if (rand() % STORE_PROB == 0) {
00165 if (gdbm_store(gdbm, key, data, GDBM_REPLACE) != 0) {
00166 fatal("gdbm_store failed");
00167 }
00168 } else {
00169 data = gdbm_fetch(gdbm, key);
00170 if (data.dptr) free(data.dptr);
00171 }
00172
00173 free(k);
00174 free(d);
00175 }
00176
00177 static int traverse_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
00178 {
00179 #if 0
00180 printf("[%s] [%s]\n", key.dptr, dbuf.dptr);
00181 #endif
00182 tdb_delete(tdb, key);
00183 return 0;
00184 }
00185
00186 static void merge_test(void)
00187 {
00188 int i;
00189 char keys[5][2];
00190 char tdata[] = "test";
00191 TDB_DATA key, data;
00192
00193 for (i = 0; i < 5; i++) {
00194 snprintf(keys[i],2, "%d", i);
00195 key.dptr = keys[i];
00196 key.dsize = 2;
00197
00198 data.dptr = tdata;
00199 data.dsize = 4;
00200
00201 if (tdb_store(db, key, data, TDB_REPLACE) != 0) {
00202 fatal("tdb_store failed");
00203 }
00204 }
00205
00206 key.dptr = keys[0];
00207 tdb_delete(db, key);
00208 key.dptr = keys[4];
00209 tdb_delete(db, key);
00210 key.dptr = keys[2];
00211 tdb_delete(db, key);
00212 key.dptr = keys[1];
00213 tdb_delete(db, key);
00214 key.dptr = keys[3];
00215 tdb_delete(db, key);
00216 }
00217
00218 int main(int argc, const char *argv[])
00219 {
00220 int i, seed=0;
00221 int loops = 10000;
00222 int num_entries;
00223 char test_gdbm[] = "test.gdbm";
00224
00225 unlink("test.gdbm");
00226
00227 db = tdb_open("test.tdb", 0, TDB_CLEAR_IF_FIRST,
00228 O_RDWR | O_CREAT | O_TRUNC, 0600);
00229 gdbm = gdbm_open(test_gdbm, 512, GDBM_WRITER|GDBM_NEWDB|GDBM_FAST,
00230 0600, NULL);
00231
00232 if (!db || !gdbm) {
00233 fatal("db open failed");
00234 }
00235
00236 #if 1
00237 srand(seed);
00238 _start_timer();
00239 for (i=0;i<loops;i++) addrec_gdbm();
00240 printf("gdbm got %.2f ops/sec\n", i/_end_timer());
00241 #endif
00242
00243 merge_test();
00244
00245 srand(seed);
00246 _start_timer();
00247 for (i=0;i<loops;i++) addrec_db();
00248 printf("tdb got %.2f ops/sec\n", i/_end_timer());
00249
00250 if (tdb_validate_freelist(db, &num_entries) == -1) {
00251 printf("tdb freelist is corrupt\n");
00252 } else {
00253 printf("tdb freelist is good (%d entries)\n", num_entries);
00254 }
00255
00256 compare_db();
00257
00258 printf("traversed %d records\n", tdb_traverse(db, traverse_fn, NULL));
00259 printf("traversed %d records\n", tdb_traverse(db, traverse_fn, NULL));
00260
00261 tdb_close(db);
00262 gdbm_close(gdbm);
00263
00264 return 0;
00265 }