fw: NccStrategy

refs #1242

Change-Id: I21f870728b7b361547adbde9d64357c93aeb1ed9
diff --git a/daemon/table/fib-entry.cpp b/daemon/table/fib-entry.cpp
index 61b9827..733782b 100644
--- a/daemon/table/fib-entry.cpp
+++ b/daemon/table/fib-entry.cpp
@@ -20,6 +20,14 @@
   return nexthop.getFace() == face;
 }
 
+bool
+Entry::hasNextHop(shared_ptr<Face> face) const
+{
+  NextHopList::const_iterator it = std::find_if(m_nextHops.begin(), m_nextHops.end(),
+    bind(&predicate_NextHop_eq_Face, _1, face));
+  return it != m_nextHops.end();
+}
+
 void
 Entry::addNextHop(shared_ptr<Face> face, int32_t cost)
 {
diff --git a/daemon/table/fib-entry.hpp b/daemon/table/fib-entry.hpp
index 6adddd8..f5c0fae 100644
--- a/daemon/table/fib-entry.hpp
+++ b/daemon/table/fib-entry.hpp
@@ -38,12 +38,12 @@
   const Name&
   getPrefix() const;
   
-  /** \brief gives the nexthops explicitly defined on this entry
-   *  This list does not include inherited nexthops.
-   */
   const NextHopList&
   getNextHops() const;
   
+  bool
+  hasNextHop(shared_ptr<Face> face) const;
+  
   /// adds a nexthop
   void
   addNextHop(shared_ptr<Face> face, int32_t cost);
diff --git a/daemon/table/measurements.cpp b/daemon/table/measurements.cpp
index ed01018..8caf343 100644
--- a/daemon/table/measurements.cpp
+++ b/daemon/table/measurements.cpp
@@ -19,6 +19,11 @@
 
 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>
diff --git a/daemon/table/pit-entry.cpp b/daemon/table/pit-entry.cpp
index 7a719df..2d016ca 100644
--- a/daemon/table/pit-entry.cpp
+++ b/daemon/table/pit-entry.cpp
@@ -33,6 +33,38 @@
   return m_outRecords;
 }
 
+static inline bool
+predicate_FaceRecord_Face(const FaceRecord& faceRecord, shared_ptr<Face> face)
+{
+  return faceRecord.getFace() == face;
+}
+
+static inline bool
+predicate_FaceRecord_ne_Face_and_unexpired(const FaceRecord& faceRecord,
+  shared_ptr<Face> face, time::Point now)
+{
+  return faceRecord.getFace() != face && faceRecord.getExpiry() >= now;
+}
+
+bool
+Entry::canForwardTo(shared_ptr<Face> face) const
+{
+  OutRecordCollection::const_iterator outIt = std::find_if(
+    m_outRecords.begin(), m_outRecords.end(),
+    bind(&predicate_FaceRecord_Face, _1, face));
+  bool hasUnexpiredOutRecord = outIt != m_outRecords.end() &&
+                               outIt->getExpiry() >= time::now();
+  if (hasUnexpiredOutRecord) {
+    return false;
+  }
+  
+  InRecordCollection::const_iterator inIt = std::find_if(
+    m_inRecords.begin(), m_inRecords.end(),
+    bind(&predicate_FaceRecord_ne_Face_and_unexpired, _1, face, time::now()));
+  bool hasUnexpiredOtherInRecord = inIt != m_inRecords.end();
+  return hasUnexpiredOtherInRecord;
+}
+
 bool
 Entry::addNonce(uint32_t nonce)
 {
@@ -42,12 +74,6 @@
   return insertResult.second;
 }
 
