Revert "Make Comparator into a Customizable Object (#8336)"
This reverts commit 6ad0810393
.
This commit is contained in:
parent
6fc2818ef8
commit
6ee0acdbb4
@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "rocksdb/customizable.h"
|
|
||||||
#include "rocksdb/rocksdb_namespace.h"
|
#include "rocksdb/rocksdb_namespace.h"
|
||||||
|
|
||||||
namespace ROCKSDB_NAMESPACE {
|
namespace ROCKSDB_NAMESPACE {
|
||||||
@ -21,7 +20,7 @@ class Slice;
|
|||||||
// used as keys in an sstable or a database. A Comparator implementation
|
// used as keys in an sstable or a database. A Comparator implementation
|
||||||
// must be thread-safe since rocksdb may invoke its methods concurrently
|
// must be thread-safe since rocksdb may invoke its methods concurrently
|
||||||
// from multiple threads.
|
// from multiple threads.
|
||||||
class Comparator : public Customizable {
|
class Comparator {
|
||||||
public:
|
public:
|
||||||
Comparator() : timestamp_size_(0) {}
|
Comparator() : timestamp_size_(0) {}
|
||||||
|
|
||||||
@ -38,11 +37,7 @@ class Comparator : public Customizable {
|
|||||||
|
|
||||||
virtual ~Comparator() {}
|
virtual ~Comparator() {}
|
||||||
|
|
||||||
static Status CreateFromString(const ConfigOptions& opts,
|
|
||||||
const std::string& id,
|
|
||||||
const Comparator** comp);
|
|
||||||
static const char* Type() { return "Comparator"; }
|
static const char* Type() { return "Comparator"; }
|
||||||
|
|
||||||
// Three-way comparison. Returns value:
|
// Three-way comparison. Returns value:
|
||||||
// < 0 iff "a" < "b",
|
// < 0 iff "a" < "b",
|
||||||
// == 0 iff "a" == "b",
|
// == 0 iff "a" == "b",
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
@ -270,7 +269,7 @@ class Configurable {
|
|||||||
protected:
|
protected:
|
||||||
// True once the object is prepared. Once the object is prepared, only
|
// True once the object is prepared. Once the object is prepared, only
|
||||||
// mutable options can be configured.
|
// mutable options can be configured.
|
||||||
std::atomic<bool> prepared_;
|
bool prepared_;
|
||||||
|
|
||||||
// Returns the raw pointer for the associated named option.
|
// Returns the raw pointer for the associated named option.
|
||||||
// The name is typically the name of an option registered via the
|
// The name is typically the name of an option registered via the
|
||||||
|
@ -35,6 +35,7 @@ enum class OptionType {
|
|||||||
kCompactionPri,
|
kCompactionPri,
|
||||||
kSliceTransform,
|
kSliceTransform,
|
||||||
kCompressionType,
|
kCompressionType,
|
||||||
|
kComparator,
|
||||||
kCompactionFilter,
|
kCompactionFilter,
|
||||||
kCompactionFilterFactory,
|
kCompactionFilterFactory,
|
||||||
kCompactionStopStyle,
|
kCompactionStopStyle,
|
||||||
|
@ -535,30 +535,22 @@ static std::unordered_map<std::string, OptionTypeInfo>
|
|||||||
OptionVerificationType::kNormal, OptionTypeFlags::kNone,
|
OptionVerificationType::kNormal, OptionTypeFlags::kNone,
|
||||||
{0, OptionType::kCompressionType})},
|
{0, OptionType::kCompressionType})},
|
||||||
{"comparator",
|
{"comparator",
|
||||||
OptionTypeInfo::AsCustomRawPtr<const Comparator>(
|
{offset_of(&ImmutableCFOptions::user_comparator),
|
||||||
offset_of(&ImmutableCFOptions::user_comparator),
|
OptionType::kComparator, OptionVerificationType::kByName,
|
||||||
OptionVerificationType::kByName, OptionTypeFlags::kCompareLoose,
|
OptionTypeFlags::kCompareLoose,
|
||||||
// Serializes a Comparator
|
// Parses the string and sets the corresponding comparator
|
||||||
[](const ConfigOptions& /*opts*/, const std::string&,
|
[](const ConfigOptions& opts, const std::string& /*name*/,
|
||||||
const void* addr, std::string* value) {
|
const std::string& value, void* addr) {
|
||||||
// it's a const pointer of const Comparator*
|
auto old_comparator = static_cast<const Comparator**>(addr);
|
||||||
const auto* ptr = static_cast<const Comparator* const*>(addr);
|
const Comparator* new_comparator = *old_comparator;
|
||||||
|
Status status =
|
||||||
// Since the user-specified comparator will be wrapped by
|
opts.registry->NewStaticObject(value, &new_comparator);
|
||||||
// InternalKeyComparator, we should persist the user-specified
|
if (status.ok()) {
|
||||||
// one instead of InternalKeyComparator.
|
*old_comparator = new_comparator;
|
||||||
if (*ptr == nullptr) {
|
return status;
|
||||||
*value = kNullptrString;
|
|
||||||
} else {
|
|
||||||
const Comparator* root_comp = (*ptr)->GetRootComparator();
|
|
||||||
if (root_comp == nullptr) {
|
|
||||||
root_comp = (*ptr);
|
|
||||||
}
|
|
||||||
*value = root_comp->Name();
|
|
||||||
}
|
}
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
},
|
}}},
|
||||||
/* Use the default match function*/ nullptr)},
|
|
||||||
{"memtable_insert_with_hint_prefix_extractor",
|
{"memtable_insert_with_hint_prefix_extractor",
|
||||||
{offset_of(
|
{offset_of(
|
||||||
&ImmutableCFOptions::memtable_insert_with_hint_prefix_extractor),
|
&ImmutableCFOptions::memtable_insert_with_hint_prefix_extractor),
|
||||||
|
@ -771,15 +771,6 @@ static int RegisterTestObjects(ObjectLibrary& library,
|
|||||||
guard->reset(new mock::MockTableFactory());
|
guard->reset(new mock::MockTableFactory());
|
||||||
return guard->get();
|
return guard->get();
|
||||||
});
|
});
|
||||||
library.Register<const Comparator>(
|
|
||||||
test::SimpleSuffixReverseComparator::kClassName(),
|
|
||||||
[](const std::string& /*uri*/,
|
|
||||||
std::unique_ptr<const Comparator>* /*guard*/,
|
|
||||||
std::string* /* errmsg */) {
|
|
||||||
static test::SimpleSuffixReverseComparator ssrc;
|
|
||||||
return &ssrc;
|
|
||||||
});
|
|
||||||
|
|
||||||
return static_cast<int>(library.GetFactoryCount(&num_types));
|
return static_cast<int>(library.GetFactoryCount(&num_types));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -789,7 +780,6 @@ static int RegisterLocalObjects(ObjectLibrary& library,
|
|||||||
// Load any locally defined objects here
|
// Load any locally defined objects here
|
||||||
return static_cast<int>(library.GetFactoryCount(&num_types));
|
return static_cast<int>(library.GetFactoryCount(&num_types));
|
||||||
}
|
}
|
||||||
#endif // !ROCKSDB_LITE
|
|
||||||
|
|
||||||
class LoadCustomizableTest : public testing::Test {
|
class LoadCustomizableTest : public testing::Test {
|
||||||
public:
|
public:
|
||||||
@ -829,31 +819,7 @@ TEST_F(LoadCustomizableTest, LoadTableFactoryTest) {
|
|||||||
ASSERT_STREQ(factory->Name(), "MockTable");
|
ASSERT_STREQ(factory->Name(), "MockTable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // !ROCKSDB_LITE
|
||||||
TEST_F(LoadCustomizableTest, LoadComparatorTest) {
|
|
||||||
const Comparator* bytewise = BytewiseComparator();
|
|
||||||
const Comparator* reverse = ReverseBytewiseComparator();
|
|
||||||
|
|
||||||
const Comparator* result = nullptr;
|
|
||||||
ASSERT_NOK(Comparator::CreateFromString(
|
|
||||||
config_options_, test::SimpleSuffixReverseComparator::kClassName(),
|
|
||||||
&result));
|
|
||||||
ASSERT_OK(
|
|
||||||
Comparator::CreateFromString(config_options_, bytewise->Name(), &result));
|
|
||||||
ASSERT_EQ(result, bytewise);
|
|
||||||
ASSERT_OK(
|
|
||||||
Comparator::CreateFromString(config_options_, reverse->Name(), &result));
|
|
||||||
ASSERT_EQ(result, reverse);
|
|
||||||
|
|
||||||
if (RegisterTests("Test")) {
|
|
||||||
ASSERT_OK(Comparator::CreateFromString(
|
|
||||||
config_options_, test::SimpleSuffixReverseComparator::kClassName(),
|
|
||||||
&result));
|
|
||||||
ASSERT_NE(result, nullptr);
|
|
||||||
ASSERT_STREQ(result->Name(),
|
|
||||||
test::SimpleSuffixReverseComparator::kClassName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ROCKSDB_NAMESPACE
|
} // namespace ROCKSDB_NAMESPACE
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
@ -562,6 +562,23 @@ bool SerializeSingleOptionHelper(const void* opt_address,
|
|||||||
: kNullptrString;
|
: kNullptrString;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OptionType::kComparator: {
|
||||||
|
// it's a const pointer of const Comparator*
|
||||||
|
const auto* ptr = static_cast<const Comparator* const*>(opt_address);
|
||||||
|
// Since the user-specified comparator will be wrapped by
|
||||||
|
// InternalKeyComparator, we should persist the user-specified one
|
||||||
|
// instead of InternalKeyComparator.
|
||||||
|
if (*ptr == nullptr) {
|
||||||
|
*value = kNullptrString;
|
||||||
|
} else {
|
||||||
|
const Comparator* root_comp = (*ptr)->GetRootComparator();
|
||||||
|
if (root_comp == nullptr) {
|
||||||
|
root_comp = (*ptr);
|
||||||
|
}
|
||||||
|
*value = root_comp->Name();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case OptionType::kCompactionFilter: {
|
case OptionType::kCompactionFilter: {
|
||||||
// it's a const pointer of const CompactionFilter*
|
// it's a const pointer of const CompactionFilter*
|
||||||
const auto* ptr =
|
const auto* ptr =
|
||||||
|
@ -98,8 +98,10 @@ class PlainInternalKeyComparator : public InternalKeyComparator {
|
|||||||
class SimpleSuffixReverseComparator : public Comparator {
|
class SimpleSuffixReverseComparator : public Comparator {
|
||||||
public:
|
public:
|
||||||
SimpleSuffixReverseComparator() {}
|
SimpleSuffixReverseComparator() {}
|
||||||
static const char* kClassName() { return "SimpleSuffixReverseComparator"; }
|
|
||||||
virtual const char* Name() const override { return kClassName(); }
|
virtual const char* Name() const override {
|
||||||
|
return "SimpleSuffixReverseComparator";
|
||||||
|
}
|
||||||
|
|
||||||
virtual int Compare(const Slice& a, const Slice& b) const override {
|
virtual int Compare(const Slice& a, const Slice& b) const override {
|
||||||
Slice prefix_a = Slice(a.data(), 8);
|
Slice prefix_a = Slice(a.data(), 8);
|
||||||
|
@ -8,17 +8,11 @@
|
|||||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||||
|
|
||||||
#include "rocksdb/comparator.h"
|
#include "rocksdb/comparator.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
#include "options/configurable_helper.h"
|
|
||||||
#include "port/port.h"
|
#include "port/port.h"
|
||||||
#include "rocksdb/slice.h"
|
#include "rocksdb/slice.h"
|
||||||
#include "rocksdb/utilities/object_registry.h"
|
|
||||||
|
|
||||||
namespace ROCKSDB_NAMESPACE {
|
namespace ROCKSDB_NAMESPACE {
|
||||||
|
|
||||||
@ -26,8 +20,8 @@ namespace {
|
|||||||
class BytewiseComparatorImpl : public Comparator {
|
class BytewiseComparatorImpl : public Comparator {
|
||||||
public:
|
public:
|
||||||
BytewiseComparatorImpl() { }
|
BytewiseComparatorImpl() { }
|
||||||
static const char* kClassName() { return "leveldb.BytewiseComparator"; }
|
|
||||||
const char* Name() const override { return kClassName(); }
|
const char* Name() const override { return "leveldb.BytewiseComparator"; }
|
||||||
|
|
||||||
int Compare(const Slice& a, const Slice& b) const override {
|
int Compare(const Slice& a, const Slice& b) const override {
|
||||||
return a.compare(b);
|
return a.compare(b);
|
||||||
@ -145,10 +139,9 @@ class ReverseBytewiseComparatorImpl : public BytewiseComparatorImpl {
|
|||||||
public:
|
public:
|
||||||
ReverseBytewiseComparatorImpl() { }
|
ReverseBytewiseComparatorImpl() { }
|
||||||
|
|
||||||
static const char* kClassName() {
|
const char* Name() const override {
|
||||||
return "rocksdb.ReverseBytewiseComparator";
|
return "rocksdb.ReverseBytewiseComparator";
|
||||||
}
|
}
|
||||||
const char* Name() const override { return kClassName(); }
|
|
||||||
|
|
||||||
int Compare(const Slice& a, const Slice& b) const override {
|
int Compare(const Slice& a, const Slice& b) const override {
|
||||||
return -a.compare(b);
|
return -a.compare(b);
|
||||||
@ -227,77 +220,4 @@ const Comparator* ReverseBytewiseComparator() {
|
|||||||
return &rbytewise;
|
return &rbytewise;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ROCKSDB_LITE
|
|
||||||
static int RegisterBuiltinComparators(ObjectLibrary& library,
|
|
||||||
const std::string& /*arg*/) {
|
|
||||||
library.Register<const Comparator>(
|
|
||||||
BytewiseComparatorImpl::kClassName(),
|
|
||||||
[](const std::string& /*uri*/,
|
|
||||||
std::unique_ptr<const Comparator>* /*guard */,
|
|
||||||
std::string* /* errmsg */) { return BytewiseComparator(); });
|
|
||||||
library.Register<const Comparator>(
|
|
||||||
ReverseBytewiseComparatorImpl::kClassName(),
|
|
||||||
[](const std::string& /*uri*/,
|
|
||||||
std::unique_ptr<const Comparator>* /*guard */,
|
|
||||||
std::string* /* errmsg */) { return ReverseBytewiseComparator(); });
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
#endif // ROCKSDB_LITE
|
|
||||||
|
|
||||||
Status Comparator::CreateFromString(const ConfigOptions& config_options,
|
|
||||||
const std::string& value,
|
|
||||||
const Comparator** result) {
|
|
||||||
#ifndef ROCKSDB_LITE
|
|
||||||
static std::once_flag once;
|
|
||||||
std::call_once(once, [&]() {
|
|
||||||
RegisterBuiltinComparators(*(ObjectLibrary::Default().get()), "");
|
|
||||||
});
|
|
||||||
#endif // ROCKSDB_LITE
|
|
||||||
std::string id;
|
|
||||||
std::unordered_map<std::string, std::string> opt_map;
|
|
||||||
Status status =
|
|
||||||
ConfigurableHelper::GetOptionsMap(value, *result, &id, &opt_map);
|
|
||||||
if (!status.ok()) { // GetOptionsMap failed
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
std::string curr_opts;
|
|
||||||
#ifndef ROCKSDB_LITE
|
|
||||||
if (*result != nullptr && (*result)->GetId() == id) {
|
|
||||||
// Try to get the existing options, ignoring any errors
|
|
||||||
ConfigOptions embedded = config_options;
|
|
||||||
embedded.delimiter = ";";
|
|
||||||
(*result)->GetOptionString(embedded, &curr_opts).PermitUncheckedError();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (id == BytewiseComparatorImpl::kClassName()) {
|
|
||||||
*result = BytewiseComparator();
|
|
||||||
} else if (id == ReverseBytewiseComparatorImpl::kClassName()) {
|
|
||||||
*result = ReverseBytewiseComparator();
|
|
||||||
} else if (value.empty()) {
|
|
||||||
// No Id and no options. Clear the object
|
|
||||||
*result = nullptr;
|
|
||||||
return Status::OK();
|
|
||||||
} else if (id.empty()) { // We have no Id but have options. Not good
|
|
||||||
return Status::NotSupported("Cannot reset object ", id);
|
|
||||||
} else {
|
|
||||||
#ifndef ROCKSDB_LITE
|
|
||||||
status = config_options.registry->NewStaticObject(id, result);
|
|
||||||
#else
|
|
||||||
status = Status::NotSupported("Cannot load object in LITE mode ", id);
|
|
||||||
#endif // ROCKSDB_LITE
|
|
||||||
if (!status.ok()) {
|
|
||||||
if (config_options.ignore_unsupported_options &&
|
|
||||||
status.IsNotSupported()) {
|
|
||||||
return Status::OK();
|
|
||||||
} else {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
} else if (!curr_opts.empty() || !opt_map.empty()) {
|
|
||||||
Comparator* comparator = const_cast<Comparator*>(*result);
|
|
||||||
status = ConfigurableHelper::ConfigureNewObject(
|
|
||||||
config_options, comparator, id, curr_opts, opt_map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
} // namespace ROCKSDB_NAMESPACE
|
} // namespace ROCKSDB_NAMESPACE
|
||||||
|
Loading…
Reference in New Issue
Block a user