@ -2,6 +2,15 @@
// 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).
//
// The OptionTypeInfo and related classes provide a framework for
// configuring and validating RocksDB classes via the Options framework.
// This file is part of the public API to allow developers who wish to
// write their own extensions and plugins to take use the Options
// framework in their custom implementations.
//
// See https://github.com/facebook/rocksdb/wiki/RocksDB-Configurable-Objects
// for more information on how to develop and use custom extensions
# pragma once
@ -15,6 +24,8 @@
namespace ROCKSDB_NAMESPACE {
class OptionTypeInfo ;
struct ColumnFamilyOptions ;
struct DBOptions ;
// The underlying "class/type" of the option.
// This enum is used to determine how the option should
@ -196,6 +207,16 @@ using EqualsFunc = std::function<bool(
const ConfigOptions & /*opts*/ , const std : : string & /*name*/ ,
const void * /*addr1*/ , const void * /*addr2*/ , std : : string * mismatch ) > ;
// Function for preparing/initializing an option.
using PrepareFunc =
std : : function < Status ( const ConfigOptions & /*opts*/ ,
const std : : string & /*name*/ , void * /*addr*/ ) > ;
// Function for validating an option.
using ValidateFunc = std : : function < Status (
const DBOptions & /*db_opts*/ , const ColumnFamilyOptions & /*cf_opts*/ ,
const std : : string & /*name*/ , const void * /*addr*/ ) > ;
// A struct for storing constant option information such as option name,
// option type, and offset.
class OptionTypeInfo {
@ -259,8 +280,9 @@ class OptionTypeInfo {
static OptionTypeInfo Enum (
int offset , const std : : unordered_map < std : : string , T > * const map ,
OptionTypeFlags flags = OptionTypeFlags : : kNone ) {
return OptionTypeInfo (
offset , OptionType : : kEnum , OptionVerificationType : : kNormal , flags ,
OptionTypeInfo info ( offset , OptionType : : kEnum ,
OptionVerificationType : : kNormal , flags ) ;
info . SetParseFunc (
// Uses the map argument to convert the input string into
// its corresponding enum value. If value is found in the map,
// addr is updated to the corresponding map entry.
@ -275,7 +297,8 @@ class OptionTypeInfo {
} else {
return Status : : InvalidArgument ( " No mapping for enum " , name ) ;
}
} ,
} ) ;
info . SetSerializeFunc (
// Uses the map argument to convert the input enum into
// its corresponding string value. If enum value is found in the map,
// value is updated to the corresponding string value in the map.
@ -291,7 +314,8 @@ class OptionTypeInfo {
} else {
return Status : : InvalidArgument ( " No mapping for enum " , name ) ;
}
} ,
} ) ;
info . SetEqualsFunc (
// Casts addr1 and addr2 to the enum type and returns true if
// they are equal, false otherwise.
[ ] ( const ConfigOptions & , const std : : string & , const void * addr1 ,
@ -299,6 +323,7 @@ class OptionTypeInfo {
return ( * static_cast < const T * > ( addr1 ) = =
* static_cast < const T * > ( addr2 ) ) ;
} ) ;
return info ;
} // End OptionTypeInfo::Enum
// Creates an OptionTypeInfo for a Struct type. Structs have a
@ -327,21 +352,23 @@ class OptionTypeInfo {
const std : : string & struct_name ,
const std : : unordered_map < std : : string , OptionTypeInfo > * struct_map ,
int offset , OptionVerificationType verification , OptionTypeFlags flags ) {
return OptionTypeInfo (
offset , OptionType : : kStruct , verification , flags ,
OptionTypeInfo info ( offset , OptionType : : kStruct , verification , flags ) ;
info . SetParseFunc (
// Parses the struct and updates the fields at addr
[ struct_name , struct_map ] ( const ConfigOptions & opts ,
const std : : string & name ,
const std : : string & value , void * addr ) {
return ParseStruct ( opts , struct_name , struct_map , name , value , addr ) ;
} ,
} ) ;
info . SetSerializeFunc (
// Serializes the struct options into value
[ struct_name , struct_map ] ( const ConfigOptions & opts ,
const std : : string & name , const void * addr ,
std : : string * value ) {
return SerializeStruct ( opts , struct_name , struct_map , name , addr ,
value ) ;
} ,
} ) ;
info . SetEqualsFunc (
// Compares the struct fields of addr1 and addr2 for equality
[ struct_name , struct_map ] ( const ConfigOptions & opts ,
const std : : string & name , const void * addr1 ,
@ -349,26 +376,16 @@ class OptionTypeInfo {
return StructsAreEqual ( opts , struct_name , struct_map , name , addr1 ,
addr2 , mismatch ) ;
} ) ;
return info ;
}
static OptionTypeInfo Struct (
const std : : string & struct_name ,
const std : : unordered_map < std : : string , OptionTypeInfo > * struct_map ,
int offset , OptionVerificationType verification , OptionTypeFlags flags ,
const ParseFunc & parse_func ) {
return OptionTypeInfo (
offset , OptionType : : kStruct , verification , flags , parse_func ,
[ struct_name , struct_map ] ( const ConfigOptions & opts ,
const std : : string & name , const void * addr ,
std : : string * value ) {
return SerializeStruct ( opts , struct_name , struct_map , name , addr ,
value ) ;
} ,
[ struct_name , struct_map ] ( const ConfigOptions & opts ,
const std : : string & name , const void * addr1 ,
const void * addr2 , std : : string * mismatch ) {
return StructsAreEqual ( opts , struct_name , struct_map , name , addr1 ,
addr2 , mismatch ) ;
} ) ;
OptionTypeInfo info (
Struct ( struct_name , struct_map , offset , verification , flags ) ) ;
return info . SetParseFunc ( parse_func ) ;
}
template < typename T >
@ -377,30 +394,28 @@ class OptionTypeInfo {
OptionTypeFlags _flags ,
const OptionTypeInfo & elem_info ,
char separator = ' : ' ) {
return OptionTypeInfo (
_offset , OptionType : : kVector , _verification , _flags ,
[ elem_info , separator ] ( const ConfigOptions & opts ,
const std : : string & name ,
const std : : string & value , void * addr ) {
auto result = static_cast < std : : vector < T > * > ( addr ) ;
return ParseVector < T > ( opts , elem_info , separator , name , value ,
result ) ;
} ,
[ elem_info , separator ] ( const ConfigOptions & opts ,
const std : : string & name , const void * addr ,
std : : string * value ) {
const auto & vec = * ( static_cast < const std : : vector < T > * > ( addr ) ) ;
return SerializeVector < T > ( opts , elem_info , separator , name , vec ,
value ) ;
} ,
[ elem_info ] ( const ConfigOptions & opts , const std : : string & name ,
const void * addr1 , const void * addr2 ,
std : : string * mismatch ) {
const auto & vec1 = * ( static_cast < const std : : vector < T > * > ( addr1 ) ) ;
const auto & vec2 = * ( static_cast < const std : : vector < T > * > ( addr2 ) ) ;
return VectorsAreEqual < T > ( opts , elem_info , name , vec1 , vec2 ,
mismatch ) ;
} ) ;
OptionTypeInfo info ( _offset , OptionType : : kVector , _verification , _flags ) ;
info . SetParseFunc ( [ elem_info , separator ] (
const ConfigOptions & opts , const std : : string & name ,
const std : : string & value , void * addr ) {
auto result = static_cast < std : : vector < T > * > ( addr ) ;
return ParseVector < T > ( opts , elem_info , separator , name , value , result ) ;
} ) ;
info . SetSerializeFunc ( [ elem_info , separator ] ( const ConfigOptions & opts ,
const std : : string & name ,
const void * addr ,
std : : string * value ) {
const auto & vec = * ( static_cast < const std : : vector < T > * > ( addr ) ) ;
return SerializeVector < T > ( opts , elem_info , separator , name , vec , value ) ;
} ) ;
info . SetEqualsFunc ( [ elem_info ] ( const ConfigOptions & opts ,
const std : : string & name , const void * addr1 ,
const void * addr2 , std : : string * mismatch ) {
const auto & vec1 = * ( static_cast < const std : : vector < T > * > ( addr1 ) ) ;
const auto & vec2 = * ( static_cast < const std : : vector < T > * > ( addr2 ) ) ;
return VectorsAreEqual < T > ( opts , elem_info , name , vec1 , vec2 , mismatch ) ;
} ) ;
return info ;
}
// Create a new std::shared_ptr<Customizable> OptionTypeInfo
@ -416,7 +431,19 @@ class OptionTypeInfo {
static OptionTypeInfo AsCustomSharedPtr ( int offset ,
OptionVerificationType ovt ,
OptionTypeFlags flags ) {
return AsCustomSharedPtr < T > ( offset , ovt , flags , nullptr , nullptr ) ;
OptionTypeInfo info ( offset , OptionType : : kCustomizable , ovt ,
flags | OptionTypeFlags : : kShared ) ;
return info . SetParseFunc ( [ ] ( const ConfigOptions & opts ,
const std : : string & name ,
const std : : string & value , void * addr ) {
auto * shared = static_cast < std : : shared_ptr < T > * > ( addr ) ;
if ( name = = kIdPropName ( ) & & value . empty ( ) ) {
shared - > reset ( ) ;
return Status : : OK ( ) ;
} else {
return T : : CreateFromString ( opts , value , shared ) ;
}
} ) ;
}
template < typename T >
@ -425,20 +452,10 @@ class OptionTypeInfo {
OptionTypeFlags flags ,
const SerializeFunc & serialize_func ,
const EqualsFunc & equals_func ) {
return OptionTypeInfo (
offset , OptionType : : kCustomizable , ovt ,
flags | OptionTypeFlags : : kShared ,
[ ] ( const ConfigOptions & opts , const std : : string & name ,
const std : : string & value , void * addr ) {
auto * shared = static_cast < std : : shared_ptr < T > * > ( addr ) ;
if ( name = = kIdPropName ( ) & & value . empty ( ) ) {
shared - > reset ( ) ;
return Status : : OK ( ) ;
} else {
return T : : CreateFromString ( opts , value , shared ) ;
}
} ,
serialize_func , equals_func ) ;
OptionTypeInfo info ( AsCustomSharedPtr < T > ( offset , ovt , flags ) ) ;
info . SetSerializeFunc ( serialize_func ) ;
info . SetEqualsFunc ( equals_func ) ;
return info ;
}
// Create a new std::unique_ptr<Customizable> OptionTypeInfo
@ -454,7 +471,19 @@ class OptionTypeInfo {
static OptionTypeInfo AsCustomUniquePtr ( int offset ,
OptionVerificationType ovt ,
OptionTypeFlags flags ) {
return AsCustomUniquePtr < T > ( offset , ovt , flags , nullptr , nullptr ) ;
OptionTypeInfo info ( offset , OptionType : : kCustomizable , ovt ,
flags | OptionTypeFlags : : kUnique ) ;
return info . SetParseFunc ( [ ] ( const ConfigOptions & opts ,
const std : : string & name ,
const std : : string & value , void * addr ) {
auto * unique = static_cast < std : : unique_ptr < T > * > ( addr ) ;
if ( name = = kIdPropName ( ) & & value . empty ( ) ) {
unique - > reset ( ) ;
return Status : : OK ( ) ;
} else {
return T : : CreateFromString ( opts , value , unique ) ;
}
} ) ;
}
template < typename T >
@ -463,20 +492,10 @@ class OptionTypeInfo {
OptionTypeFlags flags ,
const SerializeFunc & serialize_func ,
const EqualsFunc & equals_func ) {
return OptionTypeInfo (
offset , OptionType : : kCustomizable , ovt ,
flags | OptionTypeFlags : : kUnique ,
[ ] ( const ConfigOptions & opts , const std : : string & name ,
const std : : string & value , void * addr ) {
auto * unique = static_cast < std : : unique_ptr < T > * > ( addr ) ;
if ( name = = kIdPropName ( ) & & value . empty ( ) ) {
unique - > reset ( ) ;
return Status : : OK ( ) ;
} else {
return T : : CreateFromString ( opts , value , unique ) ;
}
} ,
serialize_func , equals_func ) ;
OptionTypeInfo info ( AsCustomUniquePtr < T > ( offset , ovt , flags ) ) ;
info . SetSerializeFunc ( serialize_func ) ;
info . SetEqualsFunc ( equals_func ) ;
return info ;
}
// Create a new Customizable* OptionTypeInfo
@ -491,7 +510,19 @@ class OptionTypeInfo {
template < typename T >
static OptionTypeInfo AsCustomRawPtr ( int offset , OptionVerificationType ovt ,
OptionTypeFlags flags ) {
return AsCustomRawPtr < T > ( offset , ovt , flags , nullptr , nullptr ) ;
OptionTypeInfo info ( offset , OptionType : : kCustomizable , ovt ,
flags | OptionTypeFlags : : kRawPointer ) ;
return info . SetParseFunc ( [ ] ( const ConfigOptions & opts ,
const std : : string & name ,
const std : : string & value , void * addr ) {
auto * * pointer = static_cast < T * * > ( addr ) ;
if ( name = = kIdPropName ( ) & & value . empty ( ) ) {
* pointer = nullptr ;
return Status : : OK ( ) ;
} else {
return T : : CreateFromString ( opts , value , pointer ) ;
}
} ) ;
}
template < typename T >
@ -499,20 +530,34 @@ class OptionTypeInfo {
OptionTypeFlags flags ,
const SerializeFunc & serialize_func ,
const EqualsFunc & equals_func ) {
return OptionTypeInfo (
offset , OptionType : : kCustomizable , ovt ,
flags | OptionTypeFlags : : kRawPointer ,
[ ] ( const ConfigOptions & opts , const std : : string & name ,
const std : : string & value , void * addr ) {
auto * * pointer = static_cast < T * * > ( addr ) ;
if ( name = = kIdPropName ( ) & & value . empty ( ) ) {
* pointer = nullptr ;
return Status : : OK ( ) ;
} else {
return T : : CreateFromString ( opts , value , pointer ) ;
}
} ,
serialize_func , equals_func ) ;
OptionTypeInfo info ( AsCustomRawPtr < T > ( offset , ovt , flags ) ) ;
info . SetSerializeFunc ( serialize_func ) ;
info . SetEqualsFunc ( equals_func ) ;
return info ;
}
OptionTypeInfo & SetParseFunc ( const ParseFunc & f ) {
parse_func_ = f ;
return * this ;
}
OptionTypeInfo & SetSerializeFunc ( const SerializeFunc & f ) {
serialize_func_ = f ;
return * this ;
}
OptionTypeInfo & SetEqualsFunc ( const EqualsFunc & f ) {
equals_func_ = f ;
return * this ;
}
OptionTypeInfo & SetPrepareFunc ( const PrepareFunc & f ) {
prepare_func_ = f ;
return * this ;
}
OptionTypeInfo & SetValidateFunc ( const ValidateFunc & f ) {
validate_func_ = f ;
return * this ;
}
bool IsEnabled ( OptionTypeFlags otf ) const { return ( flags_ & otf ) = = otf ; }
@ -569,6 +614,24 @@ class OptionTypeInfo {
}
}
bool ShouldPrepare ( ) const {
if ( IsDeprecated ( ) | | IsAlias ( ) ) {
return false ;
} else if ( IsEnabled ( OptionTypeFlags : : kDontPrepare ) ) {
return false ;
} else {
return ( prepare_func_ ! = nullptr | | IsConfigurable ( ) ) ;
}
}
bool ShouldValidate ( ) const {
if ( IsDeprecated ( ) | | IsAlias ( ) ) {
return false ;
} else {
return ( validate_func_ ! = nullptr | | IsConfigurable ( ) ) ;
}
}
// Returns true if the option is allowed to be null.
// Options can be null if the verification type is allow from null
// or if the flags specify allow null.
@ -599,6 +662,26 @@ class OptionTypeInfo {
bool IsCustomizable ( ) const { return ( type_ = = OptionType : : kCustomizable ) ; }
inline const void * GetOffset ( const void * base ) const {
return static_cast < const char * > ( base ) + offset_ ;
}
inline void * GetOffset ( void * base ) const {
return static_cast < char * > ( base ) + offset_ ;
}
template < typename T >
const T * GetOffsetAs ( const void * base ) const {
const void * addr = GetOffset ( base ) ;
return static_cast < const T * > ( addr ) ;
}
template < typename T >
T * GetOffsetAs ( void * base ) const {
void * addr = GetOffset ( base ) ;
return static_cast < T * > ( addr ) ;
}
// Returns the underlying pointer for the type at base_addr
// The value returned is the underlying "raw" pointer, offset from base.
template < typename T >
@ -606,20 +689,17 @@ class OptionTypeInfo {
if ( base_addr = = nullptr ) {
return nullptr ;
}
const void * opt_addr = static_cast < const char * > ( base_addr ) + offset_ ;
if ( IsUniquePtr ( ) ) {
const std : : unique_ptr < T > * ptr =
static_cast < const std : : unique_ptr < T > * > ( opt_addr ) ;
const auto ptr = GetOffsetAs < std : : unique_ptr < T > > ( base_addr ) ;
return ptr - > get ( ) ;
} else if ( IsSharedPtr ( ) ) {
const std : : shared_ptr < T > * ptr =
static_cast < const std : : shared_ptr < T > * > ( opt_addr ) ;
const auto ptr = GetOffsetAs < std : : shared_ptr < T > > ( base_addr ) ;
return ptr - > get ( ) ;
} else if ( IsRawPtr ( ) ) {
const T * const * ptr = static_cast < const T * const * > ( opt _addr) ;
const T * const * ptr = GetOffsetAs < T * const > ( base _addr) ;
return * ptr ;
} else {
return static_cast < const T * > ( opt _addr) ;
return GetOffsetAs < T > ( base _addr) ;
}
}
@ -630,18 +710,17 @@ class OptionTypeInfo {
if ( base_addr = = nullptr ) {
return nullptr ;
}
void * opt_addr = static_cast < char * > ( base_addr ) + offset_ ;
if ( IsUniquePtr ( ) ) {
std : : unique_ptr < T > * ptr = static_cast < std : : unique_ptr < T > * > ( opt _addr) ;
auto ptr = GetOffsetAs < std : : unique_ptr < T > > ( base _addr) ;
return ptr - > get ( ) ;
} else if ( IsSharedPtr ( ) ) {
std : : shared_ptr < T > * ptr = static_cast < std : : shared_ptr < T > * > ( opt _addr) ;
auto ptr = GetOffsetAs < std : : shared_ptr < T > > ( base _addr) ;
return ptr - > get ( ) ;
} else if ( IsRawPtr ( ) ) {
T * * ptr = static_cast < T * * > ( opt _addr) ;
auto ptr = GetOffsetAs < T * > ( base _addr) ;
return * ptr ;
} else {
return static_cast < T * > ( opt _addr) ;
return GetOffsetAs < T > ( base _addr) ;
}
}
@ -675,6 +754,11 @@ class OptionTypeInfo {
const std : : string & opt_name , const void * const this_ptr ,
const std : : string & that_value ) const ;
Status Prepare ( const ConfigOptions & config_options , const std : : string & name ,
void * opt_ptr ) const ;
Status Validate ( const DBOptions & db_opts , const ColumnFamilyOptions & cf_opts ,
const std : : string & name , const void * opt_ptr ) const ;
// Parses the input opts_map according to the type_map for the opt_addr
// For each name-value pair in opts_map, find the corresponding name in
// type_map If the name is found:
@ -802,6 +886,8 @@ class OptionTypeInfo {
// The optional function to match two option values
EqualsFunc equals_func_ ;
PrepareFunc prepare_func_ ;
ValidateFunc validate_func_ ;
OptionType type_ ;
OptionVerificationType verification_ ;
OptionTypeFlags flags_ ;