@nxtedition/rocksdb 15.1.2 → 15.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +15 -0
- package/binding.cc +79 -38
- package/build.sh +1 -2
- package/deps/rocksdb/rocksdb/BUCK +10 -8
- package/deps/rocksdb/rocksdb/CMakeLists.txt +27 -2
- package/deps/rocksdb/rocksdb/Makefile +27 -116
- package/deps/rocksdb/rocksdb/cache/cache_bench_tool.cc +1 -1
- package/deps/rocksdb/rocksdb/cache/clock_cache.cc +101 -124
- package/deps/rocksdb/rocksdb/cache/clock_cache.h +47 -30
- package/deps/rocksdb/rocksdb/db/c.cc +793 -131
- package/deps/rocksdb/rocksdb/db/c_test.c +571 -0
- package/deps/rocksdb/rocksdb/db/compact_files_test.cc +226 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction.h +4 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +95 -59
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job.h +2 -2
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job_test.cc +45 -35
- package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.cc +8 -4
- package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.h +1 -1
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.cc +11 -6
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.h +8 -2
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_test.cc +47 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.cc +12 -2
- package/deps/rocksdb/rocksdb/db/compaction/compaction_service_test.cc +82 -0
- package/deps/rocksdb/rocksdb/db/compaction/subcompaction_state.cc +2 -2
- package/deps/rocksdb/rocksdb/db/compaction/subcompaction_state.h +1 -1
- package/deps/rocksdb/rocksdb/db/db_basic_test.cc +69 -24
- package/deps/rocksdb/rocksdb/db/db_bloom_filter_test.cc +9 -1
- package/deps/rocksdb/rocksdb/db/db_compaction_test.cc +65 -0
- package/deps/rocksdb/rocksdb/db/db_etc3_test.cc +161 -0
- package/deps/rocksdb/rocksdb/db/db_filesnapshot.cc +1 -0
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +20 -7
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +13 -0
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +114 -39
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_files.cc +3 -0
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_follower.cc +3 -3
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +1 -1
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_secondary.cc +39 -25
- package/deps/rocksdb/rocksdb/db/db_iterator_test.cc +361 -0
- package/deps/rocksdb/rocksdb/db/db_options_test.cc +35 -0
- package/deps/rocksdb/rocksdb/db/db_range_del_test.cc +83 -0
- package/deps/rocksdb/rocksdb/db/db_test.cc +249 -4
- package/deps/rocksdb/rocksdb/db/db_test2.cc +3 -0
- package/deps/rocksdb/rocksdb/db/db_test_util.cc +2 -1
- package/deps/rocksdb/rocksdb/db/db_wal_test.cc +3 -2
- package/deps/rocksdb/rocksdb/db/flush_job_test.cc +7 -7
- package/deps/rocksdb/rocksdb/db/listener_test.cc +7 -17
- package/deps/rocksdb/rocksdb/db/memtable_list_test.cc +4 -2
- package/deps/rocksdb/rocksdb/db/obsolete_files_test.cc +41 -0
- package/deps/rocksdb/rocksdb/db/repair.cc +2 -2
- package/deps/rocksdb/rocksdb/db/version_edit.h +7 -4
- package/deps/rocksdb/rocksdb/db/version_set.cc +299 -90
- package/deps/rocksdb/rocksdb/db/version_set.h +56 -9
- package/deps/rocksdb/rocksdb/db/version_set_test.cc +41 -39
- package/deps/rocksdb/rocksdb/db/version_util.h +3 -2
- package/deps/rocksdb/rocksdb/db/wal_manager.cc +7 -1
- package/deps/rocksdb/rocksdb/db/wal_manager_test.cc +48 -10
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +1 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +5 -1
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +16 -5
- package/deps/rocksdb/rocksdb/env/env_test.cc +126 -41
- package/deps/rocksdb/rocksdb/env/fs_posix.cc +14 -7
- package/deps/rocksdb/rocksdb/env/io_posix.cc +304 -112
- package/deps/rocksdb/rocksdb/env/io_posix.h +16 -4
- package/deps/rocksdb/rocksdb/env/io_posix_test.cc +43 -0
- package/deps/rocksdb/rocksdb/folly.mk +148 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/advanced_compression.h +29 -3
- package/deps/rocksdb/rocksdb/include/rocksdb/advanced_options.h +73 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/c.h +246 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/compaction_filter.h +0 -2
- package/deps/rocksdb/rocksdb/include/rocksdb/data_structure.h +15 -9
- package/deps/rocksdb/rocksdb/include/rocksdb/db.h +19 -9
- package/deps/rocksdb/rocksdb/include/rocksdb/env.h +1 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/file_system.h +6 -4
- package/deps/rocksdb/rocksdb/include/rocksdb/metadata.h +14 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/options.h +67 -6
- package/deps/rocksdb/rocksdb/include/rocksdb/sst_file_writer.h +1 -7
- package/deps/rocksdb/rocksdb/include/rocksdb/statistics.h +3 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/thread_status.h +6 -14
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/backup_engine.h +8 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/env_mirror.h +2 -2
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/ldb_cmd_execute_result.h +0 -4
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/option_change_migration.h +33 -5
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/stackable_db.h +6 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/version.h +2 -2
- package/deps/rocksdb/rocksdb/monitoring/statistics.cc +2 -0
- package/deps/rocksdb/rocksdb/monitoring/thread_status_impl.cc +5 -2
- package/deps/rocksdb/rocksdb/monitoring/thread_status_updater.cc +2 -2
- package/deps/rocksdb/rocksdb/monitoring/thread_status_updater.h +6 -6
- package/deps/rocksdb/rocksdb/monitoring/thread_status_updater_debug.cc +2 -2
- package/deps/rocksdb/rocksdb/monitoring/thread_status_util.cc +10 -5
- package/deps/rocksdb/rocksdb/monitoring/thread_status_util.h +2 -2
- package/deps/rocksdb/rocksdb/options/cf_options.cc +15 -3
- package/deps/rocksdb/rocksdb/options/cf_options.h +7 -0
- package/deps/rocksdb/rocksdb/options/db_options.cc +27 -36
- package/deps/rocksdb/rocksdb/options/db_options.h +3 -2
- package/deps/rocksdb/rocksdb/options/options.cc +4 -0
- package/deps/rocksdb/rocksdb/options/options_helper.cc +8 -2
- package/deps/rocksdb/rocksdb/options/options_settable_test.cc +4 -1
- package/deps/rocksdb/rocksdb/options/options_test.cc +19 -3
- package/deps/rocksdb/rocksdb/src.mk +1 -1
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.cc +155 -32
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.h +7 -3
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.cc +169 -125
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.h +22 -7
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +43 -24
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.h +9 -5
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_test.cc +9 -8
- package/deps/rocksdb/rocksdb/table/block_based/filter_block.h +17 -0
- package/deps/rocksdb/rocksdb/table/block_based/filter_policy.cc +15 -5
- package/deps/rocksdb/rocksdb/table/block_based/filter_policy_internal.h +13 -18
- package/deps/rocksdb/rocksdb/table/block_based/full_filter_block.cc +29 -0
- package/deps/rocksdb/rocksdb/table/block_based/full_filter_block.h +6 -0
- package/deps/rocksdb/rocksdb/table/block_based/full_filter_block_test.cc +15 -0
- package/deps/rocksdb/rocksdb/table/block_based/index_builder.cc +79 -19
- package/deps/rocksdb/rocksdb/table/block_based/index_builder.h +48 -20
- package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.cc +51 -0
- package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.h +19 -0
- package/deps/rocksdb/rocksdb/table/block_based/user_defined_index_wrapper.h +1 -1
- package/deps/rocksdb/rocksdb/table/external_table.cc +2 -2
- package/deps/rocksdb/rocksdb/table/sst_file_dumper.cc +3 -2
- package/deps/rocksdb/rocksdb/table/sst_file_dumper.h +3 -1
- package/deps/rocksdb/rocksdb/table/table_builder.h +5 -0
- package/deps/rocksdb/rocksdb/table/table_reader.h +4 -2
- package/deps/rocksdb/rocksdb/table/table_test.cc +48 -39
- package/deps/rocksdb/rocksdb/test_util/sync_point.cc +4 -0
- package/deps/rocksdb/rocksdb/test_util/sync_point.h +32 -0
- package/deps/rocksdb/rocksdb/test_util/testutil.h +6 -2
- package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +14 -4
- package/deps/rocksdb/rocksdb/tools/ldb_cmd.cc +8 -5
- package/deps/rocksdb/rocksdb/tools/ldb_cmd_test.cc +3 -2
- package/deps/rocksdb/rocksdb/tools/sst_dump_tool.cc +63 -12
- package/deps/rocksdb/rocksdb/util/auto_tune_compressor.cc +16 -1
- package/deps/rocksdb/rocksdb/util/auto_tune_compressor.h +5 -1
- package/deps/rocksdb/rocksdb/util/bit_fields.h +133 -23
- package/deps/rocksdb/rocksdb/util/bloom_test.cc +2 -5
- package/deps/rocksdb/rocksdb/util/compression.cc +51 -23
- package/deps/rocksdb/rocksdb/util/compression_test.cc +525 -270
- package/deps/rocksdb/rocksdb/util/filter_bench.cc +3 -4
- package/deps/rocksdb/rocksdb/util/simple_mixed_compressor.cc +11 -2
- package/deps/rocksdb/rocksdb/util/simple_mixed_compressor.h +4 -1
- package/deps/rocksdb/rocksdb/util/slice_test.cc +92 -0
- package/deps/rocksdb/rocksdb/util/thread_list_test.cc +2 -2
- package/deps/rocksdb/rocksdb/util/thread_operation.h +2 -2
- package/deps/rocksdb/rocksdb/util/threadpool_imp.cc +2 -2
- package/deps/rocksdb/rocksdb/utilities/backup/backup_engine.cc +19 -2
- package/deps/rocksdb/rocksdb/utilities/backup/backup_engine_test.cc +75 -0
- package/deps/rocksdb/rocksdb/utilities/checkpoint/checkpoint_test.cc +1 -0
- package/deps/rocksdb/rocksdb/utilities/option_change_migration/option_change_migration.cc +303 -111
- package/deps/rocksdb/rocksdb/utilities/option_change_migration/option_change_migration_test.cc +379 -0
- package/deps/rocksdb/rocksdb.gyp +1 -0
- package/iterator.js +66 -70
- package/package.json +6 -6
- package/prebuilds/darwin-arm64/@nxtedition+rocksdb.node +0 -0
- package/deps/rocksdb/rocksdb/table/block_based/index_builder_test.cc +0 -183
|
@@ -1045,13 +1045,6 @@ void BlockBasedTableIterator::Prepare(const MultiScanArgs* multiscan_opts) {
|
|
|
1045
1045
|
}
|
|
1046
1046
|
|
|
1047
1047
|
void BlockBasedTableIterator::SeekMultiScan(const Slice* seek_target) {
|
|
1048
|
-
if (SeekMultiScanImpl(seek_target)) {
|
|
1049
|
-
is_out_of_bound_ = true;
|
|
1050
|
-
assert(!Valid());
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
|
-
bool BlockBasedTableIterator::SeekMultiScanImpl(const Slice* seek_target) {
|
|
1055
1048
|
assert(multi_scan_ && multi_scan_status_.ok());
|
|
1056
1049
|
// This is a MultiScan and Preapre() has been called.
|
|
1057
1050
|
|
|
@@ -1063,49 +1056,59 @@ bool BlockBasedTableIterator::SeekMultiScanImpl(const Slice* seek_target) {
|
|
|
1063
1056
|
if (!seek_target) {
|
|
1064
1057
|
// start key must be set for multi-scan
|
|
1065
1058
|
multi_scan_status_ = Status::InvalidArgument("No seek key for MultiScan");
|
|
1066
|
-
return
|
|
1059
|
+
return;
|
|
1067
1060
|
}
|
|
1068
1061
|
|
|
1069
|
-
constexpr auto out_of_bound = true;
|
|
1070
|
-
|
|
1071
1062
|
// Check the case where there is no range prepared on this table
|
|
1072
1063
|
if (multi_scan_->scan_opts->size() == 0) {
|
|
1073
1064
|
// out of bound
|
|
1074
|
-
|
|
1065
|
+
MarkPreparedRangeExhausted();
|
|
1066
|
+
return;
|
|
1075
1067
|
}
|
|
1076
1068
|
|
|
1077
1069
|
// Check whether seek key is moving forward.
|
|
1078
|
-
if (
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
//
|
|
1096
|
-
//
|
|
1097
|
-
//
|
|
1098
|
-
//
|
|
1099
|
-
//
|
|
1100
|
-
//
|
|
1101
|
-
//
|
|
1102
|
-
//
|
|
1103
|
-
//
|
|
1104
|
-
//
|
|
1105
|
-
//
|
|
1106
|
-
//
|
|
1107
|
-
//
|
|
1108
|
-
//
|
|
1070
|
+
if (multi_scan_->prev_seek_key_.empty() ||
|
|
1071
|
+
icomp_.Compare(*seek_target, multi_scan_->prev_seek_key_) > 0) {
|
|
1072
|
+
// If seek key is empty or is larger than previous seek key, update the
|
|
1073
|
+
// previous seek key. Otherwise use the previous seek key as the adjusted
|
|
1074
|
+
// seek target moving forward. This prevents seek target going backward,
|
|
1075
|
+
// which would visit pages that have been unpinned.
|
|
1076
|
+
// This issue is caused by sub-optimal range delete handling inside merge
|
|
1077
|
+
// iterator.
|
|
1078
|
+
// TODO xingbo issues:14068 : Optimize the handling of range delete iterator
|
|
1079
|
+
// inside merge iterator, so that it doesn't move seek key backward. After
|
|
1080
|
+
// that we could return error if the key moves backward here.
|
|
1081
|
+
multi_scan_->prev_seek_key_ = seek_target->ToString();
|
|
1082
|
+
} else {
|
|
1083
|
+
// Seek key is adjusted to previous one, we can return here directly.
|
|
1084
|
+
return;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
// There are 3 different Cases we need to handle:
|
|
1088
|
+
// The following diagram explain different seek targets seeking at various
|
|
1089
|
+
// position on the table, while the next_scan_idx points to the PreparedRange
|
|
1090
|
+
// 2.
|
|
1091
|
+
//
|
|
1092
|
+
// next_scan_idx: -------------------┐
|
|
1093
|
+
// ▼
|
|
1094
|
+
// table: : __[PreparedRange 1]__[PreparedRange 2]__[PreparedRange 3]__
|
|
1095
|
+
// Seek target: <----- Case 1 ------>▲<------------- Case 2 -------------->
|
|
1096
|
+
// │
|
|
1097
|
+
// Case 3
|
|
1098
|
+
//
|
|
1099
|
+
// Case 1: seek before the start of next prepared ranges. This could happen
|
|
1100
|
+
// due to too many delete tomestone triggered reseek or delete range.
|
|
1101
|
+
// Case 2: seek after the start of next prepared range.
|
|
1102
|
+
// This could happen due to seek key adjustment from delete range file.
|
|
1103
|
+
// E.g. LSM has 3 levels, each level has only 1 file:
|
|
1104
|
+
// L1 : key : 0---10
|
|
1105
|
+
// L2 : Delete range key : 0-5
|
|
1106
|
+
// L3 : key : 0---10
|
|
1107
|
+
// When a range 2-8 was prepared, the prepared key would be 2 on L3 file,
|
|
1108
|
+
// but the seek key would be 5, as the seek key was updated by the largest
|
|
1109
|
+
// key of delete range. This causes all of the cases above to be possible,
|
|
1110
|
+
// when the ranges are adjusted in the above examples.
|
|
1111
|
+
// Case 3: seek at the beginning of a prepared range (expected case)
|
|
1109
1112
|
|
|
1110
1113
|
// Allow reseek on the start of the last prepared range due to too many
|
|
1111
1114
|
// tombstone
|
|
@@ -1113,83 +1116,151 @@ bool BlockBasedTableIterator::SeekMultiScanImpl(const Slice* seek_target) {
|
|
|
1113
1116
|
std::min(multi_scan_->next_scan_idx,
|
|
1114
1117
|
multi_scan_->block_index_ranges_per_scan.size() - 1);
|
|
1115
1118
|
|
|
1119
|
+
auto user_seek_target = ExtractUserKey(*seek_target);
|
|
1120
|
+
|
|
1116
1121
|
auto compare_next_scan_start_result =
|
|
1117
1122
|
user_comparator_.CompareWithoutTimestamp(
|
|
1118
|
-
|
|
1123
|
+
user_seek_target, /*a_has_ts=*/true,
|
|
1119
1124
|
multi_scan_->scan_opts->GetScanRanges()[multi_scan_->next_scan_idx]
|
|
1120
1125
|
.range.start.value(),
|
|
1121
1126
|
/*b_has_ts=*/false);
|
|
1122
1127
|
|
|
1123
1128
|
if (compare_next_scan_start_result != 0) {
|
|
1124
|
-
// The seek
|
|
1129
|
+
// The seek target is not exactly same as what was prepared.
|
|
1125
1130
|
if (compare_next_scan_start_result < 0) {
|
|
1126
|
-
//
|
|
1127
|
-
//
|
|
1128
|
-
// next_scan_idx : |
|
|
1129
|
-
// V
|
|
1130
|
-
// table: _____[prepared range 1]_____[prepared range 2]_____
|
|
1131
|
-
// seek : 1 3 4
|
|
1132
|
-
|
|
1133
|
-
// Case 1: Seek key is before the start key of the first range
|
|
1131
|
+
// Case 1:
|
|
1134
1132
|
if (multi_scan_->next_scan_idx == 0) {
|
|
1135
|
-
|
|
1133
|
+
// This should not happen, even when seek target is adjusted by delete
|
|
1134
|
+
// range. The reason is that if the seek target is before the start key
|
|
1135
|
+
// of the first prepared range, its end key needs to be >= the smallest
|
|
1136
|
+
// key of this file, otherwise it is skipped in level iterator. If its
|
|
1137
|
+
// end key is >= the smallest key of this file, then this range will be
|
|
1138
|
+
// prepared for this file. As delete range could only adjust seek
|
|
1139
|
+
// target forward, so it would never be before the start key of the
|
|
1140
|
+
// first prepared range.
|
|
1141
|
+
assert(false && "Seek target before the first prepared range");
|
|
1142
|
+
MarkPreparedRangeExhausted();
|
|
1143
|
+
return;
|
|
1136
1144
|
}
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1145
|
+
auto seek_target_before_previous_prepared_range =
|
|
1146
|
+
user_comparator_.CompareWithoutTimestamp(
|
|
1147
|
+
user_seek_target, /*a_has_ts=*/true,
|
|
1148
|
+
multi_scan_->scan_opts
|
|
1149
|
+
->GetScanRanges()[multi_scan_->next_scan_idx - 1]
|
|
1150
|
+
.range.start.value(),
|
|
1151
|
+
/*b_has_ts=*/false) < 0;
|
|
1152
|
+
// Not expected to happen
|
|
1153
|
+
// This should never happen, the reason is that the
|
|
1154
|
+
// multi_scan_->next_scan_idx is set to a non zero value is due to a seek
|
|
1155
|
+
// target larger or equal to the start key of multi_scan_->next_scan_idx-1
|
|
1156
|
+
// happended earlier. If a seek happens before the start key of
|
|
1157
|
+
// multi_scan_->next_scan_idx-1, it would seek a key that is less than
|
|
1158
|
+
// what was seeked before.
|
|
1159
|
+
assert(!seek_target_before_previous_prepared_range);
|
|
1160
|
+
if (seek_target_before_previous_prepared_range) {
|
|
1161
|
+
multi_scan_status_ = Status::InvalidArgument(
|
|
1162
|
+
"Seek target is before the previous prepared range at index " +
|
|
1163
|
+
std::to_string(multi_scan_->next_scan_idx));
|
|
1164
|
+
return;
|
|
1165
|
+
}
|
|
1166
|
+
// It should only be possible to seek a key between the start of current
|
|
1167
|
+
// prepared scan and start of next prepared range.
|
|
1168
|
+
MultiScanUnexpectedSeekTarget(seek_target, &user_seek_target);
|
|
1142
1169
|
} else {
|
|
1143
|
-
//
|
|
1144
|
-
|
|
1145
|
-
// V
|
|
1146
|
-
// table: ____[prepared range 1]_____[prepared range 2]_____
|
|
1147
|
-
// seek : 3 4 5
|
|
1148
|
-
MultiScanUnexpectedSeekTarget(
|
|
1149
|
-
seek_target,
|
|
1150
|
-
std::get<0>(
|
|
1151
|
-
multi_scan_
|
|
1152
|
-
->block_index_ranges_per_scan[multi_scan_->next_scan_idx]));
|
|
1170
|
+
// Case 2:
|
|
1171
|
+
MultiScanUnexpectedSeekTarget(seek_target, &user_seek_target);
|
|
1153
1172
|
}
|
|
1154
1173
|
} else {
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
return out_of_bound;
|
|
1159
|
-
}
|
|
1174
|
+
// Case 2:
|
|
1175
|
+
assert(multi_scan_->next_scan_idx <
|
|
1176
|
+
multi_scan_->block_index_ranges_per_scan.size());
|
|
1160
1177
|
|
|
1161
1178
|
auto [cur_scan_start_idx, cur_scan_end_idx] =
|
|
1162
1179
|
multi_scan_->block_index_ranges_per_scan[multi_scan_->next_scan_idx];
|
|
1163
1180
|
// We should have the data block already loaded
|
|
1164
1181
|
++multi_scan_->next_scan_idx;
|
|
1165
1182
|
if (cur_scan_start_idx >= cur_scan_end_idx) {
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
} else {
|
|
1170
|
-
ResetDataIter();
|
|
1171
|
-
return false;
|
|
1172
|
-
}
|
|
1173
|
-
} else {
|
|
1174
|
-
is_out_of_bound_ = false;
|
|
1183
|
+
// No blocks are prepared for this range at current file.
|
|
1184
|
+
MarkPreparedRangeExhausted();
|
|
1185
|
+
return;
|
|
1175
1186
|
}
|
|
1176
1187
|
|
|
1177
|
-
|
|
1188
|
+
// max_sequential_skip_in_iterations can trigger a reseek on the start
|
|
1189
|
+
// key of a scan range, even though the multiscan is already past
|
|
1190
|
+
// `cur_scan_start_idx` (e.g., a user key spans multiple data blocks).
|
|
1191
|
+
size_t block_idx =
|
|
1192
|
+
std::max(cur_scan_start_idx, multi_scan_->cur_data_block_idx);
|
|
1193
|
+
MultiScanSeekTargetFromBlock(seek_target, block_idx);
|
|
1178
1194
|
}
|
|
1179
|
-
|
|
1180
|
-
return false;
|
|
1181
1195
|
}
|
|
1182
1196
|
|
|
1183
1197
|
void BlockBasedTableIterator::MultiScanUnexpectedSeekTarget(
|
|
1184
|
-
const Slice* seek_target,
|
|
1198
|
+
const Slice* seek_target, const Slice* user_seek_target) {
|
|
1185
1199
|
// linear search the block that contains the seek target, and unpin blocks
|
|
1186
1200
|
// that are before it.
|
|
1201
|
+
|
|
1202
|
+
// The logic here could be confusing when there is a delete range involved.
|
|
1203
|
+
// E.g. we have an LSM with 3 levels, each level has only 1 file:
|
|
1204
|
+
// L1: data file : 0---10
|
|
1205
|
+
// L2: Delete range : 0-5
|
|
1206
|
+
// L3: data file : 0---10
|
|
1207
|
+
//
|
|
1208
|
+
// MultiScan on ranges 1-2, 3-4, and 5-6.
|
|
1209
|
+
// When user first do Seek(1), on level 2, due to delete range 0-5, the seek
|
|
1210
|
+
// key is adjusted to 5 at level 3. Therefore, we will internally do Seek(5)
|
|
1211
|
+
// and unpins all blocks until 5 at level 3. Then the next scan's blocks from
|
|
1212
|
+
// 3-4 are unpinned at level 3. It is confusing that maybe block 3-4 should
|
|
1213
|
+
// not be unpinned, as next scan would need it. But Seek(5) implies that these
|
|
1214
|
+
// keys are all covered by some range deletion, so the next Seek(3) will also
|
|
1215
|
+
// do Seek(5) internally, so the blocks from 3-4 could be safely unpinned.
|
|
1216
|
+
|
|
1217
|
+
// advance to the right prepared range
|
|
1218
|
+
while (
|
|
1219
|
+
multi_scan_->next_scan_idx <
|
|
1220
|
+
multi_scan_->block_index_ranges_per_scan.size() &&
|
|
1221
|
+
(user_comparator_.CompareWithoutTimestamp(
|
|
1222
|
+
*user_seek_target, /*a_has_ts=*/true,
|
|
1223
|
+
multi_scan_->scan_opts->GetScanRanges()[multi_scan_->next_scan_idx]
|
|
1224
|
+
.range.start.value(),
|
|
1225
|
+
/*b_has_ts=*/false) >= 0)) {
|
|
1226
|
+
multi_scan_->next_scan_idx++;
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
// next_scan_idx is guaranteed to be higher than 0. If the seek key is before
|
|
1230
|
+
// the start key of first prepared range, it is already handled by caller
|
|
1231
|
+
// SeekMultiScan. It is equal, it would not call this funciton. If it is
|
|
1232
|
+
// after, next_scan_idx would be advanced by the loop above.
|
|
1233
|
+
assert(multi_scan_->next_scan_idx > 0);
|
|
1234
|
+
// Get the current range
|
|
1235
|
+
auto cur_scan_idx = multi_scan_->next_scan_idx - 1;
|
|
1236
|
+
auto [cur_scan_start_idx, cur_scan_end_idx] =
|
|
1237
|
+
multi_scan_->block_index_ranges_per_scan[cur_scan_idx];
|
|
1238
|
+
|
|
1239
|
+
if (cur_scan_start_idx >= cur_scan_end_idx) {
|
|
1240
|
+
// No blocks are prepared for this range at current file.
|
|
1241
|
+
MarkPreparedRangeExhausted();
|
|
1242
|
+
return;
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
// Unpin all the blocks from multi_scan_->cur_data_block_idx to
|
|
1246
|
+
// cur_scan_start_idx
|
|
1247
|
+
for (auto unpin_block_idx = multi_scan_->cur_data_block_idx;
|
|
1248
|
+
unpin_block_idx < cur_scan_start_idx; unpin_block_idx++) {
|
|
1249
|
+
if (!multi_scan_->pinned_data_blocks[unpin_block_idx].IsEmpty()) {
|
|
1250
|
+
multi_scan_->pinned_data_blocks[unpin_block_idx].Reset();
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
// Take the max here to ensure we don't move backwards.
|
|
1255
|
+
size_t block_idx =
|
|
1256
|
+
std::max(cur_scan_start_idx, multi_scan_->cur_data_block_idx);
|
|
1187
1257
|
auto const& data_block_separators = multi_scan_->data_block_separators;
|
|
1188
1258
|
while (block_idx < data_block_separators.size() &&
|
|
1189
1259
|
(user_comparator_.CompareWithoutTimestamp(
|
|
1190
|
-
|
|
1260
|
+
*user_seek_target, /*a_has_ts=*/true,
|
|
1191
1261
|
data_block_separators[block_idx],
|
|
1192
1262
|
/*b_has_ts=*/false) > 0)) {
|
|
1263
|
+
// Unpin the blocks that are passed
|
|
1193
1264
|
if (!multi_scan_->pinned_data_blocks[block_idx].IsEmpty()) {
|
|
1194
1265
|
multi_scan_->pinned_data_blocks[block_idx].Reset();
|
|
1195
1266
|
}
|
|
@@ -1197,30 +1268,11 @@ void BlockBasedTableIterator::MultiScanUnexpectedSeekTarget(
|
|
|
1197
1268
|
}
|
|
1198
1269
|
|
|
1199
1270
|
if (block_idx >= data_block_separators.size()) {
|
|
1200
|
-
//
|
|
1201
|
-
|
|
1202
|
-
ResetDataIter();
|
|
1203
|
-
assert(!Valid());
|
|
1271
|
+
// All of the prepared blocks for this file is exhausted.
|
|
1272
|
+
MarkPreparedRangeExhausted();
|
|
1204
1273
|
return;
|
|
1205
1274
|
}
|
|
1206
1275
|
|
|
1207
|
-
// // The iterator from previous seek may have moved forward a few blocks,
|
|
1208
|
-
// // In that case, have block_idx catch up the cur_data_block_idx
|
|
1209
|
-
// // Note no need to handle block unpin, as it has been handled during
|
|
1210
|
-
// iterating block_idx = std::max(block_idx, multi_scan_->cur_data_block_idx);
|
|
1211
|
-
|
|
1212
|
-
// advance to the right prepared range
|
|
1213
|
-
while (
|
|
1214
|
-
multi_scan_->next_scan_idx <
|
|
1215
|
-
multi_scan_->block_index_ranges_per_scan.size() &&
|
|
1216
|
-
(user_comparator_.CompareWithoutTimestamp(
|
|
1217
|
-
ExtractUserKey(*seek_target), /*a_has_ts=*/true,
|
|
1218
|
-
multi_scan_->scan_opts->GetScanRanges()[multi_scan_->next_scan_idx]
|
|
1219
|
-
.range.start.value(),
|
|
1220
|
-
/*b_has_ts=*/false) >= 0)) {
|
|
1221
|
-
multi_scan_->next_scan_idx++;
|
|
1222
|
-
}
|
|
1223
|
-
|
|
1224
1276
|
// The current block may contain the data for the target key
|
|
1225
1277
|
MultiScanSeekTargetFromBlock(seek_target, block_idx);
|
|
1226
1278
|
}
|
|
@@ -1257,6 +1309,7 @@ void BlockBasedTableIterator::MultiScanSeekTargetFromBlock(
|
|
|
1257
1309
|
block_iter_points_to_real_block_ = true;
|
|
1258
1310
|
block_iter_.Seek(*seek_target);
|
|
1259
1311
|
FindKeyForward();
|
|
1312
|
+
CheckOutOfBound();
|
|
1260
1313
|
}
|
|
1261
1314
|
|
|
1262
1315
|
void BlockBasedTableIterator::FindBlockForwardInMultiScan() {
|
|
@@ -1275,20 +1328,7 @@ void BlockBasedTableIterator::FindBlockForwardInMultiScan() {
|
|
|
1275
1328
|
// for this file, it may need to continue to scan into the next file, so
|
|
1276
1329
|
// we do not set is_out_of_bound_ in this case.
|
|
1277
1330
|
if (multi_scan_->cur_data_block_idx + 1 >= cur_scan_end_idx) {
|
|
1278
|
-
|
|
1279
|
-
multi_scan_->block_index_ranges_per_scan.size()) {
|
|
1280
|
-
// We are done with this file, should let LevelIter advance to the
|
|
1281
|
-
// next file instead of ending the scan
|
|
1282
|
-
ResetDataIter();
|
|
1283
|
-
assert(!is_out_of_bound_);
|
|
1284
|
-
assert(!Valid());
|
|
1285
|
-
return;
|
|
1286
|
-
}
|
|
1287
|
-
// We don't ResetDataIter() here since next scan might be reading from
|
|
1288
|
-
// the same block. ResetDataIter() will free the underlying block cache
|
|
1289
|
-
// handle and we don't want the block to be unpinned.
|
|
1290
|
-
is_out_of_bound_ = true;
|
|
1291
|
-
assert(!Valid());
|
|
1331
|
+
MarkPreparedRangeExhausted();
|
|
1292
1332
|
return;
|
|
1293
1333
|
}
|
|
1294
1334
|
// Move to the next pinned data block
|
|
@@ -1419,7 +1459,7 @@ Status BlockBasedTableIterator::CollectBlockHandles(
|
|
|
1419
1459
|
std::vector<std::tuple<size_t, size_t>>* block_index_ranges_per_scan,
|
|
1420
1460
|
std::vector<std::string>* data_block_separators) {
|
|
1421
1461
|
// print file name and level
|
|
1422
|
-
if (kVerbose) {
|
|
1462
|
+
if (UNLIKELY(kVerbose)) {
|
|
1423
1463
|
auto file_name = table_->get_rep()->file->file_name();
|
|
1424
1464
|
auto level = table_->get_rep()->level;
|
|
1425
1465
|
printf("file name : %s, level %d\n", file_name.c_str(), level);
|
|
@@ -1480,11 +1520,16 @@ Status BlockBasedTableIterator::CollectBlockHandles(
|
|
|
1480
1520
|
}
|
|
1481
1521
|
block_index_ranges_per_scan->emplace_back(
|
|
1482
1522
|
scan_block_handles->size() - num_blocks, scan_block_handles->size());
|
|
1483
|
-
if (kVerbose) {
|
|
1523
|
+
if (UNLIKELY(kVerbose)) {
|
|
1484
1524
|
printf("separators :");
|
|
1485
1525
|
for (const auto& separator : *data_block_separators) {
|
|
1486
1526
|
printf("%s, ", separator.c_str());
|
|
1487
1527
|
}
|
|
1528
|
+
printf("\nblock_index_ranges_per_scan :");
|
|
1529
|
+
for (auto const& block_index_range : *block_index_ranges_per_scan) {
|
|
1530
|
+
printf("[%zu, %zu], ", std::get<0>(block_index_range),
|
|
1531
|
+
std::get<1>(block_index_range));
|
|
1532
|
+
}
|
|
1488
1533
|
printf("\n");
|
|
1489
1534
|
}
|
|
1490
1535
|
}
|
|
@@ -1664,7 +1709,6 @@ Status BlockBasedTableIterator::ExecuteIO(
|
|
|
1664
1709
|
assert(false);
|
|
1665
1710
|
return s;
|
|
1666
1711
|
}
|
|
1667
|
-
assert(async_read.io_handle);
|
|
1668
1712
|
for (auto& req : *read_reqs) {
|
|
1669
1713
|
if (!req.status.ok()) {
|
|
1670
1714
|
assert(false);
|
|
@@ -381,6 +381,27 @@ class BlockBasedTableIterator : public InternalIteratorBase<Slice> {
|
|
|
381
381
|
bool block_iter_points_to_real_block_;
|
|
382
382
|
// See InternalIteratorBase::IsOutOfBound().
|
|
383
383
|
bool is_out_of_bound_ = false;
|
|
384
|
+
|
|
385
|
+
// Mark prepared ranges as exhausted for multiscan.
|
|
386
|
+
void MarkPreparedRangeExhausted() {
|
|
387
|
+
assert(multi_scan_ != nullptr);
|
|
388
|
+
if (multi_scan_->next_scan_idx <
|
|
389
|
+
multi_scan_->block_index_ranges_per_scan.size()) {
|
|
390
|
+
// If there are more prepared ranges, we don't ResetDataIter() here,
|
|
391
|
+
// because next scan might be reading from the same block. ResetDataIter()
|
|
392
|
+
// will free the underlying block cache handle and we don't want the
|
|
393
|
+
// block to be unpinned.
|
|
394
|
+
// Set out of bound to mark the current prepared range as exhausted.
|
|
395
|
+
is_out_of_bound_ = true;
|
|
396
|
+
} else {
|
|
397
|
+
// This is the last prepared range of this file, there might be more
|
|
398
|
+
// data on next file. Reset data iterator to indicate the iterator is
|
|
399
|
+
// no longer valid on this file. Let LevelIter advance to the next file
|
|
400
|
+
// instead of ending the scan.
|
|
401
|
+
ResetDataIter();
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
384
405
|
// During cache lookup to find readahead size, index_iter_ is iterated and it
|
|
385
406
|
// can point to a different block.
|
|
386
407
|
// If Prepare() is called, index_iter_ is used to prefetch data blocks for the
|
|
@@ -612,12 +633,8 @@ class BlockBasedTableIterator : public InternalIteratorBase<Slice> {
|
|
|
612
633
|
|
|
613
634
|
// *** BEGIN APIs relevant to multiscan ***
|
|
614
635
|
|
|
615
|
-
// Wrapper for SeekMultiScanImpl for handling out of bound
|
|
616
636
|
void SeekMultiScan(const Slice* target);
|
|
617
637
|
|
|
618
|
-
// Return true if the result is out of bound
|
|
619
|
-
bool SeekMultiScanImpl(const Slice* seek_target);
|
|
620
|
-
|
|
621
638
|
void FindBlockForwardInMultiScan();
|
|
622
639
|
|
|
623
640
|
void PrepareReadAsyncCallBack(FSReadRequest& req, void* cb_arg) {
|
|
@@ -635,14 +652,12 @@ class BlockBasedTableIterator : public InternalIteratorBase<Slice> {
|
|
|
635
652
|
std::to_string(async_state->offset) + " and async callback " +
|
|
636
653
|
std::to_string(req.offset));
|
|
637
654
|
}
|
|
638
|
-
} else {
|
|
639
|
-
assert(async_state->status.IsAborted());
|
|
640
655
|
}
|
|
641
656
|
}
|
|
642
657
|
|
|
643
658
|
void MultiScanSeekTargetFromBlock(const Slice* seek_target, size_t block_idx);
|
|
644
659
|
void MultiScanUnexpectedSeekTarget(const Slice* seek_target,
|
|
645
|
-
|
|
660
|
+
const Slice* user_seek_target);
|
|
646
661
|
|
|
647
662
|
// Return true, if there is an error, or end of file
|
|
648
663
|
bool MultiScanLoadDataBlock(size_t idx) {
|
|
@@ -2705,7 +2705,7 @@ Status BlockBasedTable::Prefetch(const ReadOptions& read_options,
|
|
|
2705
2705
|
}
|
|
2706
2706
|
BlockCacheLookupContext lookup_context{TableReaderCaller::kPrefetch};
|
|
2707
2707
|
IndexBlockIter iiter_on_stack;
|
|
2708
|
-
auto iiter = NewIndexIterator(read_options, /*
|
|
2708
|
+
auto iiter = NewIndexIterator(read_options, /*disable_prefix_seek=*/false,
|
|
2709
2709
|
&iiter_on_stack, /*get_context=*/nullptr,
|
|
2710
2710
|
&lookup_context);
|
|
2711
2711
|
std::unique_ptr<InternalIteratorBase<IndexValue>> iiter_unique_ptr;
|
|
@@ -2742,7 +2742,7 @@ Status BlockBasedTable::Prefetch(const ReadOptions& read_options,
|
|
|
2742
2742
|
DataBlockIter biter;
|
|
2743
2743
|
Status tmp_status;
|
|
2744
2744
|
NewDataBlockIterator<DataBlockIter>(
|
|
2745
|
-
read_options, block_handle, &biter, /*
|
|
2745
|
+
read_options, block_handle, &biter, /*block_type=*/BlockType::kData,
|
|
2746
2746
|
/*get_context=*/nullptr, &lookup_context,
|
|
2747
2747
|
/*prefetch_buffer=*/nullptr, /*for_compaction=*/false,
|
|
2748
2748
|
/*async_read=*/false, tmp_status, /*use_block_cache_for_lookup=*/true);
|
|
@@ -2757,7 +2757,8 @@ Status BlockBasedTable::Prefetch(const ReadOptions& read_options,
|
|
|
2757
2757
|
}
|
|
2758
2758
|
|
|
2759
2759
|
Status BlockBasedTable::VerifyChecksum(const ReadOptions& read_options,
|
|
2760
|
-
TableReaderCaller caller
|
|
2760
|
+
TableReaderCaller caller,
|
|
2761
|
+
bool meta_blocks_only) {
|
|
2761
2762
|
Status s;
|
|
2762
2763
|
// Check Meta blocks
|
|
2763
2764
|
std::unique_ptr<Block> metaindex;
|
|
@@ -2772,6 +2773,9 @@ Status BlockBasedTable::VerifyChecksum(const ReadOptions& read_options,
|
|
|
2772
2773
|
} else {
|
|
2773
2774
|
return s;
|
|
2774
2775
|
}
|
|
2776
|
+
if (meta_blocks_only) {
|
|
2777
|
+
return s;
|
|
2778
|
+
}
|
|
2775
2779
|
// Check Data blocks
|
|
2776
2780
|
IndexBlockIter iiter_on_stack;
|
|
2777
2781
|
BlockCacheLookupContext context{caller};
|
|
@@ -2967,7 +2971,7 @@ bool BlockBasedTable::TEST_BlockInCache(const BlockHandle& handle) const {
|
|
|
2967
2971
|
bool BlockBasedTable::TEST_KeyInCache(const ReadOptions& options,
|
|
2968
2972
|
const Slice& key) {
|
|
2969
2973
|
std::unique_ptr<InternalIteratorBase<IndexValue>> iiter(NewIndexIterator(
|
|
2970
|
-
options, /*
|
|
2974
|
+
options, /*disable_prefix_seek=*/false, /*input_iter=*/nullptr,
|
|
2971
2975
|
/*get_context=*/nullptr, /*lookup_context=*/nullptr));
|
|
2972
2976
|
iiter->Seek(key);
|
|
2973
2977
|
assert(iiter->status().ok());
|
|
@@ -3174,9 +3178,9 @@ bool BlockBasedTable::TEST_IndexBlockInCache() const {
|
|
|
3174
3178
|
Status BlockBasedTable::GetKVPairsFromDataBlocks(
|
|
3175
3179
|
const ReadOptions& read_options, std::vector<KVPairBlock>* kv_pair_blocks) {
|
|
3176
3180
|
std::unique_ptr<InternalIteratorBase<IndexValue>> blockhandles_iter(
|
|
3177
|
-
NewIndexIterator(read_options, /*
|
|
3181
|
+
NewIndexIterator(read_options, /*disable_prefix_seek=*/false,
|
|
3178
3182
|
/*input_iter=*/nullptr, /*get_context=*/nullptr,
|
|
3179
|
-
/*
|
|
3183
|
+
/*lookup_context=*/nullptr));
|
|
3180
3184
|
|
|
3181
3185
|
Status s = blockhandles_iter->status();
|
|
3182
3186
|
if (!s.ok()) {
|
|
@@ -3196,7 +3200,7 @@ Status BlockBasedTable::GetKVPairsFromDataBlocks(
|
|
|
3196
3200
|
Status tmp_status;
|
|
3197
3201
|
datablock_iter.reset(NewDataBlockIterator<DataBlockIter>(
|
|
3198
3202
|
read_options, blockhandles_iter->value().handle,
|
|
3199
|
-
/*input_iter=*/nullptr, /*
|
|
3203
|
+
/*input_iter=*/nullptr, /*block_type=*/BlockType::kData,
|
|
3200
3204
|
/*get_context=*/nullptr, /*lookup_context=*/nullptr,
|
|
3201
3205
|
/*prefetch_buffer=*/nullptr, /*for_compaction=*/false,
|
|
3202
3206
|
/*async_read=*/false, tmp_status, /*use_block_cache_for_lookup=*/true));
|
|
@@ -3228,7 +3232,8 @@ Status BlockBasedTable::GetKVPairsFromDataBlocks(
|
|
|
3228
3232
|
return Status::OK();
|
|
3229
3233
|
}
|
|
3230
3234
|
|
|
3231
|
-
Status BlockBasedTable::DumpTable(WritableFile* out_file
|
|
3235
|
+
Status BlockBasedTable::DumpTable(WritableFile* out_file,
|
|
3236
|
+
bool show_sequence_number_type) {
|
|
3232
3237
|
WritableFileStringStreamAdapter out_file_wrapper(out_file);
|
|
3233
3238
|
std::ostream out_stream(&out_file_wrapper);
|
|
3234
3239
|
// Output Footer
|
|
@@ -3321,15 +3326,15 @@ Status BlockBasedTable::DumpTable(WritableFile* out_file) {
|
|
|
3321
3326
|
out_stream << "Range deletions:\n"
|
|
3322
3327
|
"--------------------------------------\n";
|
|
3323
3328
|
for (; range_del_iter->Valid(); range_del_iter->Next()) {
|
|
3324
|
-
DumpKeyValue(range_del_iter->key(), range_del_iter->value(),
|
|
3325
|
-
|
|
3329
|
+
DumpKeyValue(range_del_iter->key(), range_del_iter->value(), out_stream,
|
|
3330
|
+
show_sequence_number_type);
|
|
3326
3331
|
}
|
|
3327
3332
|
out_stream << "\n";
|
|
3328
3333
|
}
|
|
3329
3334
|
delete range_del_iter;
|
|
3330
3335
|
}
|
|
3331
3336
|
// Output Data blocks
|
|
3332
|
-
s = DumpDataBlocks(out_stream);
|
|
3337
|
+
s = DumpDataBlocks(out_stream, show_sequence_number_type);
|
|
3333
3338
|
|
|
3334
3339
|
if (!s.ok()) {
|
|
3335
3340
|
return s;
|
|
@@ -3347,9 +3352,9 @@ Status BlockBasedTable::DumpIndexBlock(std::ostream& out_stream) {
|
|
|
3347
3352
|
// TODO: plumb Env::IOActivity, Env::IOPriority
|
|
3348
3353
|
const ReadOptions read_options;
|
|
3349
3354
|
std::unique_ptr<InternalIteratorBase<IndexValue>> blockhandles_iter(
|
|
3350
|
-
NewIndexIterator(read_options, /*
|
|
3355
|
+
NewIndexIterator(read_options, /*disable_prefix_seek=*/false,
|
|
3351
3356
|
/*input_iter=*/nullptr, /*get_context=*/nullptr,
|
|
3352
|
-
/*
|
|
3357
|
+
/*lookup_context=*/nullptr));
|
|
3353
3358
|
Status s = blockhandles_iter->status();
|
|
3354
3359
|
if (!s.ok()) {
|
|
3355
3360
|
out_stream << "Can not read Index Block \n\n";
|
|
@@ -3394,13 +3399,14 @@ Status BlockBasedTable::DumpIndexBlock(std::ostream& out_stream) {
|
|
|
3394
3399
|
return Status::OK();
|
|
3395
3400
|
}
|
|
3396
3401
|
|
|
3397
|
-
Status BlockBasedTable::DumpDataBlocks(std::ostream& out_stream
|
|
3402
|
+
Status BlockBasedTable::DumpDataBlocks(std::ostream& out_stream,
|
|
3403
|
+
bool show_sequence_number_type) {
|
|
3398
3404
|
// TODO: plumb Env::IOActivity, Env::IOPriority
|
|
3399
3405
|
const ReadOptions read_options;
|
|
3400
3406
|
std::unique_ptr<InternalIteratorBase<IndexValue>> blockhandles_iter(
|
|
3401
|
-
NewIndexIterator(read_options, /*
|
|
3407
|
+
NewIndexIterator(read_options, /*disable_prefix_seek=*/false,
|
|
3402
3408
|
/*input_iter=*/nullptr, /*get_context=*/nullptr,
|
|
3403
|
-
/*
|
|
3409
|
+
/*lookup_context=*/nullptr));
|
|
3404
3410
|
Status s = blockhandles_iter->status();
|
|
3405
3411
|
if (!s.ok()) {
|
|
3406
3412
|
out_stream << "Can not read Index Block \n\n";
|
|
@@ -3433,7 +3439,7 @@ Status BlockBasedTable::DumpDataBlocks(std::ostream& out_stream) {
|
|
|
3433
3439
|
Status tmp_status;
|
|
3434
3440
|
datablock_iter.reset(NewDataBlockIterator<DataBlockIter>(
|
|
3435
3441
|
read_options, blockhandles_iter->value().handle,
|
|
3436
|
-
/*input_iter=*/nullptr, /*
|
|
3442
|
+
/*input_iter=*/nullptr, /*block_type=*/BlockType::kData,
|
|
3437
3443
|
/*get_context=*/nullptr, /*lookup_context=*/nullptr,
|
|
3438
3444
|
/*prefetch_buffer=*/nullptr, /*for_compaction=*/false,
|
|
3439
3445
|
/*async_read=*/false, tmp_status, /*use_block_cache_for_lookup=*/true));
|
|
@@ -3451,7 +3457,8 @@ Status BlockBasedTable::DumpDataBlocks(std::ostream& out_stream) {
|
|
|
3451
3457
|
out_stream << "Error reading the block - Skipped \n";
|
|
3452
3458
|
break;
|
|
3453
3459
|
}
|
|
3454
|
-
DumpKeyValue(datablock_iter->key(), datablock_iter->value(), out_stream
|
|
3460
|
+
DumpKeyValue(datablock_iter->key(), datablock_iter->value(), out_stream,
|
|
3461
|
+
show_sequence_number_type);
|
|
3455
3462
|
}
|
|
3456
3463
|
out_stream << "\n";
|
|
3457
3464
|
}
|
|
@@ -3473,14 +3480,26 @@ Status BlockBasedTable::DumpDataBlocks(std::ostream& out_stream) {
|
|
|
3473
3480
|
}
|
|
3474
3481
|
|
|
3475
3482
|
void BlockBasedTable::DumpKeyValue(const Slice& key, const Slice& value,
|
|
3476
|
-
std::ostream& out_stream
|
|
3477
|
-
|
|
3478
|
-
|
|
3483
|
+
std::ostream& out_stream,
|
|
3484
|
+
bool show_sequence_number_type) {
|
|
3485
|
+
ParsedInternalKey result;
|
|
3486
|
+
auto s = ParseInternalKey(key, &result, true);
|
|
3487
|
+
if (!s.ok()) {
|
|
3488
|
+
out_stream << "Error parsing internal key - Skipped \n";
|
|
3489
|
+
return;
|
|
3490
|
+
}
|
|
3479
3491
|
|
|
3480
|
-
|
|
3481
|
-
|
|
3492
|
+
if (show_sequence_number_type) {
|
|
3493
|
+
out_stream << " HEX " << result.user_key.ToString(true)
|
|
3494
|
+
<< " seq: " << result.sequence
|
|
3495
|
+
<< " type: " << std::to_string(result.type) << " : "
|
|
3496
|
+
<< value.ToString(true) << "\n";
|
|
3497
|
+
} else {
|
|
3498
|
+
out_stream << " HEX " << result.user_key.ToString(true) << ": "
|
|
3499
|
+
<< value.ToString(true) << "\n";
|
|
3500
|
+
}
|
|
3482
3501
|
|
|
3483
|
-
std::string str_key =
|
|
3502
|
+
std::string str_key = result.user_key.ToString();
|
|
3484
3503
|
std::string str_value = value.ToString();
|
|
3485
3504
|
std::string res_key, res_value;
|
|
3486
3505
|
char cspace = ' ';
|