Merge branch 'master' of git.irl.cs.ucla.edu:ndn/chronoshare
diff --git a/gui/fs-watcher.cc b/gui/fs-watcher.cc
index a97f8b4..94c6b3f 100644
--- a/gui/fs-watcher.cc
+++ b/gui/fs-watcher.cc
@@ -38,7 +38,7 @@
                       QObject* parent)
   : QObject(parent)
   , m_watcher (new QFileSystemWatcher())
-  , m_executor (1)
+  , m_scheduler (new Scheduler ())
   , m_dirPath (dirPath)
   , m_onChange (onChange)
   , m_onDelete (onDelete)
@@ -52,22 +52,27 @@
   connect (m_watcher, SIGNAL (directoryChanged (QString)), this, SLOT (DidDirectoryChanged (QString)));
   connect (m_watcher, SIGNAL (fileChanged (QString)),      this, SLOT (DidFileChanged (QString)));
 
-  m_executor.execute (bind (&FsWatcher::ScanDirectory_Notify_Execute, this, m_dirPath));
-  m_executor.start ();
+  m_scheduler->start ();
+
+  Scheduler::scheduleOneTimeTask (m_scheduler, 0.1,
+                                  bind (&FsWatcher::ScanDirectory_Notify_Execute, this, m_dirPath),
+                                  m_dirPath.toStdString ()); // only one task will be scheduled per directory
 }
 
 FsWatcher::~FsWatcher()
 {
-  m_executor.shutdown ();
-  delete m_watcher;
+  m_scheduler->shutdown ();
 }
 
 void
 FsWatcher::DidDirectoryChanged (QString dirPath)
 {
-  // _LOG_DEBUG ("Triggered DirPath: " << dirPath.toStdString ());
+  _LOG_DEBUG ("Triggered DirPath: " << dirPath.toStdString ());
 
-  m_executor.execute (bind (&FsWatcher::ScanDirectory_Notify_Execute, this, dirPath));
+  // m_executor.execute (bind (&FsWatcher::ScanDirectory_Notify_Execute, this, dirPath));
+  Scheduler::scheduleOneTimeTask (m_scheduler, 0.5,
+                                  bind (&FsWatcher::ScanDirectory_Notify_Execute, this, dirPath),
+                                  dirPath.toStdString ()); // only one task will be scheduled per directory
 }
 
 void
@@ -85,32 +90,23 @@
   if (filesystem::exists (filesystem::path (absPathTriggeredFile)))
     {
       _LOG_DEBUG ("Triggered UPDATE of file:  " << triggeredFile.relative_path ().generic_string ());
-      m_onChange (triggeredFile.relative_path ());
+      // m_onChange (triggeredFile.relative_path ());
+
+      Scheduler::scheduleOneTimeTask (m_scheduler, 0.5,
+                                      bind (m_onChange, triggeredFile.relative_path ()),
+                                      triggeredFile.relative_path ().string());
     }
   else
     {
       _LOG_DEBUG ("Triggered DELETE of file: " << triggeredFile.relative_path ().generic_string ());
-      m_onDelete (triggeredFile.relative_path ());
+      // m_onDelete (triggeredFile.relative_path ());
+
+      Scheduler::scheduleOneTimeTask (m_scheduler, 0.5,
+                                      bind (m_onDelete, triggeredFile.relative_path ()),
+                                      triggeredFile.relative_path ().string());
     }
 }
 
