Delaying saving of the local state change from dispatcher (useful when many changes happen at about the same time)

Change-Id: I6082a335ce1f061ddcd53b7ce46f4edbab310fbe
diff --git a/src/dispatcher.cc b/src/dispatcher.cc
index 0a2bb82..bfa970c 100644
--- a/src/dispatcher.cc
+++ b/src/dispatcher.cc
@@ -168,6 +168,14 @@
       return;
     }
 
+  if (currentFile &&
+      !currentFile->is_complete ())
+    {
+      _LOG_ERROR ("Got notification about incomplete file [" << relativeFilePath << "]");
+      return;
+    }
+
+
   int seg_num;
   HashPtr hash;
   tie (hash, seg_num) = m_objectManager.localFileToObjects (absolutePath, m_localUserName);
@@ -179,7 +187,7 @@
                                          last_write_time (absolutePath), status (absolutePath).permissions (), seg_num);
 
       // notify SyncCore to propagate the change
-      m_core->localStateChanged();
+      m_core->localStateChangedDelayed ();
     }
   catch (filesystem::filesystem_error &error)
     {
@@ -213,7 +221,7 @@
 
   m_actionLog->AddLocalActionDelete (relativeFilePath.generic_string());
   // notify SyncCore to propagate the change
-  m_core->localStateChanged();
+  m_core->localStateChangedDelayed();
 }
 
 /////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -300,6 +308,7 @@
                                   0, action->seg_num () - 1, FetchManager::PRIORITY_NORMAL);
         }
     }
+  // if necessary (when version number is the highest) delete will be applied through the trigger in m_actionLog->AddRemoteAction call
 }
 
 void
diff --git a/src/sync-core.cc b/src/sync-core.cc
index 4aaf1a5..f744f26 100644
--- a/src/sync-core.cc
+++ b/src/sync-core.cc
@@ -38,6 +38,8 @@
 const std::string SYNC_INTEREST_TAG = "send-sync-interest";
 const std::string SYNC_INTEREST_TAG2 = "send-sync-interest2";
 
+const std::string LOCAL_STATE_CHANGE_DELAYED_TAG = "local-state-changed";
+
 using namespace boost;
 using namespace Ccnx;
 
@@ -112,6 +114,15 @@
 }
 
 void
+SyncCore::localStateChangedDelayed ()
+{
+  // many calls to localStateChangedDelayed within 0.5 second will be suppressed to one localStateChanged calls
+  Scheduler::scheduleOneTimeTask (m_scheduler, 0.5,
+                                  bind (&SyncCore::localStateChanged, this),
+                                  LOCAL_STATE_CHANGE_DELAYED_TAG);
+}
+
+void
 SyncCore::handleInterest(const Name &name)
 {
   int size = name.size();
diff --git a/src/sync-core.h b/src/sync-core.h
index b804ac5..c2b427b 100644
--- a/src/sync-core.h
+++ b/src/sync-core.h
@@ -56,6 +56,15 @@
   void
   localStateChanged ();
 
+  /**
+   * @brief Schedule an event to update local state with a small delay
+   *
+   * This call is preferred to localStateChanged if many local state updates
+   * are anticipated within a short period of time
+   */
+  void
+  localStateChangedDelayed ();
+
   void
   updateLocalState (sqlite3_int64);