Chronoshare should still watch the filesystem even the connection is closed.

Used only one ioService to control connection and file watch

Change-Id: Ib54d5f839acecc89f7f2391bb8b2590eac362ffe
diff --git a/core/chronoshare-common.hpp b/core/chronoshare-common.hpp
index 44b5873..56ee89c 100644
--- a/core/chronoshare-common.hpp
+++ b/core/chronoshare-common.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2013-2016, Regents of the University of California.
+ * Copyright (c) 2013-2017, Regents of the University of California.
  *
  * This file is part of ChronoShare, a decentralized file sharing application over NDN.
  *
@@ -18,8 +18,8 @@
  * See AUTHORS.md for complete list of ChronoShare authors and contributors.
  */
 
-#ifndef CHRONOSHARE_CORE_COMMON_HPP
-#define CHRONOSHARE_CORE_COMMON_HPP
+#ifndef CHRONOSHARE_CORE_CHRONOSHARE_COMMON_HPP
+#define CHRONOSHARE_CORE_CHRONOSHARE_COMMON_HPP
 
 #include "core/chronoshare-config.hpp"
 
@@ -46,7 +46,7 @@
 using std::shared_ptr;
 using std::make_shared;
 
-} // chronoshare
-} // ndn
+} // namespace chronoshare
+} // namespace ndn
 
-#endif // CHRONOSHARE_CORE_COMMON_HPP
+#endif // CHRONOSHARE_CORE_CHRONOSHARE_COMMON_HPP
diff --git a/gui/chronosharegui.cpp b/gui/chronosharegui.cpp
index ef4af73..8df191f 100644
--- a/gui/chronosharegui.cpp
+++ b/gui/chronosharegui.cpp
@@ -107,7 +107,8 @@
   m_trayIcon->show();
 
   // load settings
-  if (!loadSettings()) {
+  if (!loadSettings() || m_username.isNull() || m_username == "" || m_sharedFolderName.isNull() ||
+      m_sharedFolderName == "" || m_dirPath.isNull() || m_dirPath == "") {
     // prompt user to choose folder
     openMessageBox("First Time Setup",
                    "Please enter a username, shared folder name and choose the shared folder path on your local filesystem.");
@@ -116,15 +117,7 @@
     viewSettings();
   }
   else {
-    if (m_username.isNull() || m_username == "" || m_sharedFolderName.isNull() ||
-        m_sharedFolderName == "") {
-      openMessageBox("First Time Setup",
-                     "To activate ChronoShare, please configure your username and shared folder name.");
-      viewSettings();
-    }
-    else {
-      startBackend();
-    }
+    startBackend();
   }
 }
 
@@ -146,6 +139,10 @@
     m_watcher.reset();    // stop filewatching ASAP
     m_dispatcher.reset(); // stop dispatcher ASAP, but after watcher(to prevent triggering callbacks
                           // on deleted object)
+    m_ioServiceWork.reset();
+    m_ioSerciceManager->handle_stop();
+    m_NetworkThread.join();
+    delete m_ioSerciceManager;
   }
 
   fs::path realPathToFolder(m_dirPath.toStdString());
@@ -164,6 +161,21 @@
   m_watcher.reset(new FsWatcher(*m_ioService, realPathToFolder.string().c_str(),
                                 bind(&Dispatcher::Did_LocalFile_AddOrModify, m_dispatcher.get(), _1),
                                 bind(&Dispatcher::Did_LocalFile_Delete, m_dispatcher.get(), _1)));
+  try {
+    m_ioSerciceManager = new IoServiceManager(*m_ioService);
+    m_NetworkThread = std::thread(&IoServiceManager::run, m_ioSerciceManager);
+  }
+  catch (const std::exception& e) {
+    _LOG_ERROR("Start IO service or Face failed");
+    openWarningMessageBox("", "WARNING: Cannot allocate thread for face and io_service!",
+                          QString("Starting chronoshare failed"
+                                  "Exception caused: %1")
+                            .arg(e.what()));
+    // stop filewatching ASAP
+    m_watcher.reset();
+    m_dispatcher.reset();
+    return;
+  }
 
   if (m_httpServer != 0) {
     // no need to restart webserver if it already exists
@@ -176,18 +188,14 @@
       m_httpServer = new http::server::server(HTTP_SERVER_ADDRESS, HTTP_SERVER_PORT, DOC_ROOT);
       m_httpServerThread = std::thread(&http::server::server::run, m_httpServer);
     }
