summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/backupstore/BackupStoreCheck.cpp253
-rw-r--r--lib/backupstore/BackupStoreCheckData.cpp9
-rw-r--r--test/backupstorefix/testbackupstorefix.cpp239
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 */));