diff options
-rw-r--r-- | lib/backupstore/BackupStoreCheck.cpp | 253 | ||||
-rw-r--r-- | lib/backupstore/BackupStoreCheckData.cpp | 9 | ||||
-rw-r--r-- | test/backupstorefix/testbackupstorefix.cpp | 239 |
3 files changed, 277 insertions, 224 deletions
diff --git a/lib/backupstore/BackupStoreCheck.cpp b/lib/backupstore/BackupStoreCheck.cpp index 53301bed..b8b8cc40 100644 --- a/lib/backupstore/BackupStoreCheck.cpp +++ b/lib/backupstore/BackupStoreCheck.cpp @@ -303,7 +303,7 @@ int64_t BackupStoreCheck::CheckObjectsScanDir(int64_t StartID, int Level, const } else { - BOX_WARNING("Spurious or invalid directory " << + BOX_ERROR("Spurious or invalid directory " << rDirName << DIRECTORY_SEPARATOR << (*i) << " found, " << (mFixErrors?"deleting":"delete manually")); @@ -387,7 +387,7 @@ void BackupStoreCheck::CheckObjectsDir(int64_t StartID) if(!fileOK) { // Unexpected or bad file, delete it - BOX_WARNING("Spurious file " << dirName << + BOX_ERROR("Spurious file " << dirName << DIRECTORY_SEPARATOR << (*i) << " found" << (mFixErrors?", deleting":"")); ++mNumberErrorsFound; @@ -410,7 +410,7 @@ void BackupStoreCheck::CheckObjectsDir(int64_t StartID) if(!CheckAndAddObject(StartID | i, dirName + leaf)) { // File was bad, delete it - BOX_WARNING("Corrupted file " << dirName << + BOX_ERROR("Corrupted file " << dirName << leaf << " found" << (mFixErrors?", deleting":"")); ++mNumberErrorsFound; @@ -624,57 +624,62 @@ void BackupStoreCheck::CheckDirectories() } // Flag for modifications - bool isModified = false; - - // Check for validity + bool isModified = CheckDirectory(dir); + + // Check the directory again, now that entries have been removed if(dir.CheckAndFix()) { // Wasn't quite right, and has been modified - BOX_WARNING("Directory ID " << + BOX_ERROR("Directory ID " << BOX_FORMAT_OBJECTID(pblock->mID[e]) << - " has bad structure"); + " was still bad after all checks"); ++mNumberErrorsFound; isModified = true; } + else if(isModified) + { + BOX_INFO("Directory ID " << + BOX_FORMAT_OBJECTID(pblock->mID[e]) << + " was OK after fixing"); + } - // Go through, and check that everything in that directory exists and is valid - std::vector<int64_t> toDelete; - + if(isModified && mFixErrors) + { + BOX_WARNING("Fixing directory ID " << BOX_FORMAT_OBJECTID(pblock->mID[e])); + + // Save back to disc + RaidFileWrite fixed(mDiscSetNumber, filename); + fixed.Open(true /* allow overwriting */); + dir.WriteToStream(fixed); + // Commit it + fixed.Commit(true /* convert to raid representation now */); + } + + // Count valid entries BackupStoreDirectory::Iterator i(dir); BackupStoreDirectory::Entry *en = 0; while((en = i.Next()) != 0) { - // Lookup the item int32_t iIndex; IDBlock *piBlock = LookupID(en->GetObjectID(), iIndex); - bool badEntry = false; - if(piBlock != 0) - { - badEntry = !CheckDirectoryEntry( - *en, pblock->mID[e], - iIndex, isModified); - } - // Item can't be found. Is it a directory? - else if(en->IsDir()) - { - // Store the directory for later attention - mDirsWhichContainLostDirs[en->GetObjectID()] = pblock->mID[e]; - } - else + + ASSERT(piBlock != 0 || + mDirsWhichContainLostDirs.find(en->GetObjectID()) + != mDirsWhichContainLostDirs.end()); + if (piBlock) { - // Just remove the entry - badEntry = true; - BOX_WARNING("Directory ID " << - BOX_FORMAT_OBJECTID(pblock->mID[e]) << - " references object " << - BOX_FORMAT_OBJECTID(en->GetObjectID()) << - " which does not exist."); + // Normally it would exist and this + // check would not be necessary, but + // we might have missing directories + // that we will recreate later. + // cf mDirsWhichContainLostDirs. + uint8_t iflags = GetFlags(piBlock, iIndex); + SetFlags(piBlock, iIndex, iflags | Flags_IsContained); } - - // Is this entry worth keeping? - if(badEntry) + + if(en->IsDir()) { - toDelete.push_back(en->GetObjectID()); + mNumDirectories++; } else if(!en->IsFile()) { @@ -692,70 +697,117 @@ void BackupStoreCheck::CheckDirectories() } else if(en->IsOld()) { + mNumFiles++; + mNumOldFiles++; mBlocksInOldFiles += en->GetSizeInBlocks(); } else if(en->IsDeleted()) { + mNumFiles++; + mNumDeletedFiles++; mBlocksInDeletedFiles += en->GetSizeInBlocks(); } else { + mNumFiles++; mBlocksInCurrentFiles += en->GetSizeInBlocks(); } } - - if(toDelete.size() > 0) - { - // Delete entries from directory - for(std::vector<int64_t>::const_iterator d(toDelete.begin()); d != toDelete.end(); ++d) - { - dir.DeleteEntry(*d); - } - - // Mark as modified - isModified = true; - - // Errors found - ++mNumberErrorsFound; + } + } + } +} - // Check the directory again, now that entries have been removed - if(dir.CheckAndFix()) - { - // Wasn't quite right, and has been modified - BOX_WARNING("Directory ID " << - BOX_FORMAT_OBJECTID(pblock->mID[e]) << - " was still bad after first pass"); - ++mNumberErrorsFound; - isModified = true; - } - else - { - BOX_INFO("Directory ID " << - BOX_FORMAT_OBJECTID(pblock->mID[e]) << - " was OK after fixing"); - } - } - - if(isModified && mFixErrors) - { - BOX_WARNING("Fixing directory ID " << BOX_FORMAT_OBJECTID(pblock->mID[e])); +bool BackupStoreCheck::CheckDirectory(BackupStoreDirectory& dir) +{ + bool restart = true; + bool isModified = false; - // Save back to disc - RaidFileWrite fixed(mDiscSetNumber, filename); - fixed.Open(true /* allow overwriting */); - dir.WriteToStream(fixed); - // Commit it - fixed.Commit(true /* convert to raid representation now */); - } + while(restart) + { + std::vector<int64_t> toDelete; + restart = false; + + // Check for validity + if(dir.CheckAndFix()) + { + // Wasn't quite right, and has been modified + BOX_ERROR("Directory ID " << + BOX_FORMAT_OBJECTID(dir.GetObjectID()) << + " had invalid entries" << + (mFixErrors ? ", fixed" : "")); + ++mNumberErrorsFound; + isModified = true; + } + + // Go through, and check that everything in that directory exists and is valid + BackupStoreDirectory::Iterator i(dir); + BackupStoreDirectory::Entry *en = 0; + while((en = i.Next()) != 0) + { + // Lookup the item + int32_t iIndex; + IDBlock *piBlock = LookupID(en->GetObjectID(), iIndex); + bool badEntry = false; + if(piBlock != 0) + { + badEntry = !CheckDirectoryEntry(*en, + dir.GetObjectID(), isModified); + } + // Item can't be found. Is it a directory? + else if(en->IsDir()) + { + // Store the directory for later attention + mDirsWhichContainLostDirs[en->GetObjectID()] = + dir.GetObjectID(); + } + else + { + // Just remove the entry + badEntry = true; + BOX_ERROR("Directory ID " << + BOX_FORMAT_OBJECTID(dir.GetObjectID()) << + " references object " << + BOX_FORMAT_OBJECTID(en->GetObjectID()) << + " which does not exist."); + ++mNumberErrorsFound; + } + + // Is this entry worth keeping? + if(badEntry) + { + toDelete.push_back(en->GetObjectID()); } } + + if(toDelete.size() > 0) + { + // Delete entries from directory + for(std::vector<int64_t>::const_iterator d(toDelete.begin()); d != toDelete.end(); ++d) + { + BOX_ERROR("Removing directory entry " << + BOX_FORMAT_OBJECTID(*d) << " from " + "directory " << + BOX_FORMAT_OBJECTID(dir.GetObjectID())); + ++mNumberErrorsFound; + dir.DeleteEntry(*d); + } + + // Mark as modified + restart = true; + isModified = true; + + // Errors found + } } + return isModified; } bool BackupStoreCheck::CheckDirectoryEntry(BackupStoreDirectory::Entry& rEntry, - int64_t DirectoryID, int32_t IndexInDirBlock, bool& rIsModified) + int64_t DirectoryID, bool& rIsModified) { + int32_t IndexInDirBlock; IDBlock *piBlock = LookupID(rEntry.GetObjectID(), IndexInDirBlock); ASSERT(piBlock != 0); @@ -766,27 +818,30 @@ bool BackupStoreCheck::CheckDirectoryEntry(BackupStoreDirectory::Entry& rEntry, if(((iflags & Flags_IsDir) == Flags_IsDir) != rEntry.IsDir()) { // Entry is of wrong type - BOX_WARNING("Directory ID " << + BOX_ERROR("Directory ID " << BOX_FORMAT_OBJECTID(DirectoryID) << " references object " << BOX_FORMAT_OBJECTID(rEntry.GetObjectID()) << " which has a different type than expected."); badEntry = true; + ++mNumberErrorsFound; } // Check that the entry is not already contained. else if(iflags & Flags_IsContained) { - BOX_WARNING("Directory ID " << + BOX_ERROR("Directory ID " << BOX_FORMAT_OBJECTID(DirectoryID) << " references object " << BOX_FORMAT_OBJECTID(rEntry.GetObjectID()) << " which is already contained."); badEntry = true; + ++mNumberErrorsFound; } else { - // Not already contained -- mark as contained - SetFlags(piBlock, IndexInDirBlock, iflags | Flags_IsContained); + // Not already contained by another directory. + // Don't set the flag until later, after we finish repairing + // the directory and removing all bad entries. // Check that the container ID of the object is correct if(piBlock->mContainer[IndexInDirBlock] != DirectoryID) @@ -795,15 +850,16 @@ bool BackupStoreCheck::CheckDirectoryEntry(BackupStoreDirectory::Entry& rEntry, if(iflags & Flags_IsDir) { // Add to will fix later list - BOX_WARNING("Directory ID " << + BOX_ERROR("Directory ID " << BOX_FORMAT_OBJECTID(rEntry.GetObjectID()) << " has wrong container ID."); mDirsWithWrongContainerID.push_back(rEntry.GetObjectID()); + ++mNumberErrorsFound; } else { // This is OK for files, they might move - BOX_WARNING("File ID " << + BOX_NOTICE("File ID " << BOX_FORMAT_OBJECTID(rEntry.GetObjectID()) << " has different container ID, " "probably moved"); @@ -824,37 +880,16 @@ bool BackupStoreCheck::CheckDirectoryEntry(BackupStoreDirectory::Entry& rEntry, // Mark as changed rIsModified = true; + ++mNumberErrorsFound; // Tell user - BOX_WARNING("Directory ID " << + BOX_ERROR("Directory ID " << BOX_FORMAT_OBJECTID(DirectoryID) << " has wrong size for object " << BOX_FORMAT_OBJECTID(rEntry.GetObjectID())); } } - if (!badEntry) - { - if(rEntry.IsDir()) - { - mNumDirectories++; - } - else - { - mNumFiles++; - - if(rEntry.IsDeleted()) - { - mNumDeletedFiles++; - } - - if(rEntry.IsOld()) - { - mNumOldFiles++; - } - } - } - return !badEntry; } diff --git a/lib/backupstore/BackupStoreCheckData.cpp b/lib/backupstore/BackupStoreCheckData.cpp index fed0c3f1..ec606d52 100644 --- a/lib/backupstore/BackupStoreCheckData.cpp +++ b/lib/backupstore/BackupStoreCheckData.cpp @@ -65,16 +65,11 @@ void BackupStoreCheck::AddID(BackupStoreCheck_ID_t ID, if(mpInfoLastBlock == 0 || mInfoLastBlockEntries >= BACKUPSTORECHECK_BLOCK_SIZE) { // No. Allocate a new one - IDBlock *pblk = (IDBlock*)::malloc(sizeof(IDBlock)); + IDBlock *pblk = (IDBlock*)calloc(1, sizeof(IDBlock)); if(pblk == 0) { throw std::bad_alloc(); } - // Zero all the flags entries - for(int z = 0; z < (BACKUPSTORECHECK_BLOCK_SIZE * Flags__NumFlags / Flags__NumItemsPerEntry); ++z) - { - pblk->mFlags[z] = 0; - } // Store in map mInfo[ID] = pblk; // Allocated and stored OK, setup for use @@ -141,8 +136,8 @@ BackupStoreCheck::IDBlock *BackupStoreCheck::LookupID(BackupStoreCheck_ID_t ID, pblock = ib->second; } - ASSERT(pblock != 0); if(pblock == 0) return 0; + ASSERT(pblock != 0); // How many entries are there in the block int32_t bentries = (pblock == mpInfoLastBlock)?mInfoLastBlockEntries:BACKUPSTORECHECK_BLOCK_SIZE; diff --git a/test/backupstorefix/testbackupstorefix.cpp b/test/backupstorefix/testbackupstorefix.cpp index 288139b8..4ad8f7d0 100644 --- a/test/backupstorefix/testbackupstorefix.cpp +++ b/test/backupstorefix/testbackupstorefix.cpp @@ -354,6 +354,79 @@ int64_t fake_upload(BackupProtocolLocal& client, const std::string& file_path, upload)->GetObjectID(); } +void read_bb_dir(int64_t objectId, BackupStoreDirectory& dir) +{ + std::string fn; + StoreStructure::MakeObjectFilename(1 /* root */, storeRoot, + discSetNum, fn, true /* EnsureDirectoryExists */); + + std::auto_ptr<RaidFileRead> file(RaidFileRead::Open(discSetNum, + fn)); + dir.ReadFromStream(*file, IOStream::TimeOutInfinite); +} + +void login_client_and_check_empty(BackupProtocolCallable& client) +{ + // Check that the initial situation matches our expectations. + BackupStoreDirectory dir; + read_bb_dir(1 /* root */, dir); + + dir_en_check start_entries[] = {{-1, 0, 0}}; + check_dir(dir, start_entries); + static checkdepinfoen start_deps[] = {{-1, 0, 0}}; + check_dir_dep(dir, start_deps); + + client.QueryVersion(BACKUP_STORE_SERVER_VERSION); + client.QueryLogin(0x01234567, 0 /* read/write */); + + read_bb_dir(1 /* root */, dir); + + // Everything should be OK at the moment + TEST_THAT(dir.CheckAndFix() == false); + + // Check that we've ended up with the right preconditions + // for the tests below. + dir_en_check before_entries[] = { + {-1, 0, 0} + }; + check_dir(dir, before_entries); + static checkdepinfoen before_deps[] = {{-1, 0, 0}}; + check_dir_dep(dir, before_deps); +} + +void check_root_dir_ok(dir_en_check after_entries[], + checkdepinfoen after_deps[]) +{ + // Check the store, check that the error is detected and + // repaired, by removing x1 from the directory. + BackupStoreCheck check(storeRoot, discSetNum, + 0x01234567 /* AccountID */, false /* FixErrors */, + true /* Quiet */); + check.Check(); + TEST_THAT(!check.ErrorsFound()); + + // Read the directory back in, check that it's empty + BackupStoreDirectory dir; + read_bb_dir(1 /* root */, dir); + + check_dir(dir, after_entries); + check_dir_dep(dir, after_deps); +} + +void check_and_fix_root_dir(dir_en_check after_entries[], + checkdepinfoen after_deps[]) +{ + // Check the store, check that the error is detected and + // repaired. + BackupStoreCheck check(storeRoot, discSetNum, + 0x01234567 /* AccountID */, true /* FixErrors */, + true /* Quiet */); + check.Check(); + TEST_THAT(check.ErrorsFound()); + + check_root_dir_ok(after_entries, after_deps); +} + int test(int argc, const char *argv[]) { { @@ -381,54 +454,20 @@ int test(int argc, const char *argv[]) TEST_THAT_ABORTONFAIL(::system(PERL_EXECUTABLE " testfiles/testbackupstorefix.pl init") == 0); - BOX_INFO("Test that an entry pointing to a file that doesn't exist " - "is really deleted"); + BOX_INFO(" === Test that an entry pointing to a file that doesn't " + "exist is really deleted"); { - // Check that the initial situation matches our expectations. - std::string rootDirName; - StoreStructure::MakeObjectFilename(1 /* root */, storeRoot, - discSetNum, rootDirName, - true /* EnsureDirectoryExists */); - std::auto_ptr<RaidFileRead> file(RaidFileRead::Open(discSetNum, - rootDirName)); - - file = RaidFileRead::Open(discSetNum, rootDirName); - BackupStoreDirectory dir; - dir.ReadFromStream(*file, IOStream::TimeOutInfinite); - dir_en_check start_entries[] = {{-1, 0, 0}}; - check_dir(dir, start_entries); - static checkdepinfoen start_deps[] = {{-1, 0, 0}}; - check_dir_dep(dir, start_deps); - BackupStoreContext ctx(0x01234567, *(HousekeepingInterface *)NULL, "test" /* rConnectionDetails */); ctx.SetClientHasAccount(storeRoot, discSetNum); - BackupProtocolLocal client(ctx); - client.QueryVersion(BACKUP_STORE_SERVER_VERSION); - client.QueryLogin(0x01234567, 0 /* read/write */); + login_client_and_check_empty(client); std::string file_path = "testfiles/TestDir1/cannes/ict/metegoguered/oats"; int x1id = fake_upload(client, file_path, 0); - file = RaidFileRead::Open(discSetNum, rootDirName); - dir.ReadFromStream(*file, IOStream::TimeOutInfinite); - - // Everything should be OK at the moment - TEST_THAT(dir.CheckAndFix() == false); - - // Check that we've ended up with the right preconditions - // for the tests below. - dir_en_check before_entries[] = { - {0, x1id, BackupStoreDirectory::Entry::Flags_File}, - {-1, 0, 0} - }; - check_dir(dir, before_entries); - static checkdepinfoen before_deps[] = {{x1id, 0, 0}, {-1, 0, 0}}; - check_dir_dep(dir, before_deps); - // Now break the reverse dependency by deleting x1 (the file, // not the directory entry) std::string x1FileName; @@ -437,50 +476,21 @@ int test(int argc, const char *argv[]) RaidFileWrite deleteX1(discSetNum, x1FileName); deleteX1.Delete(); - // Check the store, check that the error is detected and - // repaired, by removing x1 from the directory. - BackupStoreCheck check(storeRoot, discSetNum, - 0x01234567 /* AccountID */, true /* FixErrors */, - false /* Quiet */); - check.Check(); - - // Read the directory back in, check that it's empty - file = RaidFileRead::Open(discSetNum, rootDirName); - dir.ReadFromStream(*file, IOStream::TimeOutInfinite); dir_en_check after_entries[] = {{-1, 0, 0}}; - check_dir(dir, after_entries); static checkdepinfoen after_deps[] = {{-1, 0, 0}}; - check_dir_dep(dir, after_deps); + check_and_fix_root_dir(after_entries, after_deps); } - BOX_INFO("Test that an entry pointing to another that doesn't exist " - "is really deleted"); + BOX_INFO(" === Test that an entry pointing to another that doesn't " + "exist is really deleted"); { - // Check that the initial situation matches our expectations. - std::string rootDirName; - StoreStructure::MakeObjectFilename(1 /* root */, storeRoot, - discSetNum, rootDirName, - true /* EnsureDirectoryExists */); - std::auto_ptr<RaidFileRead> file(RaidFileRead::Open(discSetNum, - rootDirName)); - - file = RaidFileRead::Open(discSetNum, rootDirName); - BackupStoreDirectory dir; - dir.ReadFromStream(*file, IOStream::TimeOutInfinite); - dir_en_check start_entries[] = {{-1, 0, 0}}; - check_dir(dir, start_entries); - static checkdepinfoen start_deps[] = {{-1, 0, 0}}; - check_dir_dep(dir, start_deps); - BackupStoreContext ctx(0x01234567, *(HousekeepingInterface *)NULL, "test" /* rConnectionDetails */); ctx.SetClientHasAccount(storeRoot, discSetNum); - BackupProtocolLocal client(ctx); - client.QueryVersion(BACKUP_STORE_SERVER_VERSION); - client.QueryLogin(0x01234567, 0 /* read/write */); + login_client_and_check_empty(client); std::string file_path = "testfiles/TestDir1/cannes/ict/metegoguered/oats"; int x1id = fake_upload(client, file_path, 0); @@ -492,11 +502,6 @@ int test(int argc, const char *argv[]) fs.Close(); int x1aid = fake_upload(client, file_path, x1id); - file = RaidFileRead::Open(discSetNum, rootDirName); - dir.ReadFromStream(*file, IOStream::TimeOutInfinite); - - // Everything should be OK at the moment - TEST_THAT(dir.CheckAndFix() == false); // Check that we've ended up with the right preconditions // for the tests below. @@ -506,10 +511,9 @@ int test(int argc, const char *argv[]) {0, x1aid, BackupStoreDirectory::Entry::Flags_File}, {-1, 0, 0} }; - check_dir(dir, before_entries); static checkdepinfoen before_deps[] = {{x1id, x1aid, 0}, {x1aid, 0, x1id}, {-1, 0, 0}}; - check_dir_dep(dir, before_deps); + check_root_dir_ok(before_entries, before_deps); // Now break the reverse dependency by deleting x1a (the file, // not the directory entry) @@ -519,24 +523,14 @@ int test(int argc, const char *argv[]) RaidFileWrite deleteX1a(discSetNum, x1aFileName); deleteX1a.Delete(); - // Check the store, check that the error is detected and - // repaired, by removing x1 from the directory. - BackupStoreCheck check(storeRoot, discSetNum, - 0x01234567 /* AccountID */, true /* FixErrors */, - false /* Quiet */); - check.Check(); - - // Read the directory back in, check that it's empty - file = RaidFileRead::Open(discSetNum, rootDirName); - dir.ReadFromStream(*file, IOStream::TimeOutInfinite); + // Check and fix the directory, and check that it's left empty dir_en_check after_entries[] = {{-1, 0, 0}}; - check_dir(dir, after_entries); static checkdepinfoen after_deps[] = {{-1, 0, 0}}; - check_dir_dep(dir, after_deps); + check_and_fix_root_dir(after_entries, after_deps); } // Start the bbstored server - BOX_TRACE("Starting bbstored server: " BBSTORED + BOX_TRACE(" === Starting bbstored server: " BBSTORED " testfiles/bbstored.conf"); int bbstored_pid = LaunchServer(BBSTORED " testfiles/bbstored.conf", "testfiles/bbstored.pid"); @@ -571,27 +565,27 @@ int test(int argc, const char *argv[]) TestRemoteProcessMemLeaks("bbackupd.memleaks"); #endif - // Add a reference to a file that doesn't exist, check that it's removed + BOX_INFO(" === Add a reference to a file that doesn't exist, check " + "that it's removed"); { + BackupStoreDirectory dir; + read_bb_dir(1 /* root */, dir); + + dir.AddEntry(fnames[0], 12, 0x1234567890123456LL /* id */, 1, + BackupStoreDirectory::Entry::Flags_File, 2); + std::string fn; StoreStructure::MakeObjectFilename(1 /* root */, storeRoot, discSetNum, fn, true /* EnsureDirectoryExists */); std::auto_ptr<RaidFileRead> file(RaidFileRead::Open(discSetNum, fn)); - BackupStoreDirectory dir; - dir.ReadFromStream(*file, IOStream::TimeOutInfinite); - - dir.AddEntry(fnames[0], 12, 0x1234567890123456LL /* id */, 1, - BackupStoreDirectory::Entry::Flags_File, 2); - RaidFileWrite d(discSetNum, fn); d.Open(true /* allow overwrite */); dir.WriteToStream(d); d.Commit(true /* write now! */); - file = RaidFileRead::Open(discSetNum, fn); - dir.ReadFromStream(*file, IOStream::TimeOutInfinite); + read_bb_dir(1 /* root */, dir); TEST_THAT(dir.FindEntryByID(0x1234567890123456LL) != 0); // Check it @@ -603,7 +597,7 @@ int test(int argc, const char *argv[]) // how good the checker is (or will become) at spotting errors! // But this will help us catch changes in checker behaviour, // so it's not a bad thing to test. - TEST_EQUAL(5, checker.GetNumErrorsFound()); + TEST_EQUAL(2, checker.GetNumErrorsFound()); file = RaidFileRead::Open(discSetNum, fn); dir.ReadFromStream(*file, IOStream::TimeOutInfinite); @@ -639,7 +633,7 @@ int test(int argc, const char *argv[]) } // ------------------------------------------------------------------------------------------------ - ::printf(" === Delete store info, add random file\n"); + BOX_INFO(" === Delete store info, add random file"); { // Delete store info RaidFileWrite del(discSetNum, storeRoot + "info"); @@ -667,7 +661,8 @@ int test(int argc, const char *argv[]) } // ------------------------------------------------------------------------------------------------ - ::printf(" === Delete an entry for an object from dir, change that object to be a patch, check it's deleted\n"); + BOX_INFO(" === Delete an entry for an object from dir, change that " + "object to be a patch, check it's deleted"); { // Open dir and find entry int64_t delID = getID("Test1/cannes/ict/metegoguered/oats"); @@ -729,7 +724,8 @@ int test(int argc, const char *argv[]) } // ------------------------------------------------------------------------------------------------ - ::printf(" === Delete directory, change container ID of another, duplicate entry in dir, spurious file size, delete file\n"); + BOX_INFO(" === Delete directory, change container ID of another, " + "duplicate entry in dir, spurious file size, delete file"); { BackupStoreDirectory dir; LoadDirectory("Test1/foreomizes/stemptinevidate/ict", dir); @@ -766,7 +762,33 @@ int test(int argc, const char *argv[]) // Delete a file DeleteObject("Test1/cannes/ict/scely"); // Fix it - RUN_CHECK + { + // Check it + BackupStoreCheck checker(storeRoot, discSetNum, + 0x01234567, true /* FixErrors */, false /* Quiet */); + checker.Check(); + + // Should just be greater than 1 really, we don't know quite + // how good the checker is (or will become) at spotting errors! + // But this will help us catch changes in checker behaviour, + // so it's not a bad thing to test. + + // The 11 errors are: + // ERROR: Directory ID 0xb references object 0x3e which does not exist. + // ERROR: Removing directory entry 0x3e from directory 0xb + // ERROR: Directory ID 0xc had invalid entries, fixed + // ERROR: Directory ID 0xc has wrong size for object 0x40 + // ERROR: Directory ID 0x17 has wrong container ID. + // ERROR: Object 0x51 is unattached. + // ERROR: Object 0x52 is unattached. + // ERROR: BlocksUsed changed from 282 to 278 + // ERROR: BlocksInCurrentFiles changed from 226 to 220 + // ERROR: BlocksInDirectories changed from 56 to 54 + // ERROR: NumFiles changed from 113 to 110 + + TEST_EQUAL(11, checker.GetNumErrorsFound()); + } + // Check everything is as it should be TEST_THAT(::system(PERL_EXECUTABLE " testfiles/testbackupstorefix.pl check 2") == 0); @@ -800,7 +822,8 @@ int test(int argc, const char *argv[]) } // ------------------------------------------------------------------------------------------------ - ::printf(" === Modify the obj ID of dir, delete dir with no members, add extra reference to a file\n"); + BOX_INFO(" === Modify the obj ID of dir, delete dir with no members, " + "add extra reference to a file"); // Set bad object ID { BackupStoreDirectory dir; @@ -834,7 +857,7 @@ int test(int argc, const char *argv[]) } // ------------------------------------------------------------------------------------------------ - ::printf(" === Orphan files and dirs without being recoverable\n"); + BOX_INFO(" === Orphan files and dirs without being recoverable"); DeleteObject("Test1/dir1"); DeleteObject("Test1/dir1/dir2"); // Fix it @@ -844,7 +867,7 @@ int test(int argc, const char *argv[]) " testfiles/testbackupstorefix.pl check 4") == 0); // ------------------------------------------------------------------------------------------------ - ::printf(" === Corrupt file and dir\n"); + BOX_INFO(" === Corrupt file and dir"); // File CorruptObject("Test1/foreomizes/stemptinevidate/algoughtnerge", 33, "34i729834298349283479233472983sdfhasgs"); @@ -858,7 +881,7 @@ int test(int argc, const char *argv[]) " testfiles/testbackupstorefix.pl check 5") == 0); // ------------------------------------------------------------------------------------------------ - ::printf(" === Overwrite root with a file\n"); + BOX_INFO(" === Overwrite root with a file"); { std::auto_ptr<RaidFileRead> r(RaidFileRead::Open(discSetNum, getObjectName(getID("Test1/pass/shuted/brightinats/milamptimaskates")))); RaidFileWrite w(discSetNum, getObjectName(1 /* root */)); |