src: use InMemoryStoragePersistent instead of custom LsaSegmentStorage

refs: #4788

Change-Id: Ie5d8721915864ead2f30e7f5e6181f56acefc559
diff --git a/src/lsa-segment-storage.cpp b/src/lsa-segment-storage.cpp
deleted file mode 100644
index e7d6f2d..0000000
--- a/src/lsa-segment-storage.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014-2019,  The University of Memphis,
- *                           Regents of the University of California,
- *                           Arizona Board of Regents.
- *
- * This file is part of NLSR (Named-data Link State Routing).
- * See AUTHORS.md for complete list of NLSR authors and contributors.
- *
- * NLSR 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.
- *
- * NLSR 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 a copy of the GNU General Public License along with
- * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- **/
-
-#include "lsa-segment-storage.hpp"
-#include "logger.hpp"
-#include "lsa.hpp"
-#include "utility/name-helper.hpp"
-#include "conf-parameter.hpp"
-
-namespace nlsr {
-
-INIT_LOGGER(LsaSegmentStorage);
-
-LsaSegmentStorage::LsaSegmentStorage(ndn::Scheduler& scheduler)
-  : m_scheduler(scheduler)
-{
-}
-
-void
-LsaSegmentStorage::connectToFetcher(ndn::util::SegmentFetcher& fetcher)
-{
-  fetcher.afterSegmentValidated.connect(std::bind(&LsaSegmentStorage::afterFetcherSignalEmitted,
-                                                  this, _1));
-}
-
-const ndn::Data*
-LsaSegmentStorage::getLsaSegment(const ndn::Interest& interest)
-{
-  ndn::Name lsaSegmentsKey = interest.getName();
-
-  // If this is the first interest then it does not contain the segment number,
-  // so need to append zero segment component at the end to match with the data
-  if (lsaSegmentsKey.size() > 0) {
-    if (!lsaSegmentsKey.get(-1).isSegment()) {
-      lsaSegmentsKey.appendSegment(0);
-    }
-
-    auto it = m_lsaSegments.find(lsaSegmentsKey);
-    if (it == m_lsaSegments.end()) {
-      NLSR_LOG_TRACE("Data for interest: " << interest.getName() << " cannot be found in the lsa storage");
-
-      return nullptr;
-    }
-    else {
-      NLSR_LOG_TRACE("Data for interest: " << interest.getName() << " is in the storage.");
-      return &(it->second);
-    }
-  }
-  else {
-    NLSR_LOG_ERROR("Received interest has empty name.");
-    return nullptr;
-  }
-}
-
-void
-LsaSegmentStorage::afterFetcherSignalEmitted(const ndn::Data& lsaSegment)
-{
-  NLSR_LOG_TRACE("Received a LSA segment: " << lsaSegment.getName());
-
-  // lsaSegmentName is /<router-prefix>/<LS type>/<sequence no.>/<version no.>/<segment no.>
-  auto lsaSegmentName = lsaSegment.getName();
-
-  if (lsaSegmentName.size() > 0) {
-    // lsaSegmentsKey is /<router-prefix>/<LS type>/<sequence no.>/<segment no.>
-    ndn::Name lsaSegmentsKey(lsaSegmentName.getPrefix(lsaSegmentName.size() - 2));
-    lsaSegmentsKey.append(lsaSegmentName.get(-1));
-
-    // No need to store same LSA multiple time
-    if (m_lsaSegments.find(lsaSegmentsKey) == m_lsaSegments.end()) {
-      NLSR_LOG_TRACE("Received LSA segment is new. Storing it in the storage.");
-      NLSR_LOG_TRACE("LSA data segment's name: " << lsaSegmentName);
-
-      // Delete the same LSA with lower sequence number
-      deleteOldLsas(lsaSegmentName);
-
-      m_lsaSegments[lsaSegmentsKey] = lsaSegment;
-    }
-    else {
-      NLSR_LOG_TRACE("The received segment is already in the storage.");
-    }
-
-    ndn::time::seconds expirationTime(LSA_REFRESH_TIME_DEFAULT);
-
-    // schedule the segment deletion
-    scheduleLsaSegmentDeletion(lsaSegmentsKey, expirationTime);
-  }
-  else {
-    NLSR_LOG_ERROR("The received LSA segment has empty name.");
-  }
-}
-
-void
-LsaSegmentStorage::deleteOldLsas(const ndn::Name& newLsaName)
-{
-  auto newLsaKey = newLsaName.getPrefix(newLsaName.size() - 3);
-  auto newSeqNo = newLsaName.get(-3).toNumber();
-
-  std::vector<decltype(m_lsaSegments)::key_type> lsaToDelete;
-
-  for (const auto& segment : m_lsaSegments) {
-    ndn::Name segmentKey = segment.first;
-    auto oldSeqNo = segmentKey.get(-2).toNumber();
-    auto existingLsaKey = segmentKey.getPrefix(segmentKey.size() - 2);
-
-    if (newLsaKey == existingLsaKey) {
-      if (newSeqNo > oldSeqNo) { // in the key the second last component is the sequence number
-        NLSR_LOG_TRACE("Outdated LSA: " << segmentKey << " with seq no: " <<
-                       oldSeqNo << " is deleted.");
-        lsaToDelete.push_back(segmentKey);
-      }
-    }
-  }
-
-  for (const auto& segmentKey : lsaToDelete) {
-    m_lsaSegments.erase(segmentKey);
-  }
-}
-
-void
-LsaSegmentStorage::scheduleLsaSegmentDeletion(const ndn::Name& lsaSegmentsKey,
-                                              ndn::time::seconds expirationTime)
-{
-  NLSR_LOG_TRACE("Scheduling LSA segment deletion for "
-                 << lsaSegmentsKey << " in: " << expirationTime);
-  m_scheduler.schedule(expirationTime,
-                       [lsaSegmentsKey, this] { m_lsaSegments.erase(lsaSegmentsKey); });
-}
-
-} // namespace nlsr
diff --git a/src/lsa-segment-storage.hpp b/src/lsa-segment-storage.hpp
deleted file mode 100644
index 474f422..0000000
--- a/src/lsa-segment-storage.hpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2018,  The University of Memphis,
- *                           Regents of the University of California,
- *                           Arizona Board of Regents.
- *
- * This file is part of NLSR (Named-data Link State Routing).
- * See AUTHORS.md for complete list of NLSR authors and contributors.
- *
- * NLSR 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.
- *
- * NLSR 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 a copy of the GNU General Public License along with
- * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- **/
-
-#ifndef NLSR_LSA_SEGMENT_STORAGE_HPP
-#define NLSR_LSA_SEGMENT_STORAGE_HPP
-
-#include "test-access-control.hpp"
-
-#include <ndn-cxx/util/segment-fetcher.hpp>
-#include <ndn-cxx/util/signal.hpp>
-#include <ndn-cxx/util/time.hpp>
-
-#include <vector>
-#include <tuple>
-
-namespace nlsr {
-
-class LsaSegmentStorage
-{
-public:
-  LsaSegmentStorage(ndn::Scheduler& scheduler);
-
-  /*! \brief Get connected to the signal emitted by SegmentFetcher
-   * \param fetcher The SegmentFetcher to whose signal LsaSegmentStorage will subscribe to.
-   */
-  void
-  connectToFetcher(ndn::util::SegmentFetcher& fetcher);
-
-  /*! \brief Returns an LSA segment for an interest from LsaSegmentStorage
-   * \param interest Interest corresponding to the returned LSA segment.
-   */
-  const ndn::Data*
-  getLsaSegment(const ndn::Interest& interest);
-
-PUBLIC_WITH_TESTS_ELSE_PRIVATE:
-  /*! \brief Callback when SegmentFetcher retrieves a segment.
-   */
-   void
-   afterFetcherSignalEmitted(const ndn::Data& lsaSegment);
-
-private:
-  /*! \brief Given an LSA name check whether Data for the same name exists in the
-   * LsaSegmentStorage. If the matched LSA data are of a lower sequence number,
-   * then remove them from LsaSegmentStorage.
-   * \param newLsaName Name of the LSA that will be matched against
-   */
-  void
-  deleteOldLsas(const ndn::Name& newLsaName);
-
-  /*! \brief Schedules the deletion of a LSA data given the segmentKey
-   */
-  void
-  scheduleLsaSegmentDeletion(const ndn::Name& segmentKey, ndn::time::seconds expirationTime);
-
-
-private:
-  ndn::Scheduler& m_scheduler;
-
-  // Key: /<router-prefix>/<LS type>/<sequence no.>/<segment no.>
-  // Value: corresponding LSA data packet
-  //        Data name: /<router-prefix>/<LS type>/<sequence no.>/<version no.>/<segment no.>
-  std::unordered_map<ndn::Name, ndn::Data> m_lsaSegments;
-};
-
-} // namespace nlsr
-
-#endif // NLSR_LSA_SEGMENT_STORAGE_HPP
diff --git a/src/lsdb.cpp b/src/lsdb.cpp
index 58963f4..d917fa6 100644
--- a/src/lsdb.cpp
+++ b/src/lsdb.cpp
@@ -22,7 +22,6 @@
 #include "lsdb.hpp"
 
 #include "logger.hpp"
