diff options
author | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:09:45 +0200 |
---|---|---|
committer | Daniel Wilhelm <daniel@wili.li> | 2014-04-18 17:09:45 +0200 |
commit | 88c8801298cbf6fec9cdce254c7b3cb9e066a421 (patch) | |
tree | 35a35acf48eb227bac30abc8f87ea9b1c3c57b68 /library | |
parent | 3.12 (diff) | |
download | FreeFileSync-88c8801298cbf6fec9cdce254c7b3cb9e066a421.tar.gz FreeFileSync-88c8801298cbf6fec9cdce254c7b3cb9e066a421.tar.bz2 FreeFileSync-88c8801298cbf6fec9cdce254c7b3cb9e066a421.zip |
3.13
Diffstat (limited to 'library')
-rw-r--r-- | library/binary.cpp | 2 | ||||
-rw-r--r-- | library/binary.h | 2 | ||||
-rw-r--r-- | library/cmp_filetime.h | 66 | ||||
-rw-r--r-- | library/custom_grid.cpp | 26 | ||||
-rw-r--r-- | library/custom_grid.h | 6 | ||||
-rw-r--r-- | library/db_file.cpp | 159 | ||||
-rw-r--r-- | library/db_file.h | 2 | ||||
-rw-r--r-- | library/detect_renaming.cpp | 2 | ||||
-rw-r--r-- | library/detect_renaming.h | 2 | ||||
-rw-r--r-- | library/dir_lock.cpp | 70 | ||||
-rw-r--r-- | library/dir_lock.h | 2 | ||||
-rw-r--r-- | library/error_log.cpp | 2 | ||||
-rw-r--r-- | library/error_log.h | 2 | ||||
-rw-r--r-- | library/filter.cpp | 2 | ||||
-rw-r--r-- | library/filter.h | 19 | ||||
-rw-r--r-- | library/icon_buffer.cpp | 9 | ||||
-rw-r--r-- | library/icon_buffer.h | 10 | ||||
-rw-r--r-- | library/pch.h | 2 | ||||
-rw-r--r-- | library/process_xml.cpp | 20 | ||||
-rw-r--r-- | library/process_xml.h | 10 | ||||
-rw-r--r-- | library/resources.cpp | 2 | ||||
-rw-r--r-- | library/resources.h | 2 | ||||
-rw-r--r-- | library/soft_filter.cpp | 2 | ||||
-rw-r--r-- | library/soft_filter.h | 2 | ||||
-rw-r--r-- | library/statistics.cpp | 82 | ||||
-rw-r--r-- | library/statistics.h | 29 | ||||
-rw-r--r-- | library/status_handler.cpp | 2 | ||||
-rw-r--r-- | library/status_handler.h | 2 |
28 files changed, 326 insertions, 212 deletions
diff --git a/library/binary.cpp b/library/binary.cpp index cbcef238..1b722702 100644 --- a/library/binary.cpp +++ b/library/binary.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #include "binary.h" diff --git a/library/binary.h b/library/binary.h index bf477116..847c7169 100644 --- a/library/binary.h +++ b/library/binary.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #ifndef BINARY_H_INCLUDED diff --git a/library/cmp_filetime.h b/library/cmp_filetime.h new file mode 100644 index 00000000..b95eae5f --- /dev/null +++ b/library/cmp_filetime.h @@ -0,0 +1,66 @@ +#ifndef CMP_FILETIME_H_INCLUDED +#define CMP_FILETIME_H_INCLUDED + +#include <wx/longlong.h> +#include <wx/stopwatch.h> + + +namespace ffs3 +{ +//--------------------------------------------------------------------------------------------------------------- +inline +bool sameFileTime(const wxLongLong& a, const wxLongLong& b, size_t tolerance) +{ + if (a < b) + return b <= a + tolerance; + else + return a <= b + tolerance; +} +//--------------------------------------------------------------------------------------------------------------- + +class CmpFileTime +{ +public: + CmpFileTime(size_t tolerance) : + tolerance_(tolerance) {} + + enum Result + { + TIME_EQUAL, + TIME_LEFT_NEWER, + TIME_RIGHT_NEWER, + TIME_LEFT_INVALID, + TIME_RIGHT_INVALID + }; + + Result getResult(const wxLongLong& lhs, const wxLongLong& rhs) const + { + if (lhs == rhs) + return TIME_EQUAL; + + //number of seconds since Jan 1st 1970 + 1 year (needn't be too precise) + static const long oneYearFromNow = wxGetUTCTime() + 365 * 24 * 3600; //static in header: not a big deal in this case! + + //check for erroneous dates (but only if dates are not (EXACTLY) the same) + if (lhs < 0 || lhs > oneYearFromNow) //earlier than Jan 1st 1970 or more than one year in future + return TIME_LEFT_INVALID; + + if (rhs < 0 || rhs > oneYearFromNow) + return TIME_RIGHT_INVALID; + + if (sameFileTime(lhs, rhs, tolerance_)) //last write time may differ by up to 2 seconds (NTFS vs FAT32) + return TIME_EQUAL; + + //regular time comparison + if (lhs < rhs) + return TIME_RIGHT_NEWER; + else + return TIME_LEFT_NEWER; + } + +private: + const size_t tolerance_; +}; +} + +#endif // CMP_FILETIME_H_INCLUDED diff --git a/library/custom_grid.cpp b/library/custom_grid.cpp index e7a724a0..274ef778 100644 --- a/library/custom_grid.cpp +++ b/library/custom_grid.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #include "custom_grid.h" @@ -197,8 +197,11 @@ protected: static const wxColour COLOR_CMP_BLUE; static const wxColour COLOR_CMP_GREEN; static const wxColour COLOR_SYNC_BLUE; + static const wxColour COLOR_SYNC_BLUE_LIGHT; static const wxColour COLOR_SYNC_GREEN; + static const wxColour COLOR_SYNC_GREEN_LIGHT; static const wxColour COLOR_YELLOW; + static const wxColour COLOR_YELLOW_LIGHT; const GridView* gridDataView; //(very fast) access to underlying grid data :) @@ -217,8 +220,11 @@ const wxColour CustomGridTable::COLOR_CMP_RED( 249, 163, 165); const wxColour CustomGridTable::COLOR_CMP_BLUE( 144, 232, 246); const wxColour CustomGridTable::COLOR_CMP_GREEN( 147, 253, 159); const wxColour CustomGridTable::COLOR_SYNC_BLUE( 201, 203, 247); +const wxColour CustomGridTable::COLOR_SYNC_BLUE_LIGHT(201, 225, 247); const wxColour CustomGridTable::COLOR_SYNC_GREEN(197, 248, 190); +const wxColour CustomGridTable::COLOR_SYNC_GREEN_LIGHT(226, 248, 190); const wxColour CustomGridTable::COLOR_YELLOW( 247, 252, 62); +const wxColour CustomGridTable::COLOR_YELLOW_LIGHT(253, 252, 169); class CustomGridTableRim : public CustomGridTable @@ -331,10 +337,10 @@ protected: value = zToWx(dirObj.getFullName<side>()); break; case xmlAccess::FILENAME: - value = wxEmptyString; + value = zToWx(dirObj.getShortName<side>()); break; case xmlAccess::REL_PATH: - value = zToWx(dirObj.getRelativeName<side>()); + value = zToWx(dirObj.getParentRelativeName()); break; case xmlAccess::DIRECTORY: value = zToWx(dirObj.getBaseDirPf<side>()); @@ -527,10 +533,14 @@ private: case SO_DELETE_LEFT: case SO_OVERWRITE_LEFT: return COLOR_SYNC_BLUE; + case SO_COPY_METADATA_TO_LEFT: + return COLOR_SYNC_BLUE_LIGHT; case SO_CREATE_NEW_RIGHT: case SO_DELETE_RIGHT: case SO_OVERWRITE_RIGHT: return COLOR_SYNC_GREEN; + case SO_COPY_METADATA_TO_RIGHT: + return COLOR_SYNC_GREEN_LIGHT; case SO_UNRESOLVED_CONFLICT: return COLOR_YELLOW; case SO_DO_NOTHING: @@ -554,6 +564,8 @@ private: return *wxWHITE; case FILE_CONFLICT: return COLOR_YELLOW; + case FILE_DIFFERENT_METADATA: + return COLOR_YELLOW_LIGHT; } } } @@ -1919,9 +1931,11 @@ void CustomGridMiddle::showToolTip(int rowNumber, wxPoint pos) toolTip->show(getDescription(syncOp), pos, &GlobalResources::getInstance().getImageByName(wxT("syncDeleteRightAct"))); break; case SO_OVERWRITE_LEFT: + case SO_COPY_METADATA_TO_LEFT: toolTip->show(getDescription(syncOp), pos, &GlobalResources::getInstance().getImageByName(wxT("syncDirLeftAct"))); break; case SO_OVERWRITE_RIGHT: + case SO_COPY_METADATA_TO_RIGHT: toolTip->show(getDescription(syncOp), pos, &GlobalResources::getInstance().getImageByName(wxT("syncDirRightAct"))); break; case SO_DO_NOTHING: @@ -1958,6 +1972,9 @@ void CustomGridMiddle::showToolTip(int rowNumber, wxPoint pos) case FILE_EQUAL: toolTip->show(getDescription(cmpRes), pos, &GlobalResources::getInstance().getImageByName(wxT("equalAct"))); break; + case FILE_DIFFERENT_METADATA: + toolTip->show(getDescription(cmpRes), pos, &GlobalResources::getInstance().getImageByName(wxT("conflictAct"))); + break; case FILE_CONFLICT: toolTip->show(fsObj->getCatConflict(), pos, &GlobalResources::getInstance().getImageByName(wxT("conflictAct"))); break; @@ -2178,6 +2195,7 @@ void GridCellRendererMiddle::Draw(wxGrid& grid, dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("equalSmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); break; case FILE_CONFLICT: + case FILE_DIFFERENT_METADATA: dc.DrawLabel(wxEmptyString, GlobalResources::getInstance().getImageByName(wxT("conflictSmall")), rectShrinked, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL); break; } @@ -2232,8 +2250,10 @@ const wxBitmap& ffs3::getSyncOpImage(SyncOperation syncOp) case SO_DELETE_RIGHT: return GlobalResources::getInstance().getImageByName(wxT("deleteRightSmall")); case SO_OVERWRITE_RIGHT: + case SO_COPY_METADATA_TO_RIGHT: return GlobalResources::getInstance().getImageByName(wxT("syncDirRightSmall")); case SO_OVERWRITE_LEFT: + case SO_COPY_METADATA_TO_LEFT: return GlobalResources::getInstance().getImageByName(wxT("syncDirLeftSmall")); case SO_DO_NOTHING: return GlobalResources::getInstance().getImageByName(wxT("syncDirNoneSmall")); diff --git a/library/custom_grid.h b/library/custom_grid.h index 193b403d..1517230b 100644 --- a/library/custom_grid.h +++ b/library/custom_grid.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #ifndef CUSTOMGRID_H_INCLUDED @@ -167,12 +167,12 @@ protected: template <ffs3::SelectedSide side> void setTooltip(const wxMouseEvent& event); -void setOtherGrid(CustomGridRim* other); //call during initialization! + void setOtherGrid(CustomGridRim* other); //call during initialization! private: CustomGridTableRim* getGridDataTableRim() const; -void OnResizeColumn(wxGridSizeEvent& event); + void OnResizeColumn(wxGridSizeEvent& event); //this method is called when grid view changes: useful for parallel updating of multiple grids virtual void alignOtherGrids(CustomGrid* gridLeft, CustomGrid* gridMiddle, CustomGrid* gridRight); diff --git a/library/db_file.cpp b/library/db_file.cpp index a0f5099c..180ab0a4 100644 --- a/library/db_file.cpp +++ b/library/db_file.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #include "db_file.h" @@ -29,7 +29,7 @@ namespace { //------------------------------------------------------------------------------------------------------------------------------- const char FILE_FORMAT_DESCR[] = "FreeFileSync"; -const int FILE_FORMAT_VER = 4; +const int FILE_FORMAT_VER = 5; //------------------------------------------------------------------------------------------------------------------------------- @@ -40,11 +40,10 @@ public: FileInputStream(filename) { //read FreeFileSync file identifier - char formatDescr[sizeof(FILE_FORMAT_DESCR)]; + char formatDescr[sizeof(FILE_FORMAT_DESCR)] = {}; Read(formatDescr, sizeof(formatDescr)); //throw (FileError) - formatDescr[sizeof(formatDescr) - 1] = 0; - if (std::string(formatDescr) != FILE_FORMAT_DESCR) + if (!std::equal(FILE_FORMAT_DESCR, FILE_FORMAT_DESCR + sizeof(FILE_FORMAT_DESCR), formatDescr)) throw FileError(wxString(_("Incompatible synchronization database format:")) + wxT(" \n") + wxT("\"") + zToWx(filename) + wxT("\"")); } @@ -75,6 +74,10 @@ class ReadDirInfo : public util::ReadInputStream public: ReadDirInfo(wxInputStream& stream, const wxString& errorObjName, DirInformation& dirInfo) : ReadInputStream(stream, errorObjName) { + //|------------------------------------------------------------------------------------- + //| ensure 32/64 bit portability: used fixed size data types only e.g. boost::uint32_t | + //|------------------------------------------------------------------------------------- + //read filter settings dirInfo.filter = BaseFilter::loadFilter(getStream()); check(); @@ -86,15 +89,15 @@ public: private: void execute(DirContainer& dirCont) const { - size_t fileCount = readNumberC<size_t>(); + boost::uint32_t fileCount = readNumberC<boost::uint32_t>(); while (fileCount-- != 0) readSubFile(dirCont); - size_t symlinkCount = readNumberC<size_t>(); + boost::uint32_t symlinkCount = readNumberC<boost::uint32_t>(); while (symlinkCount-- != 0) readSubLink(dirCont); - size_t dirCount = readNumberC<size_t>(); + boost::uint32_t dirCount = readNumberC<boost::uint32_t>(); while (dirCount-- != 0) readSubDirectory(dirCont); } @@ -104,11 +107,11 @@ private: //attention: order of function argument evaluation is undefined! So do it one after the other... const Zstring shortName = readStringC(); //file name - const long modHigh = readNumberC<long>(); - const unsigned long modLow = readNumberC<unsigned long>(); + const boost::int32_t modHigh = readNumberC<boost::int32_t>(); + const boost::uint32_t modLow = readNumberC<boost::uint32_t>(); - const unsigned long sizeHigh = readNumberC<unsigned long>(); - const unsigned long sizeLow = readNumberC<unsigned long>(); + const boost::uint32_t sizeHigh = readNumberC<boost::uint32_t>(); + const boost::uint32_t sizeLow = readNumberC<boost::uint32_t>(); //const util::FileID fileIdentifier(stream_); //check(); @@ -122,11 +125,11 @@ private: void readSubLink(DirContainer& dirCont) const { //attention: order of function argument evaluation is undefined! So do it one after the other... - const Zstring shortName = readStringC(); //file name - const long modHigh = readNumberC<long>(); - const unsigned long modLow = readNumberC<unsigned long>(); - const Zstring targetPath = readStringC(); //file name - const LinkDescriptor::LinkType linkType = static_cast<LinkDescriptor::LinkType>(readNumberC<int>()); + const Zstring shortName = readStringC(); //file name + const boost::int32_t modHigh = readNumberC<boost::int32_t>(); + const boost::uint32_t modLow = readNumberC<boost::uint32_t>(); + const Zstring targetPath = readStringC(); //file name + const LinkDescriptor::LinkType linkType = static_cast<LinkDescriptor::LinkType>(readNumberC<boost::int32_t>()); dirCont.addSubLink(shortName, LinkDescriptor(wxLongLong(modHigh, modLow), targetPath, linkType)); @@ -141,10 +144,13 @@ private: } }; - -typedef boost::shared_ptr<std::vector<char> > MemoryStreamPtr; //byte stream representing DirInformation -typedef std::map<util::UniqueId, MemoryStreamPtr> DirectoryTOC; //list of streams ordered by a UUID pointing to their partner database -typedef std::pair<util::UniqueId, DirectoryTOC> DbStreamData; //header data: UUID representing this database, item data: list of dir-streams +namespace +{ +typedef std::string UniqueId; +typedef boost::shared_ptr<std::vector<char> > MemoryStreamPtr; //byte stream representing DirInformation +typedef std::map<UniqueId, MemoryStreamPtr> DirectoryTOC; //list of streams ordered by a UUID pointing to their partner database +typedef std::pair<UniqueId, DirectoryTOC> DbStreamData; //header data: UUID representing this database, item data: list of dir-streams +} /* Example left side right side --------- ---------- @@ -160,21 +166,26 @@ class ReadFileStream : public util::ReadInputStream public: ReadFileStream(wxInputStream& stream, const wxString& filename, DbStreamData& output) : ReadInputStream(stream, filename) { - if (readNumberC<int>() != FILE_FORMAT_VER) //read file format version + //|------------------------------------------------------------------------------------- + //| ensure 32/64 bit portability: used fixed size data types only e.g. boost::uint32_t | + //|------------------------------------------------------------------------------------- + + if (readNumberC<boost::int32_t>() != FILE_FORMAT_VER) //read file format version throw FileError(wxString(_("Incompatible synchronization database format:")) + wxT(" \n") + wxT("\"") + filename + wxT("\"")); //read DB id - output.first = util::UniqueId(getStream()); - check(); + const CharArray tmp = readArrayC(); + output.first.assign(tmp->begin(), tmp->end()); DirectoryTOC& dbList = output.second; dbList.clear(); - size_t dbCount = readNumberC<size_t>(); //number of databases: one for each sync-pair + boost::uint32_t dbCount = readNumberC<boost::uint32_t>(); //number of databases: one for each sync-pair while (dbCount-- != 0) { - const util::UniqueId partnerID(getStream()); //DB id of partner databases - check(); + //DB id of partner databases + const CharArray tmp2 = readArrayC(); + const std::string partnerID(tmp2->begin(), tmp2->end()); CharArray buffer = readArrayC(); //read db-entry stream (containing DirInformation) @@ -188,8 +199,8 @@ DbStreamData loadFile(const Zstring& filename) //throw (FileError) { if (!ffs3::fileExists(filename)) throw FileErrorDatabaseNotExisting(wxString(_("Initial synchronization:")) + wxT(" \n\n") + - _("One of the FreeFileSync database files is not yet existing:") + wxT(" \n") + - wxT("\"") + zToWx(filename) + wxT("\"")); + _("One of the FreeFileSync database files is not yet existing:") + wxT(" \n") + + wxT("\"") + zToWx(filename) + wxT("\"")); //read format description (uncompressed) FileInputStreamDB uncompressed(filename); //throw (FileError) @@ -219,13 +230,13 @@ std::pair<DirInfoPtr, DirInfoPtr> ffs3::loadFromDisk(const BaseDirMapping& baseM if (dbLeft == dbEntriesLeft.second.end()) throw FileErrorDatabaseNotExisting(wxString(_("Initial synchronization:")) + wxT(" \n\n") + - _("One of the FreeFileSync database entries within the following file is not yet existing:") + wxT(" \n") + - wxT("\"") + zToWx(fileNameLeft) + wxT("\"")); + _("One of the FreeFileSync database entries within the following file is not yet existing:") + wxT(" \n") + + wxT("\"") + zToWx(fileNameLeft) + wxT("\"")); if (dbRight == dbEntriesRight.second.end()) throw FileErrorDatabaseNotExisting(wxString(_("Initial synchronization:")) + wxT(" \n\n") + - _("One of the FreeFileSync database entries within the following file is not yet existing:") + wxT(" \n") + - wxT("\"") + zToWx(fileNameRight) + wxT("\"")); + _("One of the FreeFileSync database entries within the following file is not yet existing:") + wxT(" \n") + + wxT("\"") + zToWx(fileNameRight) + wxT("\"")); //read streams into DirInfo boost::shared_ptr<DirInformation> dirInfoLeft(new DirInformation); @@ -278,13 +289,13 @@ private: { util::ProxyForEach<SaveDirInfo<side> > prx(*this); //grant std::for_each access to private parts of this class - writeNumberC<size_t>(std::count_if(hierObj.useSubFiles().begin(), hierObj.useSubFiles().end(), IsNonEmpty<side>())); //number of (existing) files + writeNumberC<boost::uint32_t>(std::count_if(hierObj.useSubFiles().begin(), hierObj.useSubFiles().end(), IsNonEmpty<side>())); //number of (existing) files std::for_each(hierObj.useSubFiles().begin(), hierObj.useSubFiles().end(), prx); - writeNumberC<size_t>(std::count_if(hierObj.useSubLinks().begin(), hierObj.useSubLinks().end(), IsNonEmpty<side>())); //number of (existing) files + writeNumberC<boost::uint32_t>(std::count_if(hierObj.useSubLinks().begin(), hierObj.useSubLinks().end(), IsNonEmpty<side>())); //number of (existing) files std::for_each(hierObj.useSubLinks().begin(), hierObj.useSubLinks().end(), prx); - writeNumberC<size_t>(std::count_if(hierObj.useSubDirs().begin(), hierObj.useSubDirs().end(), IsNonEmpty<side>())); //number of (existing) directories + writeNumberC<boost::uint32_t>(std::count_if(hierObj.useSubDirs().begin(), hierObj.useSubDirs().end(), IsNonEmpty<side>())); //number of (existing) directories std::for_each(hierObj.useSubDirs().begin(), hierObj.useSubDirs().end(), prx); } @@ -292,11 +303,11 @@ private: { if (!fileMap.isEmpty<side>()) { - writeStringC(fileMap.getObjShortName()); //file name - writeNumberC<long>( fileMap.getLastWriteTime<side>().GetHi()); //last modification time - writeNumberC<unsigned long>(fileMap.getLastWriteTime<side>().GetLo()); // - writeNumberC<unsigned long>(fileMap.getFileSize<side>().GetHi()); //filesize - writeNumberC<unsigned long>(fileMap.getFileSize<side>().GetLo()); // + writeStringC(fileMap.getShortName<side>()); //file name + writeNumberC<boost::int32_t> (fileMap.getLastWriteTime<side>().GetHi()); //last modification time + writeNumberC<boost::uint32_t>(fileMap.getLastWriteTime<side>().GetLo()); // + writeNumberC<boost::uint32_t>(fileMap.getFileSize<side>().GetHi()); //filesize + writeNumberC<boost::uint32_t>(fileMap.getFileSize<side>().GetLo()); // //fileMap.getFileID<side>().toStream(stream_); //unique file identifier //check(); @@ -307,11 +318,11 @@ private: { if (!linkObj.isEmpty<side>()) { - writeStringC(linkObj.getObjShortName()); - writeNumberC<long>( linkObj.getLastWriteTime<side>().GetHi()); //last modification time - writeNumberC<unsigned long>(linkObj.getLastWriteTime<side>().GetLo()); // + writeStringC(linkObj.getShortName<side>()); + writeNumberC<boost::int32_t> (linkObj.getLastWriteTime<side>().GetHi()); //last modification time + writeNumberC<boost::uint32_t>(linkObj.getLastWriteTime<side>().GetLo()); // writeStringC(linkObj.getTargetPath<side>()); - writeNumberC<int>(linkObj.getLinkType<side>()); + writeNumberC<boost::int32_t>(linkObj.getLinkType<side>()); } } @@ -319,7 +330,7 @@ private: { if (!dirMap.isEmpty<side>()) { - writeStringC(dirMap.getObjShortName()); //directory name + writeStringC(dirMap.getShortName<side>()); //directory name execute(dirMap); //recurse } } @@ -332,22 +343,22 @@ public: WriteFileStream(const DbStreamData& input, const wxString& filename, wxOutputStream& stream) : WriteOutputStream(filename, stream) { //save file format version - writeNumberC<int>(FILE_FORMAT_VER); + writeNumberC<boost::int32_t>(FILE_FORMAT_VER); //write DB id - input.first.toStream(getStream()); - check(); + writeArrayC(std::vector<char>(input.first.begin(), input.first.end())); const DirectoryTOC& dbList = input.second; - writeNumberC<size_t>(dbList.size()); //number of database records: one for each sync-pair + writeNumberC<boost::uint32_t>(static_cast<boost::uint32_t>(dbList.size())); //number of database records: one for each sync-pair for (DirectoryTOC::const_iterator i = dbList.begin(); i != dbList.end(); ++i) { - i->first.toStream(getStream()); //DB id of partner database - check(); + //DB id of partner database + writeArrayC(std::vector<char>(i->first.begin(), i->first.end())); - writeArrayC(*(i->second)); //write DirInformation stream + //write DirInformation stream + writeArrayC(*(i->second)); } } }; @@ -377,19 +388,16 @@ void saveFile(const DbStreamData& dbStream, const Zstring& filename) //throw (Fi } -bool entryExisting(const DirectoryTOC& table, const util::UniqueId& newKey, const MemoryStreamPtr& newValue) +bool entryExisting(const DirectoryTOC& table, const UniqueId& newKey, const MemoryStreamPtr& newValue) { DirectoryTOC::const_iterator iter = table.find(newKey); if (iter == table.end()) return false; - if (!iter->second.get()) - return !newValue.get(); - - if (!newValue.get()) - return false; + if (!newValue.get() || !iter->second.get()) + return !newValue.get() && !iter->second.get(); - return newValue->size() == iter->second->size() && std::equal(newValue->begin(), newValue->end(), iter->second->begin()); + return *newValue == *iter->second; } @@ -407,22 +415,27 @@ void ffs3::saveToDisk(const BaseDirMapping& baseMapping) //throw (FileError) //read file data: db ID + mapping of partner-ID/DirInfo-stream: may throw! DbStreamData dbEntriesLeft; - if (ffs3::fileExists(baseMapping.getDBFilename<LEFT_SIDE>())) - try - { - dbEntriesLeft = ::loadFile(baseMapping.getDBFilename<LEFT_SIDE>()); - } - catch(FileError&) {} //if error occurs: just overwrite old file! User is already informed about issues right after comparing! - //else -> dbEntriesLeft has empty mapping, but already a DB-ID! + try + { + dbEntriesLeft = ::loadFile(baseMapping.getDBFilename<LEFT_SIDE>()); + } + catch(FileError&) + { + //if error occurs: just overwrite old file! User is already informed about issues right after comparing! + //dbEntriesLeft has empty mapping, but already a DB-ID! + dbEntriesLeft.first = util::generateGUID(); + } //read file data: db ID + mapping of partner-ID/DirInfo-stream: may throw! DbStreamData dbEntriesRight; - if (ffs3::fileExists(baseMapping.getDBFilename<RIGHT_SIDE>())) - try - { - dbEntriesRight = ::loadFile(baseMapping.getDBFilename<RIGHT_SIDE>()); - } - catch(FileError&) {} //if error occurs: just overwrite old file! User is already informed about issues right after comparing! + try + { + dbEntriesRight = ::loadFile(baseMapping.getDBFilename<RIGHT_SIDE>()); + } + catch(FileError&) + { + dbEntriesRight.first = util::generateGUID(); + } //create new database entries MemoryStreamPtr dbEntryLeft(new std::vector<char>); diff --git a/library/db_file.h b/library/db_file.h index ea9d68ad..8b88473d 100644 --- a/library/db_file.h +++ b/library/db_file.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #ifndef DBFILE_H_INCLUDED diff --git a/library/detect_renaming.cpp b/library/detect_renaming.cpp index 617a3eba..3c491ae3 100644 --- a/library/detect_renaming.cpp +++ b/library/detect_renaming.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #include "detect_renaming.h" diff --git a/library/detect_renaming.h b/library/detect_renaming.h index 45bdf59d..ab974cf9 100644 --- a/library/detect_renaming.h +++ b/library/detect_renaming.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #ifndef DETECTRENAMING_H_INCLUDED diff --git a/library/dir_lock.cpp b/library/dir_lock.cpp index f4ed8e07..3d443b11 100644 --- a/library/dir_lock.cpp +++ b/library/dir_lock.cpp @@ -17,6 +17,7 @@ #include "../shared/serialize.h" #include <boost/cstdint.hpp> #include "../shared/build_info.h" +#include <wx/log.h> #ifdef FFS_WIN #include <tlhelp32.h> @@ -40,6 +41,9 @@ const size_t EMIT_LIFE_SIGN_INTERVAL = 5000; //show life sign; unit [ms] const size_t POLL_LIFE_SIGN_INTERVAL = 6000; //poll for life sign; unit [ms] const size_t DETECT_EXITUS_INTERVAL = 30000; //assume abandoned lock; unit [ms] +const char LOCK_FORMAT_DESCR[] = "FreeFileSync"; +const int LOCK_FORMAT_VER = 1; //lock file format version + typedef Zbase<Zchar, StorageDeepCopy> BasicString; //thread safe string class } @@ -72,7 +76,7 @@ public: } catch (const std::exception& e) //exceptions must be catched per thread { - wxMessageBox(wxString::FromAscii(e.what()), wxString(_("An exception occurred!")) + wxT("(Dirlock)"), wxOK | wxICON_ERROR); + wxSafeShowMessage(wxString(_("An exception occurred!")) + wxT("(Dirlock)"), wxString::FromAscii(e.what())); //simple wxMessageBox won't do for threads } } @@ -130,18 +134,6 @@ private: namespace { -bool somethingExists(const Zstring& objname) //throw() check whether any object with this name exists -{ -#ifdef FFS_WIN - return ::GetFileAttributes(applyLongPathPrefix(objname).c_str()) != INVALID_FILE_ATTRIBUTES; - -#elif defined FFS_LINUX - struct stat fileInfo; - return ::lstat(objname.c_str(), &fileInfo) == 0; -#endif -} - - void deleteLockFile(const Zstring& filename) //throw (FileError) { #ifdef FFS_WIN @@ -207,24 +199,25 @@ Zstring deleteAbandonedLockName(const Zstring& lockfilename) namespace { +//read string from file stream inline -std::string readString(wxInputStream& stream) //read string from file stream +std::string readString(wxInputStream& stream) //throw (std::exception) { const boost::uint32_t strLength = util::readNumber<boost::uint32_t>(stream); std::string output; - if (strLength > 0) - { - output.resize(strLength); - stream.Read(&output[0], strLength); - } + if (strLength > 0) + { + output.resize(strLength); //may throw for corrupted data + stream.Read(&output[0], strLength); + } return output; } inline void writeString(wxOutputStream& stream, const std::string& str) //write string to filestream -{ - const boost::uint32_t strLength = static_cast<boost::uint32_t>(str.length()); +{ + const boost::uint32_t strLength = static_cast<boost::uint32_t>(str.length()); util::writeNumber<boost::uint32_t>(stream, strLength); stream.Write(str.c_str(), strLength); } @@ -246,6 +239,7 @@ struct LockInformation { LockInformation() { + lockId = util::generateGUID(); #ifdef FFS_WIN procDescr.processId = ::GetCurrentProcessId(); #elif defined FFS_LINUX @@ -254,9 +248,16 @@ struct LockInformation procDescr.computerId = getComputerId(); } - LockInformation(wxInputStream& stream) : //read - lockId(util::UniqueId(stream)) + LockInformation(wxInputStream& stream) //read { + char formatDescr[sizeof(LOCK_FORMAT_DESCR)] = {}; + stream.Read(formatDescr, sizeof(LOCK_FORMAT_DESCR)); //file format header + const int lockFileVersion = util::readNumber<boost::int32_t>(stream); // + (void)lockFileVersion; + + //some format checking here? + + lockId = readString(stream); procDescr.processId = static_cast<ProcessId>(util::readNumber<boost::uint64_t>(stream)); //possible loss of precision (32/64 bit process) covered by buildId procDescr.computerId = readString(stream); } @@ -265,7 +266,10 @@ struct LockInformation { assert_static(sizeof(ProcessId) <= sizeof(boost::uint64_t)); //ensure portability - lockId.toStream(stream); + stream.Write(LOCK_FORMAT_DESCR, sizeof(LOCK_FORMAT_DESCR)); + util::writeNumber<boost::int32_t>(stream, LOCK_FORMAT_VER); + + writeString(stream, lockId); util::writeNumber<boost::uint64_t>(stream, procDescr.processId); writeString(stream, procDescr.computerId); } @@ -276,7 +280,7 @@ struct LockInformation typedef pid_t ProcessId; #endif - util::UniqueId lockId; //16 byte portable construct + std::string lockId; //16 byte UUID struct ProcessDescription { @@ -314,7 +318,6 @@ ProcessStatus getProcessStatus(const LockInformation::ProcessDescription& procDe if (!::Process32First(snapshot, //__in HANDLE hSnapshot, &processEntry)) //__inout LPPROCESSENTRY32 lppe return PROC_STATUS_NO_IDEA; - do { if (processEntry.th32ProcessID == procDescr.processId) @@ -335,7 +338,7 @@ ProcessStatus getProcessStatus(const LockInformation::ProcessDescription& procDe void writeLockInfo(const Zstring& lockfilename) //throw (FileError) { - //write GUID at the beginning of the file: this ID is a universal identifier for this lock (no matter what the path is, considering symlinks ,etc.) + //write GUID at the beginning of the file: this ID is a universal identifier for this lock (no matter what the path is, considering symlinks, distributed network, etc.) FileOutputStream lockFile(lockfilename); //throw FileError() LockInformation().toStream(lockFile); } @@ -349,7 +352,7 @@ LockInformation retrieveLockInfo(const Zstring& lockfilename) //throw (FileError } -util::UniqueId retrieveLockId(const Zstring& lockfilename) //throw (FileError, ErrorNotExisting) +std::string retrieveLockId(const Zstring& lockfilename) //throw (FileError, ErrorNotExisting) { return retrieveLockInfo(lockfilename).lockId; } @@ -541,7 +544,7 @@ public: try //actual check based on lock UUID, deadlock prevention: "lockfilename" may be an alternative name for an already active lock { - const util::UniqueId lockId = retrieveLockId(lockfilename); //throw (FileError, ErrorNotExisting) + const std::string lockId = retrieveLockId(lockfilename); //throw (FileError, ErrorNotExisting) const boost::shared_ptr<SharedDirLock>& activeLock = findActive(lockId); //returns null-lock if not found if (activeLock) @@ -554,7 +557,7 @@ public: //not yet in buffer, so create a new directory lock boost::shared_ptr<SharedDirLock> newLock(new SharedDirLock(lockfilename, callback)); //throw (FileError) - const util::UniqueId newLockId = retrieveLockId(lockfilename); //throw (FileError, ErrorNotExisting) + const std::string newLockId = retrieveLockId(lockfilename); //throw (FileError, ErrorNotExisting) //update registry fileToUuid[lockfilename] = newLockId; //throw() @@ -566,7 +569,7 @@ public: private: LockAdmin() {} - boost::shared_ptr<SharedDirLock> findActive(const util::UniqueId& lockId) //returns null-lock if not found + boost::shared_ptr<SharedDirLock> findActive(const std::string& lockId) //returns null-lock if not found { UuidToLockMap::const_iterator iterLock = uuidToLock.find(lockId); return iterLock != uuidToLock.end() ? @@ -576,8 +579,9 @@ private: typedef boost::weak_ptr<SharedDirLock> SharedLock; - typedef std::map<Zstring, util::UniqueId, LessFilename> FileToUuidMap; //n:1 handle uppper/lower case correctly - typedef std::map<util::UniqueId, SharedLock> UuidToLockMap; //1:1 + typedef std::string UniqueId; + typedef std::map<Zstring, UniqueId, LessFilename> FileToUuidMap; //n:1 handle uppper/lower case correctly + typedef std::map<UniqueId, SharedLock> UuidToLockMap; //1:1 FileToUuidMap fileToUuid; //lockname |-> UUID; locks can be referenced by a lockfilename or alternatively a UUID UuidToLockMap uuidToLock; //UUID |-> "shared lock ownership" diff --git a/library/dir_lock.h b/library/dir_lock.h index fba65d2b..9ae4da08 100644 --- a/library/dir_lock.h +++ b/library/dir_lock.h @@ -19,7 +19,7 @@ RAII structure to place a directory lock against other FFS processes: - ownership shared between all object instances refering to a specific lock location(= UUID) - can be copied safely and efficiently! (ref-counting) - detects and resolves abandoned locks (instantly if lock is associated with local pc, else after 30 seconds) - - race-free (Windows, almost on Linux) + - race-free (Windows, almost on Linux(NFS)) */ class DirLock { diff --git a/library/error_log.cpp b/library/error_log.cpp index 9936a2ea..4f7c5847 100644 --- a/library/error_log.cpp +++ b/library/error_log.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #include "error_log.h" diff --git a/library/error_log.h b/library/error_log.h index 876f78b9..d5696f80 100644 --- a/library/error_log.h +++ b/library/error_log.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #ifndef ERRORLOGGING_H_INCLUDED diff --git a/library/filter.cpp b/library/filter.cpp index 7697ea4b..789a5d81 100644 --- a/library/filter.cpp +++ b/library/filter.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #include "filter.h" diff --git a/library/filter.h b/library/filter.h index 91caff7d..c1be61eb 100644 --- a/library/filter.h +++ b/library/filter.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #ifndef FFS_FILTER_H_INCLUDED @@ -55,8 +55,8 @@ public: static FilterRef loadFilter(wxInputStream& stream); //CAVEAT!!! adapt this method for each new derivation!!! private: - virtual Zstring uniqueClassIdentifier() const = 0; //get identifier, used for serialization virtual void save(wxOutputStream& stream) const = 0; //serialization + virtual Zstring uniqueClassIdentifier() const = 0; //get identifier, used for serialization virtual bool cmpLessSameType(const BaseFilter& other) const = 0; //typeid(*this) == typeid(other) in this context! }; @@ -64,14 +64,15 @@ private: class NullFilter : public BaseFilter //no filtering at all { public: - static FilterRef load(wxInputStream& stream); //"serial constructor" virtual bool passFileFilter(const Zstring& relFilename) const; virtual bool passDirFilter(const Zstring& relDirname, bool* subObjMightMatch) const; virtual bool isNull() const; private: - virtual Zstring uniqueClassIdentifier() const; + friend class BaseFilter; virtual void save(wxOutputStream& stream) const {} + virtual Zstring uniqueClassIdentifier() const; + static FilterRef load(wxInputStream& stream); //"serial constructor" virtual bool cmpLessSameType(const BaseFilter& other) const; }; @@ -80,15 +81,16 @@ class NameFilter : public BaseFilter //standard filter by filename { public: NameFilter(const Zstring& includeFilter, const Zstring& excludeFilter); - static FilterRef load(wxInputStream& stream); //"serial constructor" virtual bool passFileFilter(const Zstring& relFilename) const; virtual bool passDirFilter(const Zstring& relDirname, bool* subObjMightMatch) const; virtual bool isNull() const; private: - virtual Zstring uniqueClassIdentifier() const; + friend class BaseFilter; virtual void save(wxOutputStream& stream) const; + virtual Zstring uniqueClassIdentifier() const; + static FilterRef load(wxInputStream& stream); //"serial constructor" virtual bool cmpLessSameType(const BaseFilter& other) const; std::set<Zstring> filterFileIn; //upper case (windows) @@ -105,15 +107,16 @@ class CombinedFilter : public BaseFilter //combine two filters to match if and { public: CombinedFilter(const FilterRef& first, const FilterRef& second) : first_(first), second_(second) {} - static FilterRef load(wxInputStream& stream); //"serial constructor" virtual bool passFileFilter(const Zstring& relFilename) const; virtual bool passDirFilter(const Zstring& relDirname, bool* subObjMightMatch) const; virtual bool isNull() const; private: - virtual Zstring uniqueClassIdentifier() const; + friend class BaseFilter; virtual void save(wxOutputStream& stream) const; + virtual Zstring uniqueClassIdentifier() const; + static FilterRef load(wxInputStream& stream); //"serial constructor" virtual bool cmpLessSameType(const BaseFilter& other) const; const FilterRef first_; diff --git a/library/icon_buffer.cpp b/library/icon_buffer.cpp index 20ff60f7..e03ec8c4 100644 --- a/library/icon_buffer.cpp +++ b/library/icon_buffer.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #include "icon_buffer.h" @@ -9,6 +9,7 @@ #include <map> #include <queue> #include <set> +#include <wx/log.h> #ifdef FFS_WIN #include <wx/msw/wrapwin.h> //includes "windows.h" @@ -321,7 +322,7 @@ void IconBuffer::WorkerThread::operator()() //thread entry } catch (const std::exception& e) //exceptions must be catched per thread { - wxMessageBox(wxString::FromAscii(e.what()), wxString(_("An exception occurred!")) + wxT("(Icon buffer)"), wxOK | wxICON_ERROR); + wxSafeShowMessage(wxString(_("An exception occurred!")) + wxT("(Icon buffer)"), wxString::FromAscii(e.what())); //simple wxMessageBox won't do for threads } } @@ -364,7 +365,7 @@ void IconBuffer::WorkerThread::doWork() //--------------------------------------------------------------------------------------------------- -class IconBuffer::IconDB : public std::map<BasicString, IconBuffer::IconHolder> {}; //entryName/icon -> ATTENTION: avoid ref-counting for this shared data structure! +class IconBuffer::IconDB : public std::map<BasicString, IconBuffer::IconHolder, LessFilename> {}; //entryName/icon -> ATTENTION: avoid ref-counting for this shared data structure! class IconBuffer::IconDbSequence : public std::queue<BasicString> {}; //entryName //--------------------------------------------------------------------------------------------------- @@ -427,7 +428,7 @@ void IconBuffer::insertIntoBuffer(const BasicString& entryName, const IconHolder assert(buffer->size() == bufSequence->size()); //remove elements if buffer becomes too big: - if (buffer->size() > BUFFER_SIZE) //limit buffer size: critical because GDI resources are limited (e.g. 10000 on XP per process) + if (buffer->size() > BUFFER_SIZE_MAX) //limit buffer size: critical because GDI resources are limited (e.g. 10000 on XP per process) { //remove oldest element buffer->erase(bufSequence->front()); diff --git a/library/icon_buffer.h b/library/icon_buffer.h index 3e021445..d273a970 100644 --- a/library/icon_buffer.h +++ b/library/icon_buffer.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #ifndef ICONBUFFER_H_INCLUDED @@ -36,14 +36,14 @@ private: IconBuffer(); ~IconBuffer(); - static const size_t BUFFER_SIZE = 800; //maximum number of icons to buffer + static const size_t BUFFER_SIZE_MAX = 800; //maximum number of icons to buffer class IconDB; class IconHolder; class IconDbSequence; //--------------------------------------------------------------------------------------------------- -typedef Zbase<Zchar, StorageDeepCopy> BasicString; //thread safe string class + typedef Zbase<Zchar, StorageDeepCopy> BasicString; //thread safe string class //avoid reference-counted objects for shared data: NOT THREADSAFE!!! (implicitly shared variable: ref-count) //--------------------------------------------------------------------------------------------------- @@ -54,8 +54,8 @@ typedef Zbase<Zchar, StorageDeepCopy> BasicString; //thread safe string class static IconHolder getAssociatedIconByExt(const BasicString& extension); #ifdef FFS_WIN -static BasicString getFileExtension(const BasicString& filename); -static bool isPriceyExtension(const BasicString& extension); + static BasicString getFileExtension(const BasicString& filename); + static bool isPriceyExtension(const BasicString& extension); #endif //---------------------- Shared Data ------------------------- diff --git a/library/pch.h b/library/pch.h index f7ff59ab..a8d6ae30 100644 --- a/library/pch.h +++ b/library/pch.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #ifndef FFS_PRECOMPILED_HEADER diff --git a/library/process_xml.cpp b/library/process_xml.cpp index bccd8e3a..c4e80d17 100644 --- a/library/process_xml.cpp +++ b/library/process_xml.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #include "process_xml.h" @@ -432,6 +432,10 @@ void FfsXmlParser::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputCfg //folder dependency check readXmlElementLogging("CheckForDependentFolders", optionalDialogs, outputCfg.optDialogs.warningDependentFolders); + + //check for multi write access for directory as part of multiple pairs + readXmlElementLogging("CheckForMultipleWriteAccess", optionalDialogs, outputCfg.optDialogs.warningMultiFolderWriteAccess); + //significant difference check readXmlElementLogging("CheckForSignificantDifference", optionalDialogs, outputCfg.optDialogs.warningSignificantDifference); //check free disk space @@ -517,9 +521,7 @@ void FfsXmlParser::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputCfg //load config history elements readXmlElementLogging("Folder", historyRight, outputCfg.gui.folderHistoryRight); - - readXmlElementLogging("SelectedTabBottomLeft", mainWindow, outputCfg.gui.selectedTabBottomLeft); - + readXmlElementLogging("Perspective", mainWindow, outputCfg.gui.guiPerspectiveLast); //external applications const TiXmlElement* extApps = TiXmlHandleConst(gui).FirstChild("ExternalApplications").FirstChild("Commandline").ToElement(); @@ -542,9 +544,6 @@ void FfsXmlParser::readXmlGlobalSettings(xmlAccess::XmlGlobalSettings& outputCfg //load config file history const TiXmlElement* cfgHistory = TiXmlHandleConst(gui).FirstChild("ConfigHistory").ToElement(); - //load max. history size - readXmlAttributeLogging("MaximumSize", cfgHistory, outputCfg.gui.cfgHistoryMax); - //load config history elements readXmlElementLogging("File", cfgHistory, outputCfg.gui.cfgFileHistory); @@ -846,6 +845,9 @@ bool writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings& inputCfg, TiXmlD //warning: dependent folders addXmlElement("CheckForDependentFolders", inputCfg.optDialogs.warningDependentFolders, optionalDialogs); + //check for multi write access for directory as part of multiple pairs + addXmlElement("CheckForMultipleWriteAccess", inputCfg.optDialogs.warningMultiFolderWriteAccess, optionalDialogs); + //significant difference check addXmlElement("CheckForSignificantDifference", inputCfg.optDialogs.warningSignificantDifference, optionalDialogs); @@ -941,7 +943,7 @@ bool writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings& inputCfg, TiXmlD addXmlElement("Folder", inputCfg.gui.folderHistoryLeft, historyLeft); addXmlElement("Folder", inputCfg.gui.folderHistoryRight, historyRight); - addXmlElement("SelectedTabBottomLeft", inputCfg.gui.selectedTabBottomLeft, mainWindow); + addXmlElement("Perspective", inputCfg.gui.guiPerspectiveLast, mainWindow); //external applications TiXmlElement* extApp = new TiXmlElement("ExternalApplications"); @@ -960,7 +962,6 @@ bool writeXmlGlobalSettings(const xmlAccess::XmlGlobalSettings& inputCfg, TiXmlD TiXmlElement* cfgHistory = new TiXmlElement("ConfigHistory"); gui->LinkEndChild(cfgHistory); - addXmlAttribute("MaximumSize", inputCfg.gui.cfgHistoryMax, cfgHistory); addXmlElement("File", inputCfg.gui.cfgFileHistory, cfgHistory); @@ -992,6 +993,7 @@ wxString xmlAccess::getGlobalConfigFile() void xmlAccess::OptionalDialogs::resetDialogs() { warningDependentFolders = true; + warningMultiFolderWriteAccess = true; warningSignificantDifference = true; warningNotEnoughDiskSpace = true; warningUnresolvedConflicts = true; diff --git a/library/process_xml.h b/library/process_xml.h index 24a2fe9b..92d94d14 100644 --- a/library/process_xml.h +++ b/library/process_xml.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #ifndef PROCESSXML_H_INCLUDED @@ -100,6 +100,7 @@ struct OptionalDialogs void resetDialogs(); bool warningDependentFolders; + bool warningMultiFolderWriteAccess; bool warningSignificantDifference; bool warningNotEnoughDiskSpace; bool warningUnresolvedConflicts; @@ -142,10 +143,8 @@ struct XmlGlobalSettings isMaximized(false), autoAdjustColumnsLeft(false), autoAdjustColumnsRight(false), - cfgHistoryMax(10), folderHistLeftMax(12), folderHistRightMax(12), - selectedTabBottomLeft(0), deleteOnBothSides(false), useRecyclerForManualDeletion(true), //enable if OS supports it; else user will have to activate first and then get an error message #ifdef FFS_WIN @@ -187,7 +186,6 @@ struct XmlGlobalSettings ExternalApps externelApplications; std::vector<wxString> cfgFileHistory; - unsigned int cfgHistoryMax; std::vector<wxString> folderHistoryLeft; unsigned int folderHistLeftMax; @@ -195,8 +193,6 @@ struct XmlGlobalSettings std::vector<wxString> folderHistoryRight; unsigned int folderHistRightMax; - int selectedTabBottomLeft; - bool deleteOnBothSides; bool useRecyclerForManualDeletion; bool textSearchRespectCase; @@ -205,6 +201,8 @@ struct XmlGlobalSettings size_t addFolderPairCountMax; long lastUpdateCheck; //time of last update check + + wxString guiPerspectiveLast; //used by wxAuiManager } gui; //--------------------------------------------------------------------- diff --git a/library/resources.cpp b/library/resources.cpp index 637dfea3..5ef33826 100644 --- a/library/resources.cpp +++ b/library/resources.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #include "resources.h" diff --git a/library/resources.h b/library/resources.h index d2e7ce49..776fe785 100644 --- a/library/resources.h +++ b/library/resources.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #ifndef RESOURCES_H_INCLUDED diff --git a/library/soft_filter.cpp b/library/soft_filter.cpp index 18dcfd54..1c191b98 100644 --- a/library/soft_filter.cpp +++ b/library/soft_filter.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #include "soft_filter.h" diff --git a/library/soft_filter.h b/library/soft_filter.h index dc889245..ad81ea44 100644 --- a/library/soft_filter.h +++ b/library/soft_filter.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #ifndef SOFTFILTER_H_INCLUDED diff --git a/library/statistics.cpp b/library/statistics.cpp index d246a7cc..7a77740c 100644 --- a/library/statistics.cpp +++ b/library/statistics.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #include "statistics.h" @@ -29,7 +29,7 @@ RetrieveStatistics::~RetrieveStatistics() outputFile.Write(wxT("Time(ms);Objects;Data\n")); - for (std::vector<statEntry>::const_iterator i = data.begin(); i != data.end(); ++i) + for (std::vector<StatEntry>::const_iterator i = data.begin(); i != data.end(); ++i) { using common::numberToString; outputFile.Write(numberToString(i->time)); @@ -44,7 +44,7 @@ RetrieveStatistics::~RetrieveStatistics() void RetrieveStatistics::writeEntry(const double value, const int objects) { - statEntry newEntry; + StatEntry newEntry; newEntry.value = value; newEntry.objects = objects; newEntry.time = timer->Time(); @@ -104,7 +104,7 @@ wxString Statistics::formatRemainingTime(double timeInMs) const formattedTime -= formattedTime % 5; //"floor" } else - formattedTime = int(remainingTime); //"floor" + formattedTime = static_cast<int>(remainingTime); //"floor" } remainingTimeLast = formattedTime; @@ -115,10 +115,10 @@ wxString Statistics::formatRemainingTime(double timeInMs) const } -Statistics::Statistics(const int totalObjectCount, - const double totalDataAmount, - const unsigned windowSizeRemainingTime, - const unsigned windowSizeBytesPerSecond) : +Statistics::Statistics(int totalObjectCount, + double totalDataAmount, + unsigned windowSizeRemainingTime, + unsigned windowSizeBytesPerSecond) : objectsTotal(totalObjectCount), dataTotal(totalDataAmount), windowSizeRemTime(windowSizeRemainingTime), @@ -132,20 +132,27 @@ Statistics::~Statistics() delete timer; } -void Statistics::addMeasurement(const int objectsCurrent, const double dataCurrent) +void Statistics::addMeasurement(int objectsCurrent, double dataCurrent) { - record newEntry; - newEntry.objects = objectsCurrent; - newEntry.data = dataCurrent; - newEntry.time = timer->Time(); + Record newRecord; + newRecord.objects = objectsCurrent; + newRecord.data = dataCurrent; + + const long currentTime = timer->Time(); + + const TimeRecordMap::value_type newEntry(currentTime, newRecord); //insert new record - measurements.push_back(newEntry); + if (!measurements.empty()) + measurements.insert(--measurements.end(), newEntry); //use fact that time is monotonously ascending + else + measurements.insert(newEntry); //remove all records earlier than "currentTime - windowSize" - const long newBegin = newEntry.time - windowMax; - while (!measurements.empty() && measurements.front().time < newBegin) - measurements.pop_front(); + const long newBegin = currentTime - windowMax; + TimeRecordMap::iterator windowBegin = measurements.upper_bound(newBegin); + if (windowBegin != measurements.begin()) + measurements.erase(measurements.begin(), --windowBegin); //retain one point before newBegin in order to handle "measurement holes" } @@ -153,20 +160,19 @@ wxString Statistics::getRemainingTime() const { if (!measurements.empty()) { + const TimeRecordMap::value_type& backRecord = *measurements.rbegin(); //find start of records "window" - const record backElement = measurements.back(); - const long frontTime = backElement.time - windowSizeRemTime; - std::list<record>::const_iterator frontElement = measurements.end(); - do - { - --frontElement; - } - while (frontElement != measurements.begin() && frontElement->time > frontTime); + const long frontTime = backRecord.first - windowSizeRemTime; + TimeRecordMap::const_iterator windowBegin = measurements.upper_bound(frontTime); + if (windowBegin != measurements.begin()) + --windowBegin; //one point before window begin in order to handle "measurement holes" - const double timeDelta = backElement.time - frontElement->time; - const double dataDelta = backElement.data - frontElement->data; + const TimeRecordMap::value_type& frontRecord = *windowBegin; +//----------------------------------------------------------------------------------------------- + const double timeDelta = backRecord.first - frontRecord.first; + const double dataDelta = backRecord.second.data - frontRecord.second.data; - const double dataRemaining = dataTotal - backElement.data; + const double dataRemaining = dataTotal - backRecord.second.data; if (!isNull(dataDelta)) return formatRemainingTime(dataRemaining * timeDelta / dataDelta); @@ -180,17 +186,17 @@ wxString Statistics::getBytesPerSecond() const { if (!measurements.empty()) { + const TimeRecordMap::value_type& backRecord = *measurements.rbegin(); //find start of records "window" - const long frontTime = measurements.back().time - windowSizeBPS; - std::list<record>::const_iterator frontElement = measurements.end(); - do - { - --frontElement; - } - while (frontElement != measurements.begin() && frontElement->time > frontTime); - - const double timeDelta = measurements.back().time - frontElement->time; - const double dataDelta = measurements.back().data - frontElement->data; + const long frontTime = backRecord.first - windowSizeBPS; + TimeRecordMap::const_iterator windowBegin = measurements.upper_bound(frontTime); + if (windowBegin != measurements.begin()) + --windowBegin; //one point before window begin in order to handle "measurement holes" + + const TimeRecordMap::value_type& frontRecord = *windowBegin; +//----------------------------------------------------------------------------------------------- + const double timeDelta = backRecord.first - frontRecord.first; + const double dataDelta = backRecord.second.data - frontRecord.second.data; if (!isNull(timeDelta)) return ffs3::formatFilesizeToShortString(dataDelta * 1000 / timeDelta) + _("/sec"); diff --git a/library/statistics.h b/library/statistics.h index 26e8c196..a9692d77 100644 --- a/library/statistics.h +++ b/library/statistics.h @@ -1,14 +1,14 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #ifndef STATISTICS_H_INCLUDED #define STATISTICS_H_INCLUDED #include <vector> -#include <list> +#include <map> #include <memory> #include <wx/defs.h> @@ -27,14 +27,14 @@ public: void writeEntry(const double value, const int objects); private: - struct statEntry + struct StatEntry { long time; int objects; double value; }; - std::vector<statEntry> data; + std::vector<StatEntry> data; std::auto_ptr<wxStopWatch> timer; }; @@ -42,14 +42,14 @@ private: class Statistics { public: - Statistics(const int totalObjectCount, - const double totalDataAmount, - const unsigned windowSizeRemainingTime, //time in ms - const unsigned windowSizeBytesPerSecond); //time in ms + Statistics(int totalObjectCount, + double totalDataAmount, + unsigned windowSizeRemainingTime, //time in ms + unsigned windowSizeBytesPerSecond); //time in ms ~Statistics(); - void addMeasurement(const int objectsCurrent, const double dataCurrent); + void addMeasurement(int objectsCurrent, double dataCurrent); wxString getRemainingTime() const; //returns the remaining time in milliseconds wxString getBytesPerSecond() const; @@ -57,7 +57,7 @@ public: void resumeTimer(); private: - wxString formatRemainingTime(const double timeInMs) const; + wxString formatRemainingTime(double timeInMs) const; const int objectsTotal; const double dataTotal; @@ -68,14 +68,15 @@ private: mutable int remainingTimeLast; //used for "smoothening" remaining time - struct record + struct Record { - int objects; + int objects; //object count double data; //unit: bytes - long time; //unit: milliseconds }; - std::list<record> measurements; + typedef std::multimap<long, Record> TimeRecordMap; //time, unit: milliseconds + TimeRecordMap measurements; // + wxStopWatch* timer; }; diff --git a/library/status_handler.cpp b/library/status_handler.cpp index 0f953a32..e81746a4 100644 --- a/library/status_handler.cpp +++ b/library/status_handler.cpp @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #include "status_handler.h" diff --git a/library/status_handler.h b/library/status_handler.h index c15a80ba..d89c4f5b 100644 --- a/library/status_handler.h +++ b/library/status_handler.h @@ -1,7 +1,7 @@ // ************************************************************************** // * This file is part of the FreeFileSync project. It is distributed under * // * GNU General Public License: http://www.gnu.org/licenses/gpl.html * -// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de) * +// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) * // ************************************************************************** // #ifndef STATUSHANDLER_H_INCLUDED |