summaryrefslogtreecommitdiff
path: root/RealtimeSync/watcher.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'RealtimeSync/watcher.cpp')
-rw-r--r--RealtimeSync/watcher.cpp76
1 files changed, 50 insertions, 26 deletions
diff --git a/RealtimeSync/watcher.cpp b/RealtimeSync/watcher.cpp
index 37664d35..97ad480a 100644
--- a/RealtimeSync/watcher.cpp
+++ b/RealtimeSync/watcher.cpp
@@ -5,14 +5,14 @@
// **************************************************************************
#include "watcher.h"
-#include "../shared/file_handling.h"
-#include "../shared/i18n.h"
-#include "../shared/stl_tools.h"
+#include <zen/file_handling.h>
+#include <zen/stl_tools.h>
#include <set>
#include <wx/timer.h>
-#include "../shared/resolve_path.h"
-#include "../shared/dir_watcher.h"
-#include "../shared/string_conv.h"
+#include "../lib/resolve_path.h"
+#include <zen/dir_watcher.h>
+#include <wx+/string_conv.h>
+#include <zen/thread.h>
//#include "../library/db_file.h" //SYNC_DB_FILE_ENDING -> complete file too much of a dependency; file ending too little to decouple into single header
//#include "../library/lock_holder.h" //LOCK_FILE_ENDING
#include <wx/msgdlg.h>
@@ -64,12 +64,15 @@ rts::WaitResult rts::waitForChanges(const std::vector<Zstring>& dirNamesNonFmt,
const Zstring& dirnameFmt = *iter;
try
{
- watches.push_back(std::make_pair(dirnameFmt, std::make_shared<DirWatcher>(dirnameFmt))); //throw FileError
+ watches.push_back(std::make_pair(dirnameFmt, std::make_shared<DirWatcher>(dirnameFmt))); //throw FileError, ErrorNotExisting
}
- catch (FileError&)
+ catch (ErrorNotExisting&) //nice atomic behavior: *no* second directory existence check!!!
{
- //Note: checking for directory existence is NOT transactional!!!
- if (!dirExists(dirnameFmt)) //that's no good locking behavior, but better than nothing
+ return CHANGE_DIR_MISSING;
+ }
+ catch (FileError&) //play safe: remedy potential FileErrors that should have been ErrorNotExisting (e.g. Linux: errors during directory traversing)
+ {
+ if (!dirExists(dirnameFmt)) //not an atomic behavior!!!
return CHANGE_DIR_MISSING;
throw;
}
@@ -102,10 +105,10 @@ rts::WaitResult rts::waitForChanges(const std::vector<Zstring>& dirNamesNonFmt,
try
{
- std::vector<Zstring> changedFiles = watcher.getChanges(); //throw FileError
+ std::vector<Zstring> changedFiles = watcher.getChanges(); //throw FileError, ErrorNotExisting
//remove to be ignored changes
- vector_remove_if(changedFiles, [](const Zstring & name)
+ vector_remove_if(changedFiles, [](const Zstring& name)
{
return endsWith(name, Zstr(".ffs_lock")) || //sync.ffs_lock, sync.Del.ffs_lock
endsWith(name, Zstr(".ffs_db")); //sync.ffs_db, .sync.tmp.ffs_db
@@ -122,10 +125,13 @@ rts::WaitResult rts::waitForChanges(const std::vector<Zstring>& dirNamesNonFmt,
}
}
- catch (FileError&)
+ catch (ErrorNotExisting&) //nice atomic behavior: *no* second directory existence check!!!
{
- //Note: checking for directory existence is NOT transactional!!!
- if (!dirExists(dirname)) //catch errors related to directory removal, e.g. ERROR_NETNAME_DELETED
+ return CHANGE_DIR_MISSING;
+ }
+ catch (FileError&) //play safe: remedy potential FileErrors that should have been ErrorNotExisting (e.g. Linux: errors during directory traversing)
+ {
+ if (!dirExists(dirname)) //not an atomic behavior!!!
return CHANGE_DIR_MISSING;
throw;
}
@@ -149,18 +155,36 @@ void rts::waitForMissingDirs(const std::vector<Zstring>& dirNamesNonFmt, WaitCal
{
lastCheck = current;
- if (std::find_if(dirNamesNonFmt.begin(), dirNamesNonFmt.end(),
- [&](const Zstring& dirnameNonFmt) -> bool
- {
- //support specifying volume by name => call getFormattedDirectoryName() repeatedly
- const Zstring formattedDir = zen::getFormattedDirectoryName(dirnameNonFmt);
-
- if (formattedDir.empty())
- throw zen::FileError(_("A directory input field is empty."));
+ auto ftDirMissing = async([=]() -> bool
+ {
+ return std::find_if(dirNamesNonFmt.begin(), dirNamesNonFmt.end(),
+ [](const Zstring& dirnameNonFmt) -> bool
+ {
+ //support specifying volume by name => call getFormattedDirectoryName() repeatedly
+ const Zstring dirnameFmt = zen::getFormattedDirectoryName(dirnameNonFmt);
+
+ if (dirnameFmt.empty())
+ throw zen::FileError(_("A directory input field is empty."));
+#ifdef FFS_WIN
+ //1. login to network share, if necessary
+ loginNetworkShare(dirnameFmt, false); //login networks shares, no PW prompt -> is this really RTS's task?
+#endif
+ //2. check dir existence
+ return !zen::dirExists(dirnameFmt);
+ }) != dirNamesNonFmt.end();
+ });
+ while (!ftDirMissing.timed_wait(boost::posix_time::milliseconds(rts::UI_UPDATE_INTERVAL)))
+ statusHandler->requestUiRefresh(); //may throw!
- return !dirExists(formattedDir);
- }) == dirNamesNonFmt.end())
- return;
+ try
+ {
+ if (!ftDirMissing.get()) //throw X
+ return;
+ }
+ catch (...) //boost::future seems to map async exceptions to "some" boost exception type -> migrate this for C++11
+ {
+ throw zen::FileError(_("A directory input field is empty."));
+ }
}
wxMilliSleep(rts::UI_UPDATE_INTERVAL);
bgstack15