1010#if !defined(ROCKSDB_LITE) && !defined(OS_WIN)
1111
1212#include < algorithm>
13+ #include < limits>
1314#include < string>
15+ #include < utility>
1416
1517#include " db/db_impl/db_impl.h"
1618#include " env/env_chroot.h"
@@ -516,6 +518,15 @@ static void AssertEmpty(DB* db, int from, int to) {
516518
517519class BackupableDBTest : public testing ::Test {
518520 public:
521+ enum ShareOption {
522+ kNoShare ,
523+ kShareNoChecksum ,
524+ kShareWithChecksum ,
525+ };
526+
527+ const std::vector<ShareOption> kAllShareOptions = {kNoShare , kShareNoChecksum ,
528+ kShareWithChecksum };
529+
519530 BackupableDBTest () {
520531 // set up files
521532 std::string db_chroot = test::PerThreadDBPath (" backupable_db" );
@@ -561,15 +572,8 @@ class BackupableDBTest : public testing::Test {
561572 return db;
562573 }
563574
564- void OpenDBAndBackupEngineShareWithChecksum (
565- bool destroy_old_data = false , bool dummy = false ,
566- bool /* share_table_files*/ = true , bool share_with_checksums = false ) {
567- backupable_options_->share_files_with_checksum = share_with_checksums;
568- OpenDBAndBackupEngine (destroy_old_data, dummy, share_with_checksums);
569- }
570-
571575 void OpenDBAndBackupEngine (bool destroy_old_data = false , bool dummy = false ,
572- bool share_table_files = true ) {
576+ ShareOption shared_option = kShareNoChecksum ) {
573577 // reset all the defaults
574578 test_backup_env_->SetLimitWrittenFiles (1000000 );
575579 test_db_env_->SetLimitWrittenFiles (1000000 );
@@ -584,7 +588,9 @@ class BackupableDBTest : public testing::Test {
584588 }
585589 db_.reset (db);
586590 backupable_options_->destroy_old_data = destroy_old_data;
587- backupable_options_->share_table_files = share_table_files;
591+ backupable_options_->share_table_files = shared_option != kNoShare ;
592+ backupable_options_->share_files_with_checksum =
593+ shared_option == kShareWithChecksum ;
588594 BackupEngine* backup_engine;
589595 ASSERT_OK (BackupEngine::Open (test_db_env_.get (), *backupable_options_,
590596 &backup_engine));
@@ -1205,7 +1211,7 @@ TEST_F(BackupableDBTest, FailOverwritingBackups) {
12051211
12061212TEST_F (BackupableDBTest, NoShareTableFiles) {
12071213 const int keys_iteration = 5000 ;
1208- OpenDBAndBackupEngine (true , false , false );
1214+ OpenDBAndBackupEngine (true , false , kNoShare );
12091215 for (int i = 0 ; i < 5 ; ++i) {
12101216 FillDB (db_.get (), keys_iteration * i, keys_iteration * (i + 1 ));
12111217 ASSERT_OK (backup_engine_->CreateNewBackup (db_.get (), !!(i % 2 )));
@@ -1221,7 +1227,7 @@ TEST_F(BackupableDBTest, NoShareTableFiles) {
12211227// Verify that you can backup and restore with share_files_with_checksum on
12221228TEST_F (BackupableDBTest, ShareTableFilesWithChecksums) {
12231229 const int keys_iteration = 5000 ;
1224- OpenDBAndBackupEngineShareWithChecksum (true , false , true , true );
1230+ OpenDBAndBackupEngine (true , false , kShareWithChecksum );
12251231 for (int i = 0 ; i < 5 ; ++i) {
12261232 FillDB (db_.get (), keys_iteration * i, keys_iteration * (i + 1 ));
12271233 ASSERT_OK (backup_engine_->CreateNewBackup (db_.get (), !!(i % 2 )));
@@ -1239,7 +1245,7 @@ TEST_F(BackupableDBTest, ShareTableFilesWithChecksums) {
12391245TEST_F (BackupableDBTest, ShareTableFilesWithChecksumsTransition) {
12401246 const int keys_iteration = 5000 ;
12411247 // set share_files_with_checksum to false
1242- OpenDBAndBackupEngineShareWithChecksum (true , false , true , false );
1248+ OpenDBAndBackupEngine (true , false , kShareNoChecksum );
12431249 for (int i = 0 ; i < 5 ; ++i) {
12441250 FillDB (db_.get (), keys_iteration * i, keys_iteration * (i + 1 ));
12451251 ASSERT_OK (backup_engine_->CreateNewBackup (db_.get (), true ));
@@ -1252,65 +1258,107 @@ TEST_F(BackupableDBTest, ShareTableFilesWithChecksumsTransition) {
12521258 }
12531259
12541260 // set share_files_with_checksum to true and do some more backups
1255- OpenDBAndBackupEngineShareWithChecksum (true , false , true , true );
1261+ OpenDBAndBackupEngine (false /* destroy_old_data */ , false ,
1262+ kShareWithChecksum );
12561263 for (int i = 5 ; i < 10 ; ++i) {
12571264 FillDB (db_.get (), keys_iteration * i, keys_iteration * (i + 1 ));
12581265 ASSERT_OK (backup_engine_->CreateNewBackup (db_.get (), true ));
12591266 }
12601267 CloseDBAndBackupEngine ();
12611268
1262- for (int i = 0 ; i < 5 ; ++i) {
1263- AssertBackupConsistency (i + 1 , 0 , keys_iteration * (i + 5 + 1 ),
1269+ // Verify first (about to delete)
1270+ AssertBackupConsistency (1 , 0 , keys_iteration, keys_iteration * 11 );
1271+
1272+ // For an extra challenge, make sure that GarbageCollect / DeleteBackup
1273+ // is OK even if we open without share_table_files
1274+ OpenDBAndBackupEngine (false /* destroy_old_data */ , false , kNoShare );
1275+ backup_engine_->DeleteBackup (1 );
1276+ backup_engine_->GarbageCollect ();
1277+ CloseDBAndBackupEngine ();
1278+
1279+ // Verify rest (not deleted)
1280+ for (int i = 1 ; i < 10 ; ++i) {
1281+ AssertBackupConsistency (i + 1 , 0 , keys_iteration * (i + 1 ),
12641282 keys_iteration * 11 );
12651283 }
12661284}
12671285
1286+ // This test simulates cleaning up after aborted or incomplete creation
1287+ // of a new backup.
12681288TEST_F (BackupableDBTest, DeleteTmpFiles) {
1269- for (int cleanup_fn : {1 , 2 , 3 }) {
1270- for (bool shared_checksum : {false , true }) {
1271- OpenDBAndBackupEngineShareWithChecksum (
1272- false /* destroy_old_data */ , false /* dummy */ ,
1273- true /* share_table_files */ , shared_checksum);
1289+ for (int cleanup_fn : {1 , 2 , 3 , 4 }) {
1290+ for (ShareOption shared_option : kAllShareOptions ) {
1291+ OpenDBAndBackupEngine (false /* destroy_old_data */ , false /* dummy */ ,
1292+ shared_option);
1293+ ASSERT_OK (backup_engine_->CreateNewBackup (db_.get ()));
1294+ BackupID next_id = 1 ;
1295+ BackupID oldest_id = std::numeric_limits<BackupID>::max ();
1296+ {
1297+ std::vector<BackupInfo> backup_info;
1298+ backup_engine_->GetBackupInfo (&backup_info);
1299+ for (const auto & bi : backup_info) {
1300+ next_id = std::max (next_id, bi.backup_id + 1 );
1301+ oldest_id = std::min (oldest_id, bi.backup_id );
1302+ }
1303+ }
12741304 CloseDBAndBackupEngine ();
1275- std::string shared_tmp = backupdir_;
1276- if (shared_checksum) {
1277- shared_tmp += " /shared_checksum" ;
1278- } else {
1279- shared_tmp += " /shared" ;
1305+
1306+ // An aborted or incomplete new backup will always be in the next
1307+ // id (maybe more)
1308+ std::string next_private = " private/" + std::to_string (next_id);
1309+
1310+ // NOTE: both shared and shared_checksum should be cleaned up
1311+ // regardless of how the backup engine is opened.
1312+ std::vector<std::string> tmp_files_and_dirs;
1313+ for (const auto & dir_and_file : {
1314+ std::make_pair (std::string (" shared" ),
1315+ std::string (" .00006.sst.tmp" )),
1316+ std::make_pair (std::string (" shared_checksum" ),
1317+ std::string (" .00007.sst.tmp" )),
1318+ std::make_pair (next_private, std::string (" 00003.sst" )),
1319+ }) {
1320+ std::string dir = backupdir_ + " /" + dir_and_file.first ;
1321+ file_manager_->CreateDir (dir);
1322+ ASSERT_OK (file_manager_->FileExists (dir));
1323+
1324+ std::string file = dir + " /" + dir_and_file.second ;
1325+ file_manager_->WriteToFile (file, " tmp" );
1326+ ASSERT_OK (file_manager_->FileExists (file));
1327+
1328+ tmp_files_and_dirs.push_back (file);
12801329 }
1281- shared_tmp += " /.00006.sst.tmp" ;
1282- std::string private_tmp_dir = backupdir_ + " /private/10" ;
1283- std::string private_tmp_file = private_tmp_dir + " /00003.sst" ;
1284- file_manager_->WriteToFile (shared_tmp, " tmp" );
1285- file_manager_->CreateDir (private_tmp_dir);
1286- file_manager_->WriteToFile (private_tmp_file, " tmp" );
1287- ASSERT_OK (file_manager_->FileExists (private_tmp_dir));
1288- if (shared_checksum) {
1289- OpenDBAndBackupEngineShareWithChecksum (
1290- false /* destroy_old_data */ , false /* dummy */ ,
1291- true /* share_table_files */ , true /* share_with_checksums */ );
1292- } else {
1293- OpenDBAndBackupEngine ();
1330+ if (cleanup_fn != /* CreateNewBackup*/ 4 ) {
1331+ // This exists after CreateNewBackup because it's deleted then
1332+ // re-created.
1333+ tmp_files_and_dirs.push_back (backupdir_ + " /" + next_private);
12941334 }
1335+
1336+ OpenDBAndBackupEngine (false /* destroy_old_data */ , false /* dummy */ ,
1337+ shared_option);
12951338 // Need to call one of these explicitly to delete tmp files
12961339 switch (cleanup_fn) {
12971340 case 1 :
1298- ( void ) backup_engine_->GarbageCollect ();
1341+ ASSERT_OK ( backup_engine_->GarbageCollect () );
12991342 break ;
13001343 case 2 :
1301- ( void ) backup_engine_->DeleteBackup (1 );
1344+ ASSERT_OK ( backup_engine_->DeleteBackup (oldest_id) );
13021345 break ;
13031346 case 3 :
1304- (void )backup_engine_->PurgeOldBackups (1 );
1347+ ASSERT_OK (backup_engine_->PurgeOldBackups (1 ));
1348+ break ;
1349+ case 4 :
1350+ // Does a garbage collect if it sees that next private dir exists
1351+ ASSERT_OK (backup_engine_->CreateNewBackup (db_.get ()));
13051352 break ;
13061353 default :
13071354 assert (false );
13081355 }
13091356 CloseDBAndBackupEngine ();
1310- ASSERT_EQ (Status::NotFound (), file_manager_->FileExists (shared_tmp));
1311- ASSERT_EQ (Status::NotFound (),
1312- file_manager_->FileExists (private_tmp_file));
1313- ASSERT_EQ (Status::NotFound (), file_manager_->FileExists (private_tmp_dir));
1357+ for (std::string file_or_dir : tmp_files_and_dirs) {
1358+ if (file_manager_->FileExists (file_or_dir) != Status::NotFound ()) {
1359+ FAIL () << file_or_dir << " was expected to be deleted." << cleanup_fn;
1360+ }
1361+ }
13141362 }
13151363 }
13161364}
0 commit comments