@ -7,6 +7,7 @@
// Use of this source code is governed by a BSD-style license that can be
// 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.
// found in the LICENSE file. See the AUTHORS file for names of contributors.
# include "rocksdb/types.h"
# include "rocksdb/transaction_log.h"
# include "rocksdb/transaction_log.h"
# include "utilities/utility_db.h"
# include "utilities/utility_db.h"
# include "utilities/backupable_db.h"
# include "utilities/backupable_db.h"
@ -29,7 +30,11 @@ class DummyDB : public StackableDB {
/* implicit */
/* implicit */
DummyDB ( const Options & options , const std : : string & dbname )
DummyDB ( const Options & options , const std : : string & dbname )
: StackableDB ( nullptr ) , options_ ( options ) , dbname_ ( dbname ) ,
: StackableDB ( nullptr ) , options_ ( options ) , dbname_ ( dbname ) ,
deletions_enabled_ ( true ) { }
deletions_enabled_ ( true ) , sequence_number_ ( 0 ) { }
virtual SequenceNumber GetLatestSequenceNumber ( ) const {
return + + sequence_number_ ;
}
virtual const std : : string & GetName ( ) const override {
virtual const std : : string & GetName ( ) const override {
return dbname_ ;
return dbname_ ;
@ -117,6 +122,7 @@ class DummyDB : public StackableDB {
Options options_ ;
Options options_ ;
std : : string dbname_ ;
std : : string dbname_ ;
bool deletions_enabled_ ;
bool deletions_enabled_ ;
mutable SequenceNumber sequence_number_ ;
} ; // DummyDB
} ; // DummyDB
class TestEnv : public EnvWrapper {
class TestEnv : public EnvWrapper {
@ -292,7 +298,7 @@ class BackupableDBTest {
// set up db options
// set up db options
options_ . create_if_missing = true ;
options_ . create_if_missing = true ;
options_ . paranoid_checks = true ;
options_ . paranoid_checks = true ;
options_ . write_buffer_size = 1 < < 19 ; // 5 12KB
options_ . write_buffer_size = 1 < < 17 ; // 128 KB
options_ . env = test_db_env_ . get ( ) ;
options_ . env = test_db_env_ . get ( ) ;
options_ . wal_dir = dbname_ ;
options_ . wal_dir = dbname_ ;
// set up backup db options
// set up backup db options
@ -305,6 +311,12 @@ class BackupableDBTest {
DestroyDB ( dbname_ , Options ( ) ) ;
DestroyDB ( dbname_ , Options ( ) ) ;
}
}
DB * OpenDB ( ) {
DB * db ;
ASSERT_OK ( DB : : Open ( options_ , dbname_ , & db ) ) ;
return db ;
}
void OpenBackupableDB ( bool destroy_old_data = false , bool dummy = false ) {
void OpenBackupableDB ( bool destroy_old_data = false , bool dummy = false ) {
// reset all the defaults
// reset all the defaults
test_backup_env_ - > SetLimitWrittenFiles ( 1000000 ) ;
test_backup_env_ - > SetLimitWrittenFiles ( 1000000 ) ;
@ -354,12 +366,12 @@ class BackupableDBTest {
} else {
} else {
ASSERT_OK ( restore_db_ - > RestoreDBFromLatestBackup ( dbname_ , dbname_ ) ) ;
ASSERT_OK ( restore_db_ - > RestoreDBFromLatestBackup ( dbname_ , dbname_ ) ) ;
}
}
OpenBackupable DB( ) ;
DB * db = Open DB( ) ;
AssertExists ( db_ . get ( ) , start_exist , end_exist ) ;
AssertExists ( db , start_exist , end_exist ) ;
if ( end ! = 0 ) {
if ( end ! = 0 ) {
AssertEmpty ( db_ . get ( ) , end_exist , end ) ;
AssertEmpty ( db , end_exist , end ) ;
}
}
CloseBackupableDB ( ) ;
delete db ;
if ( opened_restore ) {
if ( opened_restore ) {
CloseRestoreDB ( ) ;
CloseRestoreDB ( ) ;
}
}
@ -450,7 +462,7 @@ TEST(BackupableDBTest, NoDoubleCopy) {
// not be able to open that backup, but all other backups should be
// not be able to open that backup, but all other backups should be
// fine
// fine
TEST ( BackupableDBTest , CorruptionsTest ) {
TEST ( BackupableDBTest , CorruptionsTest ) {
const int keys_iteration = 20 000;
const int keys_iteration = 5 000;
Random rnd ( 6 ) ;
Random rnd ( 6 ) ;
Status s ;
Status s ;
@ -516,7 +528,7 @@ TEST(BackupableDBTest, CorruptionsTest) {
// open DB, write, close DB, backup, restore, repeat
// open DB, write, close DB, backup, restore, repeat
TEST ( BackupableDBTest , OfflineIntegrationTest ) {
TEST ( BackupableDBTest , OfflineIntegrationTest ) {
// has to be a big number, so that it triggers the memtable flush
// has to be a big number, so that it triggers the memtable flush
const int keys_iteration = 20 000;
const int keys_iteration = 5 000;
const int max_key = keys_iteration * 4 + 10 ;
const int max_key = keys_iteration * 4 + 10 ;
// first iter -- flush before backup
// first iter -- flush before backup
// second iter -- don't flush before backup
// second iter -- don't flush before backup
@ -542,9 +554,9 @@ TEST(BackupableDBTest, OfflineIntegrationTest) {
DestroyDB ( dbname_ , Options ( ) ) ;
DestroyDB ( dbname_ , Options ( ) ) ;
// ---- make sure it's empty ----
// ---- make sure it's empty ----
OpenBackupable DB( ) ;
DB * db = Open DB( ) ;
AssertEmpty ( db_ . get ( ) , 0 , fill_up_to ) ;
AssertEmpty ( db , 0 , fill_up_to ) ;
CloseBackupableDB ( ) ;
delete db ;
// ---- restore the DB ----
// ---- restore the DB ----
OpenRestoreDB ( ) ;
OpenRestoreDB ( ) ;
@ -563,7 +575,7 @@ TEST(BackupableDBTest, OfflineIntegrationTest) {
// open DB, write, backup, write, backup, close, restore
// open DB, write, backup, write, backup, close, restore
TEST ( BackupableDBTest , OnlineIntegrationTest ) {
TEST ( BackupableDBTest , OnlineIntegrationTest ) {
// has to be a big number, so that it triggers the memtable flush
// has to be a big number, so that it triggers the memtable flush
const int keys_iteration = 20 000;
const int keys_iteration = 5 000;
const int max_key = keys_iteration * 4 + 10 ;
const int max_key = keys_iteration * 4 + 10 ;
Random rnd ( 7 ) ;
Random rnd ( 7 ) ;
// delete old data
// delete old data
@ -591,9 +603,9 @@ TEST(BackupableDBTest, OnlineIntegrationTest) {
DestroyDB ( dbname_ , Options ( ) ) ;
DestroyDB ( dbname_ , Options ( ) ) ;
// ---- make sure it's empty ----
// ---- make sure it's empty ----
OpenBackupable DB( ) ;
DB * db = Open DB( ) ;
AssertEmpty ( db_ . get ( ) , 0 , max_key ) ;
AssertEmpty ( db , 0 , max_key ) ;
CloseBackupableDB ( ) ;
delete db ;
// ---- restore every backup and verify all the data is there ----
// ---- restore every backup and verify all the data is there ----
OpenRestoreDB ( ) ;
OpenRestoreDB ( ) ;
@ -624,6 +636,29 @@ TEST(BackupableDBTest, OnlineIntegrationTest) {
CloseRestoreDB ( ) ;
CloseRestoreDB ( ) ;
}
}
TEST ( BackupableDBTest , DeleteNewerBackups ) {
// create backups 1, 2, 3, 4, 5
OpenBackupableDB ( true ) ;
for ( int i = 0 ; i < 5 ; + + i ) {
FillDB ( db_ . get ( ) , 100 * i , 100 * ( i + 1 ) ) ;
ASSERT_OK ( db_ - > CreateNewBackup ( ! ! ( i % 2 ) ) ) ;
}
CloseBackupableDB ( ) ;
// backup 3 is fine
AssertBackupConsistency ( 3 , 0 , 300 , 500 ) ;
// this should delete backups 4 and 5
OpenBackupableDB ( ) ;
CloseBackupableDB ( ) ;
// backups 4 and 5 don't exist
OpenRestoreDB ( ) ;
Status s = restore_db_ - > RestoreDBFromBackup ( 4 , dbname_ , dbname_ ) ;
ASSERT_TRUE ( s . IsNotFound ( ) ) ;
s = restore_db_ - > RestoreDBFromBackup ( 5 , dbname_ , dbname_ ) ;
ASSERT_TRUE ( s . IsNotFound ( ) ) ;
CloseRestoreDB ( ) ;
}
} // anon namespace
} // anon namespace
} // namespace rocksdb
} // namespace rocksdb