YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/rocksdb/tools/sst_dump_tool.cc
Line
Count
Source (jump to first uncovered line)
1
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2
//  This source code is licensed under the BSD-style license found in the
3
//  LICENSE file in the root directory of this source tree. An additional grant
4
//  of patent rights can be found in the PATENTS file in the same directory.
5
//
6
// The following only applies to changes made to this file as part of YugaByte development.
7
//
8
// Portions Copyright (c) YugaByte, Inc.
9
//
10
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
11
// in compliance with the License.  You may obtain a copy of the License at
12
//
13
// http://www.apache.org/licenses/LICENSE-2.0
14
//
15
// Unless required by applicable law or agreed to in writing, software distributed under the License
16
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
17
// or implied.  See the License for the specific language governing permissions and limitations
18
// under the License.
19
//
20
#ifndef ROCKSDB_LITE
21
22
#include "yb/rocksdb/tools/sst_dump_tool_imp.h"
23
24
#ifndef __STDC_FORMAT_MACROS
25
#define __STDC_FORMAT_MACROS
26
#endif
27
28
#include <inttypes.h>
29
#include <map>
30
#include <sstream>
31
#include <vector>
32
33
#include "yb/rocksdb/db/filename.h"
34
#include "yb/rocksdb/db/memtable.h"
35
#include "yb/rocksdb/db/write_batch_internal.h"
36
#include "yb/rocksdb/db.h"
37
#include "yb/rocksdb/env.h"
38
#include "yb/rocksdb/immutable_options.h"
39
#include "yb/rocksdb/iterator.h"
40
#include "yb/rocksdb/slice_transform.h"
41
#include "yb/rocksdb/status.h"
42
#include "yb/rocksdb/table_properties.h"
43
#include "yb/rocksdb/table/block.h"
44
#include "yb/rocksdb/table/block_based_table_builder.h"
45
#include "yb/rocksdb/table/block_based_table_factory.h"
46
#include "yb/rocksdb/table/block_builder.h"
47
#include "yb/rocksdb/table/format.h"
48
#include "yb/rocksdb/table/meta_blocks.h"
49
#include "yb/rocksdb/table/plain_table_factory.h"
50
#include "yb/rocksdb/tools/ldb_cmd.h"
51
#include "yb/rocksdb/util/random.h"
52
53
#include "yb/rocksdb/port/port.h"
54
55
#include "yb/docdb/docdb_debug.h"
56
57
#include "yb/util/status_log.h"
58
59
using yb::docdb::StorageDbType;
60
61
namespace rocksdb {
62
63
using std::dynamic_pointer_cast;
64
65
std::string DocDBKVFormatter::Format(
66
0
    const yb::Slice&, const yb::Slice&, yb::docdb::StorageDbType) const {
67
0
  CHECK(false) << "unimplemented";
68
0
  return "";
69
0
}
70
71
SstFileReader::SstFileReader(
72
    const std::string& file_path, bool verify_checksum, OutputFormat output_format,
73
    const DocDBKVFormatter* formatter)
74
    : file_name_(file_path),
75
      read_num_(0),
76
      verify_checksum_(verify_checksum),
77
      output_format_(output_format),
78
      docdb_kv_formatter_(formatter),
79
      ioptions_(options_),
80
5
      internal_comparator_(std::make_shared<InternalKeyComparator>(BytewiseComparator())) {
81
5
  fprintf(stdout, "Process %s\n", file_path.c_str());
82
5
  init_result_ = GetTableReader(file_name_);
83
5
}
84
85
5
SstFileReader::~SstFileReader() {
86
5
}
87
88
extern const uint64_t kBlockBasedTableMagicNumber;
89
extern const uint64_t kLegacyBlockBasedTableMagicNumber;
90
extern const uint64_t kPlainTableMagicNumber;
91
extern const uint64_t kLegacyPlainTableMagicNumber;
92
93
const char* testFileName = "test_file_name";
94
95
5
Status SstFileReader::GetTableReader(const std::string& file_path) {
96
5
  uint64_t magic_number;
97
98
  // read table magic number
99
5
  Footer footer;
100
101
5
  unique_ptr<RandomAccessFile> file;
102
5
  uint64_t file_size;
103
5
  Status s = options_.env->NewRandomAccessFile(file_path, &file, soptions_);
104
5
  if (s.ok()) {
105
5
    s = options_.env->GetFileSize(file_path, &file_size);
106
5
  }
107
108
5
  file_.reset(new RandomAccessFileReader(std::move(file)));
109
110
5
  if (s.ok()) {
111
5
    s = ReadFooterFromFile(file_.get(), file_size, &footer);
112
5
  }
113
5
  if (s.ok()) {
114
5
    magic_number = footer.table_magic_number();
115
5
  }
116
117
5
  if (s.ok()) {
118
5
    if (magic_number == kPlainTableMagicNumber ||
119
5
        magic_number == kLegacyPlainTableMagicNumber) {
120
0
      soptions_.use_mmap_reads = true;
121
0
      RETURN_NOT_OK(options_.env->NewRandomAccessFile(file_path, &file, soptions_));
122
0
      file_.reset(new RandomAccessFileReader(std::move(file)));
123
0
    }
124
5
    options_.comparator = internal_comparator_.get();
125
    // For old sst format, ReadTableProperties might fail but file can be read
126
5
    if (ReadTableProperties(magic_number, file_.get(), file_size).ok()) {
127
5
      RETURN_NOT_OK(SetTableOptionsByMagicNumber(magic_number));
128
0
    } else {
129
0
      RETURN_NOT_OK(SetOldTableOptions());
130
0
    }
131
5
  }
132
133
5
  if (s.ok()) {
134
5
    s = NewTableReader(ioptions_, soptions_, *internal_comparator_, file_size,
135
5
                       &table_reader_);
136
5
    if (s.ok() && table_reader_->IsSplitSst()) {
137
5
      unique_ptr<RandomAccessFile> data_file;
138
5
      RETURN_NOT_OK(options_.env->NewRandomAccessFile(
139
5
          TableBaseToDataFileName(file_path), &data_file, soptions_));
140
5
      unique_ptr<RandomAccessFileReader> data_file_reader(
141
5
          new RandomAccessFileReader(std::move(data_file)));
142
5
      table_reader_->SetDataFileReader(std::move(data_file_reader));
143
5
    }
144
5
  }
145
5
  return s;
146
5
}
147
148
Status SstFileReader::NewTableReader(
149
    const ImmutableCFOptions& ioptions, const EnvOptions& soptions,
150
    const InternalKeyComparator& internal_comparator, uint64_t file_size,
151
5
    unique_ptr<TableReader>* table_reader) {
152
  // We need to turn off pre-fetching of index and filter nodes for
153
  // BlockBasedTable
154
5
  shared_ptr<BlockBasedTableFactory> block_table_factory =
155
5
      dynamic_pointer_cast<BlockBasedTableFactory>(options_.table_factory);
156
157
5
  if (block_table_factory) {
158
5
    return block_table_factory->NewTableReader(
159
5
        TableReaderOptions(ioptions_, soptions_, internal_comparator_,
160
5
                           /*skip_filters=*/false),
161
5
        std::move(file_), file_size, &table_reader_, DataIndexLoadMode::USE_CACHE,
162
5
        PrefetchFilter::NO);
163
5
  }
164
165
0
  assert(!block_table_factory);
166
167
  // For all other factory implementation
168
0
  return options_.table_factory->NewTableReader(
169
0
      TableReaderOptions(ioptions_, soptions_, internal_comparator_),
170
0
      std::move(file_), file_size, &table_reader_);
171
0
}
172
173
3
Status SstFileReader::DumpTable(const std::string& out_filename) {
174
3
  unique_ptr<WritableFile> out_file;
175
3
  Env* env = Env::Default();
176
3
  RETURN_NOT_OK(env->NewWritableFile(out_filename, &out_file, soptions_));
177
3
  Status s = table_reader_->DumpTable(out_file.get());
178
3
  RETURN_NOT_OK(out_file->Close());
179
3
  return s;
180
3
}
181
182
uint64_t SstFileReader::CalculateCompressedTableSize(
183
7
    const TableBuilderOptions& tb_options, size_t block_size) {
184
7
  unique_ptr<WritableFile> out_file;
185
7
  unique_ptr<Env> env(NewMemEnv(Env::Default()));
186
7
  CHECK_OK(env->NewWritableFile(testFileName, &out_file, soptions_));
187
7
  unique_ptr<WritableFileWriter> dest_writer;
188
7
  dest_writer.reset(new WritableFileWriter(std::move(out_file), soptions_));
189
7
  BlockBasedTableOptions table_options;
190
7
  table_options.block_size = block_size;
191
7
  BlockBasedTableFactory block_based_tf(table_options);
192
7
  unique_ptr<TableBuilder> table_builder;
193
7
  table_builder.reset(block_based_tf.NewTableBuilder(
194
7
      tb_options,
195
7
      TablePropertiesCollectorFactory::Context::kUnknownColumnFamily,
196
7
      dest_writer.get()));
197
7
  unique_ptr<InternalIterator> iter(table_reader_->NewIterator(ReadOptions()));
198
7.17k
  for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
199
7.16k
    if (!iter->status().ok()) {
200
0
      fputs(iter->status().ToString().c_str(), stderr);
201
0
      exit(1);
202
0
    }
203
7.16k
    table_builder->Add(iter->key(), iter->value());
204
7.16k
  }
205
7
  Status s = table_builder->Finish();
206
7
  if (!s.ok()) {
207
0
    fputs(s.ToString().c_str(), stderr);
208
0
    exit(1);
209
0
  }
210
7
  uint64_t size = table_builder->TotalFileSize();
211
7
  CHECK_OK(env->DeleteFile(testFileName));
212
7
  return size;
213
7
}
214
215
1
int SstFileReader::ShowAllCompressionSizes(size_t block_size) {
216
1
  ReadOptions read_options;
217
1
  Options opts;
218
1
  const ImmutableCFOptions imoptions(opts);
219
1
  auto ikc = std::make_shared<rocksdb::InternalKeyComparator>(opts.comparator);
220
1
  std::vector<std::unique_ptr<IntTblPropCollectorFactory> >
221
1
      block_based_table_factories;
222
223
1
  std::map<CompressionType, const char*> compress_type;
224
1
  compress_type.insert(
225
1
      std::make_pair(CompressionType::kNoCompression, "kNoCompression"));
226
1
  compress_type.insert(std::make_pair(CompressionType::kSnappyCompression,
227
1
                                      "kSnappyCompression"));
228
1
  compress_type.insert(
229
1
      std::make_pair(CompressionType::kZlibCompression, "kZlibCompression"));
230
1
  compress_type.insert(
231
1
      std::make_pair(CompressionType::kBZip2Compression, "kBZip2Compression"));
232
1
  compress_type.insert(
233
1
      std::make_pair(CompressionType::kLZ4Compression, "kLZ4Compression"));
234
1
  compress_type.insert(
235
1
      std::make_pair(CompressionType::kLZ4HCCompression, "kLZ4HCCompression"));
236
1
  compress_type.insert(std::make_pair(CompressionType::kZSTDNotFinalCompression,
237
1
                                      "kZSTDNotFinalCompression"));
238
239
1
  fprintf(stdout, "Block Size: %" ROCKSDB_PRIszt "\n", block_size);
240
241
1
  for (CompressionType i = CompressionType::kNoCompression;
242
8
       i <= CompressionType::kZSTDNotFinalCompression;
243
7
       i = (i == kLZ4HCCompression) ? kZSTDNotFinalCompression
244
7
                                    : CompressionType(i + 1)) {
245
7
    CompressionOptions compress_opt;
246
7
    TableBuilderOptions tb_opts(imoptions,
247
7
                                ikc,
248
7
                                block_based_table_factories,
249
7
                                i,
250
7
                                compress_opt,
251
7
                                false);
252
7
    uint64_t file_size = CalculateCompressedTableSize(tb_opts, block_size);
253
7
    fprintf(stdout, "Compression: %s", compress_type.find(i)->second);
254
7
    fprintf(stdout, " Size: %" PRIu64 "\n", file_size);
255
7
  }
256
1
  return 0;
257
1
}
258
259
Status SstFileReader::ReadTableProperties(uint64_t table_magic_number,
260
                                          RandomAccessFileReader* file,
261
5
                                          uint64_t file_size) {
262
5
  TableProperties* table_properties = nullptr;
263
5
  Status s = rocksdb::ReadTableProperties(file, file_size, table_magic_number,
264
5
                                          options_.env, options_.info_log.get(),
265
5
                                          &table_properties);
266
5
  if (s.ok()) {
267
5
    table_properties_.reset(table_properties);
268
0
  } else {
269
0
    fprintf(stdout, "Not able to read table properties\n");
270
0
  }
271
5
  return s;
272
5
}
273
274
Status SstFileReader::SetTableOptionsByMagicNumber(
275
5
    uint64_t table_magic_number) {
276
5
  assert(table_properties_);
277
5
  if (table_magic_number == kBlockBasedTableMagicNumber ||
278
5
      table_magic_number == kLegacyBlockBasedTableMagicNumber) {
279
5
    options_.table_factory = std::make_shared<BlockBasedTableFactory>();
280
5
    fprintf(stdout, "Sst file format: block-based\n");
281
5
    auto& props = table_properties_->user_collected_properties;
282
5
    auto pos = props.find(BlockBasedTablePropertyNames::kIndexType);
283
5
    if (pos != props.end()) {
284
5
      auto index_type_on_file = static_cast<IndexType>(DecodeFixed32(pos->second.c_str()));
285
5
      if (index_type_on_file == IndexType::kHashSearch) {
286
0
        options_.prefix_extractor.reset(NewNoopTransform());
287
0
      }
288
5
    }
289
0
  } else if (table_magic_number == kPlainTableMagicNumber ||
290
0
             table_magic_number == kLegacyPlainTableMagicNumber) {
291
0
    options_.allow_mmap_reads = true;
292
293
0
    PlainTableOptions plain_table_options;
294
0
    plain_table_options.user_key_len = kPlainTableVariableLength;
295
0
    plain_table_options.bloom_bits_per_key = 0;
296
0
    plain_table_options.hash_table_ratio = 0;
297
0
    plain_table_options.index_sparseness = 1;
298
0
    plain_table_options.huge_page_tlb_size = 0;
299
0
    plain_table_options.encoding_type = kPlain;
300
0
    plain_table_options.full_scan_mode = true;
301
302
0
    options_.table_factory.reset(NewPlainTableFactory(plain_table_options));
303
0
    fprintf(stdout, "Sst file format: plain table\n");
304
0
  } else {
305
0
    char error_msg_buffer[80];
306
0
    snprintf(error_msg_buffer, sizeof(error_msg_buffer) - 1,
307
0
             "Unsupported table magic number --- %" PRIx64, table_magic_number);
308
0
    return STATUS(InvalidArgument, error_msg_buffer);
309
0
  }
310
311
5
  return Status::OK();
312
5
}
313
314
0
Status SstFileReader::SetOldTableOptions() {
315
0
  assert(table_properties_ == nullptr);
316
0
  options_.table_factory = std::make_shared<BlockBasedTableFactory>();
317
0
  fprintf(stdout, "Sst file format: block-based(old version)\n");
318
319
0
  return Status::OK();
320
0
}
321
322
Status SstFileReader::ReadSequential(bool print_kv,
323
                                     uint64_t read_num,
324
                                     bool has_from,
325
                                     const std::string& from_key,
326
                                     bool has_to,
327
1
                                     const std::string& to_key) {
328
1
  if (!table_reader_) {
329
0
    return init_result_;
330
0
  }
331
332
1
  InternalIterator* iter =
333
1
      table_reader_->NewIterator(ReadOptions(verify_checksum_, false));
334
1
  uint64_t i = 0;
335
1
  if (has_from) {
336
0
    InternalKey ikey = InternalKey::MaxPossibleForUserKey(from_key);
337
0
    iter->Seek(ikey.Encode());
338
1
  } else {
339
1
    iter->SeekToFirst();
340
1
  }
341
1.02k
  for (; iter->Valid(); iter->Next()) {
342
1.02k
    Slice key = iter->key();
343
1.02k
    Slice value = iter->value();
344
1.02k
    ++i;
345
1.02k
    if (read_num > 0 && i > read_num)
346
0
      break;
347
348
1.02k
    ParsedInternalKey ikey;
349
1.02k
    if (!ParseInternalKey(key, &ikey)) {
350
0
      std::cerr << "Internal Key ["
351
0
                << key.ToString(true /* in hex*/)
352
0
                << "] parse error!\n";
353
0
      continue;
354
0
    }
355
356
    // If end marker was specified, we stop before it
357
1.02k
    if (has_to && BytewiseComparator()->Compare(ikey.user_key, to_key) >= 0) {
358
0
      break;
359
0
    }
360
361
1.02k
    if (print_kv) {
362
0
      switch (output_format_) {
363
0
        case OutputFormat::kRaw:
364
0
        case OutputFormat::kHex: {
365
0
          bool output_hex = (output_format_ == OutputFormat::kHex);
366
0
          fprintf(
367
0
              stdout, "%s => %s\n", ikey.DebugString(output_hex).c_str(),
368
0
              value.ToString(output_hex).c_str());
369
0
          break;
370
0
        }
371
0
        case OutputFormat::kDecodedRegularDB:
372
0
        case OutputFormat::kDecodedIntentsDB:
373
0
          auto storage_type =
374
0
              (output_format_ == OutputFormat::kDecodedRegularDB ? StorageDbType::kRegular
375
0
                                                                 : StorageDbType::kIntents);
376
0
          fprintf(stdout, "%s", docdb_kv_formatter_->Format(key, value, storage_type).c_str());
377
0
          break;
378
0
      }
379
0
    }
380
1.02k
  }
381
382
1
  read_num_ += i;
383
384
1
  Status ret = iter->status();
385
1
  delete iter;
386
1
  return ret;
387
1
}
388
389
Status SstFileReader::ReadTableProperties(
390
1
    std::shared_ptr<const TableProperties>* table_properties) {
391
1
  if (!table_reader_) {
392
0
    return init_result_;
393
0
  }
394
395
1
  *table_properties = table_reader_->GetTableProperties();
396
1
  return init_result_;
397
1
}
398
399
namespace {
400
401
0
void print_help() {
402
0
  fprintf(stderr,
403
0
          "sst_dump [--command=check|scan|none|raw] [--verify_checksum] "
404
0
          "--file=data_dir_OR_sst_file"
405
0
          " [--output_format=raw|hex|decoded_regulardb|decoded_intentsdb]"
406
0
          " [--input_key_hex]"
407
0
          " [--from=<user_key>]"
408
0
          " [--to=<user_key>]"
409
0
          " [--read_num=NUM]"
410
0
          " [--show_properties]"
411
0
          " [--show_compression_sizes]"
412
0
          " [--show_compression_sizes [--set_block_size=<block_size>]]\n");
413
0
}
414
415
}  // namespace
416
417
5
int SSTDumpTool::Run(int argc, char** argv) {
418
5
  const char* dir_or_file = nullptr;
419
5
  uint64_t read_num = -1;
420
5
  std::string command;
421
422
5
  char junk;
423
5
  uint64_t n;
424
5
  bool verify_checksum = false;
425
5
  OutputFormat output_format = OutputFormat::kRaw;
426
5
  bool input_key_hex = false;
427
5
  bool has_from = false;
428
5
  bool has_to = false;
429
5
  bool show_properties = false;
430
5
  bool show_compression_sizes = false;
431
5
  bool set_block_size = false;
432
5
  std::string from_key;
433
5
  std::string to_key;
434
5
  std::string block_size_str;
435
5
  size_t block_size;
436
15
  for (int i = 1; i < argc; i++) {
437
10
    if (strncmp(argv[i], "--file=", 7) == 0) {
438
5
      dir_or_file = argv[i] + 7;
439
5
    } else if (strncmp(argv[i], "--output_format=", 16) == 0) {
440
0
      auto option = argv[i] + 16;
441
0
      if (strcmp(option, "raw") == 0) {
442
0
        output_format = OutputFormat::kRaw;
443
0
      } else if (strcmp(option, "hex") == 0) {
444
0
        output_format = OutputFormat::kHex;
445
0
      } else if (strcmp(option, "decoded_regulardb") == 0) {
446
0
        output_format = OutputFormat::kDecodedRegularDB;
447
0
      } else if (strcmp(option, "decoded_intentsdb") == 0) {
448
0
        output_format = OutputFormat::kDecodedIntentsDB;
449
0
      } else {
450
0
        print_help();
451
0
        exit(1);
452
0
      }
453
5
    } else if (strcmp(argv[i], "--input_key_hex") == 0) {
454
0
      input_key_hex = true;
455
5
    } else if (sscanf(argv[i], "--read_num=%" PRIu64 "%c", &n, &junk) == 1) {
456
0
      read_num = n;
457
5
    } else if (strcmp(argv[i], "--verify_checksum") == 0) {
458
0
      verify_checksum = true;
459
5
    } else if (strncmp(argv[i], "--command=", 10) == 0) {
460
3
      command = argv[i] + 10;
461
2
    } else if (strncmp(argv[i], "--from=", 7) == 0) {
462
0
      from_key = argv[i] + 7;
463
0
      has_from = true;
464
2
    } else if (strncmp(argv[i], "--to=", 5) == 0) {
465
0
      to_key = argv[i] + 5;
466
0
      has_to = true;
467
2
    } else if (strcmp(argv[i], "--show_properties") == 0) {
468
1
      show_properties = true;
469
1
    } else if (strcmp(argv[i], "--show_compression_sizes") == 0) {
470
1
      show_compression_sizes = true;
471
0
    } else if (strncmp(argv[i], "--set_block_size=", 17) == 0) {
472
0
      set_block_size = true;
473
0
      block_size_str = argv[i] + 17;
474
0
      std::istringstream iss(block_size_str);
475
0
      if (iss.fail()) {
476
0
        fprintf(stderr, "block size must be numeric");
477
0
        exit(1);
478
0
      }
479
0
      iss >> block_size;
480
0
    } else {
481
0
      print_help();
482
0
      exit(1);
483
0
    }
484
10
  }
485
486
5
  if (input_key_hex) {
487
0
    if (has_from) {
488
0
      from_key = rocksdb::LDBCommand::HexToString(from_key);
489
0
    }
490
0
    if (has_to) {
491
0
      to_key = rocksdb::LDBCommand::HexToString(to_key);
492
0
    }
493
0
  }
494
495
5
  if (dir_or_file == nullptr) {
496
0
    print_help();
497
0
    exit(1);
498
0
  }
499
500
5
  std::vector<std::string> filenames;
501
5
  rocksdb::Env* env = rocksdb::Env::Default();
502
5
  rocksdb::Status st = env->GetChildren(dir_or_file, &filenames);
503
5
  bool dir = true;
504
5
  if (!st.ok()) {
505
5
    filenames.clear();
506
5
    filenames.push_back(dir_or_file);
507
5
    dir = false;
508
5
  }
509
510
5
  fprintf(stdout, "from [%s] to [%s]\n",
511
5
      rocksdb::Slice(from_key).ToString(true).c_str(),
512
5
      rocksdb::Slice(to_key).ToString(true).c_str());
513
514
5
  uint64_t total_read = 0;
515
9
  for (size_t i = 0; i < filenames.size(); i++) {
516
5
    std::string filename = filenames.at(i);
517
5
    if (filename.length() <= 4 ||
518
5
        filename.rfind(".sst") != filename.length() - 4) {
519
      // ignore
520
0
      continue;
521
0
    }
522
5
    if (dir) {
523
0
      filename = std::string(dir_or_file) + "/" + filename;
524
0
    }
525
526
5
    rocksdb::SstFileReader reader(filename, verify_checksum, output_format, formatter_);
527
5
    if (!reader.getStatus().ok()) {
528
0
      fprintf(stderr, "%s: %s\n", filename.c_str(),
529
0
              reader.getStatus().ToString().c_str());
530
0
      exit(1);
531
0
    }
532
533
5
    if (show_compression_sizes) {
534
1
      if (set_block_size) {
535
0
        reader.ShowAllCompressionSizes(block_size);
536
1
      } else {
537
1
        reader.ShowAllCompressionSizes(16384);
538
1
      }
539
1
      return 0;
540
1
    }
541
542
4
    if (command == "raw") {
543
3
      std::string out_filename = filename.substr(0, filename.length() - 4);
544
3
      out_filename.append("_dump.txt");
545
546
3
      st = reader.DumpTable(out_filename);
547
3
      if (!st.ok()) {
548
0
        fprintf(stderr, "%s: %s\n", filename.c_str(), st.ToString().c_str());
549
0
        exit(1);
550
3
      } else {
551
3
        fprintf(stdout, "raw dump written to file %s\n", &out_filename[0]);
552
3
      }
553
3
      continue;
554
1
    }
555
556
    // scan all files in give file path.
557
1
    if (command == "" || command == "scan" || command == "check") {
558
1
      st = reader.ReadSequential(command == "scan",
559
1
                                 read_num > 0 ? (read_num - total_read) :
560
0
                                                read_num,
561
1
                                 has_from, from_key, has_to, to_key);
562
1
      if (!st.ok()) {
563
0
        fprintf(stderr, "%s: %s\n", filename.c_str(),
564
0
            st.ToString().c_str());
565
0
      }
566
1
      total_read += reader.GetReadNumber();
567
1
      if (read_num > 0 && total_read > read_num) {
568
0
        break;
569
0
      }
570
1
    }
571
1
    if (show_properties) {
572
1
      const rocksdb::TableProperties* table_properties;
573
574
1
      std::shared_ptr<const rocksdb::TableProperties>
575
1
          table_properties_from_reader;
576
1
      st = reader.ReadTableProperties(&table_properties_from_reader);
577
1
      if (!st.ok()) {
578
0
        fprintf(stderr, "%s: %s\n", filename.c_str(), st.ToString().c_str());
579
0
        fprintf(stderr, "Try to use initial table properties\n");
580
0
        table_properties = reader.GetInitTableProperties();
581
1
      } else {
582
1
        table_properties = table_properties_from_reader.get();
583
1
      }
584
1
      if (table_properties != nullptr) {
585
1
        fprintf(stdout,
586
1
                "Table Properties:\n"
587
1
                "------------------------------\n"
588
1
                "  %s",
589
1
                table_properties->ToString("\n  ", ": ").c_str());
590
1
        fprintf(stdout, "# deleted keys: %" PRIu64 "\n",
591
1
                rocksdb::GetDeletedKeys(
592
1
                    table_properties->user_collected_properties));
593
1
        fprintf(stdout,
594
1
                "  User collected properties:\n"
595
1
                "  ------------------------------\n");
596
5
        for (const auto& prop : table_properties->user_collected_properties) {
597
5
          fprintf(
598
5
              stdout, "  %s: %s\n", prop.first.c_str(), Slice(prop.second).ToDebugString().c_str());
599
5
        }
600
1
      }
601
1
    }
602
1
  }
603
4
  return 0;
604
5
}
605
}  // namespace rocksdb
606
607
#endif  // ROCKSDB_LITE