Add Inner method and support for wrapped Customizable (#8373)
Summary: Inner method added for classes to override to return has-a relationship. CheckedCast expanded to use Inner to return has-a relationship. Future Customizable classes (Env, FileSystem, Statistics, etc) will use this feature Pull Request resolved: https://github.com/facebook/rocksdb/pull/8373 Reviewed By: pdillinger Differential Revision: D29176369 Pulled By: mrambacher fbshipit-source-id: cfb6d7702fa365ca4e40c4a50a19e3a534e5ac43
This commit is contained in:
parent
ecccc63179
commit
d81c2d1e3d
@ -81,6 +81,9 @@ class Customizable : public Configurable {
|
|||||||
// potential names (e.g. "PosixEnv", "DefaultEnv") may also wish to override
|
// potential names (e.g. "PosixEnv", "DefaultEnv") may also wish to override
|
||||||
// this method.
|
// this method.
|
||||||
//
|
//
|
||||||
|
// Note that IsInstanceOf only uses the "is-a" relationship and not "has-a".
|
||||||
|
// Wrapped classes that have an Inner "has-a" should not be returned.
|
||||||
|
//
|
||||||
// @param name The name of the instance to find.
|
// @param name The name of the instance to find.
|
||||||
// Returns true if the class is an instance of the input name.
|
// Returns true if the class is an instance of the input name.
|
||||||
virtual bool IsInstanceOf(const std::string& name) const {
|
virtual bool IsInstanceOf(const std::string& name) const {
|
||||||
@ -88,14 +91,19 @@ class Customizable : public Configurable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns the named instance of the Customizable as a T*, or nullptr if not
|
// Returns the named instance of the Customizable as a T*, or nullptr if not
|
||||||
// found. This method uses IsInstanceOf to find the appropriate class instance
|
// found. This method uses IsInstanceOf/Inner to find the appropriate class
|
||||||
// and then casts it to the expected return type.
|
// instance and then casts it to the expected return type.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const T* CheckedCast() const {
|
const T* CheckedCast() const {
|
||||||
if (IsInstanceOf(T::kClassName())) {
|
if (IsInstanceOf(T::kClassName())) {
|
||||||
return static_cast<const T*>(this);
|
return static_cast<const T*>(this);
|
||||||
} else {
|
} else {
|
||||||
return nullptr;
|
const auto inner = Inner();
|
||||||
|
if (inner != nullptr) {
|
||||||
|
return inner->CheckedCast<T>();
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +112,12 @@ class Customizable : public Configurable {
|
|||||||
if (IsInstanceOf(T::kClassName())) {
|
if (IsInstanceOf(T::kClassName())) {
|
||||||
return static_cast<T*>(this);
|
return static_cast<T*>(this);
|
||||||
} else {
|
} else {
|
||||||
return nullptr;
|
auto inner = const_cast<Customizable*>(Inner());
|
||||||
|
if (inner != nullptr) {
|
||||||
|
return inner->CheckedCast<T>();
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,8 +137,13 @@ class Customizable : public Configurable {
|
|||||||
// @see Configurable::GetOption for more details
|
// @see Configurable::GetOption for more details
|
||||||
Status GetOption(const ConfigOptions& config_options, const std::string& name,
|
Status GetOption(const ConfigOptions& config_options, const std::string& name,
|
||||||
std::string* value) const override;
|
std::string* value) const override;
|
||||||
|
|
||||||
#endif // ROCKSDB_LITE
|
#endif // ROCKSDB_LITE
|
||||||
|
|
||||||
|
// Returns the inner class when a Customizable implements a has-a (wrapped)
|
||||||
|
// relationship. Derived classes that implement a has-a must override this
|
||||||
|
// method in order to get CheckedCast to function properly.
|
||||||
|
virtual const Customizable* Inner() const { return nullptr; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Given a name (e.g. rocksdb.my.type.opt), returns the short name (opt)
|
// Given a name (e.g. rocksdb.my.type.opt), returns the short name (opt)
|
||||||
std::string GetOptionName(const std::string& long_name) const override;
|
std::string GetOptionName(const std::string& long_name) const override;
|
||||||
|
@ -505,6 +505,70 @@ static std::unordered_map<std::string, OptionTypeInfo> inner_option_info = {
|
|||||||
#endif // ROCKSDB_LITE
|
#endif // ROCKSDB_LITE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class InnerCustomizable : public Customizable {
|
||||||
|
public:
|
||||||
|
explicit InnerCustomizable(const std::shared_ptr<Customizable>& w)
|
||||||
|
: inner_(w) {}
|
||||||
|
static const char* kClassName() { return "Inner"; }
|
||||||
|
bool IsInstanceOf(const std::string& name) const override {
|
||||||
|
if (name == kClassName()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return Customizable::IsInstanceOf(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const Customizable* Inner() const override { return inner_.get(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Customizable> inner_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WrappedCustomizable1 : public InnerCustomizable {
|
||||||
|
public:
|
||||||
|
explicit WrappedCustomizable1(const std::shared_ptr<Customizable>& w)
|
||||||
|
: InnerCustomizable(w) {}
|
||||||
|
const char* Name() const override { return kClassName(); }
|
||||||
|
static const char* kClassName() { return "Wrapped1"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class WrappedCustomizable2 : public InnerCustomizable {
|
||||||
|
public:
|
||||||
|
explicit WrappedCustomizable2(const std::shared_ptr<Customizable>& w)
|
||||||
|
: InnerCustomizable(w) {}
|
||||||
|
const char* Name() const override { return kClassName(); }
|
||||||
|
static const char* kClassName() { return "Wrapped2"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(CustomizableTest, WrappedInnerTest) {
|
||||||
|
std::shared_ptr<TestCustomizable> ac =
|
||||||
|
std::make_shared<TestCustomizable>("A");
|
||||||
|
|
||||||
|
ASSERT_TRUE(ac->IsInstanceOf("A"));
|
||||||
|
ASSERT_TRUE(ac->IsInstanceOf("TestCustomizable"));
|
||||||
|
ASSERT_EQ(ac->CheckedCast<TestCustomizable>(), ac.get());
|
||||||
|
ASSERT_EQ(ac->CheckedCast<InnerCustomizable>(), nullptr);
|
||||||
|
ASSERT_EQ(ac->CheckedCast<WrappedCustomizable1>(), nullptr);
|
||||||
|
ASSERT_EQ(ac->CheckedCast<WrappedCustomizable2>(), nullptr);
|
||||||
|
std::shared_ptr<Customizable> wc1 =
|
||||||
|
std::make_shared<WrappedCustomizable1>(ac);
|
||||||
|
|
||||||
|
ASSERT_TRUE(wc1->IsInstanceOf(WrappedCustomizable1::kClassName()));
|
||||||
|
ASSERT_EQ(wc1->CheckedCast<WrappedCustomizable1>(), wc1.get());
|
||||||
|
ASSERT_EQ(wc1->CheckedCast<WrappedCustomizable2>(), nullptr);
|
||||||
|
ASSERT_EQ(wc1->CheckedCast<InnerCustomizable>(), wc1.get());
|
||||||
|
ASSERT_EQ(wc1->CheckedCast<TestCustomizable>(), ac.get());
|
||||||
|
|
||||||
|
std::shared_ptr<Customizable> wc2 =
|
||||||
|
std::make_shared<WrappedCustomizable2>(wc1);
|
||||||
|
ASSERT_TRUE(wc2->IsInstanceOf(WrappedCustomizable2::kClassName()));
|
||||||
|
ASSERT_EQ(wc2->CheckedCast<WrappedCustomizable2>(), wc2.get());
|
||||||
|
ASSERT_EQ(wc2->CheckedCast<WrappedCustomizable1>(), wc1.get());
|
||||||
|
ASSERT_EQ(wc2->CheckedCast<InnerCustomizable>(), wc2.get());
|
||||||
|
ASSERT_EQ(wc2->CheckedCast<TestCustomizable>(), ac.get());
|
||||||
|
}
|
||||||
|
|
||||||
class ShallowCustomizable : public Customizable {
|
class ShallowCustomizable : public Customizable {
|
||||||
public:
|
public:
|
||||||
ShallowCustomizable() {
|
ShallowCustomizable() {
|
||||||
|
Loading…
Reference in New Issue
Block a user