389
381
printf("leafsizes\t%" PRIu64 "\n", info.leafsizes);
393
dump_garbage_stats(int f, FT ft) {
394
invariant(f == toku_cachefile_get_fd(ft->cf));
384
static void dump_garbage_stats(int fd, FT ft) {
385
assert(fd == toku_cachefile_get_fd(ft->cf));
395
386
uint64_t total_space = 0;
396
387
uint64_t used_space = 0;
397
388
toku_ft_get_garbage(ft, &total_space, &used_space);
398
printf("total_size\t%" PRIu64 "\n", total_space);
399
printf("used_size\t%" PRIu64 "\n", used_space);
403
get_unaligned_uint32(unsigned char *p) {
404
return *(uint32_t *)p;
389
printf("garbage total size\t%" PRIu64 "\n", total_space);
390
printf("garbage used size\t%" PRIu64 "\n", used_space);
393
typedef struct __dump_node_extra {
398
static int dump_node_wrapper(BLOCKNUM b, int64_t UU(size), int64_t UU(address), void *extra) {
399
dump_node_extra *CAST_FROM_VOIDP(info, extra);
400
dump_node(info->fd, b, info->h);
404
static uint32_t get_unaligned_uint32(unsigned char *p) {
406
memcpy(&n, p, sizeof n);
407
410
struct dump_sub_block {
408
uint32_t compressed_size;
409
uint32_t uncompressed_size;
411
uint32_t compressed_size;
412
uint32_t uncompressed_size;
414
sub_block_deserialize(struct dump_sub_block *sb, unsigned char *sub_block_header) {
416
static void sub_block_deserialize(struct dump_sub_block *sb, unsigned char *sub_block_header) {
415
417
sb->compressed_size = toku_dtoh32(get_unaligned_uint32(sub_block_header+0));
416
418
sb->uncompressed_size = toku_dtoh32(get_unaligned_uint32(sub_block_header+4));
417
419
sb->xsum = toku_dtoh32(get_unaligned_uint32(sub_block_header+8));
421
verify_block(unsigned char *cp, uint64_t file_offset, uint64_t size) {
422
static void verify_block(unsigned char *cp, uint64_t file_offset, uint64_t size) {
422
423
// verify the header checksum
423
424
const size_t node_header = 8 + sizeof (uint32_t) + sizeof (uint32_t) + sizeof (uint32_t);
552
538
fprintf(stderr, "quit\n");
556
getuint64(const char *f) {
557
if (strncmp(f, "0x", 2) == 0 || strncmp(f, "0X", 2) == 0)
558
return strtoull(f, 0, 16);
559
else if (strncmp(f, "0", 1) == 0)
560
return strtoull(f, 0, 8);
562
return strtoull(f, 0, 10);
566
main (int argc, const char *const argv[]) {
568
int fragmentation = 0;
569
int translation_table = 0;
573
const char *arg0 = argv[0];
541
static void run_iteractive_loop(int fd, FT ft, CACHEFILE cf) {
543
printf("ftdump>"); fflush(stdout);
544
enum { maxline = 64};
545
char line[maxline+1];
546
int r = readline(line, maxline);
549
const int maxfields = 4;
550
char *fields[maxfields];
551
int nfields = split_fields(line, fields, maxfields);
554
if (strcmp(fields[0], "help") == 0) {
556
} else if (strcmp(fields[0], "header") == 0) {
558
open_header(fd, &ft, cf);
560
} else if (strcmp(fields[0], "block") == 0 && nfields == 2) {
561
BLOCKNUM blocknum = make_blocknum(getuint64(fields[1]));
562
dump_block(fd, blocknum, ft);
563
} else if (strcmp(fields[0], "node") == 0 && nfields == 2) {
564
BLOCKNUM off = make_blocknum(getuint64(fields[1]));
565
dump_node(fd, off, ft);
566
} else if (strcmp(fields[0], "dumpdata") == 0 && nfields == 2) {
567
do_dump_data = strtol(fields[1], NULL, 10);
568
} else if (strcmp(fields[0], "block_translation") == 0 || strcmp(fields[0], "bx") == 0) {
571
offset = getuint64(fields[1]);
572
dump_block_translation(ft, offset);
573
} else if (strcmp(fields[0], "fragmentation") == 0) {
574
dump_fragmentation(fd, ft, do_tsv);
575
} else if (strcmp(fields[0], "nodesizes") == 0) {
576
dump_nodesizes(fd, ft);
577
} else if (strcmp(fields[0], "garbage") == 0) {
578
dump_garbage_stats(fd, ft);
579
} else if (strcmp(fields[0], "file") == 0 && nfields >= 3) {
580
uint64_t offset = getuint64(fields[1]);
581
uint64_t size = getuint64(fields[2]);
582
FILE *outfp = stdout;
584
outfp = fopen(fields[3], "w");
585
dump_file(fd, offset, size, outfp);
586
} else if (strcmp(fields[0], "setfile") == 0 && nfields == 3) {
587
uint64_t offset = getuint64(fields[1]);
588
unsigned char newc = getuint64(fields[2]);
589
set_file(fd, offset, newc);
590
} else if (strcmp(fields[0], "quit") == 0 || strcmp(fields[0], "q") == 0) {
596
static int usage(void) {
597
fprintf(stderr, "Usage: %s ", arg0);
598
fprintf(stderr, "--interactive ");
599
fprintf(stderr, "--nodata ");
600
fprintf(stderr, "--dumpdata 0|1 ");
601
fprintf(stderr, "--header ");
602
fprintf(stderr, "--rootnode ");
603
fprintf(stderr, "--fragmentation ");
604
fprintf(stderr, "--garbage ");
605
fprintf(stderr, "--tsv ");
606
fprintf(stderr, "--translation-table ");
607
fprintf(stderr, "--tsv ");
608
fprintf(stderr, "ftfilename \n");
612
int main (int argc, const char *const argv[]) {
576
if (strcmp(argv[0], "--nodata") == 0) {
578
} else if (strcmp(argv[0], "--interactive") == 0 || strcmp(argv[0], "--i") == 0) {
616
if (strcmp(argv[0], "--interactive") == 0 || strcmp(argv[0], "--i") == 0) {
618
} else if (strcmp(argv[0], "--nodata") == 0) {
620
} else if (strcmp(argv[0], "--dumpdata") == 0 && argc > 1) {
622
do_dump_data = atoi(argv[0]);
623
} else if (strcmp(argv[0], "--header") == 0) {
625
} else if (strcmp(argv[0], "--rootnode") == 0) {
580
627
} else if (strcmp(argv[0], "--fragmentation") == 0) {
628
do_fragmentation = 1;
629
} else if (strcmp(argv[0], "--garbage") == 0) {
582
631
} else if (strcmp(argv[0], "--tsv") == 0) {
584
633
} else if (strcmp(argv[0], "--translation-table") == 0) {
585
translation_table = 1;
586
} else if (strcmp(argv[0], "--rootnode") == 0) {
588
} else if (strcmp(argv[0], "--help") == 0) {
634
do_translation_table = 1;
635
} else if (strcmp(argv[0], "--help") == 0 || strcmp(argv[0], "-?") == 0 || strcmp(argv[0], "-h") == 0) {
595
if (argc != 1) return usage(arg0);
597
645
int r = toku_ft_layer_init();
600
const char *n = argv[0];
601
int f = open(n, O_RDWR + O_BINARY); assert(f>=0);
649
int fd = open(fname, O_RDWR + O_BINARY);
651
fprintf(stderr, "%s: can not open %s errno %d\n", arg0, fname, errno);
603
655
// create a cachefile for the header
656
CACHETABLE ct = NULL;
604
657
toku_cachetable_create(&ct, 1<<25, (LSN){0}, 0);
605
659
CACHEFILE cf = NULL;
606
r = toku_cachetable_openfd (&cf, ct, f, n);
608
open_header(f, &ft, cf);
609
if (!fragmentation && !translation_table) {
610
// quick fix for now, we want those two to have clean output
615
printf("ftdump>"); fflush(stdout);
616
enum { maxline = 64};
617
char line[maxline+1];
618
r = readline(line, maxline);
621
const int maxfields = 4;
622
char *fields[maxfields];
623
int nfields = split_fields(line, fields, maxfields);
626
if (strcmp(fields[0], "help") == 0) {
628
} else if (strcmp(fields[0], "header") == 0) {
630
open_header(f, &ft, cf);
632
} else if (strcmp(fields[0], "block") == 0 && nfields == 2) {
633
BLOCKNUM blocknum = make_blocknum(getuint64(fields[1]));
634
dump_block(f, blocknum, ft);
635
} else if (strcmp(fields[0], "node") == 0 && nfields == 2) {
636
BLOCKNUM off = make_blocknum(getuint64(fields[1]));
637
dump_node(f, off, ft);
638
} else if (strcmp(fields[0], "dumpdata") == 0 && nfields == 2) {
639
dump_data = strtol(fields[1], NULL, 10);
640
} else if (strcmp(fields[0], "block_translation") == 0 || strcmp(fields[0], "bx") == 0) {
643
offset = getuint64(fields[1]);
644
dump_block_translation(ft, offset);
645
} else if (strcmp(fields[0], "fragmentation") == 0) {
646
dump_fragmentation(f, ft, tsv);
647
} else if (strcmp(fields[0], "nodesizes") == 0) {
648
dump_nodesizes(f, ft);
649
} else if (strcmp(fields[0], "garbage") == 0) {
650
dump_garbage_stats(f, ft);
651
} else if (strcmp(fields[0], "file") == 0 && nfields >= 3) {
652
uint64_t offset = getuint64(fields[1]);
653
uint64_t size = getuint64(fields[2]);
654
FILE *outfp = stdout;
656
outfp = fopen(fields[3], "w");
657
dump_file(f, offset, size, outfp);
658
} else if (strcmp(fields[0], "setfile") == 0 && nfields == 3) {
659
uint64_t offset = getuint64(fields[1]);
660
unsigned char newc = getuint64(fields[2]);
661
set_file(f, offset, newc);
662
} else if (strcmp(fields[0], "quit") == 0 || strcmp(fields[0], "q") == 0) {
666
} else if (rootnode) {
667
dump_node(f, ft->h->root_blocknum, ft);
668
} else if (fragmentation) {
669
dump_fragmentation(f, ft, tsv);
670
} else if (translation_table) {
671
toku_dump_translation_table_pretty(stdout, ft->blocktable);
660
r = toku_cachetable_openfd (&cf, ct, fd, fname);
664
open_header(fd, &ft, cf);
666
if (do_interactive) {
667
run_iteractive_loop(fd, ft, cf);
673
printf("Block translation:");
675
toku_dump_translation_table(stdout, ft->blocktable);
677
struct __dump_node_extra info;
680
toku_blocktable_iterate(ft->blocktable, TRANSLATION_CHECKPOINTED,
681
dump_node_wrapper, &info, true, true);
673
dump_node(fd, ft->h->root_blocknum, ft);
675
if (do_fragmentation) {
676
dump_fragmentation(fd, ft, do_tsv);
678
if (do_translation_table) {
679
toku_dump_translation_table_pretty(stdout, ft->blocktable);
682
dump_garbage_stats(fd, ft);
684
if (!do_header && !do_rootnode && !do_fragmentation && !do_translation_table && !do_garbage) {
685
printf("Block translation:");
687
toku_dump_translation_table(stdout, ft->blocktable);
689
struct __dump_node_extra info;
692
toku_blocktable_iterate(ft->blocktable, TRANSLATION_CHECKPOINTED,
693
dump_node_wrapper, &info, true, true);
683
696
toku_cachefile_close(&cf, false, ZERO_LSN);
684
697
toku_cachetable_close(&ct);