1 /*************************************************************************************************
2  * The command line utility of the B+ tree database API
3  *                                                               Copyright (C) 2006-2012 FAL Labs
4  * This file is part of Tokyo Cabinet.
5  * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
6  * the GNU Lesser General Public License as published by the Free Software Foundation; either
7  * version 2.1 of the License or any later version.  Tokyo Cabinet is distributed in the hope
8  * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
10  * License for more details.
11  * You should have received a copy of the GNU Lesser General Public License along with Tokyo
12  * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
13  * Boston, MA 02111-1307 USA.
14  *************************************************************************************************/
15 
16 
17 #include <tcutil.h>
18 #include <tcbdb.h>
19 #include "myconf.h"
20 
21 
22 /* global variables */
23 const char *g_progname;                  // program name
24 int g_dbgfd;                             // debugging output
25 
26 
27 /* function prototypes */
28 int main(int argc, char **argv);
29 static void usage(void);
30 static void printerr(TCBDB *bdb);
31 static int printdata(const char *ptr, int size, bool px);
32 static char *mygetline(FILE *ifp);
33 static int mycmpfunc(const char *aptr, int asiz, const char *bptr, int bsiz, void *op);
34 static int runcreate(int argc, char **argv);
35 static int runinform(int argc, char **argv);
36 static int runput(int argc, char **argv);
37 static int runout(int argc, char **argv);
38 static int runget(int argc, char **argv);
39 static int runlist(int argc, char **argv);
40 static int runoptimize(int argc, char **argv);
41 static int runimporttsv(int argc, char **argv);
42 static int runversion(int argc, char **argv);
43 static int proccreate(const char *path, int lmemb, int nmemb,
44                       int bnum, int apow, int fpow, TCCMP cmp, int opts);
45 static int procinform(const char *path, int omode);
46 static int procput(const char *path, const char *kbuf, int ksiz, const char *vbuf, int vsiz,
47                    TCCMP cmp, int omode, int dmode);
48 static int procout(const char *path, const char *kbuf, int ksiz, TCCMP cmp, int omode);
49 static int procget(const char *path, const char *kbuf, int ksiz, TCCMP cmp, int omode,
50                    bool px, bool pz);
51 static int proclist(const char *path, TCCMP cmp, int omode, int max, bool pv, bool px, bool bk,
52                     const char *jstr, const char *bstr, const char *estr, const char *fmstr);
53 static int procoptimize(const char *path, int lmemb, int nmemb,
54                         int bnum, int apow, int fpow, TCCMP cmp, int opts, int omode, bool df);
55 static int procimporttsv(const char *path, const char *file, int omode, bool sc);
56 static int procversion(void);
57 
58 
59 /* main routine */
main(int argc,char ** argv)60 int main(int argc, char **argv){
61   g_progname = argv[0];
62   g_dbgfd = -1;
63   const char *ebuf = getenv("TCDBGFD");
64   if(ebuf) g_dbgfd = tcatoix(ebuf);
65   if(argc < 2) usage();
66   int rv = 0;
67   if(!strcmp(argv[1], "create")){
68     rv = runcreate(argc, argv);
69   } else if(!strcmp(argv[1], "inform")){
70     rv = runinform(argc, argv);
71   } else if(!strcmp(argv[1], "put")){
72     rv = runput(argc, argv);
73   } else if(!strcmp(argv[1], "out")){
74     rv = runout(argc, argv);
75   } else if(!strcmp(argv[1], "get")){
76     rv = runget(argc, argv);
77   } else if(!strcmp(argv[1], "list")){
78     rv = runlist(argc, argv);
79   } else if(!strcmp(argv[1], "optimize")){
80     rv = runoptimize(argc, argv);
81   } else if(!strcmp(argv[1], "importtsv")){
82     rv = runimporttsv(argc, argv);
83   } else if(!strcmp(argv[1], "version") || !strcmp(argv[1], "--version")){
84     rv = runversion(argc, argv);
85   } else {
86     usage();
87   }
88   return rv;
89 }
90 
91 
92 /* print the usage and exit */
usage(void)93 static void usage(void){
94   fprintf(stderr, "%s: the command line utility of the B+ tree database API\n", g_progname);
95   fprintf(stderr, "\n");
96   fprintf(stderr, "usage:\n");
97   fprintf(stderr, "  %s create [-cd|-ci|-cj] [-tl] [-td|-tb|-tt|-tx] path"
98           " [lmemb [nmemb [bnum [apow [fpow]]]]]\n", g_progname);
99   fprintf(stderr, "  %s inform [-nl|-nb] path\n", g_progname);
100   fprintf(stderr, "  %s put [-cd|-ci|-cj] [-nl|-nb] [-sx] [-dk|-dc|-dd|-db|-dai|-dad] path"
101           " key value\n", g_progname);
102   fprintf(stderr, "  %s out [-cd|-ci|-cj] [-nl|-nb] [-sx] path key\n", g_progname);
103   fprintf(stderr, "  %s get [-cd|-ci|-cj] [-nl|-nb] [-sx] [-px] [-pz] path key\n", g_progname);
104   fprintf(stderr, "  %s list [-cd|-ci|-cj] [-nl|-nb] [-m num] [-bk] [-pv] [-px] [-j str]"
105           " [-rb bkey ekey] [-fm str] path\n", g_progname);
106   fprintf(stderr, "  %s optimize [-cd|-ci|-cj] [-tl] [-td|-tb|-tt|-tx] [-tz] [-nl|-nb] [-df]"
107           " path [lmemb [nmemb [bnum [apow [fpow]]]]]\n", g_progname);
108   fprintf(stderr, "  %s importtsv [-nl|-nb] [-sc] path [file]\n", g_progname);
109   fprintf(stderr, "  %s version\n", g_progname);
110   fprintf(stderr, "\n");
111   exit(1);
112 }
113 
114 
115 /* print error information */
printerr(TCBDB * bdb)116 static void printerr(TCBDB *bdb){
117   const char *path = tcbdbpath(bdb);
118   int ecode = tcbdbecode(bdb);
119   fprintf(stderr, "%s: %s: %d: %s\n", g_progname, path ? path : "-", ecode, tcbdberrmsg(ecode));
120 }
121 
122 
123 /* print record data */
printdata(const char * ptr,int size,bool px)124 static int printdata(const char *ptr, int size, bool px){
125   int len = 0;
126   while(size-- > 0){
127     if(px){
128       if(len > 0) putchar(' ');
129       len += printf("%02X", *(unsigned char *)ptr);
130     } else {
131       putchar(*ptr);
132       len++;
133     }
134     ptr++;
135   }
136   return len;
137 }
138 
139 
140 /* read a line from a file descriptor */
mygetline(FILE * ifp)141 static char *mygetline(FILE *ifp){
142   int len = 0;
143   int blen = 1024;
144   char *buf = tcmalloc(blen + 1);
145   bool end = true;
146   int c;
147   while((c = fgetc(ifp)) != EOF){
148     end = false;
149     if(c == '\0') continue;
150     if(blen <= len){
151       blen *= 2;
152       buf = tcrealloc(buf, blen + 1);
153     }
154     if(c == '\n' || c == '\r') c = '\0';
155     buf[len++] = c;
156     if(c == '\0') break;
157   }
158   if(end){
159     tcfree(buf);
160     return NULL;
161   }
162   buf[len] = '\0';
163   return buf;
164 }
165 
166 
167 /* dummy comparison function */
mycmpfunc(const char * aptr,int asiz,const char * bptr,int bsiz,void * op)168 static int mycmpfunc(const char *aptr, int asiz, const char *bptr, int bsiz, void *op){
169   return 0;
170 }
171 
172 
173 /* parse arguments of create command */
runcreate(int argc,char ** argv)174 static int runcreate(int argc, char **argv){
175   char *path = NULL;
176   char *lmstr = NULL;
177   char *nmstr = NULL;
178   char *bstr = NULL;
179   char *astr = NULL;
180   char *fstr = NULL;
181   TCCMP cmp = NULL;
182   int opts = 0;
183   for(int i = 2; i < argc; i++){
184     if(!path && argv[i][0] == '-'){
185       if(!strcmp(argv[i], "-cd")){
186         cmp = tccmpdecimal;
187       } else if(!strcmp(argv[i], "-ci")){
188         cmp = tccmpint32;
189       } else if(!strcmp(argv[i], "-cj")){
190         cmp = tccmpint64;
191       } else if(!strcmp(argv[i], "-tl")){
192         opts |= BDBTLARGE;
193       } else if(!strcmp(argv[i], "-td")){
194         opts |= BDBTDEFLATE;
195       } else if(!strcmp(argv[i], "-tb")){
196         opts |= BDBTBZIP;
197       } else if(!strcmp(argv[i], "-tt")){
198         opts |= BDBTTCBS;
199       } else if(!strcmp(argv[i], "-tx")){
200         opts |= BDBTEXCODEC;
201       } else {
202         usage();
203       }
204     } else if(!path){
205       path = argv[i];
206     } else if(!lmstr){
207       lmstr = argv[i];
208     } else if(!nmstr){
209       nmstr = argv[i];
210     } else if(!bstr){
211       bstr = argv[i];
212     } else if(!astr){
213       astr = argv[i];
214     } else if(!fstr){
215       fstr = argv[i];
216     } else {
217       usage();
218     }
219   }
220   if(!path) usage();
221   int lmemb = lmstr ? tcatoix(lmstr) : -1;
222   int nmemb = nmstr ? tcatoix(nmstr) : -1;
223   int bnum = bstr ? tcatoix(bstr) : -1;
224   int apow = astr ? tcatoix(astr) : -1;
225   int fpow = fstr ? tcatoix(fstr) : -1;
226   int rv = proccreate(path, lmemb, nmemb, bnum, apow, fpow, cmp, opts);
227   return rv;
228 }
229 
230 
231 /* parse arguments of inform command */
runinform(int argc,char ** argv)232 static int runinform(int argc, char **argv){
233   char *path = NULL;
234   int omode = 0;
235   for(int i = 2; i < argc; i++){
236     if(!path && argv[i][0] == '-'){
237       if(!strcmp(argv[i], "-nl")){
238         omode |= BDBONOLCK;
239       } else if(!strcmp(argv[i], "-nb")){
240         omode |= BDBOLCKNB;
241       } else {
242         usage();
243       }
244     } else if(!path){
245       path = argv[i];
246     } else {
247       usage();
248     }
249   }
250   if(!path) usage();
251   int rv = procinform(path, omode);
252   return rv;
253 }
254 
255 
256 /* parse arguments of put command */
runput(int argc,char ** argv)257 static int runput(int argc, char **argv){
258   char *path = NULL;
259   char *key = NULL;
260   char *value = NULL;
261   TCCMP cmp = NULL;
262   int omode = 0;
263   int dmode = 0;
264   bool sx = false;
265   for(int i = 2; i < argc; i++){
266     if(!path && argv[i][0] == '-'){
267       if(!strcmp(argv[i], "-cd")){
268         cmp = tccmpdecimal;
269       } else if(!strcmp(argv[i], "-ci")){
270         cmp = tccmpint32;
271       } else if(!strcmp(argv[i], "-cj")){
272         cmp = tccmpint64;
273       } else if(!strcmp(argv[i], "-nl")){
274         omode |= BDBONOLCK;
275       } else if(!strcmp(argv[i], "-nb")){
276         omode |= BDBOLCKNB;
277       } else if(!strcmp(argv[i], "-dk")){
278         dmode = -1;
279       } else if(!strcmp(argv[i], "-dc")){
280         dmode = 1;
281       } else if(!strcmp(argv[i], "-dd")){
282         dmode = 2;
283       } else if(!strcmp(argv[i], "-db")){
284         dmode = 3;
285       } else if(!strcmp(argv[i], "-dai")){
286         dmode = 10;
287       } else if(!strcmp(argv[i], "-dad")){
288         dmode = 11;
289       } else if(!strcmp(argv[i], "-sx")){
290         sx = true;
291       } else {
292         usage();
293       }
294     } else if(!path){
295       path = argv[i];
296     } else if(!key){
297       key = argv[i];
298     } else if(!value){
299       value = argv[i];
300     } else {
301       usage();
302     }
303   }
304   if(!path || !key || !value) usage();
305   char *kbuf, *vbuf;
306   int ksiz, vsiz;
307   if(sx){
308     kbuf = tchexdecode(key, &ksiz);
309     vbuf = tchexdecode(value, &vsiz);
310   } else {
311     ksiz = strlen(key);
312     kbuf = tcmemdup(key, ksiz);
313     vsiz = strlen(value);
314     vbuf = tcmemdup(value, vsiz);
315   }
316   int rv = procput(path, kbuf, ksiz, vbuf, vsiz, cmp, omode, dmode);
317   tcfree(vbuf);
318   tcfree(kbuf);
319   return rv;
320 }
321 
322 
323 /* parse arguments of out command */
runout(int argc,char ** argv)324 static int runout(int argc, char **argv){
325   char *path = NULL;
326   char *key = NULL;
327   TCCMP cmp = NULL;
328   int omode = 0;
329   bool sx = false;
330   for(int i = 2; i < argc; i++){
331     if(!path && argv[i][0] == '-'){
332       if(!strcmp(argv[i], "-cd")){
333         cmp = tccmpdecimal;
334       } else if(!strcmp(argv[i], "-ci")){
335         cmp = tccmpint32;
336       } else if(!strcmp(argv[i], "-cj")){
337         cmp = tccmpint64;
338       } else if(!strcmp(argv[i], "-nl")){
339         omode |= BDBONOLCK;
340       } else if(!strcmp(argv[i], "-nb")){
341         omode |= BDBOLCKNB;
342       } else if(!strcmp(argv[i], "-sx")){
343         sx = true;
344       } else {
345         usage();
346       }
347     } else if(!path){
348       path = argv[i];
349     } else if(!key){
350       key = argv[i];
351     } else {
352       usage();
353     }
354   }
355   if(!path || !key) usage();
356   int ksiz;
357   char *kbuf;
358   if(sx){
359     kbuf = tchexdecode(key, &ksiz);
360   } else {
361     ksiz = strlen(key);
362     kbuf = tcmemdup(key, ksiz);
363   }
364   int rv = procout(path, kbuf, ksiz, cmp, omode);
365   tcfree(kbuf);
366   return rv;
367 }
368 
369 
370 /* parse arguments of get command */
runget(int argc,char ** argv)371 static int runget(int argc, char **argv){
372   char *path = NULL;
373   char *key = NULL;
374   TCCMP cmp = NULL;
375   int omode = 0;
376   bool sx = false;
377   bool px = false;
378   bool pz = false;
379   for(int i = 2; i < argc; i++){
380     if(!path && argv[i][0] == '-'){
381       if(!strcmp(argv[i], "-cd")){
382         cmp = tccmpdecimal;
383       } else if(!strcmp(argv[i], "-ci")){
384         cmp = tccmpint32;
385       } else if(!strcmp(argv[i], "-cj")){
386         cmp = tccmpint64;
387       } else if(!strcmp(argv[i], "-nl")){
388         omode |= BDBONOLCK;
389       } else if(!strcmp(argv[i], "-nb")){
390         omode |= BDBOLCKNB;
391       } else if(!strcmp(argv[i], "-sx")){
392         sx = true;
393       } else if(!strcmp(argv[i], "-px")){
394         px = true;
395       } else if(!strcmp(argv[i], "-pz")){
396         pz = true;
397       } else {
398         usage();
399       }
400     } else if(!path){
401       path = argv[i];
402     } else if(!key){
403       key = argv[i];
404     } else {
405       usage();
406     }
407   }
408   if(!path || !key) usage();
409   int ksiz;
410   char *kbuf;
411   if(sx){
412     kbuf = tchexdecode(key, &ksiz);
413   } else {
414     ksiz = strlen(key);
415     kbuf = tcmemdup(key, ksiz);
416   }
417   int rv = procget(path, kbuf, ksiz, cmp, omode, px, pz);
418   tcfree(kbuf);
419   return rv;
420 }
421 
422 
423 /* parse arguments of list command */
runlist(int argc,char ** argv)424 static int runlist(int argc, char **argv){
425   char *path = NULL;
426   TCCMP cmp = NULL;
427   int omode = 0;
428   int max = -1;
429   bool pv = false;
430   bool px = false;
431   bool bk = false;
432   char *jstr = NULL;
433   char *bstr = NULL;
434   char *estr = NULL;
435   char *fmstr = NULL;
436   for(int i = 2; i < argc; i++){
437     if(!path && argv[i][0] == '-'){
438       if(!strcmp(argv[i], "-cd")){
439         cmp = tccmpdecimal;
440       } else if(!strcmp(argv[i], "-ci")){
441         cmp = tccmpint32;
442       } else if(!strcmp(argv[i], "-cj")){
443         cmp = tccmpint64;
444       } else if(!strcmp(argv[i], "-nl")){
445         omode |= BDBONOLCK;
446       } else if(!strcmp(argv[i], "-nb")){
447         omode |= BDBOLCKNB;
448       } else if(!strcmp(argv[i], "-m")){
449         if(++i >= argc) usage();
450         max = tcatoix(argv[i]);
451       } else if(!strcmp(argv[i], "-bk")){
452         bk = true;
453       } else if(!strcmp(argv[i], "-pv")){
454         pv = true;
455       } else if(!strcmp(argv[i], "-px")){
456         px = true;
457       } else if(!strcmp(argv[i], "-j")){
458         if(++i >= argc) usage();
459         jstr = argv[i];
460       } else if(!strcmp(argv[i], "-rb")){
461         if(++i >= argc) usage();
462         bstr = argv[i];
463         if(++i >= argc) usage();
464         estr = argv[i];
465       } else if(!strcmp(argv[i], "-fm")){
466         if(++i >= argc) usage();
467         fmstr = argv[i];
468       } else {
469         usage();
470       }
471     } else if(!path){
472       path = argv[i];
473     } else {
474       usage();
475     }
476   }
477   if(!path) usage();
478   int rv = proclist(path, cmp, omode, max, pv, px, bk, jstr, bstr, estr, fmstr);
479   return rv;
480 }
481 
482 
483 /* parse arguments of optimize command */
runoptimize(int argc,char ** argv)484 static int runoptimize(int argc, char **argv){
485   char *path = NULL;
486   char *lmstr = NULL;
487   char *nmstr = NULL;
488   char *bstr = NULL;
489   char *astr = NULL;
490   char *fstr = NULL;
491   TCCMP cmp = NULL;
492   int opts = UINT8_MAX;
493   int omode = 0;
494   bool df = false;
495   for(int i = 2; i < argc; i++){
496     if(!path && argv[i][0] == '-'){
497       if(!strcmp(argv[i], "-cd")){
498         cmp = tccmpdecimal;
499       } else if(!strcmp(argv[i], "-ci")){
500         cmp = tccmpint32;
501       } else if(!strcmp(argv[i], "-cj")){
502         cmp = tccmpint64;
503       } else if(!strcmp(argv[i], "-tl")){
504         if(opts == UINT8_MAX) opts = 0;
505         opts |= BDBTLARGE;
506       } else if(!strcmp(argv[i], "-td")){
507         if(opts == UINT8_MAX) opts = 0;
508         opts |= BDBTDEFLATE;
509       } else if(!strcmp(argv[i], "-tb")){
510         if(opts == UINT8_MAX) opts = 0;
511         opts |= BDBTBZIP;
512       } else if(!strcmp(argv[i], "-tt")){
513         if(opts == UINT8_MAX) opts = 0;
514         opts |= BDBTTCBS;
515       } else if(!strcmp(argv[i], "-tx")){
516         if(opts == UINT8_MAX) opts = 0;
517         opts |= BDBTEXCODEC;
518       } else if(!strcmp(argv[i], "-tz")){
519         if(opts == UINT8_MAX) opts = 0;
520       } else if(!strcmp(argv[i], "-nl")){
521         omode |= BDBONOLCK;
522       } else if(!strcmp(argv[i], "-nb")){
523         omode |= BDBOLCKNB;
524       } else if(!strcmp(argv[i], "-df")){
525         df = true;
526       } else {
527         usage();
528       }
529     } else if(!path){
530       path = argv[i];
531     } else if(!lmstr){
532       lmstr = argv[i];
533     } else if(!nmstr){
534       nmstr = argv[i];
535     } else if(!bstr){
536       bstr = argv[i];
537     } else if(!astr){
538       astr = argv[i];
539     } else if(!fstr){
540       fstr = argv[i];
541     } else {
542       usage();
543     }
544   }
545   if(!path) usage();
546   int lmemb = lmstr ? tcatoix(lmstr) : -1;
547   int nmemb = nmstr ? tcatoix(nmstr) : -1;
548   int bnum = bstr ? tcatoix(bstr) : -1;
549   int apow = astr ? tcatoix(astr) : -1;
550   int fpow = fstr ? tcatoix(fstr) : -1;
551   int rv = procoptimize(path, lmemb, nmemb, bnum, apow, fpow, cmp, opts, omode, df);
552   return rv;
553 }
554 
555 
556 /* parse arguments of importtsv command */
runimporttsv(int argc,char ** argv)557 static int runimporttsv(int argc, char **argv){
558   char *path = NULL;
559   char *file = NULL;
560   int omode = 0;
561   bool sc = false;
562   for(int i = 2; i < argc; i++){
563     if(!path && argv[i][0] == '-'){
564       if(!strcmp(argv[i], "-nl")){
565         omode |= BDBONOLCK;
566       } else if(!strcmp(argv[i], "-nb")){
567         omode |= BDBOLCKNB;
568       } else if(!strcmp(argv[i], "-sc")){
569         sc = true;
570       } else {
571         usage();
572       }
573     } else if(!path){
574       path = argv[i];
575     } else if(!file){
576       file = argv[i];
577     } else {
578       usage();
579     }
580   }
581   if(!path) usage();
582   int rv = procimporttsv(path, file, omode, sc);
583   return rv;
584 }
585 
586 
587 /* parse arguments of version command */
runversion(int argc,char ** argv)588 static int runversion(int argc, char **argv){
589   int rv = procversion();
590   return rv;
591 }
592 
593 
594 /* perform create command */
proccreate(const char * path,int lmemb,int nmemb,int bnum,int apow,int fpow,TCCMP cmp,int opts)595 static int proccreate(const char *path, int lmemb, int nmemb,
596                       int bnum, int apow, int fpow, TCCMP cmp, int opts){
597   TCBDB *bdb = tcbdbnew();
598   if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
599   if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb);
600   if(!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb);
601   if(!tcbdbtune(bdb, lmemb, nmemb, bnum, apow, fpow, opts)){
602     printerr(bdb);
603     tcbdbdel(bdb);
604     return 1;
605   }
606   if(!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | BDBOTRUNC)){
607     printerr(bdb);
608     tcbdbdel(bdb);
609     return 1;
610   }
611   bool err = false;
612   if(!tcbdbclose(bdb)){
613     printerr(bdb);
614     err = true;
615   }
616   tcbdbdel(bdb);
617   return err ? 1 : 0;
618 }
619 
620 
621 /* perform inform command */
procinform(const char * path,int omode)622 static int procinform(const char *path, int omode){
623   TCBDB *bdb = tcbdbnew();
624   if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
625   tcbdbsetcmpfunc(bdb, mycmpfunc, NULL);
626   tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL);
627   if(!tcbdbopen(bdb, path, BDBOREADER | omode)){
628     printerr(bdb);
629     tcbdbdel(bdb);
630     return 1;
631   }
632   bool err = false;
633   const char *npath = tcbdbpath(bdb);
634   if(!npath) npath = "(unknown)";
635   printf("path: %s\n", npath);
636   printf("database type: btree\n");
637   uint8_t flags = tcbdbflags(bdb);
638   printf("additional flags:");
639   if(flags & BDBFOPEN) printf(" open");
640   if(flags & BDBFFATAL) printf(" fatal");
641   printf("\n");
642   TCCMP cmp = tcbdbcmpfunc(bdb);
643   printf("comparison function: ");
644   if(cmp == tccmplexical){
645     printf("lexical");
646   } else if(cmp == tccmpdecimal){
647     printf("decimal");
648   } else if(cmp == tccmpint32){
649     printf("int32");
650   } else if(cmp == tccmpint64){
651     printf("int64");
652   } else {
653     printf("custom");
654   }
655   printf("\n");
656   printf("max leaf member: %d\n", tcbdblmemb(bdb));
657   printf("max node member: %d\n", tcbdbnmemb(bdb));
658   printf("leaf number: %llu\n", (unsigned long long)tcbdblnum(bdb));
659   printf("node number: %llu\n", (unsigned long long)tcbdbnnum(bdb));
660   printf("bucket number: %llu\n", (unsigned long long)tcbdbbnum(bdb));
661   if(bdb->hdb->cnt_writerec >= 0)
662     printf("used bucket number: %lld\n", (long long)tcbdbbnumused(bdb));
663   printf("alignment: %u\n", tcbdbalign(bdb));
664   printf("free block pool: %u\n", tcbdbfbpmax(bdb));
665   printf("inode number: %lld\n", (long long)tcbdbinode(bdb));
666   char date[48];
667   tcdatestrwww(tcbdbmtime(bdb), INT_MAX, date);
668   printf("modified time: %s\n", date);
669   uint8_t opts = tcbdbopts(bdb);
670   printf("options:");
671   if(opts & BDBTLARGE) printf(" large");
672   if(opts & BDBTDEFLATE) printf(" deflate");
673   if(opts & BDBTBZIP) printf(" bzip");
674   if(opts & BDBTTCBS) printf(" tcbs");
675   if(opts & BDBTEXCODEC) printf(" excodec");
676   printf("\n");
677   printf("record number: %llu\n", (unsigned long long)tcbdbrnum(bdb));
678   printf("file size: %llu\n", (unsigned long long)tcbdbfsiz(bdb));
679   if(!tcbdbclose(bdb)){
680     if(!err) printerr(bdb);
681     err = true;
682   }
683   tcbdbdel(bdb);
684   return err ? 1 : 0;
685 }
686 
687 
688 /* perform put command */
procput(const char * path,const char * kbuf,int ksiz,const char * vbuf,int vsiz,TCCMP cmp,int omode,int dmode)689 static int procput(const char *path, const char *kbuf, int ksiz, const char *vbuf, int vsiz,
690                    TCCMP cmp, int omode, int dmode){
691   TCBDB *bdb = tcbdbnew();
692   if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
693   if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb);
694   if(!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb);
695   if(!tcbdbopen(bdb, path, BDBOWRITER | omode)){
696     printerr(bdb);
697     tcbdbdel(bdb);
698     return 1;
699   }
700   bool err = false;
701   int inum;
702   double dnum;
703   switch(dmode){
704     case -1:
705       if(!tcbdbputkeep(bdb, kbuf, ksiz, vbuf, vsiz)){
706         printerr(bdb);
707         err = true;
708       }
709       break;
710     case 1:
711       if(!tcbdbputcat(bdb, kbuf, ksiz, vbuf, vsiz)){
712         printerr(bdb);
713         err = true;
714       }
715       break;
716     case 2:
717       if(!tcbdbputdup(bdb, kbuf, ksiz, vbuf, vsiz)){
718         printerr(bdb);
719         err = true;
720       }
721       break;
722     case 3:
723       if(!tcbdbputdupback(bdb, kbuf, ksiz, vbuf, vsiz)){
724         printerr(bdb);
725         err = true;
726       }
727       break;
728     case 10:
729       inum = tcbdbaddint(bdb, kbuf, ksiz, tcatoi(vbuf));
730       if(inum == INT_MIN){
731         printerr(bdb);
732         err = true;
733       } else {
734         printf("%d\n", inum);
735       }
736       break;
737     case 11:
738       dnum = tcbdbadddouble(bdb, kbuf, ksiz, tcatof(vbuf));
739       if(isnan(dnum)){
740         printerr(bdb);
741         err = true;
742       } else {
743         printf("%.6f\n", dnum);
744       }
745       break;
746     default:
747       if(!tcbdbput(bdb, kbuf, ksiz, vbuf, vsiz)){
748         printerr(bdb);
749         err = true;
750       }
751       break;
752   }
753   if(!tcbdbclose(bdb)){
754     if(!err) printerr(bdb);
755     err = true;
756   }
757   tcbdbdel(bdb);
758   return err ? 1 : 0;
759 }
760 
761 
762 /* perform out command */
procout(const char * path,const char * kbuf,int ksiz,TCCMP cmp,int omode)763 static int procout(const char *path, const char *kbuf, int ksiz, TCCMP cmp, int omode){
764   TCBDB *bdb = tcbdbnew();
765   if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
766   if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb);
767   if(!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb);
768   if(!tcbdbopen(bdb, path, BDBOWRITER | omode)){
769     printerr(bdb);
770     tcbdbdel(bdb);
771     return 1;
772   }
773   bool err = false;
774   if(!tcbdbout(bdb, kbuf, ksiz)){
775     printerr(bdb);
776     err = true;
777   }
778   if(!tcbdbclose(bdb)){
779     if(!err) printerr(bdb);
780     err = true;
781   }
782   tcbdbdel(bdb);
783   return err ? 1 : 0;
784 }
785 
786 
787 /* perform get command */
procget(const char * path,const char * kbuf,int ksiz,TCCMP cmp,int omode,bool px,bool pz)788 static int procget(const char *path, const char *kbuf, int ksiz, TCCMP cmp, int omode,
789                    bool px, bool pz){
790   TCBDB *bdb = tcbdbnew();
791   if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
792   if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb);
793   if(!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb);
794   if(!tcbdbopen(bdb, path, BDBOREADER | omode)){
795     printerr(bdb);
796     tcbdbdel(bdb);
797     return 1;
798   }
799   bool err = false;
800   int vsiz;
801   char *vbuf = tcbdbget(bdb, kbuf, ksiz, &vsiz);
802   if(vbuf){
803     printdata(vbuf, vsiz, px);
804     if(!pz) putchar('\n');
805     tcfree(vbuf);
806   } else {
807     printerr(bdb);
808     err = true;
809   }
810   if(!tcbdbclose(bdb)){
811     if(!err) printerr(bdb);
812     err = true;
813   }
814   tcbdbdel(bdb);
815   return err ? 1 : 0;
816 }
817 
818 
819 /* perform list command */
proclist(const char * path,TCCMP cmp,int omode,int max,bool pv,bool px,bool bk,const char * jstr,const char * bstr,const char * estr,const char * fmstr)820 static int proclist(const char *path, TCCMP cmp, int omode, int max, bool pv, bool px, bool bk,
821                     const char *jstr, const char *bstr, const char *estr, const char *fmstr){
822   TCBDB *bdb = tcbdbnew();
823   if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
824   if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb);
825   if(!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb);
826   if(!tcbdbopen(bdb, path, BDBOREADER | omode)){
827     printerr(bdb);
828     tcbdbdel(bdb);
829     return 1;
830   }
831   bool err = false;
832   if(bstr || fmstr){
833     TCLIST *keys = fmstr ? tcbdbfwmkeys2(bdb, fmstr, max) :
834       tcbdbrange(bdb, bstr, strlen(bstr), true, estr, strlen(estr), true, max);
835     int cnt = 0;
836     for(int i = 0; i < tclistnum(keys); i++){
837       int ksiz;
838       const char *kbuf = tclistval(keys, i, &ksiz);
839       if(pv){
840         TCLIST *vals = tcbdbget4(bdb, kbuf, ksiz);
841         if(vals){
842           for(int j = 0; j < tclistnum(vals); j++){
843             int vsiz;
844             const char *vbuf = tclistval(vals, j, &vsiz);
845             printdata(kbuf, ksiz, px);
846             putchar('\t');
847             printdata(vbuf, vsiz, px);
848             putchar('\n');
849             if(max >= 0 && ++cnt >= max) break;
850           }
851           tclistdel(vals);
852         }
853       } else {
854         int num = tcbdbvnum(bdb, kbuf, ksiz);
855         for(int j = 0; j < num; j++){
856           printdata(kbuf, ksiz, px);
857           putchar('\n');
858           if(max >= 0 && ++cnt >= max) break;
859         }
860       }
861       if(max >= 0 && cnt >= max) break;
862     }
863     tclistdel(keys);
864   } else {
865     BDBCUR *cur = tcbdbcurnew(bdb);
866     if(bk){
867       if(jstr){
868         if(!tcbdbcurjumpback(cur, jstr, strlen(jstr)) && tcbdbecode(bdb) != TCENOREC){
869           printerr(bdb);
870           err = true;
871         }
872       } else {
873         if(!tcbdbcurlast(cur) && tcbdbecode(bdb) != TCENOREC){
874           printerr(bdb);
875           err = true;
876         }
877       }
878     } else {
879       if(jstr){
880         if(!tcbdbcurjump(cur, jstr, strlen(jstr)) && tcbdbecode(bdb) != TCENOREC){
881           printerr(bdb);
882           err = true;
883         }
884       } else {
885         if(!tcbdbcurfirst(cur) && tcbdbecode(bdb) != TCENOREC){
886           printerr(bdb);
887           err = true;
888         }
889       }
890     }
891     TCXSTR *key = tcxstrnew();
892     TCXSTR *val = tcxstrnew();
893     int cnt = 0;
894     while(tcbdbcurrec(cur, key, val)){
895       printdata(tcxstrptr(key), tcxstrsize(key), px);
896       if(pv){
897         putchar('\t');
898         printdata(tcxstrptr(val), tcxstrsize(val), px);
899       }
900       putchar('\n');
901       if(bk){
902         if(!tcbdbcurprev(cur) && tcbdbecode(bdb) != TCENOREC){
903           printerr(bdb);
904           err = true;
905         }
906       } else {
907         if(!tcbdbcurnext(cur) && tcbdbecode(bdb) != TCENOREC){
908           printerr(bdb);
909           err = true;
910         }
911       }
912       if(max >= 0 && ++cnt >= max) break;
913     }
914     tcxstrdel(val);
915     tcxstrdel(key);
916     tcbdbcurdel(cur);
917   }
918   if(!tcbdbclose(bdb)){
919     if(!err) printerr(bdb);
920     err = true;
921   }
922   tcbdbdel(bdb);
923   return err ? 1 : 0;
924 }
925 
926 
927 /* perform optimize command */
procoptimize(const char * path,int lmemb,int nmemb,int bnum,int apow,int fpow,TCCMP cmp,int opts,int omode,bool df)928 static int procoptimize(const char *path, int lmemb, int nmemb,
929                         int bnum, int apow, int fpow, TCCMP cmp, int opts, int omode, bool df){
930   TCBDB *bdb = tcbdbnew();
931   if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
932   if(cmp && !tcbdbsetcmpfunc(bdb, cmp, NULL)) printerr(bdb);
933   if(!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb);
934   if(!tcbdbopen(bdb, path, BDBOWRITER | omode)){
935     printerr(bdb);
936     tcbdbdel(bdb);
937     return 1;
938   }
939   bool err = false;
940   if(df){
941     if(!tcbdbdefrag(bdb, INT64_MAX)){
942       printerr(bdb);
943       err = true;
944     }
945   } else {
946     if(!tcbdboptimize(bdb, lmemb, nmemb, bnum, apow, fpow, opts)){
947       printerr(bdb);
948       err = true;
949     }
950   }
951   if(!tcbdbclose(bdb)){
952     if(!err) printerr(bdb);
953     err = true;
954   }
955   tcbdbdel(bdb);
956   return err ? 1 : 0;
957 }
958 
959 
960 /* perform importtsv command */
procimporttsv(const char * path,const char * file,int omode,bool sc)961 static int procimporttsv(const char *path, const char *file, int omode, bool sc){
962   FILE *ifp = file ? fopen(file, "rb") : stdin;
963   if(!ifp){
964     fprintf(stderr, "%s: could not open\n", file ? file : "(stdin)");
965     return 1;
966   }
967   TCBDB *bdb = tcbdbnew();
968   if(g_dbgfd >= 0) tcbdbsetdbgfd(bdb, g_dbgfd);
969   if(!tcbdbsetcodecfunc(bdb, _tc_recencode, NULL, _tc_recdecode, NULL)) printerr(bdb);
970   if(!tcbdbopen(bdb, path, BDBOWRITER | BDBOCREAT | omode)){
971     printerr(bdb);
972     tcbdbdel(bdb);
973     if(ifp != stdin) fclose(ifp);
974     return 1;
975   }
976   bool err = false;
977   char *line;
978   int cnt = 0;
979   while(!err && (line = mygetline(ifp)) != NULL){
980     char *pv = strchr(line, '\t');
981     if(!pv){
982       tcfree(line);
983       continue;
984     }
985     *pv = '\0';
986     if(sc) tcstrutfnorm(line, TCUNSPACE | TCUNLOWER | TCUNNOACC | TCUNWIDTH);
987     if(!tcbdbputdup2(bdb, line, pv + 1)){
988       printerr(bdb);
989       err = true;
990     }
991     tcfree(line);
992     if(cnt > 0 && cnt % 100 == 0){
993       putchar('.');
994       fflush(stdout);
995       if(cnt % 5000 == 0) printf(" (%08d)\n", cnt);
996     }
997     cnt++;
998   }
999   printf(" (%08d)\n", cnt);
1000   if(!tcbdbclose(bdb)){
1001     if(!err) printerr(bdb);
1002     err = true;
1003   }
1004   tcbdbdel(bdb);
1005   if(ifp != stdin) fclose(ifp);
1006   return err ? 1 : 0;
1007 }
1008 
1009 
1010 /* perform version command */
procversion(void)1011 static int procversion(void){
1012   printf("Tokyo Cabinet version %s (%d:%s) for %s\n",
1013          tcversion, _TC_LIBVER, _TC_FORMATVER, TCSYSNAME);
1014   printf("Copyright (C) 2006-2012 FAL Labs\n");
1015   return 0;
1016 }
1017 
1018 
1019 
1020 // END OF FILE
1021