1 /*************************************************************************************************
2  * Writing test of Tokyo Cabinet
3  *************************************************************************************************/
4 
5 
6 #include <tcutil.h>
7 #include <tchdb.h>
8 #include <tcbdb.h>
9 #include <tcfdb.h>
10 #include <tctdb.h>
11 #include <stdbool.h>
12 #include <stdint.h>
13 #include <stdio.h>
14 #include <string.h>
15 
16 #undef TRUE
17 #define TRUE           1                 /* boolean true */
18 #undef FALSE
19 #define FALSE          0                 /* boolean false */
20 
21 #define RECBUFSIZ      32                /* buffer for records */
22 
23 
24 /* global variables */
25 const char *progname;                    /* program name */
26 int showprgr;                            /* whether to show progression */
27 
28 
29 /* function prototypes */
30 int main(int argc, char **argv);
31 void usage(void);
32 int runwrite(int argc, char **argv);
33 int runread(int argc, char **argv);
34 int runbtwrite(int argc, char **argv);
35 int runbtread(int argc, char **argv);
36 int runflwrite(int argc, char **argv);
37 int runflread(int argc, char **argv);
38 int runtblwrite(int argc, char **argv);
39 int runtblread(int argc, char **argv);
40 int myrand(void);
41 int dowrite(char *name, int rnum);
42 int doread(char *name, int rnum);
43 int dobtwrite(char *name, int rnum, int rnd);
44 int dobtread(char *name, int rnum, int rnd);
45 int doflwrite(char *name, int rnum);
46 int doflread(char *name, int rnum);
47 int dotblwrite(char *name, int rnum);
48 int dotblread(char *name, int rnum);
49 
50 
51 /* main routine */
main(int argc,char ** argv)52 int main(int argc, char **argv){
53   int rv;
54   progname = argv[0];
55   showprgr = TRUE;
56   if(getenv("HIDEPRGR")) showprgr = FALSE;
57   srand48(1978);
58   if(argc < 2) usage();
59   rv = 0;
60   if(!strcmp(argv[1], "write")){
61     rv = runwrite(argc, argv);
62   } else if(!strcmp(argv[1], "read")){
63     rv = runread(argc, argv);
64   } else if(!strcmp(argv[1], "btwrite")){
65     rv = runbtwrite(argc, argv);
66   } else if(!strcmp(argv[1], "btread")){
67     rv = runbtread(argc, argv);
68   } else if(!strcmp(argv[1], "flwrite")){
69     rv = runflwrite(argc, argv);
70   } else if(!strcmp(argv[1], "flread")){
71     rv = runflread(argc, argv);
72   } else if(!strcmp(argv[1], "tblwrite")){
73     rv = runtblwrite(argc, argv);
74   } else if(!strcmp(argv[1], "tblread")){
75     rv = runtblread(argc, argv);
76   } else {
77     usage();
78   }
79   return rv;
80 }
81 
82 
83 /* print the usage and exit */
usage(void)84 void usage(void){
85   fprintf(stderr, "%s: test cases for Tokyo Cabinet\n", progname);
86   fprintf(stderr, "\n");
87   fprintf(stderr, "usage:\n");
88   fprintf(stderr, "  %s write name rnum\n", progname);
89   fprintf(stderr, "  %s read name rnum\n", progname);
90   fprintf(stderr, "  %s btwrite [-rnd] name rnum\n", progname);
91   fprintf(stderr, "  %s btread [-rnd] name rnum\n", progname);
92   fprintf(stderr, "  %s flwrite name rnum\n", progname);
93   fprintf(stderr, "  %s flread name rnum\n", progname);
94   fprintf(stderr, "  %s tblwrite name rnum\n", progname);
95   fprintf(stderr, "  %s tblread name rnum\n", progname);
96   fprintf(stderr, "\n");
97   exit(1);
98 }
99 
100 
101 /* parse arguments of write command */
runwrite(int argc,char ** argv)102 int runwrite(int argc, char **argv){
103   char *name, *rstr;
104   int i, rnum, rv;
105   name = NULL;
106   rstr = NULL;
107   rnum = 0;
108   for(i = 2; i < argc; i++){
109     if(!name && argv[i][0] == '-'){
110       usage();
111     } else if(!name){
112       name = argv[i];
113     } else if(!rstr){
114       rstr = argv[i];
115     } else {
116       usage();
117     }
118   }
119   if(!name || !rstr) usage();
120   rnum = atoi(rstr);
121   if(rnum < 1) usage();
122   rv = dowrite(name, rnum);
123   return rv;
124 }
125 
126 
127 /* parse arguments of read command */
runread(int argc,char ** argv)128 int runread(int argc, char **argv){
129   char *name, *rstr;
130   int i, rnum, rv;
131   name = NULL;
132   rstr = NULL;
133   rnum = 0;
134   for(i = 2; i < argc; i++){
135     if(!name && argv[i][0] == '-'){
136       usage();
137     } else if(!name){
138       name = argv[i];
139     } else if(!rstr){
140       rstr = argv[i];
141     } else {
142       usage();
143     }
144   }
145   if(!name || !rstr) usage();
146   rnum = atoi(rstr);
147   if(rnum < 1) usage();
148   rv = doread(name, rnum);
149   return rv;
150 }
151 
152 
153 /* parse arguments of btwrite command */
runbtwrite(int argc,char ** argv)154 int runbtwrite(int argc, char **argv){
155   char *name, *rstr;
156   int i, rnum, rnd, rv;
157   name = NULL;
158   rstr = NULL;
159   rnum = 0;
160   rnd = FALSE;
161   for(i = 2; i < argc; i++){
162     if(!name && argv[i][0] == '-'){
163       if(!name && !strcmp(argv[i], "-rnd")){
164         rnd = TRUE;
165       } else {
166         usage();
167       }
168     } else if(!name){
169       name = argv[i];
170     } else if(!rstr){
171       rstr = argv[i];
172     } else {
173       usage();
174     }
175   }
176   if(!name || !rstr) usage();
177   rnum = atoi(rstr);
178   if(rnum < 1) usage();
179   rv = dobtwrite(name, rnum, rnd);
180   return rv;
181 }
182 
183 
184 /* parse arguments of btread command */
runbtread(int argc,char ** argv)185 int runbtread(int argc, char **argv){
186   char *name, *rstr;
187   int i, rnum, rnd, rv;
188   name = NULL;
189   rstr = NULL;
190   rnum = 0;
191   rnd = FALSE;
192   for(i = 2; i < argc; i++){
193     if(!name && argv[i][0] == '-'){
194       if(!name && !strcmp(argv[i], "-rnd")){
195         rnd = TRUE;
196       } else {
197         usage();
198       }
199     } else if(!name){
200       name = argv[i];
201     } else if(!rstr){
202       rstr = argv[i];
203     } else {
204       usage();
205     }
206   }
207   if(!name || !rstr) usage();
208   rnum = atoi(rstr);
209   if(rnum < 1) usage();
210   rv = dobtread(name, rnum, rnd);
211   return rv;
212 }
213 
214 
215 /* parse arguments of flwrite command */
runflwrite(int argc,char ** argv)216 int runflwrite(int argc, char **argv){
217   char *name, *rstr;
218   int i, rnum, rv;
219   name = NULL;
220   rstr = NULL;
221   rnum = 0;
222   for(i = 2; i < argc; i++){
223     if(!name && argv[i][0] == '-'){
224       usage();
225     } else if(!name){
226       name = argv[i];
227     } else if(!rstr){
228       rstr = argv[i];
229     } else {
230       usage();
231     }
232   }
233   if(!name || !rstr) usage();
234   rnum = atoi(rstr);
235   if(rnum < 1) usage();
236   rv = doflwrite(name, rnum);
237   return rv;
238 }
239 
240 
241 /* parse arguments of read command */
runflread(int argc,char ** argv)242 int runflread(int argc, char **argv){
243   char *name, *rstr;
244   int i, rnum, rv;
245   name = NULL;
246   rstr = NULL;
247   rnum = 0;
248   for(i = 2; i < argc; i++){
249     if(!name && argv[i][0] == '-'){
250       usage();
251     } else if(!name){
252       name = argv[i];
253     } else if(!rstr){
254       rstr = argv[i];
255     } else {
256       usage();
257     }
258   }
259   if(!name || !rstr) usage();
260   rnum = atoi(rstr);
261   if(rnum < 1) usage();
262   rv = doflread(name, rnum);
263   return rv;
264 }
265 
266 
267 /* parse arguments of tblwrite command */
runtblwrite(int argc,char ** argv)268 int runtblwrite(int argc, char **argv){
269   char *name, *rstr;
270   int i, rnum, rnd, rv;
271   name = NULL;
272   rstr = NULL;
273   rnum = 0;
274   rnd = FALSE;
275   for(i = 2; i < argc; i++){
276     if(!name && argv[i][0] == '-'){
277       usage();
278     } else if(!name){
279       name = argv[i];
280     } else if(!rstr){
281       rstr = argv[i];
282     } else {
283       usage();
284     }
285   }
286   if(!name || !rstr) usage();
287   rnum = atoi(rstr);
288   if(rnum < 1) usage();
289   rv = dotblwrite(name, rnum);
290   return rv;
291 }
292 
293 
294 /* parse arguments of tblread command */
runtblread(int argc,char ** argv)295 int runtblread(int argc, char **argv){
296   char *name, *rstr;
297   int i, rnum, rnd, rv;
298   name = NULL;
299   rstr = NULL;
300   rnum = 0;
301   rnd = FALSE;
302   for(i = 2; i < argc; i++){
303     if(!name && argv[i][0] == '-'){
304       usage();
305     } else if(!name){
306       name = argv[i];
307     } else if(!rstr){
308       rstr = argv[i];
309     } else {
310       usage();
311     }
312   }
313   if(!name || !rstr) usage();
314   rnum = atoi(rstr);
315   if(rnum < 1) usage();
316   rv = dotblread(name, rnum);
317   return rv;
318 }
319 
320 
321 /* pseudo random number generator */
myrand(void)322 int myrand(void){
323   static int cnt = 0;
324   return (lrand48() + cnt++) & 0x7FFFFFFF;
325 }
326 
327 
328 /* perform write command */
dowrite(char * name,int rnum)329 int dowrite(char *name, int rnum){
330   TCHDB *hdb;
331   int i, err, len;
332   char buf[RECBUFSIZ];
333   if(showprgr) printf("<Writing Test of Hash>\n  name=%s  rnum=%d\n\n", name, rnum);
334   /* open a database */
335   hdb = tchdbnew();
336   tchdbtune(hdb, rnum * 3, 0, 0, 0);
337   tchdbsetxmsiz(hdb, rnum * 48);
338   if(!tchdbopen(hdb, name, HDBOWRITER | HDBOCREAT | HDBOTRUNC)){
339     fprintf(stderr, "tchdbopen failed\n");
340     tchdbdel(hdb);
341     return 1;
342   }
343   err = FALSE;
344   /* loop for each record */
345   for(i = 1; i <= rnum; i++){
346     /* store a record */
347     len = sprintf(buf, "%08d", i);
348     if(!tchdbputasync(hdb, buf, len, buf, len)){
349       fprintf(stderr, "tchdbputasync failed\n");
350       err = TRUE;
351       break;
352     }
353     /* print progression */
354     if(showprgr && rnum > 250 && i % (rnum / 250) == 0){
355       putchar('.');
356       fflush(stdout);
357       if(i == rnum || i % (rnum / 10) == 0){
358         printf(" (%08d)\n", i);
359         fflush(stdout);
360       }
361     }
362   }
363   /* close the database */
364   if(!tchdbclose(hdb)){
365     fprintf(stderr, "tchdbclose failed\n");
366     tchdbdel(hdb);
367     return 1;
368   }
369   tchdbdel(hdb);
370   if(showprgr && !err) printf("ok\n\n");
371   return err ? 1 : 0;
372 }
373 
374 
375 /* perform read command */
doread(char * name,int rnum)376 int doread(char *name, int rnum){
377   TCHDB *hdb;
378   int i, err, len;
379   char buf[RECBUFSIZ], vbuf[RECBUFSIZ];
380   if(showprgr) printf("<Reading Test of Hash>\n  name=%s  rnum=%d\n\n", name, rnum);
381   /* open a database */
382   hdb = tchdbnew();
383   tchdbsetxmsiz(hdb, rnum * 48);
384   if(!tchdbopen(hdb, name, HDBOREADER)){
385     fprintf(stderr, "tchdbopen failed\n");
386     tchdbdel(hdb);
387     return 1;
388   }
389   err = FALSE;
390   /* loop for each record */
391   for(i = 1; i <= rnum; i++){
392     /* store a record */
393     len = sprintf(buf, "%08d", i);
394     if(tchdbget3(hdb, buf, len, vbuf, RECBUFSIZ) == -1){
395       fprintf(stderr, "tchdbget3 failed\n");
396       err = TRUE;
397       break;
398     }
399     /* print progression */
400     if(showprgr && rnum > 250 && i % (rnum / 250) == 0){
401       putchar('.');
402       fflush(stdout);
403       if(i == rnum || i % (rnum / 10) == 0){
404         printf(" (%08d)\n", i);
405         fflush(stdout);
406       }
407     }
408   }
409   /* close the database */
410   if(!tchdbclose(hdb)){
411     fprintf(stderr, "tchdbclose failed\n");
412     tchdbdel(hdb);
413     return 1;
414   }
415   tchdbdel(hdb);
416   if(showprgr && !err) printf("ok\n\n");
417   return err ? 1 : 0;
418 }
419 
420 
421 /* perform btwrite command */
dobtwrite(char * name,int rnum,int rnd)422 int dobtwrite(char *name, int rnum, int rnd){
423   TCBDB *bdb;
424   int i, err, len;
425   char buf[RECBUFSIZ];
426   if(showprgr) printf("<Writing Test of B+ Tree>\n  name=%s  rnum=%d\n\n", name, rnum);
427   /* open a database */
428   bdb = tcbdbnew();
429   if(rnd){
430     tcbdbtune(bdb, 77, 256, -1, 0, 0, 0);
431     tcbdbsetcache(bdb, rnum / 77, -1);
432   } else {
433     tcbdbtune(bdb, 101, 256, -1, 0, 0, 0);
434     tcbdbsetcache(bdb, 256, 256);
435   }
436   tcbdbsetxmsiz(bdb, rnum * 32);
437   if(!tcbdbopen(bdb, name, BDBOWRITER | BDBOCREAT | BDBOTRUNC)){
438     fprintf(stderr, "tcbdbopen failed\n");
439     tcbdbdel(bdb);
440     return 1;
441   }
442   err = FALSE;
443   /* loop for each record */
444   for(i = 1; i <= rnum; i++){
445     /* store a record */
446     len = sprintf(buf, "%08d", rnd ? myrand() % rnum + 1 : i);
447     if(!tcbdbput(bdb, buf, len, buf, len)){
448       fprintf(stderr, "tcbdbput failed\n");
449       err = TRUE;
450       break;
451     }
452     /* print progression */
453     if(showprgr && rnum > 250 && i % (rnum / 250) == 0){
454       putchar('.');
455       fflush(stdout);
456       if(i == rnum || i % (rnum / 10) == 0){
457         printf(" (%08d)\n", i);
458         fflush(stdout);
459       }
460     }
461   }
462   /* close the database */
463   if(!tcbdbclose(bdb)){
464     fprintf(stderr, "tcbdbclose failed\n");
465     tcbdbdel(bdb);
466     return 1;
467   }
468   tcbdbdel(bdb);
469   if(showprgr && !err) printf("ok\n\n");
470   return err ? 1 : 0;
471 }
472 
473 
474 /* perform btread command */
dobtread(char * name,int rnum,int rnd)475 int dobtread(char *name, int rnum, int rnd){
476   TCBDB *bdb;
477   int i, err, len, vlen;
478   const char *val;
479   char buf[RECBUFSIZ];
480   if(showprgr) printf("<Reading Test of B+ Tree>\n  name=%s  rnum=%d\n\n", name, rnum);
481   /* open a database */
482   bdb = tcbdbnew();
483   if(rnd){
484     tcbdbsetcache(bdb, rnum / 77 + 1, -1);
485   } else {
486     tcbdbsetcache(bdb, 256, 256);
487   }
488   tcbdbsetxmsiz(bdb, rnum * 32);
489   if(!tcbdbopen(bdb, name, BDBOREADER)){
490     fprintf(stderr, "tcbdbopen failed\n");
491     tcbdbdel(bdb);
492     return 1;
493   }
494   err = FALSE;
495   /* loop for each record */
496   for(i = 1; i <= rnum; i++){
497     /* store a record */
498     len = sprintf(buf, "%08d", rnd ? myrand() % rnum + 1 : i);
499     if(!(val = tcbdbget3(bdb, buf, len, &vlen))){
500       fprintf(stderr, "tdbdbget3 failed\n");
501       err = TRUE;
502       break;
503     }
504     /* print progression */
505     if(showprgr && rnum > 250 && i % (rnum / 250) == 0){
506       putchar('.');
507       fflush(stdout);
508       if(i == rnum || i % (rnum / 10) == 0){
509         printf(" (%08d)\n", i);
510         fflush(stdout);
511       }
512     }
513   }
514   /* close the database */
515   if(!tcbdbclose(bdb)){
516     fprintf(stderr, "tcbdbclose failed\n");
517     tcbdbdel(bdb);
518     return 1;
519   }
520   tcbdbdel(bdb);
521   if(showprgr && !err) printf("ok\n\n");
522   return err ? 1 : 0;
523 }
524 
525 
526 /* perform flwrite command */
doflwrite(char * name,int rnum)527 int doflwrite(char *name, int rnum){
528   TCFDB *fdb;
529   int i, err, len;
530   char buf[RECBUFSIZ];
531   if(showprgr) printf("<Writing Test of Fixed-Length>\n  name=%s  rnum=%d\n\n", name, rnum);
532   /* open a database */
533   fdb = tcfdbnew();
534   tcfdbtune(fdb, 8, 1024 + rnum * 9);
535   if(!tcfdbopen(fdb, name, FDBOWRITER | FDBOCREAT | FDBOTRUNC)){
536     fprintf(stderr, "tcfdbopen failed\n");
537     tcfdbdel(fdb);
538     return 1;
539   }
540   err = FALSE;
541   /* loop for each record */
542   for(i = 1; i <= rnum; i++){
543     /* store a record */
544     len = sprintf(buf, "%08d", i);
545     if(!tcfdbput(fdb, i, buf, len)){
546       fprintf(stderr, "tcfdbput failed\n");
547       err = TRUE;
548       break;
549     }
550     /* print progression */
551     if(showprgr && rnum > 250 && i % (rnum / 250) == 0){
552       putchar('.');
553       fflush(stdout);
554       if(i == rnum || i % (rnum / 10) == 0){
555         printf(" (%08d)\n", i);
556         fflush(stdout);
557       }
558     }
559   }
560   /* close the database */
561   if(!tcfdbclose(fdb)){
562     fprintf(stderr, "tcfdbclose failed\n");
563     tcfdbdel(fdb);
564     return 1;
565   }
566   tcfdbdel(fdb);
567   if(showprgr && !err) printf("ok\n\n");
568   return err ? 1 : 0;
569 }
570 
571 
572 /* perform flread command */
doflread(char * name,int rnum)573 int doflread(char *name, int rnum){
574   TCFDB *fdb;
575   int i, err;
576   char vbuf[RECBUFSIZ];
577   if(showprgr) printf("<Reading Test of Fixed-length>\n  name=%s  rnum=%d\n\n", name, rnum);
578   /* open a database */
579   fdb = tcfdbnew();
580   if(!tcfdbopen(fdb, name, FDBOREADER)){
581     fprintf(stderr, "tcfdbopen failed\n");
582     tcfdbdel(fdb);
583     return 1;
584   }
585   err = FALSE;
586   /* loop for each record */
587   for(i = 1; i <= rnum; i++){
588     /* store a record */
589     if(tcfdbget4(fdb, i, vbuf, RECBUFSIZ) == -1){
590       fprintf(stderr, "tcfdbget4 failed\n");
591       err = TRUE;
592       break;
593     }
594     /* print progression */
595     if(showprgr && rnum > 250 && i % (rnum / 250) == 0){
596       putchar('.');
597       fflush(stdout);
598       if(i == rnum || i % (rnum / 10) == 0){
599         printf(" (%08d)\n", i);
600         fflush(stdout);
601       }
602     }
603   }
604   /* close the database */
605   if(!tcfdbclose(fdb)){
606     fprintf(stderr, "tcfdbclose failed\n");
607     tcfdbdel(fdb);
608     return 1;
609   }
610   tcfdbdel(fdb);
611   if(showprgr && !err) printf("ok\n\n");
612   return err ? 1 : 0;
613 }
614 
615 
616 /* perform tblwrite command */
dotblwrite(char * name,int rnum)617 int dotblwrite(char *name, int rnum){
618   TCTDB *tdb;
619   int i, err, pksiz, vsiz;
620   char pkbuf[RECBUFSIZ], vbuf[RECBUFSIZ];
621   TCMAP *cols;
622   if(showprgr) printf("<Writing Test of Table>\n  name=%s  rnum=%d\n\n", name, rnum);
623   /* open a database */
624   tdb = tctdbnew();
625   tctdbtune(tdb, rnum * 3, 0, 0, 0);
626   tctdbsetxmsiz(tdb, rnum * 80);
627   tctdbsetcache(tdb, -1, rnum / 100, -1);
628   if(!tctdbopen(tdb, name, TDBOWRITER | TDBOCREAT | TDBOTRUNC)){
629     fprintf(stderr, "tctdbopen failed\n");
630     tctdbdel(tdb);
631     return 1;
632   }
633   if(!tctdbsetindex(tdb, "s", TDBITLEXICAL)){
634     fprintf(stderr, "tctdbsetindex failed\n");
635     tctdbdel(tdb);
636     return 1;
637   }
638   if(!tctdbsetindex(tdb, "n", TDBITDECIMAL)){
639     fprintf(stderr, "tctdbsetindex failed\n");
640     tctdbdel(tdb);
641     return 1;
642   }
643   err = FALSE;
644   /* loop for each record */
645   for(i = 1; i <= rnum; i++){
646     /* store a record */
647     pksiz = sprintf(pkbuf, "%d", i);
648     cols = tcmapnew2(7);
649     vsiz = sprintf(vbuf, "%08d", i);
650     tcmapput(cols, "s", 1, vbuf, vsiz);
651     vsiz = sprintf(vbuf, "%08d", myrand() % i);
652     tcmapput(cols, "n", 1, vbuf, vsiz);
653     vsiz = sprintf(vbuf, "%08d", i);
654     tcmapput(cols, "t", 1, vbuf, vsiz);
655     vsiz = sprintf(vbuf, "%08d", myrand() % rnum);
656     tcmapput(cols, "f", 1, vbuf, vsiz);
657     if(!tctdbput(tdb, pkbuf, pksiz, cols)){
658       fprintf(stderr, "tctdbput failed\n");
659       err = TRUE;
660       break;
661     }
662     tcmapdel(cols);
663     /* print progression */
664     if(showprgr && rnum > 250 && i % (rnum / 250) == 0){
665       putchar('.');
666       fflush(stdout);
667       if(i == rnum || i % (rnum / 10) == 0){
668         printf(" (%08d)\n", i);
669         fflush(stdout);
670       }
671     }
672   }
673   /* close the database */
674   if(!tctdbclose(tdb)){
675     fprintf(stderr, "tctdbclose failed\n");
676     tctdbdel(tdb);
677     return 1;
678   }
679   tctdbdel(tdb);
680   if(showprgr && !err) printf("ok\n\n");
681   return err ? 1 : 0;
682 }
683 
684 
685 /* perform tblread command */
dotblread(char * name,int rnum)686 int dotblread(char *name, int rnum){
687   TCTDB *tdb;
688   int i, j, err, pksiz, rsiz;
689   char pkbuf[RECBUFSIZ];
690   const char *rbuf;
691   TCMAP *cols;
692   TDBQRY *qry;
693   TCLIST *res;
694   if(showprgr) printf("<Reading Test of Table>\n  name=%s  rnum=%d\n\n", name, rnum);
695   /* open a database */
696   tdb = tctdbnew();
697   tctdbsetxmsiz(tdb, rnum * 80);
698   tctdbsetcache(tdb, -1, rnum / 100, -1);
699   if(!tctdbopen(tdb, name, TDBOREADER)){
700     fprintf(stderr, "tctdbopen failed\n");
701     tctdbdel(tdb);
702     return 1;
703   }
704   err = FALSE;
705   /* loop for each record */
706   for(i = 1; i <= rnum; i++){
707     /* search for a record */
708     pksiz = sprintf(pkbuf, "%08d", i);
709     qry = tctdbqrynew(tdb);
710     tctdbqryaddcond(qry, "s", TDBQCSTREQ, pkbuf);
711     res = tctdbqrysearch(qry);
712     for(j = 0; j < tclistnum(res); j++){
713       rbuf = tclistval(res, j, &rsiz);
714       cols = tctdbget(tdb, rbuf, rsiz);
715       if(cols){
716         tcmapdel(cols);
717       } else {
718         fprintf(stderr, "tctdbget failed\n");
719         err = TRUE;
720         break;
721       }
722     }
723     tclistdel(res);
724     tctdbqrydel(qry);
725     /* print progression */
726     if(showprgr && rnum > 250 && i % (rnum / 250) == 0){
727       putchar('.');
728       fflush(stdout);
729       if(i == rnum || i % (rnum / 10) == 0){
730         printf(" (%08d)\n", i);
731         fflush(stdout);
732       }
733     }
734   }
735   /* close the database */
736   if(!tctdbclose(tdb)){
737     fprintf(stderr, "tctdbclose failed\n");
738     tctdbdel(tdb);
739     return 1;
740   }
741   tctdbdel(tdb);
742   if(showprgr && !err) printf("ok\n\n");
743   return err ? 1 : 0;
744 }
745 
746 
747 
748 /* END OF FILE */
749