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