diff options
-rw-r--r-- | lib/backupstore/BackupStoreContext.cpp | 94 | ||||
-rw-r--r-- | lib/backupstore/BackupStoreContext.h | 3 | ||||
-rw-r--r-- | lib/backupstore/BackupStoreDirectory.cpp | 39 | ||||
-rw-r--r-- | lib/backupstore/BackupStoreDirectory.h | 265 |
4 files changed, 326 insertions, 75 deletions
diff --git a/lib/backupstore/BackupStoreContext.cpp b/lib/backupstore/BackupStoreContext.cpp index 393dc0d2..3769344b 100644 --- a/lib/backupstore/BackupStoreContext.cpp +++ b/lib/backupstore/BackupStoreContext.cpp @@ -30,13 +30,14 @@ #include "MemLeakFindOn.h" -// Maximum number of directories to keep in the cache -// When the cache is bigger than this, everything gets -// deleted. +// Maximum number of directories to keep in the cache When the cache is bigger +// than this, everything gets deleted. In tests, we set the cache size to zero +// to ensure that it's always flushed, which is very inefficient but helps to +// catch programming errors (use of freed data). #ifdef BOX_RELEASE_BUILD #define MAX_CACHE_SIZE 32 #else - #define MAX_CACHE_SIZE 2 + #define MAX_CACHE_SIZE 0 #endif // Allow the housekeeping process 4 seconds to release an account @@ -292,15 +293,21 @@ void BackupStoreContext::MakeObjectFilename(int64_t ObjectID, std::string &rOutp // -------------------------------------------------------------------------- // // Function -// Name: BackupStoreContext::GetDirectoryInternal(int64_t) -// Purpose: Return a reference to a directory. Valid only until the -// next time a function which affects directories is called. -// Mainly this funciton, and creation of files. -// Private version of this, which returns non-const directories. +// Name: BackupStoreContext::GetDirectoryInternal(int64_t, +// bool) +// Purpose: Return a reference to a directory. Valid only until +// the next time a function which affects directories +// is called. Mainly this function, and creation of +// files. Private version of this, which returns +// non-const directories. Unless called with +// AllowFlushCache == false, the cache may be flushed, +// invalidating all directory references that you may +// be holding, so beware. // Created: 2003/09/02 // // -------------------------------------------------------------------------- -BackupStoreDirectory &BackupStoreContext::GetDirectoryInternal(int64_t ObjectID) +BackupStoreDirectory &BackupStoreContext::GetDirectoryInternal(int64_t ObjectID, + bool AllowFlushCache) { // Get the filename std::string filename; @@ -309,23 +316,30 @@ BackupStoreDirectory &BackupStoreContext::GetDirectoryInternal(int64_t ObjectID) // Already in cache? std::map<int64_t, BackupStoreDirectory*>::iterator item(mDirectoryCache.find(ObjectID)); - if(item != mDirectoryCache.end()) - { - oldRevID = item->second->GetRevisionID(); - - // Check the revision ID of the file -- does it need refreshing? - if(!RaidFileRead::FileExists(mStoreDiscSet, filename, &newRevID)) - { - THROW_EXCEPTION(BackupStoreException, DirectoryHasBeenDeleted) - } - - if(newRevID == oldRevID) + if(item != mDirectoryCache.end()) { +#ifndef BOX_RELEASE_BUILD // it might be in the cache, but invalidated + // in which case, delete it instead of returning it. + if(!item->second->IsInvalidated()) +#else + if(true) +#endif { - // Looks good... return the cached object - BOX_TRACE("Returning object " << - BOX_FORMAT_OBJECTID(ObjectID) << - " from cache, modtime = " << newRevID) - return *(item->second); + oldRevID = item->second->GetRevisionID(); + + // Check the revision ID of the file -- does it need refreshing? + if(!RaidFileRead::FileExists(mStoreDiscSet, filename, &newRevID)) + { + THROW_EXCEPTION(BackupStoreException, DirectoryHasBeenDeleted) + } + + if(newRevID == oldRevID) + { + // Looks good... return the cached object + BOX_TRACE("Returning object " << + BOX_FORMAT_OBJECTID(ObjectID) << + " from cache, modtime = " << newRevID) + return *(item->second); + } } // Delete this cached object @@ -336,10 +350,22 @@ BackupStoreDirectory &BackupStoreContext::GetDirectoryInternal(int64_t ObjectID) // Need to load it up // First check to see if the cache is too big - if(mDirectoryCache.size() > MAX_CACHE_SIZE) + if(mDirectoryCache.size() > MAX_CACHE_SIZE && AllowFlushCache) { - // Very simple. Just delete everything! + // Very simple. Just delete everything! But in debug builds, + // leave the entries in the cache and invalidate them instead, + // so that any attempt to access them will cause an assertion + // failure that helps to track down the error. +#ifdef BOX_RELEASE_BUILD ClearDirectoryCache(); +#else + for(std::map<int64_t, BackupStoreDirectory*>::iterator + i = mDirectoryCache.begin(); + i != mDirectoryCache.end(); i++) + { + i->second->Invalidate(); + } +#endif } // Get a RaidFileRead to read it @@ -1022,18 +1048,20 @@ void BackupStoreContext::SaveDirectory(BackupStoreDirectory &rDir) // that it reflects the current size of the parent directory. int64_t new_dir_size = rDir.GetUserInfo1_SizeInBlocks(); if(new_dir_size != old_dir_size && - rDir.GetObjectID() != BACKUPSTORE_ROOT_DIRECTORY_ID) + ObjectID != BACKUPSTORE_ROOT_DIRECTORY_ID) { + int64_t ContainerID = rDir.GetContainerID(); BackupStoreDirectory& parent( - GetDirectoryInternal(rDir.GetContainerID())); + GetDirectoryInternal(ContainerID)); + // rDir is now invalid BackupStoreDirectory::Entry* en = - parent.FindEntryByID(rDir.GetObjectID()); + parent.FindEntryByID(ObjectID); if(!en) { BOX_ERROR("Missing entry for directory " << - BOX_FORMAT_OBJECTID(rDir.GetObjectID()) << + BOX_FORMAT_OBJECTID(ObjectID) << " in directory " << - BOX_FORMAT_OBJECTID(rDir.GetContainerID()) << + BOX_FORMAT_OBJECTID(ContainerID) << " while trying to update dir size in parent"); } else diff --git a/lib/backupstore/BackupStoreContext.h b/lib/backupstore/BackupStoreContext.h index ffbc1e96..21488526 100644 --- a/lib/backupstore/BackupStoreContext.h +++ b/lib/backupstore/BackupStoreContext.h @@ -176,7 +176,8 @@ public: private: void MakeObjectFilename(int64_t ObjectID, std::string &rOutput, bool EnsureDirectoryExists = false); - BackupStoreDirectory &GetDirectoryInternal(int64_t ObjectID); + BackupStoreDirectory &GetDirectoryInternal(int64_t ObjectID, + bool AllowFlushCache = true); void SaveDirectory(BackupStoreDirectory &rDir); void RemoveDirectoryFromCache(int64_t ObjectID); void ClearDirectoryCache(); diff --git a/lib/backupstore/BackupStoreDirectory.cpp b/lib/backupstore/BackupStoreDirectory.cpp index 37957770..332eca7a 100644 --- a/lib/backupstore/BackupStoreDirectory.cpp +++ b/lib/backupstore/BackupStoreDirectory.cpp @@ -75,7 +75,15 @@ END_STRUCTURE_PACKING_FOR_WIRE // // -------------------------------------------------------------------------- BackupStoreDirectory::BackupStoreDirectory() - : mRevisionID(0), mObjectID(0), mContainerID(0), mAttributesModTime(0), mUserInfo1(0) +: +#ifndef BOX_RELEASE_BUILD + mInvalidated(false), +#endif + mRevisionID(0), + mObjectID(0), + mContainerID(0), + mAttributesModTime(0), + mUserInfo1(0) { ASSERT(sizeof(u_int64_t) == sizeof(box_time_t)); } @@ -90,7 +98,15 @@ BackupStoreDirectory::BackupStoreDirectory() // // -------------------------------------------------------------------------- BackupStoreDirectory::BackupStoreDirectory(int64_t ObjectID, int64_t ContainerID) - : mRevisionID(0), mObjectID(ObjectID), mContainerID(ContainerID), mAttributesModTime(0), mUserInfo1(0) +: +#ifndef BOX_RELEASE_BUILD + mInvalidated(false), +#endif + mRevisionID(0), + mObjectID(ObjectID), + mContainerID(ContainerID), + mAttributesModTime(0), + mUserInfo1(0) { } @@ -122,6 +138,7 @@ BackupStoreDirectory::~BackupStoreDirectory() // -------------------------------------------------------------------------- void BackupStoreDirectory::ReadFromStream(IOStream &rStream, int Timeout) { + ASSERT(!mInvalidated); // Compiled out of release builds // Get the header dir_StreamFormat hdr; if(!rStream.ReadFullBuffer(&hdr, sizeof(hdr), 0 /* not interested in bytes read if this fails */, Timeout)) @@ -202,6 +219,7 @@ void BackupStoreDirectory::ReadFromStream(IOStream &rStream, int Timeout) // -------------------------------------------------------------------------- void BackupStoreDirectory::WriteToStream(IOStream &rStream, int16_t FlagsMustBeSet, int16_t FlagsNotToBeSet, bool StreamAttributes, bool StreamDependencyInfo) const { + ASSERT(!mInvalidated); // Compiled out of release builds // Get count of entries int32_t count = mEntries.size(); if(FlagsMustBeSet != Entry::Flags_INCLUDE_EVERYTHING || FlagsNotToBeSet != Entry::Flags_EXCLUDE_NOTHING) @@ -291,6 +309,7 @@ void BackupStoreDirectory::WriteToStream(IOStream &rStream, int16_t FlagsMustBeS // -------------------------------------------------------------------------- BackupStoreDirectory::Entry *BackupStoreDirectory::AddEntry(const Entry &rEntryToCopy) { + ASSERT(!mInvalidated); // Compiled out of release builds Entry *pnew = new Entry(rEntryToCopy); try { @@ -318,6 +337,7 @@ BackupStoreDirectory::AddEntry(const BackupStoreFilename &rName, box_time_t ModificationTime, int64_t ObjectID, int64_t SizeInBlocks, int16_t Flags, uint64_t AttributesHash) { + ASSERT(!mInvalidated); // Compiled out of release builds Entry *pnew = new Entry(rName, ModificationTime, ObjectID, SizeInBlocks, Flags, AttributesHash); try @@ -343,6 +363,7 @@ BackupStoreDirectory::AddEntry(const BackupStoreFilename &rName, // -------------------------------------------------------------------------- void BackupStoreDirectory::DeleteEntry(int64_t ObjectID) { + ASSERT(!mInvalidated); // Compiled out of release builds for(std::vector<Entry*>::iterator i(mEntries.begin()); i != mEntries.end(); ++i) { @@ -374,6 +395,7 @@ void BackupStoreDirectory::DeleteEntry(int64_t ObjectID) // -------------------------------------------------------------------------- BackupStoreDirectory::Entry *BackupStoreDirectory::FindEntryByID(int64_t ObjectID) const { + ASSERT(!mInvalidated); // Compiled out of release builds for(std::vector<Entry*>::const_iterator i(mEntries.begin()); i != mEntries.end(); ++i) { @@ -399,6 +421,9 @@ BackupStoreDirectory::Entry *BackupStoreDirectory::FindEntryByID(int64_t ObjectI // -------------------------------------------------------------------------- BackupStoreDirectory::Entry::Entry() : +#ifndef BOX_RELEASE_BUILD + mInvalidated(false), +#endif mModificationTime(0), mObjectID(0), mSizeInBlocks(0), @@ -433,6 +458,9 @@ BackupStoreDirectory::Entry::~Entry() // -------------------------------------------------------------------------- BackupStoreDirectory::Entry::Entry(const Entry &rToCopy) : +#ifndef BOX_RELEASE_BUILD + mInvalidated(false), +#endif mName(rToCopy.mName), mModificationTime(rToCopy.mModificationTime), mObjectID(rToCopy.mObjectID), @@ -458,6 +486,9 @@ BackupStoreDirectory::Entry::Entry(const Entry &rToCopy) // -------------------------------------------------------------------------- BackupStoreDirectory::Entry::Entry(const BackupStoreFilename &rName, box_time_t ModificationTime, int64_t ObjectID, int64_t SizeInBlocks, int16_t Flags, uint64_t AttributesHash) : +#ifndef BOX_RELEASE_BUILD + mInvalidated(false), +#endif mName(rName), mModificationTime(ModificationTime), mObjectID(ObjectID), @@ -483,6 +514,7 @@ BackupStoreDirectory::Entry::Entry(const BackupStoreFilename &rName, box_time_t // -------------------------------------------------------------------------- void BackupStoreDirectory::Entry::ReadFromStream(IOStream &rStream, int Timeout) { + ASSERT(!mInvalidated); // Compiled out of release builds // Grab the raw bytes from the stream which compose the header en_StreamFormat entry; if(!rStream.ReadFullBuffer(&entry, sizeof(entry), @@ -520,6 +552,7 @@ void BackupStoreDirectory::Entry::ReadFromStream(IOStream &rStream, int Timeout) // -------------------------------------------------------------------------- void BackupStoreDirectory::Entry::WriteToStream(IOStream &rStream) const { + ASSERT(!mInvalidated); // Compiled out of release builds // Build a structure en_StreamFormat entry; entry.mModificationTime = box_hton64(mModificationTime); @@ -549,6 +582,7 @@ void BackupStoreDirectory::Entry::WriteToStream(IOStream &rStream) const // -------------------------------------------------------------------------- void BackupStoreDirectory::Entry::ReadFromStreamDependencyInfo(IOStream &rStream, int Timeout) { + ASSERT(!mInvalidated); // Compiled out of release builds // Grab the raw bytes from the stream which compose the header en_StreamFormatDepends depends; if(!rStream.ReadFullBuffer(&depends, sizeof(depends), 0 /* not interested in bytes read if this fails */, Timeout)) @@ -572,6 +606,7 @@ void BackupStoreDirectory::Entry::ReadFromStreamDependencyInfo(IOStream &rStream // -------------------------------------------------------------------------- void BackupStoreDirectory::Entry::WriteToStreamDependencyInfo(IOStream &rStream) const { + ASSERT(!mInvalidated); // Compiled out of release builds // Build structure en_StreamFormatDepends depends; depends.mDependsNewer = box_hton64(mDependsNewer); diff --git a/lib/backupstore/BackupStoreDirectory.h b/lib/backupstore/BackupStoreDirectory.h index d9811fe5..5bbb0b35 100644 --- a/lib/backupstore/BackupStoreDirectory.h +++ b/lib/backupstore/BackupStoreDirectory.h @@ -29,17 +29,40 @@ class IOStream; // -------------------------------------------------------------------------- class BackupStoreDirectory { +private: +#ifndef BOX_RELEASE_BUILD + bool mInvalidated; +#endif + public: +#ifndef BOX_RELEASE_BUILD + void Invalidate() + { + mInvalidated = true; + for (std::vector<Entry*>::iterator i = mEntries.begin(); + i != mEntries.end(); i++) + { + (*i)->Invalidate(); + } + } +#endif + BackupStoreDirectory(); BackupStoreDirectory(int64_t ObjectID, int64_t ContainerID); // Convenience constructor from a stream BackupStoreDirectory(IOStream& rStream, int Timeout = IOStream::TimeOutInfinite) +#ifndef BOX_RELEASE_BUILD + : mInvalidated(false) +#endif { ReadFromStream(rStream, Timeout); } BackupStoreDirectory(std::auto_ptr<IOStream> apStream, int Timeout = IOStream::TimeOutInfinite) +#ifndef BOX_RELEASE_BUILD + : mInvalidated(false) +#endif { ReadFromStream(*apStream, Timeout); } @@ -51,7 +74,16 @@ public: class Entry { + private: +#ifndef BOX_RELEASE_BUILD + bool mInvalidated; +#endif + public: +#ifndef BOX_RELEASE_BUILD + void Invalidate() { mInvalidated = true; } +#endif + friend class BackupStoreDirectory; Entry(); @@ -61,30 +93,98 @@ public: void ReadFromStream(IOStream &rStream, int Timeout); void WriteToStream(IOStream &rStream) const; - - const BackupStoreFilename &GetName() const {return mName;} - box_time_t GetModificationTime() const {return mModificationTime;} - int64_t GetObjectID() const {return mObjectID;} - int64_t GetSizeInBlocks() const {return mSizeInBlocks;} - int16_t GetFlags() const {return mFlags;} - void AddFlags(int16_t Flags) {mFlags |= Flags;} - void RemoveFlags(int16_t Flags) {mFlags &= ~Flags;} + + const BackupStoreFilename &GetName() const + { + ASSERT(!mInvalidated); // Compiled out of release builds + return mName; + } + box_time_t GetModificationTime() const + { + ASSERT(!mInvalidated); // Compiled out of release builds + return mModificationTime; + } + int64_t GetObjectID() const + { + ASSERT(!mInvalidated); // Compiled out of release builds + return mObjectID; + } + // SetObjectID is dangerous! It should only be used when + // creating a snapshot. + void SetObjectID(int64_t NewObjectID) + { + ASSERT(!mInvalidated); // Compiled out of release builds + mObjectID = NewObjectID; + } + int64_t GetSizeInBlocks() const + { + ASSERT(!mInvalidated); // Compiled out of release builds + return mSizeInBlocks; + } + int16_t GetFlags() const + { + ASSERT(!mInvalidated); // Compiled out of release builds + return mFlags; + } + void AddFlags(int16_t Flags) + { + ASSERT(!mInvalidated); // Compiled out of release builds + mFlags |= Flags; + } + void RemoveFlags(int16_t Flags) + { + ASSERT(!mInvalidated); // Compiled out of release builds + mFlags &= ~Flags; + } // Some things can be changed - void SetName(const BackupStoreFilename &rNewName) {mName = rNewName;} - void SetSizeInBlocks(int64_t SizeInBlocks) {mSizeInBlocks = SizeInBlocks;} + void SetName(const BackupStoreFilename &rNewName) + { + ASSERT(!mInvalidated); // Compiled out of release builds + mName = rNewName; + } + void SetSizeInBlocks(int64_t SizeInBlocks) + { + ASSERT(!mInvalidated); // Compiled out of release builds + mSizeInBlocks = SizeInBlocks; + } // Attributes - bool HasAttributes() const {return !mAttributes.IsEmpty();} - void SetAttributes(const StreamableMemBlock &rAttr, uint64_t AttributesHash) {mAttributes.Set(rAttr); mAttributesHash = AttributesHash;} - const StreamableMemBlock &GetAttributes() const {return mAttributes;} - uint64_t GetAttributesHash() const {return mAttributesHash;} - + bool HasAttributes() const + { + ASSERT(!mInvalidated); // Compiled out of release builds + return !mAttributes.IsEmpty(); + } + void SetAttributes(const StreamableMemBlock &rAttr, uint64_t AttributesHash) + { + ASSERT(!mInvalidated); // Compiled out of release builds + mAttributes.Set(rAttr); + mAttributesHash = AttributesHash; + } + const StreamableMemBlock &GetAttributes() const + { + ASSERT(!mInvalidated); // Compiled out of release builds + return mAttributes; + } + uint64_t GetAttributesHash() const + { + ASSERT(!mInvalidated); // Compiled out of release builds + return mAttributesHash; + } + // Marks // The lowest mark number a version of a file of this name has ever had - uint32_t GetMinMarkNumber() const {return mMinMarkNumber;} + uint32_t GetMinMarkNumber() const + { + ASSERT(!mInvalidated); // Compiled out of release builds + return mMinMarkNumber; + } // The mark number on this file - uint32_t GetMarkNumber() const {return mMarkNumber;} + uint32_t GetMarkNumber() const + { + ASSERT(!mInvalidated); // Compiled out of release builds + return mMarkNumber; + } // Make sure these flags are synced with those in backupprocotol.txt // ListDirectory command @@ -105,36 +205,61 @@ public: // convenience methods bool inline IsDir() { + ASSERT(!mInvalidated); // Compiled out of release builds return GetFlags() & Flags_Dir; } bool inline IsFile() { + ASSERT(!mInvalidated); // Compiled out of release builds return GetFlags() & Flags_File; } bool inline IsOld() { + ASSERT(!mInvalidated); // Compiled out of release builds return GetFlags() & Flags_OldVersion; } bool inline IsDeleted() { + ASSERT(!mInvalidated); // Compiled out of release builds return GetFlags() & Flags_Deleted; } bool inline MatchesFlags(int16_t FlagsMustBeSet, int16_t FlagsNotToBeSet) { + ASSERT(!mInvalidated); // Compiled out of release builds return ((FlagsMustBeSet == Flags_INCLUDE_EVERYTHING) || ((mFlags & FlagsMustBeSet) == FlagsMustBeSet)) && ((mFlags & FlagsNotToBeSet) == 0); }; // Get dependency info // new version this depends on - int64_t GetDependsNewer() const {return mDependsNewer;} - void SetDependsNewer(int64_t ObjectID) {mDependsNewer = ObjectID;} + int64_t GetDependsNewer() const + { + ASSERT(!mInvalidated); // Compiled out of release builds + return mDependsNewer; + } + void SetDependsNewer(int64_t ObjectID) + { + ASSERT(!mInvalidated); // Compiled out of release builds + mDependsNewer = ObjectID; + } // older version which depends on this - int64_t GetDependsOlder() const {return mDependsOlder;} - void SetDependsOlder(int64_t ObjectID) {mDependsOlder = ObjectID;} + int64_t GetDependsOlder() const + { + ASSERT(!mInvalidated); // Compiled out of release builds + return mDependsOlder; + } + void SetDependsOlder(int64_t ObjectID) + { + ASSERT(!mInvalidated); // Compiled out of release builds + mDependsOlder = ObjectID; + } // Dependency info saving - bool HasDependencies() {return mDependsNewer != 0 || mDependsOlder != 0;} + bool HasDependencies() + { + ASSERT(!mInvalidated); // Compiled out of release builds + return mDependsNewer != 0 || mDependsOlder != 0; + } void ReadFromStreamDependencyInfo(IOStream &rStream, int Timeout); void WriteToStreamDependencyInfo(IOStream &rStream) const; @@ -152,7 +277,14 @@ public: uint64_t mDependsNewer; // new version this depends on uint64_t mDependsOlder; // older version which depends on this }; - + +#ifndef BOX_RELEASE_BUILD + bool IsInvalidated() + { + return mInvalidated; + } +#endif // !BOX_RELEASE_BUILD + void ReadFromStream(IOStream &rStream, int Timeout); void WriteToStream(IOStream &rStream, int16_t FlagsMustBeSet = Entry::Flags_INCLUDE_EVERYTHING, @@ -166,28 +298,78 @@ public: uint64_t AttributesHash); void DeleteEntry(int64_t ObjectID); Entry *FindEntryByID(int64_t ObjectID) const; - - int64_t GetObjectID() const {return mObjectID;} - int64_t GetContainerID() const {return mContainerID;} - + + int64_t GetObjectID() const + { + ASSERT(!mInvalidated); // Compiled out of release builds + return mObjectID; + } + + int64_t GetContainerID() const + { + ASSERT(!mInvalidated); // Compiled out of release builds + return mContainerID; + } // Need to be able to update the container ID when moving objects - void SetContainerID(int64_t ContainerID) {mContainerID = ContainerID;} + void SetContainerID(int64_t ContainerID) + { + ASSERT(!mInvalidated); // Compiled out of release builds + mContainerID = ContainerID; + } - // Purely for use of server -- not serialised into streams - int64_t GetRevisionID() const {return mRevisionID;} - void SetRevisionID(int64_t RevisionID) {mRevisionID = RevisionID;} - - unsigned int GetNumberOfEntries() const {return mEntries.size();} + // Purely for use of server -- not serialised into streams + int64_t GetRevisionID() const + { + ASSERT(!mInvalidated); // Compiled out of release builds + return mRevisionID; + } + void SetRevisionID(int64_t RevisionID) + { + ASSERT(!mInvalidated); // Compiled out of release builds + mRevisionID = RevisionID; + } + + unsigned int GetNumberOfEntries() const + { + ASSERT(!mInvalidated); // Compiled out of release builds + return mEntries.size(); + } // User info -- not serialised into streams - int64_t GetUserInfo1_SizeInBlocks() const {return mUserInfo1;} - void SetUserInfo1_SizeInBlocks(int64_t UserInfo1) {mUserInfo1 = UserInfo1;} + int64_t GetUserInfo1_SizeInBlocks() const + { + ASSERT(!mInvalidated); // Compiled out of release builds + return mUserInfo1; + } + void SetUserInfo1_SizeInBlocks(int64_t UserInfo1) + { + ASSERT(!mInvalidated); // Compiled out of release builds + mUserInfo1 = UserInfo1; + } // Attributes - bool HasAttributes() const {return !mAttributes.IsEmpty();} - void SetAttributes(const StreamableMemBlock &rAttr, box_time_t AttributesModTime) {mAttributes.Set(rAttr); mAttributesModTime = AttributesModTime;} - const StreamableMemBlock &GetAttributes() const {return mAttributes;} - box_time_t GetAttributesModTime() const {return mAttributesModTime;} + bool HasAttributes() const + { + ASSERT(!mInvalidated); // Compiled out of release builds + return !mAttributes.IsEmpty(); + } + void SetAttributes(const StreamableMemBlock &rAttr, + box_time_t AttributesModTime) + { + ASSERT(!mInvalidated); // Compiled out of release builds + mAttributes.Set(rAttr); + mAttributesModTime = AttributesModTime; + } + const StreamableMemBlock &GetAttributes() const + { + ASSERT(!mInvalidated); // Compiled out of release builds + return mAttributes; + } + box_time_t GetAttributesModTime() const + { + ASSERT(!mInvalidated); // Compiled out of release builds + return mAttributesModTime; + } class Iterator { @@ -195,10 +377,12 @@ public: Iterator(const BackupStoreDirectory &rDir) : mrDir(rDir), i(rDir.mEntries.begin()) { + ASSERT(!mrDir.mInvalidated); // Compiled out of release builds } BackupStoreDirectory::Entry *Next(int16_t FlagsMustBeSet = Entry::Flags_INCLUDE_EVERYTHING, int16_t FlagsNotToBeSet = Entry::Flags_EXCLUDE_NOTHING) { + ASSERT(!mrDir.mInvalidated); // Compiled out of release builds // Skip over things which don't match the required flags while(i != mrDir.mEntries.end() && !(*i)->MatchesFlags(FlagsMustBeSet, FlagsNotToBeSet)) { @@ -218,6 +402,7 @@ public: // In a looping situation, cache the decrypted filenames in another memory structure. BackupStoreDirectory::Entry *FindMatchingClearName(const BackupStoreFilenameClear &rFilename, int16_t FlagsMustBeSet = Entry::Flags_INCLUDE_EVERYTHING, int16_t FlagsNotToBeSet = Entry::Flags_EXCLUDE_NOTHING) { + ASSERT(!mrDir.mInvalidated); // Compiled out of release builds // Skip over things which don't match the required flags or filename while( (i != mrDir.mEntries.end()) && ( (!(*i)->MatchesFlags(FlagsMustBeSet, FlagsNotToBeSet)) @@ -247,10 +432,12 @@ public: ReverseIterator(const BackupStoreDirectory &rDir) : mrDir(rDir), i(rDir.mEntries.rbegin()) { + ASSERT(!mrDir.mInvalidated); // Compiled out of release builds } BackupStoreDirectory::Entry *Next(int16_t FlagsMustBeSet = Entry::Flags_INCLUDE_EVERYTHING, int16_t FlagsNotToBeSet = Entry::Flags_EXCLUDE_NOTHING) { + ASSERT(!mrDir.mInvalidated); // Compiled out of release builds // Skip over things which don't match the required flags while(i != mrDir.mEntries.rend() && !(*i)->MatchesFlags(FlagsMustBeSet, FlagsNotToBeSet)) { |