-    catch (std::exception& e) {
+    catch (const std::exception& e) {
       _LOG_ERROR("Start http server failed");
       m_httpServer = 0; // just to make sure
-      QMessageBox msgBox;
-      msgBox.setText("WARNING: Cannot start http server!");
-      msgBox.setIcon(QMessageBox::Warning);
-      msgBox.setInformativeText(
-        QString("Starting http server failed. You will not be able to check history from web "
-                "brower. Exception caused: %1")
-          .arg(e.what()));
-      msgBox.setStandardButtons(QMessageBox::Ok);
-      msgBox.exec();
+      openWarningMessageBox("WARNING", "WARNING: Cannot start http server!",
+                            QString("Starting http server failed. You will "
+                                    "not be able to check history from web "
+                                    "brower. Exception caused: %1")
+                              .arg(e.what()));
     }
   }
   else {
@@ -203,6 +211,12 @@
   // stop dispatcher ASAP, but after watcher to prevent triggering callbacks on the deleted object
   m_dispatcher.reset();
 
+  m_ioServiceWork.reset();
+  m_ioSerciceManager->handle_stop();
+  m_chronoshareThread.join();
+  m_NetworkThread.join();
+  delete m_ioSerciceManager;
+
   if (m_httpServer != 0) {
     m_httpServer->handle_stop();
     m_httpServerThread.join();
@@ -259,6 +273,20 @@
 }
 
 void
+ChronoShareGui::openWarningMessageBox(QString title, QString text, QString infotext)
+{
+  QMessageBox messageBox(this);
+  messageBox.setWindowTitle(title);
+  messageBox.setText(text);
+  messageBox.setInformativeText(infotext);
+
+  messageBox.setIcon(QMessageBox::Warning);
+  messageBox.setStandardButtons(QMessageBox::Ok);
+
+  messageBox.exec();
+}
+
+void
 ChronoShareGui::createActionsAndMenu()
 {
   _LOG_DEBUG("Create actions");
diff --git a/gui/chronosharegui.hpp b/gui/chronosharegui.hpp
index 827e7c3..f9844da 100644
--- a/gui/chronosharegui.hpp
+++ b/gui/chronosharegui.hpp
@@ -38,6 +38,7 @@
 #ifndef Q_MOC_RUN
 #include "dispatcher.hpp"
 #include "fs-watcher.hpp"
+#include "io-service-manager.hpp"
 #include "server.hpp"
 #endif // Q_MOC_RUN
 
@@ -126,6 +127,9 @@
   void
   openMessageBox(QString title, QString text, QString infotext);
 
+  void
+  openWarningMessageBox(QString title, QString text, QString infotext);
+
   // capture close event
   void
   closeEvent(QCloseEvent* event);
@@ -152,6 +156,7 @@
   QString m_sharedFolderName; // shared folder name
 
   http::server::server* m_httpServer;
+  IoServiceManager* m_ioSerciceManager;
   std::thread m_httpServerThread;
 
   QLabel* labelUsername;
@@ -171,7 +176,10 @@
   // QString m_settings;
 
   std::thread m_chronoshareThread;
+  std::thread m_NetworkThread;
   std::unique_ptr<boost::asio::io_service> m_ioService;
+  std::unique_ptr<boost::asio::io_service::work> m_ioServiceWork;
+
   std::unique_ptr<Face> m_face;
   std::unique_ptr<FsWatcher> m_watcher;
   std::unique_ptr<Dispatcher> m_dispatcher;
diff --git a/src/io-service-manager.cpp b/src/io-service-manager.cpp
new file mode 100644
index 0000000..8a735aa
--- /dev/null
+++ b/src/io-service-manager.cpp
@@ -0,0 +1,67 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017, Regents of the University of California.
+ *
+ * This file is part of ChronoShare, a decentralized file sharing application over NDN.
+ *
+ * ChronoShare is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * ChronoShare is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License along with
+ * ChronoShare, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ChronoShare authors and contributors.
+ */
+
+#include "io-service-manager.hpp"
+#include "core/logging.hpp"
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/thread/thread.hpp>
+
+namespace ndn {
+namespace chronoshare {
+
+using namespace ndn::chronoshare;
+
+_LOG_INIT(FaceService);
+
+IoServiceManager::IoServiceManager(boost::asio::io_service& io)
+  : m_ioService(io)
+  , m_connect(true)
+{
+}
+
+IoServiceManager::~IoServiceManager()
+{
+  handle_stop();
+}
+
+void
+IoServiceManager::run()
+{
+  while (m_connect) {
+    try {
+      m_ioServiceWork.reset(new boost::asio::io_service::work(m_ioService));
+      m_ioService.reset();
+      m_ioService.run();
+    }
+    catch (...) {
+      _LOG_DEBUG("error while connecting to the forwarder");
+    }
+  }
+}
+
+void
+IoServiceManager::handle_stop()
+{
+  m_connect = false;
+  m_ioService.stop();
+}
+
+} // namespace chronoshare
+} // namespace ndn
diff --git a/src/io-service-manager.hpp b/src/io-service-manager.hpp
new file mode 100644
index 0000000..016ff50
--- /dev/null
+++ b/src/io-service-manager.hpp
@@ -0,0 +1,61 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017, Regents of the University of California.
+ *
+ * This file is part of ChronoShare, a decentralized file sharing application over NDN.
+ *
+ * ChronoShare is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * ChronoShare is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License along with
+ * ChronoShare, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ChronoShare authors and contributors.
+ */
+
+#ifndef CHRONOSHARE_SRC_IO_SERVICE_MANAGER_HPP
+#define CHRONOSHARE_SRC_IO_SERVICE_MANAGER_HPP
+
+#include <ndn-cxx/face.hpp>
+#include <boost/asio/io_service.hpp>
+
+#define RECONNECTION_TIME 30000
+
+namespace ndn {
+namespace chronoshare {
+
+/// The class prevent face loss connection to NFD.
+class IoServiceManager : private boost::noncopyable
+{
+public:
+  /// Construct the server to listen on the specified TCP address and port, and
+  /// serve up files from the given directory.
+
+  IoServiceManager(boost::asio::io_service& io);
+
+  ~IoServiceManager();
+
+  /// Run the service's io_service loop.
+  void
+  run();
+
+  /// Handle a request to stop the service.
+  void
+  handle_stop();
+
+private:
+  /// the IO service used by NFD connection.
+  boost::asio::io_service& m_ioService;
+  std::unique_ptr<boost::asio::io_service::work> m_ioServiceWork;
+  bool m_connect;
+};
+
+} // namespace chronoshare
+} // namespace ndn
+
+#endif // CHRONOSHARE_SRC_IO_SERVICE_MANAGER_HPP
diff --git a/wscript b/wscript
index 5a9ebf4..78b5cd3 100644
--- a/wscript
+++ b/wscript
@@ -92,21 +92,12 @@
         target="chronoshare",
         features=['cxx'],
         source=bld.path.ant_glob(['src/*.proto',
-                                  'src/db-helper.cpp',
-                                  'src/sync-*.cpp',
-                                  'src/file-state.cpp',
-                                  'src/action-log.cpp',
-                                  'src/object-*.cpp',
-                                  'src/fetch*.cpp',
-                                  'src/content-server.cpp',
-                                  'src/dispatcher.cpp',
-                                  'src/state-server.cpp'
+                                  'src/*.cpp',
                                   ]),
         use='core-objects adhoc NDN_CXX BOOST TINYXML SQLITE3',
         includes="src",
         export_includes="src",
         )
-    Logs.error("Most of Chronoshare source compilation is temporary disabled")
 
     fs_watcher = bld(
           features=['qt5', 'cxx'],