Allow unregistered options to be ignored in DBOptions from files (#9045)
Summary: Adds changes to DBOptions (comparable to ColumnFamilyOptions) to allow some option values to be ignored on rehydration from the Options file. This is necessary for some customizable classes that were not registered with the ObjectRegistry but are saved/restored from the Options file. All tests pass. Will run check_format_compatible.sh shortly. Pull Request resolved: https://github.com/facebook/rocksdb/pull/9045 Reviewed By: zhichao-cao Differential Revision: D31761664 Pulled By: mrambacher fbshipit-source-id: 300c2251639cce2b223481c3bb2a63877b1f3766
This commit is contained in:
parent
8d615a2b1d
commit
8fb3fe8d39
@ -1463,7 +1463,6 @@ class LoadCustomizableTest : public testing::Test {
|
|||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(LoadCustomizableTest, LoadTableFactoryTest) {
|
TEST_F(LoadCustomizableTest, LoadTableFactoryTest) {
|
||||||
ColumnFamilyOptions cf_opts;
|
|
||||||
std::shared_ptr<TableFactory> factory;
|
std::shared_ptr<TableFactory> factory;
|
||||||
ASSERT_NOK(TableFactory::CreateFromString(
|
ASSERT_NOK(TableFactory::CreateFromString(
|
||||||
config_options_, mock::MockTableFactory::kClassName(), &factory));
|
config_options_, mock::MockTableFactory::kClassName(), &factory));
|
||||||
@ -1474,10 +1473,10 @@ TEST_F(LoadCustomizableTest, LoadTableFactoryTest) {
|
|||||||
#ifndef ROCKSDB_LITE
|
#ifndef ROCKSDB_LITE
|
||||||
std::string opts_str = "table_factory=";
|
std::string opts_str = "table_factory=";
|
||||||
ASSERT_OK(GetColumnFamilyOptionsFromString(
|
ASSERT_OK(GetColumnFamilyOptionsFromString(
|
||||||
config_options_, ColumnFamilyOptions(),
|
config_options_, cf_opts_,
|
||||||
opts_str + TableFactory::kBlockBasedTableName(), &cf_opts));
|
opts_str + TableFactory::kBlockBasedTableName(), &cf_opts_));
|
||||||
ASSERT_NE(cf_opts.table_factory.get(), nullptr);
|
ASSERT_NE(cf_opts_.table_factory.get(), nullptr);
|
||||||
ASSERT_STREQ(cf_opts.table_factory->Name(),
|
ASSERT_STREQ(cf_opts_.table_factory->Name(),
|
||||||
TableFactory::kBlockBasedTableName());
|
TableFactory::kBlockBasedTableName());
|
||||||
#endif // ROCKSDB_LITE
|
#endif // ROCKSDB_LITE
|
||||||
if (RegisterTests("Test")) {
|
if (RegisterTests("Test")) {
|
||||||
@ -1487,10 +1486,10 @@ TEST_F(LoadCustomizableTest, LoadTableFactoryTest) {
|
|||||||
ASSERT_STREQ(factory->Name(), mock::MockTableFactory::kClassName());
|
ASSERT_STREQ(factory->Name(), mock::MockTableFactory::kClassName());
|
||||||
#ifndef ROCKSDB_LITE
|
#ifndef ROCKSDB_LITE
|
||||||
ASSERT_OK(GetColumnFamilyOptionsFromString(
|
ASSERT_OK(GetColumnFamilyOptionsFromString(
|
||||||
config_options_, ColumnFamilyOptions(),
|
config_options_, cf_opts_,
|
||||||
opts_str + mock::MockTableFactory::kClassName(), &cf_opts));
|
opts_str + mock::MockTableFactory::kClassName(), &cf_opts_));
|
||||||
ASSERT_NE(cf_opts.table_factory.get(), nullptr);
|
ASSERT_NE(cf_opts_.table_factory.get(), nullptr);
|
||||||
ASSERT_STREQ(cf_opts.table_factory->Name(),
|
ASSERT_STREQ(cf_opts_.table_factory->Name(),
|
||||||
mock::MockTableFactory::kClassName());
|
mock::MockTableFactory::kClassName());
|
||||||
#endif // ROCKSDB_LITE
|
#endif // ROCKSDB_LITE
|
||||||
}
|
}
|
||||||
@ -1763,12 +1762,12 @@ TEST_F(LoadCustomizableTest, LoadEncryptionProviderTest) {
|
|||||||
EncryptionProvider::CreateFromString(config_options_, "CTR", &result));
|
EncryptionProvider::CreateFromString(config_options_, "CTR", &result));
|
||||||
ASSERT_NE(result, nullptr);
|
ASSERT_NE(result, nullptr);
|
||||||
ASSERT_STREQ(result->Name(), "CTR");
|
ASSERT_STREQ(result->Name(), "CTR");
|
||||||
ASSERT_NOK(result->ValidateOptions(DBOptions(), ColumnFamilyOptions()));
|
ASSERT_NOK(result->ValidateOptions(db_opts_, cf_opts_));
|
||||||
ASSERT_OK(EncryptionProvider::CreateFromString(config_options_, "CTR://test",
|
ASSERT_OK(EncryptionProvider::CreateFromString(config_options_, "CTR://test",
|
||||||
&result));
|
&result));
|
||||||
ASSERT_NE(result, nullptr);
|
ASSERT_NE(result, nullptr);
|
||||||
ASSERT_STREQ(result->Name(), "CTR");
|
ASSERT_STREQ(result->Name(), "CTR");
|
||||||
ASSERT_OK(result->ValidateOptions(DBOptions(), ColumnFamilyOptions()));
|
ASSERT_OK(result->ValidateOptions(db_opts_, cf_opts_));
|
||||||
|
|
||||||
if (RegisterTests("Test")) {
|
if (RegisterTests("Test")) {
|
||||||
ASSERT_OK(
|
ASSERT_OK(
|
||||||
@ -1779,7 +1778,7 @@ TEST_F(LoadCustomizableTest, LoadEncryptionProviderTest) {
|
|||||||
"Mock://test", &result));
|
"Mock://test", &result));
|
||||||
ASSERT_NE(result, nullptr);
|
ASSERT_NE(result, nullptr);
|
||||||
ASSERT_STREQ(result->Name(), "Mock");
|
ASSERT_STREQ(result->Name(), "Mock");
|
||||||
ASSERT_OK(result->ValidateOptions(DBOptions(), ColumnFamilyOptions()));
|
ASSERT_OK(result->ValidateOptions(db_opts_, cf_opts_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,7 +452,8 @@ static std::unordered_map<std::string, OptionTypeInfo>
|
|||||||
{"file_checksum_gen_factory",
|
{"file_checksum_gen_factory",
|
||||||
OptionTypeInfo::AsCustomSharedPtr<FileChecksumGenFactory>(
|
OptionTypeInfo::AsCustomSharedPtr<FileChecksumGenFactory>(
|
||||||
offsetof(struct ImmutableDBOptions, file_checksum_gen_factory),
|
offsetof(struct ImmutableDBOptions, file_checksum_gen_factory),
|
||||||
OptionVerificationType::kByName, OptionTypeFlags::kAllowNull)},
|
OptionVerificationType::kByNameAllowFromNull,
|
||||||
|
OptionTypeFlags::kAllowNull)},
|
||||||
{"statistics",
|
{"statistics",
|
||||||
OptionTypeInfo::AsCustomSharedPtr<Statistics>(
|
OptionTypeInfo::AsCustomSharedPtr<Statistics>(
|
||||||
// Statistics should not be compared and can be null
|
// Statistics should not be compared and can be null
|
||||||
@ -529,19 +530,63 @@ const std::string OptionsHelper::kDBOptionsName = "DBOptions";
|
|||||||
|
|
||||||
class MutableDBConfigurable : public Configurable {
|
class MutableDBConfigurable : public Configurable {
|
||||||
public:
|
public:
|
||||||
explicit MutableDBConfigurable(const MutableDBOptions& mdb) {
|
explicit MutableDBConfigurable(
|
||||||
mutable_ = mdb;
|
const MutableDBOptions& mdb,
|
||||||
|
const std::unordered_map<std::string, std::string>* map = nullptr)
|
||||||
|
: mutable_(mdb), opt_map_(map) {
|
||||||
RegisterOptions(&mutable_, &db_mutable_options_type_info);
|
RegisterOptions(&mutable_, &db_mutable_options_type_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OptionsAreEqual(const ConfigOptions& config_options,
|
||||||
|
const OptionTypeInfo& opt_info,
|
||||||
|
const std::string& opt_name, const void* const this_ptr,
|
||||||
|
const void* const that_ptr,
|
||||||
|
std::string* mismatch) const override {
|
||||||
|
bool equals = opt_info.AreEqual(config_options, opt_name, this_ptr,
|
||||||
|
that_ptr, mismatch);
|
||||||
|
if (!equals && opt_info.IsByName()) {
|
||||||
|
if (opt_map_ == nullptr) {
|
||||||
|
equals = true;
|
||||||
|
} else {
|
||||||
|
const auto& iter = opt_map_->find(opt_name);
|
||||||
|
if (iter == opt_map_->end()) {
|
||||||
|
equals = true;
|
||||||
|
} else {
|
||||||
|
equals = opt_info.AreEqualByName(config_options, opt_name, this_ptr,
|
||||||
|
iter->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (equals) { // False alarm, clear mismatch
|
||||||
|
*mismatch = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (equals && opt_info.IsConfigurable() && opt_map_ != nullptr) {
|
||||||
|
const auto* this_config = opt_info.AsRawPointer<Configurable>(this_ptr);
|
||||||
|
if (this_config == nullptr) {
|
||||||
|
const auto& iter = opt_map_->find(opt_name);
|
||||||
|
// If the name exists in the map and is not empty/null,
|
||||||
|
// then the this_config should be set.
|
||||||
|
if (iter != opt_map_->end() && !iter->second.empty() &&
|
||||||
|
iter->second != kNullptrString) {
|
||||||
|
*mismatch = opt_name;
|
||||||
|
equals = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return equals;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MutableDBOptions mutable_;
|
MutableDBOptions mutable_;
|
||||||
|
const std::unordered_map<std::string, std::string>* opt_map_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DBOptionsConfigurable : public MutableDBConfigurable {
|
class DBOptionsConfigurable : public MutableDBConfigurable {
|
||||||
public:
|
public:
|
||||||
explicit DBOptionsConfigurable(const DBOptions& opts)
|
explicit DBOptionsConfigurable(
|
||||||
: MutableDBConfigurable(MutableDBOptions(opts)), db_options_(opts) {
|
const DBOptions& opts,
|
||||||
|
const std::unordered_map<std::string, std::string>* map = nullptr)
|
||||||
|
: MutableDBConfigurable(MutableDBOptions(opts), map), db_options_(opts) {
|
||||||
// The ImmutableDBOptions currently requires the env to be non-null. Make
|
// The ImmutableDBOptions currently requires the env to be non-null. Make
|
||||||
// sure it is
|
// sure it is
|
||||||
if (opts.env != nullptr) {
|
if (opts.env != nullptr) {
|
||||||
@ -585,8 +630,10 @@ std::unique_ptr<Configurable> DBOptionsAsConfigurable(
|
|||||||
std::unique_ptr<Configurable> ptr(new MutableDBConfigurable(opts));
|
std::unique_ptr<Configurable> ptr(new MutableDBConfigurable(opts));
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
std::unique_ptr<Configurable> DBOptionsAsConfigurable(const DBOptions& opts) {
|
std::unique_ptr<Configurable> DBOptionsAsConfigurable(
|
||||||
std::unique_ptr<Configurable> ptr(new DBOptionsConfigurable(opts));
|
const DBOptions& opts,
|
||||||
|
const std::unordered_map<std::string, std::string>* opt_map) {
|
||||||
|
std::unique_ptr<Configurable> ptr(new DBOptionsConfigurable(opts, opt_map));
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
#endif // ROCKSDB_LITE
|
#endif // ROCKSDB_LITE
|
||||||
|
@ -47,7 +47,9 @@ void UpdateColumnFamilyOptions(const MutableCFOptions& moptions,
|
|||||||
#ifndef ROCKSDB_LITE
|
#ifndef ROCKSDB_LITE
|
||||||
std::unique_ptr<Configurable> DBOptionsAsConfigurable(
|
std::unique_ptr<Configurable> DBOptionsAsConfigurable(
|
||||||
const MutableDBOptions& opts);
|
const MutableDBOptions& opts);
|
||||||
std::unique_ptr<Configurable> DBOptionsAsConfigurable(const DBOptions& opts);
|
std::unique_ptr<Configurable> DBOptionsAsConfigurable(
|
||||||
|
const DBOptions& opts,
|
||||||
|
const std::unordered_map<std::string, std::string>* opt_map = nullptr);
|
||||||
std::unique_ptr<Configurable> CFOptionsAsConfigurable(
|
std::unique_ptr<Configurable> CFOptionsAsConfigurable(
|
||||||
const MutableCFOptions& opts);
|
const MutableCFOptions& opts);
|
||||||
std::unique_ptr<Configurable> CFOptionsAsConfigurable(
|
std::unique_ptr<Configurable> CFOptionsAsConfigurable(
|
||||||
|
@ -553,6 +553,12 @@ Status RocksDBOptionsParser::VerifyRocksDBOptionsFromFile(
|
|||||||
ConfigOptions config_options = config_options_in;
|
ConfigOptions config_options = config_options_in;
|
||||||
config_options.invoke_prepare_options =
|
config_options.invoke_prepare_options =
|
||||||
false; // No need to do a prepare for verify
|
false; // No need to do a prepare for verify
|
||||||
|
if (config_options.sanity_level < ConfigOptions::kSanityLevelExactMatch) {
|
||||||
|
// If we are not doing an exact comparison, we should ignore
|
||||||
|
// unsupported options, as they may cause the Parse to fail
|
||||||
|
// (if the ObjectRegistry is not initialized)
|
||||||
|
config_options.ignore_unsupported_options = true;
|
||||||
|
}
|
||||||
Status s = parser.Parse(config_options, file_name, fs);
|
Status s = parser.Parse(config_options, file_name, fs);
|
||||||
if (!s.ok()) {
|
if (!s.ok()) {
|
||||||
return s;
|
return s;
|
||||||
@ -622,9 +628,9 @@ Status RocksDBOptionsParser::VerifyRocksDBOptionsFromFile(
|
|||||||
Status RocksDBOptionsParser::VerifyDBOptions(
|
Status RocksDBOptionsParser::VerifyDBOptions(
|
||||||
const ConfigOptions& config_options, const DBOptions& base_opt,
|
const ConfigOptions& config_options, const DBOptions& base_opt,
|
||||||
const DBOptions& file_opt,
|
const DBOptions& file_opt,
|
||||||
const std::unordered_map<std::string, std::string>* /*opt_map*/) {
|
const std::unordered_map<std::string, std::string>* opt_map) {
|
||||||
auto base_config = DBOptionsAsConfigurable(base_opt);
|
auto base_config = DBOptionsAsConfigurable(base_opt, opt_map);
|
||||||
auto file_config = DBOptionsAsConfigurable(file_opt);
|
auto file_config = DBOptionsAsConfigurable(file_opt, opt_map);
|
||||||
std::string mismatch;
|
std::string mismatch;
|
||||||
if (!base_config->AreEquivalent(config_options, file_config.get(),
|
if (!base_config->AreEquivalent(config_options, file_config.get(),
|
||||||
&mismatch)) {
|
&mismatch)) {
|
||||||
|
@ -3710,37 +3710,86 @@ TEST_F(OptionsParserTest, DifferentDefault) {
|
|||||||
ASSERT_EQ(5000, small_opts.max_open_files);
|
ASSERT_EQ(5000, small_opts.max_open_files);
|
||||||
}
|
}
|
||||||
|
|
||||||
class OptionsSanityCheckTest : public OptionsParserTest {
|
class OptionsSanityCheckTest : public OptionsParserTest,
|
||||||
|
public ::testing::WithParamInterface<bool> {
|
||||||
|
protected:
|
||||||
|
ConfigOptions config_options_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OptionsSanityCheckTest() {}
|
OptionsSanityCheckTest() {
|
||||||
|
config_options_.ignore_unknown_options = false;
|
||||||
|
config_options_.ignore_unsupported_options = GetParam();
|
||||||
|
config_options_.input_strings_escaped = true;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Status SanityCheckCFOptions(const ColumnFamilyOptions& cf_opts,
|
Status SanityCheckOptions(const DBOptions& db_opts,
|
||||||
ConfigOptions::SanityLevel level,
|
const ColumnFamilyOptions& cf_opts,
|
||||||
bool input_strings_escaped = true) {
|
ConfigOptions::SanityLevel level) {
|
||||||
ConfigOptions config_options;
|
config_options_.sanity_level = level;
|
||||||
config_options.sanity_level = level;
|
|
||||||
config_options.ignore_unknown_options = false;
|
|
||||||
config_options.input_strings_escaped = input_strings_escaped;
|
|
||||||
|
|
||||||
return RocksDBOptionsParser::VerifyRocksDBOptionsFromFile(
|
return RocksDBOptionsParser::VerifyRocksDBOptionsFromFile(
|
||||||
config_options, DBOptions(), {"default"}, {cf_opts}, kOptionsFileName,
|
config_options_, db_opts, {"default"}, {cf_opts}, kOptionsFileName,
|
||||||
fs_.get());
|
fs_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
Status PersistCFOptions(const ColumnFamilyOptions& cf_opts) {
|
Status SanityCheckCFOptions(const ColumnFamilyOptions& cf_opts,
|
||||||
|
ConfigOptions::SanityLevel level) {
|
||||||
|
return SanityCheckOptions(DBOptions(), cf_opts, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SanityCheckCFOptions(const ColumnFamilyOptions& opts, bool exact) {
|
||||||
|
ASSERT_OK(SanityCheckCFOptions(
|
||||||
|
opts, ConfigOptions::kSanityLevelLooselyCompatible));
|
||||||
|
ASSERT_OK(SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelNone));
|
||||||
|
if (exact) {
|
||||||
|
ASSERT_OK(
|
||||||
|
SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
|
||||||
|
} else {
|
||||||
|
ASSERT_NOK(
|
||||||
|
SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Status SanityCheckDBOptions(const DBOptions& db_opts,
|
||||||
|
ConfigOptions::SanityLevel level) {
|
||||||
|
return SanityCheckOptions(db_opts, ColumnFamilyOptions(), level);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SanityCheckDBOptions(const DBOptions& opts, bool exact) {
|
||||||
|
ASSERT_OK(SanityCheckDBOptions(
|
||||||
|
opts, ConfigOptions::kSanityLevelLooselyCompatible));
|
||||||
|
ASSERT_OK(SanityCheckDBOptions(opts, ConfigOptions::kSanityLevelNone));
|
||||||
|
if (exact) {
|
||||||
|
ASSERT_OK(
|
||||||
|
SanityCheckDBOptions(opts, ConfigOptions::kSanityLevelExactMatch));
|
||||||
|
} else {
|
||||||
|
ASSERT_NOK(
|
||||||
|
SanityCheckDBOptions(opts, ConfigOptions::kSanityLevelExactMatch));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Status PersistOptions(const DBOptions& db_opts,
|
||||||
|
const ColumnFamilyOptions& cf_opts) {
|
||||||
Status s = fs_->DeleteFile(kOptionsFileName, IOOptions(), nullptr);
|
Status s = fs_->DeleteFile(kOptionsFileName, IOOptions(), nullptr);
|
||||||
if (!s.ok()) {
|
if (!s.ok()) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
return PersistRocksDBOptions(DBOptions(), {"default"}, {cf_opts},
|
return PersistRocksDBOptions(db_opts, {"default"}, {cf_opts},
|
||||||
kOptionsFileName, fs_.get());
|
kOptionsFileName, fs_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Status PersistCFOptions(const ColumnFamilyOptions& cf_opts) {
|
||||||
|
return PersistOptions(DBOptions(), cf_opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status PersistDBOptions(const DBOptions& db_opts) {
|
||||||
|
return PersistOptions(db_opts, ColumnFamilyOptions());
|
||||||
|
}
|
||||||
|
|
||||||
const std::string kOptionsFileName = "OPTIONS";
|
const std::string kOptionsFileName = "OPTIONS";
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(OptionsSanityCheckTest, SanityCheck) {
|
TEST_P(OptionsSanityCheckTest, CFOptionsSanityCheck) {
|
||||||
ColumnFamilyOptions opts;
|
ColumnFamilyOptions opts;
|
||||||
Random rnd(301);
|
Random rnd(301);
|
||||||
|
|
||||||
@ -3792,11 +3841,7 @@ TEST_F(OptionsSanityCheckTest, SanityCheck) {
|
|||||||
opts.prefix_extractor.reset(NewFixedPrefixTransform(15));
|
opts.prefix_extractor.reset(NewFixedPrefixTransform(15));
|
||||||
// expect pass only in
|
// expect pass only in
|
||||||
// ConfigOptions::kSanityLevelLooselyCompatible
|
// ConfigOptions::kSanityLevelLooselyCompatible
|
||||||
ASSERT_NOK(
|
SanityCheckCFOptions(opts, false);
|
||||||
SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
|
|
||||||
ASSERT_OK(SanityCheckCFOptions(
|
|
||||||
opts, ConfigOptions::kSanityLevelLooselyCompatible));
|
|
||||||
ASSERT_OK(SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelNone));
|
|
||||||
|
|
||||||
// Change prefix extractor from non-nullptr to nullptr
|
// Change prefix extractor from non-nullptr to nullptr
|
||||||
opts.prefix_extractor.reset();
|
opts.prefix_extractor.reset();
|
||||||
@ -3836,8 +3881,7 @@ TEST_F(OptionsSanityCheckTest, SanityCheck) {
|
|||||||
|
|
||||||
// persist the change
|
// persist the change
|
||||||
ASSERT_OK(PersistCFOptions(opts));
|
ASSERT_OK(PersistCFOptions(opts));
|
||||||
ASSERT_OK(
|
SanityCheckCFOptions(opts, config_options_.ignore_unsupported_options);
|
||||||
SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
|
|
||||||
|
|
||||||
for (int test = 0; test < 5; ++test) {
|
for (int test = 0; test < 5; ++test) {
|
||||||
// change the merge operator
|
// change the merge operator
|
||||||
@ -3848,8 +3892,7 @@ TEST_F(OptionsSanityCheckTest, SanityCheck) {
|
|||||||
|
|
||||||
// persist the change
|
// persist the change
|
||||||
ASSERT_OK(PersistCFOptions(opts));
|
ASSERT_OK(PersistCFOptions(opts));
|
||||||
ASSERT_OK(
|
SanityCheckCFOptions(opts, config_options_.ignore_unsupported_options);
|
||||||
SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test when going from merge operator -> nullptr
|
// Test when going from merge operator -> nullptr
|
||||||
@ -3860,8 +3903,7 @@ TEST_F(OptionsSanityCheckTest, SanityCheck) {
|
|||||||
|
|
||||||
// persist the change
|
// persist the change
|
||||||
ASSERT_OK(PersistCFOptions(opts));
|
ASSERT_OK(PersistCFOptions(opts));
|
||||||
ASSERT_OK(
|
SanityCheckCFOptions(opts, true);
|
||||||
SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// compaction_filter
|
// compaction_filter
|
||||||
@ -3869,15 +3911,11 @@ TEST_F(OptionsSanityCheckTest, SanityCheck) {
|
|||||||
for (int test = 0; test < 5; ++test) {
|
for (int test = 0; test < 5; ++test) {
|
||||||
// change the compaction filter
|
// change the compaction filter
|
||||||
opts.compaction_filter = test::RandomCompactionFilter(&rnd);
|
opts.compaction_filter = test::RandomCompactionFilter(&rnd);
|
||||||
ASSERT_NOK(
|
SanityCheckCFOptions(opts, false);
|
||||||
SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
|
|
||||||
ASSERT_OK(SanityCheckCFOptions(
|
|
||||||
opts, ConfigOptions::kSanityLevelLooselyCompatible));
|
|
||||||
|
|
||||||
// persist the change
|
// persist the change
|
||||||
ASSERT_OK(PersistCFOptions(opts));
|
ASSERT_OK(PersistCFOptions(opts));
|
||||||
ASSERT_OK(
|
SanityCheckCFOptions(opts, config_options_.ignore_unsupported_options);
|
||||||
SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
|
|
||||||
delete opts.compaction_filter;
|
delete opts.compaction_filter;
|
||||||
opts.compaction_filter = nullptr;
|
opts.compaction_filter = nullptr;
|
||||||
}
|
}
|
||||||
@ -3889,17 +3927,55 @@ TEST_F(OptionsSanityCheckTest, SanityCheck) {
|
|||||||
// change the compaction filter factory
|
// change the compaction filter factory
|
||||||
opts.compaction_filter_factory.reset(
|
opts.compaction_filter_factory.reset(
|
||||||
test::RandomCompactionFilterFactory(&rnd));
|
test::RandomCompactionFilterFactory(&rnd));
|
||||||
ASSERT_NOK(
|
SanityCheckCFOptions(opts, false);
|
||||||
SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
|
|
||||||
ASSERT_OK(SanityCheckCFOptions(
|
|
||||||
opts, ConfigOptions::kSanityLevelLooselyCompatible));
|
|
||||||
|
|
||||||
// persist the change
|
// persist the change
|
||||||
ASSERT_OK(PersistCFOptions(opts));
|
ASSERT_OK(PersistCFOptions(opts));
|
||||||
|
SanityCheckCFOptions(opts, config_options_.ignore_unsupported_options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(OptionsSanityCheckTest, DBOptionsSanityCheck) {
|
||||||
|
DBOptions opts;
|
||||||
|
Random rnd(301);
|
||||||
|
|
||||||
|
// default DBOptions
|
||||||
|
{
|
||||||
|
ASSERT_OK(PersistDBOptions(opts));
|
||||||
ASSERT_OK(
|
ASSERT_OK(
|
||||||
SanityCheckCFOptions(opts, ConfigOptions::kSanityLevelExactMatch));
|
SanityCheckDBOptions(opts, ConfigOptions::kSanityLevelExactMatch));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// File checksum generator
|
||||||
|
{
|
||||||
|
class MockFileChecksumGenFactory : public FileChecksumGenFactory {
|
||||||
|
public:
|
||||||
|
static const char* kClassName() { return "Mock"; }
|
||||||
|
const char* Name() const override { return kClassName(); }
|
||||||
|
std::unique_ptr<FileChecksumGenerator> CreateFileChecksumGenerator(
|
||||||
|
const FileChecksumGenContext& /*context*/) override {
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Okay to change file_checksum_gen_factory form nullptr to non-nullptr
|
||||||
|
ASSERT_EQ(opts.file_checksum_gen_factory.get(), nullptr);
|
||||||
|
opts.file_checksum_gen_factory.reset(new MockFileChecksumGenFactory());
|
||||||
|
|
||||||
|
// persist the change
|
||||||
|
ASSERT_OK(PersistDBOptions(opts));
|
||||||
|
SanityCheckDBOptions(opts, config_options_.ignore_unsupported_options);
|
||||||
|
|
||||||
|
// Change file_checksum_gen_factory from non-nullptr to nullptr
|
||||||
|
opts.file_checksum_gen_factory.reset();
|
||||||
|
// expect pass as it's safe to change file_checksum_gen_factory
|
||||||
|
// from non-null to null
|
||||||
|
SanityCheckDBOptions(opts, false);
|
||||||
|
}
|
||||||
|
// persist the change
|
||||||
|
ASSERT_OK(PersistDBOptions(opts));
|
||||||
|
ASSERT_OK(SanityCheckDBOptions(opts, ConfigOptions::kSanityLevelExactMatch));
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -4612,7 +4688,11 @@ TEST_F(ConfigOptionsTest, MergeOperatorFromString) {
|
|||||||
ASSERT_NE(delimiter, nullptr);
|
ASSERT_NE(delimiter, nullptr);
|
||||||
ASSERT_EQ(*delimiter, "&&");
|
ASSERT_EQ(*delimiter, "&&");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_CASE_P(OptionsSanityCheckTest, OptionsSanityCheckTest,
|
||||||
|
::testing::Bool());
|
||||||
#endif // !ROCKSDB_LITE
|
#endif // !ROCKSDB_LITE
|
||||||
|
|
||||||
} // namespace ROCKSDB_NAMESPACE
|
} // namespace ROCKSDB_NAMESPACE
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
@ -218,12 +218,14 @@ Status SliceTransform::CreateFromString(
|
|||||||
value, &id, &opt_map);
|
value, &id, &opt_map);
|
||||||
if (!status.ok()) { // GetOptionsMap failed
|
if (!status.ok()) { // GetOptionsMap failed
|
||||||
return status;
|
return status;
|
||||||
}
|
} else if (id.empty() && opt_map.empty()) {
|
||||||
|
result->reset();
|
||||||
|
} else {
|
||||||
#ifndef ROCKSDB_LITE
|
#ifndef ROCKSDB_LITE
|
||||||
status = config_options.registry->NewSharedObject(id, result);
|
status = config_options.registry->NewSharedObject(id, result);
|
||||||
#else
|
#else
|
||||||
auto Matches = [](const std::string& input, size_t size, const char* pattern,
|
auto Matches = [](const std::string& input, size_t size,
|
||||||
char sep) {
|
const char* pattern, char sep) {
|
||||||
auto plen = strlen(pattern);
|
auto plen = strlen(pattern);
|
||||||
return (size > plen + 2 && input[plen] == sep &&
|
return (size > plen + 2 && input[plen] == sep &&
|
||||||
StartsWith(input, pattern));
|
StartsWith(input, pattern));
|
||||||
@ -252,15 +254,13 @@ Status SliceTransform::CreateFromString(
|
|||||||
status = Status::NotSupported("Cannot load object in LITE mode ", id);
|
status = Status::NotSupported("Cannot load object in LITE mode ", id);
|
||||||
}
|
}
|
||||||
#endif // ROCKSDB_LITE
|
#endif // ROCKSDB_LITE
|
||||||
if (!status.ok()) {
|
|
||||||
if (config_options.ignore_unsupported_options && status.IsNotSupported()) {
|
if (config_options.ignore_unsupported_options && status.IsNotSupported()) {
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
} else {
|
} else if (status.ok()) {
|
||||||
return status;
|
|
||||||
}
|
|
||||||
} else if (result->get() != nullptr) {
|
|
||||||
SliceTransform* transform = const_cast<SliceTransform*>(result->get());
|
SliceTransform* transform = const_cast<SliceTransform*>(result->get());
|
||||||
status = transform->ConfigureFromMap(config_options, opt_map);
|
status =
|
||||||
|
Customizable::ConfigureNewObject(config_options, transform, opt_map);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
} // namespace ROCKSDB_NAMESPACE
|
} // namespace ROCKSDB_NAMESPACE
|
||||||
|
Loading…
Reference in New Issue
Block a user