table: add Cs::erase method

This commit also corrects CS's description in Doxygen.

refs #4318

Change-Id: Ie8854a2e2b59a072b98603c0cc31768bb84ea6d2
diff --git a/daemon/table/cs-policy-priority-fifo.hpp b/daemon/table/cs-policy-priority-fifo.hpp
index 436afd9..4ac5a63 100644
--- a/daemon/table/cs-policy-priority-fifo.hpp
+++ b/daemon/table/cs-policy-priority-fifo.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2016,  Regents of the University of California,
+/*
+ * Copyright (c) 2014-2018,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -23,8 +23,8 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef NFD_DAEMON_TABLE_CS_POLICY_FIFO_HPP
-#define NFD_DAEMON_TABLE_CS_POLICY_FIFO_HPP
+#ifndef NFD_DAEMON_TABLE_CS_POLICY_PRIORITY_FIFO_HPP
+#define NFD_DAEMON_TABLE_CS_POLICY_PRIORITY_FIFO_HPP
 
 #include "cs-policy.hpp"
 #include "core/scheduler.hpp"
@@ -61,13 +61,17 @@
 
 typedef std::map<iterator, EntryInfo*, EntryItComparator> EntryInfoMapFifo;
 
-/** \brief Priority Fifo cs replacement policy
+/** \brief Priority FIFO replacement policy
  *
- * The entries that get removed first are unsolicited Data packets,
- * which are the Data packets that got cached opportunistically without preceding
- * forwarding of the corresponding Interest packet.
- * Next, the Data packets with expired freshness are removed.
- * Last, the Data packets are removed from the Content Store on a pure FIFO basis.
+ *  This policy maintains a set of cleanup queues to decide the eviction order of CS entries.
+ *  The cleanup queues are three doubly linked lists that store Table iterators.
+ *  The three queues keep track of unsolicited, stale, and fresh Data packet, respectively.
+ *  Table iterator is placed into, removed from, and moved between suitable queues
+ *  whenever an Entry is added, removed, or has other attribute changes.
+ *  The Table iterator of an Entry should be in exactly one queue at any moment.
+ *  Within each queue, the iterators are kept in first-in-first-out order.
+ *  Eviction procedure exhausts the first queue before moving onto the next queue,
+ *  in the order of unsolicited, stale, and fresh queue.
  */
 class PriorityFifoPolicy : public Policy
 {
@@ -81,19 +85,19 @@
   static const std::string POLICY_NAME;
 
 private:
-  virtual void
+  void
   doAfterInsert(iterator i) override;
 
-  virtual void
+  void
   doAfterRefresh(iterator i) override;
 
-  virtual void
+  void
   doBeforeErase(iterator i) override;
 
-  virtual void
+  void
   doBeforeUse(iterator i) override;
 
-  virtual void
+  void
   evictEntries() override;
 
 private:
@@ -132,4 +136,4 @@
 } // namespace cs
 } // namespace nfd
 
-#endif // NFD_DAEMON_TABLE_CS_POLICY_FIFO_HPP
+#endif // NFD_DAEMON_TABLE_CS_POLICY_PRIORITY_FIFO_HPP
diff --git a/daemon/table/cs.cpp b/daemon/table/cs.cpp
index 81b3fd6..54466ed 100644
--- a/daemon/table/cs.cpp
+++ b/daemon/table/cs.cpp
@@ -89,6 +89,29 @@
 }
 
 void
+Cs::erase(const Name& prefix, size_t limit, const AfterEraseCallback& cb)
+{
+  BOOST_ASSERT(static_cast<bool>(cb));
+
+  iterator first = m_table.lower_bound(prefix);
+  iterator last = m_table.end();
+  if (prefix.size() > 0) {
+    last = m_table.lower_bound(prefix.getSuccessor());
+  }
+
+  size_t nErased = 0;
+  while (first != last && nErased < limit) {
+    m_policy->beforeErase(first);
+    first = m_table.erase(first);
+    ++nErased;
+  }
+
+  if (cb) {
+    cb(nErased);
+  }
+}
+
+void
 Cs::find(const Interest& interest,
          const HitCallback& hitCallback,
          const MissCallback& missCallback) const
diff --git a/daemon/table/cs.hpp b/daemon/table/cs.hpp
index 5a60fef..fc161c5 100644
--- a/daemon/table/cs.hpp
+++ b/daemon/table/cs.hpp
@@ -23,28 +23,6 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-/** \file
- *
- *  \brief implements the ContentStore
- *
- *  This ContentStore implementation consists of two data structures,
- *  a Table, and a set of cleanup queues.
- *
- *  The Table is a container (std::set) sorted by full Names of stored Data packets.
- *  Data packets are wrapped in Entry objects.
- *  Each Entry contain the Data packet itself,
- *  and a few addition attributes such as the staleness of the Data packet.
- *
- *  The cleanup queues are three doubly linked lists which stores Table iterators.
- *  The three queues keep track of unsolicited, stale, and fresh Data packet, respectively.
- *  Table iterator is placed into, removed from, and moved between suitable queues
- *  whenever an Entry is added, removed, or has other attribute changes.
- *  The Table iterator of an Entry should be in exactly one queue at any moment.
- *  Within each queue, the iterators are kept in first-in-first-out order.
- *  Eviction procedure exhausts the first queue before moving onto the next queue,
- *  in the order of unsolicited, stale, and fresh queue.
- */
-
 #ifndef NFD_DAEMON_TABLE_CS_HPP
 #define NFD_DAEMON_TABLE_CS_HPP
 
@@ -57,7 +35,15 @@
 namespace nfd {
 namespace cs {
 
-/** \brief represents the ContentStore
+/** \brief implements the Content Store
+ *
+ *  This Content Store implementation consists of a Table and a replacement policy.
+ *
+ *  The Table is a container ( \c std::set ) sorted by full Names of stored Data packets.
+ *  Data packets are wrapped in Entry objects. Each Entry contains the Data packet itself,
+ *  and a few additional attributes such as when the Data becomes non-fresh.
+ *
+ *  The replacement policy is implemented in a subclass of \c Policy.
  */
 class Cs : noncopyable
 {
@@ -70,8 +56,19 @@
   void
   insert(const Data& data, bool isUnsolicited = false);
 
-  typedef std::function<void(const Interest&, const Data& data)> HitCallback;
-  typedef std::function<void(const Interest&)> MissCallback;
+  using AfterEraseCallback = std::function<void(size_t nErased)>;
+
+  /** \brief asynchronously erases entries under \p prefix
+   *  \param prefix name prefix of entries
+   *  \param limit max number of entries to erase
+   *  \param cb callback to receive the actual number of erased entries; it may be empty;
+   *            it may be invoked either before or after erase() returns
+   */
+  void
+  erase(const Name& prefix, size_t limit, const AfterEraseCallback& cb);
+
+  using HitCallback = std::function<void(const Interest&, const Data&)>;
+  using MissCallback = std::function<void(const Interest&)>;
 
   /** \brief finds the best matching Data packet
    *  \param interest the Interest for lookup