@nxtedition/rocksdb 14.0.0 → 15.1.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.
Files changed (102) hide show
  1. package/binding.cc +52 -179
  2. package/deps/rocksdb/rocksdb/BUCK +7 -0
  3. package/deps/rocksdb/rocksdb/CMakeLists.txt +29 -14
  4. package/deps/rocksdb/rocksdb/Directory.Build.props +9 -0
  5. package/deps/rocksdb/rocksdb/Makefile +6 -1
  6. package/deps/rocksdb/rocksdb/cache/secondary_cache_adapter.cc +4 -4
  7. package/deps/rocksdb/rocksdb/ccache_msvc_compiler.bat +1 -0
  8. package/deps/rocksdb/rocksdb/db/compaction/compaction.cc +17 -3
  9. package/deps/rocksdb/rocksdb/db/compaction/compaction.h +8 -3
  10. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.h +10 -0
  11. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +522 -60
  12. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.h +69 -10
  13. package/deps/rocksdb/rocksdb/db/compaction/compaction_job_test.cc +443 -0
  14. package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.cc +4 -2
  15. package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.h +14 -3
  16. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.cc +5 -5
  17. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_fifo.cc +3 -6
  18. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_level.cc +1 -1
  19. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_test.cc +28 -5
  20. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.cc +4 -4
  21. package/deps/rocksdb/rocksdb/db/compaction/compaction_service_job.cc +6 -3
  22. package/deps/rocksdb/rocksdb/db/compaction/compaction_service_test.cc +455 -98
  23. package/deps/rocksdb/rocksdb/db/compaction/subcompaction_state.cc +4 -2
  24. package/deps/rocksdb/rocksdb/db/compaction/subcompaction_state.h +13 -1
  25. package/deps/rocksdb/rocksdb/db/db_flush_test.cc +146 -0
  26. package/deps/rocksdb/rocksdb/db/db_follower_test.cc +2 -2
  27. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +6 -0
  28. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +5 -2
  29. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +18 -19
  30. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_files.cc +5 -0
  31. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_secondary.cc +665 -14
  32. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_secondary.h +83 -0
  33. package/deps/rocksdb/rocksdb/db/db_iterator_test.cc +68 -0
  34. package/deps/rocksdb/rocksdb/db/db_rate_limiter_test.cc +101 -0
  35. package/deps/rocksdb/rocksdb/db/dbformat_test.cc +44 -0
  36. package/deps/rocksdb/rocksdb/db/external_sst_file_ingestion_job.cc +1 -2
  37. package/deps/rocksdb/rocksdb/db/external_sst_file_test.cc +22 -5
  38. package/deps/rocksdb/rocksdb/db/log_reader.h +4 -4
  39. package/deps/rocksdb/rocksdb/db/log_writer.h +1 -1
  40. package/deps/rocksdb/rocksdb/db/merge_helper.h +1 -1
  41. package/deps/rocksdb/rocksdb/db/version_edit.cc +477 -139
  42. package/deps/rocksdb/rocksdb/db/version_edit.h +228 -8
  43. package/deps/rocksdb/rocksdb/db/version_edit_test.cc +333 -0
  44. package/deps/rocksdb/rocksdb/db/write_thread.h +1 -1
  45. package/deps/rocksdb/rocksdb/db_stress_tool/CMakeLists.txt +1 -0
  46. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.cc +247 -32
  47. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +3 -0
  48. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_compaction_service.cc +61 -0
  49. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_compaction_service.h +17 -28
  50. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +16 -0
  51. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_listener.h +6 -1
  52. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_shared_state.h +46 -18
  53. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +18 -1
  54. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.h +8 -7
  55. package/deps/rocksdb/rocksdb/db_stress_tool/expected_value.h +4 -4
  56. package/deps/rocksdb/rocksdb/env/fs_posix.cc +1 -0
  57. package/deps/rocksdb/rocksdb/file/filename.cc +40 -0
  58. package/deps/rocksdb/rocksdb/file/filename.h +14 -1
  59. package/deps/rocksdb/rocksdb/file/writable_file_writer.cc +4 -3
  60. package/deps/rocksdb/rocksdb/file/writable_file_writer.h +2 -1
  61. package/deps/rocksdb/rocksdb/include/rocksdb/db.h +26 -7
  62. package/deps/rocksdb/rocksdb/include/rocksdb/file_system.h +5 -3
  63. package/deps/rocksdb/rocksdb/include/rocksdb/options.h +59 -0
  64. package/deps/rocksdb/rocksdb/include/rocksdb/statistics.h +3 -0
  65. package/deps/rocksdb/rocksdb/include/rocksdb/table.h +24 -0
  66. package/deps/rocksdb/rocksdb/include/rocksdb/types.h +2 -1
  67. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/stackable_db.h +4 -0
  68. package/deps/rocksdb/rocksdb/include/rocksdb/version.h +13 -8
  69. package/deps/rocksdb/rocksdb/monitoring/statistics.cc +1 -0
  70. package/deps/rocksdb/rocksdb/options/options_settable_test.cc +2 -0
  71. package/deps/rocksdb/rocksdb/options/options_test.cc +5 -0
  72. package/deps/rocksdb/rocksdb/src.mk +2 -0
  73. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.cc +73 -16
  74. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.h +10 -5
  75. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_factory.cc +32 -0
  76. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.cc +18 -27
  77. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.h +0 -3
  78. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.h +5 -1
  79. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_test.cc +708 -217
  80. package/deps/rocksdb/rocksdb/table/block_based/block_builder.cc +11 -6
  81. package/deps/rocksdb/rocksdb/table/block_based/block_builder.h +5 -3
  82. package/deps/rocksdb/rocksdb/table/block_based/block_prefetcher.cc +27 -19
  83. package/deps/rocksdb/rocksdb/table/block_based/index_builder.cc +24 -6
  84. package/deps/rocksdb/rocksdb/table/block_based/index_builder.h +51 -18
  85. package/deps/rocksdb/rocksdb/table/block_based/index_builder_test.cc +183 -0
  86. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block_test.cc +4 -2
  87. package/deps/rocksdb/rocksdb/table/block_based/partitioned_index_iterator.h +0 -2
  88. package/deps/rocksdb/rocksdb/table/block_based/user_defined_index_wrapper.h +8 -3
  89. package/deps/rocksdb/rocksdb/table/plain/plain_table_reader.cc +3 -1
  90. package/deps/rocksdb/rocksdb/table/table_test.cc +222 -36
  91. package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +246 -6
  92. package/deps/rocksdb/rocksdb/tools/ldb_cmd.cc +86 -0
  93. package/deps/rocksdb/rocksdb/tools/ldb_cmd_impl.h +21 -0
  94. package/deps/rocksdb/rocksdb/tools/ldb_tool.cc +1 -0
  95. package/deps/rocksdb/rocksdb/util/file_reader_writer_test.cc +1 -1
  96. package/deps/rocksdb/rocksdb/utilities/backup/backup_engine_test.cc +1 -0
  97. package/deps/rocksdb/rocksdb/utilities/transactions/lock/point/point_lock_manager.cc +0 -2
  98. package/deps/rocksdb/rocksdb/utilities/transactions/write_prepared_txn_db.cc +12 -12
  99. package/index.js +27 -37
  100. package/package.json +1 -1
  101. package/prebuilds/darwin-arm64/@nxtedition+rocksdb.node +0 -0
  102. package/prebuilds/linux-x64/@nxtedition+rocksdb.node +0 -0
@@ -246,6 +246,70 @@ class BlockBasedTableReaderBaseTest : public testing::Test {
246
246
  }
247
247
  };
248
248
 