-#include "lsa-segment-storage.hpp"
 #include "nlsr.hpp"
 #include "utility/name-helper.hpp"
 
@@ -51,7 +50,6 @@
                    const uint64_t& sequenceNumber) {
              return isLsaNew(routerName, lsaType, sequenceNumber);
            }, m_confParam)
-  , m_lsaStorage(m_scheduler)
   , m_lsaRefreshTime(ndn::time::seconds(m_confParam.getLsaRefreshTime()))
   , m_thisRouterPrefix(m_confParam.getRouterPrefix().toUri())
   , m_adjLsaBuildInterval(m_confParam.getAdjLsaBuildInterval())
@@ -747,7 +745,6 @@
 {
   auto it = std::find_if(m_adjLsdb.begin(), m_adjLsdb.end(),
                          std::bind(adjLsaCompareByKey, _1, key));
-
   if (it != m_adjLsdb.end()) {
     NLSR_LOG_DEBUG("Deleting Adj Lsa");
     it->writeLog();
@@ -956,22 +953,29 @@
 
   auto it = m_fetchers.insert(fetcher).first;
 
-  fetcher->onComplete.connect([this, interestName, it] (ndn::ConstBufferPtr bufferPtr) {
-                                afterFetchLsa(bufferPtr, interestName);
-                                m_fetchers.erase(it);
-                              });
-
-  fetcher->onError.connect([this, interestName, timeoutCount, deadline, lsaName, seqNo, it]
-                           (uint32_t errorCode, const std::string& msg) {
-                             onFetchLsaError(errorCode, msg, interestName,
-                                             timeoutCount, deadline, lsaName, seqNo);
-                             m_fetchers.erase(it);
-                           });
-
-  m_lsaStorage.connectToFetcher(*fetcher);
   fetcher->afterSegmentValidated.connect([this] (const ndn::Data& data) {
-                                          afterSegmentValidatedSignal(data);
-                                         });
+    // Nlsr class subscribes to this to fetch certificates
+    afterSegmentValidatedSignal(data);
+
+    // If we don't do this IMS throws: std::bad_weak_ptr: bad_weak_ptr
+    auto lsaSegment = std::make_shared<const ndn::Data>(data);
+    m_lsaStorage.insert(*lsaSegment);
+    const ndn::Name& segmentName = lsaSegment->getName();
+    // Schedule deletion of the segment
+    m_scheduler.schedule(ndn::time::seconds(LSA_REFRESH_TIME_DEFAULT),
+                         [this, segmentName] { m_lsaStorage.erase(segmentName); });
+  });
+
+  fetcher->onComplete.connect([=] (const ndn::ConstBufferPtr& bufferPtr) {
+    m_lsaStorage.erase(ndn::Name(lsaName).appendNumber(seqNo - 1));
+    afterFetchLsa(bufferPtr, interestName);
+    m_fetchers.erase(it);
+  });
+
+  fetcher->onError.connect([=] (uint32_t errorCode, const std::string& msg) {
+    onFetchLsaError(errorCode, msg, interestName, timeoutCount, deadline, lsaName, seqNo);
+    m_fetchers.erase(it);
+  });
 
   // increment a specific SENT_LSA_INTEREST
   Lsa::Type lsaType;
