@nxtedition/rocksdb 15.1.2 → 15.1.3

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 (153) hide show
  1. package/binding.cc +79 -38
  2. package/build.sh +1 -2
  3. package/deps/rocksdb/rocksdb/BUCK +10 -8
  4. package/deps/rocksdb/rocksdb/CMakeLists.txt +27 -2
  5. package/deps/rocksdb/rocksdb/Makefile +27 -116
  6. package/deps/rocksdb/rocksdb/cache/cache_bench_tool.cc +1 -1
  7. package/deps/rocksdb/rocksdb/cache/clock_cache.cc +101 -124
  8. package/deps/rocksdb/rocksdb/cache/clock_cache.h +47 -30
  9. package/deps/rocksdb/rocksdb/db/c.cc +793 -131
  10. package/deps/rocksdb/rocksdb/db/c_test.c +571 -0
  11. package/deps/rocksdb/rocksdb/db/compact_files_test.cc +226 -0
  12. package/deps/rocksdb/rocksdb/db/compaction/compaction.h +4 -0
  13. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +95 -59
  14. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.h +2 -2
  15. package/deps/rocksdb/rocksdb/db/compaction/compaction_job_test.cc +45 -35
  16. package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.cc +8 -4
  17. package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.h +1 -1
  18. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.cc +11 -6
  19. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker.h +8 -2
  20. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_test.cc +47 -0
  21. package/deps/rocksdb/rocksdb/db/compaction/compaction_picker_universal.cc +12 -2
  22. package/deps/rocksdb/rocksdb/db/compaction/compaction_service_test.cc +82 -0
  23. package/deps/rocksdb/rocksdb/db/compaction/subcompaction_state.cc +2 -2
  24. package/deps/rocksdb/rocksdb/db/compaction/subcompaction_state.h +1 -1
  25. package/deps/rocksdb/rocksdb/db/db_basic_test.cc +69 -24
  26. package/deps/rocksdb/rocksdb/db/db_bloom_filter_test.cc +9 -1
  27. package/deps/rocksdb/rocksdb/db/db_compaction_test.cc +65 -0
  28. package/deps/rocksdb/rocksdb/db/db_etc3_test.cc +161 -0
  29. package/deps/rocksdb/rocksdb/db/db_filesnapshot.cc +1 -0
  30. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +20 -7
  31. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +13 -0
  32. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +114 -39
  33. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_files.cc +3 -0
  34. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_follower.cc +3 -3
  35. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +1 -1
  36. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_secondary.cc +39 -25
  37. package/deps/rocksdb/rocksdb/db/db_iterator_test.cc +361 -0
  38. package/deps/rocksdb/rocksdb/db/db_options_test.cc +35 -0
  39. package/deps/rocksdb/rocksdb/db/db_range_del_test.cc +83 -0
  40. package/deps/rocksdb/rocksdb/db/db_test.cc +249 -4
  41. package/deps/rocksdb/rocksdb/db/db_test2.cc +3 -0
  42. package/deps/rocksdb/rocksdb/db/db_test_util.cc +2 -1
  43. package/deps/rocksdb/rocksdb/db/db_wal_test.cc +3 -2
  44. package/deps/rocksdb/rocksdb/db/flush_job_test.cc +7 -7
  45. package/deps/rocksdb/rocksdb/db/listener_test.cc +7 -17
  46. package/deps/rocksdb/rocksdb/db/memtable_list_test.cc +4 -2
  47. package/deps/rocksdb/rocksdb/db/obsolete_files_test.cc +41 -0
  48. package/deps/rocksdb/rocksdb/db/repair.cc +2 -2
  49. package/deps/rocksdb/rocksdb/db/version_edit.h +7 -4
  50. package/deps/rocksdb/rocksdb/db/version_set.cc +299 -90
  51. package/deps/rocksdb/rocksdb/db/version_set.h +56 -9
  52. package/deps/rocksdb/rocksdb/db/version_set_test.cc +41 -39
  53. package/deps/rocksdb/rocksdb/db/version_util.h +3 -2
  54. package/deps/rocksdb/rocksdb/db/wal_manager.cc +7 -1
  55. package/deps/rocksdb/rocksdb/db/wal_manager_test.cc +48 -10
  56. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +1 -0
  57. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +5 -1
  58. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +16 -5
  59. package/deps/rocksdb/rocksdb/env/env_test.cc +126 -41
  60. package/deps/rocksdb/rocksdb/env/fs_posix.cc +14 -7
  61. package/deps/rocksdb/rocksdb/env/io_posix.cc +304 -112
  62. package/deps/rocksdb/rocksdb/env/io_posix.h +16 -4
  63. package/deps/rocksdb/rocksdb/env/io_posix_test.cc +43 -0
  64. package/deps/rocksdb/rocksdb/folly.mk +148 -0
  65. package/deps/rocksdb/rocksdb/include/rocksdb/advanced_compression.h +29 -3
  66. package/deps/rocksdb/rocksdb/include/rocksdb/advanced_options.h +73 -0
  67. package/deps/rocksdb/rocksdb/include/rocksdb/c.h +246 -0
  68. package/deps/rocksdb/rocksdb/include/rocksdb/compaction_filter.h +0 -2
  69. package/deps/rocksdb/rocksdb/include/rocksdb/data_structure.h +15 -9
  70. package/deps/rocksdb/rocksdb/include/rocksdb/db.h +19 -9
  71. package/deps/rocksdb/rocksdb/include/rocksdb/env.h +1 -1
  72. package/deps/rocksdb/rocksdb/include/rocksdb/file_system.h +6 -4
  73. package/deps/rocksdb/rocksdb/include/rocksdb/metadata.h +14 -0
  74. package/deps/rocksdb/rocksdb/include/rocksdb/options.h +67 -6
  75. package/deps/rocksdb/rocksdb/include/rocksdb/sst_file_writer.h +1 -7
  76. package/deps/rocksdb/rocksdb/include/rocksdb/statistics.h +3 -0
  77. package/deps/rocksdb/rocksdb/include/rocksdb/thread_status.h +6 -14
  78. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/backup_engine.h +8 -1
  79. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/env_mirror.h +2 -2
  80. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/ldb_cmd_execute_result.h +0 -4
  81. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/option_change_migration.h +33 -5
  82. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/stackable_db.h +6 -0
  83. package/deps/rocksdb/rocksdb/include/rocksdb/version.h +2 -2
  84. package/deps/rocksdb/rocksdb/monitoring/statistics.cc +2 -0
  85. package/deps/rocksdb/rocksdb/monitoring/thread_status_impl.cc +5 -2
  86. package/deps/rocksdb/rocksdb/monitoring/thread_status_updater.cc +2 -2
  87. package/deps/rocksdb/rocksdb/monitoring/thread_status_updater.h +6 -6
  88. package/deps/rocksdb/rocksdb/monitoring/thread_status_updater_debug.cc +2 -2
  89. package/deps/rocksdb/rocksdb/monitoring/thread_status_util.cc +10 -5
  90. package/deps/rocksdb/rocksdb/monitoring/thread_status_util.h +2 -2
  91. package/deps/rocksdb/rocksdb/options/cf_options.cc +15 -3
  92. package/deps/rocksdb/rocksdb/options/cf_options.h +7 -0
  93. package/deps/rocksdb/rocksdb/options/db_options.cc +27 -36
  94. package/deps/rocksdb/rocksdb/options/db_options.h +3 -2
  95. package/deps/rocksdb/rocksdb/options/options.cc +4 -0
  96. package/deps/rocksdb/rocksdb/options/options_helper.cc +8 -2
  97. package/deps/rocksdb/rocksdb/options/options_settable_test.cc +4 -1
  98. package/deps/rocksdb/rocksdb/options/options_test.cc +19 -3
  99. package/deps/rocksdb/rocksdb/src.mk +1 -1
  100. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.cc +155 -32
  101. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.h +7 -3
  102. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.cc +169 -125
  103. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_iterator.h +22 -7
  104. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.cc +43 -24
  105. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader.h +9 -5
  106. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_reader_test.cc +9 -8
  107. package/deps/rocksdb/rocksdb/table/block_based/filter_block.h +17 -0
  108. package/deps/rocksdb/rocksdb/table/block_based/filter_policy.cc +15 -5
  109. package/deps/rocksdb/rocksdb/table/block_based/filter_policy_internal.h +13 -18
  110. package/deps/rocksdb/rocksdb/table/block_based/full_filter_block.cc +29 -0
  111. package/deps/rocksdb/rocksdb/table/block_based/full_filter_block.h +6 -0
  112. package/deps/rocksdb/rocksdb/table/block_based/full_filter_block_test.cc +15 -0
  113. package/deps/rocksdb/rocksdb/table/block_based/index_builder.cc +79 -19
  114. package/deps/rocksdb/rocksdb/table/block_based/index_builder.h +48 -20
  115. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.cc +51 -0
  116. package/deps/rocksdb/rocksdb/table/block_based/partitioned_filter_block.h +19 -0
  117. package/deps/rocksdb/rocksdb/table/block_based/user_defined_index_wrapper.h +1 -1
  118. package/deps/rocksdb/rocksdb/table/external_table.cc +2 -2
  119. package/deps/rocksdb/rocksdb/table/sst_file_dumper.cc +3 -2
  120. package/deps/rocksdb/rocksdb/table/sst_file_dumper.h +3 -1
  121. package/deps/rocksdb/rocksdb/table/table_builder.h +5 -0
  122. package/deps/rocksdb/rocksdb/table/table_reader.h +4 -2
  123. package/deps/rocksdb/rocksdb/table/table_test.cc +48 -39
  124. package/deps/rocksdb/rocksdb/test_util/sync_point.cc +4 -0
  125. package/deps/rocksdb/rocksdb/test_util/sync_point.h +32 -0
  126. package/deps/rocksdb/rocksdb/test_util/testutil.h +6 -2
  127. package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +14 -4
  128. package/deps/rocksdb/rocksdb/tools/ldb_cmd.cc +8 -5
  129. package/deps/rocksdb/rocksdb/tools/ldb_cmd_test.cc +3 -2
  130. package/deps/rocksdb/rocksdb/tools/sst_dump_tool.cc +63 -12
  131. package/deps/rocksdb/rocksdb/util/auto_tune_compressor.cc +16 -1
  132. package/deps/rocksdb/rocksdb/util/auto_tune_compressor.h +5 -1
  133. package/deps/rocksdb/rocksdb/util/bit_fields.h +133 -23
  134. package/deps/rocksdb/rocksdb/util/bloom_test.cc +2 -5
  135. package/deps/rocksdb/rocksdb/util/compression.cc +51 -23
  136. package/deps/rocksdb/rocksdb/util/compression_test.cc +525 -270
  137. package/deps/rocksdb/rocksdb/util/filter_bench.cc +3 -4
  138. package/deps/rocksdb/rocksdb/util/simple_mixed_compressor.cc +11 -2
  139. package/deps/rocksdb/rocksdb/util/simple_mixed_compressor.h +4 -1
  140. package/deps/rocksdb/rocksdb/util/slice_test.cc +92 -0
  141. package/deps/rocksdb/rocksdb/util/thread_list_test.cc +2 -2
  142. package/deps/rocksdb/rocksdb/util/thread_operation.h +2 -2
  143. package/deps/rocksdb/rocksdb/util/threadpool_imp.cc +2 -2
  144. package/deps/rocksdb/rocksdb/utilities/backup/backup_engine.cc +19 -2
  145. package/deps/rocksdb/rocksdb/utilities/backup/backup_engine_test.cc +75 -0
  146. package/deps/rocksdb/rocksdb/utilities/checkpoint/checkpoint_test.cc +1 -0
  147. package/deps/rocksdb/rocksdb/utilities/option_change_migration/option_change_migration.cc +303 -111
  148. package/deps/rocksdb/rocksdb/utilities/option_change_migration/option_change_migration_test.cc +379 -0
  149. package/deps/rocksdb/rocksdb.gyp +6 -4
  150. package/iterator.js +66 -70
  151. package/package.json +6 -6
  152. package/prebuilds/darwin-arm64/@nxtedition+rocksdb.node +0 -0
  153. package/deps/rocksdb/rocksdb/table/block_based/index_builder_test.cc +0 -183
