@nxtedition/rocksdb 7.0.26 → 7.0.29

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 (121) hide show
  1. package/binding.cc +67 -25
  2. package/chained-batch.js +1 -1
  3. package/deps/rocksdb/rocksdb/CMakeLists.txt +3 -0
  4. package/deps/rocksdb/rocksdb/Makefile +3 -0
  5. package/deps/rocksdb/rocksdb/TARGETS +10 -0
  6. package/deps/rocksdb/rocksdb/cache/cache_bench_tool.cc +17 -7
  7. package/deps/rocksdb/rocksdb/cache/cache_entry_roles.cc +2 -0
  8. package/deps/rocksdb/rocksdb/cache/cache_reservation_manager.cc +1 -0
  9. package/deps/rocksdb/rocksdb/cache/charged_cache.cc +117 -0
  10. package/deps/rocksdb/rocksdb/cache/charged_cache.h +121 -0
  11. package/deps/rocksdb/rocksdb/cache/clock_cache.cc +270 -180
  12. package/deps/rocksdb/rocksdb/cache/clock_cache.h +412 -124
  13. package/deps/rocksdb/rocksdb/cache/fast_lru_cache.cc +1 -0
  14. package/deps/rocksdb/rocksdb/cache/lru_cache.cc +1 -1
  15. package/deps/rocksdb/rocksdb/cache/lru_cache.h +2 -2
  16. package/deps/rocksdb/rocksdb/cache/lru_cache_test.cc +2 -2
  17. package/deps/rocksdb/rocksdb/cache/sharded_cache.h +1 -1
  18. package/deps/rocksdb/rocksdb/db/blob/blob_file_builder.cc +71 -9
  19. package/deps/rocksdb/rocksdb/db/blob/blob_file_builder.h +11 -2
  20. package/deps/rocksdb/rocksdb/db/blob/blob_file_builder_test.cc +21 -14
  21. package/deps/rocksdb/rocksdb/db/blob/blob_source.cc +68 -7
  22. package/deps/rocksdb/rocksdb/db/blob/blob_source.h +16 -0
  23. package/deps/rocksdb/rocksdb/db/blob/blob_source_test.cc +519 -12
  24. package/deps/rocksdb/rocksdb/db/blob/db_blob_basic_test.cc +120 -0
  25. package/deps/rocksdb/rocksdb/db/builder.cc +15 -5
  26. package/deps/rocksdb/rocksdb/db/builder.h +3 -0
  27. package/deps/rocksdb/rocksdb/db/c.cc +18 -0
  28. package/deps/rocksdb/rocksdb/db/c_test.c +18 -0
  29. package/deps/rocksdb/rocksdb/db/column_family.h +2 -0
  30. package/deps/rocksdb/rocksdb/db/compaction/clipping_iterator.h +3 -2
  31. package/deps/rocksdb/rocksdb/db/compaction/compaction.cc +9 -4
  32. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.cc +15 -10
  33. package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.h +36 -34
  34. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +50 -13
  35. package/deps/rocksdb/rocksdb/db/compaction/compaction_job.h +12 -0
  36. package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.cc +8 -1
  37. package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.h +2 -1
  38. package/deps/rocksdb/rocksdb/db/compaction/tiered_compaction_test.cc +13 -17
  39. package/deps/rocksdb/rocksdb/db/db_basic_test.cc +26 -9
  40. package/deps/rocksdb/rocksdb/db/db_compaction_test.cc +0 -11
  41. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +93 -0
  42. package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +16 -1
  43. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +3 -8
  44. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_debug.cc +8 -1
  45. package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +17 -5
  46. package/deps/rocksdb/rocksdb/db/db_test.cc +0 -3
  47. package/deps/rocksdb/rocksdb/db/db_test2.cc +39 -12
  48. package/deps/rocksdb/rocksdb/db/db_test_util.cc +9 -0
  49. package/deps/rocksdb/rocksdb/db/db_test_util.h +2 -0
  50. package/deps/rocksdb/rocksdb/db/dbformat.cc +0 -38
  51. package/deps/rocksdb/rocksdb/db/dbformat.h +14 -13
  52. package/deps/rocksdb/rocksdb/db/dbformat_test.cc +5 -2
  53. package/deps/rocksdb/rocksdb/db/event_helpers.cc +13 -1
  54. package/deps/rocksdb/rocksdb/db/external_sst_file_basic_test.cc +0 -10
  55. package/deps/rocksdb/rocksdb/db/flush_job.cc +19 -15
  56. package/deps/rocksdb/rocksdb/db/flush_job.h +7 -0
  57. package/deps/rocksdb/rocksdb/db/flush_job_test.cc +21 -15
  58. package/deps/rocksdb/rocksdb/db/forward_iterator.h +4 -3
  59. package/deps/rocksdb/rocksdb/db/memtable_list.cc +9 -0
  60. package/deps/rocksdb/rocksdb/db/memtable_list.h +5 -0
  61. package/deps/rocksdb/rocksdb/db/periodic_work_scheduler.cc +53 -12
  62. package/deps/rocksdb/rocksdb/db/periodic_work_scheduler.h +14 -2
  63. package/deps/rocksdb/rocksdb/db/periodic_work_scheduler_test.cc +10 -10
  64. package/deps/rocksdb/rocksdb/db/repair.cc +8 -6
  65. package/deps/rocksdb/rocksdb/db/seqno_time_test.cc +890 -0
  66. package/deps/rocksdb/rocksdb/db/seqno_to_time_mapping.cc +324 -0
  67. package/deps/rocksdb/rocksdb/db/seqno_to_time_mapping.h +186 -0
  68. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +2 -0
  69. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +13 -4
  70. package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +23 -2
  71. package/deps/rocksdb/rocksdb/env/env_test.cc +74 -1
  72. package/deps/rocksdb/rocksdb/env/io_posix.cc +11 -8
  73. package/deps/rocksdb/rocksdb/include/rocksdb/advanced_options.h +28 -0
  74. package/deps/rocksdb/rocksdb/include/rocksdb/c.h +14 -1
  75. package/deps/rocksdb/rocksdb/include/rocksdb/cache.h +4 -4
  76. package/deps/rocksdb/rocksdb/include/rocksdb/comparator.h +30 -23
  77. package/deps/rocksdb/rocksdb/include/rocksdb/db.h +1 -1
  78. package/deps/rocksdb/rocksdb/include/rocksdb/rate_limiter.h +3 -13
  79. package/deps/rocksdb/rocksdb/include/rocksdb/table_properties.h +5 -0
  80. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/debug.h +1 -2
  81. package/deps/rocksdb/rocksdb/include/rocksdb/utilities/ldb_cmd.h +1 -0
  82. package/deps/rocksdb/rocksdb/include/rocksdb/version.h +1 -1
  83. package/deps/rocksdb/rocksdb/monitoring/stats_history_test.cc +26 -26
  84. package/deps/rocksdb/rocksdb/options/cf_options.cc +14 -1
  85. package/deps/rocksdb/rocksdb/options/cf_options.h +5 -0
  86. package/deps/rocksdb/rocksdb/options/customizable_test.cc +0 -56
  87. package/deps/rocksdb/rocksdb/options/db_options.cc +4 -5
  88. package/deps/rocksdb/rocksdb/options/options.cc +11 -1
  89. package/deps/rocksdb/rocksdb/options/options_helper.cc +8 -0
  90. package/deps/rocksdb/rocksdb/options/options_helper.h +4 -0
  91. package/deps/rocksdb/rocksdb/options/options_settable_test.cc +4 -0
  92. package/deps/rocksdb/rocksdb/options/options_test.cc +4 -0
  93. package/deps/rocksdb/rocksdb/src.mk +3 -0
  94. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.cc +6 -1
  95. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.h +4 -0
  96. package/deps/rocksdb/rocksdb/table/block_based/block_based_table_factory.cc +36 -3
  97. package/deps/rocksdb/rocksdb/table/block_based/index_builder.cc +36 -1
  98. package/deps/rocksdb/rocksdb/table/block_based/index_builder.h +14 -3
  99. package/deps/rocksdb/rocksdb/table/internal_iterator.h +1 -1
  100. package/deps/rocksdb/rocksdb/table/meta_blocks.cc +6 -0
  101. package/deps/rocksdb/rocksdb/table/plain/plain_table_builder.cc +5 -0
  102. package/deps/rocksdb/rocksdb/table/plain/plain_table_builder.h +3 -0
  103. package/deps/rocksdb/rocksdb/table/sst_file_writer.cc +10 -7
  104. package/deps/rocksdb/rocksdb/table/table_builder.h +7 -3
  105. package/deps/rocksdb/rocksdb/table/table_properties.cc +9 -0
  106. package/deps/rocksdb/rocksdb/test_util/mock_time_env.h +3 -2
  107. package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +58 -30
  108. package/deps/rocksdb/rocksdb/tools/db_bench_tool_test.cc +1 -0
  109. package/deps/rocksdb/rocksdb/tools/ldb_cmd.cc +20 -0
  110. package/deps/rocksdb/rocksdb/util/rate_limiter.cc +29 -154
  111. package/deps/rocksdb/rocksdb/util/rate_limiter.h +16 -34
  112. package/deps/rocksdb/rocksdb/util/rate_limiter_test.cc +0 -92
  113. package/deps/rocksdb/rocksdb/util/timer.h +6 -0
  114. package/deps/rocksdb/rocksdb/util/vector_iterator.h +4 -3
  115. package/deps/rocksdb/rocksdb/utilities/backup/backup_engine.cc +4 -45
  116. package/deps/rocksdb/rocksdb/utilities/debug.cc +40 -0
  117. package/deps/rocksdb/rocksdb.gyp +2 -0
  118. package/index.js +4 -0
  119. package/package.json +1 -1
  120. package/prebuilds/darwin-arm64/node.napi.node +0 -0
  121. package/prebuilds/linux-x64/node.napi.node +0 -0
