diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:24:59 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:24:59 +0200 |
commit | a1c91f4695e208d5a8f80dc37b1818169b7829ff (patch) | |
tree | 52f5134376d17c99b6c9e53133a2eb5cf171377c /file_hierarchy.h | |
parent | 5.16 (diff) | |
download | FreeFileSync-a1c91f4695e208d5a8f80dc37b1818169b7829ff.tar.gz FreeFileSync-a1c91f4695e208d5a8f80dc37b1818169b7829ff.tar.bz2 FreeFileSync-a1c91f4695e208d5a8f80dc37b1818169b7829ff.zip |
5.17
Diffstat (limited to 'file_hierarchy.h')
-rw-r--r-- | file_hierarchy.h | 556 |
1 files changed, 248 insertions, 308 deletions
diff --git a/file_hierarchy.h b/file_hierarchy.h index eb5cc91e..7710e7ac 100644 --- a/file_hierarchy.h +++ b/file_hierarchy.h @@ -24,19 +24,22 @@ namespace zen { struct FileDescriptor { - FileDescriptor() : fileIdx(), devId() {} - FileDescriptor(Int64 lastWriteTimeRawIn, - UInt64 fileSizeIn, - const FileId& idIn) : + FileDescriptor() : fileIdx(), devId(), isFollowedSymlink() {} + FileDescriptor(const Int64& lastWriteTimeRawIn, + const UInt64& fileSizeIn, + const FileId& idIn, + bool isSymlink) : lastWriteTimeRaw(lastWriteTimeRawIn), fileSize(fileSizeIn), fileIdx(idIn.second), - devId(idIn.first) {} + devId(idIn.first), + isFollowedSymlink(isSymlink) {} Int64 lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC, same semantics like time_t (== signed long) UInt64 fileSize; FileIndex fileIdx; // == file id: optional! (however, always set on Linux, and *generally* available on Windows) - DeviceId devId; //split into file id into components to avoid padding overhead of a struct! + DeviceId devId; //split into file id into components to avoid padding overhead of a std::pair! + bool isFollowedSymlink; }; inline @@ -45,7 +48,7 @@ FileId getFileId(const FileDescriptor& fd) { return FileId(fd.devId, fd.fileIdx) struct LinkDescriptor { LinkDescriptor() {} - explicit LinkDescriptor(Int64 lastWriteTimeRawIn) : lastWriteTimeRaw(lastWriteTimeRawIn) {} + explicit LinkDescriptor(const Int64& lastWriteTimeRawIn) : lastWriteTimeRaw(lastWriteTimeRawIn) {} Int64 lastWriteTimeRaw; //number of seconds since Jan. 1st 1970 UTC, same semantics like time_t (== signed long) }; @@ -67,10 +70,28 @@ template <> struct OtherSide<RIGHT_SIDE> { static const SelectedSide result = LEFT_SIDE; }; -class BaseDirMapping; -class DirMapping; -class FileMapping; -class SymLinkMapping; +template <SelectedSide side> +struct SelectParam; + +template <> +struct SelectParam<LEFT_SIDE> +{ + template <class T> + static T& get(T& left, T& right) { return left; } +}; + +template <> +struct SelectParam<RIGHT_SIDE> +{ + template <class T> + static T& get(T& left, T& right) { return right; } +}; + + +class BaseDirPair; +class DirPair; +class FilePair; +class SymlinkPair; class FileSystemObject; //------------------------------------------------------------------ @@ -113,8 +134,8 @@ struct DirContainer } }; -//------------------------------------------------------------------ -/* inheritance diagram: +/*------------------------------------------------------------------ + inheritance diagram: ObjectMgr /|\ @@ -123,47 +144,47 @@ struct DirContainer /|\ /|\ _______________|______________ ______|______ | | | | | -SymLinkMapping FileMapping DirMapping BaseDirMapping -*/ + SymlinkPair FilePair DirPair BaseDirPair + +------------------------------------------------------------------*/ -//------------------------------------------------------------------ class HierarchyObject { - friend class DirMapping; + friend class DirPair; friend class FileSystemObject; public: - typedef zen::FixedList<FileMapping> SubFileVec; //MergeSides::execute() requires a structure that doesn't invalidate pointers after push_back() - typedef zen::FixedList<SymLinkMapping> SubLinkVec; //Note: deque<> has circular dependency in VCPP! - typedef zen::FixedList<DirMapping> SubDirVec; + typedef zen::FixedList<FilePair> SubFileVec; //MergeSides::execute() requires a structure that doesn't invalidate pointers after push_back() + typedef zen::FixedList<SymlinkPair> SubLinkVec; //Note: deque<> has circular dependency in VCPP! + typedef zen::FixedList<DirPair> SubDirVec; - DirMapping& addSubDir(const Zstring& shortNameLeft, - const Zstring& shortNameRight, - CompareDirResult defaultCmpResult); + DirPair& addSubDir(const Zstring& shortNameLeft, + const Zstring& shortNameRight, + CompareDirResult defaultCmpResult); template <SelectedSide side> - DirMapping& addSubDir(const Zstring& shortName); //dir exists on one side only + DirPair& addSubDir(const Zstring& shortName); //dir exists on one side only - FileMapping& addSubFile(const Zstring& shortNameLeft, - const FileDescriptor& left, //file exists on both sides - CompareFilesResult defaultCmpResult, - const Zstring& shortNameRight, - const FileDescriptor& right); + FilePair& addSubFile(const Zstring& shortNameLeft, + const FileDescriptor& left, //file exists on both sides + CompareFilesResult defaultCmpResult, + const Zstring& shortNameRight, + const FileDescriptor& right); template <SelectedSide side> - FileMapping& addSubFile(const Zstring& shortNameRight, //file exists on one side only - const FileDescriptor& right); + FilePair& addSubFile(const Zstring& shortNameRight, //file exists on one side only + const FileDescriptor& right); - SymLinkMapping& addSubLink(const Zstring& shortNameLeft, - const LinkDescriptor& left, //link exists on both sides - CompareSymlinkResult defaultCmpResult, - const Zstring& shortNameRight, - const LinkDescriptor& right); + SymlinkPair& addSubLink(const Zstring& shortNameLeft, + const LinkDescriptor& left, //link exists on both sides + CompareSymlinkResult defaultCmpResult, + const Zstring& shortNameRight, + const LinkDescriptor& right); template <SelectedSide side> - SymLinkMapping& addSubLink(const Zstring& shortName, //link exists on one side only - const LinkDescriptor& descr); + SymlinkPair& addSubLink(const Zstring& shortName, //link exists on one side only + const LinkDescriptor& descr); const SubFileVec& refSubFiles() const { return subFiles; } /**/ SubFileVec& refSubFiles() { return subFiles; } @@ -174,15 +195,15 @@ public: const SubDirVec& refSubDirs() const { return subDirs; } /**/ SubDirVec& refSubDirs() { return subDirs; } - BaseDirMapping& getRoot() { return root_; } + BaseDirPair& getRoot() { return root_; } const Zstring& getObjRelativeNamePf() const { return objRelNamePf; } //postfixed or empty! protected: HierarchyObject(const Zstring& relativeNamePf, - BaseDirMapping& baseMap) : + BaseDirPair& baseDirObj) : objRelNamePf(relativeNamePf), - root_(baseMap) {} + root_(baseDirObj) {} ~HierarchyObject() {} //don't need polymorphic deletion @@ -201,21 +222,21 @@ private: SubDirVec subDirs; //contained directory maps Zstring objRelNamePf; //postfixed or empty - BaseDirMapping& root_; + BaseDirPair& root_; }; //------------------------------------------------------------------ -class BaseDirMapping : public HierarchyObject //synchronization base directory +class BaseDirPair : public HierarchyObject //synchronization base directory { public: - BaseDirMapping(const Zstring& dirPostfixedLeft, - bool dirExistsLeft, - const Zstring& dirPostfixedRight, - bool dirExistsRight, - const HardFilter::FilterRef& filter, - CompareVariant cmpVar, - size_t fileTimeTolerance) : + BaseDirPair(const Zstring& dirPostfixedLeft, + bool dirExistsLeft, + const Zstring& dirPostfixedRight, + bool dirExistsRight, + const HardFilter::FilterRef& filter, + CompareVariant cmpVar, + size_t fileTimeTolerance) : #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4355) //"The this pointer is valid only within nonstatic member functions. It cannot be used in the initializer list for a base class." @@ -231,12 +252,12 @@ public: dirExistsRight_(dirExistsRight) {} template <SelectedSide side> const Zstring& getBaseDirPf() const; //base sync directory postfixed with FILE_NAME_SEPARATOR (or empty!) - static void removeEmpty(BaseDirMapping& baseDir) { baseDir.removeEmptyRec(); }; //physically remove all invalid entries (where both sides are empty) recursively + static void removeEmpty(BaseDirPair& baseDir) { baseDir.removeEmptyRec(); }; //physically remove all invalid entries (where both sides are empty) recursively template <SelectedSide side> bool isExisting() const; //status of directory existence at the time of comparison! template <SelectedSide side> void setExisting(bool value); //update after creating the directory in FFS - //get settings which were used while creating BaseDirMapping + //get settings which were used while creating BaseDirPair const HardFilter& getFilter() const { return *filter_; } CompareVariant getCompVariant() const { return cmpVar_; } size_t getFileTimeTolerance() const { return fileTimeTolerance_; } @@ -244,8 +265,8 @@ public: virtual void flip(); private: - BaseDirMapping(const BaseDirMapping&); //this class is referenced by HierarchyObject => make it non-copyable/movable! - BaseDirMapping& operator=(const BaseDirMapping&); // + BaseDirPair(const BaseDirPair&); //this class is referenced by HierarchyObject => make it non-copyable/movable! + BaseDirPair& operator=(const BaseDirPair&); // HardFilter::FilterRef filter_; //filter used while scanning directory: represents sub-view of actual files! CompareVariant cmpVar_; @@ -260,15 +281,15 @@ private: template <> inline -const Zstring& BaseDirMapping::getBaseDirPf<LEFT_SIDE>() const { return baseDirPfL; } +const Zstring& BaseDirPair::getBaseDirPf<LEFT_SIDE>() const { return baseDirPfL; } template <> inline -const Zstring& BaseDirMapping::getBaseDirPf<RIGHT_SIDE>() const { return baseDirPfR; } +const Zstring& BaseDirPair::getBaseDirPf<RIGHT_SIDE>() const { return baseDirPfR; } //get rid of shared_ptr indirection -template < class IterTy, //underlying iterator type - class U > //target object type +template <class IterTy, //underlying iterator type + class U> //target object type class DerefIter : public std::iterator<std::bidirectional_iterator_tag, U> { public: @@ -288,22 +309,22 @@ private: IterTy iter; }; -typedef std::vector<std::shared_ptr<BaseDirMapping>> FolderComparison; //make sure pointers to sub-elements remain valid -//don't change this back to std::vector<BaseDirMapping> too easily: comparison uses push_back to add entries which may result in a full copy! +typedef std::vector<std::shared_ptr<BaseDirPair>> FolderComparison; //make sure pointers to sub-elements remain valid +//don't change this back to std::vector<BaseDirPair> too easily: comparison uses push_back to add entries which may result in a full copy! -DerefIter<typename FolderComparison::iterator, BaseDirMapping> inline begin(FolderComparison& vect) { return vect.begin(); } -DerefIter<typename FolderComparison::iterator, BaseDirMapping> inline end (FolderComparison& vect) { return vect.end (); } -DerefIter<typename FolderComparison::const_iterator, const BaseDirMapping> inline begin(const FolderComparison& vect) { return vect.begin(); } -DerefIter<typename FolderComparison::const_iterator, const BaseDirMapping> inline end (const FolderComparison& vect) { return vect.end (); } +DerefIter<typename FolderComparison::iterator, BaseDirPair> inline begin(FolderComparison& vect) { return vect.begin(); } +DerefIter<typename FolderComparison::iterator, BaseDirPair> inline end (FolderComparison& vect) { return vect.end (); } +DerefIter<typename FolderComparison::const_iterator, const BaseDirPair> inline begin(const FolderComparison& vect) { return vect.begin(); } +DerefIter<typename FolderComparison::const_iterator, const BaseDirPair> inline end (const FolderComparison& vect) { return vect.end (); } //------------------------------------------------------------------ class FSObjectVisitor { public: virtual ~FSObjectVisitor() {} - virtual void visit(const FileMapping& fileObj) = 0; - virtual void visit(const SymLinkMapping& linkObj) = 0; - virtual void visit(const DirMapping& dirObj) = 0; + virtual void visit(const FilePair& fileObj) = 0; + virtual void visit(const SymlinkPair& linkObj) = 0; + virtual void visit(const DirPair& dirObj) = 0; }; //inherit from this class to allow safe random access by id instead of unsafe raw pointer @@ -335,6 +356,7 @@ private: static zen::hash_set<const ObjectMgr*>& activeObjects() { static zen::hash_set<const ObjectMgr*> inst; return inst; } //external linkage (even in header file!) }; + //------------------------------------------------------------------ class FileSystemObject : public ObjectMgr<FileSystemObject> @@ -354,27 +376,27 @@ public: CompareFilesResult getCategory() const { return cmpResult; } std::wstring getCatExtraDescription() const; //only filled if getCategory() == FILE_CONFLICT or FILE_DIFFERENT_METADATA - //sync operation - virtual SyncOperation testSyncOperation(SyncDirection testSyncDir) const; //semantics: "what if"! assumes "active, no conflict, no recursion (directory)! - virtual SyncOperation getSyncOperation() const; - std::wstring getSyncOpConflict() const; //return conflict when determining sync direction or (still unresolved) conflict during categorization - //sync settings + SyncDirection getSyncDir() const; void setSyncDir(SyncDirection newDir); void setSyncDirConflict(const std::wstring& description); //set syncDir = SYNC_DIR_NONE + fill conflict description - SyncDirection getSyncDir() const { return syncDir; } bool isActive() const; void setActive(bool active); + //sync operation + virtual SyncOperation testSyncOperation(SyncDirection testSyncDir) const; //semantics: "what if"! assumes "active, no conflict, no recursion (directory)! + virtual SyncOperation getSyncOperation() const; + std::wstring getSyncOpConflict() const; //return conflict when determining sync direction or (still unresolved) conflict during categorization + template <SelectedSide side> void removeObject(); //removes file or directory (recursively!) without physically removing the element: used by manual deletion bool isEmpty() const; //true, if both sides are empty const HierarchyObject& parent() const { return parent_; } /**/ HierarchyObject& parent() { return parent_; } - const BaseDirMapping& root() const { return parent_.getRoot(); } - /**/ BaseDirMapping& root() { return parent_.getRoot(); } + const BaseDirPair& root() const { return parent_.getRoot(); } + /**/ BaseDirPair& root() { return parent_.getRoot(); } //for use during init in "CompareProcess" only: template <CompareFilesResult res> void setCategory(); @@ -388,7 +410,7 @@ protected: CompareFilesResult defaultCmpResult) : cmpResult(defaultCmpResult), selectedForSynchronization(true), - syncDir(SYNC_DIR_NONE), + syncDir_(static_cast<unsigned char>(SYNC_DIR_NONE)), shortNameLeft_(shortNameLeft), shortNameRight_(shortNameRight), //shortNameRight_(shortNameRight == shortNameLeft ? shortNameLeft : shortNameRight), -> strangely doesn't seem to shrink peak memory consumption at all! @@ -403,8 +425,7 @@ protected: virtual void flip(); virtual void notifySyncCfgChanged() { parent().notifySyncCfgChanged(); /*propagate!*/ } - void copyToL(); - void copyToR(); + void setSynced(const Zstring& shortName); private: virtual void removeObjectL() = 0; @@ -412,24 +433,25 @@ private: //categorization std::unique_ptr<std::wstring> cmpResultDescr; //only filled if getCategory() == FILE_CONFLICT or FILE_DIFFERENT_METADATA - CompareFilesResult cmpResult; + CompareFilesResult cmpResult; //although this uses 4 bytes there is currently *no* space wasted in class layout! bool selectedForSynchronization; - SyncDirection syncDir; + unsigned char syncDir_; //use "char" instead of "SyncDirection" lacking C++11 custom size enum classes to optimize memory layout! std::unique_ptr<std::wstring> syncDirConflict; //non-empty if we have a conflict setting sync-direction //get rid of std::wstring small string optimization (consumes 32/48 byte on VS2010 x86/x64!) //Note: we model *four* states with last two variables => "syncDirConflict is empty or syncDir == NONE" is a class invariant!!! - Zstring shortNameLeft_; //slightly redundant under linux, but on windows the "same" filenames can differ in case - Zstring shortNameRight_; //use as indicator: an empty name means: not existing! + Zstring shortNameLeft_; //slightly redundant under linux, but on windows the "same" filenames can differ in case + Zstring shortNameRight_; //use as indicator: an empty name means: not existing! HierarchyObject& parent_; }; //------------------------------------------------------------------ -class DirMapping : public FileSystemObject, public HierarchyObject + +class DirPair : public FileSystemObject, public HierarchyObject { friend class HierarchyObject; @@ -438,10 +460,10 @@ public: CompareDirResult getDirCategory() const; //returns actually used subset of CompareFilesResult - DirMapping(const Zstring& shortNameLeft, //use empty shortname if "not existing" - const Zstring& shortNameRight, // - HierarchyObject& parentObj, - CompareDirResult defaultCmpResult) : + DirPair(const Zstring& shortNameLeft, //use empty shortname if "not existing" + const Zstring& shortNameRight, // + HierarchyObject& parentObj, + CompareDirResult defaultCmpResult) : FileSystemObject(shortNameLeft, shortNameRight, parentObj, static_cast<CompareFilesResult>(defaultCmpResult)), HierarchyObject(getObjRelativeName() + FILE_NAME_SEPARATOR, parentObj.getRoot()), syncOpBuffered(SO_DO_NOTHING), @@ -449,41 +471,42 @@ public: virtual SyncOperation getSyncOperation() const; - template <SelectedSide side> void copyTo(); //copy dir + void setSyncedTo(const Zstring& shortName); //call after sync, sets DIR_EQUAL private: virtual void flip(); virtual void removeObjectL(); virtual void removeObjectR(); virtual void notifySyncCfgChanged() { syncOpUpToDate = false; FileSystemObject::notifySyncCfgChanged(); HierarchyObject::notifySyncCfgChanged(); } - //------------------------------------------------------------------ mutable SyncOperation syncOpBuffered; //determining sync-op for directory may be expensive as it depends on child-objects -> buffer it - mutable bool syncOpUpToDate; // + mutable bool syncOpUpToDate; // }; //------------------------------------------------------------------ -class FileMapping : public FileSystemObject + +class FilePair : public FileSystemObject { friend class HierarchyObject; //construction public: virtual void accept(FSObjectVisitor& visitor) const; - FileMapping(const Zstring& shortNameLeft, //use empty string if "not existing" - const FileDescriptor& left, - CompareFilesResult defaultCmpResult, - const Zstring& shortNameRight, // - const FileDescriptor& right, - HierarchyObject& parentObj) : + FilePair(const Zstring& shortNameLeft, //use empty string if "not existing" + const FileDescriptor& left, + CompareFilesResult defaultCmpResult, + const Zstring& shortNameRight, // + const FileDescriptor& right, + HierarchyObject& parentObj) : FileSystemObject(shortNameLeft, shortNameRight, parentObj, defaultCmpResult), dataLeft(left), dataRight(right), moveFileRef(nullptr) {} - template <SelectedSide side> Int64 getLastWriteTime() const; - template <SelectedSide side> UInt64 getFileSize () const; - template <SelectedSide side> FileId getFileId () const; + template <SelectedSide side> Int64 getLastWriteTime () const; + template <SelectedSide side> UInt64 getFileSize () const; + template <SelectedSide side> FileId getFileId () const; + template <SelectedSide side> bool isFollowedSymlink() const; void setMoveRef(ObjectId refId) { moveFileRef = refId; } //reference to corresponding renamed file ObjectId getMoveRef() const { return moveFileRef; } //may be nullptr @@ -493,7 +516,15 @@ public: virtual SyncOperation testSyncOperation(SyncDirection testSyncDir) const; //semantics: "what if"! assumes "active, no conflict, no recursion (directory)! virtual SyncOperation getSyncOperation() const; - template <SelectedSide side> void syncTo(const FileDescriptor& descrTarget, const FileDescriptor* descrSource = nullptr); //copy + update file attributes (optional) + template <SelectedSide sideTrg> + void setSyncedTo(const Zstring& shortName, //call after sync, sets FILE_EQUAL + const UInt64& fileSize, + const Int64& lastWriteTimeTrg, + const Int64& lastWriteTimeSrc, + const FileId& fileIdTrg, + const FileId& fileIdSrc, + bool isSymlinkTrg, + bool isSymlinkSrc); private: SyncOperation applyMoveOptimization(SyncOperation op) const; @@ -501,7 +532,6 @@ private: virtual void flip(); virtual void removeObjectL(); virtual void removeObjectR(); - //------------------------------------------------------------------ FileDescriptor dataLeft; FileDescriptor dataRight; @@ -510,7 +540,8 @@ private: }; //------------------------------------------------------------------ -class SymLinkMapping : public FileSystemObject //this class models a TRUE symbolic link, i.e. one that is NEVER dereferenced: deref-links should be directly placed in class File/DirMapping + +class SymlinkPair : public FileSystemObject //this class models a TRUE symbolic link, i.e. one that is NEVER dereferenced: deref-links should be directly placed in class File/DirPair { friend class HierarchyObject; //construction @@ -521,23 +552,25 @@ public: CompareSymlinkResult getLinkCategory() const; //returns actually used subset of CompareFilesResult - SymLinkMapping(const Zstring& shortNameLeft, //use empty string if "not existing" - const LinkDescriptor& left, - CompareSymlinkResult defaultCmpResult, - const Zstring& shortNameRight, //use empty string if "not existing" - const LinkDescriptor& right, - HierarchyObject& parentObj) : + SymlinkPair(const Zstring& shortNameLeft, //use empty string if "not existing" + const LinkDescriptor& left, + CompareSymlinkResult defaultCmpResult, + const Zstring& shortNameRight, //use empty string if "not existing" + const LinkDescriptor& right, + HierarchyObject& parentObj) : FileSystemObject(shortNameLeft, shortNameRight, parentObj, static_cast<CompareFilesResult>(defaultCmpResult)), dataLeft(left), dataRight(right) {} - template <SelectedSide side> void copyTo(); //copy + template <SelectedSide sideTrg> + void setSyncedTo(const Zstring& shortName, //call after sync, sets SYMLINK_EQUAL + const Int64& lastWriteTimeTrg, + const Int64& lastWriteTimeSrc); private: virtual void flip(); virtual void removeObjectL(); virtual void removeObjectR(); - //------------------------------------------------------------------ LinkDescriptor dataLeft; LinkDescriptor dataRight; @@ -576,55 +609,46 @@ std::wstring getSyncOpDescription (const FileSystemObject& fsObj); - - - - - - - - - //---------------Inline Implementation--------------------------------------------------- -inline //inline virtual... admittedly its use may be limited -void FileMapping::accept(FSObjectVisitor& visitor) const -{ - visitor.visit(*this); -} +//inline virtual... admittedly its use may be limited +inline void FilePair ::accept(FSObjectVisitor& visitor) const { visitor.visit(*this); } +inline void DirPair ::accept(FSObjectVisitor& visitor) const { visitor.visit(*this); } +inline void SymlinkPair::accept(FSObjectVisitor& visitor) const { visitor.visit(*this); } inline -void DirMapping::accept(FSObjectVisitor& visitor) const +CompareFilesResult FilePair::getFileCategory() const { - visitor.visit(*this); + return getCategory(); } inline -void SymLinkMapping::accept(FSObjectVisitor& visitor) const +CompareDirResult DirPair::getDirCategory() const { - visitor.visit(*this); + return static_cast<CompareDirResult>(getCategory()); } inline -CompareFilesResult FileMapping::getFileCategory() const +std::wstring FileSystemObject::getCatExtraDescription() const { - return getCategory(); + assert(getCategory() == FILE_CONFLICT || getCategory() == FILE_DIFFERENT_METADATA); + return cmpResultDescr ? *cmpResultDescr : std::wstring(); } inline -CompareDirResult DirMapping::getDirCategory() const +SyncDirection FileSystemObject::getSyncDir() const { - return static_cast<CompareDirResult>(getCategory()); + return static_cast<SyncDirection>(syncDir_); } inline void FileSystemObject::setSyncDir(SyncDirection newDir) { - syncDir = newDir; //should be safe by design + syncDir_ = static_cast<unsigned char>(newDir); syncDirConflict.reset(); notifySyncCfgChanged(); @@ -632,17 +656,9 @@ void FileSystemObject::setSyncDir(SyncDirection newDir) inline -std::wstring FileSystemObject::getCatExtraDescription() const -{ - assert(getCategory() == FILE_CONFLICT || getCategory() == FILE_DIFFERENT_METADATA); - return cmpResultDescr ? *cmpResultDescr : std::wstring(); -} - - -inline void FileSystemObject::setSyncDirConflict(const std::wstring& description) { - syncDir = SYNC_DIR_NONE; + syncDir_ = static_cast<unsigned char>(SYNC_DIR_NONE); syncDirConflict.reset(new std::wstring(description)); notifySyncCfgChanged(); @@ -668,22 +684,14 @@ inline void FileSystemObject::setActive(bool active) { selectedForSynchronization = active; - notifySyncCfgChanged(); } -template <> inline -bool FileSystemObject::isEmpty<LEFT_SIDE>() const -{ - return shortNameLeft_.empty(); -} - - -template <> inline -bool FileSystemObject::isEmpty<RIGHT_SIDE>() const +template <SelectedSide side> inline +bool FileSystemObject::isEmpty() const { - return shortNameRight_.empty(); + return SelectParam<side>::get(shortNameLeft_, shortNameRight_).empty(); } @@ -694,17 +702,10 @@ bool FileSystemObject::isEmpty() const } -template <> inline -const Zstring& FileSystemObject::getShortName<LEFT_SIDE>() const -{ - return shortNameLeft_; //empty if not existing -} - - -template <> inline -const Zstring& FileSystemObject::getShortName<RIGHT_SIDE>() const +template <SelectedSide side> inline +const Zstring& FileSystemObject::getShortName() const { - return shortNameRight_; //empty if not existing + return SelectParam<side>::get(shortNameLeft_, shortNameRight_); //empty if not existing } @@ -736,17 +737,10 @@ Zstring FileSystemObject::getFullName() const } -template <> inline -const Zstring& FileSystemObject::getBaseDirPf<LEFT_SIDE>() const -{ - return root().getBaseDirPf<LEFT_SIDE>(); -} - - -template <> inline -const Zstring& FileSystemObject::getBaseDirPf<RIGHT_SIDE>() const +template <SelectedSide side> inline +const Zstring& FileSystemObject::getBaseDirPf() const { - return root().getBaseDirPf<RIGHT_SIDE>(); + return root().getBaseDirPf<side>(); } @@ -773,20 +767,10 @@ void FileSystemObject::removeObject<RIGHT_SIDE>() inline -void FileSystemObject::copyToL() +void FileSystemObject::setSynced(const Zstring& shortName) { assert(!isEmpty()); - shortNameLeft_ = shortNameRight_; - cmpResult = FILE_EQUAL; - setSyncDir(SYNC_DIR_NONE); -} - - -inline -void FileSystemObject::copyToR() -{ - assert(!isEmpty()); - shortNameRight_ = shortNameLeft_; + shortNameRight_ = shortNameLeft_ = shortName; cmpResult = FILE_EQUAL; setSyncDir(SYNC_DIR_NONE); } @@ -849,16 +833,16 @@ void FileSystemObject::flip() inline void HierarchyObject::flip() { - std::for_each(refSubFiles().begin(), refSubFiles().end(), std::mem_fun_ref(&FileMapping ::flip)); - std::for_each(refSubDirs ().begin(), refSubDirs ().end(), std::mem_fun_ref(&DirMapping ::flip)); - std::for_each(refSubLinks().begin(), refSubLinks().end(), std::mem_fun_ref(&SymLinkMapping::flip)); + std::for_each(refSubFiles().begin(), refSubFiles().end(), std::mem_fun_ref(&FilePair ::flip)); + std::for_each(refSubDirs ().begin(), refSubDirs ().end(), std::mem_fun_ref(&DirPair ::flip)); + std::for_each(refSubLinks().begin(), refSubLinks().end(), std::mem_fun_ref(&SymlinkPair::flip)); } inline -DirMapping& HierarchyObject::addSubDir(const Zstring& shortNameLeft, - const Zstring& shortNameRight, - CompareDirResult defaultCmpResult) +DirPair& HierarchyObject::addSubDir(const Zstring& shortNameLeft, + const Zstring& shortNameRight, + CompareDirResult defaultCmpResult) { subDirs.emplace_back(shortNameLeft, shortNameRight, *this, defaultCmpResult); return subDirs.back(); @@ -866,7 +850,7 @@ DirMapping& HierarchyObject::addSubDir(const Zstring& shortNameLeft, template <> inline -DirMapping& HierarchyObject::addSubDir<LEFT_SIDE>(const Zstring& shortName) +DirPair& HierarchyObject::addSubDir<LEFT_SIDE>(const Zstring& shortName) { subDirs.emplace_back(shortName, Zstring(), *this, DIR_LEFT_SIDE_ONLY); return subDirs.back(); @@ -874,7 +858,7 @@ DirMapping& HierarchyObject::addSubDir<LEFT_SIDE>(const Zstring& shortName) template <> inline -DirMapping& HierarchyObject::addSubDir<RIGHT_SIDE>(const Zstring& shortName) +DirPair& HierarchyObject::addSubDir<RIGHT_SIDE>(const Zstring& shortName) { subDirs.emplace_back(Zstring(), shortName, *this, DIR_RIGHT_SIDE_ONLY); return subDirs.back(); @@ -882,12 +866,11 @@ DirMapping& HierarchyObject::addSubDir<RIGHT_SIDE>(const Zstring& shortName) inline -FileMapping& HierarchyObject::addSubFile( - const Zstring& shortNameLeft, - const FileDescriptor& left, //file exists on both sides - CompareFilesResult defaultCmpResult, - const Zstring& shortNameRight, - const FileDescriptor& right) +FilePair& HierarchyObject::addSubFile(const Zstring& shortNameLeft, + const FileDescriptor& left, //file exists on both sides + CompareFilesResult defaultCmpResult, + const Zstring& shortNameRight, + const FileDescriptor& right) { subFiles.emplace_back(shortNameLeft, left, defaultCmpResult, shortNameRight, right, *this); return subFiles.back(); @@ -895,7 +878,7 @@ FileMapping& HierarchyObject::addSubFile( template <> inline -FileMapping& HierarchyObject::addSubFile<LEFT_SIDE>(const Zstring& shortName, const FileDescriptor& descr) +FilePair& HierarchyObject::addSubFile<LEFT_SIDE>(const Zstring& shortName, const FileDescriptor& descr) { subFiles.emplace_back(shortName, descr, FILE_LEFT_SIDE_ONLY, Zstring(), FileDescriptor(), *this); return subFiles.back(); @@ -903,7 +886,7 @@ FileMapping& HierarchyObject::addSubFile<LEFT_SIDE>(const Zstring& shortName, co template <> inline -FileMapping& HierarchyObject::addSubFile<RIGHT_SIDE>(const Zstring& shortName, const FileDescriptor& descr) +FilePair& HierarchyObject::addSubFile<RIGHT_SIDE>(const Zstring& shortName, const FileDescriptor& descr) { subFiles.emplace_back(Zstring(), FileDescriptor(), FILE_RIGHT_SIDE_ONLY, shortName, descr, *this); return subFiles.back(); @@ -911,7 +894,7 @@ FileMapping& HierarchyObject::addSubFile<RIGHT_SIDE>(const Zstring& shortName, c inline -SymLinkMapping& HierarchyObject::addSubLink( +SymlinkPair& HierarchyObject::addSubLink( const Zstring& shortNameLeft, const LinkDescriptor& left, //link exists on both sides CompareSymlinkResult defaultCmpResult, @@ -924,7 +907,7 @@ SymLinkMapping& HierarchyObject::addSubLink( template <> inline -SymLinkMapping& HierarchyObject::addSubLink<LEFT_SIDE>(const Zstring& shortName, const LinkDescriptor& descr) +SymlinkPair& HierarchyObject::addSubLink<LEFT_SIDE>(const Zstring& shortName, const LinkDescriptor& descr) { subLinks.emplace_back(shortName, descr, SYMLINK_LEFT_SIDE_ONLY, Zstring(), LinkDescriptor(), *this); return subLinks.back(); @@ -932,7 +915,7 @@ SymLinkMapping& HierarchyObject::addSubLink<LEFT_SIDE>(const Zstring& shortName, template <> inline -SymLinkMapping& HierarchyObject::addSubLink<RIGHT_SIDE>(const Zstring& shortName, const LinkDescriptor& descr) +SymlinkPair& HierarchyObject::addSubLink<RIGHT_SIDE>(const Zstring& shortName, const LinkDescriptor& descr) { subLinks.emplace_back(Zstring(), LinkDescriptor(), SYMLINK_RIGHT_SIDE_ONLY, shortName, descr, *this); return subLinks.back(); @@ -940,7 +923,7 @@ SymLinkMapping& HierarchyObject::addSubLink<RIGHT_SIDE>(const Zstring& shortName inline -void BaseDirMapping::flip() +void BaseDirPair::flip() { HierarchyObject::flip(); std::swap(baseDirPfL, baseDirPfR); @@ -949,7 +932,7 @@ void BaseDirMapping::flip() inline -void DirMapping::flip() +void DirPair::flip() { HierarchyObject ::flip(); //call base class versions FileSystemObject::flip(); // @@ -957,7 +940,7 @@ void DirMapping::flip() inline -void DirMapping::removeObjectL() +void DirPair::removeObjectL() { std::for_each(refSubFiles().begin(), refSubFiles().end(), std::mem_fun_ref(&FileSystemObject::removeObject<LEFT_SIDE>)); std::for_each(refSubLinks().begin(), refSubLinks().end(), std::mem_fun_ref(&FileSystemObject::removeObject<LEFT_SIDE>)); @@ -966,7 +949,7 @@ void DirMapping::removeObjectL() inline -void DirMapping::removeObjectR() +void DirPair::removeObjectR() { std::for_each(refSubFiles().begin(), refSubFiles().end(), std::mem_fun_ref(&FileSystemObject::removeObject<RIGHT_SIDE>)); std::for_each(refSubLinks().begin(), refSubLinks().end(), std::mem_fun_ref(&FileSystemObject::removeObject<RIGHT_SIDE>)); @@ -974,33 +957,22 @@ void DirMapping::removeObjectR() } -template <> inline -bool BaseDirMapping::isExisting<LEFT_SIDE>() const -{ - return dirExistsLeft_; -} - -template <> inline -bool BaseDirMapping::isExisting<RIGHT_SIDE>() const +template <SelectedSide side> inline +bool BaseDirPair::isExisting() const { - return dirExistsRight_; + return SelectParam<side>::get(dirExistsLeft_, dirExistsRight_); } -template <> inline -void BaseDirMapping::setExisting<LEFT_SIDE>(bool value) -{ - dirExistsLeft_ = value; -} -template <> inline -void BaseDirMapping::setExisting<RIGHT_SIDE>(bool value) +template <SelectedSide side> inline +void BaseDirPair::setExisting(bool value) { - dirExistsRight_ = value; + SelectParam<side>::get(dirExistsLeft_, dirExistsRight_) = value; } inline -void FileMapping::flip() +void FilePair::flip() { FileSystemObject::flip(); //call base class version std::swap(dataLeft, dataRight); @@ -1008,138 +980,106 @@ void FileMapping::flip() inline -void FileMapping::removeObjectL() +void FilePair::removeObjectL() { - dataLeft = FileDescriptor(); + dataLeft = FileDescriptor(); } inline -void FileMapping::removeObjectR() +void FilePair::removeObjectR() { dataRight = FileDescriptor(); } -template <> inline -zen::Int64 FileMapping::getLastWriteTime<LEFT_SIDE>() const -{ - return dataLeft.lastWriteTimeRaw; -} - - -template <> inline -zen::Int64 FileMapping::getLastWriteTime<RIGHT_SIDE>() const -{ - return dataRight.lastWriteTimeRaw; -} - - -template <> inline -zen::UInt64 FileMapping::getFileSize<LEFT_SIDE>() const +template <SelectedSide side> inline +zen::Int64 FilePair::getLastWriteTime() const { - return dataLeft.fileSize; + return SelectParam<side>::get(dataLeft, dataRight).lastWriteTimeRaw; } -template <> inline -zen::UInt64 FileMapping::getFileSize<RIGHT_SIDE>() const +template <SelectedSide side> inline +zen::UInt64 FilePair::getFileSize() const { - return dataRight.fileSize; + return SelectParam<side>::get(dataLeft, dataRight).fileSize; } -template <> inline -FileId FileMapping::getFileId<LEFT_SIDE>() const +template <SelectedSide side> inline +FileId FilePair::getFileId() const { - return FileId(dataLeft.devId, dataLeft.fileIdx); + return FileId(SelectParam<side>::get(dataLeft, dataRight).devId, + SelectParam<side>::get(dataLeft, dataRight).fileIdx); } -template <> inline -FileId FileMapping::getFileId<RIGHT_SIDE>() const +template <SelectedSide side> inline +bool FilePair::isFollowedSymlink() const { - return FileId(dataRight.devId, dataRight.fileIdx); + return SelectParam<side>::get(dataLeft, dataRight).isFollowedSymlink; } -template <> inline -void FileMapping::syncTo<LEFT_SIDE>(const FileDescriptor& descrTarget, const FileDescriptor* descrSource) //copy + update file attributes +template <SelectedSide sideTrg> inline +void FilePair::setSyncedTo(const Zstring& shortName, + const UInt64& fileSize, + const Int64& lastWriteTimeTrg, + const Int64& lastWriteTimeSrc, + const FileId& fileIdTrg, + const FileId& fileIdSrc, + bool isSymlinkTrg, + bool isSymlinkSrc) { - dataLeft = descrTarget; - if (descrSource) - dataRight = *descrSource; + //FILE_EQUAL is only allowed for same short name and file size: enforced by this method! + static const SelectedSide sideSrc = OtherSide<sideTrg>::result; - moveFileRef = nullptr; - copyToL(); //copy FileSystemObject specific part -} - - -template <> inline -void FileMapping::syncTo<RIGHT_SIDE>(const FileDescriptor& descrTarget, const FileDescriptor* descrSource) //copy + update file attributes -{ - dataRight = descrTarget; - if (descrSource) - dataLeft = *descrSource; + SelectParam<sideTrg>::get(dataLeft, dataRight) = FileDescriptor(lastWriteTimeTrg, fileSize, fileIdTrg, isSymlinkTrg); + SelectParam<sideSrc>::get(dataLeft, dataRight) = FileDescriptor(lastWriteTimeSrc, fileSize, fileIdSrc, isSymlinkSrc); moveFileRef = nullptr; - copyToR(); //copy FileSystemObject specific part + FileSystemObject::setSynced(shortName); //set FileSystemObject specific part } -template <> inline -void SymLinkMapping::copyTo<LEFT_SIDE>() //copy + update link attributes -{ - dataLeft = dataRight; - copyToL(); //copy FileSystemObject specific part -} - - -template <> inline -void SymLinkMapping::copyTo<RIGHT_SIDE>() //copy + update link attributes -{ - dataRight = dataLeft; - copyToR(); //copy FileSystemObject specific part -} - - -template <> inline -void DirMapping::copyTo<LEFT_SIDE>() +template <SelectedSide sideTrg> inline +void SymlinkPair::setSyncedTo(const Zstring& shortName, + const Int64& lastWriteTimeTrg, + const Int64& lastWriteTimeSrc) { - copyToL(); //copy FileSystemObject specific part -} + static const SelectedSide sideSrc = OtherSide<sideTrg>::result; + SelectParam<sideTrg>::get(dataLeft, dataRight) = LinkDescriptor(lastWriteTimeTrg); + SelectParam<sideSrc>::get(dataLeft, dataRight) = LinkDescriptor(lastWriteTimeSrc); -template <> inline -void DirMapping::copyTo<RIGHT_SIDE>() -{ - copyToR(); //copy FileSystemObject specific part + FileSystemObject::setSynced(shortName); //set FileSystemObject specific part } -template <> inline -zen::Int64 SymLinkMapping::getLastWriteTime<LEFT_SIDE>() const +inline +void DirPair::setSyncedTo(const Zstring& shortName) { - return dataLeft.lastWriteTimeRaw; + FileSystemObject::setSynced(shortName); //set FileSystemObject specific part } -template <> inline -zen::Int64 SymLinkMapping::getLastWriteTime<RIGHT_SIDE>() const +template <SelectedSide side> inline +zen::Int64 SymlinkPair::getLastWriteTime() const { - return dataRight.lastWriteTimeRaw; + return SelectParam<side>::get(dataLeft, dataRight).lastWriteTimeRaw; } inline -CompareSymlinkResult SymLinkMapping::getLinkCategory() const +CompareSymlinkResult SymlinkPair::getLinkCategory() const { return static_cast<CompareSymlinkResult>(getCategory()); } inline -void SymLinkMapping::flip() +void SymlinkPair::flip() { FileSystemObject::flip(); //call base class versions std::swap(dataLeft, dataRight); @@ -1147,14 +1087,14 @@ void SymLinkMapping::flip() inline -void SymLinkMapping::removeObjectL() +void SymlinkPair::removeObjectL() { - dataLeft = LinkDescriptor(); + dataLeft = LinkDescriptor(); } inline -void SymLinkMapping::removeObjectR() +void SymlinkPair::removeObjectR() { dataRight = LinkDescriptor(); } |