@@ -8,6 +8,7 @@
8
8
 
9
9
  #include <cinttypes>
10
10
  #include <iostream>
11
+ #include <regex>
11
12
 
12
13
  #include "db_stress_tool/db_stress_compression_manager.h"
13
14
  #include "options/options_helper.h"
@@ -62,6 +63,9 @@ void print_help(bool to_stderr) {
62
63
  --decode_blob_index
63
64
  Decode blob indexes and print them in a human-readable format during scans.
64
65
 
66
+ --show_sequence_number_type
67
+ Show sequence number and value type when executing raw command
68
+
65
69
  --from=<user_key>
66
70
  Key to start reading from when executing check|scan
67
71
 
@@ -100,6 +104,10 @@ void print_help(bool to_stderr) {
100
104
  instead of the built-in compression manager, which may support a
101
105
  different set of compression types.
102
106
 
107
+ --enable_index_compression=<bool>
108
+ Used with --command=recompress to specify whether to compress index
109
+ blocks (in addition to data blocks).
110
+
103
111
  --parse_internal_key=<0xKEY>
104
112
  Convenience option to parse an internal key on the command line. Dumps the
105
113
  internal key in hex format {'key' @ SN: type}
@@ -172,6 +180,7 @@ int SSTDumpTool::Run(int argc, char const* const* argv, Options options) {
172
180
  bool verify_checksum = false;
173
181
  bool output_hex = false;
174
182
  bool decode_blob_index = false;
183
+ bool show_sequence_number_type = false;
175
184
  bool input_key_hex = false;
176
185
  bool has_from = false;
177
186
  bool has_to = false;
@@ -188,8 +197,15 @@ int SSTDumpTool::Run(int argc, char const* const* argv, Options options) {
188
197
  std::string compression_level_to_str;
189
198
  size_t block_size = 16384; // A popular choice for default
190
199
  size_t readahead_size = 2 * 1024 * 1024;
200
+ // These two options are intentionally secret options because they are
201
+ // niche ways to select files to get the "recompress" treatment. And even
202
+ // if std::regex is flawed, it should be good enough for these niche uses.
203
+ std::unique_ptr<std::regex> require_property_regex;
204
+ std::unique_ptr<std::regex> exclude_property_regex;
191
205
  std::vector<CompressionType> compression_types;
192
206
  std::shared_ptr<CompressionManager> compression_manager;
207
+ bool enable_index_compression =
208
+ BlockBasedTableOptions{}.enable_index_compression;
193
209
  uint64_t total_num_files = 0;
194
210
  uint64_t total_num_data_blocks = 0;
195
211
  uint64_t total_data_block_size = 0;
@@ -223,6 +239,8 @@ int SSTDumpTool::Run(int argc, char const* const* argv, Options options) {
223
239
  output_hex = true;
224
240
  } else if (strcmp(argv[i], "--decode_blob_index") == 0) {
225
241
  decode_blob_index = true;
242
+ } else if (strcmp(argv[i], "--show_sequence_number_type") == 0) {
243
+ show_sequence_number_type = true;
226
244
  } else if (strcmp(argv[i], "--input_key_hex") == 0) {
227
245
  input_key_hex = true;
228
246
  } else if (sscanf(argv[i], "--read_num=%lu%c", (unsigned long*)&n, &junk) ==
@@ -268,6 +286,12 @@ int SSTDumpTool::Run(int argc, char const* const* argv, Options options) {
268
286
  }
269
287
  compression_types.emplace_back(iter->second);
270
288
  }
289
+ } else if (strncmp(argv[i], "--require_property_regex=", 25) == 0) {
290
+ require_property_regex = std::make_unique<std::regex>(
291
+ argv[i] + 25, std::regex_constants::egrep);
292
+ } else if (strncmp(argv[i], "--exclude_property_regex=", 25) == 0) {
293
+ exclude_property_regex = std::make_unique<std::regex>(
294
+ argv[i] + 25, std::regex_constants::egrep);
271
295
  } else if (strncmp(argv[i], "--compression_manager=", 22) == 0) {
272
296
  std::string compression_manager_str = argv[i] + 22;
273
297
  ConfigOptions config_options;
@@ -287,6 +311,11 @@ int SSTDumpTool::Run(int argc, char const* const* argv, Options options) {
287
311
  options.compression_manager = compression_manager;
288
312
  printf("Using compression manager: %s\n",
289
313
  compression_manager->GetId().c_str());
314
+ } else if (strncmp(argv[i], "--enable_index_compression=", 27) == 0) {
315
+ if (strlen(argv[i]) > 27) {
316
+ enable_index_compression =
317
+ argv[i][27] == '1' || argv[i][27] == 't' || argv[i][27] == 'T';
318
+ }
290
319
  } else if (strncmp(argv[i], "--parse_internal_key=", 21) == 0) {
291
320
  std::string in_key(argv[i] + 21);
292
321
  try {
@@ -492,6 +521,7 @@ int SSTDumpTool::Run(int argc, char const* const* argv, Options options) {
492
521
  bbto = *options.table_factory->GetOptions<BlockBasedTableOptions>();
493
522
  }
494
523
  bbto.block_size = block_size;
524
+ bbto.enable_index_compression = enable_index_compression;
495
525
  // Maximize compression features available
496
526
  bbto.format_version = kLatestFormatVersion;
497
527
  options.table_factory = std::make_shared<BlockBasedTableFactory>(bbto);
@@ -507,24 +537,45 @@ int SSTDumpTool::Run(int argc, char const* const* argv, Options options) {
507
537
 
508
538
  ROCKSDB_NAMESPACE::SstFileDumper dumper(
509
539
  options, filename, Temperature::kUnknown, readahead_size,
510
- verify_checksum, output_hex, decode_blob_index);
540
+ verify_checksum, output_hex, decode_blob_index, EnvOptions(), false,
541
+ show_sequence_number_type);
511
542
 
512
543
  // Not a valid SST
513
544
  if (!dumper.getStatus().ok()) {
514
545
  fprintf(stderr, "%s: %s\n", filename.c_str(),
515
546
  dumper.getStatus().ToString().c_str());
516
547
  continue;
517
- } else {
518
- valid_sst_files.push_back(filename);
519
- // Print out from and to key information once
520
- // where there is at least one valid SST
521
- if (valid_sst_files.size() == 1) {
522
- // from_key and to_key are only used for "check", "scan", or ""
523
- if (command == "check" || command == "scan" || command == "") {
524
- fprintf(stdout, "from [%s] to [%s]\n",
525
- ROCKSDB_NAMESPACE::Slice(from_key).ToString(true).c_str(),
526
- ROCKSDB_NAMESPACE::Slice(to_key).ToString(true).c_str());
527
- }
548
+ }
549
+ auto props_ptr = dumper.GetInitTableProperties();
550
+ if (props_ptr && (require_property_regex || exclude_property_regex)) {
551
+ // Call should match with show_properties below
552
+ auto props_str = props_ptr->ToString("\n ", ": ");
553
+ if (require_property_regex &&
554
+ !std::regex_search(props_str, *require_property_regex)) {
555
+ fprintf(stderr,
556
+ "%s: skipping because properties string doesn't match required "
557
+ "regex\n",
558
+ filename.c_str());
559
+ continue;
560
+ }
561
+ if (exclude_property_regex &&
562
+ std::regex_search(props_str, *exclude_property_regex)) {
563
+ fprintf(
564
+ stderr,
565
+ "%s: skipping because properties string matches excluded regex\n",
566
+ filename.c_str());
567
+ continue;
568
+ }
569
+ }
570
+ valid_sst_files.push_back(filename);
571
+ // Print out from and to key information once
572
+ // where there is at least one valid SST
573
+ if (valid_sst_files.size() == 1) {
574
+ // from_key and to_key are only used for "check", "scan", or ""
575
+ if (command == "check" || command == "scan" || command == "") {
576
+ fprintf(stdout, "from [%s] to [%s]\n",
577
+ ROCKSDB_NAMESPACE::Slice(from_key).ToString(true).c_str(),
578
+ ROCKSDB_NAMESPACE::Slice(to_key).ToString(true).c_str());
528
579
  }
529
580
  }
530
581
 
@@ -59,6 +59,17 @@ const char* AutoSkipCompressorWrapper::Name() const {
59
59
  return "AutoSkipCompressorWrapper";
60
60
  }
61
61
 
62
+ std::unique_ptr<Compressor> AutoSkipCompressorWrapper::Clone() const {
63
+ return std::make_unique<AutoSkipCompressorWrapper>(wrapped_->Clone(), opts_);
64
+ }
65
+
66
+ std::unique_ptr<Compressor> AutoSkipCompressorWrapper::MaybeCloneSpecialized(
67
+ CacheEntryRole block_type, DictSampleArgs&& dict_samples) const {
68
+ auto clone =
69
+ wrapped_->CloneMaybeSpecialized(block_type, std::move(dict_samples));
70
+ return std::make_unique<AutoSkipCompressorWrapper>(std::move(clone), opts_);
71
+ }
72
+
62
73
  Status AutoSkipCompressorWrapper::CompressBlock(
63
74
  Slice uncompressed_data, char* compressed_output,
64
75
  size_t* compressed_output_size, CompressionType* out_compression_type,
@@ -174,6 +185,10 @@ CostAwareCompressor::CostAwareCompressor(const CompressionOptions& opts)
174
185
  }
175
186
 
176
187
  const char* CostAwareCompressor::Name() const { return "CostAwareCompressor"; }
188
+
189
+ std::unique_ptr<Compressor> CostAwareCompressor::Clone() const {
190
+ return std::make_unique<CostAwareCompressor>(opts_);
191
+ }
177
192
  size_t CostAwareCompressor::GetMaxSampleSizeIfWantDict(
178
193
  CacheEntryRole block_type) const {
179
194
  auto idx = allcompressors_index_.back();
@@ -190,7 +205,7 @@ CompressionType CostAwareCompressor::GetPreferredCompressionType() const {
190
205
  return kZSTD;
191
206
  }
192
207
  std::unique_ptr<Compressor> CostAwareCompressor::MaybeCloneSpecialized(
193
- CacheEntryRole block_type, DictSampleArgs&& dict_samples) {
208
+ CacheEntryRole block_type, DictSampleArgs&& dict_samples) const {
194
209
  // TODO: full dictionary compression support. Currently this just falls
195
210
  // back on a non-multi compressor when asked to use a dictionary.
196
211
  auto idx = allcompressors_index_.back();
@@ -64,6 +64,9 @@ class AutoSkipCompressorWrapper : public CompressorWrapper {
64
64
  explicit AutoSkipCompressorWrapper(std::unique_ptr<Compressor> compressor,
65
65
  const CompressionOptions& opts);
66
66
 
67
+ std::unique_ptr<Compressor> Clone() const override;
68
+ std::unique_ptr<Compressor> MaybeCloneSpecialized(
69
+ CacheEntryRole block_type, DictSampleArgs&& dict_samples) const override;
67
70
  Status CompressBlock(Slice uncompressed_data, char* compressed_output,
68
71
  size_t* compressed_output_size,
69
72
  CompressionType* out_compression_type,
@@ -149,12 +152,13 @@ class CostAwareCompressor : public Compressor {
149
152
  public:
150
153
  explicit CostAwareCompressor(const CompressionOptions& opts);
151
154
  const char* Name() const override;
155
+ std::unique_ptr<Compressor> Clone() const override;
152
156
  size_t GetMaxSampleSizeIfWantDict(CacheEntryRole block_type) const override;
153
157
  Slice GetSerializedDict() const override;
154
158
  CompressionType GetPreferredCompressionType() const override;
155
159
  ManagedWorkingArea ObtainWorkingArea() override;
156
160
  std::unique_ptr<Compressor> MaybeCloneSpecialized(
157
- CacheEntryRole block_type, DictSampleArgs&& dict_samples) override;
161
+ CacheEntryRole block_type, DictSampleArgs&& dict_samples) const override;
158
162
 
159
163
  Status CompressBlock(Slice uncompressed_data, char* compressed_output,
160
164
  size_t* compressed_output_size,
@@ -6,8 +6,10 @@
6
6
  #pragma once
7
7
 
8
8
  #include <atomic>
9
+ #include <vector>
9
10
 
10
11
  #include "rocksdb/rocksdb_namespace.h"
12
+ #include "test_util/sync_point.h"
11
13
  #include "util/math.h"
12
14
 
13
15
  namespace ROCKSDB_NAMESPACE {
@@ -144,8 +146,44 @@ struct AndTransform {
144
146
  }
145
147
  };
146
148
 
147
- // TODO: AddTransfrom, which is more complicated due to possible overflow into
148
- // other fields etc.
149
+ // Can represent a combination of both subtractions and additions, representing
150
+ // subtractions as the addition of a negated value. To ensure we don't create a
151
+ // net overflow or underflow between fields, in debug builds we track the
152
+ // corresponding preconditions. (NOTE that when representing a subtraction, we
153
+ // rely on overflow of the unsigned representation.)
154
+ template <typename BitFieldsT>
155
+ struct AddTransform {
156
+ using U = typename BitFieldsT::U;
157
+ U to_add = 0;
158
+ #ifndef NDEBUG
159
+ struct Precondition {
160
+ U mask; // for bits of the target field
161
+ U piece; // component of to_add for the target field
162
+ };
163
+ std::vector<Precondition> preconditions;
164
+ #endif // NDEBUG
165
+ void AssertPreconditions([[maybe_unused]] U from) {
166
+ #ifndef NDEBUG
167
+ for (auto p : preconditions) {
168
+ U tmp = (from & p.mask) + p.piece;
169
+ // Assert no under/overflow (unless the field is at the top bits of the
170
+ // representation in U, which is allowed because it doesn't lead to
171
+ // leakage into other fields)
172
+ testable_assert((tmp & ~p.mask) == 0);
173
+ }
174
+ #endif // NDEBUG
175
+ }
176
+ // + for general combine
177
+ AddTransform<BitFieldsT> operator+(AddTransform<BitFieldsT> other) const {
178
+ AddTransform<BitFieldsT> rv{to_add + other.to_add};
179
+ #ifndef NDEBUG
180
+ rv.preconditions = preconditions;
181
+ rv.preconditions.insert(rv.preconditions.end(), other.preconditions.begin(),
182
+ other.preconditions.end());
183
+ #endif // NDEBUG
184
+ return rv;
185
+ }
186
+ };
149
187
 
150
188
  // Placeholder for PrevField for the first field
151
189
  struct NoPrevBitField {
@@ -204,6 +242,7 @@ struct UnsignedBitField {
204
242
  static_assert(kBitCount >= 1);
205
243
  static_assert(kBitCount <= 64);
206
244
  static_assert(kBitOffset >= 0 && kEndBit <= BitFieldsT::kBitCount);
245
+ static constexpr bool kIncludesTopBit = (kEndBit == BitFieldsT::kBitCount);
207
246
 
208
247
  static constexpr V kMask = (V{1} << (kBitCount - 1) << 1) - 1;
209
248
 
@@ -219,9 +258,59 @@ struct UnsignedBitField {
219
258
  bf.underlying |= static_cast<U>(value & kMask) << kBitOffset;
220
259
  }
221
260
 
261
+ // Create a transfor for clearing this field to zero.
222
262
  static AndTransform<BitFieldsT> ClearTransform() {
223
263
  return AndTransform<BitFieldsT>{~(static_cast<U>(kMask) << kBitOffset)};
224
264
  }
265
+
266
+ // Create a transform for adding a particular value, but with the precondition
267
+ // that adding the value will not overflow the field. This applies for fields
268
+ // that do not include the top bit of the underlying representation. Can be
269
+ // combined with other additive transforms for other fields.
270
+ static AddTransform<BitFieldsT> PlusTransformPromiseNoOverflow(V value) {
271
+ static_assert(!kIncludesTopBit);
272
+ AddTransform<BitFieldsT> rv{static_cast<U>(value) << kBitOffset};
273
+ #ifndef NDEBUG
274
+ rv.preconditions.push_back(
275
+ {static_cast<U>(kMask) << kBitOffset, rv.to_add});
276
+ #endif // NDEBUG
277
+ return rv;
278
+ }
279
+
280
+ // Create a transform for adding a particular value, but ignoring any overflow
281
+ // in that field. This applies for fields that include the top bit of the
282
+ // underlying representation. Can be combined with other additive transforms
283
+ // for other fields.
284
+ static AddTransform<BitFieldsT> PlusTransformIgnoreOverflow(V value) {
285
+ static_assert(kIncludesTopBit);
286
+ AddTransform<BitFieldsT> rv{static_cast<U>(value) << kBitOffset};
287
+ return rv;
288
+ }
289
+
290
+ // Create a transform for subtracting a particular value, but with the
291
+ // precondition that subtracting the value will not underflow the field. This
292
+ // applies for fields that do not include the top bit of the underlying
293
+ // representation. Can be combined with other additive transforms for other
294
+ // fields.
295
+ static AddTransform<BitFieldsT> MinusTransformPromiseNoUnderflow(V value) {
296
+ static_assert(!kIncludesTopBit);
297
+ AddTransform<BitFieldsT> rv{U{0} - (static_cast<U>(value) << kBitOffset)};
298
+ #ifndef NDEBUG
299
+ rv.preconditions.push_back(
300
+ {static_cast<U>(kMask) << kBitOffset, rv.to_add});
301
+ #endif // NDEBUG
302
+ return rv;
303
+ }
304
+
305
+ // Create a transform for subtracting a particular value, but ignoring any
306
+ // underflow in that field. This applies for fields that include the top bit
307
+ // of the underlying representation. Can be combined with other additive
308
+ // transforms for other fields.
309
+ static AddTransform<BitFieldsT> MinusTransformIgnoreUnderflow(V value) {
310
+ static_assert(kIncludesTopBit);
311
+ AddTransform<BitFieldsT> rv{U{0} - (static_cast<U>(value) << kBitOffset)};
312
+ return rv;
313
+ }
225
314
  };
226
315
 
227
316
  // A handy wrapper for a relaxed atomic on some BitFields type (unlike
@@ -260,7 +349,22 @@ class RelaxedBitFieldsAtomic {
260
349
  }
261
350
  void ApplyRelaxed(OrTransform<BitFieldsT> transform,
262
351
  BitFieldsT* before = nullptr, BitFieldsT* after = nullptr) {
263
- U before_val = v_.fetch_or(transform.to_or, std::memory_order_relaxed);
352
+ ApplyImpl<std::memory_order_relaxed>(transform, before, after);
353
+ }
354
+ void ApplyRelaxed(AndTransform<BitFieldsT> transform,
355
+ BitFieldsT* before = nullptr, BitFieldsT* after = nullptr) {
356
+ ApplyImpl<std::memory_order_relaxed>(transform, before, after);
357
+ }
358
+ void ApplyRelaxed(AddTransform<BitFieldsT> transform,
359
+ BitFieldsT* before = nullptr, BitFieldsT* after = nullptr) {
360
+ ApplyImpl<std::memory_order_relaxed>(transform, before, after);
361
+ }
362
+
363
+ protected: // fns
364
+ template <std::memory_order kOrder>
365
+ void ApplyImpl(OrTransform<BitFieldsT> transform,
366
+ BitFieldsT* before = nullptr, BitFieldsT* after = nullptr) {
367
+ U before_val = v_.fetch_or(transform.to_or, kOrder);
264
368
  if (before) {
265
369
  before->underlying = before_val;
266
370
  }
@@ -268,9 +372,10 @@ class RelaxedBitFieldsAtomic {
268
372
  after->underlying = before_val | transform.to_or;
269
373
  }
270
374
  }
271
- void ApplyRelaxed(AndTransform<BitFieldsT> transform,
272
- BitFieldsT* before = nullptr, BitFieldsT* after = nullptr) {
273
- U before_val = v_.fetch_and(transform.to_and, std::memory_order_relaxed);
375
+ template <std::memory_order kOrder>
376
+ void ApplyImpl(AndTransform<BitFieldsT> transform,
377
+ BitFieldsT* before = nullptr, BitFieldsT* after = nullptr) {
378
+ U before_val = v_.fetch_and(transform.to_and, kOrder);
274
379
  if (before) {
275
380
  before->underlying = before_val;
276
381
  }
@@ -278,8 +383,20 @@ class RelaxedBitFieldsAtomic {
278
383
  after->underlying = before_val & transform.to_and;
279
384
  }
280
385
  }
386
+ template <std::memory_order kOrder>
387
+ void ApplyImpl(AddTransform<BitFieldsT> transform,
388
+ BitFieldsT* before = nullptr, BitFieldsT* after = nullptr) {
389
+ U before_val = v_.fetch_add(transform.to_add, kOrder);
390
+ transform.AssertPreconditions(before_val);
391
+ if (before) {
392
+ before->underlying = before_val;
393
+ }
394
+ if (after) {
395
+ after->underlying = before_val + transform.to_add;
396
+ }
397
+ }
281
398
 
282
- protected:
399
+ protected: // data
283
400
  std::atomic<U> v_;
284
401
  };
285
402
 
@@ -313,25 +430,18 @@ class AcqRelBitFieldsAtomic : public RelaxedBitFieldsAtomic<BitFieldsT> {
313
430
  }
314
431
  void Apply(OrTransform<BitFieldsT> transform, BitFieldsT* before = nullptr,
315
432
  BitFieldsT* after = nullptr) {
316
- U before_val =
317
- Base::v_.fetch_or(transform.to_or, std::memory_order_acq_rel);
318
- if (before) {
319
- before->underlying = before_val;
320
- }
321
- if (after) {
322
- after->underlying = before_val | transform.to_or;
323
- }
433
+ Base::template ApplyImpl<std::memory_order_acq_rel>(transform, before,
434
+ after);
324
435
  }
325
436
  void Apply(AndTransform<BitFieldsT> transform, BitFieldsT* before = nullptr,
326
437
  BitFieldsT* after = nullptr) {
327
- U before_val =
328
- Base::v_.fetch_and(transform.to_and, std::memory_order_acq_rel);
329
- if (before) {
330
- before->underlying = before_val;
331
- }
332
- if (after) {
333
- after->underlying = before_val & transform.to_and;
334
- }
438
+ Base::template ApplyImpl<std::memory_order_acq_rel>(transform, before,
439
+ after);
440
+ }
441
+ void Apply(AddTransform<BitFieldsT> transform, BitFieldsT* before = nullptr,
442
+ BitFieldsT* after = nullptr) {
443
+ Base::template ApplyImpl<std::memory_order_acq_rel>(transform, before,
444
+ after);
335
445
  }
336
446
  };
337
447
 
@@ -86,10 +86,7 @@ class FullBloomTest : public testing::TestWithParam<std::string> {
86
86
  ResetPolicy();
87
87
  }
88
88
 
89
- BuiltinFilterBitsBuilder* GetBuiltinFilterBitsBuilder() {
90
- // Throws on bad cast
91
- return dynamic_cast<BuiltinFilterBitsBuilder*>(bits_builder_.get());
92
- }
89
+ FilterBitsBuilder* GetFilterBitsBuilder() { return bits_builder_.get(); }
93
90
 
94
91
  const BloomLikeFilterPolicy* GetBloomLikeFilterPolicy() {
95
92
  // Throws on bad cast
@@ -239,7 +236,7 @@ TEST_P(FullBloomTest, FilterSize) {
239
236
  EXPECT_EQ(bpk.second, bfp->GetMillibitsPerKey());
240
237
  EXPECT_EQ((bpk.second + 500) / 1000, bfp->GetWholeBitsPerKey());
241
238
 
242
- auto bits_builder = GetBuiltinFilterBitsBuilder();
239
+ auto bits_builder = GetFilterBitsBuilder();
243
240
  if (bpk.second == 0) {
244
241
  ASSERT_EQ(bits_builder, nullptr);
245
242
  continue;