summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Batch.icobin134332 -> 116037 bytes
-rw-r--r--lib/ShadowCopy/Shadow_Server2003.vcxproj7
-rw-r--r--lib/ShadowCopy/Shadow_Windows7.vcxproj7
-rw-r--r--lib/ShadowCopy/Shadow_XP.vcxproj7
-rw-r--r--lib/Thumbnail/Thumbnail.vcxproj7
-rw-r--r--lib/binary.cpp12
-rw-r--r--lib/db_file.cpp6
-rw-r--r--lib/dir_lock.cpp16
-rw-r--r--lib/generate_logfile.h174
-rw-r--r--lib/localization.cpp2
-rw-r--r--lib/lock_holder.h67
-rw-r--r--lib/parallel_scan.cpp2
-rw-r--r--lib/process_xml.cpp12
-rw-r--r--lib/process_xml.h2
-rw-r--r--lib/resolve_path.cpp2
-rw-r--r--lib/shadow.cpp3
-rw-r--r--lib/status_handler.cpp2
17 files changed, 198 insertions, 130 deletions
diff --git a/lib/Batch.ico b/lib/Batch.ico
index 14e2bb10..1856b1fb 100644
--- a/lib/Batch.ico
+++ b/lib/Batch.ico
Binary files differ
diff --git a/lib/ShadowCopy/Shadow_Server2003.vcxproj b/lib/ShadowCopy/Shadow_Server2003.vcxproj
index 3e70cd7a..50a3a830 100644
--- a/lib/ShadowCopy/Shadow_Server2003.vcxproj
+++ b/lib/ShadowCopy/Shadow_Server2003.vcxproj
@@ -100,6 +100,7 @@
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<DisableSpecificWarnings>4100;4996</DisableSpecificWarnings>
<AdditionalIncludeDirectories>../..;C:\Program Files\C++\boost</AdditionalIncludeDirectories>
+ <SmallerTypeCheck>true</SmallerTypeCheck>
</ClCompile>
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
@@ -112,6 +113,7 @@
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalLibraryDirectories>C:\Program Files\C++\Boost\stage\lib</AdditionalLibraryDirectories>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -134,6 +136,7 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4100;4996</DisableSpecificWarnings>
<AdditionalIncludeDirectories>../..;C:\Program Files\C++\boost</AdditionalIncludeDirectories>
+ <SmallerTypeCheck>true</SmallerTypeCheck>
</ClCompile>
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
@@ -146,6 +149,7 @@
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
<AdditionalLibraryDirectories>C:\Program Files\C++\Boost\stage_x64\lib</AdditionalLibraryDirectories>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -180,6 +184,7 @@
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalLibraryDirectories>C:\Program Files\C++\Boost\stage\lib</AdditionalLibraryDirectories>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -217,9 +222,11 @@
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
<AdditionalLibraryDirectories>C:\Program Files\C++\Boost\stage_x64\lib</AdditionalLibraryDirectories>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClCompile Include="..\..\zen\debug_memory_leaks.cpp" />
<ClCompile Include="dll_main.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
diff --git a/lib/ShadowCopy/Shadow_Windows7.vcxproj b/lib/ShadowCopy/Shadow_Windows7.vcxproj
index 985936b4..aa32253b 100644
--- a/lib/ShadowCopy/Shadow_Windows7.vcxproj
+++ b/lib/ShadowCopy/Shadow_Windows7.vcxproj
@@ -100,6 +100,7 @@
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<DisableSpecificWarnings>4100;4996</DisableSpecificWarnings>
<AdditionalIncludeDirectories>../..;C:\Program Files\C++\boost</AdditionalIncludeDirectories>
+ <SmallerTypeCheck>true</SmallerTypeCheck>
</ClCompile>
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
@@ -112,6 +113,7 @@
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalLibraryDirectories>C:\Program Files\C++\Boost\stage\lib</AdditionalLibraryDirectories>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -134,6 +136,7 @@
<DisableSpecificWarnings>4100;4996</DisableSpecificWarnings>
<AdditionalIncludeDirectories>../..;C:\Program Files\C++\boost</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;SHADOWDLL_EXPORTS;USE_SHADOW_WINDOWS7;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SmallerTypeCheck>true</SmallerTypeCheck>
</ClCompile>
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
@@ -146,6 +149,7 @@
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
<AdditionalLibraryDirectories>C:\Program Files\C++\Boost\stage_x64\lib</AdditionalLibraryDirectories>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -180,6 +184,7 @@
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalLibraryDirectories>C:\Program Files\C++\Boost\stage\lib</AdditionalLibraryDirectories>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -217,9 +222,11 @@
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
<AdditionalLibraryDirectories>C:\Program Files\C++\Boost\stage_x64\lib</AdditionalLibraryDirectories>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClCompile Include="..\..\zen\debug_memory_leaks.cpp" />
<ClCompile Include="dll_main.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
diff --git a/lib/ShadowCopy/Shadow_XP.vcxproj b/lib/ShadowCopy/Shadow_XP.vcxproj
index b49bff4c..70b792ec 100644
--- a/lib/ShadowCopy/Shadow_XP.vcxproj
+++ b/lib/ShadowCopy/Shadow_XP.vcxproj
@@ -100,6 +100,7 @@
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<DisableSpecificWarnings>4100;4996</DisableSpecificWarnings>
<AdditionalIncludeDirectories>../..;C:\Program Files\C++\boost</AdditionalIncludeDirectories>
+ <SmallerTypeCheck>true</SmallerTypeCheck>
</ClCompile>
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
@@ -112,6 +113,7 @@
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalLibraryDirectories>C:\Program Files\C++\Boost\stage\lib</AdditionalLibraryDirectories>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -135,6 +137,7 @@
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<DisableSpecificWarnings>4100;4996</DisableSpecificWarnings>
<AdditionalIncludeDirectories>../..;C:\Program Files\C++\boost</AdditionalIncludeDirectories>
+ <SmallerTypeCheck>true</SmallerTypeCheck>
</ClCompile>
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
@@ -147,6 +150,7 @@
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
<AdditionalLibraryDirectories>C:\Program Files\C++\Boost\stage_x64\lib</AdditionalLibraryDirectories>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -181,6 +185,7 @@
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalLibraryDirectories>C:\Program Files\C++\Boost\stage\lib</AdditionalLibraryDirectories>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -218,9 +223,11 @@
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
<AdditionalLibraryDirectories>C:\Program Files\C++\Boost\stage_x64\lib</AdditionalLibraryDirectories>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClCompile Include="..\..\zen\debug_memory_leaks.cpp" />
<ClCompile Include="dll_main.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
diff --git a/lib/Thumbnail/Thumbnail.vcxproj b/lib/Thumbnail/Thumbnail.vcxproj
index e3909ff8..3baa2d61 100644
--- a/lib/Thumbnail/Thumbnail.vcxproj
+++ b/lib/Thumbnail/Thumbnail.vcxproj
@@ -98,6 +98,7 @@
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<DisableSpecificWarnings>4100</DisableSpecificWarnings>
<AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories>
+ <SmallerTypeCheck>true</SmallerTypeCheck>
</ClCompile>
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
@@ -109,6 +110,7 @@
</ProfileGuidedDatabase>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -131,6 +133,7 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4100</DisableSpecificWarnings>
<AdditionalIncludeDirectories>../..</AdditionalIncludeDirectories>
+ <SmallerTypeCheck>true</SmallerTypeCheck>
</ClCompile>
<Link>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
@@ -142,6 +145,7 @@
</ProfileGuidedDatabase>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -175,6 +179,7 @@
</ProfileGuidedDatabase>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -211,9 +216,11 @@
</ProfileGuidedDatabase>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
+ <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClCompile Include="..\..\zen\debug_memory_leaks.cpp" />
<ClCompile Include="dll_main.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</PrecompiledHeader>
diff --git a/lib/binary.cpp b/lib/binary.cpp
index b9e3028d..10994cc9 100644
--- a/lib/binary.cpp
+++ b/lib/binary.cpp
@@ -44,7 +44,7 @@ public:
private:
static const size_t BUFFER_SIZE_MIN = 64 * 1024;
- static const size_t BUFFER_SIZE_START = 512 * 1024; //512 kb seems to be a reasonable initial buffer size
+ static const size_t BUFFER_SIZE_START = 128 * 1024; //initial buffer size
static const size_t BUFFER_SIZE_MAX = 16 * 1024 * 1024;
/*Tests on Win7 x64 show that buffer size does NOT matter if files are located on different physical disks!
@@ -99,23 +99,23 @@ bool zen::filesHaveSameContent(const Zstring& filename1, const Zstring& filename
const size_t length1 = file1.read(&memory1[0], bufferSize); //returns actual number of bytes read; throw FileError()
const size_t length2 = file2.read(&memory2[0], bufferSize); //
- const TickVal stopTime = getTicks();
+ const TickVal now = getTicks();
//-------- dynamically set buffer size to keep callback interval between 100 - 500ms ---------------------
if (TICKS_PER_SEC > 0)
{
- const std::int64_t loopTime = (stopTime - startTime) * 1000 / TICKS_PER_SEC; //unit: [ms]
+ const std::int64_t loopTime = dist(startTime, now) * 1000 / TICKS_PER_SEC; //unit: [ms]
if (loopTime < 100)
{
- if ((stopTime - lastDelayViolation) / TICKS_PER_SEC > 2) //avoid "flipping back": e.g. DVD-Roms read 32MB at once, so first read may be > 500 ms, but second one will be 0ms!
+ if (dist(lastDelayViolation, now) / TICKS_PER_SEC > 2) //avoid "flipping back": e.g. DVD-Roms read 32MB at once, so first read may be > 500 ms, but second one will be 0ms!
{
- lastDelayViolation = stopTime;
+ lastDelayViolation = now;
bufferSize.inc();
}
}
else if (loopTime > 500)
{
- lastDelayViolation = stopTime;
+ lastDelayViolation = now;
bufferSize.dec();
}
}
diff --git a/lib/db_file.cpp b/lib/db_file.cpp
index 53830afe..f81ada21 100644
--- a/lib/db_file.cpp
+++ b/lib/db_file.cpp
@@ -636,12 +636,12 @@ std::shared_ptr<InSyncDir> zen::loadLastSynchronousState(const BaseDirMapping& b
const Zstring fileNameLeft = getDBFilename<LEFT_SIDE >(baseMapping);
const Zstring fileNameRight = getDBFilename<RIGHT_SIDE>(baseMapping);
- if (!baseMapping.wasExisting<LEFT_SIDE >() ||
- !baseMapping.wasExisting<RIGHT_SIDE>())
+ if (!baseMapping.isExisting<LEFT_SIDE >() ||
+ !baseMapping.isExisting<RIGHT_SIDE>())
{
//avoid race condition with directory existence check: reading sync.ffs_db may succeed although first dir check had failed => conflicts!
//https://sourceforge.net/tracker/?func=detail&atid=1093080&aid=3531351&group_id=234430
- const Zstring filename = !baseMapping.wasExisting<LEFT_SIDE>() ? fileNameLeft : fileNameRight;
+ const Zstring filename = !baseMapping.isExisting<LEFT_SIDE>() ? fileNameLeft : fileNameRight;
throw FileErrorDatabaseNotExisting(_("Initial synchronization:") + L" \n" + //it could be due to a to-be-created target directory not yet existing => FileErrorDatabaseNotExisting
replaceCpy(_("Database file %x does not yet exist."), L"%x", fmtFileName(filename)));
}
diff --git a/lib/dir_lock.cpp b/lib/dir_lock.cpp
index bbd97454..5041b37e 100644
--- a/lib/dir_lock.cpp
+++ b/lib/dir_lock.cpp
@@ -105,7 +105,7 @@ public:
#elif defined FFS_LINUX
const int fileHandle = ::open(lockfilename_.c_str(), O_WRONLY | O_APPEND);
- if (fileHandle == -1)
+ if (fileHandle < 0)
return;
ZEN_ON_SCOPE_EXIT(::close(fileHandle));
@@ -418,20 +418,20 @@ void waitOnDirLock(const Zstring& lockfilename, DirLockCallback* callback) //thr
while (true)
{
- const TickVal currentTime = getTicks();
+ const TickVal now = getTicks();
const UInt64 fileSizeNew = ::getLockFileSize(lockfilename); //throw FileError, ErrorNotExisting
- if (TICKS_PER_SEC <= 0 || !lastLifeSign.isValid() || !currentTime.isValid())
+ if (TICKS_PER_SEC <= 0 || !lastLifeSign.isValid() || !now.isValid())
throw FileError(L"System Timer failed!"); //no i18n: "should" never throw ;)
if (fileSizeNew != fileSizeOld) //received life sign from lock
{
fileSizeOld = fileSizeNew;
- lastLifeSign = currentTime;
+ lastLifeSign = now;
}
if (lockOwnderDead || //no need to wait any longer...
- (currentTime - lastLifeSign) / TICKS_PER_SEC > DETECT_ABANDONED_INTERVAL)
+ dist(lastLifeSign, now) / TICKS_PER_SEC > DETECT_ABANDONED_INTERVAL)
{
DirLock dummy(deleteAbandonedLockName(lockfilename), callback); //throw FileError
@@ -458,11 +458,9 @@ void waitOnDirLock(const Zstring& lockfilename, DirLockCallback* callback) //thr
if (callback)
{
//one signal missed: it's likely this is an abandoned lock => show countdown
- if ((currentTime - lastLifeSign) / TICKS_PER_SEC > EMIT_LIFE_SIGN_INTERVAL)
+ if (dist(lastLifeSign, now) / TICKS_PER_SEC > EMIT_LIFE_SIGN_INTERVAL)
{
- int remainingSeconds = DETECT_ABANDONED_INTERVAL - (getTicks() - lastLifeSign) / TICKS_PER_SEC;
- remainingSeconds = std::max(0, remainingSeconds);
-
+ const int remainingSeconds = std::max<int>(0, DETECT_ABANDONED_INTERVAL - dist(lastLifeSign, getTicks()) / TICKS_PER_SEC);
const std::wstring remSecMsg = replaceCpy(_P("1 sec", "%x sec", remainingSeconds), L"%x", numberTo<std::wstring>(remainingSeconds));
callback->reportInfo(infoMsg + L" " + remSecMsg);
}
diff --git a/lib/generate_logfile.h b/lib/generate_logfile.h
index beb4f5d3..875d5b98 100644
--- a/lib/generate_logfile.h
+++ b/lib/generate_logfile.h
@@ -16,16 +16,24 @@
namespace zen
{
-Utf8String generateLogStream(const ErrorLog& log,
- const std::wstring& jobName, //may be empty
- const std::wstring& finalStatus,
- int itemsSynced, Int64 dataSynced,
- int itemsTotal, Int64 dataTotal,
- long totalTime); //unit: [sec]
-
-void saveToLastSyncsLog(const Utf8String& logstream); //throw FileError
+struct SummaryInfo
+{
+ std::wstring jobName; //may be empty
+ std::wstring finalStatus;
+ int itemsSynced;
+ Int64 dataSynced;
+ int itemsTotal;
+ Int64 dataTotal;
+ long totalTime; //unit: [sec]
+};
+void saveLogToFile(const SummaryInfo& summary, //throw FileError
+ const ErrorLog& log,
+ FileOutput& fileOut);
+void saveToLastSyncsLog(const SummaryInfo& summary, //throw FileError
+ const ErrorLog& log,
+ size_t maxBytesToWrite);
@@ -34,114 +42,136 @@ void saveToLastSyncsLog(const Utf8String& logstream); //throw FileError
//####################### implementation #######################
namespace
{
-Utf8String generateLogStream_impl(const ErrorLog& log,
- const std::wstring& jobName, //may be empty
- const std::wstring& finalStatus,
- int itemsSynced, Int64 dataSynced,
- int itemsTotal, Int64 dataTotal,
- long totalTime) //unit: [sec]
+std::wstring generateLogHeader(const SummaryInfo& s)
{
- assert(itemsSynced <= itemsTotal);
- assert(dataSynced <= dataTotal);
+ assert(s.itemsSynced <= s.itemsTotal);
+ assert(s.dataSynced <= s.dataTotal);
- Utf8String output;
+ std::wstring output;
//write header
std::wstring headerLine = formatTime<std::wstring>(FORMAT_DATE);
- if (!jobName.empty())
- headerLine += L" - " + jobName;
- headerLine += L": " + finalStatus;
+ if (!s.jobName.empty())
+ headerLine += L" - " + s.jobName;
+ headerLine += L": " + s.finalStatus;
//assemble results box
std::vector<std::wstring> results;
results.push_back(headerLine);
results.push_back(L"");
- const wchar_t tabSpace[] = L" ";
+ const wchar_t tabSpace[] = L" ";
- std::wstring itemsProc = tabSpace + _("Items processed:") + L" " + toGuiString(itemsSynced); //show always, even if 0!
- if (itemsSynced != 0 || dataSynced != 0) //[!] don't show 0 bytes processed if 0 items were processed
- itemsProc += + L" (" + filesizeToShortString(dataSynced) + L")";
+ std::wstring itemsProc = tabSpace + _("Items processed:") + L" " + toGuiString(s.itemsSynced); //show always, even if 0!
+ if (s.itemsSynced != 0 || s.dataSynced != 0) //[!] don't show 0 bytes processed if 0 items were processed
+ itemsProc += + L" (" + filesizeToShortString(s.dataSynced) + L")";
results.push_back(itemsProc);
- if (itemsTotal != 0 || dataTotal != 0) //=: sync phase was reached and there were actual items to sync
+ if (s.itemsTotal != 0 || s.dataTotal != 0) //=: sync phase was reached and there were actual items to sync
{
- if (itemsSynced != itemsTotal ||
- dataSynced != dataTotal)
- results.push_back(tabSpace + _("Items remaining:") + L" " + toGuiString(itemsTotal - itemsSynced) + L" (" + filesizeToShortString(dataTotal - dataSynced) + L")");
+ if (s.itemsSynced != s.itemsTotal ||
+ s.dataSynced != s.dataTotal)
+ results.push_back(tabSpace + _("Items remaining:") + L" " + toGuiString(s.itemsTotal - s.itemsSynced) + L" (" + filesizeToShortString(s.dataTotal - s.dataSynced) + L")");
}
- results.push_back(tabSpace + _("Total time:") + L" " + copyStringTo<std::wstring>(wxTimeSpan::Seconds(totalTime).Format()));
+ results.push_back(tabSpace + _("Total time:") + L" " + copyStringTo<std::wstring>(wxTimeSpan::Seconds(s.totalTime).Format()));
//calculate max width, this considers UTF-16 only, not true Unicode...
size_t sepLineLen = 0;
std::for_each(results.begin(), results.end(), [&](const std::wstring& str) { sepLineLen = std::max(sepLineLen, str.size()); });
- for (size_t i = 0; i < sepLineLen; ++i) output += '_'; //this considers UTF-16 only, not true Unicode!!!
- output += "\n";
-
- std::for_each(results.begin(), results.end(), [&](const std::wstring& str) { output += utfCvrtTo<Utf8String>(str); output += '\n'; });
+ for (size_t i = 0; i < sepLineLen; ++i) output += L'_'; //this considers UTF-16 only, not true Unicode!!!
+ output += L'\n';
- for (size_t i = 0; i < sepLineLen; ++i) output += '_';
- output += "\n\n";
+ std::for_each(results.begin(), results.end(), [&](const std::wstring& str) { output += str; output += L'\n'; });
- //write log items
- const auto& entries = log.getEntries();
- for (auto iter = entries.begin(); iter != entries.end(); ++iter)
- {
- output += utfCvrtTo<Utf8String>(formatMessage(*iter));
- output += '\n';
- }
+ for (size_t i = 0; i < sepLineLen; ++i) output += L'_';
+ output += L'\n';
- return replaceCpy(output, '\n', LINE_BREAK); //don't replace line break any earlier
+ return output;
}
}
inline
-Utf8String generateLogStream(const ErrorLog& log,
- const std::wstring& jobName, //may be empty
- const std::wstring& finalStatus,
- int itemsSynced, Int64 dataSynced,
- int itemsTotal, Int64 dataTotal,
- long totalTime) //unit: [sec]
+void saveLogToFile(const SummaryInfo& summary, //throw FileError
+ const ErrorLog& log,
+ FileOutput& fileOut)
{
- return generateLogStream_impl(log, jobName, finalStatus, itemsSynced, dataSynced, itemsTotal, dataTotal, totalTime);
+ Utf8String header = utfCvrtTo<Utf8String>(generateLogHeader(summary));
+ replace(header, '\n', LINE_BREAK); //don't replace line break any earlier
+ header += LINE_BREAK; //make sure string is not empty!
+
+ fileOut.write(&*header.begin(), header.size()); //throw FileError
+
+ //write log items one after the other instead of creating one big string: memory allocation might fail; think 1 million entries!
+ for (auto iter = log.begin(); iter != log.end(); ++iter)
+ {
+ Utf8String msg = replaceCpy(utfCvrtTo<Utf8String>(formatMessage<std::wstring>(*iter)), '\n', LINE_BREAK);
+ msg += LINE_BREAK; //make sure string is not empty!
+
+ fileOut.write(&*msg.begin(), msg.size()); //throw FileError
+ }
}
inline
-void saveToLastSyncsLog(const Utf8String& logstream) //throw FileError
+void saveToLastSyncsLog(const SummaryInfo& summary, //throw FileError
+ const ErrorLog& log,
+ size_t maxBytesToWrite) //log may be *huge*, e.g. 1 million items; LastSyncs.log *must not* create performance problems!
+
{
const Zstring filename = getConfigDir() + Zstr("LastSyncs.log");
- Utf8String oldStream;
- try
- {
- oldStream = loadBinStream<Utf8String>(filename); //throw FileError, ErrorNotExisting
- }
- catch (const ErrorNotExisting&) {}
+ Utf8String newStream = utfCvrtTo<Utf8String>(generateLogHeader(summary));
+ replace(newStream, '\n', LINE_BREAK); //don't replace line break any earlier
+ newStream += LINE_BREAK;
- Utf8String newStream = logstream;
- if (!oldStream.empty())
+ //write log items one after the other instead of creating one big string: memory allocation might fail; think 1 million entries!
+ for (auto iter = log.begin(); iter != log.end(); ++iter)
{
+ newStream += replaceCpy(utfCvrtTo<Utf8String>(formatMessage<std::wstring>(*iter)), '\n', LINE_BREAK);
newStream += LINE_BREAK;
- newStream += LINE_BREAK;
- newStream += oldStream;
- }
- //limit file size: 128 kB (but do not truncate new log)
- const size_t newSize = std::min(newStream.size(), std::max<size_t>(logstream.size(), 128 * 1024));
+ if (newStream.size() > maxBytesToWrite)
+ {
+ newStream += "[...]";
+ newStream += LINE_BREAK;
+ break;
+ }
+ }
- //do not cut in the middle of a row
- auto iter = std::search(newStream.cbegin() + newSize, newStream.cend(), std::begin(LINE_BREAK), std::end(LINE_BREAK) - 1);
- if (iter != newStream.cend())
+ //fill up the rest of permitted space by appending old log
+ if (newStream.size() < maxBytesToWrite)
{
- newStream.resize(iter - newStream.cbegin());
-
- newStream += LINE_BREAK;
- newStream += "[...]";
- newStream += LINE_BREAK;
+ Utf8String oldStream;
+ try
+ {
+ oldStream = loadBinStream<Utf8String>(filename); //throw FileError, ErrorNotExisting
+ }
+ catch (const ErrorNotExisting&) {}
+
+ if (!oldStream.empty())
+ {
+ newStream += LINE_BREAK;
+ newStream += LINE_BREAK;
+ newStream += oldStream; //impliticly limited by "maxBytesToWrite"!
+
+ //truncate size if required
+ if (newStream.size() > maxBytesToWrite)
+ {
+ //but do not cut in the middle of a row
+ auto iter = std::search(newStream.cbegin() + maxBytesToWrite, newStream.cend(), std::begin(LINE_BREAK), std::end(LINE_BREAK) - 1);
+ if (iter != newStream.cend())
+ {
+ newStream.resize(iter - newStream.cbegin());
+ newStream += LINE_BREAK;
+
+ newStream += "[...]";
+ newStream += LINE_BREAK;
+ }
+ }
+ }
}
saveBinStream(filename, newStream); //throw FileError
diff --git a/lib/localization.cpp b/lib/localization.cpp
index 64c8b0f3..5792b3d1 100644
--- a/lib/localization.cpp
+++ b/lib/localization.cpp
@@ -123,7 +123,7 @@ public:
virtual HandleLink onSymlink(const Zchar* shortName, const Zstring& fullName, const SymlinkInfo& details) { return LINK_SKIP; }
virtual std::shared_ptr<TraverseCallback> onDir(const Zchar* shortName, const Zstring& fullName) { return nullptr; }
- virtual HandleError onError(const std::wstring& msg) { return ON_ERROR_IGNORE; } //errors are not really critical in this context
+ virtual HandleError onError(const std::wstring& msg) { assert(false); return ON_ERROR_IGNORE; } //errors are not really critical in this context
private:
std::vector<Zstring>& lngFiles_;
diff --git a/lib/lock_holder.h b/lib/lock_holder.h
index 6265747b..5ae2f8ae 100644
--- a/lib/lock_holder.h
+++ b/lib/lock_holder.h
@@ -3,6 +3,7 @@
#include <map>
#include <zen/zstring.h>
+#include <zen/stl_tools.h>
#include "dir_lock.h"
#include "status_handler.h"
#include "dir_exist_async.h"
@@ -11,43 +12,49 @@ namespace zen
{
const Zstring LOCK_FILE_ENDING = Zstr(".ffs_lock"); //intermediate locks created by DirLock use this extension, too!
-//convenience class for creating and holding locks for a number of directories
+//hold locks for a number of directories without blocking during lock creation
class LockHolder
{
public:
- LockHolder(bool allowUserInteraction) : allowUserInteraction_(allowUserInteraction) {}
-
- void addDir(const Zstring& dirnameFmt, ProcessCallback& procCallback) //resolved dirname ending with path separator
+ LockHolder(const std::vector<Zstring>& dirnamesFmt, //resolved dirname ending with path separator
+ ProcessCallback& procCallback,
+ bool allowUserInteraction) : allowUserInteraction_(allowUserInteraction)
{
- if (dirnameFmt.empty())
- return;
+ std::vector<Zstring> dirs = dirnamesFmt;
+ vector_remove_if(dirs, [](const Zstring& dir) { return dir.empty(); });
- if (!dirExistsUpdating(dirnameFmt, allowUserInteraction_, procCallback))
- return;
+ for (auto iter = dirs.begin(); iter != dirs.end(); ++iter)
+ {
+ const Zstring& dirnameFmt = *iter;
- if (lockHolder.find(dirnameFmt) != lockHolder.end()) return;
- assert(endsWith(dirnameFmt, FILE_NAME_SEPARATOR)); //this is really the contract, formatting does other things as well, e.g. macro substitution
+ if (!dirExistsUpdating(dirnameFmt, allowUserInteraction_, procCallback))
+ continue;
- class WaitOnLockHandler : public DirLockCallback
- {
- public:
- WaitOnLockHandler(ProcessCallback& pc) : pc_(pc) {}
- virtual void requestUiRefresh() { pc_.requestUiRefresh(); } //allowed to throw exceptions
- virtual void reportInfo(const std::wstring& text) { pc_.reportStatus(text); }
- private:
- ProcessCallback& pc_;
- } callback(procCallback);
-
- try
- {
- //lock file creation is synchronous and may block noticably for very slow devices (usb sticks, mapped cloud storages)
- procCallback.forceUiRefresh(); //=> make sure the right folder name is shown on GUI during this time!
- lockHolder.insert(std::make_pair(dirnameFmt, DirLock(dirnameFmt + Zstr("sync") + LOCK_FILE_ENDING, &callback)));
- }
- catch (const FileError& e)
- {
- bool dummy = false; //this warning shall not be shown but logged only
- procCallback.reportWarning(e.toString(), dummy); //may throw!
+ if (lockHolder.find(dirnameFmt) != lockHolder.end())
+ continue;
+ assert(endsWith(dirnameFmt, FILE_NAME_SEPARATOR)); //this is really the contract, formatting does other things as well, e.g. macro substitution
+
+ class WaitOnLockHandler : public DirLockCallback
+ {
+ public:
+ WaitOnLockHandler(ProcessCallback& pc) : pc_(pc) {}
+ virtual void requestUiRefresh() { pc_.requestUiRefresh(); } //allowed to throw exceptions
+ virtual void reportInfo(const std::wstring& text) { pc_.reportStatus(text); }
+ private:
+ ProcessCallback& pc_;
+ } callback(procCallback);
+
+ try
+ {
+ //lock file creation is synchronous and may block noticably for very slow devices (usb sticks, mapped cloud storages)
+ procCallback.forceUiRefresh(); //=> make sure the right folder name is shown on GUI during this time!
+ lockHolder.insert(std::make_pair(dirnameFmt, DirLock(dirnameFmt + Zstr("sync") + LOCK_FILE_ENDING, &callback)));
+ }
+ catch (const FileError& e)
+ {
+ bool dummy = false; //this warning shall not be shown but logged only
+ procCallback.reportWarning(e.toString(), dummy); //may throw!
+ }
}
}
diff --git a/lib/parallel_scan.cpp b/lib/parallel_scan.cpp
index b9d29699..a31e30ee 100644
--- a/lib/parallel_scan.cpp
+++ b/lib/parallel_scan.cpp
@@ -541,7 +541,7 @@ void zen::fillBuffer(const std::set<DirectoryKey>& keysToRead, //in
std::for_each(worker.begin(), worker.end(), [](boost::thread& wt) { wt.interrupt(); }); //interrupt all at once, then join
std::for_each(worker.begin(), worker.end(), [](boost::thread& wt)
{
- if (wt.joinable()) //this is a precondition of thread::join()!!! Latter will throw an exception if violated!
+ if (wt.joinable()) //= precondition of thread::join(), which throws an exception if violated!
wt.join(); //in this context it is possible a thread is *not* joinable anymore due to the thread::timed_join() below!
});
});
diff --git a/lib/process_xml.cpp b/lib/process_xml.cpp
index 57ba69e6..aed9c35f 100644
--- a/lib/process_xml.cpp
+++ b/lib/process_xml.cpp
@@ -715,10 +715,10 @@ template <> inline
void writeStruc(const ColumnAttributeRim& value, XmlElement& output)
{
XmlOut out(output);
- out.attribute("Type", value.type_);
- out.attribute("Visible", value.visible_);
- out.attribute("Width", value.offset_);
- out.attribute("Stretch", value.stretch_);
+ out.attribute("Type", value.type_);
+ out.attribute("Visible", value.visible_);
+ out.attribute("Width", value.offset_);
+ out.attribute("Stretch", value.stretch_);
}
@@ -943,6 +943,8 @@ void readConfig(const XmlIn& in, XmlGlobalSettings& config)
//max. allowed file time deviation
inShared["FileTimeTolerance"](config.fileTimeTolerance);
+ inShared["LastSyncsFileSizeMax"](config.lastSyncsLogFileSizeMax);
+
XmlIn inOpt = inShared["OptionalDialogs"];
inOpt["WarnUnresolvedConflicts" ](config.optDialogs.warningUnresolvedConflicts);
inOpt["WarnNotEnoughDiskSpace" ](config.optDialogs.warningNotEnoughDiskSpace);
@@ -1248,6 +1250,8 @@ void writeConfig(const XmlGlobalSettings& config, XmlOut& out)
//max. allowed file time deviation
outShared["FileTimeTolerance"](config.fileTimeTolerance);
+ outShared["LastSyncsFileSizeMax"](config.lastSyncsLogFileSizeMax);
+
XmlOut outOpt = outShared["OptionalDialogs"];
outOpt["WarnUnresolvedConflicts" ](config.optDialogs.warningUnresolvedConflicts);
outOpt["WarnNotEnoughDiskSpace" ](config.optDialogs.warningNotEnoughDiskSpace);
diff --git a/lib/process_xml.h b/lib/process_xml.h
index d21f7ffc..8d1d4538 100644
--- a/lib/process_xml.h
+++ b/lib/process_xml.h
@@ -124,6 +124,7 @@ struct XmlGlobalSettings
copyFilePermissions(false),
runWithBackgroundPriority(false),
fileTimeTolerance(2), //default 2s: FAT vs NTFS
+ lastSyncsLogFileSizeMax(100000), //maximum size for LastSyncs.log: use a human-readable number
verifyFileCopy(false),
transactionalFileCopy(true),
createLockFile(true) {}
@@ -135,6 +136,7 @@ struct XmlGlobalSettings
bool runWithBackgroundPriority;
size_t fileTimeTolerance; //max. allowed file time deviation
+ size_t lastSyncsLogFileSizeMax;
bool verifyFileCopy; //verify copied files
bool transactionalFileCopy;
bool createLockFile;
diff --git a/lib/resolve_path.cpp b/lib/resolve_path.cpp
index 0b8e80b9..248e3507 100644
--- a/lib/resolve_path.cpp
+++ b/lib/resolve_path.cpp
@@ -300,7 +300,7 @@ public:
devices_.insert(std::make_pair(shortName, fullName));
return nullptr; //DON'T traverse into subdirs
}
- virtual HandleError onError(const std::wstring& msg) { return ON_ERROR_IGNORE; }
+ virtual HandleError onError(const std::wstring& msg) { assert(false); return ON_ERROR_IGNORE; }
private:
DeviceList& devices_;
diff --git a/lib/shadow.cpp b/lib/shadow.cpp
index 5f2225e7..8ef86f30 100644
--- a/lib/shadow.cpp
+++ b/lib/shadow.cpp
@@ -35,7 +35,6 @@ bool runningWOW64() //test if process is running under WOW64 (reference http://m
//#############################################################################################################
-
class ShadowCopy::ShadowVolume
{
public:
@@ -84,8 +83,8 @@ private:
Zstring shadowVolPf;
ShadowHandle backupHandle;
};
-//#############################################################################################################
+//#############################################################################################################
Zstring ShadowCopy::makeShadowCopy(const Zstring& inputFile)
{
diff --git a/lib/status_handler.cpp b/lib/status_handler.cpp
index 3188ba0d..c24c6f50 100644
--- a/lib/status_handler.cpp
+++ b/lib/status_handler.cpp
@@ -29,7 +29,7 @@ TickVal lastExec = getTicks();
bool zen::updateUiIsAllowed()
{
const TickVal now = getTicks(); //0 on error
- if (now - lastExec >= TICKS_UPDATE_INTERVAL) //perform ui updates not more often than necessary
+ if (dist(lastExec, now) >= TICKS_UPDATE_INTERVAL) //perform ui updates not more often than necessary
{
lastExec = now;
return true;
bgstack15