**breaking change** nlsr.conf: rename seq-dir as state-dir

update: conf file in seperate directory for runtime modification

refs:  #4823

Change-Id: I5378d831294814e382ad23a9e522d0b576180f20
diff --git a/docs/ROUTER-CONFIG.rst b/docs/ROUTER-CONFIG.rst
index ca8ee77..89ac3f5 100644
--- a/docs/ROUTER-CONFIG.rst
+++ b/docs/ROUTER-CONFIG.rst
@@ -95,7 +95,7 @@
         ; InterestLifetime (in seconds) for LSA fetching
         lsa-interest-lifetime 4    ; default value 4. Valid values 1-60
 
-        seq-dir /var/lib/nlsr/
+        state-dir /var/lib/nlsr/ ; state directory to store all dynamic changes to NLSR
     }
 
     ; the neighbors section contains the configuration for router's neighbors and hello's behavior
@@ -209,7 +209,7 @@
     {
       ...
 
-      seq-dir /home/username/nlsr/log  ; path for sequence directory (Absolute path)
+      state-dir /home/username/nlsr/log  ; path for sequence directory and other dynamic changes (Absolute path)
 
     }
     ...
diff --git a/docs/manpages/nlsrc.rst b/docs/manpages/nlsrc.rst
index 352a537..2508fb3 100644
--- a/docs/manpages/nlsrc.rst
+++ b/docs/manpages/nlsrc.rst
@@ -46,7 +46,7 @@
     ``advertise <name> save``
 
       ``save``
-        Advertise a prefix and also save it to the nlsr.conf file for the next start of NLSR
+        Advertise a prefix and also save it to the nlsr.conf file residing in the state-dir for the next start of NLSR that operator may copy and use for the next start of NLSR
 
   ``withdraw``
     Remove a Name prefix advertised through NLSR
@@ -59,7 +59,7 @@
     ``withdraw <name> delete``
 
       ``delete``
-        Withdraw a prefix and also delete it from the nlsr.conf file
+        Withdraw a prefix and also delete it from the nlsr.conf file residing in the state-dir
 
 Notes
 -----
diff --git a/nlsr.conf b/nlsr.conf
index 8e574f5..791cbf0 100644
--- a/nlsr.conf
+++ b/nlsr.conf
@@ -25,7 +25,7 @@
   ; sync interest lifetime of ChronoSync/PSync in milliseconds
   sync-interest-lifetime 60000  ; default value 60000. Valid values 1000-120,000
 
-  seq-dir       /var/lib/nlsr        ; path for sequence directory (Absolute path)
+  state-dir       /var/lib/nlsr        ; path for intermediate state files including sequence directory (Absolute path)
 }
 
 ; the neighbor's section contains the configuration for router's neighbors and hellos behavior
