rib-manager: deleting expired entries from the rib and fib.

refs #1326
Change-Id: I865bff19da766560f920b1818bdf3eaa91e7dbb1
diff --git a/rib/face-entry.hpp b/rib/face-entry.hpp
index bd3f1f9..c9eeb33 100644
--- a/rib/face-entry.hpp
+++ b/rib/face-entry.hpp
@@ -27,6 +27,7 @@
 #define NFD_RIB_FACE_ENTRY_HPP
 
 #include "common.hpp"
+#include "core/scheduler.hpp"
 
 namespace nfd {
 namespace rib {
@@ -43,15 +44,32 @@
     , flags(0)
     , cost(0)
     , expires(time::steady_clock::TimePoint::min())
+    , m_expirationEvent()
   {
   }
 
 public:
+  void
+  setExpirationEvent(const EventId eid)
+  {
+    m_expirationEvent = eid;
+  }
+
+  const EventId&
+  getExpirationEvent() const
+  {
+    return m_expirationEvent;
+  }
+
+public:
   uint64_t faceId;
   uint64_t origin;
   uint64_t flags;
   uint64_t cost;
   time::steady_clock::TimePoint expires;
+
+private:
+  EventId m_expirationEvent;
 };
 
 inline bool
diff --git a/rib/rib-entry.cpp b/rib/rib-entry.cpp
index 98c3b90..5043233 100644
--- a/rib/rib-entry.cpp
+++ b/rib/rib-entry.cpp
@@ -69,6 +69,9 @@
           m_nFacesWithCaptureSet--;
         }
 
+      //cancel any scheduled event
+      scheduler::cancel(it->getExpirationEvent());
+
       m_faces.erase(it);
       return true;
     }
@@ -229,12 +232,17 @@
 operator<<(std::ostream& os, const FaceEntry& entry)
 {
   os << "FaceEntry("
-     << " faceid: " << entry.faceId
-     << " origin: " << entry.origin
-     << " cost: " << entry.cost
-     << " flags: " << entry.flags
-     << " expires in: " << (entry.expires - time::steady_clock::now())
-     << ")";
+     << "faceid: " << entry.faceId
+     << ", origin: " << entry.origin
+     << ", cost: " << entry.cost
+     << ", flags: " << entry.flags;
+  if (entry.expires != time::steady_clock::TimePoint::max()) {
+    os << ", expires in: " << (entry.expires - time::steady_clock::now());
+  }
+  else {
+    os << ", never expires";
+  }
+  os << ")";
 
   return os;
 }
