53
53
54
54
#include " yb/docdb/docdb_debug.h"
55
55
56
+ #include " yb/util/format.h"
56
57
#include " yb/util/status_log.h"
57
58
58
59
using yb::docdb::StorageDbType;
59
60
60
61
namespace rocksdb {
61
62
62
63
using std::dynamic_pointer_cast;
63
- using std::unique_ptr;
64
- using std::shared_ptr;
65
64
66
65
std::string DocDBKVFormatter::Format (
67
66
const yb::Slice&, const yb::Slice&, yb::docdb::StorageDbType) const {
@@ -97,9 +96,7 @@ Status SstFileReader::GetTableReader(const std::string& file_path) {
97
96
uint64_t magic_number;
98
97
99
98
// read table magic number
100
- Footer footer;
101
-
102
- unique_ptr<RandomAccessFile> file;
99
+ std::unique_ptr<RandomAccessFile> file;
103
100
uint64_t file_size;
104
101
Status s = options_.env ->NewRandomAccessFile (file_path, &file, soptions_);
105
102
if (s.ok ()) {
@@ -109,10 +106,10 @@ Status SstFileReader::GetTableReader(const std::string& file_path) {
109
106
file_.reset (new RandomAccessFileReader (std::move (file)));
110
107
111
108
if (s.ok ()) {
112
- s = ReadFooterFromFile (file_.get (), file_size, &footer );
109
+ s = ReadFooterFromFile (file_.get (), file_size, &footer_ );
113
110
}
114
111
if (s.ok ()) {
115
- magic_number = footer .table_magic_number ();
112
+ magic_number = footer_ .table_magic_number ();
116
113
}
117
114
118
115
if (s.ok ()) {
@@ -135,10 +132,10 @@ Status SstFileReader::GetTableReader(const std::string& file_path) {
135
132
s = NewTableReader (ioptions_, soptions_, *internal_comparator_, file_size,
136
133
&table_reader_);
137
134
if (s.ok () && table_reader_->IsSplitSst ()) {
138
- unique_ptr<RandomAccessFile> data_file;
135
+ std:: unique_ptr<RandomAccessFile> data_file;
139
136
RETURN_NOT_OK (options_.env ->NewRandomAccessFile (
140
137
TableBaseToDataFileName (file_path), &data_file, soptions_));
141
- unique_ptr<RandomAccessFileReader> data_file_reader (
138
+ std:: unique_ptr<RandomAccessFileReader> data_file_reader (
142
139
new RandomAccessFileReader (std::move (data_file)));
143
140
table_reader_->SetDataFileReader (std::move (data_file_reader));
144
141
}
@@ -149,10 +146,10 @@ Status SstFileReader::GetTableReader(const std::string& file_path) {
149
146
Status SstFileReader::NewTableReader (
150
147
const ImmutableCFOptions& ioptions, const EnvOptions& soptions,
151
148
const InternalKeyComparator& internal_comparator, uint64_t file_size,
152
- unique_ptr<TableReader>* table_reader) {
149
+ std:: unique_ptr<TableReader>* table_reader) {
153
150
// We need to turn off pre-fetching of index and filter nodes for
154
151
// BlockBasedTable
155
- shared_ptr<BlockBasedTableFactory> block_table_factory =
152
+ std:: shared_ptr<BlockBasedTableFactory> block_table_factory =
156
153
dynamic_pointer_cast<BlockBasedTableFactory>(options_.table_factory );
157
154
158
155
if (block_table_factory) {
@@ -172,7 +169,7 @@ Status SstFileReader::NewTableReader(
172
169
}
173
170
174
171
Status SstFileReader::DumpTable (const std::string& out_filename) {
175
- unique_ptr<WritableFile> out_file;
172
+ std:: unique_ptr<WritableFile> out_file;
176
173
Env* env = Env::Default ();
177
174
RETURN_NOT_OK (env->NewWritableFile (out_filename, &out_file, soptions_));
178
175
Status s = table_reader_->DumpTable (out_file.get ());
@@ -182,20 +179,20 @@ Status SstFileReader::DumpTable(const std::string& out_filename) {
182
179
183
180
uint64_t SstFileReader::CalculateCompressedTableSize (
184
181
const TableBuilderOptions& tb_options, size_t block_size) {
185
- unique_ptr<WritableFile> out_file;
186
- unique_ptr<Env> env (NewMemEnv (Env::Default ()));
182
+ std:: unique_ptr<WritableFile> out_file;
183
+ std:: unique_ptr<Env> env (NewMemEnv (Env::Default ()));
187
184
CHECK_OK (env->NewWritableFile (testFileName, &out_file, soptions_));
188
- unique_ptr<WritableFileWriter> dest_writer;
185
+ std:: unique_ptr<WritableFileWriter> dest_writer;
189
186
dest_writer.reset (new WritableFileWriter (std::move (out_file), soptions_));
190
187
BlockBasedTableOptions table_options;
191
188
table_options.block_size = block_size;
192
189
BlockBasedTableFactory block_based_tf (table_options);
193
- unique_ptr<TableBuilder> table_builder;
190
+ std:: unique_ptr<TableBuilder> table_builder;
194
191
table_builder = block_based_tf.NewTableBuilder (
195
192
tb_options,
196
193
TablePropertiesCollectorFactory::Context::kUnknownColumnFamily ,
197
194
dest_writer.get ());
198
- unique_ptr<InternalIterator> iter (table_reader_->NewIterator (ReadOptions ()));
195
+ std:: unique_ptr<InternalIterator> iter (table_reader_->NewIterator (ReadOptions ()));
199
196
for (iter->SeekToFirst (); iter->Valid (); iter->Next ()) {
200
197
if (!iter->status ().ok ()) {
201
198
fputs (iter->status ().ToString ().c_str (), stderr);
@@ -387,6 +384,77 @@ Status SstFileReader::ReadSequential(bool print_kv,
387
384
return ret;
388
385
}
389
386
387
+ namespace {
388
+
389
+ void PrintSaveBlockCommand (const std::string& data_file_path, const BlockHandle& block_handle) {
390
+ std::cout << " dd if=\" " << data_file_path << " \" bs=1 skip=" << block_handle.offset ()
391
+ << " count=" << block_handle.size () << " of=\" " << data_file_path << " .offset_"
392
+ << block_handle.offset () << " .size_" << block_handle.size () << " .part\" " << std::endl;
393
+ }
394
+
395
+ } // namespace
396
+
397
+ Status SstFileReader::CheckDataBlocks (DoUncompress do_uncompress) {
398
+ if (!table_reader_) {
399
+ return init_result_;
400
+ }
401
+ ReadOptions read_options;
402
+ read_options.verify_checksums = true ;
403
+
404
+ std::unique_ptr<InternalIterator> index_iterator (table_reader_->NewIndexIterator (read_options));
405
+ RETURN_NOT_OK (index_iterator->status ());
406
+
407
+ const auto data_file_path =
408
+ table_reader_->IsSplitSst () ? TableBaseToDataFileName (file_name_) : file_name_;
409
+ std::unique_ptr<RandomAccessFile> data_file;
410
+ RETURN_NOT_OK (options_.env ->NewRandomAccessFile (data_file_path, &data_file, soptions_));
411
+ std::unique_ptr<RandomAccessFileReader> data_file_reader (
412
+ new RandomAccessFileReader (std::move (data_file)));
413
+
414
+ size_t index_entry_pos = 0 ;
415
+ BlockHandle prev_block_handle;
416
+ BlockHandle block_handle;
417
+ bool save_block = false ;
418
+ for (index_iterator->SeekToFirst (); index_iterator->Valid ();
419
+ index_iterator->Next (), ++index_entry_pos) {
420
+ prev_block_handle = block_handle;
421
+ {
422
+ auto index_value_slice = index_iterator->Entry ().value ;
423
+ auto status = block_handle.DecodeFrom (&index_value_slice);
424
+ if (!status.ok ()) {
425
+ LOG (WARNING) << " Failed to decode SST index entry #" << index_entry_pos << " : "
426
+ << index_iterator->Entry ().value .ToDebugHexString () << " . " << status;
427
+ continue ;
428
+ }
429
+ LOG_IF (WARNING, index_value_slice.size () > 0 )
430
+ << " Extra bytes (" << index_value_slice.size ()
431
+ << " ) in index entry: " << index_iterator->Entry ().value .ToDebugHexString ();
432
+ }
433
+ YB_LOG_EVERY_N_SECS (INFO, 30 ) << " Checking data block #" << index_entry_pos
434
+ << " handle: " << block_handle.ToDebugString ();
435
+
436
+ BlockContents block_contents;
437
+ auto status = ReadBlockContents (
438
+ data_file_reader.get (), footer_, read_options, block_handle, &block_contents, options_.env ,
439
+ /* mem_tracker = */ nullptr , do_uncompress);
440
+ if (!status.ok ()) {
441
+ LOG (WARNING) << " Failed to read block with handle: " << block_handle.ToDebugString () << " . "
442
+ << status;
443
+ if (prev_block_handle.IsSet ()) {
444
+ PrintSaveBlockCommand (data_file_path, prev_block_handle);
445
+ }
446
+ PrintSaveBlockCommand (data_file_path, block_handle);
447
+ // Save next block as well.
448
+ save_block = true ;
449
+ } else if (save_block) {
450
+ PrintSaveBlockCommand (data_file_path, block_handle);
451
+ save_block = false ;
452
+ }
453
+ }
454
+
455
+ return Status::OK ();
456
+ }
457
+
390
458
Status SstFileReader::ReadTableProperties (
391
459
std::shared_ptr<const TableProperties>* table_properties) {
392
460
if (!table_reader_) {
@@ -401,7 +469,7 @@ namespace {
401
469
402
470
void print_help () {
403
471
fprintf (stderr,
404
- " sst_dump [--command=check|scan|none|raw] [--verify_checksum] "
472
+ " sst_dump [--command=check|scan|check_data_blocks| none|raw] [--verify_checksum] "
405
473
" --file=data_dir_OR_sst_file"
406
474
" [--output_format=raw|hex|decoded_regulardb|decoded_intentsdb]"
407
475
" [--formatter_tablet_metadata=<path_to_tablet_metadata>"
@@ -411,7 +479,8 @@ void print_help() {
411
479
" [--read_num=NUM]"
412
480
" [--show_properties]"
413
481
" [--show_compression_sizes]"
414
- " [--show_compression_sizes [--set_block_size=<block_size>]]\n " );
482
+ " [--show_compression_sizes [--set_block_size=<block_size>]]"
483
+ " [--skip_uncompress]\n " );
415
484
}
416
485
417
486
} // namespace
@@ -431,6 +500,7 @@ int SSTDumpTool::Run(int argc, char** argv) {
431
500
bool show_properties = false ;
432
501
bool show_compression_sizes = false ;
433
502
bool set_block_size = false ;
503
+ DoUncompress do_uncompress = DoUncompress ::kTrue ;
434
504
std::string from_key;
435
505
std::string to_key;
436
506
std::string block_size_str;
@@ -470,6 +540,8 @@ int SSTDumpTool::Run(int argc, char** argv) {
470
540
show_properties = true ;
471
541
} else if (strcmp (argv[i], " --show_compression_sizes" ) == 0 ) {
472
542
show_compression_sizes = true ;
543
+ } else if (strcmp (argv[i], " --skip_uncompress" ) == 0 ) {
544
+ do_uncompress = DoUncompress::kFalse ;
473
545
} else if (strncmp (argv[i], " --set_block_size=" , 17 ) == 0 ) {
474
546
set_block_size = true ;
475
547
block_size_str = argv[i] + 17 ;
@@ -575,6 +647,8 @@ int SSTDumpTool::Run(int argc, char** argv) {
575
647
if (read_num > 0 && total_read > read_num) {
576
648
break ;
577
649
}
650
+ } else if (command == " check_data_blocks" ) {
651
+ ERROR_NOT_OK (reader.CheckDataBlocks (do_uncompress), " Failed to scan SST file blocks:" );
578
652
}
579
653
if (show_properties) {
580
654
const rocksdb::TableProperties* table_properties;
0 commit comments