1 /*************************************************************************************************
2 * The test cases of the B+ tree 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 *************************************************************************************************/
21 #define RECBUFSIZ 32 // buffer for records
24 /* global variables */
25 const char *g_progname; // program name
26 int g_dbgfd; // debugging output
29 /* function prototypes */
30 int main(int argc, char **argv);
31 static void usage(void);
32 static void iprintf(const char *format, ...);
33 static void eprint(TCBDB *bdb, const char *func);
34 static void mprint(TCBDB *bdb);
35 static int myrand(int range);
36 static int runwrite(int argc, char **argv);
37 static int runread(int argc, char **argv);
38 static int runremove(int argc, char **argv);
39 static int runrcat(int argc, char **argv);
40 static int runqueue(int argc, char **argv);
41 static int runmisc(int argc, char **argv);
42 static int runwicked(int argc, char **argv);
43 static int procwrite(const char *path, int rnum, int lmemb, int nmemb, int bnum,
44 int apow, int fpow, bool mt, BDBCMP cmp, int opts,
45 int lcnum, int ncnum, int lsmax, int capnum, int omode);
46 static int procread(const char *path, bool mt, BDBCMP cmp, int lcnum, int ncnum,
48 static int procremove(const char *path, bool mt, BDBCMP cmp, int lcnum, int ncnum, int omode);
49 static int procrcat(const char *path, int rnum,
50 int lmemb, int nmemb, int bnum, int apow, int fpow,
51 bool mt, BDBCMP cmp, int opts, int lcnum, int ncnum, int lsmax, int capnum,
52 int omode, int pnum, bool rl);
53 static int procqueue(const char *path, int rnum, int lmemb, int nmemb, int bnum,
54 int apow, int fpow, bool mt, BDBCMP cmp, int opts,
55 int lcnum, int ncnum, int lsmax, int capnum, int omode);
56 static int procmisc(const char *path, int rnum, bool mt, int opts, int omode);
57 static int procwicked(const char *path, int rnum, bool mt, int opts, int omode);
61 int main(int argc, char **argv){
64 const char *ebuf = getenv("TCDBGFD");
65 if(ebuf) g_dbgfd = atoi(ebuf);
66 srand((unsigned int)(tctime() * 1000) % UINT_MAX);
69 if(!strcmp(argv[1], "write")){
70 rv = runwrite(argc, argv);
71 } else if(!strcmp(argv[1], "read")){
72 rv = runread(argc, argv);
73 } else if(!strcmp(argv[1], "remove")){
74 rv = runremove(argc, argv);
75 } else if(!strcmp(argv[1], "rcat")){
76 rv = runrcat(argc, argv);
77 } else if(!strcmp(argv[1], "queue")){
78 rv = runqueue(argc, argv);
79 } else if(!strcmp(argv[1], "misc")){
80 rv = runmisc(argc, argv);
81 } else if(!strcmp(argv[1], "wicked")){
82 rv = runwicked(argc, argv);
90 /* print the usage and exit */
91 static void usage(void){
92 fprintf(stderr, "%s: test cases of the B+ tree database API of Tokyo Cabinet\n", g_progname);
93 fprintf(stderr, "\n");
94 fprintf(stderr, "usage:\n");
95 fprintf(stderr, " %s write [-mt] [-cd|-ci|-cj] [-tl] [-td|-tb] [-lc num] [-nc num]"
96 " [-ls num] [-ca num] [-nl|-nb] path rnum [lmemb [nmemb [bnum [apow [fpow]]]]]\n",
98 fprintf(stderr, " %s read [-mt] [-cd|-ci|-cj] [-lc num] [-nc num] [-nl|-nb] [-wb]"
99 " path\n", g_progname);
100 fprintf(stderr, " %s remove [-mt] [-cd|-ci|-cj] [-lc num] [-nc num] [-nl|-nb]"
101 " path\n", g_progname);
102 fprintf(stderr, " %s rcat [-mt] [-cd|-ci|-cj] [-tl] [-td|-tb] [-lc num] [-nc num]"
103 " [-ls num] [-ca num] [-nl|-nb] [-pn num] [-rl] path rnum"
104 " [lmemb [nmemb [bnum [apow [fpow]]]]]\n", g_progname);
105 fprintf(stderr, " %s queue [-mt] [-cd|-ci|-cj] [-tl] [-td|-tb] [-lc num] [-nc num]"
106 " [-ls num] [-ca num] [-nl|-nb] path rnum [lmemb [nmemb [bnum [apow [fpow]]]]]\n",
108 fprintf(stderr, " %s misc [-mt] [-tl] [-td|-tb] [-nl|-nb] path rnum\n", g_progname);
109 fprintf(stderr, " %s wicked [-mt] [-tl] [-td|-tb] [-nl|-nb] path rnum\n", g_progname);
110 fprintf(stderr, "\n");
115 /* print formatted information string and flush the buffer */
116 static void iprintf(const char *format, ...){
118 va_start(ap, format);
125 /* print error message of hash database */
126 static void eprint(TCBDB *bdb, const char *func){
127 const char *path = tcbdbpath(bdb);
128 int ecode = tcbdbecode(bdb);
129 fprintf(stderr, "%s: %s: %s: error: %d: %s\n",
130 g_progname, path ? path : "-", func, ecode, tcbdberrmsg(ecode));
134 /* print members of B+ tree database */
135 static void mprint(TCBDB *bdb){
136 if(bdb->hdb->cnt_writerec < 0) return;
137 iprintf("max leaf member: %d\n", tcbdblmemb(bdb));
138 iprintf("max node member: %d\n", tcbdbnmemb(bdb));
139 iprintf("leaf number: %d\n", tcbdblnum(bdb));
140 iprintf("node number: %d\n", tcbdbnnum(bdb));
141 iprintf("bucket number: %lld\n", (long long)tcbdbbnum(bdb));
142 iprintf("used bucket number: %lld\n", (long long)tcbdbbnumused(bdb));
143 iprintf("cnt_saveleaf: %lld\n", (long long)bdb->cnt_saveleaf);
144 iprintf("cnt_loadleaf: %lld\n", (long long)bdb->cnt_loadleaf);
145 iprintf("cnt_killleaf: %lld\n", (long long)bdb->cnt_killleaf);
146 iprintf("cnt_adjleafc: %lld\n", (long long)bdb->cnt_adjleafc);
147 iprintf("cnt_savenode: %lld\n", (long long)bdb->cnt_savenode);
148 iprintf("cnt_loadnode: %lld\n", (long long)bdb->cnt_loadnode);
149 iprintf("cnt_adjnodec: %lld\n", (long long)bdb->cnt_adjnodec);
150 iprintf("cnt_writerec: %lld\n", (long long)bdb->hdb->cnt_writerec);
151 iprintf("cnt_reuserec: %lld\n", (long long)bdb->hdb->cnt_reuserec);
152 iprintf("cnt_moverec: %lld\n", (long long)bdb->hdb->cnt_moverec);
153 iprintf("cnt_readrec: %lld\n", (long long)bdb->hdb->cnt_readrec);
154 iprintf("cnt_searchfbp: %lld\n", (long long)bdb->hdb->cnt_searchfbp);
155 iprintf("cnt_insertfbp: %lld\n", (long long)bdb->hdb->cnt_insertfbp);
156 iprintf("cnt_splicefbp: %lld\n", (long long)bdb->hdb->cnt_splicefbp);
157 iprintf("cnt_dividefbp: %lld\n", (long long)bdb->hdb->cnt_dividefbp);
158 iprintf("cnt_mergefbp: %lld\n", (long long)bdb->hdb->cnt_mergefbp);
159 iprintf("cnt_reducefbp: %lld\n", (long long)bdb->hdb->cnt_reducefbp);
160 iprintf("cnt_appenddrp: %lld\n", (long long)bdb->hdb->cnt_appenddrp);
161 iprintf("cnt_deferdrp: %lld\n", (long long)bdb->hdb->cnt_deferdrp);
162 iprintf("cnt_flushdrp: %lld\n", (long long)bdb->hdb->cnt_flushdrp);
163 iprintf("cnt_adjrecc: %lld\n", (long long)bdb->hdb->cnt_adjrecc);
167 /* get a random number */
168 static int myrand(int range){
169 return (int)((double)range * rand() / (RAND_MAX + 1.0));
173 /* parse arguments of write command */
174 static int runwrite(int argc, char **argv){
190 for(int i = 2; i < argc; i++){
191 if(!path && argv[i][0] == '-'){
192 if(!strcmp(argv[i], "-mt")){
194 } else if(!strcmp(argv[i], "-cd")){
195 cmp = tcbdbcmpdecimal;
196 } else if(!strcmp(argv[i], "-ci")){
198 } else if(!strcmp(argv[i], "-cj")){
200 } else if(!strcmp(argv[i], "-tl")){
202 } else if(!strcmp(argv[i], "-td")){
204 } else if(!strcmp(argv[i], "-tb")){
206 } else if(!strcmp(argv[i], "-lc")){
207 if(++i >= argc) usage();
208 lcnum = atoi(argv[i]);
209 } else if(!strcmp(argv[i], "-nc")){
210 if(++i >= argc) usage();
211 ncnum = atoi(argv[i]);
212 } else if(!strcmp(argv[i], "-ls")){
213 if(++i >= argc) usage();
214 lsmax = atoi(argv[i]);
215 } else if(!strcmp(argv[i], "-ca")){
216 if(++i >= argc) usage();
217 capnum = atoi(argv[i]);
218 } else if(!strcmp(argv[i], "-nl")){
220 } else if(!strcmp(argv[i], "-nb")){
243 if(!path || !rstr) usage();
244 int rnum = atoi(rstr);
245 if(rnum < 1) usage();
246 int lmemb = lmstr ? atoi(lmstr) : -1;
247 int nmemb = nmstr ? atoi(nmstr) : -1;
248 int bnum = bstr ? atoi(bstr) : -1;
249 int apow = astr ? atoi(astr) : -1;
250 int fpow = fstr ? atoi(fstr) : -1;
251 int rv = procwrite(path, rnum, lmemb, nmemb, bnum, apow, fpow,
252 mt, cmp, opts, lcnum, ncnum, lsmax, capnum, omode);
257 /* parse arguments of read command */
258 static int runread(int argc, char **argv){
266 for(int i = 2; i < argc; i++){
267 if(!path && argv[i][0] == '-'){
268 if(!strcmp(argv[i], "-mt")){
270 } else if(!strcmp(argv[i], "-cd")){
271 cmp = tcbdbcmpdecimal;
272 } else if(!strcmp(argv[i], "-ci")){
274 } else if(!strcmp(argv[i], "-cj")){
276 } else if(!strcmp(argv[i], "-lc")){
277 if(++i >= argc) usage();
278 lcnum = atoi(argv[i]);
279 } else if(!strcmp(argv[i], "-nc")){
280 if(++i >= argc) usage();
281 ncnum = atoi(argv[i]);
282 } else if(!strcmp(argv[i], "-nl")){
284 } else if(!strcmp(argv[i], "-nb")){
286 } else if(!strcmp(argv[i], "-wb")){
298 int rv = procread(path, mt, cmp, lcnum, ncnum, omode, wb);
303 /* parse arguments of remove command */
304 static int runremove(int argc, char **argv){
311 for(int i = 2; i < argc; i++){
312 if(!path && argv[i][0] == '-'){
313 if(!strcmp(argv[i], "-mt")){
315 } else if(!strcmp(argv[i], "-cd")){
316 cmp = tcbdbcmpdecimal;
317 } else if(!strcmp(argv[i], "-ci")){
319 } else if(!strcmp(argv[i], "-cj")){
321 } else if(!strcmp(argv[i], "-lc")){
322 if(++i >= argc) usage();
323 lcnum = atoi(argv[i]);
324 } else if(!strcmp(argv[i], "-nc")){
325 if(++i >= argc) usage();
326 ncnum = atoi(argv[i]);
327 } else if(!strcmp(argv[i], "-nl")){
329 } else if(!strcmp(argv[i], "-nb")){
341 int rv = procremove(path, mt, cmp, lcnum, ncnum, omode);
346 /* parse arguments of rcat command */
347 static int runrcat(int argc, char **argv){
365 for(int i = 2; i < argc; i++){
366 if(!path && argv[i][0] == '-'){
367 if(!strcmp(argv[i], "-mt")){
369 } else if(!strcmp(argv[i], "-cd")){
370 cmp = tcbdbcmpdecimal;
371 } else if(!strcmp(argv[i], "-ci")){
373 } else if(!strcmp(argv[i], "-cj")){
375 } else if(!strcmp(argv[i], "-tl")){
377 } else if(!strcmp(argv[i], "-td")){
379 } else if(!strcmp(argv[i], "-tb")){
381 } else if(!strcmp(argv[i], "-lc")){
382 if(++i >= argc) usage();
383 lcnum = atoi(argv[i]);
384 } else if(!strcmp(argv[i], "-nc")){
385 if(++i >= argc) usage();
386 ncnum = atoi(argv[i]);
387 } else if(!strcmp(argv[i], "-ls")){
388 if(++i >= argc) usage();
389 lsmax = atoi(argv[i]);
390 } else if(!strcmp(argv[i], "-ca")){
391 if(++i >= argc) usage();
392 capnum = atoi(argv[i]);
393 } else if(!strcmp(argv[i], "-nl")){
395 } else if(!strcmp(argv[i], "-nb")){
397 } else if(!strcmp(argv[i], "-pn")){
398 if(++i >= argc) usage();
399 pnum = atoi(argv[i]);
400 } else if(!strcmp(argv[i], "-rl")){
423 if(!path || !rstr) usage();
424 int rnum = atoi(rstr);
425 if(rnum < 1) usage();
426 int lmemb = lmstr ? atoi(lmstr) : -1;
427 int nmemb = nmstr ? atoi(nmstr) : -1;
428 int bnum = bstr ? atoi(bstr) : -1;
429 int apow = astr ? atoi(astr) : -1;
430 int fpow = fstr ? atoi(fstr) : -1;
431 int rv = procrcat(path, rnum, lmemb, nmemb, bnum, apow, fpow, mt, cmp, opts,
432 lcnum, ncnum, lsmax, capnum, omode, pnum, rl);
437 /* parse arguments of queue command */
438 static int runqueue(int argc, char **argv){
454 for(int i = 2; i < argc; i++){
455 if(!path && argv[i][0] == '-'){
456 if(!strcmp(argv[i], "-mt")){
458 } else if(!strcmp(argv[i], "-cd")){
459 cmp = tcbdbcmpdecimal;
460 } else if(!strcmp(argv[i], "-ci")){
462 } else if(!strcmp(argv[i], "-cj")){
464 } else if(!strcmp(argv[i], "-tl")){
466 } else if(!strcmp(argv[i], "-td")){
468 } else if(!strcmp(argv[i], "-tb")){
470 } else if(!strcmp(argv[i], "-lc")){
471 if(++i >= argc) usage();
472 lcnum = atoi(argv[i]);
473 } else if(!strcmp(argv[i], "-nc")){
474 if(++i >= argc) usage();
475 ncnum = atoi(argv[i]);
476 } else if(!strcmp(argv[i], "-ls")){
477 if(++i >= argc) usage();
478 lsmax = atoi(argv[i]);
479 } else if(!strcmp(argv[i], "-ca")){
480 if(++i >= argc) usage();
481 capnum = atoi(argv[i]);
482 } else if(!strcmp(argv[i], "-nl")){
484 } else if(!strcmp(argv[i], "-nb")){
507 if(!path || !rstr) usage();
508 int rnum = atoi(rstr);
509 if(rnum < 1) usage();
510 int lmemb = lmstr ? atoi(lmstr) : -1;
511 int nmemb = nmstr ? atoi(nmstr) : -1;
512 int bnum = bstr ? atoi(bstr) : -1;
513 int apow = astr ? atoi(astr) : -1;
514 int fpow = fstr ? atoi(fstr) : -1;
515 int rv = procqueue(path, rnum, lmemb, nmemb, bnum, apow, fpow,
516 mt, cmp, opts, lcnum, ncnum, lsmax, capnum, omode);
521 /* parse arguments of misc command */
522 static int runmisc(int argc, char **argv){
528 for(int i = 2; i < argc; i++){
529 if(!path && argv[i][0] == '-'){
530 if(!strcmp(argv[i], "-mt")){
532 } else if(!strcmp(argv[i], "-tl")){
534 } else if(!strcmp(argv[i], "-td")){
536 } else if(!strcmp(argv[i], "-tb")){
538 } else if(!strcmp(argv[i], "-nl")){
540 } else if(!strcmp(argv[i], "-nb")){
553 if(!path || !rstr) usage();
554 int rnum = atoi(rstr);
555 if(rnum < 1) usage();
556 int rv = procmisc(path, rnum, mt, opts, omode);
561 /* parse arguments of wicked command */
562 static int runwicked(int argc, char **argv){
568 for(int i = 2; i < argc; i++){
569 if(!path && argv[i][0] == '-'){
570 if(!strcmp(argv[i], "-mt")){
572 } else if(!strcmp(argv[i], "-tl")){
574 } else if(!strcmp(argv[i], "-td")){
576 } else if(!strcmp(argv[i], "-tb")){
578 } else if(!strcmp(argv[i], "-nl")){
580 } else if(!strcmp(argv[i], "-nb")){
593 if(!path || !rstr) usage();
594 int rnum = atoi(rstr);
595 if(rnum < 1) usage();
596 int rv = procwicked(path, rnum, mt, opts, omode);
601 /* perform write command */
602 static int procwrite(const char *path, int rnum, int lmemb, int nmemb, int bnum,
603 int apow, int fpow, bool mt, BDBCMP cmp, int opts,
604 int lcnum, int ncnum, int lsmax, int capnum, int omode){
605 iprintf("<Writing Test>\n path=%s rnum=%d lmemb=%d nmemb=%d bnum=%d apow=%d fpow=%d"
606 " mt=%d cmp=%p opts=%d lcnum=%d ncnum=%d lsmax=%d capnum=%d omode=%d\n\n",
607 path, rnum, lmemb, nmemb, bnum, apow, fpow, mt, (void *)(intptr_t)cmp,
608 opts, lcnum, ncnum, lsmax, capnum, omode);
610 double stime = tctime();
611 TCBDB *bdb = tcbdbnew();
612 if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
613 if(mt && !tcbdbsetmutex(bdb)){
614 eprint(bdb, "tcbdbsetmutex");
617 if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)){
618 eprint(bdb, "tcbdbsetcmpfunc");
621 if(!tcbdbtune(bdb, lmemb, nmemb, bnum, apow, fpow, opts)){
622 eprint(bdb, "tcbdbtune");
625 if(!tcbdbsetcache(bdb, lcnum, ncnum)){
626 eprint(bdb, "tcbdbsetcache");
629 if(!tcbdbsetlsmax(bdb, lsmax)){
630 eprint(bdb, "tcbdbsetlsmax");
633 if(!tcbdbsetcapnum(bdb, capnum)){
634 eprint(bdb, "tcbdbsetcapnum");
637 if(!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | BDBOTRUNC)){
638 eprint(bdb, "tcbdbopen");
641 for(int i = 1; i <= rnum; i++){
644 if(cmp == tcbdbcmpdecimal){
645 len = sprintf(buf, "%d", i);
646 } else if(cmp == tcbdbcmpint32){
648 memcpy(buf, &lnum, sizeof(lnum));
650 } else if(cmp == tcbdbcmpint64){
652 memcpy(buf, &llnum, sizeof(llnum));
655 len = sprintf(buf, "%08d", i);
657 if(!tcbdbput(bdb, buf, len, buf, len)){
658 eprint(bdb, "tcbdbput");
662 if(rnum > 250 && i % (rnum / 250) == 0){
665 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
668 iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
669 iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
671 if(!tcbdbclose(bdb)){
672 eprint(bdb, "tcbdbclose");
676 iprintf("time: %.3f\n", tctime() - stime);
677 iprintf("%s\n\n", err ? "error" : "ok");
682 /* perform read command */
683 static int procread(const char *path, bool mt, BDBCMP cmp, int lcnum, int ncnum,
685 iprintf("<Reading Test>\n path=%s mt=%d cmp=%p lcnum=%d ncnum=%d omode=%d wb=%d\n",
686 path, mt, (void *)(intptr_t)cmp, lcnum, ncnum, omode, wb);
688 double stime = tctime();
689 TCBDB *bdb = tcbdbnew();
690 if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
691 if(mt && !tcbdbsetmutex(bdb)){
692 eprint(bdb, "tcbdbsetmutex");
695 if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)){
696 eprint(bdb, "tcbdbsetcmpfunc");
699 if(!tcbdbsetcache(bdb, lcnum, ncnum)){
700 eprint(bdb, "tcbdbsetcache");
703 if(!tcbdbopen(bdb, path, BDBOREADER | omode)){
704 eprint(bdb, "tcbdbopen");
707 int rnum = tcbdbrnum(bdb);
708 for(int i = 1; i <= rnum; i++){
709 char kbuf[RECBUFSIZ];
711 if(cmp == tcbdbcmpdecimal){
712 ksiz = sprintf(kbuf, "%d", i);
713 } else if(cmp == tcbdbcmpint32){
715 memcpy(kbuf, &lnum, sizeof(lnum));
717 } else if(cmp == tcbdbcmpint64){
719 memcpy(kbuf, &llnum, sizeof(llnum));
720 ksiz = sizeof(llnum);
722 ksiz = sprintf(kbuf, "%08d", i);
727 const char *vbuf = tcbdbget3(bdb, kbuf, ksiz, &vsiz);
729 eprint(bdb, "tcbdbget3");
734 char *vbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz);
736 eprint(bdb, "tcbdbget");
742 if(rnum > 250 && i % (rnum / 250) == 0){
745 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
748 iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
749 iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
751 if(!tcbdbclose(bdb)){
752 eprint(bdb, "tcbdbclose");
756 iprintf("time: %.3f\n", tctime() - stime);
757 iprintf("%s\n\n", err ? "error" : "ok");
762 /* perform remove command */
763 static int procremove(const char *path, bool mt, BDBCMP cmp, int lcnum, int ncnum, int omode){
764 iprintf("<Removing Test>\n path=%s mt=%d cmp=%p lcnum=%d ncnum=%d omode=%d\n",
765 path, mt, (void *)(intptr_t)cmp, lcnum, ncnum, omode);
767 double stime = tctime();
768 TCBDB *bdb = tcbdbnew();
769 if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
770 if(mt && !tcbdbsetmutex(bdb)){
771 eprint(bdb, "tcbdbsetmutex");
774 if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)){
775 eprint(bdb, "tcbdbsetcmpfunc");
778 if(!tcbdbsetcache(bdb, lcnum, ncnum)){
779 eprint(bdb, "tcbdbsetcache");
782 if(!tcbdbopen(bdb, path, BDBOWRITER | omode)){
783 eprint(bdb, "tcbdbopen");
786 int rnum = tcbdbrnum(bdb);
787 for(int i = 1; i <= rnum; i++){
788 char kbuf[RECBUFSIZ];
790 if(cmp == tcbdbcmpdecimal){
791 ksiz = sprintf(kbuf, "%d", i);
792 } else if(cmp == tcbdbcmpint32){
794 memcpy(kbuf, &lnum, sizeof(lnum));
796 } else if(cmp == tcbdbcmpint64){
798 memcpy(kbuf, &llnum, sizeof(llnum));
799 ksiz = sizeof(llnum);
801 ksiz = sprintf(kbuf, "%08d", i);
803 if(!tcbdbout(bdb, kbuf, ksiz)){
804 eprint(bdb, "tcbdbout");
808 if(rnum > 250 && i % (rnum / 250) == 0){
811 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
814 iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
815 iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
817 if(!tcbdbclose(bdb)){
818 eprint(bdb, "tcbdbclose");
822 iprintf("time: %.3f\n", tctime() - stime);
823 iprintf("%s\n\n", err ? "error" : "ok");
828 /* perform rcat command */
829 static int procrcat(const char *path, int rnum,
830 int lmemb, int nmemb, int bnum, int apow, int fpow,
831 bool mt, BDBCMP cmp, int opts, int lcnum, int ncnum, int lsmax, int capnum,
832 int omode, int pnum, bool rl){
833 iprintf("<Random Concatenating Test>\n"
834 " path=%s rnum=%d lmemb=%d nmemb=%d bnum=%d apow=%d fpow=%d"
835 " mt=%d cmp=%p opts=%d lcnum=%d ncnum=%d lsmax=%d capnum=%d"
836 " omode=%d pnum=%d rl=%d\n\n",
837 path, rnum, lmemb, nmemb, bnum, apow, fpow, mt, (void *)(intptr_t)cmp,
838 opts, lcnum, ncnum, lsmax, capnum, omode, pnum, rl);
839 if(pnum < 1) pnum = rnum;
841 double stime = tctime();
842 TCBDB *bdb = tcbdbnew();
843 if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
844 if(mt && !tcbdbsetmutex(bdb)){
845 eprint(bdb, "tcbdbsetmutex");
848 if(!tcbdbtune(bdb, lmemb, nmemb, bnum, apow, fpow, opts)){
849 eprint(bdb, "tcbdbtune");
852 if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)){
853 eprint(bdb, "tcbdbsetcmpfunc");
856 if(!tcbdbsetcache(bdb, lcnum, ncnum)){
857 eprint(bdb, "tcbdbsetcache");
860 if(!tcbdbsetlsmax(bdb, lsmax)){
861 eprint(bdb, "tcbdbsetlsmax");
864 if(!tcbdbsetcapnum(bdb, capnum)){
865 eprint(bdb, "tcbdbsetcapnum");
868 if(!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | BDBOTRUNC | omode)){
869 eprint(bdb, "tcbdbopen");
872 for(int i = 1; i <= rnum; i++){
873 char kbuf[RECBUFSIZ];
875 if(cmp == tcbdbcmpdecimal){
876 ksiz = sprintf(kbuf, "%d", myrand(pnum));
877 } else if(cmp == tcbdbcmpint32){
878 int32_t lnum = myrand(pnum);
879 memcpy(kbuf, &lnum, sizeof(lnum));
881 } else if(cmp == tcbdbcmpint64){
882 int64_t llnum = myrand(pnum);
883 memcpy(kbuf, &llnum, sizeof(llnum));
884 ksiz = sizeof(llnum);
886 ksiz = sprintf(kbuf, "%08d", myrand(pnum));
890 int vsiz = myrand(PATH_MAX);
891 for(int j = 0; j < vsiz; j++){
892 vbuf[j] = myrand(0x100);
894 if(!tcbdbputcat(bdb, kbuf, ksiz, vbuf, vsiz)){
895 eprint(bdb, "tcbdbputcat");
900 if(!tcbdbputcat(bdb, kbuf, ksiz, kbuf, ksiz)){
901 eprint(bdb, "tcbdbputcat");
906 if(rnum > 250 && i % (rnum / 250) == 0){
909 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
912 iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
913 iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
915 if(!tcbdbclose(bdb)){
916 eprint(bdb, "tcbdbclose");
920 iprintf("time: %.3f\n", tctime() - stime);
921 iprintf("%s\n\n", err ? "error" : "ok");
926 /* perform queue command */
927 static int procqueue(const char *path, int rnum, int lmemb, int nmemb, int bnum,
928 int apow, int fpow, bool mt, BDBCMP cmp, int opts,
929 int lcnum, int ncnum, int lsmax, int capnum, int omode){
930 iprintf("<Queueing Test>\n path=%s rnum=%d lmemb=%d nmemb=%d bnum=%d apow=%d fpow=%d"
931 " mt=%d cmp=%p opts=%d lcnum=%d ncnum=%d lsmax=%d capnum=%d omode=%d\n\n",
932 path, rnum, lmemb, nmemb, bnum, apow, fpow, mt, (void *)(intptr_t)cmp,
933 opts, lcnum, ncnum, lsmax, capnum, omode);
935 double stime = tctime();
936 TCBDB *bdb = tcbdbnew();
937 if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
938 if(mt && !tcbdbsetmutex(bdb)){
939 eprint(bdb, "tcbdbsetmutex");
942 if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)){
943 eprint(bdb, "tcbdbsetcmpfunc");
946 if(!tcbdbtune(bdb, lmemb, nmemb, bnum, apow, fpow, opts)){
947 eprint(bdb, "tcbdbtune");
950 if(!tcbdbsetcache(bdb, lcnum, ncnum)){
951 eprint(bdb, "tcbdbsetcache");
954 if(!tcbdbsetlsmax(bdb, lsmax)){
955 eprint(bdb, "tcbdbsetlsmax");
958 if(!tcbdbsetcapnum(bdb, capnum)){
959 eprint(bdb, "tcbdbsetcapnum");
962 if(!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | BDBOTRUNC)){
963 eprint(bdb, "tcbdbopen");
966 int deqfreq = (lmemb > 0) ? lmemb * 2 : 256;
967 BDBCUR *cur = tcbdbcurnew(bdb);
968 for(int i = 1; i <= rnum; i++){
971 if(cmp == tcbdbcmpdecimal){
972 len = sprintf(buf, "%d", i);
973 } else if(cmp == tcbdbcmpint32){
975 memcpy(buf, &lnum, sizeof(lnum));
977 } else if(cmp == tcbdbcmpint64){
979 memcpy(buf, &llnum, sizeof(llnum));
982 len = sprintf(buf, "%08d", i);
984 if(!tcbdbput(bdb, buf, len, buf, len)){
985 eprint(bdb, "tcbdbput");
989 if(myrand(deqfreq) == 0){
990 if(!tcbdbcurfirst(cur) && tcbdbecode(bdb) != TCENOREC){
991 eprint(bdb, "tcbdbcurfirst");
995 int num = myrand(deqfreq * 2 + 1);
997 if(tcbdbcurout(cur)){
1000 if(tcbdbecode(bdb) != TCENOREC){
1001 eprint(bdb, "tcbdbcurout");
1009 if(rnum > 250 && i % (rnum / 250) == 0){
1012 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
1015 if(!tcbdbcurfirst(cur) && tcbdbecode(bdb) != TCENOREC){
1016 eprint(bdb, "tcbdbcurfirst");
1020 if(tcbdbcurout(cur)) continue;
1021 if(tcbdbecode(bdb) != TCENOREC){
1022 eprint(bdb, "tcbdbcurout");
1028 iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
1029 iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
1031 if(!tcbdbclose(bdb)){
1032 eprint(bdb, "tcbdbclose");
1036 iprintf("time: %.3f\n", tctime() - stime);
1037 iprintf("%s\n\n", err ? "error" : "ok");
1042 /* perform misc command */
1043 static int procmisc(const char *path, int rnum, bool mt, int opts, int omode){
1044 iprintf("<Miscellaneous Test>\n path=%s rnum=%d mt=%d opts=%d omode=%d\n\n",
1045 path, rnum, mt, opts, omode);
1047 double stime = tctime();
1048 TCBDB *bdb = tcbdbnew();
1049 if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
1050 if(mt && !tcbdbsetmutex(bdb)){
1051 eprint(bdb, "tcbdbsetmutex");
1054 if(!tcbdbtune(bdb, 10, 10, rnum / 50, 100, -1, opts)){
1055 eprint(bdb, "tcbdbtune");
1058 if(!tcbdbsetcache(bdb, 128, 256)){
1059 eprint(bdb, "tcbdbsetcache");
1062 if(!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | BDBOTRUNC | omode)){
1063 eprint(bdb, "tcbdbopen");
1066 iprintf("writing:\n");
1067 for(int i = 1; i <= rnum; i++){
1068 char buf[RECBUFSIZ];
1069 int len = sprintf(buf, "%08d", i);
1070 if(!tcbdbputkeep(bdb, buf, len, buf, len)){
1071 eprint(bdb, "tcbdbputkeep");
1075 if(rnum > 250 && i % (rnum / 250) == 0){
1078 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
1081 iprintf("reading:\n");
1082 for(int i = 1; i <= rnum; i++){
1083 char kbuf[RECBUFSIZ];
1084 int ksiz = sprintf(kbuf, "%08d", i);
1086 char *vbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz);
1088 eprint(bdb, "tcbdbget");
1091 } else if(vsiz != ksiz || memcmp(vbuf, kbuf, vsiz)){
1092 eprint(bdb, "(validation)");
1098 if(rnum > 250 && i % (rnum / 250) == 0){
1101 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
1104 if(tcbdbrnum(bdb) != rnum){
1105 eprint(bdb, "(validation)");
1108 iprintf("random writing:\n");
1109 for(int i = 1; i <= rnum; i++){
1110 char kbuf[RECBUFSIZ];
1111 int ksiz = sprintf(kbuf, "%d", myrand(rnum));
1112 char vbuf[RECBUFSIZ];
1113 int vsiz = myrand(RECBUFSIZ);
1114 memset(vbuf, '*', vsiz);
1115 if(!tcbdbput(bdb, kbuf, ksiz, vbuf, vsiz)){
1116 eprint(bdb, "tcbdbput");
1121 char *rbuf = tcbdbget(bdb, kbuf, ksiz, &rsiz);
1123 eprint(bdb, "tcbdbget");
1127 if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
1128 eprint(bdb, "(validation)");
1133 if(rnum > 250 && i % (rnum / 250) == 0){
1136 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
1140 iprintf("word writing:\n");
1141 const char *words[] = {
1142 "a", "A", "bb", "BB", "ccc", "CCC", "dddd", "DDDD", "eeeee", "EEEEEE",
1143 "mikio", "hirabayashi", "tokyo", "cabinet", "hyper", "estraier", "19780211", "birth day",
1144 "one", "first", "two", "second", "three", "third", "four", "fourth", "five", "fifth",
1145 "_[1]_", "uno", "_[2]_", "dos", "_[3]_", "tres", "_[4]_", "cuatro", "_[5]_", "cinco",
1146 "[\xe5\xb9\xb3\xe6\x9e\x97\xe5\xb9\xb9\xe9\x9b\x84]", "[\xe9\xa6\xac\xe9\xb9\xbf]", NULL
1148 for(int i = 0; words[i] != NULL; i += 2){
1149 const char *kbuf = words[i];
1150 int ksiz = strlen(kbuf);
1151 const char *vbuf = words[i+1];
1152 int vsiz = strlen(vbuf);
1153 if(!tcbdbputkeep(bdb, kbuf, ksiz, vbuf, vsiz)){
1154 eprint(bdb, "tcbdbputkeep");
1158 if(rnum > 250) putchar('.');
1160 if(rnum > 250) iprintf(" (%08d)\n", sizeof(words) / sizeof(*words));
1161 iprintf("random erasing:\n");
1162 for(int i = 1; i <= rnum; i++){
1163 char kbuf[RECBUFSIZ];
1164 int ksiz = sprintf(kbuf, "%d", myrand(rnum));
1165 if(!tcbdbout(bdb, kbuf, ksiz) && tcbdbecode(bdb) != TCENOREC){
1166 eprint(bdb, "tcbdbout");
1170 if(rnum > 250 && i % (rnum / 250) == 0){
1173 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
1176 iprintf("writing:\n");
1177 for(int i = 1; i <= rnum; i++){
1178 char kbuf[RECBUFSIZ];
1179 int ksiz = sprintf(kbuf, "[%d]", i);
1180 char vbuf[RECBUFSIZ];
1181 int vsiz = i % RECBUFSIZ;
1182 memset(vbuf, '*', vsiz);
1183 if(!tcbdbputkeep(bdb, kbuf, ksiz, vbuf, vsiz)){
1184 eprint(bdb, "tcbdbputkeep");
1189 char tbuf[PATH_MAX];
1190 for(int j = 0; j < PATH_MAX; j++){
1191 tbuf[j] = myrand(0x100);
1193 if(!tcbdbput(bdb, kbuf, ksiz, tbuf, PATH_MAX)){
1194 eprint(bdb, "tcbdbput");
1199 if(rnum > 250 && i % (rnum / 250) == 0){
1202 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
1205 iprintf("erasing:\n");
1206 for(int i = 1; i <= rnum; i++){
1208 char kbuf[RECBUFSIZ];
1209 int ksiz = sprintf(kbuf, "[%d]", i);
1210 if(!tcbdbout(bdb, kbuf, ksiz)){
1211 eprint(bdb, "tcbdbout");
1215 if(tcbdbout(bdb, kbuf, ksiz) || tcbdbecode(bdb) != TCENOREC){
1216 eprint(bdb, "tcbdbout");
1221 if(rnum > 250 && i % (rnum / 250) == 0){
1224 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
1227 iprintf("random writing and reopening:\n");
1228 for(int i = 1; i <= rnum; i++){
1229 if(myrand(10) == 0){
1232 ksiz = (myrand(5) == 0) ? myrand(UINT16_MAX) : myrand(RECBUFSIZ);
1233 kbuf = tcmalloc(ksiz + 1);
1234 for(int j = 0; j < ksiz; j++){
1235 kbuf[j] = 128 + myrand(128);
1237 vsiz = (myrand(5) == 0) ? myrand(UINT16_MAX) : myrand(RECBUFSIZ);
1238 vbuf = tcmalloc(vsiz + 1);
1239 for(int j = 0; j < vsiz; j++){
1240 vbuf[j] = myrand(256);
1244 if(!tcbdbput(bdb, kbuf, ksiz, vbuf, vsiz)){
1245 eprint(bdb, "tcbdbput");
1250 if(!tcbdbputcat(bdb, kbuf, ksiz, vbuf, vsiz)){
1251 eprint(bdb, "tcbdbputcat");
1256 if(!tcbdbputdup(bdb, kbuf, ksiz, vbuf, vsiz)){
1257 eprint(bdb, "tcbdbputdup");
1262 if(!tcbdbputdupback(bdb, kbuf, ksiz, vbuf, vsiz)){
1263 eprint(bdb, "tcbdbputdupback");
1268 if(!tcbdbout(bdb, kbuf, ksiz) && tcbdbecode(bdb) != TCENOREC){
1269 eprint(bdb, "tcbdbout");
1277 char kbuf[RECBUFSIZ];
1278 int ksiz = myrand(RECBUFSIZ);
1279 memset(kbuf, '@', ksiz);
1280 char vbuf[RECBUFSIZ];
1281 int vsiz = myrand(RECBUFSIZ);
1282 memset(vbuf, '@', vsiz);
1283 if(!tcbdbput(bdb, kbuf, ksiz, vbuf, vsiz)){
1284 eprint(bdb, "tcbdbputcat");
1289 if(rnum > 250 && i % (rnum / 250) == 0){
1292 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
1295 if(!tcbdbclose(bdb)){
1296 eprint(bdb, "tcbdbclose");
1299 if(!tcbdbopen(bdb, path, BDBOWRITER | omode)){
1300 eprint(bdb, "tcbdbopen");
1303 iprintf("checking:\n");
1304 for(int i = 1; i <= rnum; i++){
1305 char kbuf[RECBUFSIZ];
1306 int ksiz = sprintf(kbuf, "[%d]", i);
1308 char *vbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz);
1311 eprint(bdb, "tcbdbget");
1315 if(vsiz != i % RECBUFSIZ && vsiz != PATH_MAX){
1316 eprint(bdb, "(validation)");
1322 if(vbuf || tcbdbecode(bdb) != TCENOREC){
1323 eprint(bdb, "(validation)");
1330 if(rnum > 250 && i % (rnum / 250) == 0){
1333 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
1336 iprintf("writing:\n");
1337 for(int i = 1; i <= rnum; i++){
1338 char buf[RECBUFSIZ];
1339 int len = sprintf(buf, "%08d", i);
1340 if(!tcbdbput(bdb, buf, len, buf, len)){
1341 eprint(bdb, "tcbdbput");
1346 TCLIST *vals = tclistnew();
1347 for(int j = myrand(5) + 1; j >= 0; j--){
1348 tclistpush(vals, buf, len);
1350 if(!tcbdbputdup3(bdb, buf, len, vals)){
1351 eprint(bdb, "tcbdbput3");
1357 if(rnum > 250 && i % (rnum / 250) == 0){
1360 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
1363 iprintf("reading:\n");
1364 for(int i = 1; i <= rnum; i++){
1365 char kbuf[RECBUFSIZ];
1366 int ksiz = sprintf(kbuf, "%08d", i);
1368 char *vbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz);
1370 eprint(bdb, "tcbdbget");
1373 } else if(vsiz != ksiz || memcmp(vbuf, kbuf, vsiz)){
1374 eprint(bdb, "(validation)");
1380 if(rnum > 250 && i % (rnum / 250) == 0){
1383 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
1386 iprintf("word checking:\n");
1387 for(int i = 0; words[i] != NULL; i += 2){
1388 const char *kbuf = words[i];
1389 int ksiz = strlen(kbuf);
1390 const char *vbuf = words[i+1];
1391 int vsiz = strlen(vbuf);
1393 char *rbuf = tcbdbget(bdb, kbuf, ksiz, &rsiz);
1395 eprint(bdb, "tcbdbget");
1398 } else if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
1399 eprint(bdb, "(validation)");
1405 if(rnum > 250) putchar('.');
1407 if(rnum > 250) iprintf(" (%08d)\n", sizeof(words) / sizeof(*words));
1408 iprintf("cursor checking:\n");
1409 BDBCUR *cur = tcbdbcurnew(bdb);
1410 if(!tcbdbcurfirst(cur)){
1411 eprint(bdb, "tcbdbcurfirst");
1417 for(int i = 1; (kbuf = tcbdbcurkey(cur, &ksiz)) != NULL; i++, inum++){
1419 char *vbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz);
1421 eprint(bdb, "tcbdbget");
1429 if(rnum > 250 && i % (rnum / 250) == 0){
1432 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
1435 if(rnum > 250) iprintf(" (%08d)\n", inum);
1436 if(tcbdbecode(bdb) != TCENOREC || inum != tcbdbrnum(bdb)){
1437 eprint(bdb, "(validation)");
1440 iprintf("cursor updating:\n");
1441 if(!tcbdbcurfirst(cur)){
1442 eprint(bdb, "tcbdbcurfirst");
1446 for(int i = 1; !err && (kbuf = tcbdbcurkey(cur, &ksiz)) != NULL; i++, inum++){
1449 if(!tcbdbputdup(bdb, kbuf, ksiz, "0123456789", 10)){
1450 eprint(bdb, "tcbdbputcat");
1455 if(!tcbdbout(bdb, kbuf, ksiz)){
1456 eprint(bdb, "tcbdbout");
1461 if(!tcbdbcurput(cur, kbuf, ksiz, BDBCPCURRENT)){
1462 eprint(bdb, "tcbdbcurput");
1467 if(!tcbdbcurput(cur, kbuf, ksiz, BDBCPBEFORE)){
1468 eprint(bdb, "tcbdbcurput");
1473 if(!tcbdbcurput(cur, kbuf, ksiz, BDBCPAFTER)){
1474 eprint(bdb, "tcbdbcurput");
1479 if(!tcbdbcurout(cur) && tcbdbecode(bdb) != TCENOREC){
1480 eprint(bdb, "tcbdbcurout");
1487 if(rnum > 250 && i % (rnum / 250) == 0){
1490 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
1493 if(rnum > 250) iprintf(" (%08d)\n", inum);
1494 if(tcbdbecode(bdb) != TCENOREC){
1495 eprint(bdb, "(validation)");
1498 if(!tcbdbsync(bdb)){
1499 eprint(bdb, "tcbdbsync");
1502 iprintf("cursor updating from empty:\n");
1505 for(int i = 1; (kbuf = tcbdbcurkey(cur, &ksiz)) != NULL; i++, inum++){
1507 if(!tcbdbcurout(cur) && tcbdbecode(bdb) != TCENOREC){
1508 eprint(bdb, "tcbdbcurout");
1511 if(rnum > 250 && i % (rnum / 250) == 0){
1514 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
1517 if(rnum > 250) iprintf(" (%08d)\n", inum);
1518 if(tcbdbrnum(bdb) != 0){
1519 eprint(bdb, "(validation)");
1522 if(!tcbdbput2(bdb, "one", "first")){
1523 eprint(bdb, "tcbdbput");
1526 if(!tcbdbcurlast(cur)){
1527 eprint(bdb, "tcbdbcurlast");
1530 if(!tcbdbcurput2(cur, "second", BDBCPCURRENT) || !tcbdbcurput2(cur, "first", BDBCPBEFORE) ||
1531 !tcbdbcurput2(cur, "zero", BDBCPBEFORE) || !tcbdbcurput2(cur, "top", BDBCPBEFORE)){
1532 eprint(bdb, "tcbdbcurput2");
1535 if(!tcbdbcurlast(cur)){
1536 eprint(bdb, "tcbdbcurlast");
1539 if(!tcbdbcurput2(cur, "third", BDBCPAFTER) || !tcbdbcurput2(cur, "fourth", BDBCPAFTER) ||
1540 !tcbdbcurput2(cur, "end", BDBCPCURRENT) || !tcbdbcurput2(cur, "bottom", BDBCPAFTER)){
1541 eprint(bdb, "tcbdbcurput2");
1544 iprintf("checking transaction commit:\n");
1545 if(!tcbdbtranbegin(bdb)){
1546 eprint(bdb, "tcbdbtranbegin");
1549 for(int i = 1; i <= rnum; i++){
1550 char kbuf[RECBUFSIZ];
1551 int ksiz = sprintf(kbuf, "%d", myrand(rnum));
1552 if(!tcbdbputdup(bdb, kbuf, ksiz, kbuf, ksiz)){
1553 eprint(bdb, "tcbdbputdup");
1557 if(rnum > 250 && i % (rnum / 250) == 0){
1560 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
1563 if(!tcbdbtrancommit(bdb)){
1564 eprint(bdb, "tcbdbtrancommit");
1567 iprintf("checking transaction abort:\n");
1568 uint64_t ornum = tcbdbrnum(bdb);
1569 if(!tcbdbtranbegin(bdb)){
1570 eprint(bdb, "tcbdbtranbegin");
1573 for(int i = 1; i <= rnum; i++){
1574 char kbuf[RECBUFSIZ];
1575 int ksiz = sprintf(kbuf, "%d", myrand(rnum));
1576 if(!tcbdbout(bdb, kbuf, ksiz) && tcbdbecode(bdb) != TCENOREC){
1577 eprint(bdb, "tcbdbout");
1581 if(rnum > 250 && i % (rnum / 250) == 0){
1584 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
1587 if(!tcbdbtranabort(bdb)){
1588 eprint(bdb, "tcbdbtranabort");
1591 if(tcbdbrnum(bdb) != ornum){
1592 eprint(bdb, "(validation)");
1596 if(!tcbdbcurfirst(cur)){
1597 eprint(bdb, "tcbdbcurfirst");
1600 for(int i = 1; i < 500 && !err && (kbuf = tcbdbcurkey(cur, &ksiz)) != NULL; i++){
1602 if(myrand(20) == 0){
1603 if(!tcbdbget3(bdb, kbuf, ksiz, &vsiz)){
1604 eprint(bdb, "tcbdbget3");
1607 if(myrand(2) == 0 && !tcbdbout(bdb, kbuf, ksiz)){
1608 eprint(bdb, "tcbdbget3");
1611 if(myrand(2) == 0 && !tcbdbputdup(bdb, kbuf, ksiz, kbuf, ksiz)){
1612 eprint(bdb, "tcbdbput");
1616 if(!tcbdbcurout(cur)){
1617 eprint(bdb, "tcbdbcurout");
1622 if(myrand(30) == 0 && !tcbdbcurfirst(cur)){
1623 eprint(bdb, "tcbdbcurfirst");
1628 if(!tcbdbvanish(bdb)){
1629 eprint(bdb, "tcbdbvanish");
1632 if(!tcbdbtranbegin(bdb)){
1633 eprint(bdb, "tcbdbtranbegin");
1636 if(!tcbdbput2(bdb, "mikio", "hirabayashi")){
1637 eprint(bdb, "tcbdbput2");
1641 iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
1642 iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
1644 if(!tcbdbclose(bdb)){
1645 eprint(bdb, "tcbdbclose");
1649 iprintf("time: %.3f\n", tctime() - stime);
1650 iprintf("%s\n\n", err ? "error" : "ok");
1655 /* perform wicked command */
1656 static int procwicked(const char *path, int rnum, bool mt, int opts, int omode){
1657 iprintf("<Wicked Writing Test>\n path=%s rnum=%d mt=%d opts=%d omode=%d\n\n",
1658 path, rnum, mt, opts, omode);
1660 double stime = tctime();
1661 TCBDB *bdb = tcbdbnew();
1662 if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
1663 if(mt && !tcbdbsetmutex(bdb)){
1664 eprint(bdb, "tcbdbsetmutex");
1667 if(!tcbdbtune(bdb, 10, 10, rnum / 50, 100, -1, opts)){
1668 eprint(bdb, "tcbdbtune");
1671 if(!tcbdbsetcache(bdb, 128, 256)){
1672 eprint(bdb, "tcbdbsetcache");
1675 if(!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | BDBOTRUNC | omode)){
1676 eprint(bdb, "tcbdbopen");
1679 BDBCUR *cur = tcbdbcurnew(bdb);
1680 if(!tcbdbcurfirst(cur) && tcbdbecode(bdb) != TCENOREC){
1681 eprint(bdb, "tcbdbcurfirst");
1684 TCMAP *map = tcmapnew2(rnum / 5);
1685 for(int i = 1; i <= rnum && !err; i++){
1686 char kbuf[RECBUFSIZ];
1687 int ksiz = sprintf(kbuf, "%d", myrand(rnum));
1688 char vbuf[RECBUFSIZ];
1689 int vsiz = myrand(RECBUFSIZ);
1690 memset(vbuf, '*', vsiz);
1696 if(!tcbdbput(bdb, kbuf, ksiz, vbuf, vsiz)){
1697 eprint(bdb, "tcbdbput");
1700 tcmapput(map, kbuf, ksiz, vbuf, vsiz);
1704 if(!tcbdbput2(bdb, kbuf, vbuf)){
1705 eprint(bdb, "tcbdbput2");
1708 tcmapput2(map, kbuf, vbuf);
1712 if(!tcbdbputkeep(bdb, kbuf, ksiz, vbuf, vsiz) && tcbdbecode(bdb) != TCEKEEP){
1713 eprint(bdb, "tcbdbputkeep");
1716 tcmapputkeep(map, kbuf, ksiz, vbuf, vsiz);
1720 if(!tcbdbputkeep2(bdb, kbuf, vbuf) && tcbdbecode(bdb) != TCEKEEP){
1721 eprint(bdb, "tcbdbputkeep2");
1724 tcmapputkeep2(map, kbuf, vbuf);
1728 if(!tcbdbputcat(bdb, kbuf, ksiz, vbuf, vsiz)){
1729 eprint(bdb, "tcbdbputcat");
1732 tcmapputcat(map, kbuf, ksiz, vbuf, vsiz);
1736 if(!tcbdbputcat2(bdb, kbuf, vbuf)){
1737 eprint(bdb, "tcbdbputcat2");
1740 tcmapputcat2(map, kbuf, vbuf);
1744 if(myrand(10) == 0){
1745 if(!tcbdbout(bdb, kbuf, ksiz) && tcbdbecode(bdb) != TCENOREC){
1746 eprint(bdb, "tcbdbout");
1749 tcmapout(map, kbuf, ksiz);
1754 if(myrand(10) == 0){
1755 if(!tcbdbout2(bdb, kbuf) && tcbdbecode(bdb) != TCENOREC){
1756 eprint(bdb, "tcbdbout2");
1759 tcmapout2(map, kbuf);
1764 if(!(rbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz))){
1765 if(tcbdbecode(bdb) != TCENOREC){
1766 eprint(bdb, "tcbdbget");
1769 rbuf = tcsprintf("[%d]", myrand(i + 1));
1770 vsiz = strlen(rbuf);
1772 vsiz += myrand(vsiz);
1773 if(myrand(3) == 0) vsiz += PATH_MAX;
1774 rbuf = tcrealloc(rbuf, vsiz + 1);
1775 for(int j = 0; j < vsiz; j++){
1776 rbuf[j] = myrand(0x100);
1778 if(!tcbdbput(bdb, kbuf, ksiz, rbuf, vsiz)){
1779 eprint(bdb, "tcbdbput");
1782 tcmapput(map, kbuf, ksiz, rbuf, vsiz);
1787 if(!(rbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz)) && tcbdbecode(bdb) != TCENOREC){
1788 eprint(bdb, "tcbdbget");
1795 if(!(rbuf = tcbdbget2(bdb, kbuf)) && tcbdbecode(bdb) != TCENOREC){
1796 eprint(bdb, "tcbdbget");
1803 if(myrand(1) == 0) vsiz = 1;
1804 if(!tcbdbget3(bdb, kbuf, ksiz, &vsiz) && tcbdbecode(bdb) != TCENOREC){
1805 eprint(bdb, "tcbdbget");
1811 if(myrand(rnum / 50) == 0){
1812 if(!tcbdbcurfirst(cur) && tcbdbecode(bdb) != TCENOREC){
1813 eprint(bdb, "tcbdbcurfirst");
1817 TCXSTR *ikey = tcxstrnew();
1818 TCXSTR *ival = tcxstrnew();
1819 for(int j = myrand(rnum) / 1000 + 1; j >= 0; j--){
1821 if(tcbdbcurrec(cur, ikey, ival)){
1822 if(tcbdbvnum(bdb, tcxstrptr(ikey), tcxstrsize(ikey)) != 1){
1823 eprint(bdb, "(validation)");
1826 if(tcxstrsize(ival) != tcbdbvsiz(bdb, tcxstrptr(ikey), tcxstrsize(ikey))){
1827 eprint(bdb, "(validation)");
1831 int ecode = tcbdbecode(bdb);
1832 if(ecode != TCEINVALID && ecode != TCENOREC){
1833 eprint(bdb, "tcbdbcurrec");
1839 char *ikbuf = tcbdbcurkey(cur, &iksiz);
1843 int ecode = tcbdbecode(bdb);
1844 if(ecode != TCEINVALID && ecode != TCENOREC){
1845 eprint(bdb, "tcbdbcurkey");
1857 if(myrand(10000) == 0) srand((unsigned int)(tctime() * 1000) % UINT_MAX);
1858 if(myrand(rnum / 32 + 1) == 0){
1859 if(!tcbdbcurfirst(cur) && tcbdbecode(bdb) != TCENOREC){
1860 eprint(bdb, "tcbdbcurfirst");
1863 int cnt = myrand(30);
1864 for(int j = 0; j < rnum && !err; j++){
1865 ksiz = sprintf(kbuf, "%d", i + j);
1867 if(tcbdbout3(bdb, kbuf, ksiz)){
1869 } else if(tcbdbecode(bdb) != TCENOREC){
1870 eprint(bdb, "tcbdbout3");
1873 tcmapout(map, kbuf, ksiz);
1874 } else if(myrand(30) == 0){
1876 char *tkbuf = tcbdbcurkey(cur, &tksiz);
1878 if(tcbdbcurout(cur)){
1881 eprint(bdb, "tcbdbcurout");
1884 tcmapout(map, tkbuf, tksiz);
1886 } else if(tcbdbecode(bdb) != TCENOREC){
1887 eprint(bdb, "tcbdbcurfirst");
1891 if(tcbdbout(bdb, kbuf, ksiz)){
1893 } else if(tcbdbecode(bdb) != TCENOREC){
1894 eprint(bdb, "tcbdbout");
1897 tcmapout(map, kbuf, ksiz);
1904 if(i % 50 == 0) iprintf(" (%08d)\n", i);
1906 if(!tcbdbclose(bdb)){
1907 eprint(bdb, "tcbdbclose");
1910 if(!tcbdbopen(bdb, path, BDBOWRITER | omode)){
1911 eprint(bdb, "tcbdbopen");
1914 } else if(i == rnum / 4){
1915 char *npath = tcsprintf("%s-tmp", path);
1916 if(!tcbdbcopy(bdb, npath)){
1917 eprint(bdb, "tcbdbcopy");
1920 TCBDB *nbdb = tcbdbnew();
1921 if(!tcbdbopen(nbdb, npath, BDBOREADER | omode)){
1922 eprint(nbdb, "tcbdbopen");
1928 if(!tcbdboptimize(bdb, -1, -1, -1, -1, -1, -1)){
1929 eprint(bdb, "tcbdboptimize");
1932 if(!tcbdbcurfirst(cur) && tcbdbecode(bdb) != TCENOREC){
1933 eprint(bdb, "tcbdbcurfirst");
1936 } else if(i == rnum / 8){
1937 if(!tcbdbtranbegin(bdb)){
1938 eprint(bdb, "tcbdbtranbegin");
1941 } else if(i == rnum / 8 + rnum / 16){
1942 if(!tcbdbtrancommit(bdb)){
1943 eprint(bdb, "tcbdbtrancommit");
1948 if(rnum % 50 > 0) iprintf(" (%08d)\n", rnum);
1949 if(!tcbdbsync(bdb)){
1950 eprint(bdb, "tcbdbsync");
1953 if(tcbdbrnum(bdb) != tcmaprnum(map)){
1954 eprint(bdb, "(validation)");
1957 for(int i = 1; i <= rnum && !err; i++){
1958 char kbuf[RECBUFSIZ];
1959 int ksiz = sprintf(kbuf, "%d", i - 1);
1961 const char *vbuf = tcmapget(map, kbuf, ksiz, &vsiz);
1963 char *rbuf = tcbdbget(bdb, kbuf, ksiz, &rsiz);
1967 eprint(bdb, "tcbdbget");
1969 } else if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
1970 eprint(bdb, "(validation)");
1975 if(rbuf || tcbdbecode(bdb) != TCENOREC){
1976 eprint(bdb, "(validation)");
1981 if(i % 50 == 0) iprintf(" (%08d)\n", i);
1983 if(rnum % 50 > 0) iprintf(" (%08d)\n", rnum);
1987 for(int i = 1; (kbuf = tcmapiternext(map, &ksiz)) != NULL; i++){
1990 const char *vbuf = tcmapiterval(kbuf, &vsiz);
1992 char *rbuf = tcbdbget(bdb, kbuf, ksiz, &rsiz);
1994 eprint(bdb, "tcbdbget");
1996 } else if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
1997 eprint(bdb, "(validation)");
2001 if(!tcbdbout(bdb, kbuf, ksiz)){
2002 eprint(bdb, "tcbdbout");
2005 if(i % 50 == 0) iprintf(" (%08d)\n", i);
2007 int mrnum = tcmaprnum(map);
2008 if(mrnum % 50 > 0) iprintf(" (%08d)\n", mrnum);
2009 if(tcbdbrnum(bdb) != 0){
2010 eprint(bdb, "(validation)");
2014 iprintf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
2015 iprintf("size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
2018 if(!tcbdbclose(bdb)){
2019 eprint(bdb, "tcbdbclose");
2023 iprintf("time: %.3f\n", tctime() - stime);
2024 iprintf("%s\n\n", err ? "error" : "ok");