@@ -242,8 +250,8 @@
 std::ostream&
 operator<<(std::ostream& os, const RibEntry& entry)
 {
-  os << "RibEntry{\n";
-  os << "\tName:  " << entry.getName() << "\n";
+  os << "RibEntry {\n";
+  os << "\tName: " << entry.getName() << "\n";
 
   for (RibEntry::FaceList::const_iterator faceIt = entry.cbegin(); faceIt != entry.cend(); ++faceIt)
     {
diff --git a/rib/rib-manager.cpp b/rib/rib-manager.cpp
index d04737c..c5f8666 100644
--- a/rib/rib-manager.cpp
+++ b/rib/rib-manager.cpp
@@ -186,7 +186,8 @@
       if (!extractParameters(parameterComponent, parameters))
         {
           NFD_LOG_DEBUG("command result: malformed verb: " << verb);
-          sendResponse(command, 400, "Malformed command");
+          if (static_cast<bool>(request))
+            sendResponse(command, 400, "Malformed command");
           return;
         }
 
@@ -201,7 +202,8 @@
   else
     {
       NFD_LOG_DEBUG("Unsupported command: " << verb);
-      sendResponse(request->getName(), 501, "Unsupported command");
+      if (static_cast<bool>(request))
+        sendResponse(request->getName(), 501, "Unsupported command");
     }
 }
 
@@ -214,7 +216,8 @@
   if (!validateParameters(command, parameters))
     {
       NFD_LOG_DEBUG("register result: FAIL reason: malformed");
-      sendResponse(request->getName(), 400, "Malformed command");
+      if (static_cast<bool>(request))
+        sendResponse(request->getName(), 400, "Malformed command");
       return;
     }
 
@@ -223,7 +226,25 @@
   faceEntry.origin = parameters.getOrigin();
   faceEntry.cost = parameters.getCost();
   faceEntry.flags = parameters.getFlags();
-  faceEntry.expires = time::steady_clock::now() + parameters.getExpirationPeriod();
+
+  if (parameters.getExpirationPeriod() != time::milliseconds::max())
+    {
+      faceEntry.expires = time::steady_clock::now() + parameters.getExpirationPeriod();
+
+      // Schedule a new event, the old one will be cancelled during rib insertion.
+      EventId eventId;
+      NFD_LOG_TRACE("scheduling unregistration at: " << faceEntry.expires);
+      eventId = scheduler::schedule(parameters.getExpirationPeriod(),
+                                    bind(&RibManager::unregisterEntry,
+                                    this, shared_ptr<Interest>(), parameters));
+
+      //set the  NewEventId of this entry
+      faceEntry.setExpirationEvent(eventId);
+    }
+  else
+    {
+      faceEntry.expires = time::steady_clock::TimePoint::max();
+    }
 
   NFD_LOG_TRACE("register prefix: " << faceEntry);
 
@@ -234,14 +255,22 @@
 
 void
 RibManager::unregisterEntry(const shared_ptr<const Interest>& request,
-                            ControlParameters& parameters)
+                            ControlParameters& params)
 {
   ndn::nfd::RibUnregisterCommand command;
 
+  //passing all parameters gives error in validation.
+  //so passing only the required arguments.
+  ControlParameters parameters;
+  parameters.setName(params.getName());
+  parameters.setFaceId(params.getFaceId());
+  parameters.setOrigin(params.getOrigin());
+
   if (!validateParameters(command, parameters))
     {
-      NFD_LOG_DEBUG("register result: FAIL reason: malformed");
-      sendResponse(request->getName(), 400, "Malformed command");
+      NFD_LOG_DEBUG("unregister result: FAIL reason: malformed");
+      if (static_cast<bool>(request))
+        sendResponse(request->getName(), 400, "Malformed command");
       return;
     }
 
@@ -261,7 +290,8 @@
                                       const std::string& failureInfo)
 {
   NFD_LOG_DEBUG("RibRequestValidationFailed: " << failureInfo);
-  sendResponse(request->getName(), 403, failureInfo);
+  if (static_cast<bool>(request))
+    sendResponse(request->getName(), 403, failureInfo);
 }
 
 
@@ -323,7 +353,8 @@
       response.setText(os.str());
     }
 
-  sendResponse(request->getName(), response);
+  if (static_cast<bool>(request))
+    sendResponse(request->getName(), response);
 }
 
 void
@@ -339,7 +370,8 @@
 
   NFD_LOG_TRACE("onRegSuccess: registered " << faceEntry);
 
-  sendResponse(request->getName(), response);
+  if (static_cast<bool>(request))
+    sendResponse(request->getName(), response);
 }
 
 
@@ -356,7 +388,8 @@
 
   NFD_LOG_TRACE("onUnRegSuccess: unregistered " << faceEntry);
 
-  sendResponse(request->getName(), response);
+  if (static_cast<bool>(request))
+    sendResponse(request->getName(), response);
 }
 
 void
@@ -374,7 +407,8 @@
   response.setText("Success");
   response.setBody(parameters.wireEncode());
 
-  sendResponse(request->getName(), response);
+  if (static_cast<bool>(request))
+    sendResponse(request->getName(), response);
 }
 
 void
@@ -403,7 +437,8 @@
       response.setText(os.str());
     }
 
-  sendResponse(request->getName(), response);
+  if (static_cast<bool>(request))
+    sendResponse(request->getName(), response);
 }
 
 void
