nlsr: Add support for sources to NamePrefixList
Added support for string sources to NamePrefixList entries. Required was
some tweaking of the API, and refactoring usage around the codebase.
Change-Id: I44813e024a88dc1f591f427b0fad568a7d5353ab
refs: #4177
diff --git a/src/lsa.cpp b/src/lsa.cpp
index ad35a81..7ecad7a 100644
--- a/src/lsa.cpp
+++ b/src/lsa.cpp
@@ -19,6 +19,12 @@
* NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
**/
+#include "lsa.hpp"
+#include "nlsr.hpp"
+#include "name-prefix-list.hpp"
+#include "adjacent.hpp"
+#include "logger.hpp"
+
#include <string>
#include <iostream>
#include <sstream>
@@ -28,12 +34,6 @@
#include <boost/tokenizer.hpp>
#include <boost/algorithm/string.hpp>
-#include "nlsr.hpp"
-#include "lsa.hpp"
-#include "name-prefix-list.hpp"
-#include "adjacent.hpp"
-#include "logger.hpp"
-
namespace nlsr {
INIT_LOGGER("Lsa");
@@ -60,9 +60,8 @@
m_origRouter = origR;
m_lsSeqNo = lsn;
m_expirationTimePoint = lt;
- std::list<ndn::Name>& nl = npl.getNameList();
- for (std::list<ndn::Name>::iterator it = nl.begin(); it != nl.end(); it++) {
- addName((*it));
+ for (const auto& name : npl.getNames()) {
+ addName(name);
}
}
@@ -72,7 +71,7 @@
std::ostringstream os;
os << m_origRouter << "|" << NameLsa::TYPE_STRING << "|" << m_lsSeqNo << "|"
<< ndn::time::toIsoString(m_expirationTimePoint) << "|" << m_npl.getSize();
- for (const auto& name : m_npl.getNameList()) {
+ for (const auto& name : m_npl.getNames()) {
os << "|" << name;
}
os << "|";
@@ -127,7 +126,7 @@
_LOG_DEBUG(" Ls Lifetime: " << m_expirationTimePoint);
_LOG_DEBUG(" Names: ");
int i = 1;
- std::list<ndn::Name> nl = m_npl.getNameList();
+ std::list<ndn::Name> nl = m_npl.getNames();
for (std::list<ndn::Name>::iterator it = nl.begin(); it != nl.end(); it++)
{
_LOG_DEBUG(" Name " << i << ": " << (*it));
diff --git a/src/lsdb.cpp b/src/lsdb.cpp
index 99cd285..b71b48e 100644
--- a/src/lsdb.cpp
+++ b/src/lsdb.cpp
@@ -216,7 +216,7 @@
// prefixes to the NPT.
m_nlsr.getNamePrefixTable().addEntry(nlsa.getOrigRouter(),
nlsa.getOrigRouter());
- std::list<ndn::Name> nameList = nlsa.getNpl().getNameList();
+ std::list<ndn::Name> nameList = nlsa.getNpl().getNames();
for (std::list<ndn::Name>::iterator it = nameList.begin(); it != nameList.end();
it++) {
if ((*it) != m_nlsr.getConfParameter().getRouterPrefix()) {
@@ -245,14 +245,13 @@
nlsa.getNpl().sort();
// Obtain the set difference of the current and the incoming
// name prefix sets, and add those.
- std::list<ndn::Name> nameToAdd;
- std::set_difference(nlsa.getNpl().getNameList().begin(),
- nlsa.getNpl().getNameList().end(),
- chkNameLsa->getNpl().getNameList().begin(),
- chkNameLsa->getNpl().getNameList().end(),
- std::inserter(nameToAdd, nameToAdd.begin()));
- for (std::list<ndn::Name>::iterator it = nameToAdd.begin();
- it != nameToAdd.end(); ++it) {
+ std::list<ndn::Name> newNames = nlsa.getNpl().getNames();
+ std::list<ndn::Name> oldNames = chkNameLsa->getNpl().getNames();
+ std::list<ndn::Name> namesToAdd;
+ std::set_difference(newNames.begin(), newNames.end(), oldNames.begin(), oldNames.end(),
+ std::inserter(namesToAdd, namesToAdd.begin()));
+ for (std::list<ndn::Name>::iterator it = namesToAdd.begin();
+ it != namesToAdd.end(); ++it) {
chkNameLsa->addName((*it));
if (nlsa.getOrigRouter() != m_nlsr.getConfParameter().getRouterPrefix()) {
if ((*it) != m_nlsr.getConfParameter().getRouterPrefix()) {
@@ -264,14 +263,11 @@
chkNameLsa->getNpl().sort();
// Also remove any names that are no longer being advertised.
- std::list<ndn::Name> nameToRemove;
- std::set_difference(chkNameLsa->getNpl().getNameList().begin(),
- chkNameLsa->getNpl().getNameList().end(),
- nlsa.getNpl().getNameList().begin(),
- nlsa.getNpl().getNameList().end(),
- std::inserter(nameToRemove, nameToRemove.begin()));
- for (std::list<ndn::Name>::iterator it = nameToRemove.begin();
- it != nameToRemove.end(); ++it) {
+ std::list<ndn::Name> namesToRemove;
+ std::set_difference(oldNames.begin(), oldNames.end(), newNames.begin(), newNames.end(),
+ std::inserter(namesToRemove, namesToRemove.begin()));
+ for (std::list<ndn::Name>::iterator it = namesToRemove.begin();
+ it != namesToRemove.end(); ++it) {
_LOG_DEBUG("Removing name LSA no longer advertised: " << (*it).toUri());
chkNameLsa->removeName((*it));
if (nlsa.getOrigRouter() != m_nlsr.getConfParameter().getRouterPrefix()) {
@@ -326,10 +322,9 @@
m_nlsr.getConfParameter().getRouterPrefix()) {
m_nlsr.getNamePrefixTable().removeEntry((*it).getOrigRouter(),
(*it).getOrigRouter());
- for (std::list<ndn::Name>::iterator nit = (*it).getNpl().getNameList().begin();
- nit != (*it).getNpl().getNameList().end(); ++nit) {
- if ((*nit) != m_nlsr.getConfParameter().getRouterPrefix()) {
- m_nlsr.getNamePrefixTable().removeEntry((*nit), (*it).getOrigRouter());
+ for (const auto& name : it->getNpl().getNames()) {
+ if (name != m_nlsr.getConfParameter().getRouterPrefix()) {
+ m_nlsr.getNamePrefixTable().removeEntry(name, it->getOrigRouter());
}
}
}
diff --git a/src/name-prefix-list.cpp b/src/name-prefix-list.cpp
index 0bbcbaa..742367b 100644
--- a/src/name-prefix-list.cpp
+++ b/src/name-prefix-list.cpp
@@ -19,15 +19,16 @@
* NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
**/
+#include "name-prefix-list.hpp"
+
+#include "common.hpp"
+#include "logger.hpp"
+
#include <iostream>
#include <algorithm>
#include <ndn-cxx/common.hpp>
-#include "common.hpp"
-#include "name-prefix-list.hpp"
-#include "logger.hpp"
-
namespace nlsr {
INIT_LOGGER("NamePrefixList");
@@ -42,58 +43,115 @@
{
}
-static bool
-nameCompare(const ndn::Name& name1, const ndn::Name& name2)
+std::vector<NamePrefixList::NamePair>::iterator
+NamePrefixList::get(const ndn::Name& name)
{
- return name1 == name2;
+ return std::find_if(m_names.begin(), m_names.end(),
+ [&] (const NamePrefixList::NamePair& pair) {
+ return name == std::get<NamePrefixList::NamePairIndex::NAME>(pair);
+ });
+}
+
+std::vector<std::string>::iterator
+NamePrefixList::getSource(const std::string& source, std::vector<NamePair>::iterator& entry)
+{
+ return std::find_if(std::get<NamePairIndex::SOURCES>(*entry).begin(),
+ std::get<NamePairIndex::SOURCES>(*entry).end(),
+ [&] (const std::string& containerSource) {
+ return source == containerSource;
+ });
}
bool
-NamePrefixList::insert(const ndn::Name& name)
+NamePrefixList::insert(const ndn::Name& name, const std::string& source)
{
- std::list<ndn::Name>::iterator it = std::find_if(m_nameList.begin(),
- m_nameList.end(),
- std::bind(&nameCompare, _1 ,
- std::cref(name)));
- if (it != m_nameList.end()) {
- return false;
- }
- m_nameList.push_back(name);
- return true;
-}
-
-bool
-NamePrefixList::remove(const ndn::Name& name)
-{
- std::list<ndn::Name>::iterator it = std::find_if(m_nameList.begin(),
- m_nameList.end(),
- std::bind(&nameCompare, _1 ,
- std::cref(name)));
- if (it != m_nameList.end()) {
- m_nameList.erase(it);
+ auto pairItr = get(name);
+ if (pairItr == m_names.end()) {
+ std::vector<std::string> sources{source};
+ m_names.push_back(std::tie(name, sources));
return true;
}
+ else {
+ std::vector<std::string>& sources = std::get<NamePrefixList::NamePairIndex::SOURCES>(*pairItr);
+ auto sourceItr = getSource(source, pairItr);
+ if (sourceItr == sources.end()) {
+ sources.push_back(source);
+ return true;
+ }
+ }
+ return false;
+}
+bool
+NamePrefixList::remove(const ndn::Name& name, const std::string& source)
+{
+ auto pairItr = get(name);
+ if (pairItr != m_names.end()) {
+ std::vector<std::string>& sources = std::get<NamePrefixList::NamePairIndex::SOURCES>(*pairItr);
+ auto sourceItr = getSource(source, pairItr);
+ if (sourceItr != sources.end()) {
+ sources.erase(sourceItr);
+ if (sources.size() == 0) {
+ m_names.erase(pairItr);
+ }
+ return true;
+ }
+ }
return false;
}
bool
NamePrefixList::operator==(const NamePrefixList& other) const
{
- return m_nameList == other.getNameList();
+ return m_names == other.m_names;
}
void
NamePrefixList::sort()
{
- m_nameList.sort();
+ std::sort(m_names.begin(), m_names.end());
+}
+
+std::list<ndn::Name>
+NamePrefixList::getNames() const
+{
+ std::list<ndn::Name> names;
+ for (const auto& namePair : m_names) {
+ names.push_back(std::get<NamePrefixList::NamePairIndex::NAME>(namePair));
+ }
+ return names;
+}
+
+uint32_t
+NamePrefixList::countSources(const ndn::Name& name) const
+{
+ return getSources(name).size();
+}
+
+const std::vector<std::string>
+NamePrefixList::getSources(const ndn::Name& name) const
+{
+ auto it = std::find_if(m_names.begin(), m_names.end(),
+ [&] (const NamePrefixList::NamePair& pair) {
+ return name == std::get<NamePrefixList::NamePairIndex::NAME>(pair);
+ });
+ if (it != m_names.end()) {
+ return std::get<NamePrefixList::NamePairIndex::SOURCES>(*it);
+ }
+ else {
+ return std::vector<std::string>{};
+ }
}
std::ostream&
operator<<(std::ostream& os, const NamePrefixList& list) {
os << "Name prefix list: {\n";
- for (const auto& name : list.getNameList()) {
- os << name << "\n";
+ for (const auto& name : list.getNames()) {
+ os << name << "\n"
+ << "Sources:\n";
+ for (const auto& source : list.getSources(name)) {
+ os << " " << source << "\n";
+ }
}
os << "}" << std::endl;
return os;
diff --git a/src/name-prefix-list.hpp b/src/name-prefix-list.hpp
index cba76d3..5ec94ef 100644
--- a/src/name-prefix-list.hpp
+++ b/src/name-prefix-list.hpp
@@ -31,8 +31,13 @@
namespace nlsr {
class NamePrefixList
{
-
public:
+ using NamePair = std::tuple<ndn::Name, std::vector<std::string>>;
+ enum NamePairIndex {
+ NAME,
+ SOURCES
+ };
+
NamePrefixList();
~NamePrefixList();
@@ -42,14 +47,14 @@
\retval false If the name could not be inserted.
*/
bool
- insert(const ndn::Name& name);
+ insert(const ndn::Name& name, const std::string& source = "");
/*! \brief removes name from NamePrefixList
\retval true If the name is removed
\retval false If the name failed to be removed.
*/
bool
- remove(const ndn::Name& name);
+ remove(const ndn::Name& name, const std::string& source = "");
void
sort();
@@ -57,27 +62,45 @@
size_t
getSize()
{
- return m_nameList.size();
+ return m_names.size();
}
- std::list<ndn::Name>&
- getNameList()
- {
- return m_nameList;
- }
-
- const std::list<ndn::Name>&
- getNameList() const
- {
- return m_nameList;
- }
+ std::list<ndn::Name>
+ getNames() const;
bool
operator==(const NamePrefixList& other) const;
-private:
- std::list<ndn::Name> m_nameList;
+ /*! Returns how many unique sources this name has.
+ \retval 0 if the name is not in the list, else the number of sources.
+ */
+ uint32_t
+ countSources(const ndn::Name& name) const;
+
+ /*! Returns the sources that this name has.
+
+ \retval an empty vector if the name is not in the list, else a
+ vector containing the sources.
+ */
+ const std::vector<std::string>
+ getSources(const ndn::Name& name) const;
+
+private:
+ /*! Obtain an iterator to the entry matching name.
+
+ \note We could do this quite easily inline with a lambda, but this
+ is slightly more efficient.
+ */
+ std::vector<NamePair>::iterator
+ get(const ndn::Name& name);
+
+ /*! Obtain an iterator to a specific source in an entry
+ */
+ std::vector<std::string>::iterator
+ getSource(const std::string& source, std::vector<NamePair>::iterator& entry);
+
+ std::vector<NamePair> m_names;
};
std::ostream&
diff --git a/src/publisher/lsa-publisher.cpp b/src/publisher/lsa-publisher.cpp
index a46ef60..6bfc1dc 100644
--- a/src/publisher/lsa-publisher.cpp
+++ b/src/publisher/lsa-publisher.cpp
@@ -124,7 +124,7 @@
std::shared_ptr<tlv::LsaInfo> tlvLsaInfo = tlv::makeLsaInfo(lsa);
tlvLsa.setLsaInfo(*tlvLsaInfo);
- for (const ndn::Name& name : lsa.getNpl().getNameList()) {
+ for (const ndn::Name& name : lsa.getNpl().getNames()) {
tlvLsa.addName(name);
}
diff --git a/src/publisher/lsdb-dataset-interest-handler.cpp b/src/publisher/lsdb-dataset-interest-handler.cpp
index acd5c92..30634ac 100644
--- a/src/publisher/lsdb-dataset-interest-handler.cpp
+++ b/src/publisher/lsdb-dataset-interest-handler.cpp
@@ -133,7 +133,7 @@
std::shared_ptr<tlv::LsaInfo> tlvLsaInfo = tlv::makeLsaInfo(lsa);
tlvLsa.setLsaInfo(*tlvLsaInfo);
- for (const ndn::Name& name : lsa.getNpl().getNameList()) {
+ for (const ndn::Name& name : lsa.getNpl().getNames()) {
tlvLsa.addName(name);
}