提交 204a42ca 编写于 作者: M mrambacher 提交者: Facebook GitHub Bot

Added GetFactoryCount/Names/Types to ObjectRegistry (#9358)

Summary:
These methods allow for more thorough testing of the ObjectRegistry and Customizable infrastructure in a simpler manner.  With this change, the Customizable tests can now check what factories are registered and attempt to create each of them in a systematic fashion.

With this change, I think all of the factories registered with the ObjectRegistry/CreateFromString are now tested via the customizable_test classes.

Note that there were a few other minor changes.  There was a "posix://*" register with the ObjectRegistry which was missed during the PatternEntry conversion -- these changes found that.  The nickname and default names for the FileSystem classes was also inverted.

Pull Request resolved: https://github.com/facebook/rocksdb/pull/9358

Reviewed By: pdillinger

Differential Revision: D33433542

Pulled By: mrambacher

fbshipit-source-id: 9a32da74e6620745b4eeffb2712be70eeeadfa7e
上级 c4cd8e1a
......@@ -1139,6 +1139,15 @@ CTREncryptionProvider::CTREncryptionProvider(
RegisterOptions("Cipher", &cipher_, &ctr_encryption_provider_type_info);
}
bool CTREncryptionProvider::IsInstanceOf(const std::string& name) const {
// Special case for test purposes.
if (name == "1://test" && cipher_ != nullptr) {
return cipher_->IsInstanceOf(ROT13BlockCipher::kClassName());
} else {
return EncryptionProvider::IsInstanceOf(name);
}
}
// GetPrefixLength returns the length of the prefix that is added to every file
// and used for storing encryption options.
// For optimal performance, the prefix length should be a multiple of
......
......@@ -66,7 +66,7 @@ class CTREncryptionProvider : public EncryptionProvider {
static const char* kClassName() { return "CTR"; }
const char* Name() const override { return kClassName(); }
bool IsInstanceOf(const std::string& name) const override;
// GetPrefixLength returns the length of the prefix that is added to every
// file
// and used for storing encryption options.
......
......@@ -130,8 +130,8 @@ class PosixDynamicLibrary : public DynamicLibrary {
class PosixClock : public SystemClock {
public:
static const char* kClassName() { return "PosixClock"; }
const char* Name() const override { return kClassName(); }
const char* NickName() const override { return kDefaultName(); }
const char* Name() const override { return kDefaultName(); }
const char* NickName() const override { return kClassName(); }
uint64_t NowMicros() override {
struct timeval tv;
......
......@@ -146,6 +146,13 @@ class PosixFileSystem : public FileSystem {
const char* NickName() const override { return kDefaultName(); }
~PosixFileSystem() override {}
bool IsInstanceOf(const std::string& name) const override {
if (name == "posix") {
return true;
} else {
return FileSystem::IsInstanceOf(name);
}
}
void SetFD_CLOEXEC(int fd, const EnvOptions* options) {
if ((options == nullptr || options->set_fd_cloexec) && fd > 0) {
......
......@@ -300,6 +300,9 @@ class MemTableRepFactory : public Customizable {
static Status CreateFromString(const ConfigOptions& config_options,
const std::string& id,
std::unique_ptr<MemTableRepFactory>* factory);
static Status CreateFromString(const ConfigOptions& config_options,
const std::string& id,
std::shared_ptr<MemTableRepFactory>* factory);
virtual MemTableRep* CreateMemTableRep(const MemTableRep::KeyComparator&,
Allocator*, const SliceTransform*,
......
......@@ -13,6 +13,7 @@
#include <mutex>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "rocksdb/status.h"
......@@ -217,6 +218,18 @@ class ObjectLibrary {
// @param num_types returns how many unique types are registered.
size_t GetFactoryCount(size_t* num_types) const;
// Returns the number of factories registered for this library
// for the input type.
// @param num_types returns how many unique types are registered.
size_t GetFactoryCount(const std::string& type) const;
// Returns the registered factory names for the input type
// names is updated to include the names for the type
void GetFactoryNames(const std::string& type,
std::vector<std::string>* names) const;
void GetFactoryTypes(std::unordered_set<std::string>* types) const;
void Dump(Logger* logger) const;
// Registers the factory with the library for the name.
......@@ -497,6 +510,18 @@ class ObjectRegistry {
}
}
// Returns the number of factories registered for this library
// for the input type.
// @param num_types returns how many unique types are registered.
size_t GetFactoryCount(const std::string& type) const;
// Returns the names of registered factories for the input type.
// names is updated to include the names for the type
void GetFactoryNames(const std::string& type,
std::vector<std::string>* names) const;
void GetFactoryTypes(std::unordered_set<std::string>* types) const;
// Dump the contents of the registry to the logger
void Dump(Logger* logger) const;
......
......@@ -596,10 +596,7 @@ static std::unordered_map<std::string, OptionTypeInfo>
auto* shared =
static_cast<std::shared_ptr<MemTableRepFactory>*>(addr);
Status s =
MemTableRepFactory::CreateFromString(opts, value, &factory);
if (factory && s.ok()) {
shared->reset(factory.release());
}
MemTableRepFactory::CreateFromString(opts, value, shared);
return s;
}}},
{"memtable",
......@@ -612,10 +609,7 @@ static std::unordered_map<std::string, OptionTypeInfo>
auto* shared =
static_cast<std::shared_ptr<MemTableRepFactory>*>(addr);
Status s =
MemTableRepFactory::CreateFromString(opts, value, &factory);
if (factory && s.ok()) {
shared->reset(factory.release());
}
MemTableRepFactory::CreateFromString(opts, value, shared);
return s;
}}},
{"table_factory",
......
此差异已折叠。
......@@ -80,8 +80,8 @@ class WinClock : public SystemClock {
virtual ~WinClock() {}
static const char* kClassName() { return "WindowsClock"; }
const char* Name() const override { return kClassName(); }
const char* NickName() const override { return kDefaultName(); }
const char* Name() const override { return kDefaultName(); }
const char* NickName() const override { return kClassName(); }
uint64_t NowMicros() override;
......
......@@ -275,7 +275,7 @@ Status MemTableRepFactory::CreateFromString(
if (opts_list.empty() || opts_list.size() > 2 || !opt_map.empty()) {
status = Status::InvalidArgument("Can't parse memtable_factory option ",
value);
} else if (opts_list[0] == "skip_list" ||
} else if (opts_list[0] == SkipListFactory::kNickName() ||
opts_list[0] == SkipListFactory::kClassName()) {
// Expecting format
// skip_list:<lookahead>
......@@ -293,6 +293,17 @@ Status MemTableRepFactory::CreateFromString(
return status;
}
Status MemTableRepFactory::CreateFromString(
const ConfigOptions& config_options, const std::string& value,
std::shared_ptr<MemTableRepFactory>* result) {
std::unique_ptr<MemTableRepFactory> factory;
Status s = CreateFromString(config_options, value, &factory);
if (factory && s.ok()) {
result->reset(factory.release());
}
return s;
}
#ifndef ROCKSDB_LITE
Status GetPlainTableOptionsFromMap(
const PlainTableOptions& table_options,
......
......@@ -714,7 +714,9 @@ class ChanglingMergeOperator : public MergeOperator {
return false;
}
static const char* kClassName() { return "ChanglingMergeOperator"; }
virtual bool IsInstanceOf(const std::string& id) const override {
const char* NickName() const override { return kNickName(); }
static const char* kNickName() { return "Changling"; }
bool IsInstanceOf(const std::string& id) const override {
if (id == kClassName()) {
return true;
} else {
......@@ -747,7 +749,10 @@ class ChanglingCompactionFilter : public CompactionFilter {
}
static const char* kClassName() { return "ChanglingCompactionFilter"; }
virtual bool IsInstanceOf(const std::string& id) const override {
const char* NickName() const override { return kNickName(); }
static const char* kNickName() { return "Changling"; }
bool IsInstanceOf(const std::string& id) const override {
if (id == kClassName()) {
return true;
} else {
......@@ -781,7 +786,10 @@ class ChanglingCompactionFilterFactory : public CompactionFilterFactory {
// Returns a name that identifies this compaction filter factory.
const char* Name() const override { return name_.c_str(); }
static const char* kClassName() { return "ChanglingCompactionFilterFactory"; }
virtual bool IsInstanceOf(const std::string& id) const override {
const char* NickName() const override { return kNickName(); }
static const char* kNickName() { return "Changling"; }
bool IsInstanceOf(const std::string& id) const override {
if (id == kClassName()) {
return true;
} else {
......
......@@ -157,6 +157,37 @@ size_t ObjectLibrary::GetFactoryCount(size_t *types) const {
return factories;
}
size_t ObjectLibrary::GetFactoryCount(const std::string &type) const {
std::unique_lock<std::mutex> lock(mu_);
auto iter = factories_.find(type);
if (iter != factories_.end()) {
return iter->second.size();
} else {
return 0;
}
}
void ObjectLibrary::GetFactoryNames(const std::string &type,
std::vector<std::string> *names) const {
assert(names);
std::unique_lock<std::mutex> lock(mu_);
auto iter = factories_.find(type);
if (iter != factories_.end()) {
for (const auto &f : iter->second) {
names->push_back(f->Name());
}
}
}
void ObjectLibrary::GetFactoryTypes(
std::unordered_set<std::string> *types) const {
assert(types);
std::unique_lock<std::mutex> lock(mu_);
for (const auto &iter : factories_) {
types->insert(iter.first);
}
}
void ObjectLibrary::Dump(Logger *logger) const {
std::unique_lock<std::mutex> lock(mu_);
if (logger != nullptr && !factories_.empty()) {
......@@ -276,6 +307,46 @@ Status ObjectRegistry::ListManagedObjects(
}
}
// Returns the number of registered types for this registry.
// If specified (not-null), types is updated to include the names of the
// registered types.
size_t ObjectRegistry::GetFactoryCount(const std::string &type) const {
size_t count = 0;
if (parent_ != nullptr) {
count = parent_->GetFactoryCount(type);
}
std::unique_lock<std::mutex> lock(library_mutex_);
for (const auto &library : libraries_) {
count += library->GetFactoryCount(type);
}
return count;
}
void ObjectRegistry::GetFactoryNames(const std::string &type,
std::vector<std::string> *names) const {
assert(names);
names->clear();
if (parent_ != nullptr) {
parent_->GetFactoryNames(type, names);
}
std::unique_lock<std::mutex> lock(library_mutex_);
for (const auto &library : libraries_) {
library->GetFactoryNames(type, names);
}
}
void ObjectRegistry::GetFactoryTypes(
std::unordered_set<std::string> *types) const {
assert(types);
if (parent_ != nullptr) {
parent_->GetFactoryTypes(types);
}
std::unique_lock<std::mutex> lock(library_mutex_);
for (const auto &library : libraries_) {
library->GetFactoryTypes(types);
}
}
void ObjectRegistry::Dump(Logger *logger) const {
if (logger != nullptr) {
std::unique_lock<std::mutex> lock(library_mutex_);
......
......@@ -260,6 +260,77 @@ class MyCustomizable : public Customizable {
std::string name_;
};
TEST_F(ObjRegistryTest, TestFactoryCount) {
std::string msg;
auto grand = ObjectRegistry::Default();
auto local = ObjectRegistry::NewInstance();
std::unordered_set<std::string> grand_types, local_types;
std::vector<std::string> grand_names, local_names;
// Check how many types we have on startup.
// Grand should equal local
grand->GetFactoryTypes(&grand_types);
local->GetFactoryTypes(&local_types);
ASSERT_EQ(grand_types, local_types);
size_t grand_count = grand->GetFactoryCount(Env::Type());
size_t local_count = local->GetFactoryCount(Env::Type());
ASSERT_EQ(grand_count, local_count);
grand->GetFactoryNames(Env::Type(), &grand_names);
local->GetFactoryNames(Env::Type(), &local_names);
ASSERT_EQ(grand_names.size(), grand_count);
ASSERT_EQ(local_names.size(), local_count);
ASSERT_EQ(grand_names, local_names);
// Add an Env to the local registry.
// This will add one factory.
auto library = local->AddLibrary("local");
library->AddFactory<Env>(
"A", [](const std::string& /*uri*/, std::unique_ptr<Env>* /*guard */,
std::string* /* errmsg */) { return nullptr; });
ASSERT_EQ(local_count + 1, local->GetFactoryCount(Env::Type()));
ASSERT_EQ(grand_count, grand->GetFactoryCount(Env::Type()));
local->GetFactoryTypes(&local_types);
local->GetFactoryNames(Env::Type(), &local_names);
ASSERT_EQ(grand_names.size() + 1, local_names.size());
ASSERT_EQ(local_names.size(), local->GetFactoryCount(Env::Type()));
if (grand_count == 0) {
// There were no Env when we started. Should have one more type
// than previously
ASSERT_NE(grand_types, local_types);
ASSERT_EQ(grand_types.size() + 1, local_types.size());
} else {
// There was an Env type when we started. The types should match
ASSERT_EQ(grand_types, local_types);
}
// Add a MyCustomizable to the registry. This should be a new type
library->AddFactory<MyCustomizable>(
"MY", [](const std::string& /*uri*/,
std::unique_ptr<MyCustomizable>* /*guard */,
std::string* /* errmsg */) { return nullptr; });
ASSERT_EQ(local_count + 1, local->GetFactoryCount(Env::Type()));
ASSERT_EQ(grand_count, grand->GetFactoryCount(Env::Type()));
ASSERT_EQ(0U, grand->GetFactoryCount(MyCustomizable::Type()));
ASSERT_EQ(1U, local->GetFactoryCount(MyCustomizable::Type()));
local->GetFactoryNames(MyCustomizable::Type(), &local_names);
ASSERT_EQ(1U, local_names.size());
ASSERT_EQ(local_names[0], "MY");
local->GetFactoryTypes(&local_types);
ASSERT_EQ(grand_count == 0 ? 2 : grand_types.size() + 1, local_types.size());
// Add the same name again. We should now have 2 factories.
library->AddFactory<MyCustomizable>(
"MY", [](const std::string& /*uri*/,
std::unique_ptr<MyCustomizable>* /*guard */,
std::string* /* errmsg */) { return nullptr; });
local->GetFactoryNames(MyCustomizable::Type(), &local_names);
ASSERT_EQ(2U, local_names.size());
}
TEST_F(ObjRegistryTest, TestManagedObjects) {
auto registry = ObjectRegistry::NewInstance();
auto m_a1 = std::make_shared<MyCustomizable>("", "A");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册