~ubuntu-branches/ubuntu/utopic/mariadb-5.5/utopic-security

« back to all changes in this revision

Viewing changes to storage/tokudb/ft-index/ft/tokuftdump.cc

  • Committer: Package Import Robot
  • Author(s): Otto Kekäläinen
  • Date: 2014-08-27 21:12:36 UTC
  • mfrom: (2.1.6 sid)
  • Revision ID: package-import@ubuntu.com-20140827211236-se41hwfe4xy0hpef
* d/control: Removed Provides: libmysqlclient-dev (Closes: #759309)
* d/control: Removed Provides: libmysqld-dev with same motivation
* Re-introduced tha HPPA build patch as the upstream fix wasn't complete
* Fixed all kFreeBSD build and test suite issues
* Added Italian translation (Closes: #759813)

Show diffs side-by-side

added added

removed removed

Lines of Context:
89
89
#ident "Copyright (c) 2007-2013 Tokutek Inc.  All rights reserved."
90
90
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
91
91
 
92
 
/* Tell me the diff between two FT files. */
 
92
// Dump a fractal tree file
93
93
 
94
94
#include "cachetable.h"
95
95
#include "ft.h"
102
102
#include <inttypes.h>
103
103
#include <limits.h>
104
104
 
105
 
static void
106
 
format_time(const uint64_t time_int, char *buf) {
 
105
static int do_dump_data = 1;
 
106
static int do_interactive = 0;
 
107
static int do_header = 0;
 
108
static int do_fragmentation = 0;
 
109
static int do_garbage = 0;
 
110
static int do_translation_table = 0;
 
111
static int do_rootnode = 0;
 
112
static int do_tsv = 0;
 
113
 
 
114
static const char *arg0;
 
115
static const char *fname;
 
116
 
 
117
static void format_time(const uint64_t time_int, char *buf) {
107
118
    time_t timer = (time_t) time_int;
108
119
    ctime_r(&timer, buf);
109
120
    assert(buf[24] == '\n');
110
121
    buf[24] = 0;
111
122
}
112
123
 
113
 
static int dump_data = 1;
114
 
 
115
 
static CACHETABLE ct;
116
 
 
117
 
static void
118
 
print_item (bytevec val, ITEMLEN len) {
 
124
static void print_item(bytevec val, ITEMLEN len) {
119
125
    printf("\"");
120
126
    ITEMLEN i;
121
127
    for (i=0; i<len; i++) {
129
135
    printf("\"");
130
136
}
131
137
 
132
 
static void
133
 
simple_hex_dump(unsigned char *vp, uint64_t size) {
 
138
static void simple_hex_dump(unsigned char *vp, uint64_t size) {
134
139
    for (uint64_t i = 0; i < size; i++) {
135
140
        unsigned char c = vp[i];
136
141
        printf("%2.2X", c);
137
142
    }
138
143
}
139
144
 
140
 
static void
141
 
hex_dump(unsigned char *vp, uint64_t offset, uint64_t size) {
 
145
static void hex_dump(unsigned char *vp, uint64_t offset, uint64_t size) {
142
146
    uint64_t n = size / 32;
143
147
    for (uint64_t i = 0; i < n; i++) {
144
148
        printf("%" PRIu64 ": ", offset);
169
173
    printf("\n");
170
174
}
171
175
 
172
 
static void
173
 
dump_descriptor(DESCRIPTOR d) {
 
176
static void dump_descriptor(DESCRIPTOR d) {
174
177
    printf(" descriptor size %u ", d->dbt.size);
175
178
    simple_hex_dump((unsigned char*) d->dbt.data, d->dbt.size);
176
179
    printf("\n");
177
180
}
178
181
 
179
 
static void
180
 
open_header (int f, FT *header, CACHEFILE cf) {
 
182
static void open_header(int fd, FT *header, CACHEFILE cf) {
181
183
    FT ft = NULL;
182
184
    int r;
183
 
    r = toku_deserialize_ft_from (f, MAX_LSN, &ft);
184
 
    assert(r==0);
 
185
    r = toku_deserialize_ft_from (fd, MAX_LSN, &ft);
 
186
    if (r != 0) {
 
187
        fprintf(stderr, "%s: can not deserialize from %s error %d\n", arg0, fname, r);
 
188
        exit(1);
 
189
    }
 
190
    assert_zero(r);
185
191
    ft->cf = cf;
186
192
    *header = ft;
187
193
}
188
194
 
189
 
static void
190
 
dump_header(FT ft) {
 
195
static void dump_header(FT ft) {
191
196
    char timestr[26];
192
197
    printf("ft:\n");
193
198
    printf(" layout_version=%d\n", ft->h->layout_version);
212
217
    printf(" estimated numbytes=%" PRId64 "\n", ft->in_memory_stats.numbytes);
213
218
}
214
219
 
215
 
static int
216
 
print_le(
217
 
    const void* key, 
218
 
    const uint32_t keylen, 
219
 
    const LEAFENTRY &le, 
220
 
    const uint32_t idx UU(), 
221
 
    void *const ai UU()
222
 
    ) 
223
 
{
 
220
static int print_le(const void* key, const uint32_t keylen, const LEAFENTRY &le, const uint32_t idx UU(), void *const ai UU()) {
224
221
    print_klpair(stdout, key, keylen, le);
225
222
    printf("\n");
226
223
    return 0;
227
224
}
228
225
 
229
 
 
230
 
static void
231
 
dump_node (int f, BLOCKNUM blocknum, FT h) {
 
226
static void dump_node(int fd, BLOCKNUM blocknum, FT h) {
232
227
    FTNODE n;
233
228
    struct ftnode_fetch_extra bfe;
234
229
    FTNODE_DISK_DATA ndd = NULL;
235
230
    fill_bfe_for_full_read(&bfe, h);
236
 
    int r = toku_deserialize_ftnode_from (f, blocknum, 0 /*pass zero for hash, it doesn't matter*/, &n, &ndd, &bfe);
237
 
    assert(r==0);
 
231
    int r = toku_deserialize_ftnode_from (fd, blocknum, 0 /*pass zero for hash, it doesn't matter*/, &n, &ndd, &bfe);
 
232
    assert_zero(r);
238
233
    assert(n!=0);
239
234
    printf("ftnode\n");
240
235
    DISKOFF disksize, diskoffset;
271
266
    }
272
267
    printf(" children:\n");
273
268
    for (int i=0; i<n->n_children; i++) {
 
269
            printf("  child %d: ", i);
274
270
        if (n->height > 0) {
275
 
            printf("   child %d: %" PRId64 "\n", i, BP_BLOCKNUM(n, i).b);
 
271
            printf("%" PRId64 "\n", BP_BLOCKNUM(n, i).b);
276
272
            NONLEAF_CHILDINFO bnc = BNC(n, i);
277
273
            unsigned int n_bytes = toku_bnc_nbytesinbuf(bnc); 
278
274
            int n_entries = toku_bnc_n_entries(bnc);
279
275
            if (n_bytes > 0 || n_entries > 0) {
280
276
                printf("   buffer contains %u bytes (%d items)\n", n_bytes, n_entries);
281
277
            }
282
 
            if (dump_data) {
 
278
            if (do_dump_data) {
283
279
                FIFO_ITERATE(bnc->buffer, key, keylen, data, datalen, typ, msn, xids, UU(is_fresh),
284
280
                             {
285
281
                                 printf("    msn=%" PRIu64 " (0x%" PRIx64 ") ", msn.msn, msn.msn);
316
312
        } else {
317
313
            printf(" n_bytes_in_buffer= %" PRIu64 "", BLB_DATA(n, i)->get_disk_size());
318
314
            printf(" items_in_buffer=%u\n", BLB_DATA(n, i)->num_klpairs());
319
 
            if (dump_data) {
 
315
            if (do_dump_data) {
320
316
                BLB_DATA(n, i)->iterate<void, print_le>(NULL);
321
317
            }
322
318
        }
325
321
    toku_free(ndd);
326
322
}
327
323
 
328
 
static void 
329
 
dump_block_translation(FT h, uint64_t offset) {
 
324
static void dump_block_translation(FT h, uint64_t offset) {
330
325
    toku_blocknum_dump_translation(h->blocktable, make_blocknum(offset));
331
326
}
332
327
 
333
 
static void
334
 
dump_fragmentation(int UU(f), FT h, int tsv) {
 
328
static void dump_fragmentation(int UU(f), FT h, int tsv) {
335
329
    int64_t used_space;
336
330
    int64_t total_space;
337
331
    toku_blocktable_internal_fragmentation(h->blocktable, &total_space, &used_space);
349
343
}
350
344
 
351
345
typedef struct {
352
 
    int f;
 
346
    int fd;
353
347
    FT h;
354
348
    uint64_t blocksizes;
355
349
    uint64_t leafsizes;
356
350
    uint64_t leafblocks;
357
351
} frag_help_extra;
358
352
 
359
 
static int
360
 
nodesizes_helper(BLOCKNUM b, int64_t size, int64_t UU(address), void *extra) {
 
353
static int nodesizes_helper(BLOCKNUM b, int64_t size, int64_t UU(address), void *extra) {
361
354
    frag_help_extra *CAST_FROM_VOIDP(info, extra);
362
355
    FTNODE n;
363
356
    FTNODE_DISK_DATA ndd = NULL;
364
357
    struct ftnode_fetch_extra bfe;
365
358
    fill_bfe_for_full_read(&bfe, info->h);
366
 
    int r = toku_deserialize_ftnode_from(info->f, b, 0 /*pass zero for hash, it doesn't matter*/, &n, &ndd, &bfe);
 
359
    int r = toku_deserialize_ftnode_from(info->fd, b, 0 /*pass zero for hash, it doesn't matter*/, &n, &ndd, &bfe);
367
360
    if (r==0) {
368
361
        info->blocksizes += size;
369
362
        if (n->height == 0) {
376
369
    return 0;
377
370
}
378
371
 
379
 
static void
380
 
dump_nodesizes(int f, FT h) {
 
372
static void dump_nodesizes(int fd, FT h) {
381
373
    frag_help_extra info;
382
374
    memset(&info, 0, sizeof(info));
383
 
    info.f = f;
 
375
    info.fd = fd;
384
376
    info.h = h;
385
377
    toku_blocktable_iterate(h->blocktable, TRANSLATION_CHECKPOINTED,
386
378
                            nodesizes_helper, &info, true, true);
389
381
    printf("leafsizes\t%" PRIu64 "\n", info.leafsizes);
390
382
}
391
383
 
392
 
static void
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);
400
 
}
401
 
 
402
 
static uint32_t 
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);
 
391
}
 
392
 
 
393
typedef struct __dump_node_extra {
 
394
    int fd;
 
395
    FT h;
 
396
} dump_node_extra;
 
397
 
 
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);
 
401
    return 0;
 
402
}
 
403
 
 
404
static uint32_t get_unaligned_uint32(unsigned char *p) {
 
405
    uint32_t n;
 
406
    memcpy(&n, p, sizeof n);
 
407
    return n;
405
408
}
406
409
 
407
410
struct dump_sub_block {
408
 
  uint32_t compressed_size;
409
 
  uint32_t uncompressed_size;
410
 
  uint32_t xsum;
 
411
    uint32_t compressed_size;
 
412
    uint32_t uncompressed_size;
 
413
    uint32_t xsum;
411
414
};
412
415
 
413
 
static void
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));
418
420
}
419
421
 
420
 
static void
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);
424
425
    
461
462
        printf("offset %u expected %" PRIu64 "\n", offset, size);
462
463
}
463
464
 
464
 
static void
465
 
dump_block(int f, BLOCKNUM blocknum, FT h) {
 
465
static void dump_block(int fd, BLOCKNUM blocknum, FT h) {
466
466
    DISKOFF offset, size;
467
467
    toku_translate_blocknum_to_offset_size(h->blocktable, blocknum, &offset, &size);
468
468
    printf("%" PRId64 " at %" PRId64 " size %" PRId64 "\n", blocknum.b, offset, size);
469
469
 
470
470
    unsigned char *CAST_FROM_VOIDP(vp, toku_malloc(size));
471
 
    uint64_t r = pread(f, vp, size, offset);
 
471
    uint64_t r = pread(fd, vp, size, offset);
472
472
    if (r == (uint64_t)size) {
473
473
        verify_block(vp, offset, size);
474
474
    }
475
475
    toku_free(vp);
476
476
}
477
477
 
478
 
static void
479
 
dump_file(int f, uint64_t offset, uint64_t size, FILE *outfp) {
 
478
static void dump_file(int fd, uint64_t offset, uint64_t size, FILE *outfp) {
480
479
    unsigned char *XMALLOC_N(size, vp);
481
 
    uint64_t r = pread(f, vp, size, offset);
 
480
    uint64_t r = pread(fd, vp, size, offset);
482
481
    if (r == size) {
483
482
        if (outfp == stdout) {
484
483
            hex_dump(vp, offset, size);
490
489
    toku_free(vp);
491
490
}
492
491
 
493
 
static void
494
 
set_file(int f, uint64_t offset, unsigned char newc) {
495
 
    toku_os_pwrite(f, &newc, sizeof newc, offset);
 
492
static void set_file(int fd, uint64_t offset, unsigned char newc) {
 
493
    toku_os_pwrite(fd, &newc, sizeof newc, offset);
496
494
}
497
495
 
498
 
static int
499
 
readline (char *line, int maxline) {
 
496
static int readline(char *line, int maxline) {
500
497
    int i = 0;
501
498
    int c;
502
499
    while ((c = getchar()) != EOF && c != '\n' && i < maxline) {
506
503
    return c == EOF ? EOF : i;
507
504
}
508
505
 
509
 
static int
510
 
split_fields (char *line, char *fields[], int maxfields) {
 
506
static int split_fields(char *line, char *fields[], int maxfields) {
511
507
    int i;
512
508
    for (i=0; i<maxfields; i++)
513
509
        fields[i] = NULL;
520
516
    return i;
521
517
}
522
518
 
523
 
static int
524
 
usage(const char *arg0) {
525
 
    printf("Usage: %s [--nodata] [--i[nteractive]|--fragmentation [--tsv]|--translation-table|--rootnode] ftfilename\n", arg0);
526
 
    return 1;
527
 
}
528
 
 
529
 
typedef struct __dump_node_extra {
530
 
    int f;
531
 
    FT h;
532
 
} dump_node_extra;
533
 
 
534
 
static int
535
 
dump_node_wrapper(BLOCKNUM b, int64_t UU(size), int64_t UU(address), void *extra) {
536
 
    dump_node_extra *CAST_FROM_VOIDP(info, extra);
537
 
    dump_node(info->f, b, info->h);
538
 
    return 0;
539
 
}
540
 
 
541
 
static void 
542
 
interactive_help(void) {
 
519
static uint64_t getuint64(const char *f) {
 
520
    if (strncmp(f, "0x", 2) == 0 || strncmp(f, "0X", 2) == 0)
 
521
        return strtoull(f, 0, 16);
 
522
    else if (strncmp(f, "0", 1) == 0)
 
523
        return strtoull(f, 0, 8);
 
524
    else
 
525
        return strtoull(f, 0, 10);
 
526
}
 
527
 
 
528
static void interactive_help(void) {
543
529
    fprintf(stderr, "help\n");
544
530
    fprintf(stderr, "header\n");
545
531
    fprintf(stderr, "node NUMBER\n");
552
538
    fprintf(stderr, "quit\n");
553
539
}
554
540
 
555
 
static uint64_t
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);
561
 
    else
562
 
        return strtoull(f, 0, 10);
563
 
}
564
 
 
565
 
int 
566
 
main (int argc, const char *const argv[]) {
567
 
    int interactive = 0;
568
 
    int fragmentation = 0;
569
 
    int translation_table = 0;
570
 
    int rootnode = 0;
571
 
    int tsv = 0;
572
 
 
573
 
    const char *arg0 = argv[0];
 
541
static void run_iteractive_loop(int fd, FT ft, CACHEFILE cf) {
 
542
    while (1) {
 
543
        printf("ftdump>"); fflush(stdout);
 
544
        enum { maxline = 64};
 
545
        char line[maxline+1];
 
546
        int r = readline(line, maxline);
 
547
        if (r == EOF)
 
548
            break;
 
549
        const int maxfields = 4;
 
550
        char *fields[maxfields];
 
551
        int nfields = split_fields(line, fields, maxfields);
 
552
        if (nfields == 0) 
 
553
            continue;
 
554
        if (strcmp(fields[0], "help") == 0) {
 
555
            interactive_help();
 
556
        } else if (strcmp(fields[0], "header") == 0) {
 
557
            toku_ft_free(ft);
 
558
            open_header(fd, &ft, cf);
 
559
            dump_header(ft);
 
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) {
 
569
            uint64_t offset = 0;
 
570
            if (nfields == 2)
 
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;
 
583
            if (nfields >= 4)
 
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) {
 
591
            break;
 
592
        }
 
593
    }
 
594
}
 
595
 
 
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");
 
609
    return 1;
 
610
}
 
611
 
 
612
int main (int argc, const char *const argv[]) {
 
613
    arg0 = argv[0];
574
614
    argc--; argv++;
575
615
    while (argc>0) {
576
 
        if (strcmp(argv[0], "--nodata") == 0) {
577
 
            dump_data = 0;
578
 
        } else if (strcmp(argv[0], "--interactive") == 0 || strcmp(argv[0], "--i") == 0) {
579
 
            interactive = 1;
 
616
        if (strcmp(argv[0], "--interactive") == 0 || strcmp(argv[0], "--i") == 0) {
 
617
            do_interactive = 1;
 
618
        } else if (strcmp(argv[0], "--nodata") == 0) {
 
619
            do_dump_data = 0;
 
620
        } else if (strcmp(argv[0], "--dumpdata") == 0 && argc > 1) {
 
621
            argc--; argv++;
 
622
            do_dump_data = atoi(argv[0]);
 
623
        } else if (strcmp(argv[0], "--header") == 0) {
 
624
            do_header = 1;
 
625
        } else if (strcmp(argv[0], "--rootnode") == 0) {
 
626
            do_rootnode = 1;
580
627
        } else if (strcmp(argv[0], "--fragmentation") == 0) {
581
 
            fragmentation = 1;
 
628
            do_fragmentation = 1;
 
629
        } else if (strcmp(argv[0], "--garbage") == 0) {
 
630
            do_garbage = 1;
582
631
        } else if (strcmp(argv[0], "--tsv") == 0) {
583
 
            tsv = 1;
 
632
            do_tsv = 1;
584
633
        } else if (strcmp(argv[0], "--translation-table") == 0) {
585
 
            translation_table = 1;
586
 
        } else if (strcmp(argv[0], "--rootnode") == 0) {
587
 
            rootnode = 1;
588
 
        } else if (strcmp(argv[0], "--help") == 0) {
589
 
            return usage(arg0);
 
634
            do_translation_table = 1;
 
635
        } else if (strcmp(argv[0], "--help") == 0 || strcmp(argv[0], "-?") == 0 || strcmp(argv[0], "-h") == 0) {
 
636
            return usage();
590
637
        } else {
591
638
            break;
592
639
        }
593
640
        argc--; argv++;
594
641
    }
595
 
    if (argc != 1) return usage(arg0);
 
642
    if (argc != 1) 
 
643
        return usage();
596
644
 
597
645
    int r = toku_ft_layer_init();
598
 
    invariant_zero(r);
599
 
 
600
 
    const char *n = argv[0];
601
 
    int f = open(n, O_RDWR + O_BINARY);  assert(f>=0);
602
 
    FT ft;
 
646
    assert_zero(r);
 
647
 
 
648
    fname = argv[0];
 
649
    int fd = open(fname, O_RDWR + O_BINARY);
 
650
    if (fd < 0) {
 
651
        fprintf(stderr, "%s: can not open %s errno %d\n", arg0, fname, errno);
 
652
        return 1;
 
653
    }
 
654
 
603
655
    // create a cachefile for the header
 
656
    CACHETABLE ct = NULL;
604
657
    toku_cachetable_create(&ct, 1<<25, (LSN){0}, 0);
 
658
 
605
659
    CACHEFILE cf = NULL;
606
 
    r = toku_cachetable_openfd (&cf, ct, f, n);
607
 
    assert(r==0);
608
 
    open_header(f, &ft, cf);
609
 
    if (!fragmentation && !translation_table) {
610
 
        // quick fix for now, we want those two to have clean output
611
 
        dump_header(ft);
612
 
    }
613
 
    if (interactive) {
614
 
        while (1) {
615
 
            printf("ftdump>"); fflush(stdout);
616
 
            enum { maxline = 64};
617
 
            char line[maxline+1];
618
 
            r = readline(line, maxline);
619
 
            if (r == EOF)
620
 
                break;
621
 
            const int maxfields = 4;
622
 
            char *fields[maxfields];
623
 
            int nfields = split_fields(line, fields, maxfields);
624
 
            if (nfields == 0) 
625
 
                continue;
626
 
            if (strcmp(fields[0], "help") == 0) {
627
 
                interactive_help();
628
 
            } else if (strcmp(fields[0], "header") == 0) {
629
 
                toku_ft_free(ft);
630
 
                open_header(f, &ft, cf);
631
 
                dump_header(ft);
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) {
641
 
                uint64_t offset = 0;
642
 
                if (nfields == 2)
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;
655
 
                if (nfields >= 4)
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) {
663
 
                break;
664
 
            }
665
 
        }
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);
 
661
    assert_zero(r);
 
662
 
 
663
    FT ft = NULL;
 
664
    open_header(fd, &ft, cf);
 
665
 
 
666
    if (do_interactive) {
 
667
        run_iteractive_loop(fd, ft, cf);
672
668
    } else {
673
 
        printf("Block translation:");
674
 
 
675
 
        toku_dump_translation_table(stdout, ft->blocktable);
676
 
 
677
 
        struct __dump_node_extra info;
678
 
        info.f = f;
679
 
        info.h = ft;
680
 
        toku_blocktable_iterate(ft->blocktable, TRANSLATION_CHECKPOINTED,
681
 
                                dump_node_wrapper, &info, true, true);
 
669
        if (do_header) {
 
670
            dump_header(ft);
 
671
        }
 
672
        if (do_rootnode) {
 
673
            dump_node(fd, ft->h->root_blocknum, ft);
 
674
        } 
 
675
        if (do_fragmentation) {
 
676
            dump_fragmentation(fd, ft, do_tsv);
 
677
        }
 
678
        if (do_translation_table) {
 
679
            toku_dump_translation_table_pretty(stdout, ft->blocktable);
 
680
        }
 
681
        if (do_garbage) {
 
682
            dump_garbage_stats(fd, ft);
 
683
        }
 
684
        if (!do_header && !do_rootnode && !do_fragmentation && !do_translation_table && !do_garbage) {
 
685
            printf("Block translation:");
 
686
            
 
687
            toku_dump_translation_table(stdout, ft->blocktable);
 
688
            
 
689
            struct __dump_node_extra info;
 
690
            info.fd = fd;
 
691
            info.h = ft;
 
692
            toku_blocktable_iterate(ft->blocktable, TRANSLATION_CHECKPOINTED,
 
693
                                    dump_node_wrapper, &info, true, true);
 
694
        }
682
695
    }
683
696
    toku_cachefile_close(&cf, false, ZERO_LSN);
684
697
    toku_cachetable_close(&ct);