@@ -5,6 +5,7 @@
5
5
 
6
6
  #include "rocksdb/table_properties.h"
7
7
 
8
+ #include "db/seqno_to_time_mapping.h"
8
9
  #include "port/malloc.h"
9
10
  #include "port/port.h"
10
11
  #include "rocksdb/env.h"
@@ -164,6 +165,12 @@ std::string TableProperties::ToString(
164
165
  s.ok() ? UniqueIdToHumanString(id) : "N/A", prop_delim,
165
166
  kv_delim);
166
167
 
168
+ SeqnoToTimeMapping seq_time_mapping;
169
+ s = seq_time_mapping.Add(seqno_to_time_mapping);
170
+ AppendProperty(result, "Sequence number to time mapping",
171
+ s.ok() ? seq_time_mapping.ToHumanString() : "N/A", prop_delim,
172
+ kv_delim);
173
+
167
174
  return result;
168
175
  }
169
176
 
@@ -307,6 +314,8 @@ const std::string TablePropertiesNames::kSlowCompressionEstimatedDataSize =
307
314
  "rocksdb.sample_for_compression.slow.data.size";
308
315
  const std::string TablePropertiesNames::kFastCompressionEstimatedDataSize =
309
316
  "rocksdb.sample_for_compression.fast.data.size";
