From 8bf668665b107469086f16cb8ad23e47d479d2b4 Mon Sep 17 00:00:00 2001 From: Daniel Wilhelm Date: Fri, 18 Apr 2014 17:14:37 +0200 Subject: 4.0 --- RealtimeSync/RealtimeSync.cbp | 3 +- RealtimeSync/RealtimeSync.vcxproj | 6 +- RealtimeSync/application.cpp | 2 +- RealtimeSync/gui_generated.cpp | 42 +++++------ RealtimeSync/gui_generated.h | 4 +- RealtimeSync/main_dlg.cpp | 6 +- RealtimeSync/main_dlg.h | 4 +- RealtimeSync/makefile | 1 + RealtimeSync/resources.cpp | 2 +- RealtimeSync/tray_menu.cpp | 13 +++- RealtimeSync/watcher.cpp | 151 +++++++++++++++++--------------------- RealtimeSync/watcher.h | 15 +++- RealtimeSync/xml_ffs.cpp | 6 +- 13 files changed, 127 insertions(+), 128 deletions(-) (limited to 'RealtimeSync') diff --git a/RealtimeSync/RealtimeSync.cbp b/RealtimeSync/RealtimeSync.cbp index 8464abfc..5a928487 100644 --- a/RealtimeSync/RealtimeSync.cbp +++ b/RealtimeSync/RealtimeSync.cbp @@ -65,6 +65,7 @@ + @@ -125,7 +126,6 @@ - @@ -135,6 +135,7 @@ + diff --git a/RealtimeSync/RealtimeSync.vcxproj b/RealtimeSync/RealtimeSync.vcxproj index 5936b74c..f6f018a1 100644 --- a/RealtimeSync/RealtimeSync.vcxproj +++ b/RealtimeSync/RealtimeSync.vcxproj @@ -28,7 +28,7 @@ Application true Unicode - v100 + Windows7.1SDK Application @@ -41,7 +41,7 @@ false true Unicode - v100 + Windows7.1SDK Application @@ -230,12 +230,12 @@ - + diff --git a/RealtimeSync/application.cpp b/RealtimeSync/application.cpp index 6b7e81e9..aa1a1385 100644 --- a/RealtimeSync/application.cpp +++ b/RealtimeSync/application.cpp @@ -93,7 +93,7 @@ int Application::OnRun() wxFile safeOutput(zen::getConfigDir() + wxT("LastError.txt"), wxFile::write); safeOutput.Write(wxString::FromAscii(e.what())); - wxSafeShowMessage(_("An exception occurred!"), wxString::FromAscii(e.what())); + wxSafeShowMessage(_("An exception occurred!") + L" - RTS", wxString::FromAscii(e.what())); return -9; } diff --git a/RealtimeSync/gui_generated.cpp b/RealtimeSync/gui_generated.cpp index 13f789f7..2ec50c11 100644 --- a/RealtimeSync/gui_generated.cpp +++ b/RealtimeSync/gui_generated.cpp @@ -14,7 +14,7 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style ) { - this->SetSizeHints( wxSize( 420,440 ), wxDefaultSize ); + this->SetSizeHints( wxSize( 420, 440 ), wxDefaultSize ); m_menubar1 = new wxMenuBar( 0 ); m_menuFile = new wxMenu(); @@ -66,7 +66,7 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr m_staticText2->Wrap( -1 ); m_staticText2->SetFont( wxFont( 10, 74, 90, 90, true, wxEmptyString ) ); - sbSizer41->Add( m_staticText2, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + sbSizer41->Add( m_staticText2, 0, wxBOTTOM | wxRIGHT | wxLEFT, 5 ); m_staticText3 = new wxStaticText( m_panelMain, wxID_ANY, _("1. Select directories to monitor."), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText3->Wrap( -1 ); @@ -81,16 +81,16 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr sbSizer41->Add( m_staticText5, 0, wxLEFT, 10 ); m_staticline3 = new wxStaticLine( m_panelMain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - sbSizer41->Add( m_staticline3, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); + sbSizer41->Add( m_staticline3, 0, wxEXPAND | wxTOP | wxBOTTOM, 5 ); m_staticText21 = new wxStaticText( m_panelMain, wxID_ANY, _("The command line is executed each time:\n- all directories become available (e.g. USB stick insert)\n- files within these directories or subdirectories are modified"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText21->Wrap( -1 ); - sbSizer41->Add( m_staticText21, 0, wxRIGHT|wxLEFT|wxEXPAND, 5 ); + sbSizer41->Add( m_staticText21, 0, wxRIGHT | wxLEFT | wxEXPAND, 5 ); - bSizer1->Add( sbSizer41, 0, wxALIGN_CENTER_HORIZONTAL|wxRIGHT|wxLEFT|wxEXPAND, 40 ); + bSizer1->Add( sbSizer41, 0, wxALIGN_CENTER_HORIZONTAL | wxRIGHT | wxLEFT | wxEXPAND, 40 ); m_staticline2 = new wxStaticLine( m_panelMain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer1->Add( m_staticline2, 0, wxTOP|wxBOTTOM|wxEXPAND, 10 ); + bSizer1->Add( m_staticline2, 0, wxTOP | wxBOTTOM | wxEXPAND, 10 ); wxBoxSizer* bSizer8; bSizer8 = new wxBoxSizer( wxVERTICAL ); @@ -104,15 +104,15 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr wxBoxSizer* bSizer781; bSizer781 = new wxBoxSizer( wxHORIZONTAL ); - m_bpButtonAddFolder = new wxBitmapButton( m_panelMainFolder, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19,21 ), wxBU_AUTODRAW ); + m_bpButtonAddFolder = new wxBitmapButton( m_panelMainFolder, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19, 21 ), wxBU_AUTODRAW ); m_bpButtonAddFolder->SetToolTip( _("Add folder") ); - bSizer781->Add( m_bpButtonAddFolder, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer781->Add( m_bpButtonAddFolder, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 5 ); - m_bpButtonRemoveTopFolder = new wxBitmapButton( m_panelMainFolder, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19,21 ), wxBU_AUTODRAW ); + m_bpButtonRemoveTopFolder = new wxBitmapButton( m_panelMainFolder, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19, 21 ), wxBU_AUTODRAW ); m_bpButtonRemoveTopFolder->SetToolTip( _("Remove folder") ); - bSizer781->Add( m_bpButtonRemoveTopFolder, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer781->Add( m_bpButtonRemoveTopFolder, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL, 5 ); bSizer114->Add( bSizer781, 0, wxALIGN_CENTER_VERTICAL, 5 ); @@ -129,7 +129,7 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr bSizer114->Fit( m_panelMainFolder ); sbSizerDirToWatch->Add( m_panelMainFolder, 0, wxEXPAND, 5 ); - m_scrolledWinFolders = new wxScrolledWindow( m_panelMain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); + m_scrolledWinFolders = new wxScrolledWindow( m_panelMain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL | wxVSCROLL ); m_scrolledWinFolders->SetScrollRate( 5, 5 ); bSizerFolders = new wxBoxSizer( wxVERTICAL ); @@ -138,7 +138,7 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr bSizerFolders->Fit( m_scrolledWinFolders ); sbSizerDirToWatch->Add( m_scrolledWinFolders, 0, wxEXPAND, 5 ); - bSizer8->Add( sbSizerDirToWatch, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + bSizer8->Add( sbSizerDirToWatch, 0, wxEXPAND | wxBOTTOM | wxRIGHT | wxLEFT, 5 ); bSizer1->Add( bSizer8, 1, wxEXPAND, 5 ); @@ -146,9 +146,9 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr sbSizer3 = new wxStaticBoxSizer( new wxStaticBox( m_panelMain, wxID_ANY, _("Command line") ), wxVERTICAL ); m_textCtrlCommand = new wxTextCtrl( m_panelMain, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); - sbSizer3->Add( m_textCtrlCommand, 0, wxEXPAND|wxBOTTOM, 5 ); + sbSizer3->Add( m_textCtrlCommand, 0, wxEXPAND | wxBOTTOM, 5 ); - bSizer1->Add( sbSizer3, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); + bSizer1->Add( sbSizer3, 0, wxEXPAND | wxTOP | wxRIGHT | wxLEFT, 5 ); wxStaticBoxSizer* sbSizer4; sbSizer4 = new wxStaticBoxSizer( new wxStaticBox( m_panelMain, wxID_ANY, _("Minimum Idle Time [seconds]") ), wxVERTICAL ); @@ -156,20 +156,20 @@ MainDlgGenerated::MainDlgGenerated( wxWindow* parent, wxWindowID id, const wxStr m_spinCtrlDelay = new wxSpinCtrl( m_panelMain, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 2000000000, 0 ); m_spinCtrlDelay->SetToolTip( _("Idle time between detection of last change and execution of command line in seconds") ); - sbSizer4->Add( m_spinCtrlDelay, 0, wxBOTTOM|wxRIGHT|wxLEFT|wxALIGN_CENTER_HORIZONTAL, 5 ); + sbSizer4->Add( m_spinCtrlDelay, 0, wxBOTTOM | wxRIGHT | wxLEFT | wxALIGN_CENTER_HORIZONTAL, 5 ); - bSizer1->Add( sbSizer4, 0, wxEXPAND|wxRIGHT|wxLEFT, 5 ); + bSizer1->Add( sbSizer4, 0, wxEXPAND | wxRIGHT | wxLEFT, 5 ); m_staticline1 = new wxStaticLine( m_panelMain, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); - bSizer1->Add( m_staticline1, 0, wxEXPAND|wxTOP|wxBOTTOM, 10 ); + bSizer1->Add( m_staticline1, 0, wxEXPAND | wxTOP | wxBOTTOM, 10 ); - m_buttonStart = new wxButtonWithImage( m_panelMain, wxID_ANY, _("Start"), wxDefaultPosition, wxSize( -1,40 ), 0 ); + m_buttonStart = new wxButtonWithImage( m_panelMain, wxID_ANY, _("Start"), wxDefaultPosition, wxSize( -1, 40 ), 0 ); m_buttonStart->SetDefault(); m_buttonStart->SetFont( wxFont( 14, 74, 90, 92, false, wxT("Arial Black") ) ); - bSizer1->Add( m_buttonStart, 0, wxALL|wxALIGN_CENTER_HORIZONTAL, 5 ); + bSizer1->Add( m_buttonStart, 0, wxALL | wxALIGN_CENTER_HORIZONTAL, 5 ); - m_buttonCancel = new wxButton( m_panelMain, wxID_CANCEL, _("dummy"), wxDefaultPosition, wxSize( 0,0 ), 0 ); + m_buttonCancel = new wxButton( m_panelMain, wxID_CANCEL, _("dummy"), wxDefaultPosition, wxSize( 0, 0 ), 0 ); bSizer1->Add( m_buttonCancel, 0, 0, 5 ); m_panelMain->SetSizer( bSizer1 ); @@ -215,7 +215,7 @@ FolderGenerated::FolderGenerated( wxWindow* parent, wxWindowID id, const wxPoint wxBoxSizer* bSizer114; bSizer114 = new wxBoxSizer( wxHORIZONTAL ); - m_bpButtonRemoveFolder = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19,21 ), wxBU_AUTODRAW ); + m_bpButtonRemoveFolder = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( 19, 21 ), wxBU_AUTODRAW ); m_bpButtonRemoveFolder->SetToolTip( _("Remove folder") ); bSizer114->Add( m_bpButtonRemoveFolder, 0, wxALIGN_CENTER_VERTICAL, 5 ); diff --git a/RealtimeSync/gui_generated.h b/RealtimeSync/gui_generated.h index aee6a5e8..fa31652f 100644 --- a/RealtimeSync/gui_generated.h +++ b/RealtimeSync/gui_generated.h @@ -89,7 +89,7 @@ protected: public: FfsDirPickerCtrl* m_dirPickerMain; - MainDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("RealtimeSync - Automated Synchronization"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL ); + MainDlgGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("RealtimeSync - Automated Synchronization"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxDEFAULT_FRAME_STYLE | wxTAB_TRAVERSAL ); ~MainDlgGenerated(); @@ -109,7 +109,7 @@ public: wxTextCtrl* m_txtCtrlDirectory; FfsDirPickerCtrl* m_dirPicker; - FolderGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL ); + FolderGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1, -1 ), long style = wxTAB_TRAVERSAL ); ~FolderGenerated(); }; diff --git a/RealtimeSync/main_dlg.cpp b/RealtimeSync/main_dlg.cpp index e8851428..539a8bbe 100644 --- a/RealtimeSync/main_dlg.cpp +++ b/RealtimeSync/main_dlg.cpp @@ -42,7 +42,7 @@ MainDialog::MainDialog(wxDialog* dlg, const wxString& cfgFileName) Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(MainDialog::OnKeyPressed), NULL, this); //prepare drag & drop - dirNameFirst.reset(new zen::DirectoryName(*m_panelMainFolder, *m_dirPickerMain, *m_txtCtrlDirectoryMain, sbSizerDirToWatch)); + dirNameFirst.reset(new DirectoryName(*m_panelMainFolder, *m_dirPickerMain, *m_txtCtrlDirectoryMain, sbSizerDirToWatch)); #ifdef FFS_WIN @@ -127,9 +127,9 @@ const wxString& MainDialog::lastConfigFileName() void MainDialog::OnShowHelp(wxCommandEvent& event) { #ifdef FFS_WIN - zen::displayHelpEntry(wxT("html\\advanced\\RealtimeSync.html")); + zen::displayHelpEntry(wxT("html\\RealtimeSync.html")); #elif defined FFS_LINUX - zen::displayHelpEntry(wxT("html/advanced/RealtimeSync.html")); + zen::displayHelpEntry(wxT("html/RealtimeSync.html")); #endif } diff --git a/RealtimeSync/main_dlg.h b/RealtimeSync/main_dlg.h index 54d4d50c..ca054b65 100644 --- a/RealtimeSync/main_dlg.h +++ b/RealtimeSync/main_dlg.h @@ -30,7 +30,7 @@ public: wxString getName() const { return dirName.getName(); } private: - zen::DirectoryName dirName; + zen::DirectoryName dirName; }; @@ -69,7 +69,7 @@ private: static const wxString& lastConfigFileName(); - std::auto_ptr dirNameFirst; + std::auto_ptr> dirNameFirst; std::vector dirNamesExtra; //additional pairs to the standard pair wxString currentConfigFileName; diff --git a/RealtimeSync/makefile b/RealtimeSync/makefile index 3bc19061..c0ac3aa5 100644 --- a/RealtimeSync/makefile +++ b/RealtimeSync/makefile @@ -26,6 +26,7 @@ FILE_LIST+=xml_proc.cpp FILE_LIST+=xml_ffs.cpp FILE_LIST+=../library/process_xml.cpp FILE_LIST+=../structures.cpp +FILE_LIST+=../shared/folder_history_box.cpp FILE_LIST+=../shared/util.cpp FILE_LIST+=../shared/i18n.cpp FILE_LIST+=../shared/localization.cpp diff --git a/RealtimeSync/resources.cpp b/RealtimeSync/resources.cpp index e9231623..2a7e2818 100644 --- a/RealtimeSync/resources.cpp +++ b/RealtimeSync/resources.cpp @@ -41,7 +41,7 @@ GlobalResources::~GlobalResources() void GlobalResources::load() const { - wxFFileInputStream input(zen::getResourceDir() + wxT("Resources.dat")); + wxFFileInputStream input(zen::getResourceDir() + wxT("Resources.zip")); if (input.IsOk()) //if not... we don't want to react too harsh here { //activate support for .png files diff --git a/RealtimeSync/tray_menu.cpp b/RealtimeSync/tray_menu.cpp index 98c66cb5..cbdf6070 100644 --- a/RealtimeSync/tray_menu.cpp +++ b/RealtimeSync/tray_menu.cpp @@ -227,7 +227,7 @@ std::vector convert(const std::vector& dirList) { std::set output; std::transform(dirList.begin(), dirList.end(), - std::inserter(output, output.end()), [](const wxString& str) { return zen::toZ(str); }); + std::inserter(output, output.end()), [](const wxString & str) { return zen::toZ(str); }); return std::vector(output.begin(), output.end()); } } @@ -291,15 +291,16 @@ watcher.h (low level wait for directory changes) rts::MonitorResponse rts::startDirectoryMonitor(const xmlAccess::XmlRealConfig& config, const wxString& jobname) { - const std::vector dirList = convert(config.directories); + Zstring lastFileChanged; + const std::vector dirList = convert(config.directories); try { WaitCallbackImpl callback(jobname); if (config.commandline.empty()) { - std::wstring errorMsg = _("Invalid commandline: %x"); + std::wstring errorMsg = _("Invalid command line: %x"); replace(errorMsg, L"%x", L"\"" + config.commandline + L"\""); throw FileError(errorMsg); } @@ -310,6 +311,8 @@ rts::MonitorResponse rts::startDirectoryMonitor(const xmlAccess::XmlRealConfig& while (true) { + ::wxSetEnv(L"changed_file", utf8CvrtTo(lastFileChanged)); //some way to output what file changed to the user + //execute command zen::shellExecute(config.commandline, zen::EXEC_TYPE_SYNC); @@ -322,7 +325,8 @@ rts::MonitorResponse rts::startDirectoryMonitor(const xmlAccess::XmlRealConfig& while (true) { //wait for changes (and for all directories to become available) - switch (waitForChanges(dirList, &callback)) + WaitResult res = waitForChanges(dirList, &callback); + switch (res.type) { case CHANGE_DIR_MISSING: //don't execute the commandline before all directories are available! callback.scheduleNextSync(std::numeric_limits::max()); //next sync not scheduled (yet) @@ -331,6 +335,7 @@ rts::MonitorResponse rts::startDirectoryMonitor(const xmlAccess::XmlRealConfig& callback.notifyAllDirectoriesExist(); break; case CHANGE_DETECTED: + lastFileChanged = res.filename; break; } diff --git a/RealtimeSync/watcher.cpp b/RealtimeSync/watcher.cpp index b17c63ba..37664d35 100644 --- a/RealtimeSync/watcher.cpp +++ b/RealtimeSync/watcher.cpp @@ -7,6 +7,7 @@ #include "watcher.h" #include "../shared/file_handling.h" #include "../shared/i18n.h" +#include "../shared/stl_tools.h" #include #include #include "../shared/resolve_path.h" @@ -32,112 +33,102 @@ bool rts::updateUiIsAllowed() return false; } - -class MonitorExistence //detect changes to directory availability +namespace { -public: - MonitorExistence() : allExisting_(true) {} - - //initialization - void addForMonitoring(const Zstring& dirName) - { - dirList.insert(dirName); - } - - bool allExisting() const //polling explicitly allowed! - { - const int UPDATE_INTERVAL = 1000; //1 second interval - - const wxLongLong current = wxGetLocalTimeMillis(); - if (current - lastCheck >= UPDATE_INTERVAL) - { - lastCheck = current; - allExisting_ = std::find_if(dirList.begin(), dirList.end(), std::not1(std::ptr_fun(&zen::dirExists))) == dirList.end(); - } - - return allExisting_; - } - -private: - mutable wxLongLong lastCheck; - mutable bool allExisting_; - - std::set dirList; //save avail. directories, avoid double-entries -}; - +const int CHECK_DIR_INTERVAL = 1000; //1 second interval +} -rts::WaitResult rts::waitForChanges(const std::vector& dirNames, WaitCallback* statusHandler) //throw(FileError) +rts::WaitResult rts::waitForChanges(const std::vector& dirNamesNonFmt, WaitCallback* statusHandler) //throw FileError { - if (dirNames.empty()) //pathological case, but check is needed nevertheless - throw zen::FileError(_("A directory input field is empty.")); + std::set dirNamesFmt; - //detect when volumes are removed/are not available anymore - MonitorExistence checkExist; - std::vector> watches; - - for (std::vector::const_iterator i = dirNames.begin(); i != dirNames.end(); ++i) + std::for_each(dirNamesNonFmt.begin(), dirNamesNonFmt.end(), + [&](const Zstring& dirnameNonFmt) { - const Zstring formattedDir = zen::getFormattedDirectoryName(*i); + const Zstring& dirnameFmt = zen::getFormattedDirectoryName(dirnameNonFmt); - if (formattedDir.empty()) + if (dirnameFmt.empty()) throw zen::FileError(_("A directory input field is empty.")); + dirNamesFmt.insert(dirnameFmt); + }); + if (dirNamesFmt.empty()) //pathological case, but check is needed nevertheless + throw zen::FileError(_("A directory input field is empty.")); - checkExist.addForMonitoring(formattedDir); + //detect when volumes are removed/are not available anymore + std::vector>> watches; + + for (auto iter = dirNamesFmt.begin(); iter != dirNamesFmt.end(); ++iter) + { + const Zstring& dirnameFmt = *iter; try { - watches.push_back(std::make_shared(formattedDir)); //throw FileError + watches.push_back(std::make_pair(dirnameFmt, std::make_shared(dirnameFmt))); //throw FileError } - catch (zen::FileError&) + catch (FileError&) { - if (!zen::dirExists(formattedDir)) //that's no good locking behavior, but better than nothing + //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; throw; } } + wxLongLong lastCheck; while (true) { - //IMPORTANT CHECK: dirwatcher has problems detecting removal of top watched directories! - if (!checkExist.allExisting()) //check for removed devices: - return CHANGE_DIR_MISSING; + const bool checkDirExistNow = [&lastCheck]() -> bool //checking once per sec should suffice + { + const wxLongLong current = wxGetLocalTimeMillis(); + if (current - lastCheck >= CHECK_DIR_INTERVAL) + { + lastCheck = current; + return true; + } + return false; + }(); - try + + for (auto iter = watches.begin(); iter != watches.end(); ++iter) { - for (auto iter = watches.begin(); iter != watches.end(); ++iter) + const Zstring& dirname = iter->first; + DirWatcher& watcher = *(iter->second); + + //IMPORTANT CHECK: dirwatcher has problems detecting removal of top watched directories! + if (checkDirExistNow) + if (!dirExists(dirname)) //catch errors related to directory removal, e.g. ERROR_NETNAME_DELETED + return CHANGE_DIR_MISSING; + + try { - std::vector changedFiles = (*iter)->getChanges(); //throw FileError + std::vector changedFiles = watcher.getChanges(); //throw FileError //remove to be ignored changes - changedFiles.erase(std::remove_if(changedFiles.begin(), changedFiles.end(), - [](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 //no need to ignore temporal recycle bin directory: this must be caused by a file deletion anyway - }), changedFiles.end()); + }); if (!changedFiles.empty()) { /* std::for_each(changedFiles.begin(), changedFiles.end(), [](const Zstring& fn) { wxMessageBox(toWx(fn));}); - - const wxString filename = toWx(changedFiles[0]); - ::wxSetEnv(wxT("RTS_CHANGE"), filename); */ - - return CHANGE_DETECTED; //directory change detected + return WaitResult(CHANGE_DETECTED, changedFiles[0]); //directory change detected } + + } + catch (FileError&) + { + //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; + throw; } - } - catch (FileError&) - { - //maybe some error is caused due to some unexpected removal/unavailability of a watched directory? If so we can remedy this error: - if (!checkExist.allExisting()) - return CHANGE_DIR_MISSING; - throw; } wxMilliSleep(rts::UI_UPDATE_INTERVAL); @@ -147,35 +138,29 @@ rts::WaitResult rts::waitForChanges(const std::vector& dirNames, WaitCa //support for monitoring newly connected directories volumes (e.g.: USB-sticks) -void rts::waitForMissingDirs(const std::vector& dirNames, WaitCallback* statusHandler) //throw(FileError) +void rts::waitForMissingDirs(const std::vector& dirNamesNonFmt, WaitCallback* statusHandler) //throw FileError { wxLongLong lastCheck; while (true) { - const int UPDATE_INTERVAL = 1000; //1 second interval const wxLongLong current = wxGetLocalTimeMillis(); - if (current - lastCheck >= UPDATE_INTERVAL) + if (current - lastCheck >= CHECK_DIR_INTERVAL) { lastCheck = current; - bool allExisting = true; - for (std::vector::const_iterator i = dirNames.begin(); i != dirNames.end(); ++i) - { - //support specifying volume by name => call getFormattedDirectoryName() repeatedly - const Zstring formattedDir = zen::getFormattedDirectoryName(*i); + 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.")); - if (!zen::dirExists(formattedDir)) - { - allExisting = false; - break; - } - } - if (allExisting) //check for newly arrived devices: - return; + return !dirExists(formattedDir); + }) == dirNamesNonFmt.end()) + return; } wxMilliSleep(rts::UI_UPDATE_INTERVAL); diff --git a/RealtimeSync/watcher.h b/RealtimeSync/watcher.h index 04a0d860..dd0dd88d 100644 --- a/RealtimeSync/watcher.h +++ b/RealtimeSync/watcher.h @@ -28,15 +28,24 @@ public: //wait until changes are detected or if a directory is not available (anymore) -enum WaitResult +enum ChangeType { CHANGE_DETECTED, CHANGE_DIR_MISSING }; -WaitResult waitForChanges(const std::vector& dirNames, WaitCallback* statusHandler); //throw(FileError) +struct WaitResult +{ + WaitResult(ChangeType tp, const Zstring& chgFile = Zstring()) : type(tp), filename(chgFile) {} + + ChangeType type; + Zstring filename; //filled if type == CHANGE_DETECTED +}; +WaitResult waitForChanges(const std::vector& dirNamesNonFmt, //non-formatted dir names that yet require call to getFormattedDirectoryName() + WaitCallback* statusHandler); //throw(FileError) //wait until all directories become available (again) -void waitForMissingDirs(const std::vector& dirNames, WaitCallback* statusHandler); //throw(FileError) +void waitForMissingDirs(const std::vector& dirNamesNonFmt, + WaitCallback* statusHandler); //throw(FileError) } #endif // WATCHER_H_INCLUDED diff --git a/RealtimeSync/xml_ffs.cpp b/RealtimeSync/xml_ffs.cpp index ed0a4331..23ee1b38 100644 --- a/RealtimeSync/xml_ffs.cpp +++ b/RealtimeSync/xml_ffs.cpp @@ -6,9 +6,7 @@ #include "xml_ffs.h" #include "../shared/standard_paths.h" -#include "../shared/global_func.h" #include "../shared/zstring.h" -//#include "functions.h" #include "../shared/xml_base.h" #include "../shared/string_conv.h" @@ -30,7 +28,7 @@ xmlAccess::XmlRealConfig convertBatchToReal(const xmlAccess::XmlBatchConfig& bat //additional folders std::for_each(batchCfg.mainCfg.additionalPairs.begin(), batchCfg.mainCfg.additionalPairs.end(), - [&](const FolderPairEnh& fp) + [&](const FolderPairEnh & fp) { uniqueFolders.insert(fp.leftDirectory); uniqueFolders.insert(fp.rightDirectory); @@ -40,7 +38,7 @@ xmlAccess::XmlRealConfig convertBatchToReal(const xmlAccess::XmlBatchConfig& bat output.directories.clear(); std::transform(uniqueFolders.begin(), uniqueFolders.end(), std::back_inserter(output.directories), - [](const Zstring& fn) { return toWx(fn); }); + [](const Zstring & fn) { return toWx(fn); }); output.commandline = wxT("\"") + zen::getLauncher() + wxT("\"") + wxT(" \"") + filename + wxT("\""); -- cgit