Skip to content

Commit

Permalink
Option string/map/file can set env from object registry (facebook#5237)
Browse files Browse the repository at this point in the history
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: facebook#5237

Differential Revision: D15056360

Pulled By: siying

fbshipit-source-id: 4b5f0b83297a5058f8949ec955dbf27d98d73d7e
  • Loading branch information
ajkr committed Apr 27, 2019
1 parent 2597e93 commit 0b91537
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 5 deletions.
1 change: 1 addition & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
## 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`.
* When reading from option file/string/map, customized envs can be filled according to object registry.

# 5.17.2 (10/24/2018)
### Bug Fixes
Expand Down
3 changes: 3 additions & 0 deletions include/rocksdb/utilities/options_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ namespace rocksdb {
// * merge_operator
// * compaction_filter
//
// User can choose to load customized env through object registry:
// * env needs to be registered through Registrar<Env>
//
// For table_factory, this function further supports deserializing
// BlockBasedTableFactory and its BlockBasedTableOptions except the
// pointer options of BlockBasedTableOptions (flush_block_policy_factory,
Expand Down
16 changes: 13 additions & 3 deletions options/options_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "rocksdb/rate_limiter.h"
#include "rocksdb/slice_transform.h"
#include "rocksdb/table.h"
#include "rocksdb/utilities/object_registry.h"
#include "table/block_based_table_factory.h"
#include "table/plain_table_factory.h"
#include "util/cast_util.h"
Expand Down Expand Up @@ -232,6 +233,8 @@ std::unordered_map<std::string, CompressionType>
{"kDisableCompressionOption", kDisableCompressionOption}};
#ifndef ROCKSDB_LITE

const std::string kNameEnv = "env";

template <typename T>
Status GetStringFromStruct(
std::string* opt_string, const T& options,
Expand Down Expand Up @@ -1115,6 +1118,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()) {
Expand Down Expand Up @@ -1324,7 +1335,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;
Expand Down Expand Up @@ -1489,8 +1499,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,
Expand Down
3 changes: 2 additions & 1 deletion options/options_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ enum class OptionType {
kAccessHint,
kInfoLogLevel,
kLRUCacheOptions,
kUnknown
kEnv,
kUnknown,
};

enum class OptionVerificationType {
Expand Down
20 changes: 19 additions & 1 deletion options/options_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "rocksdb/convenience.h"
#include "rocksdb/memtablerep.h"
#include "rocksdb/utilities/leveldb_options.h"
#include "rocksdb/utilities/object_registry.h"
#include "util/random.h"
#include "util/stderr_logger.h"
#include "util/string_util.h"
Expand Down Expand Up @@ -722,14 +723,29 @@ 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;"
"block_based_table_factory={block_cache=1M;block_size=4;};"
"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);
Expand Down Expand Up @@ -758,6 +774,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) {
Expand Down

0 comments on commit 0b91537

Please sign in to comment.