317
+ const std::string TablePropertiesNames::kSequenceNumberTimeMapping =
318
+ "rocksdb.seqno.time.map";
310
319
 
311
320
  #ifndef NDEBUG
312
321
  // WARNING: TEST_SetRandomTableProperties assumes the following layout of
@@ -60,8 +60,9 @@ class MockSystemClock : public SystemClockWrapper {
60
60
 
61
61
  void MockSleepForSeconds(int seconds) {
62
62
  assert(seconds >= 0);
63
- int micros = seconds * kMicrosInSecond;
64
- SleepForMicroseconds(micros);
63
+ uint64_t micros = static_cast<uint64_t>(seconds) * kMicrosInSecond;
64
+ assert(current_time_us_ + micros >= current_time_us_);
65
+ current_time_us_.fetch_add(micros);
65
66
  }
66
67
 
67
68
  // TODO: this is a workaround for the different behavior on different platform
@@ -1096,6 +1096,10 @@ DEFINE_int32(blob_cache_numshardbits, 6,
1096
1096
  "the block and blob caches are different "
1097
1097
  "(use_shared_block_and_blob_cache = false).");
1098
1098
 
1099
+ DEFINE_int32(prepopulate_blob_cache, 0,
1100
+ "[Integrated BlobDB] Pre-populate hot/warm blobs in blob cache. 0 "
1101
+ "to disable and 1 to insert during flush.");
1102
+
1099
1103
  #ifndef ROCKSDB_LITE
1100
1104
 
1101
1105
  // Secondary DB instance Options
@@ -1166,24 +1170,29 @@ DEFINE_bool(async_io, false,
1166
1170
 
1167
1171
  DEFINE_bool(charge_compression_dictionary_building_buffer, false,
1168
1172
  "Setting for "
1169
- "CacheEntryRoleOptions::charged of"
1173
+ "CacheEntryRoleOptions::charged of "
1170
1174
  "CacheEntryRole::kCompressionDictionaryBuildingBuffer");
1171
1175
 
1172
1176
  DEFINE_bool(charge_filter_construction, false,
1173
1177
  "Setting for "
1174
- "CacheEntryRoleOptions::charged of"
1178
+ "CacheEntryRoleOptions::charged of "
1175
1179
  "CacheEntryRole::kFilterConstruction");
1176
1180
 
1177
1181
  DEFINE_bool(charge_table_reader, false,
1178
1182
  "Setting for "
1179
- "CacheEntryRoleOptions::charged of"
1183
+ "CacheEntryRoleOptions::charged of "
1180
1184
  "CacheEntryRole::kBlockBasedTableReader");
1181
1185
 
1182
1186
  DEFINE_bool(charge_file_metadata, false,
1183
1187
  "Setting for "
1184
- "CacheEntryRoleOptions::charged of"
1188
+ "CacheEntryRoleOptions::charged of "
1185
1189
  "CacheEntryRole::kFileMetadata");
1186
1190
 
1191
+ DEFINE_bool(charge_blob_cache, false,
1192
+ "Setting for "
1193
+ "CacheEntryRoleOptions::charged of "
1194
+ "CacheEntryRole::kBlobCache");
1195
+
1187
1196
  DEFINE_uint64(backup_rate_limit, 0ull,
1188
1197
  "If non-zero, db_bench will rate limit reads and writes for DB "
1189
1198
  "backup. This "
@@ -4290,6 +4299,11 @@ class Benchmark {
4290
4299
  {/*.charged = */ FLAGS_charge_file_metadata
4291
4300
  ? CacheEntryRoleOptions::Decision::kEnabled
4292
4301
  : CacheEntryRoleOptions::Decision::kDisabled}});
4302
+ block_based_options.cache_usage_options.options_overrides.insert(
4303
+ {CacheEntryRole::kBlobCache,
4304
+ {/*.charged = */ FLAGS_charge_blob_cache
4305
+ ? CacheEntryRoleOptions::Decision::kEnabled
4306
+ : CacheEntryRoleOptions::Decision::kDisabled}});
4293
4307
  block_based_options.block_cache_compressed = compressed_cache_;
4294
4308
  block_based_options.block_size = FLAGS_block_size;
4295
4309
  block_based_options.block_restart_interval = FLAGS_block_restart_interval;
@@ -4365,6 +4379,46 @@ class Benchmark {
4365
4379
 
4366
4380
  #endif
4367
4381
  }
4382
+
4383
+ if (FLAGS_use_blob_cache) {
4384
+ if (FLAGS_use_shared_block_and_blob_cache) {
4385
+ options.blob_cache = cache_;
4386
+ } else {
4387
+ if (FLAGS_blob_cache_size > 0) {
4388
+ LRUCacheOptions co;
4389
+ co.capacity = FLAGS_blob_cache_size;
4390
+ co.num_shard_bits = FLAGS_blob_cache_numshardbits;
4391
+ options.blob_cache = NewLRUCache(co);
4392
+ } else {
4393
+ fprintf(
4394
+ stderr,
4395
+ "Unable to create a standalone blob cache if blob_cache_size "
4396
+ "<= 0.\n");
4397
+ exit(1);
4398
+ }
4399
+ }
4400
+ switch (FLAGS_prepopulate_blob_cache) {
4401
+ case 0:
4402
+ options.prepopulate_blob_cache = PrepopulateBlobCache::kDisable;
4403
+ break;
4404
+ case 1:
4405
+ options.prepopulate_blob_cache = PrepopulateBlobCache::kFlushOnly;
4406
+ break;
4407
+ default:
4408
+ fprintf(stderr, "Unknown prepopulate blob cache mode\n");
4409
+ exit(1);
4410
+ }
4411
+ fprintf(stdout,
4412
+ "Integrated BlobDB: blob cache enabled, block and blob caches "
4413
+ "shared: %d, blob cache size %" PRIu64
4414
+ ", blob cache num shard bits: %d, hot/warm blobs prepopulated: "
4415
+ "%d\n",
4416
+ FLAGS_use_shared_block_and_blob_cache, FLAGS_blob_cache_size,
4417
+ FLAGS_blob_cache_numshardbits, FLAGS_prepopulate_blob_cache);
4418
+ } else {
4419
+ fprintf(stdout, "Integrated BlobDB: blob cache disabled\n");
4420
+ }
4421
+
4368
4422
  options.table_factory.reset(
4369
4423
  NewBlockBasedTableFactory(block_based_options));
4370
4424
  }
@@ -4508,32 +4562,6 @@ class Benchmark {
4508
4562
  FLAGS_blob_compaction_readahead_size;
4509
4563
  options.blob_file_starting_level = FLAGS_blob_file_starting_level;
4510
4564
 
4511
- if (FLAGS_use_blob_cache) {
4512
- if (FLAGS_use_shared_block_and_blob_cache) {
4513
- options.blob_cache = cache_;
4514
- } else {
4515
- if (FLAGS_blob_cache_size > 0) {
4516
- LRUCacheOptions co;
4517
- co.capacity = FLAGS_blob_cache_size;
4518
- co.num_shard_bits = FLAGS_blob_cache_numshardbits;
4519
- options.blob_cache = NewLRUCache(co);
4520
- } else {
4521
- fprintf(stderr,
4522
- "Unable to create a standalone blob cache if blob_cache_size "
4523
- "<= 0.\n");
4524
- exit(1);
4525
- }
4526
- }
4527
- fprintf(stdout,
4528
- "Integrated BlobDB: blob cache enabled, block and blob caches "
4529
- "shared: %d, blob cache size %" PRIu64
4530
- ", blob cache num shard bits: %d\n",
4531
- FLAGS_use_shared_block_and_blob_cache, FLAGS_blob_cache_size,
4532
- FLAGS_blob_cache_numshardbits);
4533
- } else {
4534
- fprintf(stdout, "Integrated BlobDB: blob cache disabled\n");
4535
- }
4536
-
4537
4565
  #ifndef ROCKSDB_LITE
4538
4566
  if (FLAGS_readonly && FLAGS_transaction_db) {
4539
4567
  fprintf(stderr, "Cannot use readonly flag with transaction_db\n");
@@ -276,6 +276,7 @@ const std::string options_file_content = R"OPTIONS_FILE(
276
276
  blob_garbage_collection_force_threshold=0.75
277
277
  blob_compaction_readahead_size=262144
278
278
  blob_file_starting_level=0
279
+ prepopulate_blob_cache=kDisable;
279
280
 
280
281
  [TableOptions/BlockBasedTable "default"]
281
282
  format_version=0
@@ -102,6 +102,8 @@ const std::string LDBCommand::ARG_BLOB_COMPACTION_READAHEAD_SIZE =
102
102
  "blob_compaction_readahead_size";
103
103
  const std::string LDBCommand::ARG_BLOB_FILE_STARTING_LEVEL =
104
104
  "blob_file_starting_level";
105
+ const std::string LDBCommand::ARG_PREPOPULATE_BLOB_CACHE =
106
+ "prepopulate_blob_cache";
105
107
  const std::string LDBCommand::ARG_DECODE_BLOB_INDEX = "decode_blob_index";
106
108
  const std::string LDBCommand::ARG_DUMP_UNCOMPRESSED_BLOBS =
107
109
  "dump_uncompressed_blobs";
@@ -556,6 +558,7 @@ std::vector<std::string> LDBCommand::BuildCmdLineOptions(
556
558
  ARG_BLOB_GARBAGE_COLLECTION_FORCE_THRESHOLD,
557
559
  ARG_BLOB_COMPACTION_READAHEAD_SIZE,
558
560
  ARG_BLOB_FILE_STARTING_LEVEL,
561
+ ARG_PREPOPULATE_BLOB_CACHE,
559
562
  ARG_IGNORE_UNKNOWN_OPTIONS,
560
563
  ARG_CF_NAME};
561
564
  ret.insert(ret.end(), options.begin(), options.end());
@@ -833,6 +836,23 @@ void LDBCommand::OverrideBaseCFOptions(ColumnFamilyOptions* cf_opts) {
833
836
  }
834
837
  }
835
838
 
839
+ int prepopulate_blob_cache;
840
+ if (ParseIntOption(option_map_, ARG_PREPOPULATE_BLOB_CACHE,
841
+ prepopulate_blob_cache, exec_state_)) {
842
+ switch (prepopulate_blob_cache) {
843
+ case 0:
844
+ cf_opts->prepopulate_blob_cache = PrepopulateBlobCache::kDisable;
845
+ break;
846
+ case 1:
847
+ cf_opts->prepopulate_blob_cache = PrepopulateBlobCache::kFlushOnly;
848
+ break;
849
+ default:
850
+ exec_state_ = LDBCommandExecuteResult::Failed(
851
+ ARG_PREPOPULATE_BLOB_CACHE +
852
+ " must be 0 (disable) or 1 (flush only).");
853
+ }
854
+ }
855
+
836
856
  auto itr = option_map_.find(ARG_AUTO_COMPACTION);
837
857
  if (itr != option_map_.end()) {
838
858
  cf_opts->disable_auto_compactions = !StringToBool(itr->second);
@@ -13,14 +13,9 @@
13
13
 
14
14
  #include "monitoring/statistics.h"
15
15
  #include "port/port.h"
16
- #include "rocksdb/convenience.h"
17
16
  #include "rocksdb/system_clock.h"
18
- #include "rocksdb/utilities/customizable_util.h"
19
- #include "rocksdb/utilities/object_registry.h"
20
- #include "rocksdb/utilities/options_type.h"
21
17
  #include "test_util/sync_point.h"
22
18
  #include "util/aligned_buffer.h"
23
- #include "util/string_util.h"
24
19
 
25
20
  namespace ROCKSDB_NAMESPACE {
26
21
  size_t RateLimiter::RequestToken(size_t bytes, size_t alignment,
@@ -50,68 +45,33 @@ struct GenericRateLimiter::Req {
50
45
  bool granted;
51
46
  };
52
47
 
53
- static std::unordered_map<std::string, OptionTypeInfo>
54
- generic_rate_limiter_type_info = {
55
- #ifndef ROCKSDB_LITE
56
- {"rate_bytes_per_sec",
57
- {offsetof(struct GenericRateLimiter::GenericRateLimiterOptions,
58
- max_bytes_per_sec),
59
- OptionType::kInt64T}},
60
- {"refill_period_us",
61
- {offsetof(struct GenericRateLimiter::GenericRateLimiterOptions,
62
- refill_period_us),
63
- OptionType::kInt64T}},
64
- {"fairness",
65
- {offsetof(struct GenericRateLimiter::GenericRateLimiterOptions,
66
- fairness),
67
- OptionType::kInt32T}},
68
- {"auto_tuned",
69
- {offsetof(struct GenericRateLimiter::GenericRateLimiterOptions,
70
- auto_tuned),
71
- OptionType::kBoolean}},
72
- {"clock",
73
- OptionTypeInfo::AsCustomSharedPtr<SystemClock>(
74
- offsetof(struct GenericRateLimiter::GenericRateLimiterOptions,
75
- clock),
76
- OptionVerificationType::kByNameAllowFromNull,
77
- OptionTypeFlags::kAllowNull)},
78
- #endif // ROCKSDB_LITE
79
- };
80
-
81
48
  GenericRateLimiter::GenericRateLimiter(
82
49
  int64_t rate_bytes_per_sec, int64_t refill_period_us, int32_t fairness,
83
50
  RateLimiter::Mode mode, const std::shared_ptr<SystemClock>& clock,
84
51
  bool auto_tuned)
85
52
  : RateLimiter(mode),
86
- options_(rate_bytes_per_sec, refill_period_us, fairness, clock,
87
- auto_tuned),
53
+ refill_period_us_(refill_period_us),
54
+ rate_bytes_per_sec_(auto_tuned ? rate_bytes_per_sec / 2
55
+ : rate_bytes_per_sec),
56
+ refill_bytes_per_period_(
57
+ CalculateRefillBytesPerPeriod(rate_bytes_per_sec_)),
58
+ clock_(clock),
88
59
  stop_(false),
89
60
  exit_cv_(&request_mutex_),
90
61
  requests_to_wait_(0),
91
62
  available_bytes_(0),
63
+ next_refill_us_(NowMicrosMonotonic()),
64
+ fairness_(fairness > 100 ? 100 : fairness),
92
65
  rnd_((uint32_t)time(nullptr)),
93
66
  wait_until_refill_pending_(false),
94
- num_drains_(0) {
95
- RegisterOptions(&options_, &generic_rate_limiter_type_info);
67
+ auto_tuned_(auto_tuned),
68
+ num_drains_(0),
69
+ max_bytes_per_sec_(rate_bytes_per_sec),
70
+ tuned_time_(NowMicrosMonotonic()) {
96
71
  for (int i = Env::IO_LOW; i < Env::IO_TOTAL; ++i) {
97
72
  total_requests_[i] = 0;
98
73
  total_bytes_through_[i] = 0;
99
74
  }
100
- Initialize();
101
- }
102
- void GenericRateLimiter::Initialize() {
103
- if (options_.clock == nullptr) {
104
- options_.clock = SystemClock::Default();
105
- }
106
- options_.fairness = std::min(options_.fairness, 100);
107
- next_refill_us_ = NowMicrosMonotonic();
108
- tuned_time_ = std::chrono::microseconds(NowMicrosMonotonic());
109
- if (options_.auto_tuned) {
110
- rate_bytes_per_sec_ = options_.max_bytes_per_sec / 2;
111
- } else {
112
- rate_bytes_per_sec_ = options_.max_bytes_per_sec;
113
- }
114
- refill_bytes_per_period_ = CalculateRefillBytesPerPeriod(rate_bytes_per_sec_);
115
75
  }
116
76
 
117
77
  GenericRateLimiter::~GenericRateLimiter() {
@@ -135,18 +95,6 @@ GenericRateLimiter::~GenericRateLimiter() {
135
95
  }
136
96
  }
137
97
 
138
- Status GenericRateLimiter::PrepareOptions(const ConfigOptions& options) {
139
- if (options_.fairness <= 0) {
140
- return Status::InvalidArgument("Fairness must be > 0");
141
- } else if (options_.max_bytes_per_sec <= 0) {
142
- return Status::InvalidArgument("max_bytes_per_sec must be > 0");
143
- } else if (options_.refill_period_us <= 0) {
144
- return Status::InvalidArgument("Refill_period_us must be > 0");
145
- }
146
- Initialize();
147
- return RateLimiter::PrepareOptions(options);
148
- }
149
-
150
98
  // This API allows user to dynamically change rate limiter's bytes per second.
151
99
  void GenericRateLimiter::SetBytesPerSecond(int64_t bytes_per_second) {
152
100
  assert(bytes_per_second > 0);
@@ -165,11 +113,11 @@ void GenericRateLimiter::Request(int64_t bytes, const Env::IOPriority pri,
165
113
  &rate_bytes_per_sec_);
166
114
  MutexLock g(&request_mutex_);
167
115
 
168
- if (options_.auto_tuned) {
116
+ if (auto_tuned_) {
169
117
  static const int kRefillsPerTune = 100;
170
118
  std::chrono::microseconds now(NowMicrosMonotonic());
171
- if (now - tuned_time_ >= kRefillsPerTune * std::chrono::microseconds(
172
- options_.refill_period_us)) {
119
+ if (now - tuned_time_ >=
120
+ kRefillsPerTune * std::chrono::microseconds(refill_period_us_)) {
173
121
  Status s = Tune();
174
122
  s.PermitUncheckedError(); //**TODO: What to do on error?
175
123
  }
@@ -213,7 +161,7 @@ void GenericRateLimiter::Request(int64_t bytes, const Env::IOPriority pri,
213
161
  } else {
214
162
  // Whichever thread reaches here first performs duty (1) as described
215
163
  // above.
216
- int64_t wait_until = options_.clock->NowMicros() + time_until_refill_us;
164
+ int64_t wait_until = clock_->NowMicros() + time_until_refill_us;
217
165
  RecordTick(stats, NUMBER_RATE_LIMITER_DRAINS);
218
166
  ++num_drains_;
219
167
  wait_until_refill_pending_ = true;
@@ -273,12 +221,12 @@ GenericRateLimiter::GeneratePriorityIterationOrder() {
273
221
  // first
274
222
  pri_iteration_order[0] = Env::IO_USER;
275
223
 
276
- bool high_pri_iterated_after_mid_low_pri = rnd_.OneIn(options_.fairness);
224
+ bool high_pri_iterated_after_mid_low_pri = rnd_.OneIn(fairness_);
277
225
  TEST_SYNC_POINT_CALLBACK(
278
226
  "GenericRateLimiter::GeneratePriorityIterationOrder::"
279
227
  "PostRandomOneInFairnessForHighPri",
280
228
  &high_pri_iterated_after_mid_low_pri);
281
- bool mid_pri_itereated_after_low_pri = rnd_.OneIn(options_.fairness);
229
+ bool mid_pri_itereated_after_low_pri = rnd_.OneIn(fairness_);
282
230
  TEST_SYNC_POINT_CALLBACK(
283
231
  "GenericRateLimiter::GeneratePriorityIterationOrder::"
284
232
  "PostRandomOneInFairnessForMidPri",
@@ -307,7 +255,7 @@ GenericRateLimiter::GeneratePriorityIterationOrder() {
307
255
 
308
256
  void GenericRateLimiter::RefillBytesAndGrantRequests() {
309
257
  TEST_SYNC_POINT("GenericRateLimiter::RefillBytesAndGrantRequests");
310
- next_refill_us_ = NowMicrosMonotonic() + options_.refill_period_us;
258
+ next_refill_us_ = NowMicrosMonotonic() + refill_period_us_;
311
259
  // Carry over the left over quota from the last period
312
260
  auto refill_bytes_per_period =
313
261
  refill_bytes_per_period_.load(std::memory_order_relaxed);
@@ -348,12 +296,12 @@ void GenericRateLimiter::RefillBytesAndGrantRequests() {
348
296
  int64_t GenericRateLimiter::CalculateRefillBytesPerPeriod(
349
297
  int64_t rate_bytes_per_sec) {
350
298
  if (std::numeric_limits<int64_t>::max() / rate_bytes_per_sec <
351
- options_.refill_period_us) {
299
+ refill_period_us_) {
352
300
  // Avoid unexpected result in the overflow case. The result now is still
353
301
  // inaccurate but is a number that is large enough.
354
302
  return std::numeric_limits<int64_t>::max() / 1000000;
355
303
  } else {
356
- return rate_bytes_per_sec * options_.refill_period_us / 1000000;
304
+ return rate_bytes_per_sec * refill_period_us_ / 1000000;
357
305
  }
358
306
  }
359
307
 
@@ -368,11 +316,10 @@ Status GenericRateLimiter::Tune() {
368
316
  std::chrono::microseconds prev_tuned_time = tuned_time_;
369
317
  tuned_time_ = std::chrono::microseconds(NowMicrosMonotonic());
370
318
 
371
- int64_t elapsed_intervals =
372
- (tuned_time_ - prev_tuned_time +
373
- std::chrono::microseconds(options_.refill_period_us) -
374
- std::chrono::microseconds(1)) /
375
- std::chrono::microseconds(options_.refill_period_us);
319
+ int64_t elapsed_intervals = (tuned_time_ - prev_tuned_time +
320
+ std::chrono::microseconds(refill_period_us_) -
321
+ std::chrono::microseconds(1)) /
322
+ std::chrono::microseconds(refill_period_us_);
376
323
  // We tune every kRefillsPerTune intervals, so the overflow and division-by-
377
324
  // zero conditions should never happen.
378
325
  assert(num_drains_ <= std::numeric_limits<int64_t>::max() / 100);
@@ -382,13 +329,13 @@ Status GenericRateLimiter::Tune() {
382
329
  int64_t prev_bytes_per_sec = GetBytesPerSecond();
383
330
  int64_t new_bytes_per_sec;
384
331
  if (drained_pct == 0) {
385
- new_bytes_per_sec = options_.max_bytes_per_sec / kAllowedRangeFactor;
332
+ new_bytes_per_sec = max_bytes_per_sec_ / kAllowedRangeFactor;
386
333
  } else if (drained_pct < kLowWatermarkPct) {
387
334
  // sanitize to prevent overflow
388
335
  int64_t sanitized_prev_bytes_per_sec =
389
336
  std::min(prev_bytes_per_sec, std::numeric_limits<int64_t>::max() / 100);
390
337
  new_bytes_per_sec =
391
- std::max(options_.max_bytes_per_sec / kAllowedRangeFactor,
338
+ std::max(max_bytes_per_sec_ / kAllowedRangeFactor,
392
339
  sanitized_prev_bytes_per_sec * 100 / (100 + kAdjustFactorPct));
393
340
  } else if (drained_pct > kHighWatermarkPct) {
394
341
  // sanitize to prevent overflow
@@ -396,7 +343,7 @@ Status GenericRateLimiter::Tune() {
396
343
  std::min(prev_bytes_per_sec, std::numeric_limits<int64_t>::max() /
397
344
  (100 + kAdjustFactorPct));
398
345
  new_bytes_per_sec =
399
- std::min(options_.max_bytes_per_sec,
346
+ std::min(max_bytes_per_sec_,
400
347
  sanitized_prev_bytes_per_sec * (100 + kAdjustFactorPct) / 100);
401
348
  } else {
402
349
  new_bytes_per_sec = prev_bytes_per_sec;
@@ -419,79 +366,7 @@ RateLimiter* NewGenericRateLimiter(
419
366
  std::unique_ptr<RateLimiter> limiter(
420
367
  new GenericRateLimiter(rate_bytes_per_sec, refill_period_us, fairness,
421
368
  mode, SystemClock::Default(), auto_tuned));
422
- Status s = limiter->PrepareOptions(ConfigOptions());
423
- if (s.ok()) {
424
- return limiter.release();
425
- } else {
426
- assert(false);
427
- return nullptr;
428
- }
429
- }
430
- namespace {
431
- #ifndef ROCKSDB_LITE
432
- static int RegisterBuiltinRateLimiters(ObjectLibrary& library,
433
- const std::string& /*arg*/) {
434
- library.AddFactory<RateLimiter>(
435
- GenericRateLimiter::kClassName(),
436
- [](const std::string& /*uri*/, std::unique_ptr<RateLimiter>* guard,
437
- std::string* /*errmsg*/) {
438
- guard->reset(
439
- new GenericRateLimiter(std::numeric_limits<int64_t>::max()));
440
- return guard->get();
441
- });
442
- size_t num_types;
443
- return static_cast<int>(library.GetFactoryCount(&num_types));
444
- }
445
-
446
- static std::unordered_map<std::string, RateLimiter::Mode>
447
- rate_limiter_mode_map = {
448
- {"kReadsOnly", RateLimiter::Mode::kReadsOnly},
449
- {"kWritesOnly", RateLimiter::Mode::kWritesOnly},
450
- {"kAllIo", RateLimiter::Mode::kAllIo},
451
- };
452
- #endif // ROCKSDB_LITE
453
- static bool LoadRateLimiter(const std::string& name,
454
- std::shared_ptr<RateLimiter>* limiter) {
455
- auto plen = strlen(GenericRateLimiter::kClassName());
456
- if (name.size() > plen + 2 && name[plen] == ':' &&
457
- StartsWith(name, GenericRateLimiter::kClassName())) {
458
- auto rate = ParseInt64(name.substr(plen + 1));
459
- limiter->reset(new GenericRateLimiter(rate));
460
- return true;
461
- } else {
462
- return false;
463
- }
464
- }
465
-
466
- static std::unordered_map<std::string, OptionTypeInfo> rate_limiter_type_info =
467
- {
468
- #ifndef ROCKSDB_LITE
469
- {"mode",
470
- OptionTypeInfo::Enum<RateLimiter::Mode>(0, &rate_limiter_mode_map)},
471
- #endif // ROCKSDB_LITE
472
- };
473
- } // namespace
474
-
475
- RateLimiter::RateLimiter(Mode mode) : mode_(mode) {
476
- RegisterOptions("", &mode_, &rate_limiter_type_info);
477
- }
478
-
479
- Status RateLimiter::CreateFromString(const ConfigOptions& config_options,
480
- const std::string& value,
481
- std::shared_ptr<RateLimiter>* result) {
482
- if (value.empty()) {
483
- result->reset();
484
- return Status::OK();
485
- } else {
486
- #ifndef ROCKSDB_LITE
487
- static std::once_flag once;
488
- std::call_once(once, [&]() {
489
- RegisterBuiltinRateLimiters(*(ObjectLibrary::Default().get()), "");
490
- });
491
- #endif // ROCKSDB_LITE
492
- return LoadSharedObject<RateLimiter>(config_options, value, LoadRateLimiter,
493
- result);
494
- }
369
+ return limiter.release();
495
370
  }
496
371
 
497
372
  } // namespace ROCKSDB_NAMESPACE
@@ -26,38 +26,13 @@ namespace ROCKSDB_NAMESPACE {
26
26
 
27
27
  class GenericRateLimiter : public RateLimiter {
28
28
  public:
29
- struct GenericRateLimiterOptions {
30
- static const char* kName() { return "GenericRateLimiterOptions"; }
31
- GenericRateLimiterOptions(int64_t _rate_bytes_per_sec,
32
- int64_t _refill_period_us, int32_t _fairness,
33
- const std::shared_ptr<SystemClock>& _clock,
34
- bool _auto_tuned)
35
- : max_bytes_per_sec(_rate_bytes_per_sec),
36
- refill_period_us(_refill_period_us),
37
- clock(_clock),
38
- fairness(_fairness > 100 ? 100 : _fairness),
39
- auto_tuned(_auto_tuned) {}
40
- int64_t max_bytes_per_sec;
41
- int64_t refill_period_us;
42
- std::shared_ptr<SystemClock> clock;
43
- int32_t fairness;
44
- bool auto_tuned;
45
- };
46
-
47
- public:
48
- explicit GenericRateLimiter(
49
- int64_t refill_bytes, int64_t refill_period_us = 100 * 1000,
50
- int32_t fairness = 10,
51
- RateLimiter::Mode mode = RateLimiter::Mode::kWritesOnly,
52
- const std::shared_ptr<SystemClock>& clock = nullptr,
53
- bool auto_tuned = false);
29
+ GenericRateLimiter(int64_t refill_bytes, int64_t refill_period_us,
30
+ int32_t fairness, RateLimiter::Mode mode,
31
+ const std::shared_ptr<SystemClock>& clock,
32
+ bool auto_tuned);
54
33
 
55
34
  virtual ~GenericRateLimiter();
56
35
 
57
- static const char* kClassName() { return "GenericRateLimiter"; }
58
- const char* Name() const override { return kClassName(); }
59
- Status PrepareOptions(const ConfigOptions& options) override;
60
-
61
36
  // This API allows user to dynamically change rate limiter's bytes per second.
62
37
  virtual void SetBytesPerSecond(int64_t bytes_per_second) override;
63
38
 
@@ -120,25 +95,29 @@ class GenericRateLimiter : public RateLimiter {
120
95
  return rate_bytes_per_sec_;
121
96
  }
122
97
 
98
+ virtual void TEST_SetClock(std::shared_ptr<SystemClock> clock) {
99
+ MutexLock g(&request_mutex_);
100
+ clock_ = std::move(clock);
101
+ next_refill_us_ = NowMicrosMonotonic();
102
+ }
103
+
123
104
  private:
124
- void Initialize();
125
105
  void RefillBytesAndGrantRequests();
126
106
  std::vector<Env::IOPriority> GeneratePriorityIterationOrder();
127
107
  int64_t CalculateRefillBytesPerPeriod(int64_t rate_bytes_per_sec);
128
108
  Status Tune();
129
109
 
130
- uint64_t NowMicrosMonotonic() {
131
- return options_.clock->NowNanos() / std::milli::den;
132
- }
110
+ uint64_t NowMicrosMonotonic() { return clock_->NowNanos() / std::milli::den; }
133
111
 
134
112
  // This mutex guard all internal states
135
113
  mutable port::Mutex request_mutex_;
136
114
 
137
- GenericRateLimiterOptions options_;
115
+ const int64_t refill_period_us_;
138
116
 
139
117
  int64_t rate_bytes_per_sec_;
140
118
  // This variable can be changed dynamically.
141
119
  std::atomic<int64_t> refill_bytes_per_period_;
120
+ std::shared_ptr<SystemClock> clock_;
142
121
 
143
122
  bool stop_;
144
123
  port::CondVar exit_cv_;
@@ -149,13 +128,16 @@ class GenericRateLimiter : public RateLimiter {
149
128
  int64_t available_bytes_;
150
129
  int64_t next_refill_us_;
151
130
 
131
+ int32_t fairness_;
152
132
  Random rnd_;
153
133
 
154
134
  struct Req;
155
135
  std::deque<Req*> queue_[Env::IO_TOTAL];
156
136
  bool wait_until_refill_pending_;
157
137
 
138
+ bool auto_tuned_;
158
139
  int64_t num_drains_;
140
+ const int64_t max_bytes_per_sec_;
159
141
  std::chrono::microseconds tuned_time_;
160
142
  };
161
143