diff --git a/src/conf-file-processor.cpp b/src/conf-file-processor.cpp
index bdf39a1..a468e6c 100644
--- a/src/conf-file-processor.cpp
+++ b/src/conf-file-processor.cpp
@@ -322,17 +322,26 @@
   }
 
   try {
-    std::string seqDir = section.get<std::string>("seq-dir");
-    if (boost::filesystem::exists(seqDir)) {
-      if (boost::filesystem::is_directory(seqDir)) {
-        std::string testFileName=seqDir+"/test.seq";
-        std::ofstream testOutFile;
-        testOutFile.open(testFileName.c_str());
-        if (testOutFile.is_open() && testOutFile.good()) {
-          m_confParam.setSeqFileDir(seqDir);
+    std::string stateDir = section.get<std::string>("state-dir");
+    if (boost::filesystem::exists(stateDir)) {
+      if (boost::filesystem::is_directory(stateDir)) {
+
+        // copying nlsr.conf file to a user define directory for possible modification
+        std::string conFileDynamic = (boost::filesystem::path(stateDir) / "nlsr.conf").c_str();
+        m_confParam.setConfFileNameDynamic(conFileDynamic);
+        try {
+          copy_file(m_confFileName, conFileDynamic, boost::filesystem::copy_option::overwrite_if_exists);
+        }
+        catch (const boost::filesystem::filesystem_error& e) {
+          std::cerr << "Error copying conf file to the state directory: " << e.what() << std::endl;
+        }
+        std::string testFileName = (boost::filesystem::path(stateDir) / "test.seq").c_str();
+        std::ofstream testOutFile(testFileName);
+        if (testOutFile) {
+          m_confParam.setStateFileDir(stateDir);
         }
         else {
-          std::cerr << "User does not have read and write permission on the directory";
+          std::cerr << "User does not have read and write permission on the state directory";
           std::cerr << std::endl;
           return false;
         }
@@ -340,17 +349,17 @@
         remove(testFileName.c_str());
       }
       else {
-        std::cerr << "Provided path is not a directory" << std::endl;
+        std::cerr << "Provided: " << stateDir << "is not a directory" << std::endl;
         return false;
       }
     }
     else {
-      std::cerr << "Provided sequence directory <" << seqDir << "> does not exist" << std::endl;
+      std::cerr << "Provided state directory <" << stateDir << "> does not exist" << std::endl;
       return false;
     }
   }
   catch (const std::exception& ex) {
-    std::cerr << "You must configure sequence directory" << std::endl;
+    std::cerr << "You must configure state directory" << std::endl;
     std::cerr << ex.what() << std::endl;
     return false;
   }
diff --git a/src/conf-parameter.cpp b/src/conf-parameter.cpp
index 2d50838..948d804 100644
--- a/src/conf-parameter.cpp
+++ b/src/conf-parameter.cpp
@@ -78,7 +78,7 @@
   for (auto const& value: m_corTheta) {
     NLSR_LOG_INFO("Hyp Angle " << i++ << ": "<< value);
   }
-  NLSR_LOG_INFO("Seq Directory: " << m_seqFileDir);
+  NLSR_LOG_INFO("State Directory: " << m_stateFileDir);
 
   // Event Intervals
   NLSR_LOG_INFO("Adjacency LSA build interval:  " << m_adjLsaBuildInterval);
diff --git a/src/conf-parameter.hpp b/src/conf-parameter.hpp
index c1f6073..1ecf6c8 100644
--- a/src/conf-parameter.hpp
+++ b/src/conf-parameter.hpp
@@ -404,15 +404,26 @@
   }
 
   void
-  setSeqFileDir(const std::string& ssfd)
+  setStateFileDir(const std::string& ssfd)
   {
-    m_seqFileDir = ssfd;
+    m_stateFileDir = ssfd;
   }
 
   const std::string&
-  getSeqFileDir() const
+  getStateFileDir() const
   {
-    return m_seqFileDir;
+    return m_stateFileDir;
+  }
+
+  void setConfFileNameDynamic(const std::string& confFileDynamic)
+  {
+    m_confFileNameDynamic = confFileDynamic;
+  }
+
+  const std::string&
+  getConfFileNameDynamic() const
+  {
+    return m_confFileNameDynamic;
   }
 
   void
@@ -497,11 +508,14 @@
 
   uint32_t m_maxFacesPerPrefix;
 
-  std::string m_seqFileDir;
+  std::string m_stateFileDir;
+
   ndn::time::milliseconds m_syncInterestLifetime;
 
   int32_t m_syncProtocol;
 
+  std::string m_confFileNameDynamic;
+
 PUBLIC_WITH_TESTS_ELSE_PRIVATE:
   static const uint64_t SYNC_VERSION;
 
diff --git a/src/lsdb.cpp b/src/lsdb.cpp
index e4b3912..4159c4f 100644
--- a/src/lsdb.cpp
+++ b/src/lsdb.cpp
@@ -55,7 +55,7 @@
   , m_lsaRefreshTime(ndn::time::seconds(m_confParam.getLsaRefreshTime()))
   , m_thisRouterPrefix(m_confParam.getRouterPrefix().toUri())
   , m_adjLsaBuildInterval(m_confParam.getAdjLsaBuildInterval())
-  , m_sequencingManager(m_confParam.getSeqFileDir(), m_confParam.getHyperbolicState())
+  , m_sequencingManager(m_confParam.getStateFileDir(), m_confParam.getHyperbolicState())
   , m_onNewLsaConnection(m_sync.onNewLsa->connect(
       [this] (const ndn::Name& updateName, uint64_t sequenceNumber) {
         ndn::Name lsaInterest{updateName};
diff --git a/src/nlsr.cpp b/src/nlsr.cpp
index 33855ee..78e6d0c 100644
--- a/src/nlsr.cpp
+++ b/src/nlsr.cpp
@@ -64,7 +64,7 @@
                             m_confParam.getPrefixUpdateValidator(),
                             m_namePrefixList,
                             m_lsdb,
-                            m_confParam.getConfFileName())
+                            m_confParam.getConfFileNameDynamic())
   , m_nfdRibCommandProcessor(m_dispatcher,
                              m_namePrefixList,
                              m_lsdb)
diff --git a/src/update/prefix-update-processor.cpp b/src/update/prefix-update-processor.cpp
index 6222198..0e20c8c 100644
--- a/src/update/prefix-update-processor.cpp
+++ b/src/update/prefix-update-processor.cpp
@@ -56,7 +56,7 @@
                                              Lsdb& lsdb, const std::string& configFileName)
   : CommandManagerBase(dispatcher, namePrefixList, lsdb, "prefix-update")
   , m_validator(validator)
-  , m_configFileName(configFileName)
+  , m_confFileNameDynamic(configFileName)
 {
   NLSR_LOG_DEBUG("Setting dispatcher to capture Interests for: "
     << ndn::Name(Nlsr::LOCALHOST_PREFIX).append("prefix-update"));
@@ -108,7 +108,7 @@
 PrefixUpdateProcessor::checkForPrefixInFile(const std::string prefix)
 {
   std::string line;
-  std::fstream fp(m_configFileName);
+  std::fstream fp(m_confFileNameDynamic);
   if (!fp.good() || !fp.is_open()) {
     NLSR_LOG_ERROR("Failed to open configuration file for parsing");
     return true;
@@ -130,7 +130,7 @@
   std::string fileString;
   std::string line;
   std::string trimedLine;
-  std::fstream input(m_configFileName, input.in);
+  std::fstream input(m_confFileNameDynamic, input.in);
   if (!input.good() || !input.is_open()) {
     NLSR_LOG_ERROR("Failed to open configuration file for parsing");
     return false;
@@ -171,7 +171,7 @@
     }
   }
   input.close();
-  std::ofstream output(m_configFileName);
+  std::ofstream output(m_confFileNameDynamic);
   output << fileString;
   output.close();
   return true;
diff --git a/src/update/prefix-update-processor.hpp b/src/update/prefix-update-processor.hpp
index f397df1..9aedae3 100644
--- a/src/update/prefix-update-processor.hpp
+++ b/src/update/prefix-update-processor.hpp
@@ -96,7 +96,7 @@
 
 private:
   ndn::security::ValidatorConfig& m_validator;
-  const std::string& m_configFileName;
+  const std::string& m_confFileNameDynamic;
 };
 
 } // namespace update
diff --git a/tests/test-conf-file-processor.cpp b/tests/test-conf-file-processor.cpp
index 9cff6f9..4f0d8a7 100644
--- a/tests/test-conf-file-processor.cpp
+++ b/tests/test-conf-file-processor.cpp
@@ -45,7 +45,7 @@
   "  router-dead-interval 86400\n"
   "  sync-protocol psync\n"
   "  sync-interest-lifetime 10000\n"
-  "  seq-dir /tmp\n"
+  "  state-dir /tmp\n"
   "}\n\n";
 
 const std::string SECTION_NEIGHBORS =
@@ -176,7 +176,7 @@
   BOOST_CHECK_EQUAL(conf.getLsaInterestLifetime(), ndn::time::seconds(3));
   BOOST_CHECK_EQUAL(conf.getRouterDeadInterval(), 86400);
   BOOST_CHECK_EQUAL(conf.getSyncInterestLifetime(), ndn::time::milliseconds(10000));
-  BOOST_CHECK_EQUAL(conf.getSeqFileDir(), "/tmp");
+  BOOST_CHECK_EQUAL(conf.getStateFileDir(), "/tmp");
 
   // Neighbors
   BOOST_CHECK_EQUAL(conf.getInterestRetryNumber(), 3);
diff --git a/tests/update/test-save-delete-prefix.cpp b/tests/update/test-save-delete-prefix.cpp
index ab65564..10988bf 100644
--- a/tests/update/test-save-delete-prefix.cpp
+++ b/tests/update/test-save-delete-prefix.cpp
@@ -24,6 +24,7 @@
 
 #include "../control-commands.hpp"
 #include "../test-common.hpp"
+#include "conf-parameter.hpp"
 
 #include <ndn-cxx/mgmt/nfd/control-response.hpp>
 #include <ndn-cxx/security/command-interest-signer.hpp>
@@ -58,6 +59,7 @@
     source.close();
     destination.close();
 
+    conf.setConfFileNameDynamic(testConfFile);
     siteIdentity = addIdentity(siteIdentityName);
     saveCertificate(siteIdentity, SITE_CERT_PATH.string());
 
@@ -80,6 +82,7 @@
         }
       }
     }
