summaryrefslogtreecommitdiff
path: root/comparison.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'comparison.cpp')
-rw-r--r--comparison.cpp609
1 files changed, 326 insertions, 283 deletions
diff --git a/comparison.cpp b/comparison.cpp
index 0ad2e1fb..f90b47de 100644
--- a/comparison.cpp
+++ b/comparison.cpp
@@ -15,160 +15,25 @@
using namespace FreeFileSync;
-CompareProcess::CompareProcess(bool lineBreakOnMessages, bool handleDstOnFat32Drives, StatusHandler* handler) :
- includeLineBreak(lineBreakOnMessages),
- handleDstOnFat32(handleDstOnFat32Drives),
- statusUpdater(handler),
- txtComparingContentOfFiles(_("Comparing content of files %x"))
-{
- if (includeLineBreak)
- txtComparingContentOfFiles.Replace(wxT("%x"), wxT("\n\"%x\""), false);
- else
- txtComparingContentOfFiles.Replace(wxT("%x"), wxT("\"%x\""), false);
-}
-
-
-struct MemoryAllocator
-{
- MemoryAllocator()
- {
- buffer1 = new unsigned char[bufferSize];
- buffer2 = new unsigned char[bufferSize];
- }
-
- ~MemoryAllocator()
- {
- delete [] buffer1;
- delete [] buffer2;
- }
-
- static const unsigned int bufferSize = 1024 * 512; //512 kb seems to be the perfect buffer size
- unsigned char* buffer1;
- unsigned char* buffer2;
-};
-
-
-bool filesHaveSameContent(const Zstring& filename1, const Zstring& filename2)
-{
- static MemoryAllocator memory;
-
- wxFFile file1(filename1.c_str(), wxT("rb"));
- if (!file1.IsOpened())
- throw FileError(Zstring(_("Error reading file:")) + wxT(" \"") + filename1 + wxT("\""));
-
- wxFFile file2(filename2.c_str(), wxT("rb"));
- if (!file2.IsOpened()) //NO cleanup necessary for (wxFFile) file1
- throw FileError(Zstring(_("Error reading file:")) + wxT(" \"") + filename2 + wxT("\""));
-
- do
- {
- size_t length1 = file1.Read(memory.buffer1, memory.bufferSize);
- if (file1.Error()) throw FileError(Zstring(_("Error reading file:")) + wxT(" \"") + filename1 + wxT("\""));
-
- size_t length2 = file2.Read(memory.buffer2, memory.bufferSize);
- if (file2.Error()) throw FileError(Zstring(_("Error reading file:")) + wxT(" \"") + filename2 + wxT("\""));
-
- if (length1 != length2 || memcmp(memory.buffer1, memory.buffer2, length1) != 0)
- return false;
- }
- while (!file1.Eof());
-
- if (!file2.Eof())
- return false;
-
- return true;
-}
-
-
-//handle execution of a method while updating the UI
-class UpdateWhileComparing : public UpdateWhileExecuting
-{
-public:
- UpdateWhileComparing() {}
- ~UpdateWhileComparing() {}
-
- Zstring file1;
- Zstring file2;
- bool success;
- Zstring errorMessage;
- bool result;
-
-private:
- void longRunner() //virtual method implementation
- {
- try
- {
- result = filesHaveSameContent(file1, file2);
- success = true;
- }
- catch (FileError& error)
- {
- success = false;
- errorMessage = error.show();
- }
- }
-};
-
-
-bool filesHaveSameContentMultithreaded(const Zstring& filename1, const Zstring& filename2, StatusHandler* updateClass)
-{
- static UpdateWhileComparing cmpAndUpdate; //single instantiation: thread enters wait phase after each execution
-
- cmpAndUpdate.waitUntilReady();
-
- //longRunner is called from thread, but no mutex needed here, since thread is in waiting state!
- cmpAndUpdate.file1 = filename1;
- cmpAndUpdate.file2 = filename2;
-
- cmpAndUpdate.execute(updateClass);
-
- //no mutex needed here since longRunner is finished
- if (!cmpAndUpdate.success)
- throw FileError(cmpAndUpdate.errorMessage);
-
- return cmpAndUpdate.result;
-}
-
-
-void calcTotalDataForCompare(int& objectsTotal, double& dataTotal, const FileCompareResult& grid, const std::set<int>& rowsToCompare)
-{
- dataTotal = 0;
-
- for (std::set<int>::iterator i = rowsToCompare.begin(); i != rowsToCompare.end(); ++i)
- {
- const FileCompareLine& gridline = grid[*i];
-
- dataTotal+= gridline.fileDescrLeft.fileSize.ToDouble();
- dataTotal+= gridline.fileDescrRight.fileSize.ToDouble();
- }
-
- objectsTotal = rowsToCompare.size() * 2;
-}
-
-
-inline
-void writeText(const wxChar* text, const int length, wxChar*& currentPos)
-{
- memcpy(currentPos, text, length * sizeof(wxChar));
- currentPos+=length;
-}
-
class GetAllFilesFull : public FullDetailFileTraverser
{
public:
- GetAllFilesFull(DirectoryDescrType& output, Zstring dirThatIsSearched, const bool includeLineBreak, StatusHandler* updateClass) :
+ GetAllFilesFull(DirectoryDescrType& output, Zstring dirThatIsSearched, StatusHandler* handler) :
m_output(output),
directory(dirThatIsSearched),
- statusUpdater(updateClass)
+ statusHandler(handler)
{
- assert(updateClass);
prefixLength = directory.length();
+ textScanning = Zstring(_("Scanning:")) + wxT(" \n"); //performance optimization
+ }
- if (includeLineBreak)
- textScanning = Zstring(_("Scanning:")) + wxT("\n"); //performance optimization
- else
- textScanning = Zstring(_("Scanning:")) + wxT(" "); //performance optimization
+
+ inline
+ void writeText(const wxChar* text, const int length, wxChar*& currentPos)
+ {
+ memcpy(currentPos, text, length * sizeof(wxChar));
+ currentPos+=length;
}
@@ -197,11 +62,11 @@ public:
*position = 0;
//update UI/commandline status information
- statusUpdater->updateStatusText(statusText);
+ statusHandler->updateStatusText(statusText);
//add 1 element to the progress indicator
- statusUpdater->updateProcessedData(1, 0); //NO performance issue at all
+ statusHandler->updateProcessedData(1, 0); //NO performance issue at all
//trigger display refresh
- statusUpdater->requestUiRefresh();
+ statusHandler->requestUiRefresh();
return wxDIR_CONTINUE;
}
@@ -238,11 +103,11 @@ public:
*position = 0;
//update UI/commandline status information
- statusUpdater->updateStatusText(statusText);
+ statusHandler->updateStatusText(statusText);
//add 1 element to the progress indicator
- statusUpdater->updateProcessedData(1, 0); //NO performance issue at all
+ statusHandler->updateProcessedData(1, 0); //NO performance issue at all
//trigger display refresh
- statusUpdater->requestUiRefresh();
+ statusHandler->requestUiRefresh();
return wxDIR_CONTINUE;
}
@@ -250,7 +115,20 @@ public:
wxDirTraverseResult GetAllFilesFull::OnError(const Zstring& errorText) //virtual impl.
{
- wxMessageBox(errorText.c_str(), _("Error"));
+ while (true)
+ {
+ ErrorHandler::Response rv = statusHandler->reportError(errorText);
+ if (rv == ErrorHandler::IGNORE_ERROR)
+ return wxDIR_CONTINUE;
+ else if (rv == ErrorHandler::RETRY)
+ ; //I have to admit "retry" is a bit of a fake here... at least the user has opportunity to abort!
+ else
+ {
+ assert (false);
+ return wxDIR_CONTINUE;
+ }
+ }
+
return wxDIR_CONTINUE;
}
@@ -259,25 +137,10 @@ private:
Zstring directory;
int prefixLength;
Zstring textScanning;
- StatusHandler* statusUpdater;
+ StatusHandler* statusHandler;
};
-void generateFileAndFolderDescriptions(DirectoryDescrType& output, const Zstring& directory, const bool includeLineBreak, StatusHandler* updateClass)
-{
- assert (updateClass);
-
- output.clear();
-
- //get all files and folders from directory (and subdirectories) + information
- const Zstring directoryFormatted = FreeFileSync::getFormattedDirectoryName(directory);
-
- GetAllFilesFull traverser(output, directoryFormatted, includeLineBreak, updateClass);
-
- traverseInDetail(directoryFormatted, &traverser);
-}
-
-
struct DescrBufferLine
{
Zstring directoryName;
@@ -294,9 +157,13 @@ struct DescrBufferLine
};
-class DirectoryDescrBuffer //buffer multiple scans of the same directories
+class FreeFileSync::DirectoryDescrBuffer //buffer multiple scans of the same directories
{
public:
+ DirectoryDescrBuffer(const bool traverseSymbolicLinks, StatusHandler* statusUpdater) :
+ m_traverseSymbolicLinks(traverseSymbolicLinks),
+ m_statusUpdater(statusUpdater) {}
+
~DirectoryDescrBuffer()
{
//clean up
@@ -304,13 +171,13 @@ public:
delete i->directoryDesc;
}
- DirectoryDescrType* getDirectoryDescription(const Zstring& directory, const bool includeLineBreak, StatusHandler* statusUpdater)
+ DirectoryDescrType* getDirectoryDescription(const Zstring& directoryFormatted)
{
DescrBufferLine bufferEntry;
- bufferEntry.directoryName = directory;
+ bufferEntry.directoryName = directoryFormatted;
- std::set<DescrBufferLine>::iterator entryFound;
- if ((entryFound = buffer.find(bufferEntry)) != buffer.end())
+ std::set<DescrBufferLine>::iterator entryFound = buffer.find(bufferEntry);
+ if (entryFound != buffer.end())
{
//entry found in buffer; return
return entryFound->directoryDesc;
@@ -321,18 +188,234 @@ public:
bufferEntry.directoryDesc = new DirectoryDescrType;
buffer.insert(bufferEntry); //exception safety: insert into buffer right after creation!
- bufferEntry.directoryDesc->reserve(400000); //reserve space for up to 400000 files to avoid vector reallocations
+ bufferEntry.directoryDesc->reserve(400000); //reserve space for up to 400000 files to avoid too many vector reallocations
+
+ //get all files and folders from directoryFormatted (and subdirectories)
+ GetAllFilesFull traverser(*bufferEntry.directoryDesc, directoryFormatted, m_statusUpdater); //exceptions may be thrown!
+ traverseInDetail(directoryFormatted, m_traverseSymbolicLinks, &traverser);
- generateFileAndFolderDescriptions(*bufferEntry.directoryDesc, directory, includeLineBreak, statusUpdater); //exceptions may be thrown!
return bufferEntry.directoryDesc;
}
}
private:
std::set<DescrBufferLine> buffer;
+
+ const bool m_traverseSymbolicLinks;
+ StatusHandler* m_statusUpdater;
};
+bool foldersAreValidForComparison(const std::vector<FolderPair>& folderPairs, wxString& errorMessage)
+{
+ errorMessage.Clear();
+
+ for (std::vector<FolderPair>::const_iterator i = folderPairs.begin(); i != folderPairs.end(); ++i)
+ {
+ const Zstring leftFolderName = getFormattedDirectoryName(i->leftDirectory);
+ const Zstring rightFolderName = getFormattedDirectoryName(i->rightDirectory);
+
+ //check if folder name is empty
+ if (leftFolderName.empty() || rightFolderName.empty())
+ {
+ errorMessage = _("Please fill all empty directory fields.");
+ return false;
+ }
+
+ //check if folder exists
+ if (!wxDirExists(leftFolderName))
+ {
+ errorMessage = wxString(_("Directory does not exist:")) + wxT(" \"") + leftFolderName + wxT("\"");
+ return false;
+ }
+ if (!wxDirExists(rightFolderName))
+ {
+ errorMessage = wxString(_("Directory does not exist:")) + wxT(" \"") + rightFolderName + wxT("\"");
+ return false;
+ }
+ }
+ return true;
+}
+
+
+bool dependencyExists(const std::vector<Zstring>& folders, const Zstring& newFolder, wxString& warningMessage)
+{
+ warningMessage.Clear();
+
+ for (std::vector<Zstring>::const_iterator i = folders.begin(); i != folders.end(); ++i)
+ if (newFolder.StartsWith(*i) || i->StartsWith(newFolder))
+ {
+ warningMessage = wxString(_("Directories are dependent! Be careful when setting up synchronization rules:\n")) +
+ wxT("\"") + *i + wxT("\",\n") +
+ wxT("\"") + newFolder + wxT("\"");
+ return true;
+ }
+ return false;
+}
+
+
+bool foldersHaveDependencies(const std::vector<FolderPair>& folderPairs, wxString& warningMessage)
+{
+ warningMessage.Clear();
+
+ std::vector<Zstring> folders;
+ for (std::vector<FolderPair>::const_iterator i = folderPairs.begin(); i != folderPairs.end(); ++i)
+ {
+ const Zstring leftFolderName = getFormattedDirectoryName(i->leftDirectory);
+ const Zstring rightFolderName = getFormattedDirectoryName(i->rightDirectory);
+
+ if (dependencyExists(folders, leftFolderName, warningMessage))
+ return true;
+ folders.push_back(leftFolderName);
+
+ if (dependencyExists(folders, rightFolderName, warningMessage))
+ return true;
+ folders.push_back(rightFolderName);
+ }
+
+ return false;
+}
+
+
+CompareProcess::CompareProcess(const bool traverseSymLinks,
+ const bool handleDstOnFat32Drives,
+ bool& warningDependentFolders,
+ StatusHandler* handler) :
+ traverseSymbolicLinks(traverseSymLinks),
+ handleDstOnFat32(handleDstOnFat32Drives),
+ m_warningDependentFolders(warningDependentFolders),
+ statusUpdater(handler),
+ txtComparingContentOfFiles(_("Comparing content of files %x"))
+{
+ descriptionBuffer = new DirectoryDescrBuffer(traverseSymLinks, handler);
+ txtComparingContentOfFiles.Replace(wxT("%x"), wxT("\n\"%x\""), false);
+}
+
+
+CompareProcess::~CompareProcess()
+{
+ delete descriptionBuffer;
+}
+
+
+struct MemoryAllocator
+{
+ MemoryAllocator()
+ {
+ buffer1 = new unsigned char[bufferSize];
+ buffer2 = new unsigned char[bufferSize];
+ }
+
+ ~MemoryAllocator()
+ {
+ delete [] buffer1;
+ delete [] buffer2;
+ }
+
+ static const unsigned int bufferSize = 1024 * 512; //512 kb seems to be the perfect buffer size
+ unsigned char* buffer1;
+ unsigned char* buffer2;
+};
+
+
+bool filesHaveSameContent(const Zstring& filename1, const Zstring& filename2)
+{
+ static MemoryAllocator memory;
+
+ wxFFile file1(filename1.c_str(), wxT("rb"));
+ if (!file1.IsOpened())
+ throw FileError(Zstring(_("Error reading file:")) + wxT(" \"") + filename1 + wxT("\""));
+
+ wxFFile file2(filename2.c_str(), wxT("rb"));
+ if (!file2.IsOpened()) //NO cleanup necessary for (wxFFile) file1
+ throw FileError(Zstring(_("Error reading file:")) + wxT(" \"") + filename2 + wxT("\""));
+
+ do
+ {
+ size_t length1 = file1.Read(memory.buffer1, memory.bufferSize);
+ if (file1.Error()) throw FileError(Zstring(_("Error reading file:")) + wxT(" \"") + filename1 + wxT("\""));
+
+ size_t length2 = file2.Read(memory.buffer2, memory.bufferSize);
+ if (file2.Error()) throw FileError(Zstring(_("Error reading file:")) + wxT(" \"") + filename2 + wxT("\""));
+
+ if (length1 != length2 || memcmp(memory.buffer1, memory.buffer2, length1) != 0)
+ return false;
+ }
+ while (!file1.Eof());
+
+ if (!file2.Eof())
+ return false;
+
+ return true;
+}
+
+
+//handle execution of a method while updating the UI
+class UpdateWhileComparing : public UpdateWhileExecuting
+{
+public:
+ UpdateWhileComparing() {}
+ ~UpdateWhileComparing() {}
+
+ Zstring file1;
+ Zstring file2;
+ bool success;
+ Zstring errorMessage;
+ bool sameContent;
+
+private:
+ void longRunner() //virtual method implementation
+ {
+ try
+ {
+ sameContent = filesHaveSameContent(file1, file2);
+ success = true;
+ }
+ catch (FileError& error)
+ {
+ success = false;
+ errorMessage = error.show();
+ }
+ }
+};
+
+
+bool filesHaveSameContentMultithreaded(const Zstring& filename1, const Zstring& filename2, StatusHandler* updateClass)
+{
+ static UpdateWhileComparing cmpAndUpdate; //single instantiation: thread enters wait phase after each execution
+
+ cmpAndUpdate.waitUntilReady();
+
+ //longRunner is called from thread, but no mutex needed here, since thread is in waiting state!
+ cmpAndUpdate.file1 = filename1;
+ cmpAndUpdate.file2 = filename2;
+
+ cmpAndUpdate.execute(updateClass);
+
+ //no mutex needed here since longRunner is finished
+ if (!cmpAndUpdate.success)
+ throw FileError(cmpAndUpdate.errorMessage);
+
+ return cmpAndUpdate.sameContent;
+}
+
+
+void calcTotalDataForCompare(int& objectsTotal, double& dataTotal, const FileCompareResult& grid, const std::set<int>& rowsToCompare)
+{
+ dataTotal = 0;
+
+ for (std::set<int>::iterator i = rowsToCompare.begin(); i != rowsToCompare.end(); ++i)
+ {
+ const FileCompareLine& gridline = grid[*i];
+
+ dataTotal+= gridline.fileDescrLeft.fileSize.ToDouble();
+ dataTotal+= gridline.fileDescrRight.fileSize.ToDouble();
+ }
+
+ objectsTotal = rowsToCompare.size() * 2;
+}
+
+
inline
bool sameFileTime(const time_t a, const time_t b, const time_t tolerance)
{
@@ -343,39 +426,70 @@ bool sameFileTime(const time_t a, const time_t b, const time_t tolerance)
}
-void CompareProcess::startCompareProcess(const std::vector<FolderPair>& directoryPairsFormatted,
+void CompareProcess::startCompareProcess(const std::vector<FolderPair>& directoryPairs,
const CompareVariant cmpVar,
FileCompareResult& output) throw(AbortThisProcess)
{
#ifndef __WXDEBUG__
wxLogNull noWxLogs; //hide wxWidgets log messages in release build
#endif
- assert (statusUpdater);
- FileCompareResult output_tmp; //write to output not before END of process!
+
+ //format directory pairs
+ std::vector<FolderPair> directoryPairsFormatted;
+
+ for (std::vector<FolderPair>::const_iterator i = directoryPairs.begin(); i != directoryPairs.end(); ++i)
+ {
+ FolderPair newEntry;
+ newEntry.leftDirectory = FreeFileSync::getFormattedDirectoryName(i->leftDirectory);
+ newEntry.rightDirectory = FreeFileSync::getFormattedDirectoryName(i->rightDirectory);
+ directoryPairsFormatted.push_back(newEntry);
+ }
+
+ //some basic checks:
+
+ //check if folders are valid
+ wxString errorMessage;
+ if (!foldersAreValidForComparison(directoryPairsFormatted, errorMessage))
+ {
+ statusUpdater->reportFatalError(errorMessage.c_str());
+ return; //should be obsolete!
+ }
+
+ //check if folders have dependencies
+ if (m_warningDependentFolders) //test if check should be executed
+ {
+ wxString warningMessage;
+ if (foldersHaveDependencies(directoryPairsFormatted, warningMessage))
+ {
+ bool dontShowAgain = false;
+ statusUpdater->reportWarning(warningMessage.c_str(),
+ dontShowAgain);
+ m_warningDependentFolders = !dontShowAgain;
+ }
+ }
try
{
+ FileCompareResult output_tmp; //write to output not before END of process!
if (cmpVar == CMP_BY_TIME_SIZE)
compareByTimeSize(directoryPairsFormatted, output_tmp);
else if (cmpVar == CMP_BY_CONTENT)
compareByContent(directoryPairsFormatted, output_tmp);
else assert(false);
+
+ //only if everything was processed correctly output is written to! output mustn't change to be in sync with GUI grid view!!!
+ output_tmp.swap(output);
}
catch (const RuntimeException& theException)
{
- wxMessageBox(theException.show(), _("An exception occured!"), wxOK | wxICON_ERROR);
- statusUpdater->requestAbortion();
- return;
+ statusUpdater->reportFatalError(theException.show().c_str());
+ return; //should be obsolete!
}
catch (std::bad_alloc& e)
{
- wxMessageBox(wxString(_("System out of memory!")) + wxT(" ") + wxString::From8BitData(e.what()), _("An exception occured!"), wxOK | wxICON_ERROR);
- statusUpdater->requestAbortion();
- return;
+ statusUpdater->reportFatalError((wxString(_("System out of memory!")) + wxT(" ") + wxString::From8BitData(e.what())).c_str());
+ return; //should be obsolete!
}
-
- //only if everything was processed correctly output is written to!
- output_tmp.swap(output);
}
@@ -384,20 +498,17 @@ void CompareProcess::compareByTimeSize(const std::vector<FolderPair>& directoryP
//inform about the total amount of data that will be processed from now on
statusUpdater->initNewProcess(-1, 0, StatusHandler::PROCESS_SCANNING); //it's not known how many files will be scanned => -1 objects
- //buffer accesses to the same directories; useful when multiple folder pairs are used
- DirectoryDescrBuffer descriptionBuffer;
-
//process one folder pair after each other
unsigned tableSizeOld = 0;
for (std::vector<FolderPair>::const_iterator pair = directoryPairsFormatted.begin(); pair != directoryPairsFormatted.end(); ++pair)
{
//do basis scan: only result lines of type FILE_UNDEFINED (files that exist on both sides) need to be determined after this call
- this->performBaseComparison(*pair, descriptionBuffer, output);
+ this->performBaseComparison(*pair, output);
//add some tolerance if one of the folders is FAT/FAT32
time_t tolerance = 0;
#ifdef FFS_WIN
- if (handleDstOnFat32 && (isFatDrive(pair->leftDirectory) || isFatDrive(pair->leftDirectory)))
+ if (handleDstOnFat32 && (isFatDrive(pair->leftDirectory) || isFatDrive(pair->rightDirectory)))
tolerance = FILE_TIME_PRECISION + 3600; //tolerate filetime diff <= 1 h to handle daylight saving time issues
else
tolerance = FILE_TIME_PRECISION;
@@ -437,14 +548,11 @@ void CompareProcess::compareByContent(const std::vector<FolderPair>& directoryPa
//inform about the total amount of data that will be processed from now on
statusUpdater->initNewProcess(-1, 0, StatusHandler::PROCESS_SCANNING); //it's not known how many files will be scanned => -1 objects
- //buffer accesses to the same directories; useful when multiple folder pairs are used
- DirectoryDescrBuffer descriptionBuffer;
-
//process one folder pair after each other
for (std::vector<FolderPair>::const_iterator pair = directoryPairsFormatted.begin(); pair != directoryPairsFormatted.end(); ++pair)
{
//do basis scan: only result lines of type FILE_UNDEFINED (files that exist on both sides) need to be determined after this call
- this->performBaseComparison(*pair, descriptionBuffer, output);
+ this->performBaseComparison(*pair, output);
}
@@ -526,7 +634,7 @@ public:
m_directory(directory)
{
if (Create() != wxTHREAD_NO_ERROR)
- throw RuntimeException(wxString(wxT("Error starting thread for sorting!")));
+ throw RuntimeException(wxString(wxT("Error creating thread for sorting!")));
}
~ThreadSorting() {}
@@ -543,12 +651,12 @@ private:
};
-void CompareProcess::performBaseComparison(const FolderPair& pair, DirectoryDescrBuffer& descriptionBuffer, FileCompareResult& output)
+void CompareProcess::performBaseComparison(const FolderPair& pair, FileCompareResult& output)
{
//PERF_START;
//retrieve sets of files (with description data)
- DirectoryDescrType* directoryLeft = descriptionBuffer.getDirectoryDescription(pair.leftDirectory, includeLineBreak, statusUpdater);
- DirectoryDescrType* directoryRight = descriptionBuffer.getDirectoryDescription(pair.rightDirectory, includeLineBreak, statusUpdater);
+ DirectoryDescrType* directoryLeft = descriptionBuffer->getDirectoryDescription(pair.leftDirectory);
+ DirectoryDescrType* directoryRight = descriptionBuffer->getDirectoryDescription(pair.rightDirectory);
statusUpdater->updateStatusText(_("Generating file list..."));
statusUpdater->forceUiRefresh(); //keep total number of scanned files up to date
@@ -559,16 +667,23 @@ void CompareProcess::performBaseComparison(const FolderPair& pair, DirectoryDesc
{
//no synchronization (multithreading) needed here: directoryLeft and directoryRight are disjunct
//reference counting Zstring also shouldn't be an issue, as no strings are deleted during std::sort()
- ThreadSorting sortLeft(directoryLeft);
- ThreadSorting sortRight(directoryRight);
+ std::auto_ptr<ThreadSorting> sortLeft(new ThreadSorting(directoryLeft));
+ std::auto_ptr<ThreadSorting> sortRight(new ThreadSorting(directoryRight));
+
+ if (sortLeft->Run() != wxTHREAD_NO_ERROR)
+ throw RuntimeException(wxString(wxT("Error starting thread for sorting!")));
- sortLeft.Run();
if (directoryLeft != directoryRight) //attention: might point to the same vector because of buffer!
{
- sortRight.Run();
- sortRight.Wait();
+ if (sortRight->Run() != wxTHREAD_NO_ERROR)
+ throw RuntimeException(wxString(wxT("Error starting thread for sorting!")));
+
+ if (sortRight->Wait() != 0)
+ throw RuntimeException(wxString(wxT("Error waiting for thread (sorting)!")));
}
- sortLeft.Wait();
+
+ if (sortLeft->Wait() != 0)
+ throw RuntimeException(wxString(wxT("Error waiting for thread (sorting)!")));
}
else //single threaded
{
@@ -579,14 +694,14 @@ void CompareProcess::performBaseComparison(const FolderPair& pair, DirectoryDesc
}
//PERF_STOP;
- //reserve some space to avoid vector reallocations
+ //reserve some space to avoid too many vector reallocations
output.reserve(output.size() + unsigned(std::max(directoryLeft->size(), directoryRight->size()) * 1.2));
//begin base comparison
FileCompareLine newline;
DirectoryDescrType::iterator j;
- for (DirectoryDescrType::iterator i = directoryLeft->begin(); i != directoryLeft->end(); ++i)
- { //find files/folders that exist in left file model but not in right model
+ for (DirectoryDescrType::const_iterator i = directoryLeft->begin(); i != directoryLeft->end(); ++i)
+ { //find files/folders that exist in left file tree but not in right one
if ((j = custom_binary_search(directoryRight->begin(), directoryRight->end(), *i)) == directoryRight->end())
{
newline.fileDescrLeft = *i;
@@ -595,7 +710,7 @@ void CompareProcess::performBaseComparison(const FolderPair& pair, DirectoryDesc
newline.cmpResult = FILE_LEFT_SIDE_ONLY;
output.push_back(newline);
}
- //find files/folders that exist in left and right file model
+ //find files/folders that exist on left and right side
else
{
const FileDescrLine::ObjectType typeLeft = i->objType;
@@ -638,7 +753,7 @@ void CompareProcess::performBaseComparison(const FolderPair& pair, DirectoryDesc
}
- for (DirectoryDescrType::iterator j = directoryRight->begin(); j != directoryRight->end(); ++j)
+ for (DirectoryDescrType::const_iterator j = directoryRight->begin(); j != directoryRight->end(); ++j)
{
//find files/folders that exist in right file model but not in left model
if (custom_binary_search(directoryLeft->begin(), directoryLeft->end(), *j) == directoryLeft->end())
@@ -653,75 +768,3 @@ void CompareProcess::performBaseComparison(const FolderPair& pair, DirectoryDesc
//PERF_STOP
}
-
-
-bool FreeFileSync::foldersAreValidForComparison(const std::vector<FolderPair>& folderPairs, wxString& errorMessage)
-{
- errorMessage.Clear();
-
- for (std::vector<FolderPair>::const_iterator i = folderPairs.begin(); i != folderPairs.end(); ++i)
- {
- const Zstring leftFolderName = getFormattedDirectoryName(i->leftDirectory);
- const Zstring rightFolderName = getFormattedDirectoryName(i->rightDirectory);
-
- //check if folder name is empty
- if (leftFolderName.empty() || rightFolderName.empty())
- {
- errorMessage = _("Please fill all empty directory fields.");
- return false;
- }
-
- //check if folder exists
- if (!wxDirExists(leftFolderName))
- {
- errorMessage = wxString(_("Directory does not exist:")) + wxT(" \"") + leftFolderName + wxT("\"");
- return false;
- }
- if (!wxDirExists(rightFolderName))
- {
- errorMessage = wxString(_("Directory does not exist:")) + wxT(" \"") + rightFolderName + wxT("\"");
- return false;
- }
- }
- return true;
-}
-
-
-bool dependencyExists(const std::vector<Zstring>& folders, const Zstring& newFolder, wxString& warningMessage)
-{
- warningMessage.Clear();
-
- for (std::vector<Zstring>::const_iterator i = folders.begin(); i != folders.end(); ++i)
- if (newFolder.StartsWith(*i) || i->StartsWith(newFolder))
- {
- warningMessage = wxString(_("Directories are dependent:")) +
- wxT(" \n\"") + *i + wxT("\"") + wxT(", \n") + wxT("\"") + newFolder + wxT("\"");
- return true;
- }
-
- return false;
-}
-
-
-bool FreeFileSync::foldersHaveDependencies(const std::vector<FolderPair>& folderPairs, wxString& warningMessage)
-{
- warningMessage.Clear();
-
- std::vector<Zstring> folders;
- for (std::vector<FolderPair>::const_iterator i = folderPairs.begin(); i != folderPairs.end(); ++i)
- {
- const Zstring leftFolderName = getFormattedDirectoryName(i->leftDirectory);
- const Zstring rightFolderName = getFormattedDirectoryName(i->rightDirectory);
-
- if (dependencyExists(folders, leftFolderName, warningMessage))
- return true;
- folders.push_back(leftFolderName);
-
- if (dependencyExists(folders, rightFolderName, warningMessage))
- return true;
- folders.push_back(rightFolderName);
- }
-
- return false;
-}
-
bgstack15