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