diff --git a/rib/rib.cpp b/rib/rib.cpp
index c3fc399..9901b77 100644
--- a/rib/rib.cpp
+++ b/rib/rib.cpp
@@ -74,7 +74,7 @@
   return m_rib.find(prefix);
 }
 
-shared_ptr<FaceEntry>
+FaceEntry*
 Rib::find(const Name& prefix, const FaceEntry& face) const
 {
   RibTable::const_iterator ribIt = m_rib.find(prefix);
@@ -84,16 +84,15 @@
     {
       shared_ptr<RibEntry> entry(ribIt->second);
 
-      RibEntry::const_iterator faceIt = std::find_if(entry->begin(), entry->end(),
+      RibEntry::iterator faceIt = std::find_if(entry->begin(), entry->end(),
                                                      bind(&compareFaceIdAndOrigin, _1, face));
 
       if (faceIt != entry->end())
         {
-          return make_shared<FaceEntry>(*faceIt);
+          return &((*faceIt));
         }
     }
-
-  return shared_ptr<FaceEntry>();
+  return 0;
 }
 
 void
@@ -126,6 +125,13 @@
         }
       else // Entry exists, update fields
         {
+          // First cancel old scheduled event, if any, then set the EventId to new one
+          if (static_cast<bool>(faceIt->getExpirationEvent()))
+              scheduler::cancel(faceIt->getExpirationEvent());
+
+          // No checks are required here as the iterator needs to be updated in all cases.
+          faceIt->setExpirationEvent(face.getExpirationEvent());
+
           // Save flags for update processing
           uint64_t previousFlags = faceIt->flags;
 
@@ -171,7 +177,6 @@
                 {
                   parent->removeChild((*child));
                 }
-
               entry->addChild((*child));
             }
         }
@@ -183,7 +188,6 @@
     }
 }
 
-
 void
 Rib::erase(const Name& prefix, const FaceEntry& face)
 {
@@ -199,12 +203,13 @@
       // Need to copy face to do FIB updates with correct cost and flags since nfdc does not
       // pass flags or cost
       RibEntry::iterator faceIt = entry->findFace(face);
-      FaceEntry faceToErase = *faceIt;
-      faceToErase.flags = faceIt->flags;
-      faceToErase.cost = faceIt->cost;
 
       if (faceIt != entry->end())
         {
+          FaceEntry faceToErase = *faceIt;
+          faceToErase.flags = faceIt->flags;
+          faceToErase.cost = faceIt->cost;
+
           entry->eraseFace(faceIt);
           m_nItems--;
 
diff --git a/rib/rib.hpp b/rib/rib.hpp
index 89cad32..c555d21 100644
--- a/rib/rib.hpp
+++ b/rib/rib.hpp
@@ -55,7 +55,7 @@
   const_iterator
   find(const Name& prefix) const;
 
-  shared_ptr<FaceEntry>
+  FaceEntry*
   find(const Name& prefix, const FaceEntry& face) const;
 
   void
diff --git a/tests/rib/rib.cpp b/tests/rib/rib.cpp
index 2ee3070..faa1845 100644
--- a/tests/rib/rib.cpp
+++ b/tests/rib/rib.cpp
@@ -319,8 +319,8 @@
   rib.erase(name4, entry2);
   BOOST_CHECK_EQUAL(rib.size(), 2);
 
-  BOOST_CHECK(rib.find(name2, entry2) == shared_ptr<rib::FaceEntry>());
-  BOOST_CHECK(rib.find(name1, entry1) != shared_ptr<rib::FaceEntry>());
+  BOOST_CHECK_EQUAL(rib.find(name2, entry2), static_cast<FaceEntry*>(0));
+  BOOST_CHECK_NE(rib.find(name1, entry1), static_cast<FaceEntry*>(0));
 
   rib.erase(name1, entry1);
   BOOST_CHECK_EQUAL(rib.size(), 1);