summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorChris Wilson <chris+github@qwirx.com>2014-11-16 23:12:06 +0000
committerChris Wilson <chris+github@qwirx.com>2014-11-16 23:12:06 +0000
commit258e57eaecfe85356181706d70141a2563d22737 (patch)
treef1b64fd4d00a7b39ec062869dc97897f091d9b57 /lib
parent286c37b195f15236ccb0f51fd912777c17a2e2db (diff)
Add cache invalidation checks to BackupStoreDirectory.
Allows us to catch programming errors related to use of a cached reference to a directory after the cache may have been invalidated by requesting another directory from the cache, which could clear it. In DEBUG builds, the cache is no longer cleared, but any entries in it are invalidated, which is effectively a memory leak, but these builds should only be used for running tests, where it doesn't matter.
Diffstat (limited to 'lib')
-rw-r--r--lib/backupstore/BackupStoreContext.cpp94
-rw-r--r--lib/backupstore/BackupStoreContext.h3
-rw-r--r--lib/backupstore/BackupStoreDirectory.cpp39
-rw-r--r--lib/backupstore/BackupStoreDirectory.h265
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))
{