@ -581,7 +581,8 @@ bool AreEqualOptions(
Status RocksDBOptionsParser : : VerifyRocksDBOptionsFromFile (
Status RocksDBOptionsParser : : VerifyRocksDBOptionsFromFile (
const DBOptions & db_opt , const std : : vector < std : : string > & cf_names ,
const DBOptions & db_opt , const std : : vector < std : : string > & cf_names ,
const std : : vector < ColumnFamilyOptions > & cf_opts ,
const std : : vector < ColumnFamilyOptions > & cf_opts ,
const std : : string & file_name , Env * env ) {
const std : : string & file_name , Env * env ,
OptionsSanityCheckLevel sanity_check_level ) {
RocksDBOptionsParser parser ;
RocksDBOptionsParser parser ;
std : : unique_ptr < SequentialFile > seq_file ;
std : : unique_ptr < SequentialFile > seq_file ;
Status s = parser . Parse ( file_name , env ) ;
Status s = parser . Parse ( file_name , env ) ;
@ -590,20 +591,28 @@ Status RocksDBOptionsParser::VerifyRocksDBOptionsFromFile(
}
}
// Verify DBOptions
// Verify DBOptions
s = VerifyDBOptions ( db_opt , * parser . db_opt ( ) , parser . db_opt_map ( ) ) ;
s = VerifyDBOptions ( db_opt , * parser . db_opt ( ) , parser . db_opt_map ( ) ,
sanity_check_level ) ;
if ( ! s . ok ( ) ) {
if ( ! s . ok ( ) ) {
return s ;
return s ;
}
}
// Verify ColumnFamily Name
// Verify ColumnFamily Name
if ( cf_names . size ( ) ! = parser . cf_names ( ) - > size ( ) ) {
if ( cf_names . size ( ) ! = parser . cf_names ( ) - > size ( ) ) {
return Status : : Corruption (
if ( sanity_check_level > = kSanityLevelLooselyCompatible ) {
" [RocksDBOptionParser Error] The persisted options does not have "
return Status : : InvalidArgument (
" the same number of column family names as the db instance. " ) ;
" [RocksDBOptionParser Error] The persisted options does not have "
" the same number of column family names as the db instance. " ) ;
} else if ( cf_opts . size ( ) > parser . cf_opts ( ) - > size ( ) ) {
return Status : : InvalidArgument (
" [RocksDBOptionsParser Error] " ,
" The persisted options file has less number of column family "
" names than that of the specified one. " ) ;
}
}
}
for ( size_t i = 0 ; i < cf_names . size ( ) ; + + i ) {
for ( size_t i = 0 ; i < cf_names . size ( ) ; + + i ) {
if ( cf_names [ i ] ! = parser . cf_names ( ) - > at ( i ) ) {
if ( cf_names [ i ] ! = parser . cf_names ( ) - > at ( i ) ) {
return Status : : Corruption (
return Status : : InvalidArgument (
" [RocksDBOptionParser Error] The persisted options and the db "
" [RocksDBOptionParser Error] The persisted options and the db "
" instance does not have the same name for column family " ,
" instance does not have the same name for column family " ,
ToString ( i ) ) ;
ToString ( i ) ) ;
@ -612,18 +621,27 @@ Status RocksDBOptionsParser::VerifyRocksDBOptionsFromFile(
// Verify Column Family Options
// Verify Column Family Options
if ( cf_opts . size ( ) ! = parser . cf_opts ( ) - > size ( ) ) {
if ( cf_opts . size ( ) ! = parser . cf_opts ( ) - > size ( ) ) {
return Status : : Corruption (
if ( sanity_check_level > = kSanityLevelLooselyCompatible ) {
" [RocksDBOptionParser Error] The persisted options does not have "
return Status : : InvalidArgument (
" the same number of column families as the db instance. " ) ;
" [RocksDBOptionsParser Error] " ,
" The persisted options does not have the same number of "
" column families as the db instance. " ) ;
} else if ( cf_opts . size ( ) > parser . cf_opts ( ) - > size ( ) ) {
return Status : : InvalidArgument (
" [RocksDBOptionsParser Error] " ,
" The persisted options file has less number of column families "
" than that of the specified number. " ) ;
}
}
}
for ( size_t i = 0 ; i < cf_opts . size ( ) ; + + i ) {
for ( size_t i = 0 ; i < cf_opts . size ( ) ; + + i ) {
s = VerifyCFOptions ( cf_opts [ i ] , parser . cf_opts ( ) - > at ( i ) ,
s = VerifyCFOptions ( cf_opts [ i ] , parser . cf_opts ( ) - > at ( i ) ,
& ( parser . cf_opt_maps ( ) - > at ( i ) ) ) ;
& ( parser . cf_opt_maps ( ) - > at ( i ) ) , sanity_check_level ) ;
if ( ! s . ok ( ) ) {
if ( ! s . ok ( ) ) {
return s ;
return s ;
}
}
s = VerifyTableFactory ( cf_opts [ i ] . table_factory . get ( ) ,
s = VerifyTableFactory ( cf_opts [ i ] . table_factory . get ( ) ,
parser . cf_opts ( ) - > at ( i ) . table_factory . get ( ) ) ;
parser . cf_opts ( ) - > at ( i ) . table_factory . get ( ) ,
sanity_check_level ) ;
if ( ! s . ok ( ) ) {
if ( ! s . ok ( ) ) {
return s ;
return s ;
}
}
@ -633,42 +651,75 @@ Status RocksDBOptionsParser::VerifyRocksDBOptionsFromFile(
}
}
Status RocksDBOptionsParser : : VerifyDBOptions (
Status RocksDBOptionsParser : : VerifyDBOptions (
const DBOptions & base_opt , const DBOptions & new_opt ,
const DBOptions & base_opt , const DBOptions & persisted_opt ,
const std : : unordered_map < std : : string , std : : string > * opt_map ) {
const std : : unordered_map < std : : string , std : : string > * opt_map ,
OptionsSanityCheckLevel sanity_check_level ) {
for ( auto pair : db_options_type_info ) {
for ( auto pair : db_options_type_info ) {
if ( pair . second . verification = = OptionVerificationType : : kDeprecated ) {
if ( pair . second . verification = = OptionVerificationType : : kDeprecated ) {
// We skip checking deprecated variables as they might
// We skip checking deprecated variables as they might
// contain random values since they might not be initialized
// contain random values since they might not be initialized
continue ;
continue ;
}
}
if ( ! AreEqualOptions ( reinterpret_cast < const char * > ( & base_opt ) ,
if ( DBOptionSanityCheckLevel ( pair . first ) < = sanity_check_level ) {
reinterpret_cast < const char * > ( & new_opt ) , pair . second ,
if ( ! AreEqualOptions ( reinterpret_cast < const char * > ( & base_opt ) ,
pair . first , nullptr ) ) {
reinterpret_cast < const char * > ( & persisted_opt ) ,
return Status : : Corruption (
pair . second , pair . first , nullptr ) ) {
" [RocksDBOptionsParser]: "
const size_t kBufferSize = 2048 ;
" failed the verification on DBOptions:: " ,
char buffer [ kBufferSize ] ;
pair . first ) ;
std : : string base_value ;
std : : string persisted_value ;
SerializeSingleOptionHelper (
reinterpret_cast < const char * > ( & base_opt ) + pair . second . offset ,
pair . second . type , & base_value ) ;
SerializeSingleOptionHelper (
reinterpret_cast < const char * > ( & persisted_opt ) + pair . second . offset ,
pair . second . type , & persisted_value ) ;
snprintf ( buffer , sizeof ( buffer ) ,
" [RocksDBOptionsParser]: "
" failed the verification on DBOptions::%s --- "
" The specified one is %s while the persisted one is %s. \n " ,
pair . first . c_str ( ) , base_value . c_str ( ) ,
persisted_value . c_str ( ) ) ;
return Status : : InvalidArgument ( Slice ( buffer , strlen ( buffer ) ) ) ;
}
}
}
}
}
return Status : : OK ( ) ;
return Status : : OK ( ) ;
}
}
Status RocksDBOptionsParser : : VerifyCFOptions (
Status RocksDBOptionsParser : : VerifyCFOptions (
const ColumnFamilyOptions & base_opt , const ColumnFamilyOptions & new_opt ,
const ColumnFamilyOptions & base_opt ,
const std : : unordered_map < std : : string , std : : string > * new_opt_map ) {
const ColumnFamilyOptions & persisted_opt ,
const std : : unordered_map < std : : string , std : : string > * persisted_opt_map ,
OptionsSanityCheckLevel sanity_check_level ) {
for ( auto & pair : cf_options_type_info ) {
for ( auto & pair : cf_options_type_info ) {
if ( pair . second . verification = = OptionVerificationType : : kDeprecated ) {
if ( pair . second . verification = = OptionVerificationType : : kDeprecated ) {
// We skip checking deprecated variables as they might
// We skip checking deprecated variables as they might
// contain random values since they might not be initialized
// contain random values since they might not be initialized
continue ;
continue ;
}
}
if ( ! AreEqualOptions ( reinterpret_cast < const char * > ( & base_opt ) ,
if ( CFOptionSanityCheckLevel ( pair . first ) < = sanity_check_level ) {
reinterpret_cast < const char * > ( & new_opt ) , pair . second ,
if ( ! AreEqualOptions ( reinterpret_cast < const char * > ( & base_opt ) ,
pair . first , new_opt_map ) ) {
reinterpret_cast < const char * > ( & persisted_opt ) ,
return Status : : Corruption (
pair . second , pair . first , persisted_opt_map ) ) {
" [RocksDBOptionsParser]: "
const size_t kBufferSize = 2048 ;
" failed the verification on ColumnFamilyOptions:: " ,
char buffer [ kBufferSize ] ;
pair . first ) ;
std : : string base_value ;
std : : string persisted_value ;
SerializeSingleOptionHelper (
reinterpret_cast < const char * > ( & base_opt ) + pair . second . offset ,
pair . second . type , & base_value ) ;
SerializeSingleOptionHelper (
reinterpret_cast < const char * > ( & persisted_opt ) + pair . second . offset ,
pair . second . type , & persisted_value ) ;
snprintf ( buffer , sizeof ( buffer ) ,
" [RocksDBOptionsParser]: "
" failed the verification on ColumnFamilyOptions::%s --- "
" The specified one is %s while the persisted one is %s. \n " ,
pair . first . c_str ( ) , base_value . c_str ( ) ,
persisted_value . c_str ( ) ) ;
return Status : : InvalidArgument ( Slice ( buffer , sizeof ( buffer ) ) ) ;
}
}
}
}
}
return Status : : OK ( ) ;
return Status : : OK ( ) ;
@ -676,8 +727,10 @@ Status RocksDBOptionsParser::VerifyCFOptions(
Status RocksDBOptionsParser : : VerifyBlockBasedTableFactory (
Status RocksDBOptionsParser : : VerifyBlockBasedTableFactory (
const BlockBasedTableFactory * base_tf ,
const BlockBasedTableFactory * base_tf ,
const BlockBasedTableFactory * file_tf ) {
const BlockBasedTableFactory * file_tf ,
if ( ( base_tf ! = nullptr ) ! = ( file_tf ! = nullptr ) ) {
OptionsSanityCheckLevel sanity_check_level ) {
if ( ( base_tf ! = nullptr ) ! = ( file_tf ! = nullptr ) & &
sanity_check_level > kSanityLevelNone ) {
return Status : : Corruption (
return Status : : Corruption (
" [RocksDBOptionsParser]: Inconsistent TableFactory class type " ) ;
" [RocksDBOptionsParser]: Inconsistent TableFactory class type " ) ;
}
}
@ -694,29 +747,34 @@ Status RocksDBOptionsParser::VerifyBlockBasedTableFactory(
// contain random values since they might not be initialized
// contain random values since they might not be initialized
continue ;
continue ;
}
}
if ( ! AreEqualOptions ( reinterpret_cast < const char * > ( & base_opt ) ,
if ( BBTOptionSanityCheckLevel ( pair . first ) < = sanity_check_level ) {
reinterpret_cast < const char * > ( & file_opt ) , pair . second ,
if ( ! AreEqualOptions ( reinterpret_cast < const char * > ( & base_opt ) ,
pair . first , nullptr ) ) {
reinterpret_cast < const char * > ( & file_opt ) ,
return Status : : Corruption (
pair . second , pair . first , nullptr ) ) {
" [RocksDBOptionsParser]: "
return Status : : Corruption (
" failed the verification on BlockBasedTableOptions:: " ,
" [RocksDBOptionsParser]: "
pair . first ) ;
" failed the verification on BlockBasedTableOptions:: " ,
pair . first ) ;
}
}
}
}
}
return Status : : OK ( ) ;
return Status : : OK ( ) ;
}
}
Status RocksDBOptionsParser : : VerifyTableFactory ( const TableFactory * base_tf ,
Status RocksDBOptionsParser : : VerifyTableFactory (
const TableFactory * file_tf ) {
const TableFactory * base_tf , const TableFactory * file_tf ,
OptionsSanityCheckLevel sanity_check_level ) {
if ( base_tf & & file_tf ) {
if ( base_tf & & file_tf ) {
if ( base_tf - > Name ( ) ! = file_tf - > Name ( ) ) {
if ( sanity_check_level > kSanityLevelNone & &
base_tf - > Name ( ) ! = file_tf - > Name ( ) ) {
return Status : : Corruption (
return Status : : Corruption (
" [RocksDBOptionsParser]: "
" [RocksDBOptionsParser]: "
" failed the verification on TableFactory->Name() " ) ;
" failed the verification on TableFactory->Name() " ) ;
}
}
auto s = VerifyBlockBasedTableFactory (
auto s = VerifyBlockBasedTableFactory (
dynamic_cast < const BlockBasedTableFactory * > ( base_tf ) ,
dynamic_cast < const BlockBasedTableFactory * > ( base_tf ) ,
dynamic_cast < const BlockBasedTableFactory * > ( file_tf ) ) ;
dynamic_cast < const BlockBasedTableFactory * > ( file_tf ) ,
sanity_check_level ) ;
if ( ! s . ok ( ) ) {
if ( ! s . ok ( ) ) {
return s ;
return s ;
}
}