-static inline bool
-predicate_FaceRecord_Face(const FaceRecord& faceRecord, shared_ptr<Face> face)
-{
-  return faceRecord.getFace() == face;
-}
-
 InRecordCollection::iterator
 Entry::insertOrUpdateInRecord(shared_ptr<Face> face, const Interest& interest)
 {
diff --git a/daemon/table/pit-entry.hpp b/daemon/table/pit-entry.hpp
index 979af6c..c9cfdac 100644
--- a/daemon/table/pit-entry.hpp
+++ b/daemon/table/pit-entry.hpp
@@ -24,61 +24,68 @@
  */
 typedef std::list<OutRecord> OutRecordCollection;
 
-/** \class Entry
- *  \brief represents a PIT entry
+/** \brief represents a PIT entry
  */
 class Entry : public StrategyInfoHost, noncopyable
 {
 public:
   explicit
   Entry(const Interest& interest);
-  
+
   const Interest&
   getInterest() const;
-  
-  /** \return{ Interest Name }
+
+  /** \return Interest Name
    */
   const Name&
   getName() const;
-  
+
   const InRecordCollection&
   getInRecords() const;
-  
+
   const OutRecordCollection&
   getOutRecords() const;
-  
+
+  /** \brief decides whether Interest can be forwarded to face
+   *
+   *  \return true if OutRecord of this face does not exist or has expired,
+   *          and there is an InRecord not of this face
+   */
+  bool
+  canForwardTo(shared_ptr<Face> face) const;
+
   /** \brief records a nonce
    *
-   *  \return{ true if nonce is new; false if nonce is seen before }
+   *  \return true if nonce is new; false if nonce is seen before
    */
   bool
   addNonce(uint32_t nonce);
-  
+
   /** \brief inserts a InRecord for face, and updates it with interest
    *
    *  If InRecord for face exists, the existing one is updated.
    *  This method does not add the Nonce as a seen Nonce.
-   *  \return{ an iterator to the InRecord }
+   *  \return an iterator to the InRecord
    */
   InRecordCollection::iterator
   insertOrUpdateInRecord(shared_ptr<Face> face, const Interest& interest);
-  
+
   /// deletes all InRecords
   void
   deleteInRecords();
-  
+
   /** \brief inserts a OutRecord for face, and updates it with interest
    *
    *  If OutRecord for face exists, the existing one is updated.
-   *  \return{ an iterator to the OutRecord }
+   *  \return an iterator to the OutRecord
    */
   OutRecordCollection::iterator
   insertOrUpdateOutRecord(shared_ptr<Face> face, const Interest& interest);
-  
+
   /// deletes one OutRecord for face if exists
   void
   deleteOutRecord(shared_ptr<Face> face);
-  
+
 public:
   EventId m_unsatisfyTimer;
   EventId m_stragglerTimer;
diff --git a/daemon/table/strategy-info-host.hpp b/daemon/table/strategy-info-host.hpp
index 41199b2..272177f 100644
--- a/daemon/table/strategy-info-host.hpp
+++ b/daemon/table/strategy-info-host.hpp
@@ -25,6 +25,14 @@
   shared_ptr<T>
   getStrategyInfo();
   
+  template<typename T>
+  shared_ptr<T>
+  getOrCreateStrategyInfo();
+  
+  template<typename T, typename T1>
+  shared_ptr<T>
+  getOrCreateStrategyInfo(T1& a1);
+  
   void
   clearStrategyInfo();
 
@@ -47,6 +55,30 @@
   return static_pointer_cast<T, fw::StrategyInfo>(m_strategyInfo);
 }
 
+template<typename T>
+shared_ptr<T>
+StrategyInfoHost::getOrCreateStrategyInfo()
+{
+  shared_ptr<T> info = this->getStrategyInfo<T>();
+  if (!static_cast<bool>(info)) {
+    info = make_shared<T>();
+    this->setStrategyInfo(info);
+  }
+  return info;
+}
+
+template<typename T, typename T1>
+shared_ptr<T>
+StrategyInfoHost::getOrCreateStrategyInfo(T1& a1)
+{
+  shared_ptr<T> info = this->getStrategyInfo<T>();
+  if (!static_cast<bool>(info)) {
+    info = make_shared<T>(boost::ref(a1));
+    this->setStrategyInfo(info);
+  }
+  return info;
+}
+
 } // namespace nfd
 
 #endif // NFD_TABLE_STRATEGY_INFO_HOST_HPP