table: Measurements on NameTree

Change-Id: I17bab4a7a085c529b04b35b7fe47e02dd9d6ff00
refs #1200
refs #1201
diff --git a/daemon/fw/forwarder.cpp b/daemon/fw/forwarder.cpp
index ce22c22..417a4cb 100644
--- a/daemon/fw/forwarder.cpp
+++ b/daemon/fw/forwarder.cpp
@@ -19,6 +19,7 @@
   , m_nameTree(1024) // "1024" could be made as one configurable parameter of the forwarder.
   , m_fib(m_nameTree)
   , m_pit(m_nameTree)
+  , m_measurements(m_nameTree)
 {
   m_strategy = make_shared<fw::BestRouteStrategy>(boost::ref(*this));
 }
diff --git a/daemon/table/measurements.cpp b/daemon/table/measurements.cpp
index 8caf343..e361aba 100644
--- a/daemon/table/measurements.cpp
+++ b/daemon/table/measurements.cpp
@@ -5,40 +5,34 @@
  */
 
 #include "measurements.hpp"
-#include <algorithm>
-#include "fib-entry.hpp"
+#include "name-tree.hpp"
 #include "pit-entry.hpp"
+#include "fib-entry.hpp"
 
 namespace nfd {
 
 const time::Duration Measurements::s_defaultLifetime = time::seconds(4);
 
-Measurements::Measurements()
+Measurements::Measurements(NameTree& nameTree)
+  : m_nameTree(nameTree)
+  , m_nItems(0)
 {
 }
 
 Measurements::~Measurements()
 {
-  for (std::map<Name, shared_ptr<measurements::Entry> >::iterator it = m_table.begin();
-       it != m_table.end(); ++it) {
-    shared_ptr<measurements::Entry> entry = it->second;
-    scheduler::cancel(entry->m_cleanup);
-  }
 }
 
 shared_ptr<measurements::Entry>
 Measurements::get(const Name& name)
 {
-  std::map<Name, shared_ptr<measurements::Entry> >::iterator it = m_table.find(name);
-  if (it != m_table.end()) {
-    return it->second;
-  }
-
-  shared_ptr<measurements::Entry> entry = make_shared<measurements::Entry>(name);
-  std::pair<std::map<Name, shared_ptr<measurements::Entry> >::iterator, bool> pair =
-    m_table.insert(std::make_pair(name, entry));
-  this->extendLifetimeInternal(pair.first, s_defaultLifetime);
-
+  shared_ptr<name_tree::Entry> nameTreeEntry = m_nameTree.lookup(name);
+  shared_ptr<measurements::Entry> entry = nameTreeEntry->getMeasurementsEntry();
+  if (static_cast<bool>(entry))
+    return entry;
+  entry = make_shared<measurements::Entry>(name);
+  nameTreeEntry->setMeasurementsEntry(entry);
+  m_nItems++;
   return entry;
 }
 
@@ -57,6 +51,8 @@
 shared_ptr<measurements::Entry>
 Measurements::getParent(shared_ptr<measurements::Entry> child)
 {
+  BOOST_ASSERT(child);
+
   if (child->getName().size() == 0) {
     return shared_ptr<measurements::Entry>();
   }
@@ -64,48 +60,57 @@
   return this->get(child->getName().getPrefix(-1));
 }
 
-//shared_ptr<fib::Entry>
-//Measurements::findLongestPrefixMatch(const Name& name) const
-//{
-//}
-//
-//shared_ptr<fib::Entry>
-//Measurements::findExactMatch(const Name& name) const
-//{
-//}
-
-void
-Measurements::extendLifetime(measurements::Entry& entry, const time::Duration& lifetime)
+shared_ptr<measurements::Entry>
+Measurements::findLongestPrefixMatch(const Name& name) const
 {
-  std::map<Name, shared_ptr<measurements::Entry> >::iterator it =
-      m_table.find(entry.getName());
-  BOOST_ASSERT(it != m_table.end());
-
-  this->extendLifetimeInternal(it, lifetime);
-}
-
-void
-Measurements::extendLifetimeInternal(
-    std::map<Name, shared_ptr<measurements::Entry> >::iterator it,
-    const time::Duration& lifetime)
-{
-  shared_ptr<measurements::Entry>& entry = it->second;
-
-  time::Point expiry = time::now() + lifetime;
-  if (entry->m_expiry >= expiry) { // has longer lifetime, not extending
-    return;
+  shared_ptr<name_tree::Entry> nameTreeEntry = m_nameTree.findLongestPrefixMatch(name);
+  while (static_cast<bool>(nameTreeEntry))
+  {
+    if (static_cast<bool>(nameTreeEntry->getMeasurementsEntry()))
+      return nameTreeEntry->getMeasurementsEntry();
+    nameTreeEntry = nameTreeEntry->getParent();
   }
+  return shared_ptr<measurements::Entry>();
+}
 
-  scheduler::cancel(entry->m_cleanup);
-  entry->m_expiry = expiry;
-  entry->m_cleanup = scheduler::schedule(lifetime,
-                         bind(&Measurements::cleanup, this, it));
+shared_ptr<measurements::Entry>
+Measurements::findExactMatch(const Name& name) const
+{
+  shared_ptr<name_tree::Entry> nameTreeEntry = m_nameTree.lookup(name);
+  if (static_cast<bool>(nameTreeEntry))
+    return nameTreeEntry->getMeasurementsEntry();
+  return shared_ptr<measurements::Entry>();
 }
 
 void
-Measurements::cleanup(std::map<Name, shared_ptr<measurements::Entry> >::iterator it)
+Measurements::extendLifetime(measurements::Entry& entry, const time::Duration lifetime)
 {
-  m_table.erase(it);
+  shared_ptr<measurements::Entry> ret = this->findExactMatch(entry.getName());
+  if (static_cast<bool>(ret))
+  {
+    time::Point expiry = time::now() + lifetime;
+    if (ret->m_expiry >= expiry) // has longer lifetime, not extending
+      return;
+    scheduler::cancel(entry.m_cleanup);
+    entry.m_expiry = expiry;
+    entry.m_cleanup = scheduler::schedule(lifetime,
+                         bind(&Measurements::cleanup, this, ret));
+  }
+}
+
+void
+Measurements::cleanup(shared_ptr<measurements::Entry> entry)
+{
+  BOOST_ASSERT(entry);
+
+  shared_ptr<name_tree::Entry> nameTreeEntry = m_nameTree.findExactMatch(entry->getName());
+  if (static_cast<bool>(nameTreeEntry))
+  {
+    nameTreeEntry->eraseMeasurementsEntry(
+      nameTreeEntry->getMeasurementsEntry());
+    m_nItems--;
+  }
+    
 }
 
 } // namespace nfd
diff --git a/daemon/table/measurements.hpp b/daemon/table/measurements.hpp
index 4c6d946..794f4a6 100644
--- a/daemon/table/measurements.hpp
+++ b/daemon/table/measurements.hpp
@@ -8,19 +8,28 @@
 #define NFD_TABLE_MEASUREMENTS_HPP
 
 #include "measurements-entry.hpp"
-#include "fib-entry.hpp"
-#include "pit-entry.hpp"
 #include "core/time.hpp"
+#include "name-tree.hpp"
 
 namespace nfd {
 
+namespace fib {
+class Entry;
+}
+
+namespace pit {
+class Entry;
+}
+
+
 /** \class Measurement
  *  \brief represents the Measurements table
  */
 class Measurements : noncopyable
 {
 public:
-  Measurements();
+  explicit
+  Measurements(NameTree& nametree);
 
   ~Measurements();
 
@@ -36,43 +45,47 @@
   shared_ptr<measurements::Entry>
   get(const pit::Entry& pitEntry);
 
-  /** \brief find or insert a Measurements entry for child's parent
+  /** find or insert a Measurements entry for child's parent
    *
    *  If child is the root entry, returns null.
    */
   shared_ptr<measurements::Entry>
   getParent(shared_ptr<measurements::Entry> child);
 
-//  /// perform a longest prefix match
-//  shared_ptr<fib::Entry>
-//  findLongestPrefixMatch(const Name& name) const;
-//
-//  /// perform an exact match
-//  shared_ptr<fib::Entry>
-//  findExactMatch(const Name& name) const;
+  /// perform a longest prefix match
+  shared_ptr<measurements::Entry>
+  findLongestPrefixMatch(const Name& name) const;
 
-  /** \brief extend lifetime of an entry
+  /// perform an exact match
+  shared_ptr<measurements::Entry>
+  findExactMatch(const Name& name) const;
+
+  /** extend lifetime of an entry
    *
    *  The entry will be kept until at least now()+lifetime.
    */
   void
-  extendLifetime(measurements::Entry& entry, const time::Duration& lifetime);
+  extendLifetime(measurements::Entry& entry, const time::Duration lifetime);
+
+  size_t
+  size() const;
 
 private:
   void
-  extendLifetimeInternal(
-    std::map<Name, shared_ptr<measurements::Entry> >::iterator it,
-    const time::Duration& lifetime);
-
-  void
-  cleanup(std::map<Name, shared_ptr<measurements::Entry> >::iterator it);
+  cleanup(shared_ptr<measurements::Entry> entry);
 
 private:
-  std::map<Name, shared_ptr<measurements::Entry> > m_table;
-
+  NameTree& m_nameTree;
+  size_t m_nItems;
   static const time::Duration s_defaultLifetime;
 };
 
+inline size_t
+Measurements::size() const
+{
+  return m_nItems;
+}
+
 } // namespace nfd
 
 #endif // NFD_TABLE_MEASUREMENTS_HPP