@nxtedition/rocksdb 13.5.12 → 14.0.0
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/binding.cc +33 -2
- package/binding.gyp +2 -2
- package/chained-batch.js +9 -16
- package/deps/rocksdb/rocksdb/BUCK +18 -1
- package/deps/rocksdb/rocksdb/CMakeLists.txt +10 -3
- package/deps/rocksdb/rocksdb/Makefile +20 -9
- package/deps/rocksdb/rocksdb/cache/cache_bench_tool.cc +90 -13
- package/deps/rocksdb/rocksdb/cache/clock_cache.cc +88 -75
- package/deps/rocksdb/rocksdb/cache/clock_cache.h +44 -36
- package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache.cc +184 -148
- package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache.h +5 -11
- package/deps/rocksdb/rocksdb/cache/compressed_secondary_cache_test.cc +116 -47
- package/deps/rocksdb/rocksdb/cache/lru_cache_test.cc +1 -1
- package/deps/rocksdb/rocksdb/cache/secondary_cache_adapter.cc +3 -6
- package/deps/rocksdb/rocksdb/db/arena_wrapped_db_iter.h +1 -1
- package/deps/rocksdb/rocksdb/db/builder.cc +4 -2
- package/deps/rocksdb/rocksdb/db/c.cc +207 -0
- package/deps/rocksdb/rocksdb/db/c_test.c +72 -0
- package/deps/rocksdb/rocksdb/db/column_family.cc +3 -2
- package/deps/rocksdb/rocksdb/db/column_family.h +5 -0
- package/deps/rocksdb/rocksdb/db/compact_files_test.cc +4 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction.cc +2 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.cc +51 -38
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.h +29 -12
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator_test.cc +5 -10
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +566 -366
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job.h +131 -4
- package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.cc +1 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.h +7 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.cc +4 -4
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.h +13 -14
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.cc +12 -7
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.h +8 -10
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_test.cc +97 -76
- package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.cc +11 -14
- package/deps/rocksdb/rocksdb/db/compaction/compaction_service_job.cc +1 -1
- package/deps/rocksdb/rocksdb/db/compaction/subcompaction_state.h +8 -0
- package/deps/rocksdb/rocksdb/db/compaction/tiered_compaction_test.cc +16 -3
- package/deps/rocksdb/rocksdb/db/db_basic_test.cc +1 -0
- package/deps/rocksdb/rocksdb/db/db_compaction_test.cc +448 -1
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +22 -20
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +4 -1
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +5 -5
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +7 -3
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_secondary.cc +1 -1
- package/deps/rocksdb/rocksdb/db/db_iter.cc +104 -0
- package/deps/rocksdb/rocksdb/db/db_iter.h +4 -11
- package/deps/rocksdb/rocksdb/db/db_iterator_test.cc +331 -58
- package/deps/rocksdb/rocksdb/db/db_memtable_test.cc +129 -0
- package/deps/rocksdb/rocksdb/db/db_sst_test.cc +64 -0
- package/deps/rocksdb/rocksdb/db/db_table_properties_test.cc +40 -0
- package/deps/rocksdb/rocksdb/db/db_test2.cc +25 -15
- package/deps/rocksdb/rocksdb/db/db_test_util.cc +42 -24
- package/deps/rocksdb/rocksdb/db/db_test_util.h +29 -14
- package/deps/rocksdb/rocksdb/db/db_universal_compaction_test.cc +69 -36
- package/deps/rocksdb/rocksdb/db/db_with_timestamp_basic_test.cc +0 -1
- package/deps/rocksdb/rocksdb/db/event_helpers.cc +1 -0
- package/deps/rocksdb/rocksdb/db/experimental.cc +5 -4
- package/deps/rocksdb/rocksdb/db/external_sst_file_basic_test.cc +8 -1
- package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.cc +275 -79
- package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.h +23 -5
- package/deps/rocksdb/rocksdb/db/external_sst_file_test.cc +591 -175
- package/deps/rocksdb/rocksdb/db/flush_job.cc +3 -4
- package/deps/rocksdb/rocksdb/db/log_reader.cc +5 -2
- package/deps/rocksdb/rocksdb/db/memtable.cc +84 -35
- package/deps/rocksdb/rocksdb/db/memtable.h +39 -34
- package/deps/rocksdb/rocksdb/db/merge_helper.cc +1 -0
- package/deps/rocksdb/rocksdb/db/merge_operator.cc +1 -1
- package/deps/rocksdb/rocksdb/db/multi_scan.cc +11 -5
- package/deps/rocksdb/rocksdb/db/version_edit.cc +1 -1
- package/deps/rocksdb/rocksdb/db/version_edit.h +1 -1
- package/deps/rocksdb/rocksdb/db/version_edit_handler.cc +34 -14
- package/deps/rocksdb/rocksdb/db/version_edit_handler.h +28 -5
- package/deps/rocksdb/rocksdb/db/version_set.cc +159 -14
- package/deps/rocksdb/rocksdb/db/version_set.h +2 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/CMakeLists.txt +1 -1
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.cc +60 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +16 -1
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_compaction_service.h +75 -10
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_compression_manager.cc +28 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_compression_manager.h +2 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_driver.cc +31 -1
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +50 -2
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_shared_state.h +57 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_stat.h +0 -4
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +266 -35
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.h +5 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_tool.cc +0 -6
- package/deps/rocksdb/rocksdb/db_stress_tool/no_batched_ops_stress.cc +18 -2
- package/deps/rocksdb/rocksdb/env/env.cc +12 -0
- package/deps/rocksdb/rocksdb/env/env_test.cc +18 -0
- package/deps/rocksdb/rocksdb/env/file_system_tracer.cc +2 -0
- package/deps/rocksdb/rocksdb/env/fs_posix.cc +9 -5
- package/deps/rocksdb/rocksdb/env/io_posix.cc +4 -2
- package/deps/rocksdb/rocksdb/file/random_access_file_reader.cc +19 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/advanced_compression.h +33 -31
- package/deps/rocksdb/rocksdb/include/rocksdb/advanced_options.h +42 -9
- package/deps/rocksdb/rocksdb/include/rocksdb/c.h +93 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/cache.h +43 -49
- package/deps/rocksdb/rocksdb/include/rocksdb/compaction_job_stats.h +4 -3
- package/deps/rocksdb/rocksdb/include/rocksdb/compression_type.h +8 -6
- package/deps/rocksdb/rocksdb/include/rocksdb/data_structure.h +487 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/db.h +11 -12
- package/deps/rocksdb/rocksdb/include/rocksdb/env.h +135 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/file_system.h +5 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/iostats_context.h +12 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/iterator.h +1 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/ldb_tool.h +8 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/memtablerep.h +12 -8
- package/deps/rocksdb/rocksdb/include/rocksdb/metadata.h +3 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/multi_scan.h +19 -9
- package/deps/rocksdb/rocksdb/include/rocksdb/options.h +219 -24
- package/deps/rocksdb/rocksdb/include/rocksdb/point_lock_bench_tool.h +14 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/secondary_cache.h +2 -2
- package/deps/rocksdb/rocksdb/include/rocksdb/slice.h +1 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/statistics.h +7 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/status.h +16 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/table.h +16 -4
- package/deps/rocksdb/rocksdb/include/rocksdb/table_properties.h +13 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/types.h +4 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/universal_compaction.h +0 -2
- package/deps/rocksdb/rocksdb/include/rocksdb/user_defined_index.h +45 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/cache_dump_load.h +1 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/stackable_db.h +1 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/transaction.h +6 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/transaction_db.h +21 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/version.h +2 -2
- package/deps/rocksdb/rocksdb/memory/memory_allocator_impl.h +3 -3
- package/deps/rocksdb/rocksdb/memtable/inlineskiplist.h +77 -51
- package/deps/rocksdb/rocksdb/memtable/skiplist.h +10 -13
- package/deps/rocksdb/rocksdb/memtable/skiplistrep.cc +16 -7
- package/deps/rocksdb/rocksdb/memtable/vectorrep.cc +9 -4
- package/deps/rocksdb/rocksdb/monitoring/iostats_context.cc +2 -0
- package/deps/rocksdb/rocksdb/monitoring/statistics.cc +6 -0
- package/deps/rocksdb/rocksdb/options/cf_options.cc +13 -1
- package/deps/rocksdb/rocksdb/options/cf_options.h +6 -2
- package/deps/rocksdb/rocksdb/options/options.cc +2 -0
- package/deps/rocksdb/rocksdb/options/options_helper.cc +9 -8
- package/deps/rocksdb/rocksdb/options/options_settable_test.cc +9 -5
- package/deps/rocksdb/rocksdb/port/mmap.cc +1 -1
- package/deps/rocksdb/rocksdb/port/win/xpress_win.cc +51 -0
- package/deps/rocksdb/rocksdb/port/win/xpress_win.h +4 -0
- package/deps/rocksdb/rocksdb/src.mk +8 -2
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.cc +1125 -765
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.h +35 -24
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_factory.cc +29 -4
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.cc +732 -256
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.h +225 -16
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +102 -26
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.h +1 -1
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_sync_and_async.h +2 -75
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_test.cc +433 -141
- package/deps/rocksdb/rocksdb/table/block_based/block_builder.h +2 -0
- package/deps/rocksdb/rocksdb/table/block_based/flush_block_policy.cc +17 -10
- package/deps/rocksdb/rocksdb/table/block_based/flush_block_policy_impl.h +20 -0
- package/deps/rocksdb/rocksdb/table/block_based/index_builder.cc +112 -85
- package/deps/rocksdb/rocksdb/table/block_based/index_builder.h +191 -36
- package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.cc +2 -2
- package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block_test.cc +1 -1
- package/deps/rocksdb/rocksdb/table/block_based/user_defined_index_wrapper.h +108 -31
- package/deps/rocksdb/rocksdb/table/external_table.cc +7 -3
- package/deps/rocksdb/rocksdb/table/format.cc +6 -12
- package/deps/rocksdb/rocksdb/table/format.h +10 -0
- package/deps/rocksdb/rocksdb/table/internal_iterator.h +1 -1
- package/deps/rocksdb/rocksdb/table/iterator_wrapper.h +1 -1
- package/deps/rocksdb/rocksdb/table/merging_iterator.cc +1 -1
- package/deps/rocksdb/rocksdb/table/meta_blocks.cc +5 -0
- package/deps/rocksdb/rocksdb/table/multiget_context.h +3 -1
- package/deps/rocksdb/rocksdb/table/sst_file_dumper.cc +118 -46
- package/deps/rocksdb/rocksdb/table/sst_file_dumper.h +9 -8
- package/deps/rocksdb/rocksdb/table/table_builder.h +5 -0
- package/deps/rocksdb/rocksdb/table/table_properties.cc +16 -0
- package/deps/rocksdb/rocksdb/table/table_test.cc +1540 -155
- package/deps/rocksdb/rocksdb/test_util/testutil.h +21 -5
- package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +26 -5
- package/deps/rocksdb/rocksdb/tools/ldb.cc +1 -2
- package/deps/rocksdb/rocksdb/tools/ldb_cmd.cc +2 -0
- package/deps/rocksdb/rocksdb/tools/ldb_tool.cc +9 -3
- package/deps/rocksdb/rocksdb/tools/sst_dump_test.cc +133 -165
- package/deps/rocksdb/rocksdb/tools/sst_dump_tool.cc +173 -64
- package/deps/rocksdb/rocksdb/util/aligned_buffer.h +69 -0
- package/deps/rocksdb/rocksdb/util/atomic.h +6 -0
- package/deps/rocksdb/rocksdb/util/auto_tune_compressor.cc +29 -20
- package/deps/rocksdb/rocksdb/util/auto_tune_compressor.h +10 -6
- package/deps/rocksdb/rocksdb/util/bit_fields.h +338 -0
- package/deps/rocksdb/rocksdb/util/coding.h +3 -3
- package/deps/rocksdb/rocksdb/util/compaction_job_stats_impl.cc +2 -2
- package/deps/rocksdb/rocksdb/util/compression.cc +777 -82
- package/deps/rocksdb/rocksdb/util/compression.h +5 -0
- package/deps/rocksdb/rocksdb/util/compression_test.cc +5 -3
- package/deps/rocksdb/rocksdb/util/dynamic_bloom.cc +2 -2
- package/deps/rocksdb/rocksdb/util/dynamic_bloom.h +15 -14
- package/deps/rocksdb/rocksdb/util/interval_test.cc +102 -0
- package/deps/rocksdb/rocksdb/util/semaphore.h +164 -0
- package/deps/rocksdb/rocksdb/util/simple_mixed_compressor.cc +10 -6
- package/deps/rocksdb/rocksdb/util/simple_mixed_compressor.h +4 -2
- package/deps/rocksdb/rocksdb/util/slice_test.cc +136 -0
- package/deps/rocksdb/rocksdb/util/status.cc +1 -0
- package/deps/rocksdb/rocksdb/util/string_util.cc +2 -16
- package/deps/rocksdb/rocksdb/utilities/cache_dump_load_impl.cc +1 -1
- package/deps/rocksdb/rocksdb/utilities/cache_dump_load_impl.h +1 -1
- package/deps/rocksdb/rocksdb/utilities/fault_injection_fs.cc +7 -4
- package/deps/rocksdb/rocksdb/utilities/fault_injection_fs.h +35 -14
- package/deps/rocksdb/rocksdb/utilities/persistent_cache/hash_table_test.cc +2 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/lock_manager.cc +5 -2
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/any_lock_manager_test.h +244 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_bench.cc +18 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_bench_tool.cc +159 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager.cc +1244 -161
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager.h +66 -12
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager_stress_test.cc +103 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager_test.cc +1275 -8
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager_test.h +40 -262
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager_test_common.h +78 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_validation_test_runner.h +469 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/lock/range/range_locking_test.cc +2 -6
- package/deps/rocksdb/rocksdb/utilities/transactions/pessimistic_transaction.cc +4 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/pessimistic_transaction.h +9 -1
- package/deps/rocksdb/rocksdb/utilities/transactions/timestamped_snapshot_test.cc +18 -9
- package/deps/rocksdb/rocksdb/utilities/transactions/transaction_base.h +2 -0
- package/deps/rocksdb/rocksdb/utilities/transactions/transaction_db_mutex_impl.cc +2 -1
- package/deps/rocksdb/rocksdb/utilities/transactions/transaction_test.cc +72 -44
- package/deps/rocksdb/rocksdb/utilities/transactions/transaction_test.h +92 -15
- package/deps/rocksdb/rocksdb/utilities/transactions/write_committed_transaction_ts_test.cc +6 -20
- package/deps/rocksdb/rocksdb/utilities/transactions/write_prepared_transaction_test.cc +143 -112
- package/deps/rocksdb/rocksdb/utilities/transactions/write_unprepared_transaction_test.cc +23 -16
- package/index.js +3 -3
- package/package.json +1 -1
- package/prebuilds/darwin-arm64/@nxtedition+rocksdb.node +0 -0
- package/prebuilds/linux-x64/@nxtedition+rocksdb.node +0 -0
- package/util.h +38 -12
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_stat.cc +0 -17
|
@@ -4142,13 +4142,18 @@ TEST_P(DBIteratorTest, AverageMemtableOpsScanFlushTriggerByOverwrites) {
|
|
|
4142
4142
|
ASSERT_EQ(1, NumTableFilesAtLevel(0));
|
|
4143
4143
|
}
|
|
4144
4144
|
|
|
4145
|
-
class DBMultiScanIteratorTest : public DBTestBase
|
|
4145
|
+
class DBMultiScanIteratorTest : public DBTestBase,
|
|
4146
|
+
public ::testing::WithParamInterface<bool> {
|
|
4146
4147
|
public:
|
|
4147
4148
|
DBMultiScanIteratorTest()
|
|
4148
4149
|
: DBTestBase("db_multi_scan_iterator_test", /*env_do_fsync=*/true) {}
|
|
4149
4150
|
};
|
|
4150
4151
|
|
|
4151
|
-
|
|
4152
|
+
// Param 0: ReadOptions::fill_cache
|
|
4153
|
+
INSTANTIATE_TEST_CASE_P(DBMultiScanIteratorTest, DBMultiScanIteratorTest,
|
|
4154
|
+
::testing::Bool());
|
|
4155
|
+
|
|
4156
|
+
TEST_P(DBMultiScanIteratorTest, BasicTest) {
|
|
4152
4157
|
// Create a file
|
|
4153
4158
|
for (int i = 0; i < 100; ++i) {
|
|
4154
4159
|
std::stringstream ss;
|
|
@@ -4159,9 +4164,10 @@ TEST_F(DBMultiScanIteratorTest, BasicTest) {
|
|
|
4159
4164
|
|
|
4160
4165
|
std::vector<std::string> key_ranges({"k03", "k10", "k25", "k50"});
|
|
4161
4166
|
ReadOptions ro;
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4167
|
+
ro.fill_cache = GetParam();
|
|
4168
|
+
MultiScanArgs scan_options(BytewiseComparator());
|
|
4169
|
+
scan_options.insert(key_ranges[0], key_ranges[1]);
|
|
4170
|
+
scan_options.insert(key_ranges[2], key_ranges[3]);
|
|
4165
4171
|
ColumnFamilyHandle* cfh = dbfull()->DefaultColumnFamily();
|
|
4166
4172
|
std::unique_ptr<MultiScan> iter =
|
|
4167
4173
|
dbfull()->NewMultiScan(ro, cfh, scan_options);
|
|
@@ -4187,23 +4193,48 @@ TEST_F(DBMultiScanIteratorTest, BasicTest) {
|
|
|
4187
4193
|
abort();
|
|
4188
4194
|
}
|
|
4189
4195
|
iter.reset();
|
|
4196
|
+
}
|
|
4190
4197
|
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4198
|
+
TEST_P(DBMultiScanIteratorTest, MixedBoundsTest) {
|
|
4199
|
+
// Create a file
|
|
4200
|
+
for (int i = 0; i < 100; ++i) {
|
|
4201
|
+
std::stringstream ss;
|
|
4202
|
+
ss << std::setw(2) << std::setfill('0') << i;
|
|
4203
|
+
ASSERT_OK(Put("k" + ss.str(), "val" + ss.str()));
|
|
4204
|
+
}
|
|
4205
|
+
ASSERT_OK(Flush());
|
|
4206
|
+
|
|
4207
|
+
std::vector<std::string> key_ranges(
|
|
4208
|
+
{"k03", "k10", "k25", "k50", "k75", "k90"});
|
|
4209
|
+
ReadOptions ro;
|
|
4210
|
+
ro.fill_cache = GetParam();
|
|
4211
|
+
MultiScanArgs scan_options(BytewiseComparator());
|
|
4212
|
+
scan_options.insert(key_ranges[0], key_ranges[1]);
|
|
4213
|
+
scan_options.insert(key_ranges[2]);
|
|
4214
|
+
scan_options.insert(key_ranges[4], key_ranges[5]);
|
|
4215
|
+
ColumnFamilyHandle* cfh = dbfull()->DefaultColumnFamily();
|
|
4216
|
+
std::unique_ptr<MultiScan> iter =
|
|
4217
|
+
dbfull()->NewMultiScan(ro, cfh, scan_options);
|
|
4195
4218
|
try {
|
|
4196
4219
|
int idx = 0;
|
|
4197
4220
|
int count = 0;
|
|
4198
4221
|
for (auto range : *iter) {
|
|
4199
4222
|
for (auto it : range) {
|
|
4200
|
-
ASSERT_GE(
|
|
4201
|
-
|
|
4223
|
+
ASSERT_GE(
|
|
4224
|
+
it.first.ToString().compare(
|
|
4225
|
+
scan_options.GetScanRanges()[idx].range.start->ToString()),
|
|
4226
|
+
0);
|
|
4227
|
+
if (scan_options.GetScanRanges()[idx].range.limit) {
|
|
4228
|
+
ASSERT_LT(
|
|
4229
|
+
it.first.ToString().compare(
|
|
4230
|
+
scan_options.GetScanRanges()[idx].range.limit->ToString()),
|
|
4231
|
+
0);
|
|
4232
|
+
}
|
|
4202
4233
|
count++;
|
|
4203
4234
|
}
|
|
4204
|
-
idx
|
|
4235
|
+
idx++;
|
|
4205
4236
|
}
|
|
4206
|
-
ASSERT_EQ(count,
|
|
4237
|
+
ASSERT_EQ(count, 97);
|
|
4207
4238
|
} catch (MultiScanException& ex) {
|
|
4208
4239
|
// Make sure exception contains the status
|
|
4209
4240
|
ASSERT_NOK(ex.status());
|
|
@@ -4214,25 +4245,31 @@ TEST_F(DBMultiScanIteratorTest, BasicTest) {
|
|
|
4214
4245
|
abort();
|
|
4215
4246
|
}
|
|
4216
4247
|
iter.reset();
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
scan_options[
|
|
4220
|
-
scan_options
|
|
4248
|
+
scan_options = MultiScanArgs(BytewiseComparator());
|
|
4249
|
+
scan_options.insert(key_ranges[0]);
|
|
4250
|
+
scan_options.insert(key_ranges[2], key_ranges[3]);
|
|
4251
|
+
scan_options.insert(key_ranges[4]);
|
|
4221
4252
|
iter = dbfull()->NewMultiScan(ro, cfh, scan_options);
|
|
4222
4253
|
try {
|
|
4223
4254
|
int idx = 0;
|
|
4224
4255
|
int count = 0;
|
|
4225
4256
|
for (auto range : *iter) {
|
|
4226
4257
|
for (auto it : range) {
|
|
4227
|
-
ASSERT_GE(
|
|
4228
|
-
|
|
4229
|
-
|
|
4258
|
+
ASSERT_GE(
|
|
4259
|
+
it.first.ToString().compare(
|
|
4260
|
+
scan_options.GetScanRanges()[idx].range.start->ToString()),
|
|
4261
|
+
0);
|
|
4262
|
+
if (scan_options.GetScanRanges()[idx].range.limit) {
|
|
4263
|
+
ASSERT_LT(
|
|
4264
|
+
it.first.ToString().compare(
|
|
4265
|
+
scan_options.GetScanRanges()[idx].range.limit->ToString()),
|
|
4266
|
+
0);
|
|
4230
4267
|
}
|
|
4231
4268
|
count++;
|
|
4232
4269
|
}
|
|
4233
|
-
idx
|
|
4270
|
+
idx++;
|
|
4234
4271
|
}
|
|
4235
|
-
ASSERT_EQ(count,
|
|
4272
|
+
ASSERT_EQ(count, 147);
|
|
4236
4273
|
} catch (MultiScanException& ex) {
|
|
4237
4274
|
// Make sure exception contains the status
|
|
4238
4275
|
ASSERT_NOK(ex.status());
|
|
@@ -4245,42 +4282,150 @@ TEST_F(DBMultiScanIteratorTest, BasicTest) {
|
|
|
4245
4282
|
iter.reset();
|
|
4246
4283
|
}
|
|
4247
4284
|
|
|
4248
|
-
|
|
4285
|
+
TEST_P(DBMultiScanIteratorTest, RangeAcrossFiles) {
|
|
4286
|
+
auto options = CurrentOptions();
|
|
4287
|
+
options.target_file_size_base = 100 << 10; // 20KB
|
|
4288
|
+
options.compaction_style = kCompactionStyleUniversal;
|
|
4289
|
+
options.num_levels = 50;
|
|
4290
|
+
options.compression = kNoCompression;
|
|
4291
|
+
DestroyAndReopen(options);
|
|
4292
|
+
|
|
4293
|
+
auto rnd = Random::GetTLSInstance();
|
|
4294
|
+
// Write ~200KB data
|
|
4295
|
+
for (int i = 0; i < 100; ++i) {
|
|
4296
|
+
ASSERT_OK(Put(Key(i), rnd->RandomString(2 << 10)));
|
|
4297
|
+
}
|
|
4298
|
+
ASSERT_OK(Flush());
|
|
4299
|
+
|
|
4300
|
+
ASSERT_OK(db_->CompactRange({}, nullptr, nullptr));
|
|
4301
|
+
ASSERT_EQ(2, NumTableFilesAtLevel(49));
|
|
4302
|
+
std::vector<std::string> key_ranges({Key(10), Key(90)});
|
|
4303
|
+
ReadOptions ro;
|
|
4304
|
+
ro.fill_cache = GetParam();
|
|
4305
|
+
MultiScanArgs scan_options(BytewiseComparator());
|
|
4306
|
+
scan_options.insert(key_ranges[0], key_ranges[1]);
|
|
4307
|
+
ColumnFamilyHandle* cfh = dbfull()->DefaultColumnFamily();
|
|
4308
|
+
std::unique_ptr<MultiScan> iter =
|
|
4309
|
+
dbfull()->NewMultiScan(ro, cfh, scan_options);
|
|
4310
|
+
try {
|
|
4311
|
+
int i = 10;
|
|
4312
|
+
for (auto range : *iter) {
|
|
4313
|
+
for (auto it : range) {
|
|
4314
|
+
ASSERT_EQ(it.first.ToString(), Key(i));
|
|
4315
|
+
++i;
|
|
4316
|
+
}
|
|
4317
|
+
}
|
|
4318
|
+
ASSERT_EQ(i, 90);
|
|
4319
|
+
} catch (MultiScanException& ex) {
|
|
4320
|
+
// Make sure exception contains the status
|
|
4321
|
+
ASSERT_NOK(ex.status());
|
|
4322
|
+
std::cerr << "Iterator returned status " << ex.what();
|
|
4323
|
+
abort();
|
|
4324
|
+
} catch (std::logic_error& ex) {
|
|
4325
|
+
std::cerr << "Iterator returned logic error " << ex.what();
|
|
4326
|
+
abort();
|
|
4327
|
+
}
|
|
4328
|
+
iter.reset();
|
|
4329
|
+
}
|
|
4330
|
+
|
|
4331
|
+
TEST_P(DBMultiScanIteratorTest, FailureTest) {
|
|
4332
|
+
auto options = CurrentOptions();
|
|
4333
|
+
options.compression = kNoCompression;
|
|
4334
|
+
DestroyAndReopen(options);
|
|
4335
|
+
|
|
4336
|
+
Random rnd(301);
|
|
4249
4337
|
// Create a file
|
|
4250
4338
|
for (int i = 0; i < 100; ++i) {
|
|
4251
4339
|
std::stringstream ss;
|
|
4252
4340
|
ss << std::setw(2) << std::setfill('0') << i;
|
|
4253
|
-
ASSERT_OK(Put("k" + ss.str(),
|
|
4341
|
+
ASSERT_OK(Put("k" + ss.str(), rnd.RandomString(1024)));
|
|
4254
4342
|
}
|
|
4255
4343
|
ASSERT_OK(Flush());
|
|
4256
4344
|
|
|
4257
|
-
std::vector<std::string> key_ranges(
|
|
4258
|
-
|
|
4345
|
+
std::vector<std::string> key_ranges({"k04", "k06", "k12", "k14"});
|
|
4346
|
+
ReadOptions ro;
|
|
4347
|
+
Slice ub;
|
|
4348
|
+
ro.iterate_upper_bound = &ub;
|
|
4349
|
+
ro.fill_cache = GetParam();
|
|
4350
|
+
MultiScanArgs scan_options(BytewiseComparator());
|
|
4351
|
+
scan_options.insert(key_ranges[0], key_ranges[1]);
|
|
4352
|
+
scan_options.insert(key_ranges[2], key_ranges[3]);
|
|
4353
|
+
scan_options.max_prefetch_size = 4500;
|
|
4354
|
+
ColumnFamilyHandle* cfh = dbfull()->DefaultColumnFamily();
|
|
4355
|
+
std::unique_ptr<Iterator> iter(dbfull()->NewIterator(ro, cfh));
|
|
4356
|
+
ASSERT_NE(iter, nullptr);
|
|
4357
|
+
iter->Prepare(scan_options);
|
|
4358
|
+
int count = 0;
|
|
4359
|
+
ub = key_ranges[1];
|
|
4360
|
+
iter->Seek(key_ranges[0]);
|
|
4361
|
+
while (iter->status().ok() && iter->Valid()) {
|
|
4362
|
+
ASSERT_GE(iter->key().compare(key_ranges[0]), 0);
|
|
4363
|
+
ASSERT_LT(iter->key().compare(key_ranges[1]), 0);
|
|
4364
|
+
count++;
|
|
4365
|
+
iter->Next();
|
|
4366
|
+
}
|
|
4367
|
+
ASSERT_OK(iter->status()) << iter->status().ToString();
|
|
4368
|
+
ASSERT_EQ(count, 2);
|
|
4369
|
+
|
|
4370
|
+
// Second seek should hit the max_prefetch_size limit
|
|
4371
|
+
ub = key_ranges[3];
|
|
4372
|
+
iter->Seek(key_ranges[2]);
|
|
4373
|
+
ASSERT_NOK(iter->status());
|
|
4374
|
+
iter.reset();
|
|
4375
|
+
|
|
4376
|
+
// Test the case of unexpected Seek key
|
|
4377
|
+
iter.reset(dbfull()->NewIterator(ro, cfh));
|
|
4378
|
+
ASSERT_NE(iter, nullptr);
|
|
4379
|
+
scan_options.max_prefetch_size = 0;
|
|
4380
|
+
iter->Prepare(scan_options);
|
|
4381
|
+
ub = key_ranges[3];
|
|
4382
|
+
iter->Seek(key_ranges[2]);
|
|
4383
|
+
ASSERT_NOK(iter->status());
|
|
4384
|
+
iter.reset();
|
|
4385
|
+
}
|
|
4386
|
+
|
|
4387
|
+
TEST_P(DBMultiScanIteratorTest, RangeBetweenFiles) {
|
|
4388
|
+
auto options = CurrentOptions();
|
|
4389
|
+
options.target_file_size_base = 100 << 10; // 20KB
|
|
4390
|
+
options.compaction_style = kCompactionStyleUniversal;
|
|
4391
|
+
options.num_levels = 50;
|
|
4392
|
+
options.compression = kNoCompression;
|
|
4393
|
+
DestroyAndReopen(options);
|
|
4394
|
+
|
|
4395
|
+
auto rnd = Random::GetTLSInstance();
|
|
4396
|
+
// Write ~200KB data
|
|
4397
|
+
for (int i = 0; i < 100; ++i) {
|
|
4398
|
+
ASSERT_OK(Put(Key(i), rnd->RandomString(2 << 10)));
|
|
4399
|
+
}
|
|
4400
|
+
ASSERT_OK(Flush());
|
|
4401
|
+
|
|
4402
|
+
ASSERT_OK(db_->CompactRange({}, nullptr, nullptr));
|
|
4403
|
+
ASSERT_EQ(2, NumTableFilesAtLevel(49));
|
|
4404
|
+
|
|
4405
|
+
// Test with a scan range that overlaps an entire file, with upper bound
|
|
4406
|
+
// between 2 files
|
|
4407
|
+
std::vector<LiveFileMetaData> file_meta;
|
|
4408
|
+
dbfull()->GetLiveFilesMetaData(&file_meta);
|
|
4409
|
+
ASSERT_EQ(file_meta.size(), 2);
|
|
4410
|
+
std::vector<std::string> key_ranges(4);
|
|
4411
|
+
key_ranges[0] = file_meta[0].smallestkey;
|
|
4412
|
+
key_ranges[1] = file_meta[0].largestkey + "0";
|
|
4413
|
+
key_ranges[2] = file_meta[1].smallestkey + "0";
|
|
4414
|
+
key_ranges[3] = file_meta[1].largestkey;
|
|
4259
4415
|
ReadOptions ro;
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4416
|
+
ro.fill_cache = GetParam();
|
|
4417
|
+
MultiScanArgs scan_options(BytewiseComparator());
|
|
4418
|
+
scan_options.insert(key_ranges[0], key_ranges[1]);
|
|
4419
|
+
scan_options.insert(key_ranges[2], key_ranges[3]);
|
|
4263
4420
|
ColumnFamilyHandle* cfh = dbfull()->DefaultColumnFamily();
|
|
4264
4421
|
std::unique_ptr<MultiScan> iter =
|
|
4265
4422
|
dbfull()->NewMultiScan(ro, cfh, scan_options);
|
|
4266
4423
|
try {
|
|
4267
|
-
int idx = 0;
|
|
4268
|
-
int count = 0;
|
|
4269
4424
|
for (auto range : *iter) {
|
|
4270
4425
|
for (auto it : range) {
|
|
4271
|
-
ASSERT_GE(it.first.ToString()
|
|
4272
|
-
scan_options[idx].range.start->ToString()),
|
|
4273
|
-
0);
|
|
4274
|
-
if (scan_options[idx].range.limit) {
|
|
4275
|
-
ASSERT_LT(it.first.ToString().compare(
|
|
4276
|
-
scan_options[idx].range.limit->ToString()),
|
|
4277
|
-
0);
|
|
4278
|
-
}
|
|
4279
|
-
count++;
|
|
4426
|
+
ASSERT_GE(it.first.ToString(), key_ranges[0]);
|
|
4280
4427
|
}
|
|
4281
|
-
idx++;
|
|
4282
4428
|
}
|
|
4283
|
-
ASSERT_EQ(count, 97);
|
|
4284
4429
|
} catch (MultiScanException& ex) {
|
|
4285
4430
|
// Make sure exception contains the status
|
|
4286
4431
|
ASSERT_NOK(ex.status());
|
|
@@ -4292,28 +4437,21 @@ TEST_F(DBMultiScanIteratorTest, MixedBoundsTest) {
|
|
|
4292
4437
|
}
|
|
4293
4438
|
iter.reset();
|
|
4294
4439
|
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4440
|
+
// Test multiscan with a range entirely between adjacent files
|
|
4441
|
+
key_ranges[0] = file_meta[0].largestkey + "0";
|
|
4442
|
+
key_ranges[1] = file_meta[0].largestkey + "1";
|
|
4443
|
+
key_ranges[2] = file_meta[1].smallestkey + "0";
|
|
4444
|
+
key_ranges[3] = file_meta[1].largestkey;
|
|
4445
|
+
(*scan_options).clear();
|
|
4446
|
+
scan_options.insert(key_ranges[0], key_ranges[1]);
|
|
4447
|
+
scan_options.insert(key_ranges[2], key_ranges[3]);
|
|
4298
4448
|
iter = dbfull()->NewMultiScan(ro, cfh, scan_options);
|
|
4299
4449
|
try {
|
|
4300
|
-
int idx = 0;
|
|
4301
|
-
int count = 0;
|
|
4302
4450
|
for (auto range : *iter) {
|
|
4303
4451
|
for (auto it : range) {
|
|
4304
|
-
ASSERT_GE(it.first.ToString()
|
|
4305
|
-
scan_options[idx].range.start->ToString()),
|
|
4306
|
-
0);
|
|
4307
|
-
if (scan_options[idx].range.limit) {
|
|
4308
|
-
ASSERT_LT(it.first.ToString().compare(
|
|
4309
|
-
scan_options[idx].range.limit->ToString()),
|
|
4310
|
-
0);
|
|
4311
|
-
}
|
|
4312
|
-
count++;
|
|
4452
|
+
ASSERT_GE(it.first.ToString(), key_ranges[0]);
|
|
4313
4453
|
}
|
|
4314
|
-
idx++;
|
|
4315
4454
|
}
|
|
4316
|
-
ASSERT_EQ(count, 147);
|
|
4317
4455
|
} catch (MultiScanException& ex) {
|
|
4318
4456
|
// Make sure exception contains the status
|
|
4319
4457
|
ASSERT_NOK(ex.status());
|
|
@@ -4325,6 +4463,141 @@ TEST_F(DBMultiScanIteratorTest, MixedBoundsTest) {
|
|
|
4325
4463
|
}
|
|
4326
4464
|
iter.reset();
|
|
4327
4465
|
}
|
|
4466
|
+
|
|
4467
|
+
// This test case tests multiscan in the presence of fragmented range
|
|
4468
|
+
// tombstones in the LSM.
|
|
4469
|
+
TEST_P(DBMultiScanIteratorTest, FragmentedRangeTombstones) {
|
|
4470
|
+
auto options = CurrentOptions();
|
|
4471
|
+
// Compaction may create files 2x the target_file_size_base,
|
|
4472
|
+
// so set this to 50KB so we atleast end up with 2 files of
|
|
4473
|
+
// 100KB
|
|
4474
|
+
options.target_file_size_base = 50 << 10; // 50KB
|
|
4475
|
+
options.compaction_style = kCompactionStyleUniversal;
|
|
4476
|
+
options.num_levels = 50;
|
|
4477
|
+
options.compression = kNoCompression;
|
|
4478
|
+
DestroyAndReopen(options);
|
|
4479
|
+
|
|
4480
|
+
// Setup the LSM as follows -
|
|
4481
|
+
// 1. Ingest a file with 100 keys
|
|
4482
|
+
// 2. Ingest a file with one overlapping key
|
|
4483
|
+
// 3. Do a Put and flush a file to L0 with one overlapping key
|
|
4484
|
+
// 4. Ingest a standalone delete range file that covers the full key space
|
|
4485
|
+
// and a file with the same 100 keys with new values. This will ingest
|
|
4486
|
+
// into L0 due to the presence of an existing file in L0
|
|
4487
|
+
// The final LSM will have an SST in Lmax with 100 keys, and 2 SST files
|
|
4488
|
+
// in Lmax-1 with half the keys each and completely overlapping delete ranges
|
|
4489
|
+
std::unordered_map<std::string, std::string> kvs;
|
|
4490
|
+
auto rnd = Random::GetTLSInstance();
|
|
4491
|
+
auto create_ingestion_data_file_and_update_key_value =
|
|
4492
|
+
[&](const std::string& filename, int start_key, int end_key) {
|
|
4493
|
+
std::unique_ptr<SstFileWriter> writer;
|
|
4494
|
+
writer.reset(new SstFileWriter(EnvOptions(), options));
|
|
4495
|
+
ASSERT_OK(writer->Open(filename));
|
|
4496
|
+
for (int i = start_key; i < end_key; ++i) {
|
|
4497
|
+
auto kiter = kvs.find(Key(i));
|
|
4498
|
+
if (kiter != kvs.end()) {
|
|
4499
|
+
kvs.erase(kiter);
|
|
4500
|
+
}
|
|
4501
|
+
auto res =
|
|
4502
|
+
kvs.emplace(std::make_pair(Key(i), rnd->RandomString(2 << 10)));
|
|
4503
|
+
ASSERT_OK(writer->Put(res.first->first, res.first->second));
|
|
4504
|
+
}
|
|
4505
|
+
ASSERT_OK(writer->Finish());
|
|
4506
|
+
writer.reset();
|
|
4507
|
+
};
|
|
4508
|
+
|
|
4509
|
+
CreateColumnFamilies({"new_cf"}, options);
|
|
4510
|
+
std::string ingest_file = dbname_ + "test.sst";
|
|
4511
|
+
// Write ~200KB data
|
|
4512
|
+
create_ingestion_data_file_and_update_key_value(ingest_file + "_0", 0, 100);
|
|
4513
|
+
create_ingestion_data_file_and_update_key_value(ingest_file + "_1", 50, 51);
|
|
4514
|
+
ColumnFamilyHandle* cfh = handles_[0];
|
|
4515
|
+
IngestExternalFileOptions ifo;
|
|
4516
|
+
Status s = dbfull()->IngestExternalFile(
|
|
4517
|
+
cfh, {ingest_file + "_0", ingest_file + "_1"}, ifo);
|
|
4518
|
+
ASSERT_OK(s);
|
|
4519
|
+
|
|
4520
|
+
ASSERT_OK(Put(0, Key(50), rnd->RandomString(2 << 10)));
|
|
4521
|
+
ASSERT_OK(Flush());
|
|
4522
|
+
|
|
4523
|
+
{
|
|
4524
|
+
std::unique_ptr<SstFileWriter> writer;
|
|
4525
|
+
writer.reset(new SstFileWriter(EnvOptions(), options));
|
|
4526
|
+
ASSERT_OK(writer->Open(ingest_file + "_2"));
|
|
4527
|
+
ASSERT_OK(writer->DeleteRange("a", "z"));
|
|
4528
|
+
ASSERT_OK(writer->Finish());
|
|
4529
|
+
writer.reset();
|
|
4530
|
+
}
|
|
4531
|
+
create_ingestion_data_file_and_update_key_value(ingest_file + "_3", 0, 100);
|
|
4532
|
+
s = dbfull()->IngestExternalFile(
|
|
4533
|
+
cfh, {ingest_file + "_2", ingest_file + "_3"}, ifo);
|
|
4534
|
+
ASSERT_OK(s);
|
|
4535
|
+
|
|
4536
|
+
ASSERT_OK(dbfull()->TEST_WaitForCompact());
|
|
4537
|
+
|
|
4538
|
+
// The first scan range overlaps the DB key range, while the second extends
|
|
4539
|
+
// beyond but overlaps the delete range
|
|
4540
|
+
std::vector<std::string> key_ranges({"key000085", "key000090", "l", "n"});
|
|
4541
|
+
ReadOptions ro;
|
|
4542
|
+
ro.fill_cache = GetParam();
|
|
4543
|
+
MultiScanArgs scan_options(BytewiseComparator());
|
|
4544
|
+
scan_options.insert(key_ranges[0], key_ranges[1]);
|
|
4545
|
+
scan_options.insert(key_ranges[2], key_ranges[3]);
|
|
4546
|
+
std::unique_ptr<MultiScan> iter =
|
|
4547
|
+
dbfull()->NewMultiScan(ro, cfh, scan_options);
|
|
4548
|
+
try {
|
|
4549
|
+
int i = 0;
|
|
4550
|
+
int count = 0;
|
|
4551
|
+
for (auto range : *iter) {
|
|
4552
|
+
for (auto it : range) {
|
|
4553
|
+
ASSERT_GE(it.first.ToString(), key_ranges[i]);
|
|
4554
|
+
ASSERT_LT(it.first.ToString(), key_ranges[i + 1]);
|
|
4555
|
+
auto kiter = kvs.find(it.first.ToString());
|
|
4556
|
+
ASSERT_NE(kiter, kvs.end());
|
|
4557
|
+
ASSERT_EQ(kiter->second, it.second.ToString());
|
|
4558
|
+
count++;
|
|
4559
|
+
}
|
|
4560
|
+
i += 2;
|
|
4561
|
+
}
|
|
4562
|
+
ASSERT_EQ(i, 4);
|
|
4563
|
+
ASSERT_EQ(count, 5);
|
|
4564
|
+
} catch (MultiScanException& ex) {
|
|
4565
|
+
ASSERT_OK(ex.status());
|
|
4566
|
+
}
|
|
4567
|
+
iter.reset();
|
|
4568
|
+
|
|
4569
|
+
// The second scan range start overlaps the delete range in the first file
|
|
4570
|
+
// in Lmax-1, while the end overlaps the keys in the second file
|
|
4571
|
+
(*scan_options).clear();
|
|
4572
|
+
key_ranges[0] = "key000010";
|
|
4573
|
+
key_ranges[1] = "key000020";
|
|
4574
|
+
key_ranges[2] = "key0000500";
|
|
4575
|
+
key_ranges[3] = "key000060";
|
|
4576
|
+
scan_options.insert(key_ranges[0], key_ranges[1]);
|
|
4577
|
+
scan_options.insert(key_ranges[2], key_ranges[3]);
|
|
4578
|
+
iter = dbfull()->NewMultiScan(ro, cfh, scan_options);
|
|
4579
|
+
try {
|
|
4580
|
+
int i = 0;
|
|
4581
|
+
int count = 0;
|
|
4582
|
+
for (auto range : *iter) {
|
|
4583
|
+
for (auto it : range) {
|
|
4584
|
+
ASSERT_GE(it.first.ToString(), key_ranges[i]);
|
|
4585
|
+
ASSERT_LT(it.first.ToString(), key_ranges[i + 1]);
|
|
4586
|
+
auto kiter = kvs.find(it.first.ToString());
|
|
4587
|
+
ASSERT_NE(kiter, kvs.end());
|
|
4588
|
+
ASSERT_EQ(kiter->second, it.second.ToString());
|
|
4589
|
+
count++;
|
|
4590
|
+
}
|
|
4591
|
+
i += 2;
|
|
4592
|
+
}
|
|
4593
|
+
ASSERT_EQ(i, 4);
|
|
4594
|
+
ASSERT_EQ(count, 19);
|
|
4595
|
+
} catch (MultiScanException& ex) {
|
|
4596
|
+
ASSERT_OK(ex.status());
|
|
4597
|
+
}
|
|
4598
|
+
iter.reset();
|
|
4599
|
+
}
|
|
4600
|
+
|
|
4328
4601
|
} // namespace ROCKSDB_NAMESPACE
|
|
4329
4602
|
|
|
4330
4603
|
int main(int argc, char** argv) {
|
|
@@ -339,6 +339,135 @@ TEST_F(DBMemTableTest, ColumnFamilyId) {
|
|
|
339
339
|
}
|
|
340
340
|
}
|
|
341
341
|
|
|
342
|
+
class DBMemTableTestForSeek : public DBMemTableTest,
|
|
343
|
+
virtual public ::testing::WithParamInterface<
|
|
344
|
+
std::tuple<bool, bool, bool>> {};
|
|
345
|
+
|
|
346
|
+
TEST_P(DBMemTableTestForSeek, IntegrityChecks) {
|
|
347
|
+
// Validate key corruption could be detected during seek.
|
|
348
|
+
// We insert many keys into skiplist. Then we corrupt the each key one at a
|
|
349
|
+
// time. With memtable_veirfy_per_key_checksum_on_seek enabled, when the
|
|
350
|
+
// corrupted key is searched, the checksum of every key visited during the
|
|
351
|
+
// seek is validated. It will report data corruption. Otherwise seek returns
|
|
352
|
+
// not found.
|
|
353
|
+
auto allow_data_in_error = std::get<0>(GetParam());
|
|
354
|
+
Options options = CurrentOptions();
|
|
355
|
+
options.allow_data_in_errors = allow_data_in_error;
|
|
356
|
+
options.paranoid_memory_checks = std::get<1>(GetParam());
|
|
357
|
+
options.memtable_veirfy_per_key_checksum_on_seek = std::get<2>(GetParam());
|
|
358
|
+
options.memtable_protection_bytes_per_key = 8;
|
|
359
|
+
DestroyAndReopen(options);
|
|
360
|
+
|
|
361
|
+
// capture the data pointer of all of the keys
|
|
362
|
+
std::vector<char*> raw_data_pointer;
|
|
363
|
+
|
|
364
|
+
// Insert enough keys, so memtable would create multiple levels.
|
|
365
|
+
auto key_count = 100;
|
|
366
|
+
for (int i = 0; i < key_count; i++) {
|
|
367
|
+
// The last digit of the key will be corrupted from value 0 to value 5
|
|
368
|
+
ASSERT_OK(Put(Key(i * 10), "val0"));
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
ReadOptions rops;
|
|
372
|
+
|
|
373
|
+
// Iterate all the keys to get key pointers
|
|
374
|
+
SyncPoint::GetInstance()->DisableProcessing();
|
|
375
|
+
SyncPoint::GetInstance()->SetCallBack("InlineSkipList::Iterator::Next::key",
|
|
376
|
+
[&raw_data_pointer](void* key) {
|
|
377
|
+
auto p = static_cast<char*>(key);
|
|
378
|
+
raw_data_pointer.push_back(p);
|
|
379
|
+
});
|
|
380
|
+
SyncPoint::GetInstance()->EnableProcessing();
|
|
381
|
+
|
|
382
|
+
{
|
|
383
|
+
std::unique_ptr<Iterator> iter{db_->NewIterator(rops)};
|
|
384
|
+
iter->Seek(Key(0));
|
|
385
|
+
while (iter->Valid()) {
|
|
386
|
+
ASSERT_OK(iter->status());
|
|
387
|
+
iter->Next();
|
|
388
|
+
}
|
|
389
|
+
// check status after valid returned false.
|
|
390
|
+
auto status = iter->status();
|
|
391
|
+
ASSERT_TRUE(status.ok());
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
SyncPoint::GetInstance()->DisableProcessing();
|
|
395
|
+
SyncPoint::GetInstance()->ClearAllCallBacks();
|
|
396
|
+
|
|
397
|
+
ASSERT_EQ(raw_data_pointer.size(), key_count);
|
|
398
|
+
|
|
399
|
+
bool enable_key_validation_on_seek =
|
|
400
|
+
options.memtable_veirfy_per_key_checksum_on_seek;
|
|
401
|
+
|
|
402
|
+
// For each key, corrupt it, validate corruption is detected correctly, then
|
|
403
|
+
// revert it.
|
|
404
|
+
for (int i = 0; i < key_count; i++) {
|
|
405
|
+
std::string key_to_corrupt = Key(i * 10);
|
|
406
|
+
raw_data_pointer[i][key_to_corrupt.size()] = '5';
|
|
407
|
+
|
|
408
|
+
auto corrupted_key = key_to_corrupt;
|
|
409
|
+
corrupted_key.data()[key_to_corrupt.size() - 1] = '5';
|
|
410
|
+
auto corrupted_key_slice =
|
|
411
|
+
Slice(corrupted_key.data(), corrupted_key.length());
|
|
412
|
+
auto corrupted_key_hex = corrupted_key_slice.ToString(/*hex=*/true);
|
|
413
|
+
|
|
414
|
+
{
|
|
415
|
+
// Test Get API
|
|
416
|
+
std::string val;
|
|
417
|
+
auto status = db_->Get(rops, key_to_corrupt, &val);
|
|
418
|
+
if (enable_key_validation_on_seek) {
|
|
419
|
+
ASSERT_TRUE(status.IsCorruption()) << key_to_corrupt;
|
|
420
|
+
ASSERT_EQ(
|
|
421
|
+
status.ToString().find(corrupted_key_hex) != std::string::npos,
|
|
422
|
+
allow_data_in_error)
|
|
423
|
+
<< status.ToString() << "\n"
|
|
424
|
+
<< corrupted_key_hex;
|
|
425
|
+
} else {
|
|
426
|
+
ASSERT_TRUE(status.IsNotFound());
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
{
|
|
431
|
+
// Test MultiGet API
|
|
432
|
+
std::vector<std::string> vals;
|
|
433
|
+
std::vector<Status> statuses = db_->MultiGet(
|
|
434
|
+
rops, {db_->DefaultColumnFamily()}, {key_to_corrupt}, &vals, nullptr);
|
|
435
|
+
if (enable_key_validation_on_seek) {
|
|
436
|
+
ASSERT_TRUE(statuses[0].IsCorruption());
|
|
437
|
+
ASSERT_EQ(
|
|
438
|
+
statuses[0].ToString().find(corrupted_key_hex) != std::string::npos,
|
|
439
|
+
allow_data_in_error);
|
|
440
|
+
} else {
|
|
441
|
+
ASSERT_TRUE(statuses[0].IsNotFound());
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
{
|
|
446
|
+
// Test Iterator Seek API
|
|
447
|
+
std::unique_ptr<Iterator> iter{db_->NewIterator(rops)};
|
|
448
|
+
ASSERT_OK(iter->status());
|
|
449
|
+
iter->Seek(key_to_corrupt);
|
|
450
|
+
auto status = iter->status();
|
|
451
|
+
if (enable_key_validation_on_seek) {
|
|
452
|
+
ASSERT_TRUE(status.IsCorruption());
|
|
453
|
+
ASSERT_EQ(
|
|
454
|
+
status.ToString().find(corrupted_key_hex) != std::string::npos,
|
|
455
|
+
allow_data_in_error);
|
|
456
|
+
} else {
|
|
457
|
+
ASSERT_FALSE(iter->Valid());
|
|
458
|
+
ASSERT_FALSE(status.ok());
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// revert the key corruption.
|
|
463
|
+
raw_data_pointer[i][key_to_corrupt.size()] = '0';
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
INSTANTIATE_TEST_CASE_P(DBMemTableTestForSeek, DBMemTableTestForSeek,
|
|
468
|
+
::testing::Combine(::testing::Bool(), ::testing::Bool(),
|
|
469
|
+
::testing::Bool()));
|
|
470
|
+
|
|
342
471
|
TEST_F(DBMemTableTest, IntegrityChecks) {
|
|
343
472
|
// We insert keys key000000, key000001 and key000002 into skiplist at fixed
|
|
344
473
|
// height 1 (smallest height). Then we corrupt the second key to aey000001 to
|
|
@@ -1937,6 +1937,70 @@ TEST_F(DBSSTTest, DBWithSFMForBlobFilesAtomicFlush) {
|
|
|
1937
1937
|
ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->ClearAllCallBacks();
|
|
1938
1938
|
}
|
|
1939
1939
|
|
|
1940
|
+
TEST_F(DBSSTTest, SstGetFileSizeFails) {
|
|
1941
|
+
// Build an SST file
|
|
1942
|
+
ASSERT_OK(Put("x", "zaphod"));
|
|
1943
|
+
ASSERT_OK(Flush());
|
|
1944
|
+
std::vector<LiveFileMetaData> metadata;
|
|
1945
|
+
db_->GetLiveFilesMetaData(&metadata);
|
|
1946
|
+
ASSERT_EQ(1U, metadata.size());
|
|
1947
|
+
std::string filename = dbname_ + metadata[0].name;
|
|
1948
|
+
|
|
1949
|
+
// Prepare for fault injection
|
|
1950
|
+
std::shared_ptr<FaultInjectionTestFS> fault_fs =
|
|
1951
|
+
std::make_shared<FaultInjectionTestFS>(
|
|
1952
|
+
CurrentOptions().env->GetFileSystem());
|
|
1953
|
+
std::unique_ptr<Env> fault_fs_env(NewCompositeEnv(fault_fs));
|
|
1954
|
+
Options options = CurrentOptions();
|
|
1955
|
+
options.env = fault_fs_env.get();
|
|
1956
|
+
options.paranoid_checks = false; // don't check file sizes on open
|
|
1957
|
+
|
|
1958
|
+
for (int i = 0; i < 4; i++) {
|
|
1959
|
+
SCOPED_TRACE("Iteration = " + std::to_string(i));
|
|
1960
|
+
fault_fs->SetFailRandomAccessGetFileSizeSst(false);
|
|
1961
|
+
fault_fs->SetFailFilesystemGetFileSizeSst(false);
|
|
1962
|
+
Close();
|
|
1963
|
+
|
|
1964
|
+
if (i == 1) {
|
|
1965
|
+
// Just FSRandomAccessFile::GetFileSize fails, which should be worked
|
|
1966
|
+
// around
|
|
1967
|
+
fault_fs->SetFailRandomAccessGetFileSizeSst(true);
|
|
1968
|
+
} else if (i == 2) {
|
|
1969
|
+
// FileSystem::GetFileSize fails, which should be worked around if
|
|
1970
|
+
// FSRandomAccessFile::GetFileSize is supported
|
|
1971
|
+
fault_fs->SetFailFilesystemGetFileSizeSst(true);
|
|
1972
|
+
} else if (i == 3) {
|
|
1973
|
+
// Both GetFileSize APIs fail with an IOError
|
|
1974
|
+
fault_fs->SetFailRandomAccessGetFileSizeSst(true);
|
|
1975
|
+
fault_fs->SetFailFilesystemGetFileSizeSst(true);
|
|
1976
|
+
}
|
|
1977
|
+
|
|
1978
|
+
ASSERT_OK(TryReopen(options));
|
|
1979
|
+
std::string value;
|
|
1980
|
+
Status get_status = db_->Get({}, "x", &value);
|
|
1981
|
+
if (i < 2) {
|
|
1982
|
+
ASSERT_OK(get_status);
|
|
1983
|
+
} else if (i == 2) {
|
|
1984
|
+
if (encrypted_env_) {
|
|
1985
|
+
// Can't recover because RandomAccessFile::GetFileSize is not supported
|
|
1986
|
+
// on EncryptedEnv
|
|
1987
|
+
// Fail with propagated IOError. (Not Corruption nor NotSupported!)
|
|
1988
|
+
ASSERT_EQ(get_status.code(), Status::Code::kIOError);
|
|
1989
|
+
ASSERT_STREQ(get_status.getState(), "FileSystem::GetFileSize failed");
|
|
1990
|
+
} else {
|
|
1991
|
+
// Never sees the FileSystem::GetFileSize failure
|
|
1992
|
+
ASSERT_OK(get_status);
|
|
1993
|
+
}
|
|
1994
|
+
} else {
|
|
1995
|
+
ASSERT_EQ(i, 3);
|
|
1996
|
+
// Fail with propagated IOError. (Not Corruption nor NotSupported!)
|
|
1997
|
+
ASSERT_EQ(get_status.code(), Status::Code::kIOError);
|
|
1998
|
+
ASSERT_STREQ(get_status.getState(), "FileSystem::GetFileSize failed");
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
2001
|
+
Close();
|
|
2002
|
+
}
|
|
2003
|
+
|
|
1940
2004
|
} // namespace ROCKSDB_NAMESPACE
|
|
1941
2005
|
|
|
1942
2006
|
int main(int argc, char** argv) {
|