249
+ struct BlockBasedTableReaderTestParam {
250
+ BlockBasedTableReaderTestParam(
251
+ CompressionType _compression_type, bool _use_direct_reads,
252
+ BlockBasedTableOptions::IndexType _index_type, bool _no_block_cache,
253
+ test::UserDefinedTimestampTestMode _udt_test_mode,
254
+ uint32_t _compression_parallel_threads, uint32_t _compression_dict_bytes,
255
+ bool _same_key_diff_ts, const Comparator* _comparator, bool _fill_cache,
256
+ bool _use_async_io, bool _block_align, size_t _super_block_alignment_size,
257
+ size_t _super_block_alignment_space_overhead_ratio)
258
+ : compression_type(_compression_type),
259
+ use_direct_reads(_use_direct_reads),
260
+ index_type(_index_type),
261
+ no_block_cache(_no_block_cache),
262
+ udt_test_mode(_udt_test_mode),
263
+ compression_parallel_threads(_compression_parallel_threads),
264
+ compression_dict_bytes(_compression_dict_bytes),
265
+ same_key_diff_ts(_same_key_diff_ts),
266
+ comparator(_comparator),
267
+ fill_cache(_fill_cache),
268
+ use_async_io(_use_async_io),
269
+ block_align(_block_align),
270
+ super_block_alignment_size(_super_block_alignment_size),
271
+ super_block_alignment_space_overhead_ratio(
272
+ _super_block_alignment_space_overhead_ratio) {}
273
+
274
+ CompressionType compression_type;
275
+ bool use_direct_reads;
276
+ BlockBasedTableOptions::IndexType index_type;
277
+ bool no_block_cache;
278
+ test::UserDefinedTimestampTestMode udt_test_mode;
279
+ uint32_t compression_parallel_threads;
280
+ uint32_t compression_dict_bytes;
281
+ bool same_key_diff_ts;
282
+ const Comparator* comparator;
283
+ bool fill_cache;
284
+ bool use_async_io;
285
+ bool block_align;
286
+ size_t super_block_alignment_size;
287
+ size_t super_block_alignment_space_overhead_ratio;
288
+ };
289
+
290
+ // Define operator<< for SpotLockManagerTestParam to stop valgrind from
291
+ // complaining uinitialized value when printing SpotLockManagerTestParam.
292
+ std::ostream& operator<<(std::ostream& os,
293
+ const BlockBasedTableReaderTestParam& param) {
294
+ os << "compression_type: " << CompressionTypeToString(param.compression_type)
295
+ << " use_direct_reads: " << param.use_direct_reads
296
+ << " index_type: " << static_cast<int>(param.index_type)
297
+ << " no_block_cache: " << param.no_block_cache
298
+ << " udt_test_mode: " << static_cast<int>(param.udt_test_mode)
299
+ << " compression_parallel_threads: " << param.compression_parallel_threads
300
+ << " compression_dict_bytes: " << param.compression_dict_bytes
301
+ << " same_key_diff_ts: " << param.same_key_diff_ts
302
+ << " comparator: " << param.comparator->Name()
303
+ << " fill_cache: " << param.fill_cache
304
+ << " use_async_io: " << param.use_async_io
305
+ << " block_align: " << param.block_align
306
+ << " super_block_alignment_size: " << param.super_block_alignment_size
307
+ << " super_block_alignment_space_overhead_ratio: "
308
+ << param.super_block_alignment_space_overhead_ratio;
309
+
310
+ return os;
311
+ }
312
+
249
313
  // Param 1: compression type
250
314
  // Param 2: whether to use direct reads
251
315
  // Param 3: Block Based Table Index type
