]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/tokyocabinet/tchmgr.c
ebl Add tokyocabinet source to bacula
[bacula/bacula] / bacula / src / lib / tokyocabinet / tchmgr.c
1 /*************************************************************************************************
2  * The command line utility 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  *************************************************************************************************/
15
16
17 #include <tcutil.h>
18 #include <tchdb.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(TCHDB *hdb);
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 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 bnum, int apow, int fpow, int opts);
44 static int procinform(const char *path, int omode);
45 static int procput(const char *path, const char *kbuf, int ksiz, const char *vbuf, int vsiz,
46                    int omode, int dmode);
47 static int procout(const char *path, const char *kbuf, int ksiz, int omode);
48 static int procget(const char *path, const char *kbuf, int ksiz, int omode, bool px, bool pz);
49 static int proclist(const char *path, int omode, int max, bool pv, bool px, const char *fmstr);
50 static int procoptimize(const char *path, int bnum, int apow, int fpow, int opts, int omode);
51 static int procimporttsv(const char *path, const char *file, int omode, bool sc);
52 static int procversion(void);
53
54
55 /* main routine */
56 int main(int argc, char **argv){
57   g_progname = argv[0];
58   g_dbgfd = -1;
59   const char *ebuf = getenv("TCDBGFD");
60   if(ebuf) g_dbgfd = atoi(ebuf);
61   if(argc < 2) usage();
62   int rv = 0;
63   if(!strcmp(argv[1], "create")){
64     rv = runcreate(argc, argv);
65   } else if(!strcmp(argv[1], "inform")){
66     rv = runinform(argc, argv);
67   } else if(!strcmp(argv[1], "put")){
68     rv = runput(argc, argv);
69   } else if(!strcmp(argv[1], "out")){
70     rv = runout(argc, argv);
71   } else if(!strcmp(argv[1], "get")){
72     rv = runget(argc, argv);
73   } else if(!strcmp(argv[1], "list")){
74     rv = runlist(argc, argv);
75   } else if(!strcmp(argv[1], "optimize")){
76     rv = runoptimize(argc, argv);
77   } else if(!strcmp(argv[1], "importtsv")){
78     rv = runimporttsv(argc, argv);
79   } else if(!strcmp(argv[1], "version") || !strcmp(argv[1], "--version")){
80     rv = runversion(argc, argv);
81   } else {
82     usage();
83   }
84   return rv;
85 }
86
87
88 /* print the usage and exit */
89 static void usage(void){
90   fprintf(stderr, "%s: the command line utility of the hash database API\n", g_progname);
91   fprintf(stderr, "\n");
92   fprintf(stderr, "usage:\n");
93   fprintf(stderr, "  %s create [-tl] [-td|-tb] path [bnum [apow [fpow]]]\n", g_progname);
94   fprintf(stderr, "  %s inform [-nl|-nb] path\n", g_progname);
95   fprintf(stderr, "  %s put [-nl|-nb] [-sx] [-dk|-dc] path key value\n", g_progname);
96   fprintf(stderr, "  %s out [-nl|-nb] [-sx] path key\n", g_progname);
97   fprintf(stderr, "  %s get [-nl|-nb] [-sx] [-px] [-pz] path key\n", g_progname);
98   fprintf(stderr, "  %s list [-nl|-nb] [-m num] [-pv] [-px] [-fm str] path\n", g_progname);
99   fprintf(stderr, "  %s optimize [-tl] [-td|-tb] [-tz] [-nl|-nb] path [bnum [apow [fpow]]]\n",
100           g_progname);
101   fprintf(stderr, "  %s importtsv [-nl|-nb] [-sc] path [file]\n", g_progname);
102   fprintf(stderr, "  %s version\n", g_progname);
103   fprintf(stderr, "\n");
104   exit(1);
105 }
106
107
108 /* print error information */
109 static void printerr(TCHDB *hdb){
110   const char *path = tchdbpath(hdb);
111   int ecode = tchdbecode(hdb);
112   fprintf(stderr, "%s: %s: %d: %s\n", g_progname, path ? path : "-", ecode, tchdberrmsg(ecode));
113 }
114
115
116 /* print record data */
117 static int printdata(const char *ptr, int size, bool px){
118   int len = 0;
119   while(size-- > 0){
120     if(px){
121       if(len > 0) putchar(' ');
122       len += printf("%02X", *(unsigned char *)ptr);
123     } else {
124       putchar(*ptr);
125       len++;
126     }
127     ptr++;
128   }
129   return len;
130 }
131
132
133 /* create a binary object from a hexadecimal string */
134 static char *hextoobj(const char *str, int *sp){
135   int len = strlen(str);
136   char *buf = tcmalloc(len + 1);
137   int j = 0;
138   for(int i = 0; i < len; i += 2){
139     while(strchr(" \n\r\t\f\v", str[i])){
140       i++;
141     }
142     char mbuf[3];
143     if((mbuf[0] = str[i]) == '\0') break;
144     if((mbuf[1] = str[i+1]) == '\0') break;
145     mbuf[2] = '\0';
146     buf[j++] = (char)strtol(mbuf, NULL, 16);
147   }
148   buf[j] = '\0';
149   *sp = j;
150   return buf;
151 }
152
153
154 /* read a line from a file descriptor */
155 static char *mygetline(FILE *ifp){
156   char *buf;
157   int c, len, blen;
158   buf = NULL;
159   len = 0;
160   blen = 256;
161   while((c = fgetc(ifp)) != EOF){
162     if(blen <= len) blen *= 2;
163     buf = tcrealloc(buf, blen + 1);
164     if(c == '\n' || c == '\r') c = '\0';
165     buf[len++] = c;
166     if(c == '\0') break;
167   }
168   if(!buf) return NULL;
169   buf[len] = '\0';
170   return buf;
171 }
172
173
174 /* parse arguments of create command */
175 static int runcreate(int argc, char **argv){
176   char *path = NULL;
177   char *bstr = NULL;
178   char *astr = NULL;
179   char *fstr = NULL;
180   int opts = 0;
181   for(int i = 2; i < argc; i++){
182     if(!path && argv[i][0] == '-'){
183       if(!strcmp(argv[i], "-tl")){
184         opts |= HDBTLARGE;
185       } else if(!strcmp(argv[i], "-td")){
186         opts |= HDBTDEFLATE;
187       } else if(!strcmp(argv[i], "-tb")){
188         opts |= HDBTTCBS;
189       } else {
190         usage();
191       }
192     } else if(!path){
193       path = argv[i];
194     } else if(!bstr){
195       bstr = argv[i];
196     } else if(!astr){
197       astr = argv[i];
198     } else if(!fstr){
199       fstr = argv[i];
200     } else {
201       usage();
202     }
203   }
204   if(!path) usage();
205   int bnum = bstr ? atoi(bstr) : -1;
206   int apow = astr ? atoi(astr) : -1;
207   int fpow = fstr ? atoi(fstr) : -1;
208   int rv = proccreate(path, bnum, apow, fpow, opts);
209   return rv;
210 }
211
212
213 /* parse arguments of inform command */
214 static int runinform(int argc, char **argv){
215   char *path = NULL;
216   int omode = 0;
217   for(int i = 2; i < argc; i++){
218     if(!path && argv[i][0] == '-'){
219       if(!strcmp(argv[i], "-nl")){
220         omode |= HDBONOLCK;
221       } else if(!strcmp(argv[i], "-nb")){
222         omode |= HDBOLCKNB;
223       } else {
224         usage();
225       }
226     } else if(!path){
227       path = argv[i];
228     } else {
229       usage();
230     }
231   }
232   if(!path) usage();
233   int rv = procinform(path, omode);
234   return rv;
235 }
236
237
238 /* parse arguments of put command */
239 static int runput(int argc, char **argv){
240   char *path = NULL;
241   char *key = NULL;
242   char *value = NULL;
243   int omode = 0;
244   int dmode = 0;
245   bool sx = false;
246   for(int i = 2; i < argc; i++){
247     if(!path && argv[i][0] == '-'){
248       if(!strcmp(argv[i], "-nl")){
249         omode |= HDBONOLCK;
250       } else if(!strcmp(argv[i], "-nb")){
251         omode |= HDBOLCKNB;
252       } else if(!strcmp(argv[i], "-dk")){
253         dmode = -1;
254       } else if(!strcmp(argv[i], "-dc")){
255         dmode = 1;
256       } else if(!strcmp(argv[i], "-sx")){
257         sx = true;
258       } else {
259         usage();
260       }
261     } else if(!path){
262       path = argv[i];
263     } else if(!key){
264       key = argv[i];
265     } else if(!value){
266       value = argv[i];
267     } else {
268       usage();
269     }
270   }
271   if(!path || !key || !value) usage();
272   int ksiz, vsiz;
273   char *kbuf, *vbuf;
274   if(sx){
275     kbuf = hextoobj(key, &ksiz);
276     vbuf = hextoobj(value, &vsiz);
277   } else {
278     ksiz = strlen(key);
279     kbuf = tcmemdup(key, ksiz);
280     vsiz = strlen(value);
281     vbuf = tcmemdup(value, vsiz);
282   }
283   int rv = procput(path, kbuf, ksiz, vbuf, vsiz, omode, dmode);
284   free(vbuf);
285   free(kbuf);
286   return rv;
287 }
288
289
290 /* parse arguments of out command */
291 static int runout(int argc, char **argv){
292   char *path = NULL;
293   char *key = NULL;
294   int omode = 0;
295   bool sx = false;
296   for(int i = 2; i < argc; i++){
297     if(!path && argv[i][0] == '-'){
298       if(!strcmp(argv[i], "-nl")){
299         omode |= HDBONOLCK;
300       } else if(!strcmp(argv[i], "-nb")){
301         omode |= HDBOLCKNB;
302       } else if(!strcmp(argv[i], "-sx")){
303         sx = true;
304       } else {
305         usage();
306       }
307     } else if(!path){
308       path = argv[i];
309     } else if(!key){
310       key = argv[i];
311     } else {
312       usage();
313     }
314   }
315   if(!path || !key) usage();
316   int ksiz;
317   char *kbuf;
318   if(sx){
319     kbuf = hextoobj(key, &ksiz);
320   } else {
321     ksiz = strlen(key);
322     kbuf = tcmemdup(key, ksiz);
323   }
324   int rv = procout(path, kbuf, ksiz, omode);
325   free(kbuf);
326   return rv;
327 }
328
329
330 /* parse arguments of get command */
331 static int runget(int argc, char **argv){
332   char *path = NULL;
333   char *key = NULL;
334   int omode = 0;
335   bool sx = false;
336   bool px = false;
337   bool pz = false;
338   for(int i = 2; i < argc; i++){
339     if(!path && argv[i][0] == '-'){
340       if(!strcmp(argv[i], "-nl")){
341         omode |= HDBONOLCK;
342       } else if(!strcmp(argv[i], "-nb")){
343         omode |= HDBOLCKNB;
344       } else if(!strcmp(argv[i], "-sx")){
345         sx = true;
346       } else if(!strcmp(argv[i], "-px")){
347         px = true;
348       } else if(!strcmp(argv[i], "-pz")){
349         pz = true;
350       } else {
351         usage();
352       }
353     } else if(!path){
354       path = argv[i];
355     } else if(!key){
356       key = argv[i];
357     } else {
358       usage();
359     }
360   }
361   if(!path || !key) usage();
362   int ksiz;
363   char *kbuf;
364   if(sx){
365     kbuf = hextoobj(key, &ksiz);
366   } else {
367     ksiz = strlen(key);
368     kbuf = tcmemdup(key, ksiz);
369   }
370   int rv = procget(path, kbuf, ksiz, omode, px, pz);
371   free(kbuf);
372   return rv;
373 }
374
375
376 /* parse arguments of list command */
377 static int runlist(int argc, char **argv){
378   char *path = NULL;
379   int omode = 0;
380   int max = -1;
381   bool pv = false;
382   bool px = false;
383   char *fmstr = NULL;
384   for(int i = 2; i < argc; i++){
385     if(!path && argv[i][0] == '-'){
386       if(!strcmp(argv[i], "-nl")){
387         omode |= HDBONOLCK;
388       } else if(!strcmp(argv[i], "-nb")){
389         omode |= HDBOLCKNB;
390       } else if(!strcmp(argv[i], "-m")){
391         if(++i >= argc) usage();
392         max = atoi(argv[i]);
393       } else if(!strcmp(argv[i], "-pv")){
394         pv = true;
395       } else if(!strcmp(argv[i], "-px")){
396         px = true;
397       } else if(!strcmp(argv[i], "-fm")){
398         if(++i >= argc) usage();
399         fmstr = argv[i];
400       } else {
401         usage();
402       }
403     } else if(!path){
404       path = argv[i];
405     } else {
406       usage();
407     }
408   }
409   if(!path) usage();
410   int rv = proclist(path, omode, max, pv, px, fmstr);
411   return rv;
412 }
413
414
415 /* parse arguments of optimize command */
416 static int runoptimize(int argc, char **argv){
417   char *path = NULL;
418   char *bstr = NULL;
419   char *astr = NULL;
420   char *fstr = NULL;
421   int opts = UINT8_MAX;
422   int omode = 0;
423   for(int i = 2; i < argc; i++){
424     if(!path && argv[i][0] == '-'){
425       if(!strcmp(argv[i], "-tl")){
426         if(opts == UINT8_MAX) opts = 0;
427         opts |= HDBTLARGE;
428       } else if(!strcmp(argv[i], "-td")){
429         if(opts == UINT8_MAX) opts = 0;
430         opts |= HDBTDEFLATE;
431       } else if(!strcmp(argv[i], "-tb")){
432         if(opts == UINT8_MAX) opts = 0;
433         opts |= HDBTTCBS;
434       } else if(!strcmp(argv[i], "-tz")){
435         if(opts == UINT8_MAX) opts = 0;
436       } else if(!strcmp(argv[i], "-nl")){
437         omode |= HDBONOLCK;
438       } else if(!strcmp(argv[i], "-nb")){
439         omode |= HDBOLCKNB;
440       } else {
441         usage();
442       }
443     } else if(!path){
444       path = argv[i];
445     } else if(!bstr){
446       bstr = argv[i];
447     } else if(!astr){
448       astr = argv[i];
449     } else if(!fstr){
450       fstr = argv[i];
451     } else {
452       usage();
453     }
454   }
455   if(!path) usage();
456   int bnum = bstr ? atoi(bstr) : -1;
457   int apow = astr ? atoi(astr) : -1;
458   int fpow = fstr ? atoi(fstr) : -1;
459   int rv = procoptimize(path, bnum, apow, fpow, opts, omode);
460   return rv;
461 }
462
463
464 /* parse arguments of importtsv command */
465 static int runimporttsv(int argc, char **argv){
466   char *path = NULL;
467   char *file = NULL;
468   int omode = 0;
469   bool sc = false;
470   for(int i = 2; i < argc; i++){
471     if(!path && argv[i][0] == '-'){
472       if(!strcmp(argv[i], "-nl")){
473         omode |= HDBONOLCK;
474       } else if(!strcmp(argv[i], "-nb")){
475         omode |= HDBOLCKNB;
476       } else if(!strcmp(argv[i], "-sc")){
477         sc = true;
478       } else {
479         usage();
480       }
481     } else if(!path){
482       path = argv[i];
483     } else if(!file){
484       file = argv[i];
485     } else {
486       usage();
487     }
488   }
489   if(!path) usage();
490   int rv = procimporttsv(path, file, omode, sc);
491   return rv;
492 }
493
494
495 /* parse arguments of version command */
496 static int runversion(int argc, char **argv){
497   int rv = procversion();
498   return rv;
499 }
500
501
502 /* perform create command */
503 static int proccreate(const char *path, int bnum, int apow, int fpow, int opts){
504   TCHDB *hdb = tchdbnew();
505   if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
506   if(!tchdbtune(hdb, bnum, apow, fpow, opts)){
507     printerr(hdb);
508     tchdbdel(hdb);
509     return 1;
510   }
511   if(!tchdbopen(hdb, path, HDBOWRITER | HDBOCREAT | HDBOTRUNC)){
512     printerr(hdb);
513     tchdbdel(hdb);
514     return 1;
515   }
516   bool err = false;
517   if(!tchdbclose(hdb)){
518     printerr(hdb);
519     err = true;
520   }
521   tchdbdel(hdb);
522   return err ? 1 : 0;
523 }
524
525
526 /* perform inform command */
527 static int procinform(const char *path, int omode){
528   TCHDB *hdb = tchdbnew();
529   if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
530   if(!tchdbopen(hdb, path, HDBOREADER | omode)){
531     printerr(hdb);
532     tchdbdel(hdb);
533     return 1;
534   }
535   bool err = false;
536   const char *npath = tchdbpath(hdb);
537   if(!npath) npath = "(unknown)";
538   printf("path: %s\n", npath);
539   const char *type = "(unknown)";
540   switch(tchdbtype(hdb)){
541   case HDBTHASH: type = "hash"; break;
542   case HDBTBTREE: type = "btree"; break;
543   }
544   printf("database type: %s\n", type);
545   uint8_t flags = tchdbflags(hdb);
546   printf("additional flags:");
547   if(flags & HDBFOPEN) printf(" open");
548   if(flags & HDBFFATAL) printf(" fatal");
549   printf("\n");
550   printf("bucket number: %llu\n", (unsigned long long)tchdbbnum(hdb));
551   if(hdb->cnt_writerec >= 0)
552     printf("used bucket number: %lld\n", (long long)tchdbbnumused(hdb));
553   printf("alignment: %u\n", tchdbalign(hdb));
554   printf("free block pool: %u\n", tchdbfbpmax(hdb));
555   printf("inode number: %lld\n", (long long)tchdbinode(hdb));
556   char date[48];
557   tcdatestrwww(tchdbmtime(hdb), INT_MAX, date);
558   printf("modified time: %s\n", date);
559   uint8_t opts = tchdbopts(hdb);
560   printf("options:");
561   if(opts & HDBTLARGE) printf(" large");
562   if(opts & HDBTDEFLATE) printf(" deflate");
563   if(opts & HDBTTCBS) printf(" tcbs");
564   printf("\n");
565   printf("record number: %llu\n", (unsigned long long)tchdbrnum(hdb));
566   printf("file size: %llu\n", (unsigned long long)tchdbfsiz(hdb));
567   if(!tchdbclose(hdb)){
568     if(!err) printerr(hdb);
569     err = true;
570   }
571   tchdbdel(hdb);
572   return err ? 1 : 0;
573 }
574
575
576 /* perform put command */
577 static int procput(const char *path, const char *kbuf, int ksiz, const char *vbuf, int vsiz,
578                    int omode, int dmode){
579   TCHDB *hdb = tchdbnew();
580   if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
581   if(!tchdbopen(hdb, path, HDBOWRITER | omode)){
582     printerr(hdb);
583     tchdbdel(hdb);
584     return 1;
585   }
586   bool err = false;
587   switch(dmode){
588   case -1:
589     if(!tchdbputkeep(hdb, kbuf, ksiz, vbuf, vsiz)){
590       printerr(hdb);
591       err = true;
592     }
593     break;
594   case 1:
595     if(!tchdbputcat(hdb, kbuf, ksiz, vbuf, vsiz)){
596       printerr(hdb);
597       err = true;
598     }
599     break;
600   default:
601     if(!tchdbput(hdb, kbuf, ksiz, vbuf, vsiz)){
602       printerr(hdb);
603       err = true;
604     }
605     break;
606   }
607   if(!tchdbclose(hdb)){
608     if(!err) printerr(hdb);
609     err = true;
610   }
611   tchdbdel(hdb);
612   return err ? 1 : 0;
613 }
614
615
616 /* perform out command */
617 static int procout(const char *path, const char *kbuf, int ksiz, int omode){
618   TCHDB *hdb = tchdbnew();
619   if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
620   if(!tchdbopen(hdb, path, HDBOWRITER | omode)){
621     printerr(hdb);
622     tchdbdel(hdb);
623     return 1;
624   }
625   bool err = false;
626   if(!tchdbout(hdb, kbuf, ksiz)){
627     printerr(hdb);
628     err = true;
629   }
630   if(!tchdbclose(hdb)){
631     if(!err) printerr(hdb);
632     err = true;
633   }
634   tchdbdel(hdb);
635   return err ? 1 : 0;
636 }
637
638
639 /* perform get command */
640 static int procget(const char *path, const char *kbuf, int ksiz, int omode, bool px, bool pz){
641   TCHDB *hdb = tchdbnew();
642   if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
643   if(!tchdbopen(hdb, path, HDBOREADER | omode)){
644     printerr(hdb);
645     tchdbdel(hdb);
646     return 1;
647   }
648   bool err = false;
649   int vsiz;
650   char *vbuf = tchdbget(hdb, kbuf, ksiz, &vsiz);
651   if(vbuf){
652     printdata(vbuf, vsiz, px);
653     if(!pz) putchar('\n');
654     free(vbuf);
655   } else {
656     printerr(hdb);
657     err = true;
658   }
659   if(!tchdbclose(hdb)){
660     if(!err) printerr(hdb);
661     err = true;
662   }
663   tchdbdel(hdb);
664   return err ? 1 : 0;
665 }
666
667
668 /* perform list command */
669 static int proclist(const char *path, int omode, int max, bool pv, bool px, const char *fmstr){
670   TCHDB *hdb = tchdbnew();
671   if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
672   if(!tchdbopen(hdb, path, HDBOREADER | omode)){
673     printerr(hdb);
674     tchdbdel(hdb);
675     return 1;
676   }
677   bool err = false;
678   if(fmstr){
679     TCLIST *keys = tchdbfwmkeys2(hdb, fmstr, max);
680     for(int i = 0; i < tclistnum(keys); i++){
681       int ksiz;
682       const char *kbuf = tclistval(keys, i, &ksiz);
683       printdata(kbuf, ksiz, px);
684       if(pv){
685         int vsiz;
686         char *vbuf = tchdbget(hdb, kbuf, ksiz, &vsiz);
687         if(vbuf){
688           putchar('\t');
689           printdata(vbuf, vsiz, px);
690           free(vbuf);
691         }
692       }
693       putchar('\n');
694     }
695     tclistdel(keys);
696   } else {
697     if(!tchdbiterinit(hdb)){
698       printerr(hdb);
699       err = true;
700     }
701     TCXSTR *key = tcxstrnew();
702     TCXSTR *val = tcxstrnew();
703     int cnt = 0;
704     while(tchdbiternext3(hdb, key, val)){
705       printdata(tcxstrptr(key), tcxstrsize(key), px);
706       if(pv){
707         putchar('\t');
708         printdata(tcxstrptr(val), tcxstrsize(val), px);
709       }
710       putchar('\n');
711       if(max >= 0 && ++cnt >= max) break;
712     }
713     tcxstrdel(val);
714     tcxstrdel(key);
715   }
716   if(!tchdbclose(hdb)){
717     if(!err) printerr(hdb);
718     err = true;
719   }
720   tchdbdel(hdb);
721   return err ? 1 : 0;
722 }
723
724
725 /* perform optimize command */
726 static int procoptimize(const char *path, int bnum, int apow, int fpow, int opts, int omode){
727   TCHDB *hdb = tchdbnew();
728   if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
729   if(!tchdbopen(hdb, path, HDBOWRITER | omode)){
730     printerr(hdb);
731     tchdbdel(hdb);
732     return 1;
733   }
734   bool err = false;
735   if(!tchdboptimize(hdb, bnum, apow, fpow, opts)){
736     printerr(hdb);
737     err = true;
738   }
739   if(!tchdbclose(hdb)){
740     if(!err) printerr(hdb);
741     err = true;
742   }
743   tchdbdel(hdb);
744   return err ? 1 : 0;
745 }
746
747
748 /* perform importtsv command */
749 static int procimporttsv(const char *path, const char *file, int omode, bool sc){
750   TCHDB *hdb = tchdbnew();
751   if(g_dbgfd >= 0) tchdbsetdbgfd(hdb, g_dbgfd);
752   FILE *ifp = file ? fopen(file, "rb") : stdin;
753   if(!ifp){
754     fprintf(stderr, "%s: could not open\n", file ? file : "(stdin)");
755     tchdbdel(hdb);
756     return 1;
757   }
758   if(!tchdbopen(hdb, path, HDBOWRITER | HDBOCREAT | omode)){
759     printerr(hdb);
760     tchdbdel(hdb);
761     return 1;
762   }
763   bool err = false;
764   char *line;
765   int cnt = 0;
766   while(!err && (line = mygetline(ifp)) != NULL){
767     char *pv = strchr(line, '\t');
768     if(!pv) continue;
769     *pv = '\0';
770     if(sc) tcstrtolower(line);
771     if(!tchdbput2(hdb, line, pv + 1) && tchdbecode(hdb) != TCEKEEP){
772       printerr(hdb);
773       err = true;
774     }
775     free(line);
776     if(cnt > 0 && cnt % 100 == 0){
777       putchar('.');
778       fflush(stdout);
779       if(cnt % 5000 == 0) printf(" (%08d)\n", cnt);
780     }
781     cnt++;
782   }
783   printf(" (%08d)\n", cnt);
784   if(!tchdbclose(hdb)){
785     if(!err) printerr(hdb);
786     err = true;
787   }
788   tchdbdel(hdb);
789   if(ifp != stdin) fclose(ifp);
790   return err ? 1 : 0;
791 }
792
793
794 /* perform version command */
795 static int procversion(void){
796   printf("Tokyo Cabinet version %s (%d:%s)\n", tcversion, _TC_LIBVER, _TC_FORMATVER);
797   printf("Copyright (C) 2006-2008 Mikio Hirabayashi\n");
798   return 0;
799 }
800
801
802
803 // END OF FILE