1 /*************************************************************************************************
2 * The test cases of the hash 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(TCHDB *hdb, const char *func);
34 static void mprint(TCHDB *hdb);
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 runmisc(int argc, char **argv);
41 static int runwicked(int argc, char **argv);
42 static int procwrite(const char *path, int rnum, int bnum, int apow, int fpow,
43 bool mt, int opts, int rcnum, int omode, bool as);
44 static int procread(const char *path, bool mt, int rcnum, int omode, bool wb);
45 static int procremove(const char *path, bool mt, int rcnum, int omode);
46 static int procrcat(const char *path, int rnum, int bnum, int apow, int fpow,
47 bool mt, int opts, int rcnum, int omode, int pnum, bool rl);
48 static int procmisc(const char *path, int rnum, bool mt, int opts, int omode);
49 static int procwicked(const char *path, int rnum, bool mt, int opts, int omode);
53 int main(int argc, char **argv){
56 const char *ebuf = getenv("TCDBGFD");
57 if(ebuf) g_dbgfd = atoi(ebuf);
58 srand((unsigned int)(tctime() * 1000) % UINT_MAX);
61 if(!strcmp(argv[1], "write")){
62 rv = runwrite(argc, argv);
63 } else if(!strcmp(argv[1], "read")){
64 rv = runread(argc, argv);
65 } else if(!strcmp(argv[1], "remove")){
66 rv = runremove(argc, argv);
67 } else if(!strcmp(argv[1], "rcat")){
68 rv = runrcat(argc, argv);
69 } else if(!strcmp(argv[1], "misc")){
70 rv = runmisc(argc, argv);
71 } else if(!strcmp(argv[1], "wicked")){
72 rv = runwicked(argc, argv);
80 /* print the usage and exit */
81 static void usage(void){
82 fprintf(stderr, "%s: test cases of the hash database API of Tokyo Cabinet\n", g_progname);
83 fprintf(stderr, "\n");
84 fprintf(stderr, "usage:\n");
85 fprintf(stderr, " %s write [-mt] [-tl] [-td|-tb] [-rc num] [-nl|-nb] [-as] path rnum"
86 " [bnum [apow [fpow]]]\n", g_progname);
87 fprintf(stderr, " %s read [-mt] [-rc num] [-nl|-nb] [-wb] path\n", g_progname);
88 fprintf(stderr, " %s remove [-mt] [-rc num] [-nl|-nb] path\n", g_progname);
89 fprintf(stderr, " %s rcat [-mt] [-rc num] [-tl] [-td|-tb] [-nl|-nb] [-pn num] [-rl]"
90 " path rnum [bnum [apow [fpow]]]\n", g_progname);
91 fprintf(stderr, " %s misc [-mt] [-tl] [-td|-tb] [-nl|-nb] path rnum\n", g_progname);
92 fprintf(stderr, " %s wicked [-mt] [-tl] [-td|-tb] [-nl|-nb] path rnum\n", g_progname);
93 fprintf(stderr, "\n");
98 /* print formatted information string and flush the buffer */
99 static void iprintf(const char *format, ...){
101 va_start(ap, format);
108 /* print error message of hash database */
109 static void eprint(TCHDB *hdb, const char *func){
110 const char *path = tchdbpath(hdb);
111 int ecode = tchdbecode(hdb);
112 fprintf(stderr, "%s: %s: %s: error: %d: %s\n",
113 g_progname, path ? path : "-", func, ecode, tchdberrmsg(ecode));
117 /* print members of hash database */
118 static void mprint(TCHDB *hdb){
119 if(hdb->cnt_writerec < 0) return;
120 iprintf("bucket number: %lld\n", (long long)tchdbbnum(hdb));
121 iprintf("used bucket number: %lld\n", (long long)tchdbbnumused(hdb));
122 iprintf("cnt_writerec: %lld\n", (long long)hdb->cnt_writerec);
123 iprintf("cnt_reuserec: %lld\n", (long long)hdb->cnt_reuserec);
124 iprintf("cnt_moverec: %lld\n", (long long)hdb->cnt_moverec);
125 iprintf("cnt_readrec: %lld\n", (long long)hdb->cnt_readrec);
126 iprintf("cnt_searchfbp: %lld\n", (long long)hdb->cnt_searchfbp);
127 iprintf("cnt_insertfbp: %lld\n", (long long)hdb->cnt_insertfbp);
128 iprintf("cnt_splicefbp: %lld\n", (long long)hdb->cnt_splicefbp);
129 iprintf("cnt_dividefbp: %lld\n", (long long)hdb->cnt_dividefbp);
130 iprintf("cnt_mergefbp: %lld\n", (long long)hdb->cnt_mergefbp);
131 iprintf("cnt_reducefbp: %lld\n", (long long)hdb->cnt_reducefbp);
132 iprintf("cnt_appenddrp: %lld\n", (long long)hdb->cnt_appenddrp);
133 iprintf("cnt_deferdrp: %lld\n", (long long)hdb->cnt_deferdrp);
134 iprintf("cnt_flushdrp: %lld\n", (long long)hdb->cnt_flushdrp);
135 iprintf("cnt_adjrecc: %lld\n", (long long)hdb->cnt_adjrecc);
139 /* get a random number */
140 static int myrand(int range){
141 return (int)((double)range * rand() / (RAND_MAX + 1.0));
145 /* parse arguments of write command */
146 static int runwrite(int argc, char **argv){
157 for(int i = 2; i < argc; i++){
158 if(!path && argv[i][0] == '-'){
159 if(!strcmp(argv[i], "-mt")){
161 } else if(!strcmp(argv[i], "-tl")){
163 } else if(!strcmp(argv[i], "-td")){
165 } else if(!strcmp(argv[i], "-tb")){
167 } else if(!strcmp(argv[i], "-rc")){
168 if(++i >= argc) usage();
169 rcnum = atoi(argv[i]);
170 } else if(!strcmp(argv[i], "-nl")){
172 } else if(!strcmp(argv[i], "-nb")){
174 } else if(!strcmp(argv[i], "-as")){
193 if(!path || !rstr) usage();
194 int rnum = atoi(rstr);
195 if(rnum < 1) usage();
196 int bnum = bstr ? atoi(bstr) : -1;
197 int apow = astr ? atoi(astr) : -1;
198 int fpow = fstr ? atoi(fstr) : -1;
199 int rv = procwrite(path, rnum, bnum, apow, fpow, mt, opts, rcnum, omode, as);
204 /* parse arguments of read command */
205 static int runread(int argc, char **argv){
211 for(int i = 2; i < argc; i++){
212 if(!path && argv[i][0] == '-'){
213 if(!strcmp(argv[i], "-mt")){
215 } else if(!strcmp(argv[i], "-rc")){
216 if(++i >= argc) usage();
217 rcnum = atoi(argv[i]);
218 } else if(!strcmp(argv[i], "-nl")){
220 } else if(!strcmp(argv[i], "-nb")){
222 } else if(!strcmp(argv[i], "-wb")){
234 int rv = procread(path, mt, rcnum, omode, wb);
239 /* parse arguments of remove command */
240 static int runremove(int argc, char **argv){
245 for(int i = 2; i < argc; i++){
246 if(!path && argv[i][0] == '-'){
247 if(!strcmp(argv[i], "-mt")){
249 } else if(!strcmp(argv[i], "-rc")){
250 if(++i >= argc) usage();
251 rcnum = atoi(argv[i]);
252 } else if(!strcmp(argv[i], "-nl")){
254 } else if(!strcmp(argv[i], "-nb")){
266 int rv = procremove(path, mt, rcnum, omode);
271 /* parse arguments of rcat command */
272 static int runrcat(int argc, char **argv){
284 for(int i = 2; i < argc; i++){
285 if(!path && argv[i][0] == '-'){
286 if(!strcmp(argv[i], "-mt")){
288 } else if(!strcmp(argv[i], "-tl")){
290 } else if(!strcmp(argv[i], "-td")){
292 } else if(!strcmp(argv[i], "-tb")){
294 } else if(!strcmp(argv[i], "-rc")){
295 if(++i >= argc) usage();
296 rcnum = atoi(argv[i]);
297 } else if(!strcmp(argv[i], "-nl")){
299 } else if(!strcmp(argv[i], "-nb")){
301 } else if(!strcmp(argv[i], "-pn")){
302 if(++i >= argc) usage();
303 pnum = atoi(argv[i]);
304 } else if(!strcmp(argv[i], "-rl")){
323 if(!path || !rstr) usage();
324 int rnum = atoi(rstr);
325 if(rnum < 1) usage();
326 int bnum = bstr ? atoi(bstr) : -1;
327 int apow = astr ? atoi(astr) : -1;
328 int fpow = fstr ? atoi(fstr) : -1;
329 int rv = procrcat(path, rnum, bnum, apow, fpow, mt, opts, rcnum, omode, pnum, rl);
334 /* parse arguments of misc command */
335 static int runmisc(int argc, char **argv){
341 for(int i = 2; i < argc; i++){
342 if(!path && argv[i][0] == '-'){
343 if(!strcmp(argv[i], "-mt")){
345 } else if(!strcmp(argv[i], "-tl")){
347 } else if(!strcmp(argv[i], "-td")){
349 } else if(!strcmp(argv[i], "-tb")){
351 } else if(!strcmp(argv[i], "-nl")){
353 } else if(!strcmp(argv[i], "-nb")){
366 if(!path || !rstr) usage();
367 int rnum = atoi(rstr);
368 if(rnum < 1) usage();
369 int rv = procmisc(path, rnum, mt, opts, omode);
374 /* parse arguments of wicked command */
375 static int runwicked(int argc, char **argv){
381 for(int i = 2; i < argc; i++){
382 if(!path && argv[i][0] == '-'){
383 if(!strcmp(argv[i], "-mt")){
385 } else if(!strcmp(argv[i], "-tl")){
387 } else if(!strcmp(argv[i], "-td")){
389 } else if(!strcmp(argv[i], "-tb")){
391 } else if(!strcmp(argv[i], "-nl")){
393 } else if(!strcmp(argv[i], "-nb")){
406 if(!path || !rstr) usage();
407 int rnum = atoi(rstr);
408 if(rnum < 1) usage();
409 int rv = procwicked(path, rnum, mt, opts, omode);
414 /* perform write command */
415 static int procwrite(const char *path, int rnum, int bnum, int apow, int fpow,
416 bool mt, int opts, int rcnum, int omode, bool as){
417 iprintf("<Writing Test>\n path=%s rnum=%d bnum=%d apow=%d fpow=%d mt=%d"
418 " opts=%d rcnum=%d omode=%d as=%d\n\n",
419 path, rnum, bnum, apow, fpow, mt, opts, rcnum, omode, as);
421 double stime = tctime();
422 TCHDB *hdb = tchdbnew();
423 if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
424 if(mt && !tchdbsetmutex(hdb)){
425 eprint(hdb, "tchdbsetmutex");
428 if(!tchdbtune(hdb, bnum, apow, fpow, opts)){
429 eprint(hdb, "tchdbtune");
432 if(!tchdbsetcache(hdb, rcnum)){
433 eprint(hdb, "tchdbsetcache");
436 if(!tchdbopen(hdb, path, HDBOWRITER | HDBOCREAT | HDBOTRUNC | omode)){
437 eprint(hdb, "tchdbopen");
440 for(int i = 1; i <= rnum; i++){
442 int len = sprintf(buf, "%08d", i);
444 if(!tchdbputasync(hdb, buf, len, buf, len)){
445 eprint(hdb, "tchdbput");
450 if(!tchdbput(hdb, buf, len, buf, len)){
451 eprint(hdb, "tchdbput");
456 if(rnum > 250 && i % (rnum / 250) == 0){
459 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
462 iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
463 iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
465 if(!tchdbclose(hdb)){
466 eprint(hdb, "tchdbclose");
470 iprintf("time: %.3f\n", tctime() - stime);
471 iprintf("%s\n\n", err ? "error" : "ok");
476 /* perform read command */
477 static int procread(const char *path, bool mt, int rcnum, int omode, bool wb){
478 iprintf("<Reading Test>\n path=%s mt=%d rcnum=%d omode=%d wb=%d\n",
479 path, mt, rcnum, omode, wb);
481 double stime = tctime();
482 TCHDB *hdb = tchdbnew();
483 if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
484 if(mt && !tchdbsetmutex(hdb)){
485 eprint(hdb, "tchdbsetmutex");
488 if(!tchdbsetcache(hdb, rcnum)){
489 eprint(hdb, "tchdbsetcache");
492 if(!tchdbopen(hdb, path, HDBOREADER | omode)){
493 eprint(hdb, "tchdbopen");
496 int rnum = tchdbrnum(hdb);
497 for(int i = 1; i <= rnum; i++){
498 char kbuf[RECBUFSIZ];
499 int ksiz = sprintf(kbuf, "%08d", i);
502 char vbuf[RECBUFSIZ];
503 int vsiz = tchdbget3(hdb, kbuf, ksiz, vbuf, RECBUFSIZ);
505 eprint(hdb, "tchdbget3");
510 char *vbuf = tchdbget(hdb, kbuf, ksiz, &vsiz);
512 eprint(hdb, "tchdbget");
518 if(rnum > 250 && i % (rnum / 250) == 0){
521 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
524 iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
525 iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
527 if(!tchdbclose(hdb)){
528 eprint(hdb, "tchdbclose");
532 iprintf("time: %.3f\n", tctime() - stime);
533 iprintf("%s\n\n", err ? "error" : "ok");
538 /* perform remove command */
539 static int procremove(const char *path, bool mt, int rcnum, int omode){
540 iprintf("<Removing Test>\n path=%s mt=%d rcnum=%d omode=%d\n", path, mt, rcnum, omode);
542 double stime = tctime();
543 TCHDB *hdb = tchdbnew();
544 if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
545 if(mt && !tchdbsetmutex(hdb)){
546 eprint(hdb, "tchdbsetmutex");
549 if(!tchdbsetcache(hdb, rcnum)){
550 eprint(hdb, "tchdbsetcache");
553 if(!tchdbopen(hdb, path, HDBOWRITER | omode)){
554 eprint(hdb, "tchdbopen");
557 int rnum = tchdbrnum(hdb);
558 for(int i = 1; i <= rnum; i++){
559 char kbuf[RECBUFSIZ];
560 int ksiz = sprintf(kbuf, "%08d", i);
561 if(!tchdbout(hdb, kbuf, ksiz)){
562 eprint(hdb, "tchdbout");
566 if(rnum > 250 && i % (rnum / 250) == 0){
569 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
572 iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
573 iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
575 if(!tchdbclose(hdb)){
576 eprint(hdb, "tchdbclose");
580 iprintf("time: %.3f\n", tctime() - stime);
581 iprintf("%s\n\n", err ? "error" : "ok");
586 /* perform rcat command */
587 static int procrcat(const char *path, int rnum, int bnum, int apow, int fpow,
588 bool mt, int opts, int rcnum, int omode, int pnum, bool rl){
589 iprintf("<Random Concatenating Test>\n"
590 " path=%s rnum=%d bnum=%d apow=%d fpow=%d mt=%d opts=%d rcnum=%d"
591 " omode=%d pnum=%d rl=%d\n\n",
592 path, rnum, bnum, apow, fpow, mt, opts, rcnum, omode, pnum, rl);
593 if(pnum < 1) pnum = rnum;
595 double stime = tctime();
596 TCHDB *hdb = tchdbnew();
597 if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
598 if(mt && !tchdbsetmutex(hdb)){
599 eprint(hdb, "tchdbsetmutex");
602 if(!tchdbtune(hdb, bnum, apow, fpow, opts)){
603 eprint(hdb, "tchdbtune");
606 if(!tchdbsetcache(hdb, rcnum)){
607 eprint(hdb, "tchdbsetcache");
610 if(!tchdbopen(hdb, path, HDBOWRITER | HDBOCREAT | HDBOTRUNC | omode)){
611 eprint(hdb, "tchdbopen");
614 for(int i = 1; i <= rnum; i++){
615 char kbuf[RECBUFSIZ];
616 int ksiz = sprintf(kbuf, "%d", myrand(pnum));
619 int vsiz = myrand(PATH_MAX);
620 for(int j = 0; j < vsiz; j++){
621 vbuf[j] = myrand(0x100);
623 if(!tchdbputcat(hdb, kbuf, ksiz, vbuf, vsiz)){
624 eprint(hdb, "tchdbputcat");
629 if(!tchdbputcat(hdb, kbuf, ksiz, kbuf, ksiz)){
630 eprint(hdb, "tchdbputcat");
635 if(rnum > 250 && i % (rnum / 250) == 0){
638 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
641 iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
642 iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
644 if(!tchdbclose(hdb)){
645 eprint(hdb, "tchdbclose");
649 iprintf("time: %.3f\n", tctime() - stime);
650 iprintf("%s\n\n", err ? "error" : "ok");
655 /* perform misc command */
656 static int procmisc(const char *path, int rnum, bool mt, int opts, int omode){
657 iprintf("<Miscellaneous Test>\n path=%s rnum=%d mt=%d opts=%d omode=%d\n\n",
658 path, rnum, mt, opts, omode);
660 double stime = tctime();
661 TCHDB *hdb = tchdbnew();
662 if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
663 if(mt && !tchdbsetmutex(hdb)){
664 eprint(hdb, "tchdbsetmutex");
667 if(!tchdbtune(hdb, rnum / 50, 2, -1, opts)){
668 eprint(hdb, "tchdbtune");
671 if(!tchdbsetcache(hdb, rnum / 10)){
672 eprint(hdb, "tchdbsetcache");
675 if(!tchdbopen(hdb, path, HDBOWRITER | HDBOCREAT | HDBOTRUNC | omode)){
676 eprint(hdb, "tchdbopen");
679 iprintf("writing:\n");
680 for(int i = 1; i <= rnum; i++){
682 int len = sprintf(buf, "%08d", i);
684 if(!tchdbputkeep(hdb, buf, len, buf, len)){
685 eprint(hdb, "tchdbputkeep");
690 if(!tchdbputasync(hdb, buf, len, buf, len)){
691 eprint(hdb, "tchdbputasync");
696 if(rnum > 250 && i % (rnum / 250) == 0){
699 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
702 iprintf("reading:\n");
703 for(int i = 1; i <= rnum; i++){
704 char kbuf[RECBUFSIZ];
705 int ksiz = sprintf(kbuf, "%08d", i);
707 char *vbuf = tchdbget(hdb, kbuf, ksiz, &vsiz);
709 eprint(hdb, "tchdbget");
712 } else if(vsiz != ksiz || memcmp(vbuf, kbuf, vsiz)){
713 eprint(hdb, "(validation)");
719 if(rnum > 250 && i % (rnum / 250) == 0){
722 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
725 if(tchdbrnum(hdb) != rnum){
726 eprint(hdb, "(validation)");
729 iprintf("random writing:\n");
730 for(int i = 1; i <= rnum; i++){
731 char kbuf[RECBUFSIZ];
732 int ksiz = sprintf(kbuf, "%d", myrand(rnum));
733 char vbuf[RECBUFSIZ];
734 int vsiz = myrand(RECBUFSIZ);
735 memset(vbuf, '*', vsiz);
736 if(!tchdbput(hdb, kbuf, ksiz, vbuf, vsiz)){
737 eprint(hdb, "tchdbput");
742 char *rbuf = tchdbget(hdb, kbuf, ksiz, &rsiz);
744 eprint(hdb, "tchdbget");
748 if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
749 eprint(hdb, "(validation)");
754 if(rnum > 250 && i % (rnum / 250) == 0){
757 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
761 iprintf("word writing:\n");
762 const char *words[] = {
763 "a", "A", "bb", "BB", "ccc", "CCC", "dddd", "DDDD", "eeeee", "EEEEEE",
764 "mikio", "hirabayashi", "tokyo", "cabinet", "hyper", "estraier", "19780211", "birth day",
765 "one", "first", "two", "second", "three", "third", "four", "fourth", "five", "fifth",
766 "_[1]_", "uno", "_[2]_", "dos", "_[3]_", "tres", "_[4]_", "cuatro", "_[5]_", "cinco",
767 "[\xe5\xb9\xb3\xe6\x9e\x97\xe5\xb9\xb9\xe9\x9b\x84]", "[\xe9\xa6\xac\xe9\xb9\xbf]", NULL
769 for(int i = 0; words[i] != NULL; i += 2){
770 const char *kbuf = words[i];
771 int ksiz = strlen(kbuf);
772 const char *vbuf = words[i+1];
773 int vsiz = strlen(vbuf);
774 if(!tchdbputkeep(hdb, kbuf, ksiz, vbuf, vsiz)){
775 eprint(hdb, "tchdbputkeep");
779 if(rnum > 250) putchar('.');
781 if(rnum > 250) iprintf(" (%08d)\n", sizeof(words) / sizeof(*words));
782 iprintf("random erasing:\n");
783 for(int i = 1; i <= rnum; i++){
784 char kbuf[RECBUFSIZ];
785 int ksiz = sprintf(kbuf, "%d", myrand(rnum));
786 if(!tchdbout(hdb, kbuf, ksiz) && tchdbecode(hdb) != TCENOREC){
787 eprint(hdb, "tchdbout");
791 if(rnum > 250 && i % (rnum / 250) == 0){
794 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
797 iprintf("writing:\n");
798 for(int i = 1; i <= rnum; i++){
799 char kbuf[RECBUFSIZ];
800 int ksiz = sprintf(kbuf, "[%d]", i);
801 char vbuf[RECBUFSIZ];
802 int vsiz = i % RECBUFSIZ;
803 memset(vbuf, '*', vsiz);
804 if(!tchdbputkeep(hdb, kbuf, ksiz, vbuf, vsiz)){
805 eprint(hdb, "tchdbputkeep");
811 for(int j = 0; j < PATH_MAX; j++){
812 tbuf[j] = myrand(0x100);
814 if(!tchdbput(hdb, kbuf, ksiz, tbuf, PATH_MAX)){
815 eprint(hdb, "tchdbput");
820 if(rnum > 250 && i % (rnum / 250) == 0){
823 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
826 iprintf("erasing:\n");
827 for(int i = 1; i <= rnum; i++){
829 char kbuf[RECBUFSIZ];
830 int ksiz = sprintf(kbuf, "[%d]", i);
831 if(!tchdbout(hdb, kbuf, ksiz)){
832 eprint(hdb, "tchdbout");
836 if(tchdbout(hdb, kbuf, ksiz) || tchdbecode(hdb) != TCENOREC){
837 eprint(hdb, "tchdbout");
842 if(rnum > 250 && i % (rnum / 250) == 0){
845 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
848 iprintf("random writing and reopening:\n");
849 for(int i = 1; i <= rnum; i++){
853 ksiz = (myrand(5) == 0) ? myrand(UINT16_MAX) : myrand(RECBUFSIZ);
854 kbuf = tcmalloc(ksiz + 1);
855 memset(kbuf, '@', ksiz);
856 vsiz = (myrand(5) == 0) ? myrand(UINT16_MAX) : myrand(RECBUFSIZ);
857 vbuf = tcmalloc(vsiz + 1);
858 for(int j = 0; j < vsiz; j++){
859 vbuf[j] = myrand(256);
863 if(!tchdbput(hdb, kbuf, ksiz, vbuf, vsiz)){
864 eprint(hdb, "tchdbput");
869 if(!tchdbputcat(hdb, kbuf, ksiz, vbuf, vsiz)){
870 eprint(hdb, "tchdbputcat");
875 if(!tchdbputasync(hdb, kbuf, ksiz, vbuf, vsiz)){
876 eprint(hdb, "tchdbputasync");
881 if(!tchdbout(hdb, kbuf, ksiz) && tchdbecode(hdb) != TCENOREC){
882 eprint(hdb, "tchdbout");
890 char kbuf[RECBUFSIZ];
891 int ksiz = myrand(RECBUFSIZ);
892 memset(kbuf, '@', ksiz);
893 char vbuf[RECBUFSIZ];
894 int vsiz = myrand(RECBUFSIZ);
895 memset(vbuf, '@', vsiz);
896 if(!tchdbput(hdb, kbuf, ksiz, vbuf, vsiz)){
897 eprint(hdb, "tchdbputcat");
902 if(rnum > 250 && i % (rnum / 250) == 0){
905 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
908 if(!tchdbclose(hdb)){
909 eprint(hdb, "tchdbclose");
912 if(!tchdbopen(hdb, path, HDBOWRITER | omode)){
913 eprint(hdb, "tchdbopen");
916 iprintf("checking:\n");
917 for(int i = 1; i <= rnum; i++){
918 char kbuf[RECBUFSIZ];
919 int ksiz = sprintf(kbuf, "[%d]", i);
921 char *vbuf = tchdbget(hdb, kbuf, ksiz, &vsiz);
924 eprint(hdb, "tchdbget");
928 if(vsiz != i % RECBUFSIZ && vsiz != PATH_MAX){
929 eprint(hdb, "(validation)");
935 if(vbuf || tchdbecode(hdb) != TCENOREC){
936 eprint(hdb, "(validation)");
943 if(rnum > 250 && i % (rnum / 250) == 0){
946 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
949 iprintf("writing:\n");
950 for(int i = 1; i <= rnum; i++){
952 int len = sprintf(buf, "%08d", i);
953 if(!tchdbput(hdb, buf, len, buf, len)){
954 eprint(hdb, "tchdbput");
958 if(rnum > 250 && i % (rnum / 250) == 0){
961 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
964 iprintf("reading:\n");
965 for(int i = 1; i <= rnum; i++){
966 char kbuf[RECBUFSIZ];
967 int ksiz = sprintf(kbuf, "%08d", i);
969 char *vbuf = tchdbget(hdb, kbuf, ksiz, &vsiz);
971 eprint(hdb, "tchdbget");
974 } else if(vsiz != ksiz || memcmp(vbuf, kbuf, vsiz)){
975 eprint(hdb, "(validation)");
981 if(rnum > 250 && i % (rnum / 250) == 0){
984 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
987 iprintf("word checking:\n");
988 for(int i = 0; words[i] != NULL; i += 2){
989 const char *kbuf = words[i];
990 int ksiz = strlen(kbuf);
991 const char *vbuf = words[i+1];
992 int vsiz = strlen(vbuf);
994 char *rbuf = tchdbget(hdb, kbuf, ksiz, &rsiz);
996 eprint(hdb, "tchdbget");
999 } else if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
1000 eprint(hdb, "(validation)");
1006 if(rnum > 250) putchar('.');
1008 if(rnum > 250) iprintf(" (%08d)\n", sizeof(words) / sizeof(*words));
1009 iprintf("iterator checking:\n");
1010 if(!tchdbiterinit(hdb)){
1011 eprint(hdb, "tchdbiterinit");
1017 for(int i = 1; (kbuf = tchdbiternext(hdb, &ksiz)) != NULL; i++, inum++){
1019 char *vbuf = tchdbget(hdb, kbuf, ksiz, &vsiz);
1021 eprint(hdb, "tchdbget");
1028 if(rnum > 250 && i % (rnum / 250) == 0){
1031 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
1034 if(rnum > 250) iprintf(" (%08d)\n", inum);
1035 if(tchdbecode(hdb) != TCENOREC || inum != tchdbrnum(hdb)){
1036 eprint(hdb, "(validation)");
1039 iprintf("iteration updating:\n");
1040 if(!tchdbiterinit(hdb)){
1041 eprint(hdb, "tchdbiterinit");
1045 for(int i = 1; (kbuf = tchdbiternext(hdb, &ksiz)) != NULL; i++, inum++){
1047 if(!tchdbputcat(hdb, kbuf, ksiz, "0123456789", 10)){
1048 eprint(hdb, "tchdbputcat");
1054 if(!tchdbout(hdb, kbuf, ksiz)){
1055 eprint(hdb, "tchdbout");
1062 if(rnum > 250 && i % (rnum / 250) == 0){
1065 if(i == rnum || i % (rnum / 10) == 0) iprintf(" (%08d)\n", i);
1068 if(rnum > 250) iprintf(" (%08d)\n", inum);
1069 if(tchdbecode(hdb) != TCENOREC || inum < tchdbrnum(hdb)){
1070 eprint(hdb, "(validation)");
1073 if(!tchdbsync(hdb)){
1074 eprint(hdb, "tchdbsync");
1077 if(!tchdbvanish(hdb)){
1078 eprint(hdb, "tchdbvanish");
1081 iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
1082 iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
1084 if(!tchdbclose(hdb)){
1085 eprint(hdb, "tchdbclose");
1089 iprintf("time: %.3f\n", tctime() - stime);
1090 iprintf("%s\n\n", err ? "error" : "ok");
1095 /* perform wicked command */
1096 static int procwicked(const char *path, int rnum, bool mt, int opts, int omode){
1097 iprintf("<Wicked Writing Test>\n path=%s rnum=%d mt=%d opts=%d omode=%d\n\n",
1098 path, rnum, mt, opts, omode);
1100 double stime = tctime();
1101 TCHDB *hdb = tchdbnew();
1102 if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
1103 if(mt && !tchdbsetmutex(hdb)){
1104 eprint(hdb, "tchdbsetmutex");
1107 if(!tchdbtune(hdb, rnum / 50, 2, -1, opts)){
1108 eprint(hdb, "tchdbtune");
1111 if(!tchdbsetcache(hdb, rnum / 10)){
1112 eprint(hdb, "tchdbsetcache");
1115 if(!tchdbopen(hdb, path, HDBOWRITER | HDBOCREAT | HDBOTRUNC | omode)){
1116 eprint(hdb, "tchdbopen");
1119 if(!tchdbiterinit(hdb)){
1120 eprint(hdb, "tchdbiterinit");
1123 TCMAP *map = tcmapnew2(rnum / 5);
1124 for(int i = 1; i <= rnum && !err; i++){
1125 char kbuf[RECBUFSIZ];
1126 int ksiz = sprintf(kbuf, "%d", myrand(rnum));
1127 char vbuf[RECBUFSIZ];
1128 int vsiz = myrand(RECBUFSIZ);
1129 memset(vbuf, '*', vsiz);
1135 if(!tchdbput(hdb, kbuf, ksiz, vbuf, vsiz)){
1136 eprint(hdb, "tchdbput");
1139 tcmapput(map, kbuf, ksiz, vbuf, vsiz);
1143 if(!tchdbput2(hdb, kbuf, vbuf)){
1144 eprint(hdb, "tchdbput2");
1147 tcmapput2(map, kbuf, vbuf);
1151 if(!tchdbputkeep(hdb, kbuf, ksiz, vbuf, vsiz) && tchdbecode(hdb) != TCEKEEP){
1152 eprint(hdb, "tchdbputkeep");
1155 tcmapputkeep(map, kbuf, ksiz, vbuf, vsiz);
1159 if(!tchdbputkeep2(hdb, kbuf, vbuf) && tchdbecode(hdb) != TCEKEEP){
1160 eprint(hdb, "tchdbputkeep2");
1163 tcmapputkeep2(map, kbuf, vbuf);
1167 if(!tchdbputcat(hdb, kbuf, ksiz, vbuf, vsiz)){
1168 eprint(hdb, "tchdbputcat");
1171 tcmapputcat(map, kbuf, ksiz, vbuf, vsiz);
1175 if(!tchdbputcat2(hdb, kbuf, vbuf)){
1176 eprint(hdb, "tchdbputcat2");
1179 tcmapputcat2(map, kbuf, vbuf);
1183 if(!tchdbputasync(hdb, kbuf, ksiz, vbuf, vsiz)){
1184 eprint(hdb, "tchdbputasync");
1187 tcmapput(map, kbuf, ksiz, vbuf, vsiz);
1191 if(!tchdbputasync2(hdb, kbuf, vbuf)){
1192 eprint(hdb, "tchdbputasync2");
1195 tcmapput2(map, kbuf, vbuf);
1199 if(myrand(10) == 0){
1200 if(!tchdbout(hdb, kbuf, ksiz) && tchdbecode(hdb) != TCENOREC){
1201 eprint(hdb, "tchdbout");
1204 tcmapout(map, kbuf, ksiz);
1209 if(myrand(10) == 0){
1210 if(!tchdbout2(hdb, kbuf) && tchdbecode(hdb) != TCENOREC){
1211 eprint(hdb, "tchdbout2");
1214 tcmapout2(map, kbuf);
1219 if(!(rbuf = tchdbget(hdb, kbuf, ksiz, &vsiz))){
1220 if(tchdbecode(hdb) != TCENOREC){
1221 eprint(hdb, "tchdbget");
1224 rbuf = tcsprintf("[%d]", myrand(i + 1));
1225 vsiz = strlen(rbuf);
1227 vsiz += myrand(vsiz);
1228 if(myrand(3) == 0) vsiz += PATH_MAX;
1229 rbuf = tcrealloc(rbuf, vsiz + 1);
1230 for(int j = 0; j < vsiz; j++){
1231 rbuf[j] = myrand(0x100);
1233 if(!tchdbput(hdb, kbuf, ksiz, rbuf, vsiz)){
1234 eprint(hdb, "tchdbput");
1237 tcmapput(map, kbuf, ksiz, rbuf, vsiz);
1242 if(!(rbuf = tchdbget(hdb, kbuf, ksiz, &vsiz)) && tchdbecode(hdb) != TCENOREC){
1243 eprint(hdb, "tchdbget");
1250 if(!(rbuf = tchdbget2(hdb, kbuf)) && tchdbecode(hdb) != TCENOREC){
1251 eprint(hdb, "tchdbget");
1258 if(myrand(1) == 0) vsiz = 1;
1259 if((vsiz = tchdbget3(hdb, kbuf, ksiz, vbuf, vsiz)) < 0 && tchdbecode(hdb) != TCENOREC){
1260 eprint(hdb, "tchdbget");
1266 if(myrand(rnum / 50) == 0){
1267 if(!tchdbiterinit(hdb)){
1268 eprint(hdb, "tchdbiterinit");
1272 TCXSTR *ikey = tcxstrnew();
1273 TCXSTR *ival = tcxstrnew();
1274 for(int j = myrand(rnum) / 1000 + 1; j >= 0; j--){
1276 if(tchdbiternext3(hdb, ikey, ival)){
1277 if(tcxstrsize(ival) != tchdbvsiz(hdb, tcxstrptr(ikey), tcxstrsize(ikey))){
1278 eprint(hdb, "(validation)");
1282 int ecode = tchdbecode(hdb);
1283 if(ecode != TCEINVALID && ecode != TCENOREC){
1284 eprint(hdb, "tchdbiternext3");
1290 char *ikbuf = tchdbiternext(hdb, &iksiz);
1294 int ecode = tchdbecode(hdb);
1295 if(ecode != TCEINVALID && ecode != TCENOREC){
1296 eprint(hdb, "tchdbiternext");
1307 if(myrand(10000) == 0) srand((unsigned int)(tctime() * 1000) % UINT_MAX);
1308 if(myrand(rnum / 16 + 1) == 0){
1309 int cnt = myrand(30);
1310 for(int j = 0; j < rnum && !err; j++){
1311 ksiz = sprintf(kbuf, "%d", i + j);
1312 if(tchdbout(hdb, kbuf, ksiz)){
1314 } else if(tchdbecode(hdb) != TCENOREC){
1315 eprint(hdb, "tcbdbout");
1318 tcmapout(map, kbuf, ksiz);
1324 if(i % 50 == 0) iprintf(" (%08d)\n", i);
1326 if(!tchdbclose(hdb)){
1327 eprint(hdb, "tchdbclose");
1330 if(!tchdbopen(hdb, path, HDBOWRITER | omode)){
1331 eprint(hdb, "tchdbopen");
1334 } else if(i == rnum / 4){
1335 char *npath = tcsprintf("%s-tmp", path);
1336 if(!tchdbcopy(hdb, npath)){
1337 eprint(hdb, "tchdbcopy");
1340 TCHDB *nhdb = tchdbnew();
1341 if(!tchdbopen(nhdb, npath, HDBOREADER | omode)){
1342 eprint(nhdb, "tchdbopen");
1348 if(!tchdboptimize(hdb, rnum / 50, -1, -1, -1)){
1349 eprint(hdb, "tchdboptimize");
1352 if(!tchdbiterinit(hdb)){
1353 eprint(hdb, "tchdbiterinit");
1358 if(rnum % 50 > 0) iprintf(" (%08d)\n", rnum);
1359 if(!tchdbsync(hdb)){
1360 eprint(hdb, "tchdbsync");
1363 if(tchdbrnum(hdb) != tcmaprnum(map)){
1364 eprint(hdb, "(validation)");
1367 for(int i = 1; i <= rnum && !err; i++){
1368 char kbuf[RECBUFSIZ];
1369 int ksiz = sprintf(kbuf, "%d", i - 1);
1371 const char *vbuf = tcmapget(map, kbuf, ksiz, &vsiz);
1373 char *rbuf = tchdbget(hdb, kbuf, ksiz, &rsiz);
1377 eprint(hdb, "tchdbget");
1379 } else if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
1380 eprint(hdb, "(validation)");
1385 if(rbuf || tchdbecode(hdb) != TCENOREC){
1386 eprint(hdb, "(validation)");
1391 if(i % 50 == 0) iprintf(" (%08d)\n", i);
1393 if(rnum % 50 > 0) iprintf(" (%08d)\n", rnum);
1397 for(int i = 1; (kbuf = tcmapiternext(map, &ksiz)) != NULL; i++){
1400 const char *vbuf = tcmapiterval(kbuf, &vsiz);
1402 char *rbuf = tchdbget(hdb, kbuf, ksiz, &rsiz);
1404 eprint(hdb, "tchdbget");
1406 } else if(rsiz != vsiz || memcmp(rbuf, vbuf, rsiz)){
1407 eprint(hdb, "(validation)");
1411 if(!tchdbout(hdb, kbuf, ksiz)){
1412 eprint(hdb, "tchdbout");
1415 if(i % 50 == 0) iprintf(" (%08d)\n", i);
1417 int mrnum = tcmaprnum(map);
1418 if(mrnum % 50 > 0) iprintf(" (%08d)\n", mrnum);
1419 if(tchdbrnum(hdb) != 0){
1420 eprint(hdb, "(validation)");
1423 iprintf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
1424 iprintf("size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
1427 if(!tchdbclose(hdb)){
1428 eprint(hdb, "tchdbclose");
1432 iprintf("time: %.3f\n", tctime() - stime);
1433 iprintf("%s\n\n", err ? "error" : "ok");