@@ -265,28 +329,30 @@ class BlockBasedTableReaderBaseTest : public testing::Test {
265
329
  // Param 9: test both the default comparator and a reverse comparator.
266
330
  class BlockBasedTableReaderTest
267
331
  : public BlockBasedTableReaderBaseTest,
268
- public testing::WithParamInterface<
269
- std::tuple<CompressionType, bool, BlockBasedTableOptions::IndexType,
270
- bool, test::UserDefinedTimestampTestMode, uint32_t,
271
- uint32_t, bool, const Comparator*>> {
332
+ public testing::WithParamInterface<BlockBasedTableReaderTestParam> {
272
333
  protected:
273
334
  void SetUp() override {
274
- compression_type_ = std::get<0>(GetParam());
275
- use_direct_reads_ = std::get<1>(GetParam());
276
- test::UserDefinedTimestampTestMode udt_test_mode = std::get<4>(GetParam());
335
+ auto param = GetParam();
336
+ compression_type_ = param.compression_type;
337
+ use_direct_reads_ = param.use_direct_reads;
338
+ test::UserDefinedTimestampTestMode udt_test_mode = param.udt_test_mode;
277
339
  udt_enabled_ = test::IsUDTEnabled(udt_test_mode);
278
340
  persist_udt_ = test::ShouldPersistUDT(udt_test_mode);
279
- compression_parallel_threads_ = std::get<5>(GetParam());
280
- compression_dict_bytes_ = std::get<6>(GetParam());
281
- same_key_diff_ts_ = std::get<7>(GetParam());
282
- comparator_ = std::get<8>(GetParam());
341
+ compression_parallel_threads_ = param.compression_parallel_threads;
342
+ compression_dict_bytes_ = param.compression_dict_bytes;
343
+ same_key_diff_ts_ = param.same_key_diff_ts;
344
+ comparator_ = param.comparator;
283
345
  BlockBasedTableReaderBaseTest::SetUp();
284
346
  }
285
347
 
286
348
  void ConfigureTableFactory() override {
287
349
  BlockBasedTableOptions opts;
288
- opts.index_type = std::get<2>(GetParam());
289
- opts.no_block_cache = std::get<3>(GetParam());
350
+ auto param = GetParam();
351
+ opts.index_type = param.index_type;
352
+ opts.no_block_cache = param.no_block_cache;
353
+ opts.super_block_alignment_size = param.super_block_alignment_size;
354
+ opts.super_block_alignment_space_overhead_ratio =
355
+ param.super_block_alignment_space_overhead_ratio;
290
356
  opts.filter_policy.reset(NewBloomFilterPolicy(10, false));
291
357
  opts.partition_filters =
292
358
  opts.index_type ==
@@ -1009,184 +1075,287 @@ TEST_P(BlockBasedTableReaderTestVerifyChecksum, ChecksumMismatch) {
1009
1075
  ASSERT_EQ(s.code(), Status::kCorruption);
1010
1076
  }
1011
1077
 
1078
+ class BlockBasedTableReaderMultiScanTest : public BlockBasedTableReaderTest {
1079
+ public:
1080
+ void SetUp() override {
1081
+ BlockBasedTableReaderTest::SetUp();
1082
+ options_.comparator = comparator_;
1083
+ }
1084
+ };
1085
+
1086
+ class BlockBasedTableReaderMultiScanAsyncIOTest
1087
+ : public BlockBasedTableReaderMultiScanTest {};
1088
+
1012
1089
  // TODO: test no block cache case
1013
- TEST_P(BlockBasedTableReaderTest, MultiScanPrepare) {
1014
- std::ostringstream param_trace;
1015
- param_trace << "[MultiScanPrepare] Test params: " << "CompressionType="
1016
- << CompressionTypeToString(compression_type_)
1017
- << ", UseDirectReads=" << (use_direct_reads_ ? "true" : "false")
1018
- << ", UDTEnabled=" << (udt_enabled_ ? "true" : "false")
1019
- << ", PersistUDT=" << (persist_udt_ ? "true" : "false")
1020
- << ", CompressionParallelThreads="
1021
- << compression_parallel_threads_
1022
- << ", CompressionDictBytes=" << compression_dict_bytes_
1023
- << ", SameKeyDiffTs=" << (same_key_diff_ts_ ? "true" : "false");
1024
- SCOPED_TRACE(param_trace.str());
1025
-
1026
- for (bool fill_cache : {false, true}) {
1027
- SCOPED_TRACE(std::string("fill_cache=") + std::to_string(fill_cache));
1028
- for (bool use_async_io : {false,
1029
- #ifdef ROCKSDB_IOURING_PRESENT
1030
- true
1031
- #endif
1032
- }) {
1033
- SCOPED_TRACE(std::string("use_async_io=") + std::to_string(use_async_io));
1034
- Options options;
1035
- options.statistics = CreateDBStatistics();
1036
- options.comparator = comparator_;
1037
- std::shared_ptr<FileSystem> fs = options.env->GetFileSystem();
1038
- ReadOptions read_opts;
1039
- read_opts.fill_cache = fill_cache;
1040
- size_t ts_sz = options.comparator->timestamp_size();
1041
- std::vector<std::pair<std::string, std::string>> kv =
1042
- BlockBasedTableReaderBaseTest::GenerateKVMap(
1043
- 100 /* num_block */,
1044
- true /* mixed_with_human_readable_string_value */, ts_sz,
1045
- same_key_diff_ts_, comparator_);
1046
- std::string table_name = "BlockBasedTableReaderTest_NewIterator" +
1047
- CompressionTypeToString(compression_type_) +
1048
- "_async" + std::to_string(use_async_io);
1049
- ImmutableOptions ioptions(options);
1050
- CreateTable(table_name, ioptions, compression_type_, kv,
1051
- compression_parallel_threads_, compression_dict_bytes_);
1052
-
1053
- std::unique_ptr<BlockBasedTable> table;
1054
- FileOptions foptions;
1055
- foptions.use_direct_reads = use_direct_reads_;
1056
- InternalKeyComparator comparator(options.comparator);
1057
- NewBlockBasedTableReader(
1058
- foptions, ioptions, comparator, table_name, &table,
1059
- true /* bool prefetch_index_and_filter_in_cache */,
1060
- nullptr /* status */, persist_udt_);
1061
-
1062
- // 1. Should coalesce into a single I/O
1063
- std::unique_ptr<InternalIterator> iter;
1064
- iter.reset(table->NewIterator(
1065
- read_opts, options_.prefix_extractor.get(), /*arena=*/nullptr,
1066
- /*skip_filters=*/false, TableReaderCaller::kUncategorized));
1067
-
1068
- MultiScanArgs scan_options(comparator_);
1069
- scan_options.use_async_io = use_async_io;
1070
- scan_options.insert(ExtractUserKey(kv[0].first),
1071
- ExtractUserKey(kv[kEntriesPerBlock].first));
1072
- scan_options.insert(ExtractUserKey(kv[2 * kEntriesPerBlock].first),
1073
- ExtractUserKey(kv[3 * kEntriesPerBlock].first));
1074
- auto read_count_before =
1075
- options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT);
1076
-
1077
- iter->Prepare(&scan_options);
1078
- iter->Seek(kv[0].first);
1079
- for (size_t i = 0; i < kEntriesPerBlock + 1; ++i) {
1080
- ASSERT_TRUE(iter->status().ok()) << iter->status().ToString();
1081
- ASSERT_TRUE(iter->Valid()) << i;
1082
- ASSERT_EQ(iter->key().ToString(), kv[i].first);
1083
- iter->Next();
1084
- }
1085
- // Iter may still be valid after scan range. Upper layer (DBIter) handles
1086
- // exact upper bound checking. So we don't check !iter->Valid() here.
1087
- ASSERT_OK(iter->status());
1088
- iter->Seek(kv[2 * kEntriesPerBlock].first);
1089
- for (size_t i = 2 * kEntriesPerBlock; i < 3 * kEntriesPerBlock; ++i) {
1090
- ASSERT_TRUE(iter->Valid());
1091
- ASSERT_EQ(iter->key().ToString(), kv[i].first);
1092
- iter->Next();
1093
- }
1094
- ASSERT_OK(iter->status());
1095
- auto read_count_after =
1096
- options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT);
1097
- ASSERT_EQ(read_count_before + 1, read_count_after);
1090
+ TEST_P(BlockBasedTableReaderMultiScanAsyncIOTest, MultiScanPrepare) {
1091
+ auto param = GetParam();
1092
+ auto fill_cache = param.fill_cache;
1093
+ auto use_async_io = param.use_async_io;
1098
1094
 
1099
- // 2. No IO coalesce, should do MultiRead/ReadAsync with 2 read requests.
1100
- iter.reset(table->NewIterator(
1101
- read_opts, options_.prefix_extractor.get(), /*arena=*/nullptr,
1102
- /*skip_filters=*/false, TableReaderCaller::kUncategorized));
1103
- scan_options = MultiScanArgs(comparator_);
1104
- scan_options.insert(ExtractUserKey(kv[70 * kEntriesPerBlock].first),
1105
- ExtractUserKey(kv[75 * kEntriesPerBlock].first));
1106
- scan_options.insert(ExtractUserKey(kv[90 * kEntriesPerBlock].first),
1107
- ExtractUserKey(kv[95 * kEntriesPerBlock].first));
1108
-
1109
- read_count_before =
1110
- options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT);
1111
- iter->Prepare(&scan_options);
1112
-
1113
- iter->Seek(kv[70 * kEntriesPerBlock].first);
1114
- for (size_t i = 70 * kEntriesPerBlock; i < 75 * kEntriesPerBlock; ++i) {
1115
- ASSERT_TRUE(iter->Valid());
1116
- ASSERT_EQ(iter->key().ToString(), kv[i].first);
1117
- iter->Next();
1118
- }
1119
- ASSERT_OK(iter->status());
1120
- iter->Seek(kv[90 * kEntriesPerBlock].first);
1121
- for (size_t i = 90 * kEntriesPerBlock; i < 95 * kEntriesPerBlock; ++i) {
1122
- ASSERT_TRUE(iter->Valid());
1123
- ASSERT_EQ(iter->key().ToString(), kv[i].first);
1124
- iter->Next();
1125
- }
1126
- ASSERT_OK(iter->status());
1095
+ options_.statistics = CreateDBStatistics();
1096
+ std::shared_ptr<FileSystem> fs = options_.env->GetFileSystem();
1097
+ ReadOptions read_opts;
1098
+ read_opts.fill_cache = fill_cache;
1099
+ size_t ts_sz = options_.comparator->timestamp_size();
1100
+ std::vector<std::pair<std::string, std::string>> kv =
1101
+ BlockBasedTableReaderBaseTest::GenerateKVMap(
1102
+ 100 /* num_block */,
1103
+ true /* mixed_with_human_readable_string_value */, ts_sz,
1104
+ same_key_diff_ts_, comparator_);
1105
+ std::string table_name = "BlockBasedTableReaderTest_NewIterator" +
1106
+ CompressionTypeToString(compression_type_) +
1107
+ "_async" + std::to_string(use_async_io);
1108
+ ImmutableOptions ioptions(options_);
1109
+ // Only insert 60 out of 100 blocks
1110
+ CreateTable(table_name, ioptions, compression_type_,
1111
+ std::vector<std::pair<std::string, std::string>>{
1112
+ kv.begin() + 20 * kEntriesPerBlock,
1113
+ kv.begin() + 80 * kEntriesPerBlock},
1114
+ compression_parallel_threads_, compression_dict_bytes_);
1115
+
1116
+ std::unique_ptr<BlockBasedTable> table;
1117
+ FileOptions foptions;
1118
+ foptions.use_direct_reads = use_direct_reads_;
1119
+ InternalKeyComparator comparator(options_.comparator);
1120
+ NewBlockBasedTableReader(foptions, ioptions, comparator, table_name, &table,
1121
+ true /* bool prefetch_index_and_filter_in_cache */,
1122
+ nullptr /* status */, persist_udt_);
1123
+
1124
+ // 1. Should coalesce into a single I/O
1125
+ std::unique_ptr<InternalIterator> iter;
1126
+ iter.reset(table->NewIterator(
1127
+ read_opts, options_.prefix_extractor.get(), /*arena=*/nullptr,
1128
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized));
1129
+
1130
+ MultiScanArgs scan_options(comparator_);
1131
+ scan_options.use_async_io = use_async_io;
1132
+ scan_options.insert(ExtractUserKey(kv[30 * kEntriesPerBlock].first),
1133
+ ExtractUserKey(kv[31 * kEntriesPerBlock].first));
1134
+ scan_options.insert(ExtractUserKey(kv[32 * kEntriesPerBlock].first),
1135
+ ExtractUserKey(kv[33 * kEntriesPerBlock].first));
1136
+ auto read_count_before =
1137
+ options_.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT);
1138
+
1139
+ iter->Prepare(&scan_options);
1140
+ iter->Seek(kv[30 * kEntriesPerBlock].first);
1141
+ for (size_t i = 30 * kEntriesPerBlock; i <= 31 * kEntriesPerBlock; ++i) {
1142
+ ASSERT_TRUE(iter->status().ok()) << iter->status().ToString();
1143
+ ASSERT_TRUE(iter->Valid()) << i;
1144
+ ASSERT_EQ(iter->key().ToString(), kv[i].first);
1145
+ iter->Next();
1146
+ }
1147
+ // Iter may still be valid after scan range. Upper layer (DBIter) handles
1148
+ // exact upper bound checking. So we don't check !iter->Valid() here.
1149
+ ASSERT_OK(iter->status());
1150
+ iter->Seek(kv[32 * kEntriesPerBlock].first);
1151
+ for (size_t i = 32 * kEntriesPerBlock; i < 33 * kEntriesPerBlock; ++i) {
1152
+ ASSERT_TRUE(iter->Valid());
1153
+ ASSERT_EQ(iter->key().ToString(), kv[i].first);
1154
+ iter->Next();
1155
+ }
1156
+ ASSERT_OK(iter->status());
1157
+ auto read_count_after =
1158
+ options_.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT);
1159
+ ASSERT_EQ(read_count_before + 1, read_count_after);
1127
1160
 
1128
- read_count_after =
1129
- options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT);
1161
+ // 2. No IO coalesce, should do MultiRead/ReadAsync with 2 read requests.
1162
+ iter.reset(table->NewIterator(
1163
+ read_opts, options_.prefix_extractor.get(), /*arena=*/nullptr,
1164
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized));
1165
+ scan_options = MultiScanArgs(comparator_);
1166
+ scan_options.insert(ExtractUserKey(kv[40 * kEntriesPerBlock].first),
1167
+ ExtractUserKey(kv[45 * kEntriesPerBlock].first));
1168
+ scan_options.insert(ExtractUserKey(kv[70 * kEntriesPerBlock].first),
1169
+ ExtractUserKey(kv[75 * kEntriesPerBlock].first));
1170
+
1171
+ read_count_before =
1172
+ options_.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT);
1173
+ iter->Prepare(&scan_options);
1174
+
1175
+ iter->Seek(kv[40 * kEntriesPerBlock].first);
1176
+ for (size_t i = 40 * kEntriesPerBlock; i < 45 * kEntriesPerBlock; ++i) {
1177
+ ASSERT_TRUE(iter->Valid());
1178
+ ASSERT_EQ(iter->key().ToString(), kv[i].first);
1179
+ iter->Next();
1180
+ }
1181
+ ASSERT_OK(iter->status());
1182
+ iter->Seek(kv[70 * kEntriesPerBlock].first);
1183
+ for (size_t i = 70 * kEntriesPerBlock; i < 75 * kEntriesPerBlock; ++i) {
1184
+ ASSERT_TRUE(iter->Valid());
1185
+ ASSERT_EQ(iter->key().ToString(), kv[i].first);
1186
+ iter->Next();
1187
+ }
1188
+ ASSERT_OK(iter->status());
1189
+
1190
+ read_count_after =
1191
+ options_.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT);
1192
+ ASSERT_EQ(read_count_before + 2, read_count_after);
1193
+
1194
+ iter.reset(table->NewIterator(
1195
+ read_opts, options_.prefix_extractor.get(), /*arena=*/nullptr,
1196
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized));
1197
+
1198
+ // 3. Tests I/O excludes blocks already in cache.
1199
+ // Reading blocks from 40-79
1200
+ // From reads above, blocks 40-44 and 70-74 already in cache
1201
+ // So we should read 45-69, 75-79 in two I/Os.
1202
+ // If fill_cache is false, then we'll do one giant I/O.
1203
+ scan_options = MultiScanArgs(comparator_);
1204
+ scan_options.use_async_io = use_async_io;
1205
+ scan_options.insert(ExtractUserKey(kv[40 * kEntriesPerBlock].first),
1206
+ ExtractUserKey(kv[80 * kEntriesPerBlock].first));
1207
+ read_count_before =
1208
+ options_.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT);
1209
+ iter->Prepare(&scan_options);
1210
+ read_count_after =
1211
+ options_.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT);
1212
+ if (!use_async_io) {
1213
+ if (!fill_cache) {
1214
+ ASSERT_EQ(read_count_before + 1, read_count_after);
1215
+ } else {
1130
1216
  ASSERT_EQ(read_count_before + 2, read_count_after);
1217
+ }
1218
+ } else {
1219
+ // stat is recorded in async callback which happens in Poll(), and
1220
+ // Poll() happens during scanning.
1221
+ ASSERT_EQ(read_count_before, read_count_after);
1222
+ }
1131
1223
 
