Option string/map/file can set env from object registry (#5237)
Summary: - By providing the "env" field in any text-based options (i.e., string, map, or file), we can use `NewCustomObject` to deserialize the text value into an actual `Env` object. - Currently factory functions for `Env` registered with object registry should only return pointer to static `Env` objects. That's because `DBOptions::env` is a raw pointer so we cannot easily delegate cleanup. - Note I did not add `env` to `db_option_type_info`. It wasn't needed for (de)serialization, and I believe we don't want to do verification on `env`, even by checking name. That's because the user should be able to copy their DB from Linux to Windows, change envs, and not see an option verification error. Pull Request resolved: https://github.com/facebook/rocksdb/pull/5237 Differential Revision: D15056360 Pulled By: siying fbshipit-source-id: 4b5f0b83297a5058f8949ec955dbf27d98d73d7e
This commit is contained in:
parent
084a3c697c
commit
6eb317bb4c
@ -2,12 +2,11 @@
|
||||
## Unreleased
|
||||
### New Features
|
||||
* Add an option `strict_bytes_per_sync` that causes a file-writing thread to block rather than exceed the limit on bytes pending writeback specified by `bytes_per_sync` or `wal_bytes_per_sync`.
|
||||
|
||||
## Unreleased
|
||||
### New Features
|
||||
* Improve range scan performance by avoiding per-key upper bound check in BlockBasedTableIterator.
|
||||
* Introduce Periodic Compaction for Level style compaction. Files are re-compacted periodically and put in the same level.
|
||||
* Block-based table index now contains exact highest key in the file, rather than an upper bound. This may improve Get() and iterator Seek() performance in some situations, especially when direct IO is enabled and block cache is disabled. A setting BlockBasedTableOptions::index_shortening is introduced to control this behavior. Set it to kShortenSeparatorsAndSuccessor to get the old behavior.
|
||||
* When reading from option file/string/map, customized envs can be filled according to object registry.
|
||||
|
||||
### Public API Change
|
||||
* Change the behavior of OptimizeForPointLookup(): move away from hash-based block-based-table index, and use whole key memtable filtering.
|
||||
* Change the behavior of OptimizeForSmallDb(): use a 16MB block cache, put index and filter blocks into it, and cost the memtable size to it. DBOptions.OptimizeForSmallDb() and ColumnFamilyOptions.OptimizeForSmallDb() start to take an optional cache object.
|
||||
|
@ -33,9 +33,10 @@ namespace rocksdb {
|
||||
// * merge_operator
|
||||
// * compaction_filter
|
||||
//
|
||||
// User can also choose to load customized comparator and/or merge_operator
|
||||
// through object registry:
|
||||
// User can also choose to load customized comparator, env, and/or
|
||||
// merge_operator through object registry:
|
||||
// * comparator needs to be registered through Registrar<const Comparator>
|
||||
// * env needs to be registered through Registrar<Env>
|
||||
// * merge operator needs to be registered through
|
||||
// Registrar<std::shared_ptr<MergeOperator>>.
|
||||
//
|
||||
|
@ -247,6 +247,7 @@ std::unordered_map<std::string, CompressionType>
|
||||
#ifndef ROCKSDB_LITE
|
||||
|
||||
const std::string kNameComparator = "comparator";
|
||||
const std::string kNameEnv = "env";
|
||||
const std::string kNameMergeOperator = "merge_operator";
|
||||
|
||||
template <typename T>
|
||||
@ -1179,6 +1180,14 @@ Status ParseDBOption(const std::string& name,
|
||||
if (name == "rate_limiter_bytes_per_sec") {
|
||||
new_options->rate_limiter.reset(
|
||||
NewGenericRateLimiter(static_cast<int64_t>(ParseUint64(value))));
|
||||
} else if (name == kNameEnv) {
|
||||
// Currently `Env` can be deserialized from object registry only.
|
||||
std::unique_ptr<Env> env_guard;
|
||||
Env* env = NewCustomObject<Env>(value, &env_guard);
|
||||
// Only support static env for now.
|
||||
if (env != nullptr && !env_guard) {
|
||||
new_options->env = env;
|
||||
}
|
||||
} else {
|
||||
auto iter = db_options_type_info.find(name);
|
||||
if (iter == db_options_type_info.end()) {
|
||||
@ -1388,7 +1397,6 @@ std::unordered_map<std::string, OptionTypeInfo>
|
||||
OptionsHelper::db_options_type_info = {
|
||||
/*
|
||||
// not yet supported
|
||||
Env* env;
|
||||
std::shared_ptr<Cache> row_cache;
|
||||
std::shared_ptr<DeleteScheduler> delete_scheduler;
|
||||
std::shared_ptr<Logger> info_log;
|
||||
@ -1553,8 +1561,8 @@ std::unordered_map<std::string, OptionTypeInfo>
|
||||
OptionVerificationType::kNormal, true,
|
||||
offsetof(struct MutableDBOptions, wal_bytes_per_sync)}},
|
||||
{"strict_bytes_per_sync",
|
||||
{offsetof(struct DBOptions, strict_bytes_per_sync), OptionType::kBoolean,
|
||||
OptionVerificationType::kNormal, true,
|
||||
{offsetof(struct DBOptions, strict_bytes_per_sync),
|
||||
OptionType::kBoolean, OptionVerificationType::kNormal, true,
|
||||
offsetof(struct MutableDBOptions, strict_bytes_per_sync)}},
|
||||
{"stats_dump_period_sec",
|
||||
{offsetof(struct DBOptions, stats_dump_period_sec), OptionType::kUInt,
|
||||
@ -1639,8 +1647,8 @@ std::unordered_map<std::string, OptionTypeInfo>
|
||||
{"avoid_unnecessary_blocking_io",
|
||||
{offsetof(struct DBOptions, avoid_unnecessary_blocking_io),
|
||||
OptionType::kBoolean, OptionVerificationType::kNormal, false,
|
||||
offsetof(struct ImmutableDBOptions, avoid_unnecessary_blocking_io)}}
|
||||
};
|
||||
offsetof(struct ImmutableDBOptions, avoid_unnecessary_blocking_io)}},
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, BlockBasedTableOptions::IndexType>
|
||||
OptionsHelper::block_base_table_index_type_string_map = {
|
||||
|
@ -81,7 +81,8 @@ enum class OptionType {
|
||||
kAccessHint,
|
||||
kInfoLogLevel,
|
||||
kLRUCacheOptions,
|
||||
kUnknown
|
||||
kEnv,
|
||||
kUnknown,
|
||||
};
|
||||
|
||||
enum class OptionVerificationType {
|
||||
|
@ -759,6 +759,21 @@ TEST_F(OptionsTest, GetOptionsFromStringTest) {
|
||||
block_based_table_options.cache_index_and_filter_blocks = true;
|
||||
base_options.table_factory.reset(
|
||||
NewBlockBasedTableFactory(block_based_table_options));
|
||||
|
||||
// Register an Env with object registry.
|
||||
const static char* kCustomEnvName = "CustomEnv";
|
||||
class CustomEnv : public EnvWrapper {
|
||||
public:
|
||||
explicit CustomEnv(Env* _target) : EnvWrapper(_target) {}
|
||||
};
|
||||
|
||||
static Registrar<Env> test_reg_env(
|
||||
kCustomEnvName,
|
||||
[](const std::string& /*name*/, std::unique_ptr<Env>* /*env_guard*/) {
|
||||
static CustomEnv env(Env::Default());
|
||||
return &env;
|
||||
});
|
||||
|
||||
ASSERT_OK(GetOptionsFromString(
|
||||
base_options,
|
||||
"write_buffer_size=10;max_write_buffer_number=16;"
|
||||
@ -766,7 +781,7 @@ TEST_F(OptionsTest, GetOptionsFromStringTest) {
|
||||
"compression_opts=4:5:6;create_if_missing=true;max_open_files=1;"
|
||||
"bottommost_compression_opts=5:6:7;create_if_missing=true;max_open_files="
|
||||
"1;"
|
||||
"rate_limiter_bytes_per_sec=1024",
|
||||
"rate_limiter_bytes_per_sec=1024;env=CustomEnv",
|
||||
&new_options));
|
||||
|
||||
ASSERT_EQ(new_options.compression_opts.window_bits, 4);
|
||||
@ -795,6 +810,8 @@ TEST_F(OptionsTest, GetOptionsFromStringTest) {
|
||||
ASSERT_EQ(new_options.create_if_missing, true);
|
||||
ASSERT_EQ(new_options.max_open_files, 1);
|
||||
ASSERT_TRUE(new_options.rate_limiter.get() != nullptr);
|
||||
std::unique_ptr<Env> env_guard;
|
||||
ASSERT_EQ(NewCustomObject<Env>(kCustomEnvName, &env_guard), new_options.env);
|
||||
}
|
||||
|
||||
TEST_F(OptionsTest, DBOptionsSerialization) {
|
||||
|
Loading…
Reference in New Issue
Block a user