@@ -1043,8 +1047,8 @@
     lsaIncrementSignal(Statistics::PacketType::SENT_LSA_DATA);
   }
   else { // else the interest is for other router's lsa, serve from LsaSegmentStorage
-    const ndn::Data* lsaSegment = m_lsaStorage.getLsaSegment(interest);
-    if (lsaSegment != nullptr) {
+    std::shared_ptr<const ndn::Data> lsaSegment = m_lsaStorage.find(interest);
+    if (lsaSegment) {
       NLSR_LOG_TRACE("Found data in lsa storage. Sending the data for " << interest.getName());
       m_face.put(*lsaSegment);
     }
diff --git a/src/lsdb.hpp b/src/lsdb.hpp
index 2c68906..9d6575f 100644
--- a/src/lsdb.hpp
+++ b/src/lsdb.hpp
@@ -24,7 +24,6 @@
 
 #include "conf-parameter.hpp"
 #include "lsa.hpp"
-#include "lsa-segment-storage.hpp"
 #include "sequencing-manager.hpp"
 #include "test-access-control.hpp"
 #include "communication/sync-logic-handler.hpp"
@@ -35,6 +34,7 @@
 #include <ndn-cxx/util/signal.hpp>
 #include <ndn-cxx/util/time.hpp>
 #include <ndn-cxx/util/segment-fetcher.hpp>
+#include <ndn-cxx/ims/in-memory-storage-persistent.hpp>
 
 #include <PSync/segment-publisher.hpp>
 
@@ -52,12 +52,6 @@
 
   ~Lsdb();
 
-  SyncLogicHandler&
-  getSyncLogicHandler()
-  {
-    return m_sync;
-  }
-
   bool
   isLsaNew(const ndn::Name& routerName, const Lsa::Type& lsaType, const uint64_t& sequenceNumber);
 
@@ -191,18 +185,6 @@
     m_adjLsaBuildInterval = ndn::time::seconds(interval);
   }
 
-  const ndn::time::seconds&
-  getAdjLsaBuildInterval() const
-  {
-    return m_adjLsaBuildInterval;
-  }
-
-  SequencingManager&
-  getSequencingManager()
-  {
-    return m_sequencingManager;
-  }
-
   void
   writeAdjLsdbLog();
 
@@ -326,6 +308,7 @@
   processInterestForCoordinateLsa(const ndn::Interest& interest,
                                   const ndn::Name& lsaKey,
                                   uint64_t seqNo);
+
   void
   onContentValidated(const std::shared_ptr<const ndn::Data>& data);
 
@@ -392,10 +375,9 @@
   ConfParameter& m_confParam;
   NamePrefixTable& m_namePrefixTable;
   RoutingTable& m_routingTable;
-  SyncLogicHandler m_sync;
 
 PUBLIC_WITH_TESTS_ELSE_PRIVATE:
-  LsaSegmentStorage m_lsaStorage;
+  SyncLogicHandler m_sync;
 
 private:
   std::list<NameLsa> m_nameLsdb;
@@ -414,10 +396,12 @@
   static const ndn::time::seconds GRACE_PERIOD;
   static const ndn::time::steady_clock::TimePoint DEFAULT_LSA_RETRIEVAL_DEADLINE;
 
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
   ndn::time::seconds m_adjLsaBuildInterval;
 
   SequencingManager m_sequencingManager;
 
+private:
   ndn::util::signal::ScopedConnection m_onNewLsaConnection;
 
   std::set<std::shared_ptr<ndn::util::SegmentFetcher>> m_fetchers;
@@ -425,6 +409,9 @@
 
   bool m_isBuildAdjLsaSheduled;
   int64_t m_adjBuildCount;
+
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+  ndn::InMemoryStoragePersistent m_lsaStorage;
 };
 
 } // namespace nlsr