1132
- iter.reset(table->NewIterator(
1133
- read_opts, options_.prefix_extractor.get(), /*arena=*/nullptr,
1134
- /*skip_filters=*/false, TableReaderCaller::kUncategorized));
1135
-
1136
- // 3. Tests I/O excludes blocks already in cache.
1137
- // Reading blocks from 50-99
1138
- // From reads above, blocks 70-75 and 90-95 already in cache
1139
- // So we should read 50-70 76-89 96-99 in three I/Os.
1140
- // If fill_cache is false, then we'll do one giant I/O.
1141
- scan_options = MultiScanArgs(comparator_);
1142
- scan_options.use_async_io = use_async_io;
1143
- scan_options.insert(ExtractUserKey(kv[50 * kEntriesPerBlock].first));
1144
- read_count_before =
1145
- options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT);
1146
- iter->Prepare(&scan_options);
1147
- read_count_after =
1148
- options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT);
1149
- if (!use_async_io) {
1150
- if (!fill_cache) {
1151
- ASSERT_EQ(read_count_before + 1, read_count_after);
1152
- } else {
1153
- ASSERT_EQ(read_count_before + 3, read_count_after);
1154
- }
1155
- } else {
1156
- // stat is recorded in async callback which happens in Poll(), and
1157
- // Poll() happens during scanning.
1158
- ASSERT_EQ(read_count_before, read_count_after);
1159
- }
1224
+ iter->Seek(kv[40 * kEntriesPerBlock].first);
1225
+ for (size_t i = 40 * kEntriesPerBlock; i < 80 * kEntriesPerBlock; ++i) {
1226
+ ASSERT_TRUE(iter->Valid());
1227
+ ASSERT_EQ(iter->key().ToString(), kv[i].first);
1228
+ iter->Next();
1229
+ }
1230
+ ASSERT_FALSE(iter->Valid());
1231
+ ASSERT_OK(iter->status());
1232
+ read_count_after =
1233
+ options_.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT);
1234
+ if (!fill_cache) {
1235
+ ASSERT_EQ(read_count_before + 1, read_count_after);
1236
+ } else {
1237
+ ASSERT_EQ(read_count_before + 2, read_count_after);
1238
+ }
1239
+
1240
+ // 4. Check cases when Seek key does not match start key in ScanOptions
1241
+ iter.reset(table->NewIterator(
1242
+ read_opts, options_.prefix_extractor.get(), /*arena=*/nullptr,
1243
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized));
1244
+ scan_options = MultiScanArgs(comparator_);
1245
+ scan_options.use_async_io = use_async_io;
1246
+ scan_options.insert(ExtractUserKey(kv[30 * kEntriesPerBlock].first),
1247
+ ExtractUserKey(kv[40 * kEntriesPerBlock].first));
1248
+ scan_options.insert(ExtractUserKey(kv[50 * kEntriesPerBlock].first),
1249
+ ExtractUserKey(kv[60 * kEntriesPerBlock].first));
1250
+ iter->Prepare(&scan_options);
1251
+ // Match start key
1252
+ iter->Seek(kv[30 * kEntriesPerBlock].first);
1253
+ for (size_t i = 30 * kEntriesPerBlock; i < 40 * kEntriesPerBlock; ++i) {
1254
+ ASSERT_TRUE(iter->Valid());
1255
+ ASSERT_EQ(iter->key().ToString(), kv[i].first);
1256
+ iter->Next();
1257
+ }
1258
+ ASSERT_OK(iter->status());
1259
+
1260
+ // Seek a key that is larger than next start key is allowed, as long as it is
1261
+ // larger than the previous key
1262
+ iter->Seek(kv[50 * kEntriesPerBlock + 1].first);
1263
+ ASSERT_OK(iter->status());
1160
1264
 
