]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/tokyocabinet/tcumttest.c
Purged was missed, Adding here.
[bacula/bacula] / bacula / src / lib / tokyocabinet / tcumttest.c
1 /*************************************************************************************************
2  * The test cases of the on-memory database API
3  *                                                      Copyright (C) 2006-2008 Mikio Hirabayashi
4  * This file is part of Tokyo Cabinet.
5  * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
6  * the GNU Lesser General Public License as published by the Free Software Foundation; either
7  * version 2.1 of the License or any later version.  Tokyo Cabinet is distributed in the hope
8  * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
10  * License for more details.
11  * You should have received a copy of the GNU Lesser General Public License along with Tokyo
12  * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
13  * Boston, MA 02111-1307 USA.
14  *************************************************************************************************/
15
16
17 #include <tcutil.h>
18 #include "myconf.h"
19
20 #define RECBUFSIZ      32                // buffer for records
21
22 typedef struct {                         // type of structure for combo thread
23   TCMDB *mdb;
24   int rnum;
25   bool rnd;
26   int id;
27 } TARGCOMBO;
28
29 typedef struct {                         // type of structure for typical thread
30   TCMDB *mdb;
31   int rnum;
32   bool nc;
33   int rratio;
34   int id;
35 } TARGTYPICAL;
36
37
38 /* global variables */
39 const char *g_progname;                  // program name
40
41
42 /* function prototypes */
43 int main(int argc, char **argv);
44 static void usage(void);
45 static void iprintf(const char *format, ...);
46 static void eprint(const char *func);
47 static int myrand(int range);
48 static int myrandnd(int range);
49 static int runcombo(int argc, char **argv);
50 static int runtypical(int argc, char **argv);
51 static int proccombo(int tnum, int rnum, int bnum, bool rnd);
52 static int proctypical(int tnum, int rnum, int bnum, bool nc, int rratio);
53 static void *threadwrite(void *targ);
54 static void *threadread(void *targ);
55 static void *threadremove(void *targ);
56 static void *threadtypical(void *targ);
57
58
59 /* main routine */
60 int main(int argc, char **argv){
61   g_progname = argv[0];
62   srand((unsigned int)(tctime() * 1000) % UINT_MAX);
63   if(argc < 2) usage();
64   int rv = 0;
65   if(!strcmp(argv[1], "combo")){
66     rv = runcombo(argc, argv);
67   } else if(!strcmp(argv[1], "typical")){
68     rv = runtypical(argc, argv);
69   } else {
70     usage();
71   }
72   return rv;
73 }
74
75
76 /* print the usage and exit */
77 static void usage(void){
78   fprintf(stderr, "%s: test cases of the on-memory database API of Tokyo Cabinet\n", g_progname);
79   fprintf(stderr, "\n");
80   fprintf(stderr, "usage:\n");
81   fprintf(stderr, "  %s combo [-rnd] tnum rnum [bnum]\n", g_progname);
82   fprintf(stderr, "  %s typical [-nc] [-rr num] tnum rnum [bnum]\n", g_progname);
83   fprintf(stderr, "\n");
84   exit(1);
85 }
86
87
88 /* print formatted information string and flush the buffer */
89 static void iprintf(const char *format, ...){
90   va_list ap;
91   va_start(ap, format);
92   vprintf(format, ap);
93   fflush(stdout);
94   va_end(ap);
95 }
96
97
98 /* print error message of on-memory database */
99 static void eprint(const char *func){
100   fprintf(stderr, "%s: %s: error\n", g_progname, func);
101 }
102
103
104 /* get a random number */
105 static int myrand(int range){
106   return (int)((double)range * rand() / (RAND_MAX + 1.0));
107 }
108
109
110 /* get a random number based on normal distribution */
111 static int myrandnd(int range){
112   int num = (int)tcdrandnd(range >> 1, range / 10);
113   return (num < 0 || num >= range) ? 0 : num;
114 }
115
116
117 /* parse arguments of combo command */
118 static int runcombo(int argc, char **argv){
119   char *tstr = NULL;
120   char *rstr = NULL;
121   char *bstr = NULL;
122   bool rnd = false;
123   for(int i = 2; i < argc; i++){
124     if(!tstr && argv[i][0] == '-'){
125       if(!strcmp(argv[i], "-rnd")){
126         rnd = true;
127       } else {
128         usage();
129       }
130     } else if(!tstr){
131       tstr = argv[i];
132     } else if(!rstr){
133       rstr = argv[i];
134     } else if(!bstr){
135       bstr = argv[i];
136     } else {
137       usage();
138     }
139   }
140   if(!tstr || !rstr) usage();
141   int tnum = atoi(tstr);
142   int rnum = atoi(rstr);
143   if(tnum < 1 || rnum < 1) usage();
144   int bnum = bstr ? atoi(bstr) : -1;
145   int rv = proccombo(tnum, rnum, bnum, rnd);
146   return rv;
147 }
148
149
150 /* parse arguments of typical command */
151 static int runtypical(int argc, char **argv){
152   char *tstr = NULL;
153   char *rstr = NULL;
154   char *bstr = NULL;
155   int rratio = -1;
156   bool nc = false;
157   for(int i = 2; i < argc; i++){
158     if(!tstr && argv[i][0] == '-'){
159       if(!strcmp(argv[i], "-nc")){
160         nc = true;
161       } else if(!strcmp(argv[i], "-rr")){
162         if(++i >= argc) usage();
163         rratio = atoi(argv[i]);
164       } else {
165         usage();
166       }
167     } else if(!tstr){
168       tstr = argv[i];
169     } else if(!rstr){
170       rstr = argv[i];
171     } else if(!bstr){
172       bstr = argv[i];
173     } else {
174       usage();
175     }
176   }
177   if(!tstr || !rstr) usage();
178   int tnum = atoi(tstr);
179   int rnum = atoi(rstr);
180   if(tnum < 1 || rnum < 1) usage();
181   int bnum = bstr ? atoi(bstr) : -1;
182   int rv = proctypical(tnum, rnum, bnum, nc, rratio);
183   return rv;
184 }
185
186
187 /* perform combo command */
188 static int proccombo(int tnum, int rnum, int bnum, bool rnd){
189   iprintf("<Combination Test>\n  tnum=%d  rnum=%d  bnum=%d  rnd=%d\n\n", tnum, rnum, bnum, rnd);
190   bool err = false;
191   double stime = tctime();
192   TCMDB *mdb = (bnum > 0) ? tcmdbnew2(bnum) : tcmdbnew();
193   TARGCOMBO targs[tnum];
194   pthread_t threads[tnum];
195   if(tnum == 1){
196     targs[0].mdb = mdb;
197     targs[0].rnum = rnum;
198     targs[0].rnd = rnd;
199     targs[0].id = 0;
200     if(threadwrite(targs) != NULL) err = true;
201   } else {
202     for(int i = 0; i < tnum; i++){
203       targs[i].mdb = mdb;
204       targs[i].rnum = rnum;
205       targs[i].rnd = rnd;
206       targs[i].id = i;
207       if(pthread_create(threads + i, NULL, threadwrite, targs + i) != 0){
208         eprint("pthread_create");
209         targs[i].id = -1;
210         err = true;
211       }
212     }
213     for(int i = 0; i < tnum; i++){
214       if(targs[i].id == -1) continue;
215       void *rv;
216       if(pthread_join(threads[i], &rv) != 0){
217         eprint("pthread_join");
218         err = true;
219       } else if(rv){
220         err = true;
221       }
222     }
223   }
224   if(tnum == 1){
225     targs[0].mdb = mdb;
226     targs[0].rnum = rnum;
227     targs[0].rnd = rnd;
228     targs[0].id = 0;
229     if(threadread(targs) != NULL) err = true;
230   } else {
231     for(int i = 0; i < tnum; i++){
232       targs[i].mdb = mdb;
233       targs[i].rnum = rnum;
234       targs[i].rnd = rnd;
235       targs[i].id = i;
236       if(pthread_create(threads + i, NULL, threadread, targs + i) != 0){
237         eprint("pthread_create");
238         targs[i].id = -1;
239         err = true;
240       }
241     }
242     for(int i = 0; i < tnum; i++){
243       if(targs[i].id == -1) continue;
244       void *rv;
245       if(pthread_join(threads[i], &rv) != 0){
246         eprint("pthread_join");
247         err = true;
248       } else if(rv){
249         err = true;
250       }
251     }
252   }
253   if(tnum == 1){
254     targs[0].mdb = mdb;
255     targs[0].rnum = rnum;
256     targs[0].rnd = rnd;
257     targs[0].id = 0;
258     if(threadremove(targs) != NULL) err = true;
259   } else {
260     for(int i = 0; i < tnum; i++){
261       targs[i].mdb = mdb;
262       targs[i].rnum = rnum;
263       targs[i].rnd = rnd;
264       targs[i].id = i;
265       if(pthread_create(threads + i, NULL, threadremove, targs + i) != 0){
266         eprint("pthread_create");
267         targs[i].id = -1;
268         err = true;
269       }
270     }
271     for(int i = 0; i < tnum; i++){
272       if(targs[i].id == -1) continue;
273       void *rv;
274       if(pthread_join(threads[i], &rv) != 0){
275         eprint("pthread_join");
276         err = true;
277       } else if(rv){
278         err = true;
279       }
280     }
281   }
282   iprintf("record number: %llu\n", (unsigned long long)tcmdbrnum(mdb));
283   tcmdbdel(mdb);
284   iprintf("time: %.3f\n", tctime() - stime);
285   iprintf("%s\n\n", err ? "error" : "ok");
286   return err ? 1 : 0;
287 }
288
289
290 /* perform typical command */
291 static int proctypical(int tnum, int rnum, int bnum, bool nc, int rratio){
292   iprintf("<Typical Access Test>\n  tnum=%d  rnum=%d  bnum=%d  nc=%d  rratio=%d\n\n",
293           tnum, rnum, bnum, nc, rratio);
294   bool err = false;
295   double stime = tctime();
296   TCMDB *mdb = (bnum > 0) ? tcmdbnew2(bnum) : tcmdbnew();
297   TARGTYPICAL targs[tnum];
298   pthread_t threads[tnum];
299   if(tnum == 1){
300     targs[0].mdb = mdb;
301     targs[0].rnum = rnum;
302     targs[0].nc = nc;
303     targs[0].rratio = rratio;
304     targs[0].id = 0;
305     if(threadtypical(targs) != NULL) err = true;
306   } else {
307     for(int i = 0; i < tnum; i++){
308       targs[i].mdb = mdb;
309       targs[i].rnum = rnum;
310       targs[i].nc = nc;
311       targs[i].rratio= rratio;
312       targs[i].id = i;
313       if(pthread_create(threads + i, NULL, threadtypical, targs + i) != 0){
314         eprint("pthread_create");
315         targs[i].id = -1;
316         err = true;
317       }
318     }
319     for(int i = 0; i < tnum; i++){
320       if(targs[i].id == -1) continue;
321       void *rv;
322       if(pthread_join(threads[i], &rv) != 0){
323         eprint("pthread_join");
324         err = true;
325       } else if(rv){
326         err = true;
327       }
328     }
329   }
330   iprintf("record number: %llu\n", (unsigned long long)tcmdbrnum(mdb));
331   tcmdbdel(mdb);
332   iprintf("time: %.3f\n", tctime() - stime);
333   iprintf("%s\n\n", err ? "error" : "ok");
334   return err ? 1 : 0;
335 }
336
337
338 /* thread the write function */
339 static void *threadwrite(void *targ){
340   TCMDB *mdb = ((TARGCOMBO *)targ)->mdb;
341   int rnum = ((TARGCOMBO *)targ)->rnum;
342   bool rnd = ((TARGCOMBO *)targ)->rnd;
343   int id = ((TARGCOMBO *)targ)->id;
344   double stime = tctime();
345   if(id == 0) iprintf("writing:\n");
346   int base = id * rnum;
347   for(int i = 1; i <= rnum; i++){
348     char buf[RECBUFSIZ];
349     int len = sprintf(buf, "%08d", base + (rnd ? myrand(i) : i));
350     tcmdbput(mdb, buf, len, buf, len);
351     if(id == 0 && rnum > 250 && i % (rnum / 250) == 0){
352       putchar('.');
353       fflush(stdout);
354       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
355     }
356   }
357   if(id == 0) iprintf("time: %.3f\n", tctime() - stime);
358   return NULL;
359 }
360
361
362 /* thread the read function */
363 static void *threadread(void *targ){
364   TCMDB *mdb = ((TARGCOMBO *)targ)->mdb;
365   int rnum = ((TARGCOMBO *)targ)->rnum;
366   bool rnd = ((TARGCOMBO *)targ)->rnd;
367   int id = ((TARGCOMBO *)targ)->id;
368   double stime = tctime();
369   if(id == 0) iprintf("reading:\n");
370   int base = id * rnum;
371   for(int i = 1; i <= rnum; i++){
372     char kbuf[RECBUFSIZ];
373     int ksiz = sprintf(kbuf, "%08d", base + (rnd ? myrand(i) : i));
374     int vsiz;
375     char *vbuf = tcmdbget(mdb, kbuf, ksiz, &vsiz);
376     if(vbuf) free(vbuf);
377     if(id == 0 && rnum > 250 && i % (rnum / 250) == 0){
378       putchar('.');
379       fflush(stdout);
380       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
381     }
382   }
383   if(id == 0) iprintf("time: %.3f\n", tctime() - stime);
384   return NULL;
385 }
386
387
388 /* thread the remove function */
389 static void *threadremove(void *targ){
390   TCMDB *mdb = ((TARGCOMBO *)targ)->mdb;
391   int rnum = ((TARGCOMBO *)targ)->rnum;
392   bool rnd = ((TARGCOMBO *)targ)->rnd;
393   int id = ((TARGCOMBO *)targ)->id;
394   double stime = tctime();
395   if(id == 0) iprintf("removing:\n");
396   int base = id * rnum;
397   for(int i = 1; i <= rnum; i++){
398     char buf[RECBUFSIZ];
399     int len = sprintf(buf, "%08d", base + (rnd ? myrand(i) : i));
400     tcmdbout(mdb, buf, len);
401     if(id == 0 && rnum > 250 && i % (rnum / 250) == 0){
402       putchar('.');
403       fflush(stdout);
404       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
405     }
406   }
407   if(id == 0) iprintf("time: %.3f\n", tctime() - stime);
408   return NULL;
409 }
410
411
412 /* thread the typical function */
413 static void *threadtypical(void *targ){
414   TCMDB *mdb = ((TARGTYPICAL *)targ)->mdb;
415   int rnum = ((TARGTYPICAL *)targ)->rnum;
416   bool nc = ((TARGTYPICAL *)targ)->nc;
417   int rratio = ((TARGTYPICAL *)targ)->rratio;
418   int id = ((TARGTYPICAL *)targ)->id;
419   bool err = false;
420   TCMAP *map = (!nc && id == 0) ? tcmapnew2(rnum + 1) : NULL;
421   int base = id * rnum;
422   int mrange = tclmax(50 + rratio, 100);
423   for(int i = 1; !err && i <= rnum; i++){
424     char buf[RECBUFSIZ];
425     int len = sprintf(buf, "%08d", base + myrandnd(i));
426     int rnd = myrand(mrange);
427     if(rnd < 10){
428       tcmdbput(mdb, buf, len, buf, len);
429       if(map) tcmapput(map, buf, len, buf, len);
430     } else if(rnd < 15){
431       tcmdbputkeep(mdb, buf, len, buf, len);
432       if(map) tcmapputkeep(map, buf, len, buf, len);
433     } else if(rnd < 20){
434       tcmdbputcat(mdb, buf, len, buf, len);
435       if(map) tcmapputcat(map, buf, len, buf, len);
436     } else if(rnd < 30){
437       tcmdbout(mdb, buf, len);
438       if(map) tcmapout(map, buf, len);
439     } else if(rnd < 31){
440       if(myrand(10) == 0) tcmdbiterinit(mdb);
441       for(int j = 0; !err && j < 10; j++){
442         int ksiz;
443         char *kbuf = tcmdbiternext(mdb, &ksiz);
444         if(kbuf) free(kbuf);
445       }
446     } else {
447       int vsiz;
448       char *vbuf = tcmdbget(mdb, buf, len, &vsiz);
449       if(vbuf){
450         if(map){
451           int msiz;
452           const char *mbuf = tcmapget(map, buf, len, &msiz);
453           if(msiz != vsiz || memcmp(mbuf, vbuf, vsiz)){
454             eprint("(validation)");
455             err = true;
456           }
457         }
458         free(vbuf);
459       } else {
460         if(map && tcmapget(map, buf, len, &vsiz)){
461           eprint("(validation)");
462           err = true;
463         }
464       }
465     }
466     if(id == 0 && rnum > 250 && i % (rnum / 250) == 0){
467       putchar('.');
468       fflush(stdout);
469       if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
470     }
471   }
472   if(map){
473     tcmapiterinit(map);
474     int ksiz;
475     const char *kbuf;
476     while(!err && (kbuf = tcmapiternext(map, &ksiz)) != NULL){
477       int vsiz;
478       char *vbuf = tcmdbget(mdb, kbuf, ksiz, &vsiz);
479       if(vbuf){
480         int msiz;
481         const char *mbuf = tcmapget(map, kbuf, ksiz, &msiz);
482         if(!mbuf || msiz != vsiz || memcmp(mbuf, vbuf, vsiz)){
483           eprint("(validation)");
484           err = true;
485         }
486         free(vbuf);
487       } else {
488         eprint("(validation)");
489         err = true;
490       }
491     }
492     tcmapdel(map);
493   }
494   return err ? "error" : NULL;
495 }
496
497
498
499 // END OF FILE