@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.
- package/binding.cc +67 -25
- package/chained-batch.js +1 -1
- package/deps/rocksdb/rocksdb/CMakeLists.txt +3 -0
- package/deps/rocksdb/rocksdb/Makefile +3 -0
- package/deps/rocksdb/rocksdb/TARGETS +10 -0
- package/deps/rocksdb/rocksdb/cache/cache_bench_tool.cc +17 -7
- package/deps/rocksdb/rocksdb/cache/cache_entry_roles.cc +2 -0
- package/deps/rocksdb/rocksdb/cache/cache_reservation_manager.cc +1 -0
- package/deps/rocksdb/rocksdb/cache/charged_cache.cc +117 -0
- package/deps/rocksdb/rocksdb/cache/charged_cache.h +121 -0
- package/deps/rocksdb/rocksdb/cache/clock_cache.cc +270 -180
- package/deps/rocksdb/rocksdb/cache/clock_cache.h +412 -124
- package/deps/rocksdb/rocksdb/cache/fast_lru_cache.cc +1 -0
- package/deps/rocksdb/rocksdb/cache/lru_cache.cc +1 -1
- package/deps/rocksdb/rocksdb/cache/lru_cache.h +2 -2
- package/deps/rocksdb/rocksdb/cache/lru_cache_test.cc +2 -2
- package/deps/rocksdb/rocksdb/cache/sharded_cache.h +1 -1
- package/deps/rocksdb/rocksdb/db/blob/blob_file_builder.cc +71 -9
- package/deps/rocksdb/rocksdb/db/blob/blob_file_builder.h +11 -2
- package/deps/rocksdb/rocksdb/db/blob/blob_file_builder_test.cc +21 -14
- package/deps/rocksdb/rocksdb/db/blob/blob_source.cc +68 -7
- package/deps/rocksdb/rocksdb/db/blob/blob_source.h +16 -0
- package/deps/rocksdb/rocksdb/db/blob/blob_source_test.cc +519 -12
- package/deps/rocksdb/rocksdb/db/blob/db_blob_basic_test.cc +120 -0
- package/deps/rocksdb/rocksdb/db/builder.cc +15 -5
- package/deps/rocksdb/rocksdb/db/builder.h +3 -0
- package/deps/rocksdb/rocksdb/db/c.cc +18 -0
- package/deps/rocksdb/rocksdb/db/c_test.c +18 -0
- package/deps/rocksdb/rocksdb/db/column_family.h +2 -0
- package/deps/rocksdb/rocksdb/db/compaction/clipping_iterator.h +3 -2
- package/deps/rocksdb/rocksdb/db/compaction/compaction.cc +9 -4
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.cc +15 -10
- package/deps/rocksdb/rocksdb/db/compaction/compaction_iterator.h +36 -34
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job.cc +50 -13
- package/deps/rocksdb/rocksdb/db/compaction/compaction_job.h +12 -0
- package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.cc +8 -1
- package/deps/rocksdb/rocksdb/db/compaction/compaction_outputs.h +2 -1
- package/deps/rocksdb/rocksdb/db/compaction/tiered_compaction_test.cc +13 -17
- package/deps/rocksdb/rocksdb/db/db_basic_test.cc +26 -9
- package/deps/rocksdb/rocksdb/db/db_compaction_test.cc +0 -11
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.cc +93 -0
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl.h +16 -1
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_compaction_flush.cc +3 -8
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_debug.cc +8 -1
- package/deps/rocksdb/rocksdb/db/db_impl/db_impl_open.cc +17 -5
- package/deps/rocksdb/rocksdb/db/db_test.cc +0 -3
- package/deps/rocksdb/rocksdb/db/db_test2.cc +39 -12
- package/deps/rocksdb/rocksdb/db/db_test_util.cc +9 -0
- package/deps/rocksdb/rocksdb/db/db_test_util.h +2 -0
- package/deps/rocksdb/rocksdb/db/dbformat.cc +0 -38
- package/deps/rocksdb/rocksdb/db/dbformat.h +14 -13
- package/deps/rocksdb/rocksdb/db/dbformat_test.cc +5 -2
- package/deps/rocksdb/rocksdb/db/event_helpers.cc +13 -1
- package/deps/rocksdb/rocksdb/db/external_sst_file_basic_test.cc +0 -10
- package/deps/rocksdb/rocksdb/db/flush_job.cc +19 -15
- package/deps/rocksdb/rocksdb/db/flush_job.h +7 -0
- package/deps/rocksdb/rocksdb/db/flush_job_test.cc +21 -15
- package/deps/rocksdb/rocksdb/db/forward_iterator.h +4 -3
- package/deps/rocksdb/rocksdb/db/memtable_list.cc +9 -0
- package/deps/rocksdb/rocksdb/db/memtable_list.h +5 -0
- package/deps/rocksdb/rocksdb/db/periodic_work_scheduler.cc +53 -12
- package/deps/rocksdb/rocksdb/db/periodic_work_scheduler.h +14 -2
- package/deps/rocksdb/rocksdb/db/periodic_work_scheduler_test.cc +10 -10
- package/deps/rocksdb/rocksdb/db/repair.cc +8 -6
- package/deps/rocksdb/rocksdb/db/seqno_time_test.cc +890 -0
- package/deps/rocksdb/rocksdb/db/seqno_to_time_mapping.cc +324 -0
- package/deps/rocksdb/rocksdb/db/seqno_to_time_mapping.h +186 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_common.h +2 -0
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_gflags.cc +13 -4
- package/deps/rocksdb/rocksdb/db_stress_tool/db_stress_test_base.cc +23 -2
- package/deps/rocksdb/rocksdb/env/env_test.cc +74 -1
- package/deps/rocksdb/rocksdb/env/io_posix.cc +11 -8
- package/deps/rocksdb/rocksdb/include/rocksdb/advanced_options.h +28 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/c.h +14 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/cache.h +4 -4
- package/deps/rocksdb/rocksdb/include/rocksdb/comparator.h +30 -23
- package/deps/rocksdb/rocksdb/include/rocksdb/db.h +1 -1
- package/deps/rocksdb/rocksdb/include/rocksdb/rate_limiter.h +3 -13
- package/deps/rocksdb/rocksdb/include/rocksdb/table_properties.h +5 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/debug.h +1 -2
- package/deps/rocksdb/rocksdb/include/rocksdb/utilities/ldb_cmd.h +1 -0
- package/deps/rocksdb/rocksdb/include/rocksdb/version.h +1 -1
- package/deps/rocksdb/rocksdb/monitoring/stats_history_test.cc +26 -26
- package/deps/rocksdb/rocksdb/options/cf_options.cc +14 -1
- package/deps/rocksdb/rocksdb/options/cf_options.h +5 -0
- package/deps/rocksdb/rocksdb/options/customizable_test.cc +0 -56
- package/deps/rocksdb/rocksdb/options/db_options.cc +4 -5
- package/deps/rocksdb/rocksdb/options/options.cc +11 -1
- package/deps/rocksdb/rocksdb/options/options_helper.cc +8 -0
- package/deps/rocksdb/rocksdb/options/options_helper.h +4 -0
- package/deps/rocksdb/rocksdb/options/options_settable_test.cc +4 -0
- package/deps/rocksdb/rocksdb/options/options_test.cc +4 -0
- package/deps/rocksdb/rocksdb/src.mk +3 -0
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.cc +6 -1
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_builder.h +4 -0
- package/deps/rocksdb/rocksdb/table/block_based/block_based_table_factory.cc +36 -3
- package/deps/rocksdb/rocksdb/table/block_based/index_builder.cc +36 -1
- package/deps/rocksdb/rocksdb/table/block_based/index_builder.h +14 -3
- package/deps/rocksdb/rocksdb/table/internal_iterator.h +1 -1
- package/deps/rocksdb/rocksdb/table/meta_blocks.cc +6 -0
- package/deps/rocksdb/rocksdb/table/plain/plain_table_builder.cc +5 -0
- package/deps/rocksdb/rocksdb/table/plain/plain_table_builder.h +3 -0
- package/deps/rocksdb/rocksdb/table/sst_file_writer.cc +10 -7
- package/deps/rocksdb/rocksdb/table/table_builder.h +7 -3
- package/deps/rocksdb/rocksdb/table/table_properties.cc +9 -0
- package/deps/rocksdb/rocksdb/test_util/mock_time_env.h +3 -2
- package/deps/rocksdb/rocksdb/tools/db_bench_tool.cc +58 -30
- package/deps/rocksdb/rocksdb/tools/db_bench_tool_test.cc +1 -0
- package/deps/rocksdb/rocksdb/tools/ldb_cmd.cc +20 -0
- package/deps/rocksdb/rocksdb/util/rate_limiter.cc +29 -154
- package/deps/rocksdb/rocksdb/util/rate_limiter.h +16 -34
- package/deps/rocksdb/rocksdb/util/rate_limiter_test.cc +0 -92
- package/deps/rocksdb/rocksdb/util/timer.h +6 -0
- package/deps/rocksdb/rocksdb/util/vector_iterator.h +4 -3
- package/deps/rocksdb/rocksdb/utilities/backup/backup_engine.cc +4 -45
- package/deps/rocksdb/rocksdb/utilities/debug.cc +40 -0
- package/deps/rocksdb/rocksdb.gyp +2 -0
- package/index.js +4 -0
- package/package.json +1 -1
- package/prebuilds/darwin-arm64/node.napi.node +0 -0
- 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
|
-
|
|
64
|
-
|
|
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
|
-
|
|
87
|
-
|
|
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
|
-
|
|
95
|
-
|
|
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 (
|
|
116
|
+
if (auto_tuned_) {
|
|
169
117
|
static const int kRefillsPerTune = 100;
|
|
170
118
|
std::chrono::microseconds now(NowMicrosMonotonic());
|
|
171
|
-
if (now - tuned_time_ >=
|
|
172
|
-
|
|
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 =
|
|
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(
|
|
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(
|
|
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() +
|
|
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
|
-
|
|
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 *
|
|
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
|
-
|
|
373
|
-
|
|
374
|
-
|
|
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 =
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
|
|
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
|
|