diff --git a/HISTORY.md b/HISTORY.md index 55dd18d93..2819c69a5 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,9 @@ # Rocksdb Change Log +### Unreleased +### New Features +* When reading from option file/string/map, customized comparators and/or merge operators can be filled according to object registry. + ## 6.1.0 (3/27/2019) ### New Features * Introduce two more stats levels, kExceptHistogramOrTimers and kExceptTimers. diff --git a/include/rocksdb/utilities/options_util.h b/include/rocksdb/utilities/options_util.h index aa5116e0a..d97b394ea 100644 --- a/include/rocksdb/utilities/options_util.h +++ b/include/rocksdb/utilities/options_util.h @@ -33,6 +33,12 @@ namespace rocksdb { // * merge_operator // * compaction_filter // +// User can also choose to load customized comparator and/or merge_operator +// through object registry: +// * comparator needs to be registered through Registrar +// * merge operator needs to be registered through +// Registrar>. +// // For table_factory, this function further supports deserializing // BlockBasedTableFactory and its BlockBasedTableOptions except the // pointer options of BlockBasedTableOptions (flush_block_policy_factory, diff --git a/options/options_helper.cc b/options/options_helper.cc index ed0efa3e4..be8ec2e18 100644 --- a/options/options_helper.cc +++ b/options/options_helper.cc @@ -242,6 +242,7 @@ std::unordered_map #ifndef ROCKSDB_LITE const std::string kNameComparator = "comparator"; +const std::string kNameMergeOperator = "merge_operator"; template Status GetStringFromStruct( @@ -1025,7 +1026,17 @@ Status ParseColumnFamilyOption(const std::string& name, if (comp != nullptr && !comp_guard) { new_options->comparator = comp; } + } else if (name == kNameMergeOperator) { + // Try to get merge operator from object registry first. + std::unique_ptr> mo_guard; + std::shared_ptr* mo = + NewCustomObject>(value, &mo_guard); + // Only support static comparator for now. + if (mo != nullptr) { + new_options->merge_operator = *mo; + } } + auto iter = cf_options_type_info.find(name); if (iter == cf_options_type_info.end()) { return Status::InvalidArgument( @@ -1917,7 +1928,7 @@ std::unordered_map {offset_of(&ColumnFamilyOptions::compaction_filter_factory), OptionType::kCompactionFilterFactory, OptionVerificationType::kByName, false, 0}}, - {"merge_operator", + {kNameMergeOperator, {offset_of(&ColumnFamilyOptions::merge_operator), OptionType::kMergeOperator, OptionVerificationType::kByNameAllowFromNull, false, 0}}, diff --git a/options/options_test.cc b/options/options_test.cc index 32f178df9..586e5697c 100644 --- a/options/options_test.cc +++ b/options/options_test.cc @@ -32,6 +32,7 @@ #include "util/string_util.h" #include "util/testharness.h" #include "util/testutil.h" +#include "utilities/merge_operators/bytesxor.h" #ifndef GFLAGS bool FLAGS_enable_print = false; @@ -348,6 +349,22 @@ TEST_F(OptionsTest, GetColumnFamilyOptionsFromStringTest) { base_cf_opt, "comparator=" + kCompName + ";", &new_cf_opt)); ASSERT_EQ(new_cf_opt.comparator, ReverseBytewiseComparator()); + // MergeOperator from object registry + std::unique_ptr bxo(new BytesXOROperator()); + std::string kMoName = bxo->Name(); + static Registrar> test_reg_b( + kMoName, [](const std::string& /*name*/, + std::unique_ptr>* + merge_operator_guard) { + merge_operator_guard->reset( + new std::shared_ptr(new BytesXOROperator())); + return merge_operator_guard->get(); + }); + + ASSERT_OK(GetColumnFamilyOptionsFromString( + base_cf_opt, "merge_operator=" + kMoName + ";", &new_cf_opt)); + ASSERT_EQ(kMoName, std::string(new_cf_opt.merge_operator->Name())); + // Wrong key/value pair ASSERT_NOK(GetColumnFamilyOptionsFromString(base_cf_opt, "write_buffer_size=13;max_write_buffer_number;", &new_cf_opt));