// -------------------------------------------------------------------------- // // File // Name: BackupStoreDirectory.h // Purpose: Representation of a backup directory // Created: 2003/08/26 // // -------------------------------------------------------------------------- #ifndef BACKUPSTOREDIRECTORY__H #define BACKUPSTOREDIRECTORY__H #include #include #include "BackupStoreFilenameClear.h" #include "StreamableMemBlock.h" #include "BoxTime.h" class IOStream; // -------------------------------------------------------------------------- // // Class // Name: BackupStoreDirectory // Purpose: In memory representation of a directory // Created: 2003/08/26 // // -------------------------------------------------------------------------- class BackupStoreDirectory { private: #ifndef BOX_RELEASE_BUILD bool mInvalidated; #endif public: #ifndef BOX_RELEASE_BUILD void Invalidate() { mInvalidated = true; for (std::vector::iterator i = mEntries.begin(); i != mEntries.end(); i++) { (*i)->Invalidate(); } } #endif typedef enum { Option_DependencyInfoPresent = 1 } dir_StreamFormatOptions; 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 apStream, int Timeout = IOStream::TimeOutInfinite) #ifndef BOX_RELEASE_BUILD : mInvalidated(false) #endif { ReadFromStream(*apStream, Timeout); } private: // Copying not allowed BackupStoreDirectory(const BackupStoreDirectory &rToCopy); public: ~BackupStoreDirectory(); class Entry { private: #ifndef BOX_RELEASE_BUILD bool mInvalidated; #endif public: #ifndef BOX_RELEASE_BUILD void Invalidate() { mInvalidated = true; } #endif friend class BackupStoreDirectory; Entry(); ~Entry(); Entry(const Entry &rToCopy); Entry(const BackupStoreFilename &rName, box_time_t ModificationTime, int64_t ObjectID, int64_t SizeInBlocks, int16_t Flags, uint64_t AttributesHash); void ReadFromStream(IOStream &rStream, int Timeout); void WriteToStream(IOStream &rStream) const; 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) { 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 { 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 { ASSERT(!mInvalidated); // Compiled out of release builds return mMinMarkNumber; } // The mark number on this file 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 enum { Flags_INCLUDE_EVERYTHING = -1, Flags_EXCLUDE_NOTHING = 0, Flags_EXCLUDE_EVERYTHING = 31, // make sure this is kept as sum of ones below! Flags_File = 1, Flags_Dir = 2, Flags_Deleted = 4, Flags_OldVersion = 8, Flags_RemoveASAP = 16 // if this flag is set, housekeeping will remove it as it is marked Deleted or OldVersion }; // characters for textual listing of files -- see bbackupquery/BackupQueries #define BACKUPSTOREDIRECTORY_ENTRY_FLAGS_DISPLAY_NAMES "fdXoR" // 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 { 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 { 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() { ASSERT(!mInvalidated); // Compiled out of release builds return mDependsNewer != 0 || mDependsOlder != 0; } void ReadFromStreamDependencyInfo(IOStream &rStream, int Timeout); void WriteToStreamDependencyInfo(IOStream &rStream) const; private: BackupStoreFilename mName; box_time_t mModificationTime; int64_t mObjectID; int64_t mSizeInBlocks; int16_t mFlags; uint64_t mAttributesHash; StreamableMemBlock mAttributes; uint32_t mMinMarkNumber; uint32_t mMarkNumber; 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, int16_t FlagsNotToBeSet = Entry::Flags_EXCLUDE_NOTHING, bool StreamAttributes = true, bool StreamDependencyInfo = true) const; Entry *AddEntry(const Entry &rEntryToCopy); Entry *AddEntry(const BackupStoreFilename &rName, box_time_t ModificationTime, int64_t ObjectID, int64_t SizeInBlocks, int16_t Flags, uint64_t AttributesHash); void DeleteEntry(int64_t ObjectID); Entry *FindEntryByID(int64_t ObjectID) const; 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) { ASSERT(!mInvalidated); // Compiled out of release builds mContainerID = ContainerID; } // 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 { 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 { 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 { 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)) { ++i; } // Not the last one? if(i == mrDir.mEntries.end()) { return 0; } // Return entry, and increment return (*(i++)); } // WARNING: This function is really very inefficient. // Only use when you want to look up ONE filename, not in a loop looking up lots. // 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)) || (BackupStoreFilenameClear((*i)->GetName()).GetClearFilename() != rFilename.GetClearFilename()) ) ) { ++i; } // Not the last one? if(i == mrDir.mEntries.end()) { return 0; } // Return entry, and increment return (*(i++)); } private: const BackupStoreDirectory &mrDir; std::vector::const_iterator i; }; friend class Iterator; class ReverseIterator { 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)) { ++i; } // Not the last one? if(i == mrDir.mEntries.rend()) { return 0; } // Return entry, and increment return (*(i++)); } private: const BackupStoreDirectory &mrDir; std::vector::const_reverse_iterator i; }; friend class ReverseIterator; // For recovery of the store // Implemented in BackupStoreCheck2.cpp bool CheckAndFix(); void AddUnattachedObject(const BackupStoreFilename &rName, box_time_t ModificationTime, int64_t ObjectID, int64_t SizeInBlocks, int16_t Flags); bool NameInUse(const BackupStoreFilename &rName); // For testing // Don't use these functions in normal code! void TESTONLY_SetObjectID(int64_t ObjectID) {mObjectID = ObjectID;} // Debug and diagnostics void Dump(void *clibFileHandle, bool ToTrace); // first arg is FILE *, but avoid including stdio.h everywhere private: int64_t mRevisionID; int64_t mObjectID; int64_t mContainerID; std::vector mEntries; box_time_t mAttributesModTime; StreamableMemBlock mAttributes; int64_t mUserInfo1; }; #endif // BACKUPSTOREDIRECTORY__H