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 *************************************************************************************************/
22 /* global variables */
23 const char *g_progname; // program name
24 int g_dbgfd; // debugging output
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);
56 int main(int argc, char **argv){
59 const char *ebuf = getenv("TCDBGFD");
60 if(ebuf) g_dbgfd = atoi(ebuf);
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);
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",
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");
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));
116 /* print record data */
117 static int printdata(const char *ptr, int size, bool px){
121 if(len > 0) putchar(' ');
122 len += printf("%02X", *(unsigned char *)ptr);
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);
138 for(int i = 0; i < len; i += 2){
139 while(strchr(" \n\r\t\f\v", str[i])){
143 if((mbuf[0] = str[i]) == '\0') break;
144 if((mbuf[1] = str[i+1]) == '\0') break;
146 buf[j++] = (char)strtol(mbuf, NULL, 16);
154 /* read a line from a file descriptor */
155 static char *mygetline(FILE *ifp){
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';
168 if(!buf) return NULL;
174 /* parse arguments of create command */
175 static int runcreate(int argc, char **argv){
181 for(int i = 2; i < argc; i++){
182 if(!path && argv[i][0] == '-'){
183 if(!strcmp(argv[i], "-tl")){
185 } else if(!strcmp(argv[i], "-td")){
187 } else if(!strcmp(argv[i], "-tb")){
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);
213 /* parse arguments of inform command */
214 static int runinform(int argc, char **argv){
217 for(int i = 2; i < argc; i++){
218 if(!path && argv[i][0] == '-'){
219 if(!strcmp(argv[i], "-nl")){
221 } else if(!strcmp(argv[i], "-nb")){
233 int rv = procinform(path, omode);
238 /* parse arguments of put command */
239 static int runput(int argc, char **argv){
246 for(int i = 2; i < argc; i++){
247 if(!path && argv[i][0] == '-'){
248 if(!strcmp(argv[i], "-nl")){
250 } else if(!strcmp(argv[i], "-nb")){
252 } else if(!strcmp(argv[i], "-dk")){
254 } else if(!strcmp(argv[i], "-dc")){
256 } else if(!strcmp(argv[i], "-sx")){
271 if(!path || !key || !value) usage();
275 kbuf = hextoobj(key, &ksiz);
276 vbuf = hextoobj(value, &vsiz);
279 kbuf = tcmemdup(key, ksiz);
280 vsiz = strlen(value);
281 vbuf = tcmemdup(value, vsiz);
283 int rv = procput(path, kbuf, ksiz, vbuf, vsiz, omode, dmode);
290 /* parse arguments of out command */
291 static int runout(int argc, char **argv){
296 for(int i = 2; i < argc; i++){
297 if(!path && argv[i][0] == '-'){
298 if(!strcmp(argv[i], "-nl")){
300 } else if(!strcmp(argv[i], "-nb")){
302 } else if(!strcmp(argv[i], "-sx")){
315 if(!path || !key) usage();
319 kbuf = hextoobj(key, &ksiz);
322 kbuf = tcmemdup(key, ksiz);
324 int rv = procout(path, kbuf, ksiz, omode);
330 /* parse arguments of get command */
331 static int runget(int argc, char **argv){
338 for(int i = 2; i < argc; i++){
339 if(!path && argv[i][0] == '-'){
340 if(!strcmp(argv[i], "-nl")){
342 } else if(!strcmp(argv[i], "-nb")){
344 } else if(!strcmp(argv[i], "-sx")){
346 } else if(!strcmp(argv[i], "-px")){
348 } else if(!strcmp(argv[i], "-pz")){
361 if(!path || !key) usage();
365 kbuf = hextoobj(key, &ksiz);
368 kbuf = tcmemdup(key, ksiz);
370 int rv = procget(path, kbuf, ksiz, omode, px, pz);
376 /* parse arguments of list command */
377 static int runlist(int argc, char **argv){
384 for(int i = 2; i < argc; i++){
385 if(!path && argv[i][0] == '-'){
386 if(!strcmp(argv[i], "-nl")){
388 } else if(!strcmp(argv[i], "-nb")){
390 } else if(!strcmp(argv[i], "-m")){
391 if(++i >= argc) usage();
393 } else if(!strcmp(argv[i], "-pv")){
395 } else if(!strcmp(argv[i], "-px")){
397 } else if(!strcmp(argv[i], "-fm")){
398 if(++i >= argc) usage();
410 int rv = proclist(path, omode, max, pv, px, fmstr);
415 /* parse arguments of optimize command */
416 static int runoptimize(int argc, char **argv){
421 int opts = UINT8_MAX;
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;
428 } else if(!strcmp(argv[i], "-td")){
429 if(opts == UINT8_MAX) opts = 0;
431 } else if(!strcmp(argv[i], "-tb")){
432 if(opts == UINT8_MAX) opts = 0;
434 } else if(!strcmp(argv[i], "-tz")){
435 if(opts == UINT8_MAX) opts = 0;
436 } else if(!strcmp(argv[i], "-nl")){
438 } else if(!strcmp(argv[i], "-nb")){
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);
464 /* parse arguments of importtsv command */
465 static int runimporttsv(int argc, char **argv){
470 for(int i = 2; i < argc; i++){
471 if(!path && argv[i][0] == '-'){
472 if(!strcmp(argv[i], "-nl")){
474 } else if(!strcmp(argv[i], "-nb")){
476 } else if(!strcmp(argv[i], "-sc")){
490 int rv = procimporttsv(path, file, omode, sc);
495 /* parse arguments of version command */
496 static int runversion(int argc, char **argv){
497 int rv = procversion();
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)){
511 if(!tchdbopen(hdb, path, HDBOWRITER | HDBOCREAT | HDBOTRUNC)){
517 if(!tchdbclose(hdb)){
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)){
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;
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");
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));
557 tcdatestrwww(tchdbmtime(hdb), INT_MAX, date);
558 printf("modified time: %s\n", date);
559 uint8_t opts = tchdbopts(hdb);
561 if(opts & HDBTLARGE) printf(" large");
562 if(opts & HDBTDEFLATE) printf(" deflate");
563 if(opts & HDBTTCBS) printf(" tcbs");
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);
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)){
589 if(!tchdbputkeep(hdb, kbuf, ksiz, vbuf, vsiz)){
595 if(!tchdbputcat(hdb, kbuf, ksiz, vbuf, vsiz)){
601 if(!tchdbput(hdb, kbuf, ksiz, vbuf, vsiz)){
607 if(!tchdbclose(hdb)){
608 if(!err) printerr(hdb);
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)){
626 if(!tchdbout(hdb, kbuf, ksiz)){
630 if(!tchdbclose(hdb)){
631 if(!err) printerr(hdb);
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)){
650 char *vbuf = tchdbget(hdb, kbuf, ksiz, &vsiz);
652 printdata(vbuf, vsiz, px);
653 if(!pz) putchar('\n');
659 if(!tchdbclose(hdb)){
660 if(!err) printerr(hdb);
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)){
679 TCLIST *keys = tchdbfwmkeys2(hdb, fmstr, max);
680 for(int i = 0; i < tclistnum(keys); i++){
682 const char *kbuf = tclistval(keys, i, &ksiz);
683 printdata(kbuf, ksiz, px);
686 char *vbuf = tchdbget(hdb, kbuf, ksiz, &vsiz);
689 printdata(vbuf, vsiz, px);
697 if(!tchdbiterinit(hdb)){
701 TCXSTR *key = tcxstrnew();
702 TCXSTR *val = tcxstrnew();
704 while(tchdbiternext3(hdb, key, val)){
705 printdata(tcxstrptr(key), tcxstrsize(key), px);
708 printdata(tcxstrptr(val), tcxstrsize(val), px);
711 if(max >= 0 && ++cnt >= max) break;
716 if(!tchdbclose(hdb)){
717 if(!err) printerr(hdb);
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)){
735 if(!tchdboptimize(hdb, bnum, apow, fpow, opts)){
739 if(!tchdbclose(hdb)){
740 if(!err) printerr(hdb);
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;
754 fprintf(stderr, "%s: could not open\n", file ? file : "(stdin)");
758 if(!tchdbopen(hdb, path, HDBOWRITER | HDBOCREAT | omode)){
766 while(!err && (line = mygetline(ifp)) != NULL){
767 char *pv = strchr(line, '\t');
770 if(sc) tcstrtolower(line);
771 if(!tchdbput2(hdb, line, pv + 1) && tchdbecode(hdb) != TCEKEEP){
776 if(cnt > 0 && cnt % 100 == 0){
779 if(cnt % 5000 == 0) printf(" (%08d)\n", cnt);
783 printf(" (%08d)\n", cnt);
784 if(!tchdbclose(hdb)){
785 if(!err) printerr(hdb);
789 if(ifp != stdin) fclose(ifp);
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");