+
     inputFile.close();
 
     // Site cert
@@ -172,7 +175,7 @@
 
 BOOST_AUTO_TEST_CASE(Basic)
 {
-  // only advertise
+
   face.receive(advertiseWithdraw("/prefix/to/save", "advertise", false));
   this->advanceClocks(ndn::time::milliseconds(10));
   BOOST_CHECK_EQUAL(checkPrefix("/prefix/to/save"), false);
@@ -208,7 +211,7 @@
   BOOST_CHECK_EQUAL(checkPrefix("/prefix/to/save"), true);
 
   // trying to advertise same name prefix
-  /*face.receive(advertiseWithdraw("/prefix/to/save", "advertise", true));
+  face.receive(advertiseWithdraw("/prefix/to/save", "advertise", true));
   this->advanceClocks(ndn::time::milliseconds(10));
   BOOST_REQUIRE(counter == 1);
   BOOST_CHECK_EQUAL(getResponseCode(), 406);
@@ -226,7 +229,7 @@
   this->advanceClocks(ndn::time::milliseconds(10));
   // after withdrawn delete prefix should be deleted from the file
   BOOST_CHECK_EQUAL(getResponseCode(), 205);
-  BOOST_CHECK_EQUAL(checkPrefix("/prefix/to/save"), false);*/
+  BOOST_CHECK_EQUAL(checkPrefix("/prefix/to/save"), false);
 }
 
 BOOST_AUTO_TEST_SUITE_END()