-
-void FsWatcher::DidDirectoryChanged_Execute (QString dirPath)
-{
-//   // scan directory and populate file list
-//   QHash<QString, qint64> currentState = scanDirectory(dirPath);
-
-//   // reconcile directory and report changes
-//   std::vector<sEventInfo> dirChanges = reconcileDirectory(currentState, dirPath);
-// #ifdef _DEBUG
-//   // DEBUG: Print Changes
-//   printChanges(dirChanges);
-// #endif
-//   // emit the signal if not empty
-//   if(!dirChanges.empty())
-//     emit dirEventSignal(dirChanges);
-}
-
 void
 FsWatcher::ScanDirectory_Notify_Execute (QString dirPath)
 {
diff --git a/gui/fs-watcher.h b/gui/fs-watcher.h
index 6ba6671..109e8da 100644
--- a/gui/fs-watcher.h
+++ b/gui/fs-watcher.h
@@ -26,7 +26,7 @@
 #include <QFileSystemWatcher>
 #include <boost/filesystem.hpp>
 
-#include "executor.h"
+#include "scheduler.h"
 
 class FsWatcher : public QObject
 {
@@ -57,9 +57,6 @@
 
 private:
   // handle callback from the watcher
-  void
-  DidDirectoryChanged_Execute (QString dirPath);
-
   // scan directory and notify callback about any file changes
   void
   ScanDirectory_Notify_Execute (QString dirPath);
@@ -76,7 +73,7 @@
 
 private:
   QFileSystemWatcher* m_watcher; // filesystem watcher
-  Executor m_executor;
+  SchedulerPtr m_scheduler;
 
   QString m_dirPath; // monitored path
 
diff --git a/src/dispatcher.cc b/src/dispatcher.cc
index ea634b6..5b4388e 100644
--- a/src/dispatcher.cc
+++ b/src/dispatcher.cc
@@ -157,12 +157,19 @@
   HashPtr hash;
   tie (hash, seg_num) = m_objectManager.localFileToObjects (absolutePath, m_localUserName);
 
-  m_actionLog->AddLocalActionUpdate (relativeFilePath.generic_string(),
-                                     *hash,
-                                     last_write_time (absolutePath), status (absolutePath).permissions (), seg_num);
+  try
+    {
+      m_actionLog->AddLocalActionUpdate (relativeFilePath.generic_string(),
+                                         *hash,
+                                         last_write_time (absolutePath), status (absolutePath).permissions (), seg_num);
 
-  // notify SyncCore to propagate the change
-  m_core->localStateChanged();
+      // notify SyncCore to propagate the change
+      m_core->localStateChanged();
+    }
+  catch (filesystem::filesystem_error &error)
+    {
+      _LOG_ERROR ("File operations failed on [" << relativeFilePath << "] (ignoring)");
+    }
 }
 
 void
@@ -178,7 +185,7 @@
   if (filesystem::exists(absolutePath))
     {
       //BOOST_THROW_EXCEPTION (Error::Dispatcher() << error_info_str("Delete notification but file exists: " + absolutePath.string() ));
-      _LOG_DEBUG("DELETE command, but file still exists: " << absolutePath.string());
+      _LOG_ERROR("DELETE command, but file still exists: " << absolutePath.string());
       return;
     }
 
diff --git a/src/fetch-manager.cc b/src/fetch-manager.cc
index 4c0ba02..a883118 100644
--- a/src/fetch-manager.cc
+++ b/src/fetch-manager.cc
@@ -49,7 +49,7 @@
   m_scheduler->start ();
 
   m_scheduleFetchesTask = Scheduler::schedulePeriodicTask (m_scheduler,
-                                                           make_shared<SimpleIntervalGenerator> (1),
+                                                           make_shared<SimpleIntervalGenerator> (300), // no need to check to often. if needed, will be rescheduled
                                                            bind (&FetchManager::ScheduleFetches, this), SCHEDULE_FETCHES_TAG);
 }
 
@@ -107,6 +107,7 @@
   unique_lock<mutex> lock (m_parellelFetchMutex);
 
   boost::posix_time::ptime currentTime = date_time::second_clock<boost::posix_time::ptime>::universal_time ();
+  boost::posix_time::ptime nextSheduleCheck = currentTime + posix_time::seconds (300); // no reason to have anything, but just in case
 
   for (FetchList::iterator item = m_fetchList.begin ();
        m_currentParallelFetches < m_maxParallelFetches && item != m_fetchList.end ();
@@ -120,6 +121,9 @@
 
       if (currentTime < item->GetNextScheduledRetry ())
         {
+          if (item->GetNextScheduledRetry () < nextSheduleCheck)
+            nextSheduleCheck = item->GetNextScheduledRetry ();
+
           _LOG_DEBUG ("Item is delayed");
           continue;
         }
@@ -129,6 +133,8 @@
       m_currentParallelFetches ++;
       item->RestartPipeline ();
     }
+
+  m_scheduler->rescheduleTaskAt (m_scheduleFetchesTask, (nextSheduleCheck - currentTime).seconds ());
 }
 
 void
@@ -168,6 +174,8 @@
 
   fetcher.SetRetryPause (delay);
   fetcher.SetNextScheduledRetry (date_time::second_clock<boost::posix_time::ptime>::universal_time () + posix_time::seconds (delay));
+
+  m_scheduler->rescheduleTaskAt (m_scheduleFetchesTask, 0);
 }
 
 void
@@ -179,4 +187,5 @@
     m_fetchList.erase_and_dispose (FetchList::s_iterator_to (fetcher), fetcher_disposer ());
   }
 
+  m_scheduler->rescheduleTaskAt (m_scheduleFetchesTask, 0);
 }