|
|
|
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
|
|
|
// This source code is licensed under both the GPLv2 (found in the
|
|
|
|
// COPYING file in the root directory) and Apache 2.0 License
|
|
|
|
// (found in the LICENSE.Apache file in the root directory).
|
|
|
|
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "rocksdb/configurable.h"
|
|
|
|
#include "rocksdb/status.h"
|
|
|
|
|
|
|
|
namespace ROCKSDB_NAMESPACE {
|
|
|
|
/**
|
|
|
|
* Customizable a base class used by the rocksdb that describes a
|
|
|
|
* standard way of configuring and creating objects. Customizable objects
|
|
|
|
* are configurable objects that can be created from an ObjectRegistry.
|
|
|
|
*
|
|
|
|
* Customizable classes are used when there are multiple potential
|
|
|
|
* implementations of a class for use by RocksDB (e.g. Table, Cache,
|
|
|
|
* MergeOperator, etc). The abstract base class is expected to define a method
|
|
|
|
* declaring its type and a factory method for creating one of these, such as:
|
|
|
|
* static const char *Type() { return "Table"; }
|
|
|
|
* static Status CreateFromString(const ConfigOptions& options,
|
|
|
|
* const std::string& id,
|
|
|
|
* std::shared_ptr<TableFactory>* result);
|
|
|
|
* The "Type" string is expected to be unique (no two base classes are the same
|
|
|
|
* type). This factory is expected, based on the options and id, create and
|
|
|
|
* return the appropriate derived type of the customizable class (e.g.
|
|
|
|
* BlockBasedTableFactory, PlainTableFactory, etc). For extension developers,
|
|
|
|
* helper classes and methods are provided for writing this factory.
|
|
|
|
*
|
|
|
|
* Instances of a Customizable class need to define:
|
|
|
|
* - A "static const char *kClassName()" method. This method defines the name
|
|
|
|
* of the class instance (e.g. BlockBasedTable, LRUCache) and is used by the
|
|
|
|
* CheckedCast method.
|
|
|
|
* - The Name() of the object. This name is used when creating and saving
|
|
|
|
* instances of this class. Typically this name will be the same as
|
|
|
|
* kClassName().
|
|
|
|
*
|
|
|
|
* Additionally, Customizable classes should register any options used to
|
|
|
|
* configure themselves with the Configurable subsystem.
|
|
|
|
*
|
|
|
|
* When a Customizable is being created, the "name" property specifies
|
|
|
|
* the name of the instance being created.
|
|
|
|
* For custom objects, their configuration and name can be specified by:
|
|
|
|
* [prop]={name=X;option 1 = value1[; option2=value2...]}
|
|
|
|
*
|
|
|
|
* [prop].name=X
|
|
|
|
* [prop].option1 = value1
|
|
|
|
*
|
|
|
|
* [prop].name=X
|
|
|
|
* X.option1 =value1
|
|
|
|
*/
|
|
|
|
class Customizable : public Configurable {
|
|
|
|
public:
|
|
|
|
~Customizable() override {}
|
|
|
|
|
|
|
|
// Returns the name of this class of Customizable
|
|
|
|
virtual const char* Name() const = 0;
|
|
|
|
|
|
|
|
// Returns an identifier for this Customizable.
|
|
|
|
// This could be its name or something more complex (like its URL/pattern).
|
|
|
|
// Used for pretty printing.
|
|
|
|
virtual std::string GetId() const {
|
|
|
|
std::string id = Name();
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is typically determined by if the input name matches the
|
|
|
|
// name of this object.
|
|
|
|
// This method is typically used in conjunction with CheckedCast to find the
|
|
|
|
// derived class instance from its base. For example, if you have an Env
|
|
|
|
// and want the "Default" env, you would IsInstanceOf("Default") to get
|
|
|
|
// the default implementation. This method should be used when you need a
|
|
|
|
// specific derivative or implementation of a class.
|
|
|
|
//
|
|
|
|
// Intermediary caches (such as SharedCache) may wish to override this method
|
|
|
|
// to check for the intermediary name (SharedCache). Classes with multiple
|
|
|
|
// potential names (e.g. "PosixEnv", "DefaultEnv") may also wish to override
|
|
|
|
// 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.
|
|
|
|
// Returns true if the class is an instance of the input name.
|
|
|
|
virtual bool IsInstanceOf(const std::string& name) const {
|
|
|
|
if (name.empty()) {
|
|
|
|
return false;
|
|
|
|
} else if (name == Name()) {
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
const char* nickname = NickName();
|
|
|
|
if (nickname != nullptr && name == nickname) {
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const void* GetOptionsPtr(const std::string& name) const override {
|
|
|
|
const void* ptr = Configurable::GetOptionsPtr(name);
|
|
|
|
if (ptr != nullptr) {
|
|
|
|
return ptr;
|
|
|
|
} else {
|
|
|
|
const auto inner = Inner();
|
|
|
|
if (inner != nullptr) {
|
|
|
|
return inner->GetOptionsPtr(name);
|
|
|
|
} else {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the named instance of the Customizable as a T*, or nullptr if not
|
|
|
|
// found. This method uses IsInstanceOf/Inner to find the appropriate class
|
|
|
|
// instance and then casts it to the expected return type.
|
|
|
|
template <typename T>
|
|
|
|
const T* CheckedCast() const {
|
|
|
|
if (IsInstanceOf(T::kClassName())) {
|
|
|
|
return static_cast<const T*>(this);
|
|
|
|
} else {
|
|
|
|
const auto inner = Inner();
|
|
|
|
if (inner != nullptr) {
|
|
|
|
return inner->CheckedCast<T>();
|
|
|
|
} else {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
T* CheckedCast() {
|
|
|
|
if (IsInstanceOf(T::kClassName())) {
|
|
|
|
return static_cast<T*>(this);
|
|
|
|
} else {
|
|
|
|
auto inner = const_cast<Customizable*>(Inner());
|
|
|
|
if (inner != nullptr) {
|
|
|
|
return inner->CheckedCast<T>();
|
|
|
|
} else {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Checks to see if this Customizable is equivalent to other.
|
|
|
|
// This method assumes that the two objects are of the same class.
|
|
|
|
// @param config_options Controls how the options are compared.
|
|
|
|
// @param other The other object to compare to.
|
|
|
|
// @param mismatch If the objects do not match, this parameter contains
|
|
|
|
// the name of the option that triggered the match failure.
|
|
|
|
// @param True if the objects match, false otherwise.
|
|
|
|
// @see Configurable::AreEquivalent for more details
|
|
|
|
bool AreEquivalent(const ConfigOptions& config_options,
|
|
|
|
const Configurable* other,
|
|
|
|
std::string* mismatch) const override;
|
|
|
|
#ifndef ROCKSDB_LITE
|
|
|
|
// Gets the value of the option associated with the input name
|
|
|
|
// @see Configurable::GetOption for more details
|
|
|
|
Status GetOption(const ConfigOptions& config_options, const std::string& name,
|
|
|
|
std::string* value) const override;
|
|
|
|
#endif // ROCKSDB_LITE
|
|
|
|
// Helper method for getting for parsing the opt_value into the corresponding
|
|
|
|
// options for use in potentially creating a new Customizable object (this
|
|
|
|
// method is primarily a support method for LoadSharedObject et al for new
|
|
|
|
// Customizable objects). The opt_value may be either name-value pairs
|
|
|
|
// separated by ";" (a=b; c=d), or a simple name (a). In order to create a new
|
|
|
|
// Customizable, the ID is determined by:
|
|
|
|
// - If the value is a simple name (e.g. "BlockBasedTable"), the id is this
|
|
|
|
// name;
|
|
|
|
// - Otherwise, if there is a "id=value", the id is set to "value"
|
|
|
|
// - Otherwise, if the input customizable is not null, custom->GetId is used
|
|
|
|
// - Otherwise, an error is returned.
|
|
|
|
//
|
|
|
|
// If the opt_value is name-value pairs, these pairs will be returned in
|
|
|
|
// options (without the id pair). If the ID being returned matches the ID of
|
|
|
|
// the input custom object, then the options from the input object will also
|
|
|
|
// be added to the returned options.
|
|
|
|
//
|
|
|
|
// This method returns non-OK if the ID could not be found, or if the
|
|
|
|
// opt_value could not be parsed into name-value pairs.
|
|
|
|
static Status GetOptionsMap(
|
|
|
|
const ConfigOptions& config_options, const Customizable* custom,
|
|
|
|
const std::string& opt_value, std::string* id,
|
|
|
|
std::unordered_map<std::string, std::string>* options);
|
|
|
|
|
|
|
|
// Helper method to configure a new object with the supplied options.
|
|
|
|
// If the object is not null and invoke_prepare_options=true, the object
|
|
|
|
// will be configured and prepared.
|
|
|
|
// Returns success if the object is properly configured and (optionally)
|
|
|
|
// prepared Returns InvalidArgument if the object is nullptr and there are
|
|
|
|
// options in the map Returns the result of the ConfigureFromMap or
|
|
|
|
// PrepareOptions
|
|
|
|
static Status ConfigureNewObject(
|
|
|
|
const ConfigOptions& config_options, Customizable* object,
|
|
|
|
const std::unordered_map<std::string, std::string>& options);
|
|
|
|
|
|
|
|
// 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:
|
|
|
|
// Generates a ID specific for this instance of the customizable.
|
|
|
|
// The unique ID is of the form <name>:<addr>#pid, where:
|
|
|
|
// - name is the Name() of this object;
|
|
|
|
// - addr is the memory address of this object;
|
|
|
|
// - pid is the process ID of this process ID for this process.
|
|
|
|
// Note that if obj1 and obj2 have the same unique IDs, they must be the
|
|
|
|
// same. However, if an object is deleted and recreated, it may have the
|
|
|
|
// same unique ID as a predecessor
|
|
|
|
//
|
|
|
|
// This method is useful for objects (especially ManagedObjects) that
|
|
|
|
// wish to generate an ID that is specific for this instance and wish to
|
|
|
|
// override the GetId() method.
|
|
|
|
std::string GenerateIndividualId() const;
|
|
|
|
|
|
|
|
// Some classes have both a class name (e.g. PutOperator) and a nickname
|
|
|
|
// (e.g. put). Classes can override this method to return a
|
|
|
|
// nickname. Nicknames can be used by InstanceOf and object creation.
|
|
|
|
virtual const char* NickName() const { return ""; }
|
|
|
|
// Given a name (e.g. rocksdb.my.type.opt), returns the short name (opt)
|
|
|
|
std::string GetOptionName(const std::string& long_name) const override;
|
|
|
|
#ifndef ROCKSDB_LITE
|
|
|
|
std::string SerializeOptions(const ConfigOptions& options,
|
|
|
|
const std::string& prefix) const override;
|
|
|
|
#endif // ROCKSDB_LITE
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace ROCKSDB_NAMESPACE
|