diff options
Diffstat (limited to 'lib/backupstore/BackupStoreCheck2.cpp')
-rw-r--r-- | lib/backupstore/BackupStoreCheck2.cpp | 271 |
1 files changed, 171 insertions, 100 deletions
diff --git a/lib/backupstore/BackupStoreCheck2.cpp b/lib/backupstore/BackupStoreCheck2.cpp index 9c6f2452..bcb5c5e9 100644 --- a/lib/backupstore/BackupStoreCheck2.cpp +++ b/lib/backupstore/BackupStoreCheck2.cpp @@ -95,6 +95,21 @@ void BackupStoreCheck::CreateBlankDirectory(int64_t DirectoryID, int64_t Contain mBlocksInDirectories += size; } +class BackupStoreDirectoryFixer +{ + private: + BackupStoreDirectory mDirectory; + std::string mFilename; + std::string mStoreRoot; + int mDiscSetNumber; + + public: + BackupStoreDirectoryFixer(std::string storeRoot, int discSetNumber, + int64_t ID); + void InsertObject(int64_t ObjectID, bool IsDirectory, + int32_t lostDirNameSerial); + ~BackupStoreDirectoryFixer(); +}; // -------------------------------------------------------------------------- // @@ -106,6 +121,10 @@ void BackupStoreCheck::CreateBlankDirectory(int64_t DirectoryID, int64_t Contain // -------------------------------------------------------------------------- void BackupStoreCheck::CheckUnattachedObjects() { + typedef std::map<int64_t, BackupStoreDirectoryFixer*> fixers_t; + typedef std::pair<int64_t, BackupStoreDirectoryFixer*> fixer_pair_t; + fixers_t fixers; + // Scan all objects, finding ones which have no container for(Info_t::const_iterator i(mInfo.begin()); i != mInfo.end(); ++i) { @@ -118,7 +137,9 @@ void BackupStoreCheck::CheckUnattachedObjects() if((flags & Flags_IsContained) == 0) { // Unattached object... - BOX_WARNING("Object " << BOX_FORMAT_OBJECTID(pblock->mID[e]) << " is unattached."); + BOX_WARNING("Object " << + BOX_FORMAT_OBJECTID(pblock->mID[e]) << + " is unattached."); ++mNumberErrorsFound; // What's to be done? @@ -196,14 +217,50 @@ void BackupStoreCheck::CheckUnattachedObjects() } ASSERT(putIntoDirectoryID != 0); + if (!mFixErrors) + { + continue; + } + + BackupStoreDirectoryFixer* pFixer; + fixers_t::iterator fi = + fixers.find(putIntoDirectoryID); + if (fi == fixers.end()) + { + // no match, create a new one + pFixer = new BackupStoreDirectoryFixer( + mStoreRoot, mDiscSetNumber, + putIntoDirectoryID); + fixers.insert(fixer_pair_t( + putIntoDirectoryID, pFixer)); + } + else + { + pFixer = fi->second; + } + + int32_t lostDirNameSerial = 0; + + if(flags & Flags_IsDir) + { + lostDirNameSerial = mLostDirNameSerial++; + } + // Add it to the directory - InsertObjectIntoDirectory(pblock->mID[e], putIntoDirectoryID, - ((flags & Flags_IsDir) == Flags_IsDir)); + pFixer->InsertObject(pblock->mID[e], + ((flags & Flags_IsDir) == Flags_IsDir), + lostDirNameSerial); } } } -} + // clean up all the fixers. Deleting them commits them automatically. + for (fixers_t::iterator i = fixers.begin(); i != fixers.end(); i++) + { + BackupStoreDirectoryFixer* pFixer = i->second; + delete pFixer; + } +} // -------------------------------------------------------------------------- // @@ -261,6 +318,86 @@ bool BackupStoreCheck::TryToRecreateDirectory(int64_t MissingDirectoryID) return true; } +BackupStoreDirectoryFixer::BackupStoreDirectoryFixer(std::string storeRoot, + int discSetNumber, int64_t ID) +: mStoreRoot(storeRoot), + mDiscSetNumber(discSetNumber) +{ + // Generate filename + StoreStructure::MakeObjectFilename(ID, mStoreRoot, mDiscSetNumber, + mFilename, false /* don't make sure the dir exists */); + + // Read it in + std::auto_ptr<RaidFileRead> file( + RaidFileRead::Open(mDiscSetNumber, mFilename)); + mDirectory.ReadFromStream(*file, IOStream::TimeOutInfinite); +} + +void BackupStoreDirectoryFixer::InsertObject(int64_t ObjectID, bool IsDirectory, + int32_t lostDirNameSerial) +{ + // Data for the object + BackupStoreFilename objectStoreFilename; + int64_t modTime = 100; // something which isn't zero or a special time + int32_t sizeInBlocks = 0; // suitable for directories + + if(IsDirectory) + { + // Directory -- simply generate a name for it. + char name[32]; + ::sprintf(name, "dir%08x", lostDirNameSerial); + objectStoreFilename.SetAsClearFilename(name); + } + else + { + // Files require a little more work... + // Open file + std::string fileFilename; + StoreStructure::MakeObjectFilename(ObjectID, mStoreRoot, + mDiscSetNumber, fileFilename, + false /* don't make sure the dir exists */); + std::auto_ptr<RaidFileRead> file( + RaidFileRead::Open(mDiscSetNumber, fileFilename)); + + // Fill in size information + sizeInBlocks = file->GetDiscUsageInBlocks(); + + // Read in header + file_StreamFormat hdr; + if(file->Read(&hdr, sizeof(hdr)) != sizeof(hdr) || + (ntohl(hdr.mMagicValue) != OBJECTMAGIC_FILE_MAGIC_VALUE_V1 +#ifndef BOX_DISABLE_BACKWARDS_COMPATIBILITY_BACKUPSTOREFILE + && ntohl(hdr.mMagicValue) != OBJECTMAGIC_FILE_MAGIC_VALUE_V0 +#endif + )) + { + // This should never happen, everything has been + // checked before. + THROW_EXCEPTION(BackupStoreException, Internal) + } + // This tells us nice things + modTime = box_ntoh64(hdr.mModificationTime); + // And the filename comes next + objectStoreFilename.ReadFromStream(*file, IOStream::TimeOutInfinite); + } + + // Add a new entry in an appropriate place + mDirectory.AddUnattactedObject(objectStoreFilename, modTime, + ObjectID, sizeInBlocks, + IsDirectory?(BackupStoreDirectory::Entry::Flags_Dir):(BackupStoreDirectory::Entry::Flags_File)); +} + +BackupStoreDirectoryFixer::~BackupStoreDirectoryFixer() +{ + // Fix any flags which have been broken, which there's a good chance of doing + mDirectory.CheckAndFix(); + + // Write it out + RaidFileWrite root(mDiscSetNumber, mFilename); + root.Open(true /* allow overwriting */); + mDirectory.WriteToStream(root); + root.Commit(true /* convert to raid now */); +} // -------------------------------------------------------------------------- // @@ -335,91 +472,6 @@ int64_t BackupStoreCheck::GetLostAndFoundDirID() // -------------------------------------------------------------------------- // // Function -// Name: BackupStoreCheck::InsertObjectIntoDirectory(int64_t, int64_t, bool) -// Purpose: -// Created: 22/4/04 -// -// -------------------------------------------------------------------------- -void BackupStoreCheck::InsertObjectIntoDirectory(int64_t ObjectID, int64_t DirectoryID, bool IsDirectory) -{ - if(!mFixErrors) - { - // Don't do anything if we're not supposed to fix errors - return; - } - - // Data for the object - BackupStoreFilename objectStoreFilename; - int64_t modTime = 100; // something which isn't zero or a special time - int32_t sizeInBlocks = 0; // suitable for directories - - if(IsDirectory) - { - // Directory -- simply generate a name for it. - char name[32]; - ::sprintf(name, "dir%08x", mLostDirNameSerial++); - objectStoreFilename.SetAsClearFilename(name); - } - else - { - // Files require a little more work... - // Open file - std::string fileFilename; - StoreStructure::MakeObjectFilename(ObjectID, mStoreRoot, mDiscSetNumber, fileFilename, false /* don't make sure the dir exists */); - std::auto_ptr<RaidFileRead> file(RaidFileRead::Open(mDiscSetNumber, fileFilename)); - // Fill in size information - sizeInBlocks = file->GetDiscUsageInBlocks(); - // Read in header - file_StreamFormat hdr; - if(file->Read(&hdr, sizeof(hdr)) != sizeof(hdr) || (ntohl(hdr.mMagicValue) != OBJECTMAGIC_FILE_MAGIC_VALUE_V1 -#ifndef BOX_DISABLE_BACKWARDS_COMPATIBILITY_BACKUPSTOREFILE - && ntohl(hdr.mMagicValue) != OBJECTMAGIC_FILE_MAGIC_VALUE_V0 -#endif - )) - { - // This should never happen, everything has been checked before. - THROW_EXCEPTION(BackupStoreException, Internal) - } - // This tells us nice things - modTime = box_ntoh64(hdr.mModificationTime); - // And the filename comes next - objectStoreFilename.ReadFromStream(*file, IOStream::TimeOutInfinite); - } - - // Directory object - BackupStoreDirectory dir; - - // Generate filename - std::string filename; - StoreStructure::MakeObjectFilename(DirectoryID, mStoreRoot, mDiscSetNumber, filename, false /* don't make sure the dir exists */); - - // Read it in - { - std::auto_ptr<RaidFileRead> file(RaidFileRead::Open(mDiscSetNumber, filename)); - dir.ReadFromStream(*file, IOStream::TimeOutInfinite); - } - - // Add a new entry in an appropraite place - dir.AddUnattactedObject(objectStoreFilename, modTime, ObjectID, sizeInBlocks, - IsDirectory?(BackupStoreDirectory::Entry::Flags_Dir):(BackupStoreDirectory::Entry::Flags_File)); - - // Fix any flags which have been broken, which there's a good change of going - dir.CheckAndFix(); - - // Write it out - if(mFixErrors) - { - RaidFileWrite root(mDiscSetNumber, filename); - root.Open(true /* allow overwriting */); - dir.WriteToStream(root); - root.Commit(true /* convert to raid now */); - } -} - - -// -------------------------------------------------------------------------- -// -// Function // Name: BackupStoreCheck::FixDirsWithWrongContainerID() // Purpose: Rewrites container IDs where required // Created: 22/4/04 @@ -594,6 +646,8 @@ void BackupStoreCheck::WriteNewStoreInfo() } } +#define FMT_OID(x) BOX_FORMAT_OBJECTID(x) +#define FMT_i BOX_FORMAT_OBJECTID((*i)->GetObjectID()) // -------------------------------------------------------------------------- // @@ -620,7 +674,11 @@ bool BackupStoreDirectory::CheckAndFix() if(newerEn == 0) { // Depends on something, but it isn't there. - TRACE2("Entry id %llx removed because depends on newer version %llx which doesn't exist\n", (*i)->GetObjectID(), dependsNewer); + BOX_TRACE("Entry id " << FMT_i << + " removed because depends " + "on newer version " << + FMT_OID(dependsNewer) << + " which doesn't exist"); // Remove delete *i; @@ -638,7 +696,12 @@ bool BackupStoreDirectory::CheckAndFix() if(newerEn->GetDependsOlder() != (*i)->GetObjectID()) { // Wrong entry - TRACE3("Entry id %llx, correcting DependsOlder to %llx, was %llx\n", dependsNewer, (*i)->GetObjectID(), newerEn->GetDependsOlder()); + BOX_TRACE("Entry id " << + FMT_OID(dependsNewer) << + ", correcting DependsOlder to " << + FMT_i << + ", was " << + FMT_OID(newerEn->GetDependsOlder())); newerEn->SetDependsOlder((*i)->GetObjectID()); // Mark as changed changed = true; @@ -657,7 +720,11 @@ bool BackupStoreDirectory::CheckAndFix() if(dependsOlder != 0 && FindEntryByID(dependsOlder) == 0) { // Has an older version marked, but this doesn't exist. Remove this mark - TRACE2("Entry id %llx was marked that %llx depended on it, which doesn't exist, dependency info cleared\n", (*i)->GetObjectID(), dependsOlder); + BOX_TRACE("Entry id " << FMT_i << + " was marked as depended on by " << + FMT_OID(dependsOlder) << ", " + "which doesn't exist, dependency " + "info cleared"); (*i)->SetDependsOlder(0); @@ -683,7 +750,7 @@ bool BackupStoreDirectory::CheckAndFix() // Records of things seen std::set<int64_t> idsEncountered; - std::set<BackupStoreFilename> filenamesEncountered; + std::set<std::string> filenamesEncountered; do { @@ -693,7 +760,7 @@ bool BackupStoreDirectory::CheckAndFix() bool removeEntry = false; if((*i) == 0) { - TRACE0("Remove because null pointer found\n"); + BOX_TRACE("Remove because null pointer found"); removeEntry = true; } else @@ -704,7 +771,8 @@ bool BackupStoreDirectory::CheckAndFix() if(isDir && (((*i)->GetFlags() & Entry::Flags_File) == Entry::Flags_File)) { // Bad! Unset the file flag - TRACE1("Entry %llx: File flag set when dir flag set\n", (*i)->GetObjectID()); + BOX_TRACE("Entry " << FMT_i << + ": File flag and dir flag both set"); (*i)->RemoveFlags(Entry::Flags_File); changed = true; } @@ -713,7 +781,8 @@ bool BackupStoreDirectory::CheckAndFix() if(idsEncountered.find((*i)->GetObjectID()) != idsEncountered.end()) { // ID already seen, or type doesn't match - TRACE1("Entry %llx: Remove because ID already seen\n", (*i)->GetObjectID()); + BOX_TRACE("Entry " << FMT_i << + ": Remove because ID already seen"); removeEntry = true; } else @@ -723,14 +792,15 @@ bool BackupStoreDirectory::CheckAndFix() // Check to see if the name has already been encountered -- if not, then it // needs to have the old version flag set - if(filenamesEncountered.find((*i)->GetName()) != filenamesEncountered.end()) + if(filenamesEncountered.find((*i)->GetName().GetEncodedFilename()) != filenamesEncountered.end()) { // Seen before -- check old version flag set if(((*i)->GetFlags() & Entry::Flags_OldVersion) != Entry::Flags_OldVersion && ((*i)->GetFlags() & Entry::Flags_Deleted) == 0) { // Not set, set it - TRACE1("Entry %llx: Set old flag\n", (*i)->GetObjectID()); + BOX_TRACE("Entry " << FMT_i << + ": Set old flag"); (*i)->AddFlags(Entry::Flags_OldVersion); changed = true; } @@ -741,13 +811,14 @@ bool BackupStoreDirectory::CheckAndFix() if(((*i)->GetFlags() & Entry::Flags_OldVersion) == Entry::Flags_OldVersion) { // Set, unset it - TRACE1("Entry %llx: Old flag unset\n", (*i)->GetObjectID()); + BOX_TRACE("Entry " << FMT_i << + ": Old flag unset"); (*i)->RemoveFlags(Entry::Flags_OldVersion); changed = true; } // Remember filename - filenamesEncountered.insert((*i)->GetName()); + filenamesEncountered.insert((*i)->GetName().GetEncodedFilename()); } } } |