1161
- iter->Seek(kv[50 * kEntriesPerBlock].first);
1162
- for (size_t i = 50 * kEntriesPerBlock; i < 100 * kEntriesPerBlock; ++i) {
1163
- ASSERT_TRUE(iter->Valid());
1164
- ASSERT_EQ(iter->key().ToString(), kv[i].first);
1265
+ // Check seek key going backward
1266
+ iter.reset(table->NewIterator(
1267
+ read_opts, options_.prefix_extractor.get(), /*arena=*/nullptr,
1268
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized));
1269
+ scan_options = MultiScanArgs(comparator_);
1270
+ scan_options.use_async_io = use_async_io;
1271
+ scan_options.insert(ExtractUserKey(kv[30 * kEntriesPerBlock].first),
1272
+ ExtractUserKey(kv[31 * kEntriesPerBlock].first));
1273
+ scan_options.insert(ExtractUserKey(kv[32 * kEntriesPerBlock].first),
1274
+ ExtractUserKey(kv[33 * kEntriesPerBlock].first));
1275
+ iter->Prepare(&scan_options);
1276
+ iter->Seek(kv[32 * kEntriesPerBlock].first);
1277
+ ASSERT_OK(iter->status());
1278
+ iter->Seek(kv[34 * kEntriesPerBlock].first);
1279
+ ASSERT_OK(iter->status());
1280
+ // Seek key could not going backward
1281
+ iter->Seek(kv[30 * kEntriesPerBlock].first);
1282
+ ASSERT_EQ(iter->status(),
1283
+ Status::InvalidArgument("Unexpected seek key moving backward"));
1284
+
1285
+ // Test prefetch limit reached.
1286
+ iter.reset(table->NewIterator(
1287
+ read_opts, options_.prefix_extractor.get(), /*arena=*/nullptr,
1288
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized));
1289
+ scan_options = MultiScanArgs(comparator_);
1290
+ scan_options.use_async_io = use_async_io;
1291
+ scan_options.max_prefetch_size = 1024; // less than block size
1292
+ scan_options.insert(ExtractUserKey(kv[30 * kEntriesPerBlock].first),
1293
+ ExtractUserKey(kv[40 * kEntriesPerBlock].first));
1294
+ iter->Prepare(&scan_options);
1295
+ iter->Seek(kv[31 * kEntriesPerBlock].first);
1296
+ ASSERT_TRUE(iter->status().IsIncomplete());
1297
+
1298
+ // Randomly seek keys on the file, as long as the key is moving forward, it
1299
+ // is allowed
1300
+
1301
+ if (use_async_io) {
1302
+ // Skip following test when async io is enabled. There is some issue with
1303
+ // IO_uring that I am still trying to root cause.
1304
+ // TODO : enable the test again with async IO
1305
+ return;
1306
+ }
1307
+ for (int i = 0; i < 100; i++) {
1308
+ iter.reset(table->NewIterator(
1309
+ read_opts, options_.prefix_extractor.get(), /*arena=*/nullptr,
1310
+ /*skip_filters=*/false, TableReaderCaller::kUncategorized));
1311
+ scan_options = MultiScanArgs(comparator_);
1312
+ scan_options.use_async_io = use_async_io;
1313
+ scan_options.insert(ExtractUserKey(kv[5 * kEntriesPerBlock].first),
1314
+ ExtractUserKey(kv[10 * kEntriesPerBlock].first));
1315
+ scan_options.insert(ExtractUserKey(kv[25 * kEntriesPerBlock].first),
1316
+ ExtractUserKey(kv[35 * kEntriesPerBlock].first));
1317
+ scan_options.insert(ExtractUserKey(kv[35 * kEntriesPerBlock].first),
1318
+ ExtractUserKey(kv[40 * kEntriesPerBlock].first));
1319
+ scan_options.insert(ExtractUserKey(kv[45 * kEntriesPerBlock].first),
1320
+ ExtractUserKey(kv[50 * kEntriesPerBlock].first));
1321
+ scan_options.insert(ExtractUserKey(kv[75 * kEntriesPerBlock].first),
1322
+ ExtractUserKey(kv[85 * kEntriesPerBlock].first));
1323
+ scan_options.insert(ExtractUserKey(kv[85 * kEntriesPerBlock].first),
1324
+ ExtractUserKey(kv[95 * kEntriesPerBlock].first));
1325
+
1326
+ iter->Prepare(&scan_options);
1327
+
1328
+ auto random_seed = static_cast<uint32_t>(
1329
+ std::chrono::duration_cast<std::chrono::nanoseconds>(
1330
+ std::chrono::system_clock::now().time_since_epoch())
1331
+ .count());
1332
+ Random rnd(random_seed);
1333
+ std::cout << random_seed << std::endl;
1334
+ SCOPED_TRACE("Random seed " + std::to_string(random_seed));
1335
+
1336
+ int last_read_key_index = rnd.Uniform(100);
1337
+ while (last_read_key_index < 100) {
1338
+ iter->Seek(kv[last_read_key_index * kEntriesPerBlock].first);
1339
+ EXPECT_OK(iter->status());
1340
+ // iterate for a few keys
1341
+ while (iter->Valid()) {
1165
1342
  iter->Next();
1343
+ last_read_key_index++;
1344
+ EXPECT_OK(iter->status());
1166
1345
  }
1167
- ASSERT_FALSE(iter->Valid());
1168
- ASSERT_OK(iter->status());
1169
- read_count_after =
1170
- options.statistics->getTickerCount(NON_LAST_LEVEL_READ_COUNT);
1171
- if (!fill_cache) {
1172
- ASSERT_EQ(read_count_before + 1, read_count_after);
1173
- } else {
1174
- ASSERT_EQ(read_count_before + 3, read_count_after);
1175
- }
1346
+ last_read_key_index += rnd.Uniform(100);
1176
1347
  }
1177
1348
  }
1178
1349
  }
1179
1350
 
