@ -1217,10 +1217,6 @@ void StressTest::TestCompactFiles(ThreadState* /* thread */,
Status StressTest : : TestBackupRestore (
Status StressTest : : TestBackupRestore (
ThreadState * thread , const std : : vector < int > & rand_column_families ,
ThreadState * thread , const std : : vector < int > & rand_column_families ,
const std : : vector < int64_t > & rand_keys ) {
const std : : vector < int64_t > & rand_keys ) {
// Note the column families chosen by `rand_column_families` cannot be
// dropped while the locks for `rand_keys` are held. So we should not have
// to worry about accessing those column families throughout this function.
assert ( rand_column_families . size ( ) = = rand_keys . size ( ) ) ;
std : : string backup_dir = FLAGS_db + " /.backup " + ToString ( thread - > tid ) ;
std : : string backup_dir = FLAGS_db + " /.backup " + ToString ( thread - > tid ) ;
std : : string restore_dir = FLAGS_db + " /.restore " + ToString ( thread - > tid ) ;
std : : string restore_dir = FLAGS_db + " /.restore " + ToString ( thread - > tid ) ;
BackupableDBOptions backup_opts ( backup_dir ) ;
BackupableDBOptions backup_opts ( backup_dir ) ;
@ -1249,32 +1245,60 @@ Status StressTest::TestBackupRestore(
}
}
}
}
BackupEngine * backup_engine = nullptr ;
BackupEngine * backup_engine = nullptr ;
std : : string from = " a backup/restore operation " ;
Status s = BackupEngine : : Open ( db_stress_env , backup_opts , & backup_engine ) ;
Status s = BackupEngine : : Open ( db_stress_env , backup_opts , & backup_engine ) ;
if ( ! s . ok ( ) ) {
from = " BackupEngine::Open " ;
}
if ( s . ok ( ) ) {
if ( s . ok ( ) ) {
s = backup_engine - > CreateNewBackup ( db_ ) ;
s = backup_engine - > CreateNewBackup ( db_ ) ;
if ( ! s . ok ( ) ) {
from = " BackupEngine::CreateNewBackup " ;
}
}
}
if ( s . ok ( ) ) {
if ( s . ok ( ) ) {
delete backup_engine ;
delete backup_engine ;
backup_engine = nullptr ;
backup_engine = nullptr ;
s = BackupEngine : : Open ( db_stress_env , backup_opts , & backup_engine ) ;
s = BackupEngine : : Open ( db_stress_env , backup_opts , & backup_engine ) ;
if ( ! s . ok ( ) ) {
from = " BackupEngine::Open (again) " ;
}
}
}
std : : vector < BackupInfo > backup_info ;
std : : vector < BackupInfo > backup_info ;
if ( s . ok ( ) ) {
if ( s . ok ( ) ) {
backup_engine - > GetBackupInfo ( & backup_info ) ;
backup_engine - > GetBackupInfo ( & backup_info ) ;
if ( backup_info . empty ( ) ) {
if ( backup_info . empty ( ) ) {
s = Status : : NotFound ( " no backups found " ) ;
s = Status : : NotFound ( " no backups found " ) ;
from = " BackupEngine::GetBackupInfo " ;
}
}
}
}
if ( s . ok ( ) & & thread - > rand . OneIn ( 2 ) ) {
if ( s . ok ( ) & & thread - > rand . OneIn ( 2 ) ) {
s = backup_engine - > VerifyBackup (
s = backup_engine - > VerifyBackup (
backup_info . front ( ) . backup_id ,
backup_info . front ( ) . backup_id ,
thread - > rand . OneIn ( 2 ) /* verify_with_checksum */ ) ;
thread - > rand . OneIn ( 2 ) /* verify_with_checksum */ ) ;
if ( ! s . ok ( ) ) {
from = " BackupEngine::VerifyBackup " ;
}
}
}
bool from_latest = false ;
if ( s . ok ( ) ) {
if ( s . ok ( ) ) {
int count = static_cast < int > ( backup_info . size ( ) ) ;
int count = static_cast < int > ( backup_info . size ( ) ) ;
if ( count > 1 ) {
s = backup_engine - > RestoreDBFromBackup (
s = backup_engine - > RestoreDBFromBackup (
RestoreOptions ( ) , backup_info [ thread - > rand . Uniform ( count ) ] . backup_id ,
RestoreOptions ( ) , backup_info [ thread - > rand . Uniform ( count ) ] . backup_id ,
restore_dir /* db_dir */ , restore_dir /* wal_dir */ ) ;
restore_dir /* db_dir */ , restore_dir /* wal_dir */ ) ;
if ( ! s . ok ( ) ) {
from = " BackupEngine::RestoreDBFromBackup " ;
}
} else {
from_latest = true ;
s = backup_engine - > RestoreDBFromLatestBackup ( RestoreOptions ( ) ,
restore_dir /* db_dir */ ,
restore_dir /* wal_dir */ ) ;
if ( ! s . ok ( ) ) {
from = " BackupEngine::RestoreDBFromLatestBackup " ;
}
}
}
}
if ( s . ok ( ) ) {
if ( s . ok ( ) ) {
uint32_t to_keep = 0 ;
uint32_t to_keep = 0 ;
@ -1283,6 +1307,9 @@ Status StressTest::TestBackupRestore(
to_keep = thread - > rand . Uniform ( 3 ) ;
to_keep = thread - > rand . Uniform ( 3 ) ;
}
}
s = backup_engine - > PurgeOldBackups ( to_keep ) ;
s = backup_engine - > PurgeOldBackups ( to_keep ) ;
if ( ! s . ok ( ) ) {
from = " BackupEngine::PurgeOldBackups " ;
}
}
}
DB * restored_db = nullptr ;
DB * restored_db = nullptr ;
std : : vector < ColumnFamilyHandle * > restored_cf_handles ;
std : : vector < ColumnFamilyHandle * > restored_cf_handles ;
@ -1300,11 +1327,19 @@ Status StressTest::TestBackupRestore(
}
}
s = DB : : Open ( DBOptions ( restore_options ) , restore_dir , cf_descriptors ,
s = DB : : Open ( DBOptions ( restore_options ) , restore_dir , cf_descriptors ,
& restored_cf_handles , & restored_db ) ;
& restored_cf_handles , & restored_db ) ;
if ( ! s . ok ( ) ) {
from = " DB::Open in backup/restore " ;
}
}
// for simplicity, currently only verifies existence/non-existence of a few
}
// keys
// Note the column families chosen by `rand_column_families` cannot be
for ( size_t i = 0 ; s . ok ( ) & & i < rand_column_families . size ( ) ; + + i ) {
// dropped while the locks for `rand_keys` are held. So we should not have
std : : string key_str = Key ( rand_keys [ i ] ) ;
// to worry about accessing those column families throughout this function.
//
// For simplicity, currently only verifies existence/non-existence of a
// single key
for ( size_t i = 0 ; from_latest & & s . ok ( ) & & i < rand_column_families . size ( ) ;
+ + i ) {
std : : string key_str = Key ( rand_keys [ 0 ] ) ;
Slice key = key_str ;
Slice key = key_str ;
std : : string restored_value ;
std : : string restored_value ;
Status get_status = restored_db - > Get (
Status get_status = restored_db - > Get (
@ -1321,6 +1356,9 @@ Status StressTest::TestBackupRestore(
}
}
} else {
} else {
s = get_status ;
s = get_status ;
if ( ! s . ok ( ) ) {
from = " DB::Get in backup/restore " ;
}
}
}
}
}
if ( backup_engine ! = nullptr ) {
if ( backup_engine ! = nullptr ) {
@ -1335,7 +1373,7 @@ Status StressTest::TestBackupRestore(
restored_db = nullptr ;
restored_db = nullptr ;
}
}
if ( ! s . ok ( ) ) {
if ( ! s . ok ( ) ) {
fprintf ( stderr , " A backup/restore operation failed with: %s\n " ,
fprintf ( stderr , " Failure in %s with: %s\n " , from . c_str ( ) ,
s . ToString ( ) . c_str ( ) ) ;
s . ToString ( ) . c_str ( ) ) ;
}
}
return s ;
return s ;