lsa-segment-storage: fix segfault in scheduled erase of lsa segment
refs: #4520
Change-Id: I597604b4be9e063a08ff5031faa8d305408b676d
diff --git a/src/lsa-segment-storage.cpp b/src/lsa-segment-storage.cpp
index fa656d3..3e85bd0 100644
--- a/src/lsa-segment-storage.cpp
+++ b/src/lsa-segment-storage.cpp
@@ -23,15 +23,14 @@
#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,
- const ndn::time::seconds lsaDeletionTimepoint)
+LsaSegmentStorage::LsaSegmentStorage(ndn::Scheduler& scheduler)
: m_scheduler(scheduler)
- , m_lsaDeletionTimepoint(lsaDeletionTimepoint)
{
}
@@ -98,8 +97,23 @@
NLSR_LOG_TRACE("The received segment is already in the storage.");
}
+ std::string content(reinterpret_cast<const char*>(lsaSegment.getContent().value()),
+ lsaSegment.getContent().value_size());
+
+ ndn::time::seconds expirationTime(LSA_REFRESH_TIME_DEFAULT);
+
+ std::vector<std::string> options;
+ boost::split(options, content, boost::is_any_of("|"));
+
+ try {
+ expirationTime = ndn::time::duration_cast<ndn::time::seconds>
+ (ndn::time::system_clock::now() - ndn::time::fromIsoString(options.at(3)));
+ } catch (const std::exception& e) {
+ NLSR_LOG_ERROR("Cannot extract expiration time from LSA content: " << e.what());
+ }
+
// schedule the segment deletion
- scheduleLsaSegmentDeletion(lsaSegmentsKey);
+ scheduleLsaSegmentDeletion(lsaSegmentsKey, expirationTime);
}
else {
NLSR_LOG_ERROR("The received LSA segment has empty name.");
@@ -114,7 +128,7 @@
std::vector<decltype(m_lsaSegments)::key_type> lsaToDelete;
- for (auto& segment : m_lsaSegments) {
+ for (const auto& segment : m_lsaSegments) {
ndn::Name segmentKey = segment.first;
auto oldSeqNo = segmentKey.get(-2).toNumber();
auto existingLsaKey = segmentKey.getPrefix(segmentKey.size() - 2);
@@ -128,16 +142,19 @@
}
}
- for (auto& segmentKey : lsaToDelete) {
+ for (const auto& segmentKey : lsaToDelete) {
m_lsaSegments.erase(segmentKey);
}
}
void
-LsaSegmentStorage::scheduleLsaSegmentDeletion(const ndn::Name& lsaSegmentsKey)
+LsaSegmentStorage::scheduleLsaSegmentDeletion(const ndn::Name& lsaSegmentsKey,
+ ndn::time::seconds expirationTime)
{
- m_scheduler.scheduleEvent(m_lsaDeletionTimepoint,
- [&, this] {
+ NLSR_LOG_TRACE("Scheduling LSA segment deletion for "
+ << lsaSegmentsKey << " in: " << expirationTime);
+ m_scheduler.scheduleEvent(expirationTime,
+ [lsaSegmentsKey, this] {
m_lsaSegments.erase(lsaSegmentsKey);
});
}
diff --git a/src/lsa-segment-storage.hpp b/src/lsa-segment-storage.hpp
index 468b2fe..474f422 100644
--- a/src/lsa-segment-storage.hpp
+++ b/src/lsa-segment-storage.hpp
@@ -36,8 +36,7 @@
class LsaSegmentStorage
{
public:
- LsaSegmentStorage(ndn::Scheduler& scheduler,
- const ndn::time::seconds lsaDeletionTimepoint);
+ LsaSegmentStorage(ndn::Scheduler& scheduler);
/*! \brief Get connected to the signal emitted by SegmentFetcher
* \param fetcher The SegmentFetcher to whose signal LsaSegmentStorage will subscribe to.
@@ -69,7 +68,7 @@
/*! \brief Schedules the deletion of a LSA data given the segmentKey
*/
void
- scheduleLsaSegmentDeletion(const ndn::Name& segmentKey);
+ scheduleLsaSegmentDeletion(const ndn::Name& segmentKey, ndn::time::seconds expirationTime);
private:
@@ -79,8 +78,6 @@
// 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;
-
- const ndn::time::seconds m_lsaDeletionTimepoint;
};
} // namespace nlsr
diff --git a/src/lsdb.cpp b/src/lsdb.cpp
index 5ebef48..a38dd55 100644
--- a/src/lsdb.cpp
+++ b/src/lsdb.cpp
@@ -72,8 +72,7 @@
const uint64_t& sequenceNumber) {
return isLsaNew(routerName, lsaType, sequenceNumber);
}, m_nlsr.getConfParameter())
- , m_lsaStorage(scheduler,
- ndn::time::seconds(m_nlsr.getConfParameter().getLsaRefreshTime()))
+ , m_lsaStorage(scheduler)
, m_lsaRefreshTime(0)
, m_adjLsaBuildInterval(ADJ_LSA_BUILD_INTERVAL_DEFAULT)
, m_sequencingManager()
diff --git a/tests/test-lsa-segment-storage.cpp b/tests/test-lsa-segment-storage.cpp
index de0ee13..e690ae8 100644
--- a/tests/test-lsa-segment-storage.cpp
+++ b/tests/test-lsa-segment-storage.cpp
@@ -27,6 +27,7 @@
#include "test-common.hpp"
#include "nlsr.hpp"
#include "name-prefix-list.hpp"
+#include "lsa.hpp"
#include <boost/test/unit_test.hpp>
@@ -41,18 +42,29 @@
, nlsr(m_ioService, m_scheduler, face, m_keyChain)
, lsdb(nlsr.getLsdb())
, lsaStorage(lsdb.getLsaStorage())
+ , lsaGeneratedBeforeNow(180)
{
}
- static shared_ptr<ndn::Data>
+ std::string
+ makeLsaContent()
+ {
+ ndn::Name s1{"name1"};
+ ndn::Name s2{"name2"};
+ NamePrefixList npl1{s1, s2};
+ NameLsa nameLsa("/ndn/other-site/%C1.Router/other-router", 12,
+ ndn::time::system_clock::now() - lsaGeneratedBeforeNow, npl1);
+ return nameLsa.serialize();
+ }
+
+ shared_ptr<ndn::Data>
makeLsaSegment(const ndn::Name& baseName, uint64_t segmentNo, bool isFinal)
{
- const uint8_t buffer[] = "Hello, world!";
-
ndn::Name lsaDataName(baseName);
lsaDataName.appendSegment(segmentNo);
auto lsaSegment = make_shared<ndn::Data>(ndn::Name(lsaDataName));
- lsaSegment->setContent(buffer, sizeof(buffer));
+ std::string content = makeLsaContent();
+ lsaSegment->setContent(reinterpret_cast<const uint8_t*>(content.c_str()), content.length());
if (isFinal) {
lsaSegment->setFinalBlockId(lsaSegment->getName()[-1]);
}
@@ -80,6 +92,7 @@
Nlsr nlsr;
Lsdb& lsdb;
LsaSegmentStorage& lsaStorage;
+ ndn::time::seconds lsaGeneratedBeforeNow;
};
BOOST_FIXTURE_TEST_SUITE(TestLsaSegmentStorage, LsaSegmentStorageFixture)
@@ -148,6 +161,24 @@
BOOST_CHECK_EQUAL(face.sentData.size(), 1);
}
+BOOST_AUTO_TEST_CASE(ScheduledDeletion)
+{
+ ndn::Name lsaInterestName("/ndn/NLSR/LSA/other-site/%C1.Router/other-router/NAME");
+ lsaInterestName.appendNumber(12);
+
+ ndn::Name lsaDataName(lsaInterestName);
+ lsaDataName.appendVersion();
+
+ auto lsaData = makeLsaSegment(lsaDataName, 0, true);
+ lsaStorage.afterFetcherSignalEmitted(*lsaData);
+
+ BOOST_CHECK(lsaStorage.getLsaSegment(ndn::Interest(lsaInterestName)) != nullptr);
+
+ advanceClocks(ndn::time::milliseconds(lsaGeneratedBeforeNow), 10);
+
+ BOOST_CHECK(lsaStorage.getLsaSegment(ndn::Interest(lsaInterestName)) == nullptr);
+}
+
BOOST_AUTO_TEST_SUITE_END() // TestLsaSegmentStorage
} // namespace test