1180
- TEST_P(BlockBasedTableReaderTest, MultiScanPrefetchSizeLimit) {
1351
+ TEST_P(BlockBasedTableReaderMultiScanTest, MultiScanPrefetchSizeLimit) {
1181
1352
  if (compression_type_ != kNoCompression) {
1182
1353
  // This test relies on block sizes to be close to what's set in option.
1183
1354
  ROCKSDB_GTEST_BYPASS("This test assumes no compression.");
1184
1355
  return;
1185
1356
  }
1186
- Options options;
1187
- options.comparator = comparator_;
1188
1357
  ReadOptions read_opts;
1189
- size_t ts_sz = options.comparator->timestamp_size();
1358
+ size_t ts_sz = options_.comparator->timestamp_size();
1190
1359
 
1191
1360
  // Generate data that spans multiple blocks
1192
1361
  std::vector<std::pair<std::string, std::string>> kv =
@@ -1197,14 +1366,14 @@ TEST_P(BlockBasedTableReaderTest, MultiScanPrefetchSizeLimit) {
1197
1366
  std::string table_name = "BlockBasedTableReaderTest_PrefetchSizeLimit" +
1198
1367
  CompressionTypeToString(compression_type_);
1199
1368
 
1200
- ImmutableOptions ioptions(options);
1369
+ ImmutableOptions ioptions(options_);
1201
1370
  CreateTable(table_name, ioptions, compression_type_, kv,
1202
1371
  compression_parallel_threads_, compression_dict_bytes_);
1203
1372
 
1204
1373
  std::unique_ptr<BlockBasedTable> table;
1205
1374
  FileOptions foptions;
1206
1375
  foptions.use_direct_reads = use_direct_reads_;
1207
- InternalKeyComparator comparator(options.comparator);
1376
+ InternalKeyComparator comparator(options_.comparator);
1208
1377
  NewBlockBasedTableReader(foptions, ioptions, comparator, table_name, &table,
1209
1378
  true /* bool prefetch_index_and_filter_in_cache */,
1210
1379
  nullptr /* status */, persist_udt_);
@@ -1377,11 +1546,11 @@ TEST_P(BlockBasedTableReaderTest, MultiScanPrefetchSizeLimit) {
1377
1546
  }
1378
1547
  }
1379
1548
 
1380
- TEST_P(BlockBasedTableReaderTest, MultiScanUnpinPreviousBlocks) {
1549
+ TEST_P(BlockBasedTableReaderMultiScanTest, MultiScanUnpinPreviousBlocks) {
1381
1550
  std::vector<std::pair<std::string, std::string>> kv =
1382
1551
  BlockBasedTableReaderBaseTest::GenerateKVMap(
1383
- 30 /* num_block */,
1384
- true /* mixed_with_human_readable_string_value */);
1552
+ 30 /* num_block */, true /* mixed_with_human_readable_string_value */,
1553
+ comparator_->timestamp_size(), same_key_diff_ts_, comparator_);
1385
1554
  std::string table_name = "BlockBasedTableReaderTest_UnpinPreviousBlocks" +
1386
1555
  CompressionTypeToString(compression_type_);
1387
1556
  ImmutableOptions ioptions(options_);
@@ -1454,53 +1623,375 @@ TEST_P(BlockBasedTableReaderTest, MultiScanUnpinPreviousBlocks) {
1454
1623
  }
1455
1624
  }
1456
1625
 
1626
+ // Test that fs_prefetch_support flag is correctly initialized during table
1627
+ // construction based on filesystem capabilities
1628
+ TEST_P(BlockBasedTableReaderTest, FSPrefetchSupportInitializedCorrectly) {
1629
+ class ConfigurablePrefetchFS : public FileSystemWrapper {
1630
+ public:
1631
+ ConfigurablePrefetchFS(const std::shared_ptr<FileSystem>& target,
1632
+ bool support_prefetch)
1633
+ : FileSystemWrapper(target), support_prefetch_(support_prefetch) {}
1634
+
1635
+ static const char* kClassName() { return "ConfigurablePrefetchFS"; }
1636
+ const char* Name() const override { return kClassName(); }
1637
+
1638
+ void SupportedOps(int64_t& supported_ops) override {
1639
+ target()->SupportedOps(supported_ops);
1640
+ if (!support_prefetch_) { // Disable prefetch support if requested
1641
+ supported_ops &= ~(1 << FSSupportedOps::kFSPrefetch);
1642
+ }
1643
+ }
1644
+
1645
+ private:
1646
+ bool support_prefetch_;
1647
+ };
1648
+
1649
+ // Prepare test table
1650
+ Options options;
1651
+ options.persist_user_defined_timestamps = persist_udt_;
1652
+ if (udt_enabled_) {
1653
+ options.comparator = test::BytewiseComparatorWithU64TsWrapper();
1654
+ }
1655
+ size_t ts_sz = options.comparator->timestamp_size();
1656
+ auto kv = BlockBasedTableReaderBaseTest::GenerateKVMap(5, true, ts_sz);
1657
+ std::string table_name = "BlockBasedTableReaderTest_BlockPrefetcherTest" +
1658
+ CompressionTypeToString(compression_type_);
1659
+ ImmutableOptions ioptions(options);
1660
+ CreateTable(table_name, ioptions, compression_type_, kv,
1661
+ compression_parallel_threads_, compression_dict_bytes_);
1662
+
1663
+ // Test Case 1: Filesystem supports prefetch, fs_prefetch_support should be
1664
+ // true
1665
+ {
1666
+ auto fs_with_prefetch = std::make_shared<ConfigurablePrefetchFS>(
1667
+ env_->GetFileSystem(), true /* support_prefetch */);
1668
+ std::unique_ptr<Env> env_wrapper(
1669
+ new CompositeEnvWrapper(env_, fs_with_prefetch));
1670
+ options.env = env_wrapper.get();
1671
+
1672
+ FileOptions fopts;
1673
+ fopts.use_direct_reads = use_direct_reads_;
1674
+ InternalKeyComparator cmp(options.comparator);
1675
+ ImmutableOptions iopts(options);
1676
+
1677
+ std::unique_ptr<BlockBasedTable> table;
1678
+ NewBlockBasedTableReader(fopts, iopts, cmp, table_name, &table,
1679
+ false /* prefetch_index_and_filter_in_cache */,
1680
+ nullptr, persist_udt_);
1681
+
1682
+ ASSERT_TRUE(table->get_rep()->fs_prefetch_support);
1683
+ ASSERT_TRUE(CheckFSFeatureSupport(fs_with_prefetch.get(),
1684
+ FSSupportedOps::kFSPrefetch));
1685
+ }
1686
+
1687
+ // Test Case 2: Filesystem doesn't support prefetch, fs_prefetch_support
1688
+ // should be false
1689
+ {
1690
+ auto fs_without_prefetch = std::make_shared<ConfigurablePrefetchFS>(
1691
+ env_->GetFileSystem(), false /* support_prefetch */);
1692
+ std::unique_ptr<Env> env_wrapper(
1693
+ new CompositeEnvWrapper(env_, fs_without_prefetch));
1694
+ options.env = env_wrapper.get();
1695
+
1696
+ FileOptions fopts;
1697
+ fopts.use_direct_reads = use_direct_reads_;
1698
+ InternalKeyComparator cmp(options.comparator);
1699
+ ImmutableOptions iopts(options);
1700
+
1701
+ std::unique_ptr<BlockBasedTable> table;
1702
+ NewBlockBasedTableReader(fopts, iopts, cmp, table_name, &table,
1703
+ false /* prefetch_index_and_filter_in_cache */,
1704
+ nullptr, persist_udt_);
1705
+
1706
+ ASSERT_FALSE(table->get_rep()->fs_prefetch_support);
1707
+ ASSERT_FALSE(CheckFSFeatureSupport(fs_without_prefetch.get(),
1708
+ FSSupportedOps::kFSPrefetch));
1709
+ }
1710
+ }
1711
+ std::vector<BlockBasedTableReaderTestParam> GenerateCombinedParameters(
1712
+ const std::vector<CompressionType>& compression_types,
1713
+ const std::vector<bool>& use_direct_read_flags,
1714
+ const std::vector<BlockBasedTableOptions::IndexType>& index_types,
1715
+ const std::vector<bool>& no_block_cache_flags,
1716
+ const std::vector<test::UserDefinedTimestampTestMode>& udt_test_modes,
1717
+ const std::vector<int>& parallel_compression_thread_counts,
1718
+ const std::vector<uint32_t>& compression_dict_byte_counts,
1719
+ const std::vector<bool>& same_key_diff_ts_flags,
1720
+ const std::vector<const Comparator*>& comparators,
1721
+ const std::vector<bool>& fill_cache_flags,
1722
+ const std::vector<bool>& use_async_io_flags,
1723
+ const std::vector<bool>& block_align_flags,
1724
+ const std::vector<size_t>& super_block_alignment_sizes,
1725
+ const std::vector<size_t>& super_block_alignment_space_overhead_ratios) {
1726
+ std::vector<BlockBasedTableReaderTestParam> params;
1727
+ for (const auto& compression_type : compression_types) {
1728
+ for (auto use_direct_read : use_direct_read_flags) {
1729
+ for (const auto& index_type : index_types) {
1730
+ for (auto no_block_cache : no_block_cache_flags) {
1731
+ for (const auto& udt_test_mode : udt_test_modes) {
1732
+ for (auto parallel_compression_thread_count :
1733
+ parallel_compression_thread_counts) {
1734
+ for (auto compression_dict_byte_count :
1735
+ compression_dict_byte_counts) {
1736
+ for (auto same_key_diff_ts_flag : same_key_diff_ts_flags) {
1737
+ for (const auto& comparator : comparators) {
1738
+ for (auto fill_cache : fill_cache_flags) {
1739
+ for (auto use_async_io : use_async_io_flags) {
1740
+ for (auto block_align : block_align_flags) {
1741
+ for (auto super_block_alignment_size :
1742
+ super_block_alignment_sizes) {
1743
+ for (
1744
+ auto
1745
+ super_block_alignment_space_overhead_ratio :
1746
+ super_block_alignment_space_overhead_ratios) {
1747
+ if (super_block_alignment_size == 0) {
1748
+ // Override padding size to 0 if alignment size
1749
+ // is 0, which means no super block alignment
1750
+ super_block_alignment_space_overhead_ratio = 0;
1751
+ }
1752
+ params.emplace_back(
1753
+ compression_type, use_direct_read, index_type,
1754
+ no_block_cache, udt_test_mode,
1755
+ parallel_compression_thread_count,
1756
+ compression_dict_byte_count,
1757
+ same_key_diff_ts_flag, comparator, fill_cache,
1758
+ use_async_io, block_align,
1759
+ super_block_alignment_size,
1760
+ super_block_alignment_space_overhead_ratio);
1761
+ }
1762
+ }
1763
+ }
1764
+ }
1765
+ }
1766
+ }
1767
+ }
1768
+ }
1769
+ }
1770
+ }
1771
+ }
1772
+ }
1773
+ }
1774
+ }
1775
+ return params;
1776
+ }
1777
+
1778
+ std::vector<bool> Bool() { return {true, false}; }
1779
+
1780
+ struct BlockBasedTableReaderTestParamBuilder {
1781
+ BlockBasedTableReaderTestParamBuilder() {
1782
+ // Default values
1783
+ compression_types = GetSupportedCompressions();
1784
+ use_direct_read_flags = Bool();
1785
+ index_types = {
1786
+ BlockBasedTableOptions::IndexType::kBinarySearch,
1787
+ BlockBasedTableOptions::IndexType::kHashSearch,
1788
+ BlockBasedTableOptions::IndexType::kTwoLevelIndexSearch,
1789
+ BlockBasedTableOptions::IndexType::kBinarySearchWithFirstKey};
1790
+ no_block_cache_flags = {false};
1791
+ udt_test_modes = {
1792
+ test::UserDefinedTimestampTestMode::kStripUserDefinedTimestamp};
1793
+ parallel_compression_thread_counts = {1, 2};
1794
+ compression_dict_byte_counts = {0, 4096};
1795
+ same_key_diff_ts_flags = {false};
1796
+ comparators = {BytewiseComparator()};
1797
+ fill_cache_flags = {true};
1798
+ use_async_io_flags = {false};
1799
+ block_align_flags = {false};
1800
+ super_block_alignment_sizes = {0};
1801
+ super_block_alignment_space_overhead_ratios = {128};
1802
+ }
1803
+
1804
+ // builder methods for each member
1805
+ BlockBasedTableReaderTestParamBuilder& WithCompressionTypes(
1806
+ const std::vector<CompressionType>& _compression_types) {
1807
+ compression_types = _compression_types;
1808
+ return *this;
1809
+ }
1810
+
1811
+ BlockBasedTableReaderTestParamBuilder& WithUseDirectReadFlags(
1812
+ const std::vector<bool>& _use_direct_read_flags) {
1813
+ use_direct_read_flags = _use_direct_read_flags;
1814
+ return *this;
1815
+ }
1816
+
1817
+ BlockBasedTableReaderTestParamBuilder& WithIndexTypes(
1818
+ const std::vector<BlockBasedTableOptions::IndexType>& _index_types) {
1819
+ index_types = _index_types;
1820
+ return *this;
1821
+ }
1822
+
1823
+ BlockBasedTableReaderTestParamBuilder& WithNoBlockCacheFlags(
1824
+ const std::vector<bool>& _no_block_cache_flags) {
1825
+ no_block_cache_flags = _no_block_cache_flags;
1826
+ return *this;
1827
+ }
1828
+
1829
+ BlockBasedTableReaderTestParamBuilder& WithUDTTestModes(
1830
+ const std::vector<test::UserDefinedTimestampTestMode>& _udt_test_modes) {
1831
+ udt_test_modes = _udt_test_modes;
1832
+ return *this;
1833
+ }
1834
+
1835
+ BlockBasedTableReaderTestParamBuilder& WithParallelCompressionThreadCounts(
1836
+ const std::vector<int>& _parallel_compression_thread_counts) {
1837
+ parallel_compression_thread_counts = _parallel_compression_thread_counts;
1838
+ return *this;
1839
+ }
1840
+
1841
+ BlockBasedTableReaderTestParamBuilder& WithCompressionDictByteCounts(
1842
+ const std::vector<uint32_t>& _compression_dict_byte_counts) {
1843
+ compression_dict_byte_counts = _compression_dict_byte_counts;
1844
+ return *this;
1845
+ }
1846
+
1847
+ BlockBasedTableReaderTestParamBuilder& WithSameKeyDiffTsFlags(
1848
+ const std::vector<bool>& _same_key_diff_ts_flags) {
1849
+ same_key_diff_ts_flags = _same_key_diff_ts_flags;
1850
+ return *this;
1851
+ }
1852
+
1853
+ BlockBasedTableReaderTestParamBuilder& WithComparators(
1854
+ const std::vector<const Comparator*>& _comparators) {
1855
+ comparators = _comparators;
1856
+ return *this;
1857
+ }
1858
+
1859
+ BlockBasedTableReaderTestParamBuilder& WithFillCacheFlags(
1860
+ const std::vector<bool>& _fill_cache_flags) {
1861
+ fill_cache_flags = _fill_cache_flags;
1862
+ return *this;
1863
+ }
1864
+
1865
+ BlockBasedTableReaderTestParamBuilder& WithUseAsyncIoFlags(
1866
+ const std::vector<bool>& _use_async_io_flags) {
1867
+ use_async_io_flags = _use_async_io_flags;
1868
+ return *this;
1869
+ }
1870
+
1871
+ BlockBasedTableReaderTestParamBuilder& WithBlockAlignFlags(
1872
+ const std::vector<bool>& _block_align_flags) {
1873
+ block_align_flags = _block_align_flags;
1874
+ return *this;
1875
+ }
1876
+
1877
+ BlockBasedTableReaderTestParamBuilder& WithSuperBlockAlignmentSizes(
1878
+ const std::vector<size_t>& _super_block_alignment_sizes) {
1879
+ super_block_alignment_sizes = _super_block_alignment_sizes;
1880
+ return *this;
1881
+ }
1882
+
1883
+ BlockBasedTableReaderTestParamBuilder&
1884
+ WithSuperBlockAlignmentSpaceOverheadRatios(
1885
+ const std::vector<size_t>& _super_block_alignment_space_overhead_ratios) {
1886
+ super_block_alignment_space_overhead_ratios =
1887
+ _super_block_alignment_space_overhead_ratios;
1888
+ return *this;
1889
+ }
1890
+
1891
+ std::vector<BlockBasedTableReaderTestParam> build() {
1892
+ return GenerateCombinedParameters(
1893
+ compression_types, use_direct_read_flags, index_types,
1894
+ no_block_cache_flags, udt_test_modes,
1895
+ parallel_compression_thread_counts, compression_dict_byte_counts,
1896
+ same_key_diff_ts_flags, comparators, fill_cache_flags,
1897
+ use_async_io_flags, block_align_flags, super_block_alignment_sizes,
1898
+ super_block_alignment_space_overhead_ratios);
1899
+ }
1900
+
1901
+ std::vector<CompressionType> compression_types;
1902
+ std::vector<bool> use_direct_read_flags;
1903
+ std::vector<BlockBasedTableOptions::IndexType> index_types;
1904
+ std::vector<bool> no_block_cache_flags;
1905
+ std::vector<test::UserDefinedTimestampTestMode> udt_test_modes;
1906
+ std::vector<int> parallel_compression_thread_counts;
1907
+ std::vector<uint32_t> compression_dict_byte_counts;
1908
+ std::vector<bool> same_key_diff_ts_flags;
1909
+ std::vector<const Comparator*> comparators;
1910
+ std::vector<bool> fill_cache_flags;
1911
+ std::vector<bool> use_async_io_flags;
1912
+ std::vector<bool> block_align_flags;
1913
+ std::vector<size_t> super_block_alignment_sizes;
1914
+ std::vector<size_t> super_block_alignment_space_overhead_ratios;
1915
+ };
1916
+
1917
+ std::vector<bool> IOUringFlags() {
1918
+ #ifdef ROCKSDB_IOURING_PRESENT
1919
+ return {false, true};
1920
+ #else
1921
+ return {false};
1922
+ #endif
1923
+ }
1924
+
1457
1925
  INSTANTIATE_TEST_CASE_P(
1458
1926
  BlockBasedTableReaderTest, BlockBasedTableReaderTest,
1459
- ::testing::Combine(
1460
- ::testing::ValuesIn(GetSupportedCompressions()), ::testing::Bool(),
1461
- ::testing::Values(
1462
- BlockBasedTableOptions::IndexType::kBinarySearch,
1463
- BlockBasedTableOptions::IndexType::kHashSearch,
1464
- BlockBasedTableOptions::IndexType::kTwoLevelIndexSearch,
1465
- BlockBasedTableOptions::IndexType::kBinarySearchWithFirstKey),
1466
- ::testing::Values(false), ::testing::ValuesIn(test::GetUDTTestModes()),
1467
- ::testing::Values(1, 2), ::testing::Values(0, 4096),
1468
- ::testing::Values(false),
1469
- ::testing::Values(BytewiseComparator(), ReverseBytewiseComparator())));
1927
+ ::testing::ValuesIn(BlockBasedTableReaderTestParamBuilder()
1928
+ .WithUDTTestModes(test::GetUDTTestModes())
1929
+ .build()));
1930
+
1931
+ INSTANTIATE_TEST_CASE_P(
1932
+ BlockBasedTableReaderMultiScanAsyncIOTest,
1933
+ BlockBasedTableReaderMultiScanAsyncIOTest,
1934
+ ::testing::ValuesIn(BlockBasedTableReaderTestParamBuilder()
1935
+ .WithComparators({BytewiseComparator(),
1936
+ ReverseBytewiseComparator()})
1937
+ .WithFillCacheFlags(Bool())
1938
+ .WithUseAsyncIoFlags(IOUringFlags())
1939
+ .build()));
1940
+
1941
+ INSTANTIATE_TEST_CASE_P(
1942
+ BlockBasedTableReaderMultiScanTest, BlockBasedTableReaderMultiScanTest,
1943
+ ::testing::ValuesIn(BlockBasedTableReaderTestParamBuilder()
1944
+ .WithComparators({BytewiseComparator(),
1945
+ ReverseBytewiseComparator()})
1946
+ .build()));
1947
+
1470
1948
  INSTANTIATE_TEST_CASE_P(
1471
1949
  BlockBasedTableReaderGetTest, BlockBasedTableReaderGetTest,
1472
- ::testing::Combine(
1473
- ::testing::ValuesIn(GetSupportedCompressions()), ::testing::Bool(),
1474
- ::testing::Values(
1475
- BlockBasedTableOptions::IndexType::kBinarySearch,
1476
- BlockBasedTableOptions::IndexType::kHashSearch,
1477
- BlockBasedTableOptions::IndexType::kTwoLevelIndexSearch,
1478
- BlockBasedTableOptions::IndexType::kBinarySearchWithFirstKey),
1479
- ::testing::Values(false), ::testing::ValuesIn(test::GetUDTTestModes()),
1480
- ::testing::Values(1, 2), ::testing::Values(0, 4096),
1481
- ::testing::Values(false, true),
1482
- ::testing::Values(BytewiseComparator(), ReverseBytewiseComparator())));
1950
+ ::testing::ValuesIn(BlockBasedTableReaderTestParamBuilder()
1951
+ .WithUDTTestModes(test::GetUDTTestModes())
1952
+ .WithSameKeyDiffTsFlags(Bool())
1953
+ .WithComparators({BytewiseComparator(),
1954
+ ReverseBytewiseComparator()})
1955
+ .WithFillCacheFlags({false})
1956
+ .build()));
1957
+
1958
+ INSTANTIATE_TEST_CASE_P(
1959
+ BlockBasedTableReaderSuperBlockAlignTest, BlockBasedTableReaderGetTest,
1960
+ ::testing::ValuesIn(
1961
+ BlockBasedTableReaderTestParamBuilder()
1962
+ .WithIndexTypes(
1963
+ {BlockBasedTableOptions::IndexType::kBinarySearch,
1964
+ BlockBasedTableOptions::IndexType::kTwoLevelIndexSearch})
1965
+ .WithFillCacheFlags({false})
1966
+ .WithBlockAlignFlags(Bool())
1967
+ .WithSuperBlockAlignmentSizes({0, 32 * 1024, 16 * 1024})
1968
+ .WithSuperBlockAlignmentSpaceOverheadRatios({0, 4, 256})
1969
+ .build()));
1970
+
1483
1971
  INSTANTIATE_TEST_CASE_P(
1484
1972
  StrictCapacityLimitReaderTest, StrictCapacityLimitReaderTest,
1485
- ::testing::Combine(
1486
- ::testing::ValuesIn(GetSupportedCompressions()), ::testing::Bool(),
1487
- ::testing::Values(
1488
- BlockBasedTableOptions::IndexType::kTwoLevelIndexSearch),
1489
- ::testing::Values(false), ::testing::ValuesIn(test::GetUDTTestModes()),
1490
- ::testing::Values(1, 2), ::testing::Values(0),
1491
- ::testing::Values(false, true),
1492
- ::testing::Values(BytewiseComparator(), ReverseBytewiseComparator())));
1973
+ ::testing::ValuesIn(
1974
+ BlockBasedTableReaderTestParamBuilder()
1975
+ .WithIndexTypes(
1976
+ {BlockBasedTableOptions::IndexType::kTwoLevelIndexSearch})
1977
+ .WithUDTTestModes(test::GetUDTTestModes())
1978
+ .WithCompressionDictByteCounts({0})
1979
+ .WithSameKeyDiffTsFlags(Bool())
1980
+ .WithFillCacheFlags({false})
1981
+ .build()));
1982
+
1493
1983
  INSTANTIATE_TEST_CASE_P(
1494
1984
  VerifyChecksum, BlockBasedTableReaderTestVerifyChecksum,
1495
- ::testing::Combine(
1496
- ::testing::ValuesIn(GetSupportedCompressions()),
1497
- ::testing::Values(false),
1498
- ::testing::Values(
1499
- BlockBasedTableOptions::IndexType::kTwoLevelIndexSearch),
1500
- ::testing::Values(true), ::testing::ValuesIn(test::GetUDTTestModes()),
1501
- ::testing::Values(1, 2), ::testing::Values(0), ::testing::Values(false),
1502
- ::testing::Values(BytewiseComparator(), ReverseBytewiseComparator())));
1503
-
1985
+ ::testing::ValuesIn(
1986
+ BlockBasedTableReaderTestParamBuilder()
1987
+ .WithUseDirectReadFlags({false})
1988
+ .WithIndexTypes(
1989
+ {BlockBasedTableOptions::IndexType::kTwoLevelIndexSearch})
1990
+ .WithNoBlockCacheFlags({true})
1991
+ .WithUDTTestModes(test::GetUDTTestModes())
1992
+ .WithCompressionDictByteCounts({0})
1993
+ .WithFillCacheFlags({false})
1994
+ .build()));
1504
1995
  } // namespace ROCKSDB_NAMESPACE
1505
1996
 
1506
1997
  int main(int argc, char** argv) {