Add customizable_util.h to the public API (#8301)
Summary: Useful for allowing new classes to create and manage Customizable objects without using internal APIs. Pull Request resolved: https://github.com/facebook/rocksdb/pull/8301 Reviewed By: zhichao-cao Differential Revision: D29428303 Pulled By: mrambacher fbshipit-source-id: 3d33d5197cc8379fe35b54d3d169f91f0dfe7a47main
parent
bac399449d
commit
89f66d4484
@ -0,0 +1,293 @@ |
||||
// 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).
|
||||
|
||||
#pragma once |
||||
#include <functional> |
||||
#include <memory> |
||||
#include <unordered_map> |
||||
|
||||
#include "options/configurable_helper.h" |
||||
#include "rocksdb/convenience.h" |
||||
#include "rocksdb/customizable.h" |
||||
#include "rocksdb/status.h" |
||||
#include "rocksdb/utilities/object_registry.h" |
||||
|
||||
namespace ROCKSDB_NAMESPACE { |
||||
// The FactoryFunc functions are used to create a new customizable object
|
||||
// without going through the ObjectRegistry. This methodology is especially
|
||||
// useful in LITE mode, where there is no ObjectRegistry. The methods take
|
||||
// in an ID of the object to create and a pointer to store the created object.
|
||||
// If the factory successfully recognized the input ID, the method should return
|
||||
// success; otherwise false should be returned. On success, the object
|
||||
// parameter contains the new object.
|
||||
template <typename T> |
||||
using SharedFactoryFunc = |
||||
std::function<bool(const std::string&, std::shared_ptr<T>*)>; |
||||
|
||||
template <typename T> |
||||
using UniqueFactoryFunc = |
||||
std::function<bool(const std::string&, std::unique_ptr<T>*)>; |
||||
|
||||
template <typename T> |
||||
using StaticFactoryFunc = std::function<bool(const std::string&, T**)>; |
||||
|
||||
// Creates a new shared customizable instance object based on the
|
||||
// input parameters using the object registry.
|
||||
//
|
||||
// The id parameter specifies the instance class of the object to create.
|
||||
// The opt_map parameter specifies the configuration of the new instance.
|
||||
//
|
||||
// The config_options parameter controls the process and how errors are
|
||||
// returned. If ignore_unknown_options=true, unknown values are ignored during
|
||||
// the configuration. If ignore_unsupported_options=true, unknown instance types
|
||||
// are ignored. If invoke_prepare_options=true, the resulting instance will be
|
||||
// initialized (via PrepareOptions)
|
||||
//
|
||||
// @param config_options Controls how the instance is created and errors are
|
||||
// handled
|
||||
// @param id The identifier of the new object being created. This string
|
||||
// will be used by the object registry to locate the appropriate object to
|
||||
// create.
|
||||
// @param opt_map Optional name-value pairs of properties to set for the newly
|
||||
// created object
|
||||
// @param result The newly created and configured instance.
|
||||
template <typename T> |
||||
static Status NewSharedObject( |
||||
const ConfigOptions& config_options, const std::string& id, |
||||
const std::unordered_map<std::string, std::string>& opt_map, |
||||
std::shared_ptr<T>* result) { |
||||
Status status; |
||||
if (!id.empty()) { |
||||
#ifndef ROCKSDB_LITE |
||||
status = config_options.registry->NewSharedObject(id, result); |
||||
#else |
||||
status = Status::NotSupported("Cannot load object in LITE mode ", id); |
||||
#endif // ROCKSDB_LITE
|
||||
if (config_options.ignore_unsupported_options && status.IsNotSupported()) { |
||||
return Status::OK(); |
||||
} |
||||
} else { |
||||
status = Status::NotSupported("Cannot reset object "); |
||||
} |
||||
if (!status.ok() || opt_map.empty()) { |
||||
return status; |
||||
} else if (result->get() != nullptr) { |
||||
return result->get()->ConfigureFromMap(config_options, opt_map); |
||||
} else { |
||||
return Status::InvalidArgument("Cannot configure null object ", id); |
||||
} |
||||
} |
||||
|
||||
// Creates a new shared Customizable object based on the input parameters.
|
||||
// This method parses the input value to determine the type of instance to
|
||||
// create. If there is an existing instance (in result) and it is the same ID
|
||||
// as the object being created, the existing configuration is stored and used as
|
||||
// the default for the new object.
|
||||
//
|
||||
// The value parameter specified the instance class of the object to create.
|
||||
// If it is a simple string (e.g. BlockBasedTable), then the instance will be
|
||||
// created using the default settings. If the value is a set of name-value
|
||||
// pairs, then the "id" value is used to determine the instance to create and
|
||||
// the remaining parameters are used to configure the object. Id name-value
|
||||
// pairs are specified, there should be an "id=value" pairing or an error may
|
||||
// result.
|
||||
//
|
||||
// The config_options parameter controls the process and how errors are
|
||||
// returned. If ignore_unknown_options=true, unknown values are ignored during
|
||||
// the configuration. If ignore_unsupported_options=true, unknown instance types
|
||||
// are ignored. If invoke_prepare_options=true, the resulting instance will be
|
||||
// initialized (via PrepareOptions)
|
||||
//
|
||||
// @param config_options Controls how the instance is created and errors are
|
||||
// handled
|
||||
// @param value Either the simple name of the instance to create, or a set of
|
||||
// name-value pairs to create and initailize the object
|
||||
// @param func Optional function to call to attempt to create an instance
|
||||
// @param result The newly created instance.
|
||||
template <typename T> |
||||
static Status LoadSharedObject(const ConfigOptions& config_options, |
||||
const std::string& value, |
||||
const SharedFactoryFunc<T>& func, |
||||
std::shared_ptr<T>* result) { |
||||
std::string id; |
||||
std::unordered_map<std::string, std::string> opt_map; |
||||
|
||||
Status status = Customizable::GetOptionsMap(config_options, result->get(), |
||||
value, &id, &opt_map); |
||||
if (!status.ok()) { // GetOptionsMap failed
|
||||
return status; |
||||
} else if (func == nullptr || |
||||
!func(id, result)) { // No factory, or it failed
|
||||
if (value.empty()) { // No Id and no options. Clear the object
|
||||
*result = nullptr; |
||||
return Status::OK(); |
||||
} else { |
||||
return NewSharedObject(config_options, id, opt_map, result); |
||||
} |
||||
} else if (opt_map.empty()) { |
||||
return status; |
||||
} else if (result->get() != nullptr) { |
||||
return result->get()->ConfigureFromMap(config_options, opt_map); |
||||
} else { |
||||
return Status::InvalidArgument("Cannot configure null object "); |
||||
} |
||||
} |
||||
|
||||
// Creates a new unique pointer customizable instance object based on the
|
||||
// input parameters using the object registry.
|
||||
// @see NewSharedObject for more information on the inner workings of this
|
||||
// method.
|
||||
//
|
||||
// @param config_options Controls how the instance is created and errors are
|
||||
// handled
|
||||
// @param id The identifier of the new object being created. This string
|
||||
// will be used by the object registry to locate the appropriate object to
|
||||
// create.
|
||||
// @param opt_map Optional name-value pairs of properties to set for the newly
|
||||
// created object
|
||||
// @param result The newly created and configured instance.
|
||||
template <typename T> |
||||
static Status NewUniqueObject( |
||||
const ConfigOptions& config_options, const std::string& id, |
||||
const std::unordered_map<std::string, std::string>& opt_map, |
||||
std::unique_ptr<T>* result) { |
||||
Status status; |
||||
if (id.empty()) { |
||||
status = Status::NotSupported("Cannot reset object "); |
||||
} else { |
||||
#ifndef ROCKSDB_LITE |
||||
status = config_options.registry->NewUniqueObject(id, result); |
||||
#else |
||||
status = Status::NotSupported("Cannot load object in LITE mode ", id); |
||||
#endif // ROCKSDB_LITE
|
||||
if (config_options.ignore_unsupported_options && status.IsNotSupported()) { |
||||
return Status::OK(); |
||||
} |
||||
} |
||||
if (!status.ok() || opt_map.empty()) { |
||||
return status; |
||||
} else if (result->get() != nullptr) { |
||||
return result->get()->ConfigureFromMap(config_options, opt_map); |
||||
} else { |
||||
return Status::InvalidArgument("Cannot configure null object "); |
||||
} |
||||
} |
||||
|
||||
// Creates a new unique customizable instance object based on the input
|
||||
// parameters.
|
||||
// @see LoadSharedObject for more information on the inner workings of this
|
||||
// method.
|
||||
//
|
||||
// @param config_options Controls how the instance is created and errors are
|
||||
// handled
|
||||
// @param value Either the simple name of the instance to create, or a set of
|
||||
// name-value pairs to create and initailize the object
|
||||
// @param func Optional function to call to attempt to create an instance
|
||||
// @param result The newly created instance.
|
||||
template <typename T> |
||||
static Status LoadUniqueObject(const ConfigOptions& config_options, |
||||
const std::string& value, |
||||
const UniqueFactoryFunc<T>& func, |
||||
std::unique_ptr<T>* result) { |
||||
std::string id; |
||||
std::unordered_map<std::string, std::string> opt_map; |
||||
Status status = Customizable::GetOptionsMap(config_options, result->get(), |
||||
value, &id, &opt_map); |
||||
if (!status.ok()) { // GetOptionsMap failed
|
||||
return status; |
||||
} else if (func == nullptr || |
||||
!func(id, result)) { // No factory, or it failed
|
||||
if (value.empty()) { // No Id and no options. Clear the object
|
||||
*result = nullptr; |
||||
return Status::OK(); |
||||
} else { |
||||
return NewUniqueObject(config_options, id, opt_map, result); |
||||
} |
||||
} else if (opt_map.empty()) { |
||||
return status; |
||||
} else if (result->get() != nullptr) { |
||||
return result->get()->ConfigureFromMap(config_options, opt_map); |
||||
} else { |
||||
return Status::InvalidArgument("Cannot configure null object "); |
||||
} |
||||
} |
||||
|
||||
// Creates a new static (raw pointer) customizable instance object based on the
|
||||
// input parameters using the object registry.
|
||||
// @see NewSharedObject for more information on the inner workings of this
|
||||
// method.
|
||||
//
|
||||
// @param config_options Controls how the instance is created and errors are
|
||||
// handled
|
||||
// @param id The identifier of the new object being created. This string
|
||||
// will be used by the object registry to locate the appropriate object to
|
||||
// create.
|
||||
// @param opt_map Optional name-value pairs of properties to set for the newly
|
||||
// created object
|
||||
// @param result The newly created and configured instance.
|
||||
template <typename T> |
||||
static Status NewStaticObject( |
||||
const ConfigOptions& config_options, const std::string& id, |
||||
const std::unordered_map<std::string, std::string>& opt_map, T** result) { |
||||
Status status; |
||||
if (id.empty()) { |
||||
status = Status::NotSupported("Cannot reset object "); |
||||
} 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 (config_options.ignore_unsupported_options && status.IsNotSupported()) { |
||||
return Status::OK(); |
||||
} |
||||
} |
||||
if (!status.ok() || opt_map.empty()) { |
||||
return status; |
||||
} else if (*result != nullptr) { |
||||
return (*result)->ConfigureFromMap(config_options, opt_map); |
||||
} else { |
||||
return Status::InvalidArgument("Cannot configure null object "); |
||||
} |
||||
} |
||||
|
||||
// Creates a new static (raw pointer) customizable instance object based on the
|
||||
// input parameters.
|
||||
// @see LoadSharedObject for more information on the inner workings of this
|
||||
// method.
|
||||
//
|
||||
// @param config_options Controls how the instance is created and errors are
|
||||
// handled
|
||||
// @param value Either the simple name of the instance to create, or a set of
|
||||
// name-value pairs to create and initailize the object
|
||||
// @param func Optional function to call to attempt to create an instance
|
||||
// @param result The newly created instance.
|
||||
template <typename T> |
||||
static Status LoadStaticObject(const ConfigOptions& config_options, |
||||
const std::string& value, |
||||
const StaticFactoryFunc<T>& func, T** result) { |
||||
std::string id; |
||||
std::unordered_map<std::string, std::string> opt_map; |
||||
Status status = Customizable::GetOptionsMap(config_options, *result, value, |
||||
&id, &opt_map); |
||||
if (!status.ok()) { // GetOptionsMap failed
|
||||
return status; |
||||
} else if (func == nullptr || |
||||
!func(id, result)) { // No factory, or it failed
|
||||
if (value.empty()) { // No Id and no options. Clear the object
|
||||
*result = nullptr; |
||||
return Status::OK(); |
||||
} else { |
||||
return NewStaticObject(config_options, id, opt_map, result); |
||||
} |
||||
} else if (opt_map.empty()) { |
||||
return status; |
||||
} else if (*result != nullptr) { |
||||
return (*result)->ConfigureFromMap(config_options, opt_map); |
||||
} else { |
||||
return Status::InvalidArgument("Cannot configure null object "); |
||||
} |
||||
} |
||||
} // namespace ROCKSDB_NAMESPACE
|
@ -1,221 +0,0 @@ |
||||
// 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).
|
||||
|
||||
#pragma once |
||||
#include <functional> |
||||
#include <memory> |
||||
#include <unordered_map> |
||||
|
||||
#include "options/configurable_helper.h" |
||||
#include "rocksdb/convenience.h" |
||||
#include "rocksdb/customizable.h" |
||||
#include "rocksdb/status.h" |
||||
#include "rocksdb/utilities/object_registry.h" |
||||
|
||||
namespace ROCKSDB_NAMESPACE { |
||||
template <typename T> |
||||
using SharedFactoryFunc = |
||||
std::function<bool(const std::string&, std::shared_ptr<T>*)>; |
||||
|
||||
template <typename T> |
||||
using UniqueFactoryFunc = |
||||
std::function<bool(const std::string&, std::unique_ptr<T>*)>; |
||||
|
||||
template <typename T> |
||||
using StaticFactoryFunc = std::function<bool(const std::string&, T**)>; |
||||
|
||||
// Creates a new shared Customizable object based on the input parameters.
|
||||
// This method parses the input value to determine the type of instance to
|
||||
// create. If there is an existing instance (in result) and it is the same type
|
||||
// as the object being created, the existing configuration is stored and used as
|
||||
// the default for the new object.
|
||||
//
|
||||
// The value parameter specified the instance class of the object to create.
|
||||
// If it is a simple string (e.g. BlockBasedTable), then the instance will be
|
||||
// created using the default settings. If the value is a set of name-value
|
||||
// pairs, then the "id" value is used to determine the instance to create and
|
||||
// the remaining parameters are used to configure the object. Id name-value
|
||||
// pairs are specified, there must be an "id=value" pairing or an error will
|
||||
// result.
|
||||
//
|
||||
// The config_options parameter controls the process and how errors are
|
||||
// returned. If ignore_unknown_options=true, unknown values are ignored during
|
||||
// the configuration If ignore_unsupported_options=true, unknown instance types
|
||||
// are ignored If invoke_prepare_options=true, the resulting instance wll be
|
||||
// initialized (via PrepareOptions
|
||||
//
|
||||
// @param config_options Controls how the instance is created and errors are
|
||||
// handled
|
||||
// @param value Either the simple name of the instance to create, or a set of
|
||||
// name-value pairs to
|
||||
// create and initailzie the object
|
||||
// @param func Optional function to call to attempt to create an instance
|
||||
// @param result The newly created instance.
|
||||
template <typename T> |
||||
static Status LoadSharedObject(const ConfigOptions& config_options, |
||||
const std::string& value, |
||||
const SharedFactoryFunc<T>& func, |
||||
std::shared_ptr<T>* result) { |
||||
std::string id; |
||||
std::unordered_map<std::string, std::string> opt_map; |
||||
Status status = |
||||
ConfigurableHelper::GetOptionsMap(value, result->get(), &id, &opt_map); |
||||
if (!status.ok()) { // GetOptionsMap failed
|
||||
return status; |
||||
} |
||||
std::string curr_opts; |
||||
#ifndef ROCKSDB_LITE |
||||
if (result->get() != nullptr && result->get()->GetId() == id) { |
||||
// Try to get the existing options, ignoring any errors
|
||||
ConfigOptions embedded = config_options; |
||||
embedded.delimiter = ";"; |
||||
result->get()->GetOptionString(embedded, &curr_opts).PermitUncheckedError(); |
||||
} |
||||
#endif |
||||
if (func == nullptr || !func(id, result)) { // No factory, or it failed
|
||||
if (value.empty()) { |
||||
// No Id and no options. Clear the object
|
||||
result->reset(); |
||||
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->NewSharedObject(id, result); |
||||
#else |
||||
status = Status::NotSupported("Cannot load object in LITE mode ", id); |
||||
#endif |
||||
if (!status.ok()) { |
||||
if (config_options.ignore_unsupported_options && |
||||
status.IsNotSupported()) { |
||||
return Status::OK(); |
||||
} else { |
||||
return status; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return ConfigurableHelper::ConfigureNewObject(config_options, result->get(), |
||||
id, curr_opts, opt_map); |
||||
} |
||||
|
||||
// Creates a new unique customizable instance object based on the input
|
||||
// parameters.
|
||||
// @see LoadSharedObject for more information on the inner workings of this
|
||||
// method.
|
||||
//
|
||||
// @param config_options Controls how the instance is created and errors are
|
||||
// handled
|
||||
// @param value Either the simple name of the instance to create, or a set of
|
||||
// name-value pairs to
|
||||
// create and initailzie the object
|
||||
// @param func Optional function to call to attempt to create an instance
|
||||
// @param result The newly created instance.
|
||||
template <typename T> |
||||
static Status LoadUniqueObject(const ConfigOptions& config_options, |
||||
const std::string& value, |
||||
const UniqueFactoryFunc<T>& func, |
||||
std::unique_ptr<T>* result) { |
||||
std::string id; |
||||
std::unordered_map<std::string, std::string> opt_map; |
||||
Status status = |
||||
ConfigurableHelper::GetOptionsMap(value, result->get(), &id, &opt_map); |
||||
if (!status.ok()) { // GetOptionsMap failed
|
||||
return status; |
||||
} |
||||
std::string curr_opts; |
||||
#ifndef ROCKSDB_LITE |
||||
if (result->get() != nullptr && result->get()->GetId() == id) { |
||||
// Try to get the existing options, ignoring any errors
|
||||
ConfigOptions embedded = config_options; |
||||
embedded.delimiter = ";"; |
||||
result->get()->GetOptionString(embedded, &curr_opts).PermitUncheckedError(); |
||||
} |
||||
#endif |
||||
if (func == nullptr || !func(id, result)) { // No factory, or it failed
|
||||
if (value.empty()) { |
||||
// No Id and no options. Clear the object
|
||||
result->reset(); |
||||
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->NewUniqueObject(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; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return ConfigurableHelper::ConfigureNewObject(config_options, result->get(), |
||||
id, curr_opts, opt_map); |
||||
} |
||||
// Creates a new static (raw pointer) customizable instance object based on the
|
||||
// input parameters.
|
||||
// @see LoadSharedObject for more information on the inner workings of this
|
||||
// method.
|
||||
//
|
||||
// @param config_options Controls how the instance is created and errors are
|
||||
// handled
|
||||
// @param value Either the simple name of the instance to create, or a set of
|
||||
// name-value pairs to
|
||||
// create and initailzie the object
|
||||
// @param func Optional function to call to attempt to create an instance
|
||||
// @param result The newly created instance.
|
||||
template <typename T> |
||||
static Status LoadStaticObject(const ConfigOptions& config_options, |
||||
const std::string& value, |
||||
const StaticFactoryFunc<T>& func, T** result) { |
||||
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 (func == nullptr || !func(id, result)) { // No factory, or it failed
|
||||
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; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return ConfigurableHelper::ConfigureNewObject(config_options, *result, id, |
||||
curr_opts, opt_map); |
||||
} |
||||
} // namespace ROCKSDB_NAMESPACE
|
Loading…
Reference in new issue