lsdb: emit signals when modified

RoutingTable and NamePrefixTable consume the signal
and behave accordingly.

refs: #4127

Change-Id: I6540f30f0222f804b01dc7d9640831c84e5264cc
diff --git a/src/lsa/adj-lsa.cpp b/src/lsa/adj-lsa.cpp
index 781422c..3d49533 100644
--- a/src/lsa/adj-lsa.cpp
+++ b/src/lsa/adj-lsa.cpp
@@ -124,7 +124,7 @@
 AdjLsa::toString() const
 {
   std::ostringstream os;
-  os << Lsa::toString();
+  os << getString();
   os << "      Adjacent(s):\n";
 
   int adjacencyIndex = 0;
@@ -139,6 +139,20 @@
   return os.str();
 }
 
+std::tuple<bool, std::list<ndn::Name>, std::list<ndn::Name>>
+AdjLsa::update(const std::shared_ptr<Lsa>& lsa)
+{
+  auto alsa = std::static_pointer_cast<AdjLsa>(lsa);
+  if (!isEqualContent(*alsa)) {
+    resetAdl();
+    for (const auto& adjacent : alsa->getAdl()) {
+      addAdjacent(adjacent);
+    }
+    return std::make_tuple(true, std::list<ndn::Name>{}, std::list<ndn::Name>{});
+  }
+  return std::make_tuple(false, std::list<ndn::Name>{}, std::list<ndn::Name>{});
+}
+
 std::ostream&
 operator<<(std::ostream& os, const AdjLsa& lsa)
 {
diff --git a/src/lsa/adj-lsa.hpp b/src/lsa/adj-lsa.hpp
index 9857cc8..43562a6 100644
--- a/src/lsa/adj-lsa.hpp
+++ b/src/lsa/adj-lsa.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2020,  The University of Memphis,
+ * Copyright (c) 2014-2021,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -113,6 +113,9 @@
   std::string
   toString() const override;
 
+  std::tuple<bool, std::list<ndn::Name>, std::list<ndn::Name>>
+  update(const std::shared_ptr<Lsa>& lsa) override;
+
 private:
   uint32_t m_noLink;
 
diff --git a/src/lsa/coordinate-lsa.cpp b/src/lsa/coordinate-lsa.cpp
index 32172e6..f61fb29 100644
--- a/src/lsa/coordinate-lsa.cpp
+++ b/src/lsa/coordinate-lsa.cpp
@@ -144,7 +144,7 @@
 CoordinateLsa::toString() const
 {
   std::ostringstream os;
-  os << Lsa::toString();
+  os << getString();
   os << "      Hyperbolic Radius  : " << m_hyperbolicRadius << "\n";
   int i = 0;
   for (const auto& value : m_hyperbolicAngles) {
@@ -154,6 +154,21 @@
   return os.str();
 }
 
+std::tuple<bool, std::list<ndn::Name>, std::list<ndn::Name>>
+CoordinateLsa::update(const std::shared_ptr<Lsa>& lsa)
+{
+  auto clsa = std::static_pointer_cast<CoordinateLsa>(lsa);
+  if (!isEqualContent(*clsa)) {
+    m_hyperbolicRadius = clsa->getCorRadius();
+    m_hyperbolicAngles.clear();
+    for (const auto& angle : clsa->getCorTheta()) {
+      m_hyperbolicAngles.push_back(angle);
+    }
+    return std::make_tuple(true, std::list<ndn::Name>{}, std::list<ndn::Name>{});
+  }
+  return std::make_tuple(false, std::list<ndn::Name>{}, std::list<ndn::Name>{});
+}
+
 std::ostream&
 operator<<(std::ostream& os, const CoordinateLsa& lsa)
 {
diff --git a/src/lsa/coordinate-lsa.hpp b/src/lsa/coordinate-lsa.hpp
index 4b07627..c1d3a13 100644
--- a/src/lsa/coordinate-lsa.hpp
+++ b/src/lsa/coordinate-lsa.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2020,  The University of Memphis,
+ * Copyright (c) 2014-2021,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -98,6 +98,9 @@
   std::string
   toString() const override;
 
+  std::tuple<bool, std::list<ndn::Name>, std::list<ndn::Name>>
+  update(const std::shared_ptr<Lsa>& lsa) override;
+
 private:
   double m_hyperbolicRadius = 0.0;
   std::vector<double> m_hyperbolicAngles;
diff --git a/src/lsa/lsa.cpp b/src/lsa/lsa.cpp
index 25841d2..c633549 100644
--- a/src/lsa/lsa.cpp
+++ b/src/lsa/lsa.cpp
@@ -35,6 +35,13 @@
 {
 }
 
+Lsa::Lsa(const Lsa& lsa)
+  : m_originRouter(lsa.getOriginRouter())
+  , m_seqNo(lsa.getSeqNo())
+  , m_expirationTimePoint(lsa.getExpirationTimePoint())
+{
+}
+
 template<ndn::encoding::Tag TAG>
 size_t
 Lsa::wireEncode(ndn::EncodingImpl<TAG>& encoder) const
@@ -138,13 +145,13 @@
 }
 
 std::string
-Lsa::toString() const
+Lsa::getString() const
 {
   std::ostringstream os;
-  auto duration = getExpirationTimePoint() - ndn::time::system_clock::now();
+  auto duration = m_expirationTimePoint - ndn::time::system_clock::now();
   os << "    " << getType() << " LSA:\n"
-     << "      Origin Router      : " << getOriginRouter() << "\n"
-     << "      Sequence Number    : " << getSeqNo() << "\n"
+     << "      Origin Router      : " << m_originRouter << "\n"
+     << "      Sequence Number    : " << m_seqNo << "\n"
      << "      Expires in         : " << ndn::time::duration_cast<ndn::time::milliseconds>(duration)
      << "\n";
   return os.str();
diff --git a/src/lsa/lsa.hpp b/src/lsa/lsa.hpp
index 7fb1058..89ddb85 100644
--- a/src/lsa/lsa.hpp
+++ b/src/lsa/lsa.hpp
@@ -60,6 +60,8 @@
 
   Lsa() = default;
 
+  Lsa(const Lsa& lsa);
+
 public:
   virtual
   ~Lsa() = default;
@@ -108,19 +110,16 @@
   void
   setExpiringEventId(ndn::scheduler::EventId eid)
   {
-    m_expiringEventId = std::move(eid);
+    m_expiringEventId = eid;
   }
 
-  ndn::scheduler::EventId
-  getExpiringEventId() const
-  {
-    return m_expiringEventId;
-  }
-
-  /*! Get data common to all LSA types.
+  /*! Get data common to all LSA types for printing purposes.
    */
   virtual std::string
-  toString() const;
+  toString() const = 0;
+
+  virtual std::tuple<bool, std::list<ndn::Name>, std::list<ndn::Name>>
+  update(const std::shared_ptr<Lsa>& lsa) = 0;
 
   virtual const ndn::Block&
   wireEncode() const = 0;
@@ -133,11 +132,14 @@
   void
   wireDecode(const ndn::Block& wire);
 
+  std::string
+  getString() const;
+
 PUBLIC_WITH_TESTS_ELSE_PROTECTED:
   ndn::Name m_originRouter;
   uint64_t m_seqNo = 0;
   ndn::time::system_clock::TimePoint m_expirationTimePoint;
-  ndn::scheduler::EventId m_expiringEventId;
+  ndn::scheduler::ScopedEventId m_expiringEventId;
 
   mutable ndn::Block m_wire;
 };
diff --git a/src/lsa/name-lsa.cpp b/src/lsa/name-lsa.cpp
index 173b9c7..266649a 100644
--- a/src/lsa/name-lsa.cpp
+++ b/src/lsa/name-lsa.cpp
@@ -122,7 +122,7 @@
 NameLsa::toString() const
 {
   std::ostringstream os;
-  os << Lsa::toString();
+  os << getString();
   os << "      Names:\n";
   int i = 0;
   for (const auto& name : m_npl.getNames()) {
@@ -132,6 +132,38 @@
   return os.str();
 }
 
+std::tuple<bool, std::list<ndn::Name>, std::list<ndn::Name>>
+NameLsa::update(const std::shared_ptr<Lsa>& lsa)
+{
+  auto nlsa = std::static_pointer_cast<NameLsa>(lsa);
+  bool updated = false;
+
+  // Obtain the set difference of the current and the incoming
+  // name prefix sets, and add those.
+  std::list<ndn::Name> newNames = nlsa->getNpl().getNames();
+  std::list<ndn::Name> oldNames = m_npl.getNames();
+  std::list<ndn::Name> namesToAdd;
+  std::set_difference(newNames.begin(), newNames.end(), oldNames.begin(), oldNames.end(),
+                      std::inserter(namesToAdd, namesToAdd.begin()));
+  for (const auto& name : namesToAdd) {
+    addName(name);
+    updated = true;
+  }
+
+  m_npl.sort();
+
+  // Also remove any names that are no longer being advertised.
+  std::list<ndn::Name> namesToRemove;
+  std::set_difference(oldNames.begin(), oldNames.end(), newNames.begin(), newNames.end(),
+                      std::inserter(namesToRemove, namesToRemove.begin()));
+  for (const auto& name : namesToRemove) {
+    removeName(name);
+    updated = true;
+  }
+
+  return std::make_tuple(updated, namesToAdd, namesToRemove);
+}
+
 std::ostream&
 operator<<(std::ostream& os, const NameLsa& lsa)
 {
diff --git a/src/lsa/name-lsa.hpp b/src/lsa/name-lsa.hpp
index 5e9c8d5..5d6e02b 100644
--- a/src/lsa/name-lsa.hpp
+++ b/src/lsa/name-lsa.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2020,  The University of Memphis,
+ * Copyright (c) 2014-2021,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -97,6 +97,9 @@
   std::string
   toString() const override;
 
+  std::tuple<bool, std::list<ndn::Name>, std::list<ndn::Name>>
+  update(const std::shared_ptr<Lsa>& lsa) override;
+
 private:
   NamePrefixList m_npl;
 };