table: add CS enablement flags

This commit also:

* deletes never-implemented and unused Cs::erase method
* groups CS configuration methods together
* uses Table::emplace in Cs::insert

refs #4050

Change-Id: If8cf29dd33921da2f2c4ce56e02395d43cd3ee99
diff --git a/daemon/table/cs.cpp b/daemon/table/cs.cpp
index 89c54e9..81b3fd6 100644
--- a/daemon/table/cs.cpp
+++ b/daemon/table/cs.cpp
@@ -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,
@@ -44,42 +44,20 @@
 }
 
 Cs::Cs(size_t nMaxPackets)
+  : m_shouldAdmit(true)
+  , m_shouldServe(true)
 {
   this->setPolicyImpl(makeDefaultPolicy());
   m_policy->setLimit(nMaxPackets);
 }
 
 void
-Cs::setLimit(size_t nMaxPackets)
-{
-  m_policy->setLimit(nMaxPackets);
-}
-
-size_t
-Cs::getLimit() const
-{
-  return m_policy->getLimit();
-}
-
-void
-Cs::setPolicy(unique_ptr<Policy> policy)
-{
-  BOOST_ASSERT(policy != nullptr);
-  BOOST_ASSERT(m_policy != nullptr);
-  size_t limit = m_policy->getLimit();
-  this->setPolicyImpl(std::move(policy));
-  m_policy->setLimit(limit);
-}
-
-void
 Cs::insert(const Data& data, bool isUnsolicited)
 {
-  NFD_LOG_DEBUG("insert " << data.getName());
-
-  if (m_policy->getLimit() == 0) {
-    // shortcut for disabled CS
+  if (!m_shouldAdmit || m_policy->getLimit() == 0) {
     return;
   }
+  NFD_LOG_DEBUG("insert " << data.getName());
 
   // recognize CachePolicy
   shared_ptr<lp::CachePolicyTag> tag = data.getTag<lp::CachePolicyTag>();
@@ -90,10 +68,9 @@
     }
   }
 
-  bool isNewEntry = false;
   iterator it;
-  // use .insert because gcc46 does not support .emplace
-  std::tie(it, isNewEntry) = m_table.insert(EntryImpl(data.shared_from_this(), isUnsolicited));
+  bool isNewEntry = false;
+  std::tie(it, isNewEntry) = m_table.emplace(data.shared_from_this(), isUnsolicited);
   EntryImpl& entry = const_cast<EntryImpl&>(*it);
 
   entry.updateStaleTime();
@@ -119,6 +96,10 @@
   BOOST_ASSERT(static_cast<bool>(hitCallback));
   BOOST_ASSERT(static_cast<bool>(missCallback));
 
+  if (!m_shouldServe || m_policy->getLimit() == 0) {
+    missCallback(interest);
+    return;
+  }
   const Name& prefix = interest.getName();
   bool isRightmost = interest.getChildSelector() == 1;
   NFD_LOG_DEBUG("find " << prefix << (isRightmost ? " R" : " L"));
@@ -192,6 +173,25 @@
 }
 
 void
+Cs::dump()
+{
+  NFD_LOG_DEBUG("dump table");
+  for (const EntryImpl& entry : m_table) {
+    NFD_LOG_TRACE(entry.getFullName());
+  }
+}
+
+void
+Cs::setPolicy(unique_ptr<Policy> policy)
+{
+  BOOST_ASSERT(policy != nullptr);
+  BOOST_ASSERT(m_policy != nullptr);
+  size_t limit = m_policy->getLimit();
+  this->setPolicyImpl(std::move(policy));
+  m_policy->setLimit(limit);
+}
+
+void
 Cs::setPolicyImpl(unique_ptr<Policy> policy)
 {
   NFD_LOG_DEBUG("set-policy " << policy->getName());
@@ -205,12 +205,23 @@
 }
 
 void
-Cs::dump()
+Cs::enableAdmit(bool shouldAdmit)
 {
-  NFD_LOG_DEBUG("dump table");
-  for (const EntryImpl& entry : m_table) {
-    NFD_LOG_TRACE(entry.getFullName());
+  if (m_shouldAdmit == shouldAdmit) {
+    return;
   }
+  m_shouldAdmit = shouldAdmit;
+  NFD_LOG_INFO((shouldAdmit ? "Enabling" : "Disabling") << " Data admittance");
+}
+
+void
+Cs::enableServe(bool shouldServe)
+{
+  if (m_shouldServe == shouldServe) {
+    return;
+  }
+  m_shouldServe = shouldServe;
+  NFD_LOG_INFO((shouldServe ? "Enabling" : "Disabling") << " Data serving");
 }
 
 } // namespace cs
diff --git a/daemon/table/cs.hpp b/daemon/table/cs.hpp
index 34fd408..5a60fef 100644
--- a/daemon/table/cs.hpp
+++ b/daemon/table/cs.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017,  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,
@@ -85,37 +85,7 @@
        const HitCallback& hitCallback,
        const MissCallback& missCallback) const;
 
-  void
-  erase(const Name& exactName)
-  {
-    BOOST_ASSERT_MSG(false, "not implemented");
-  }
-
-  /** \brief changes capacity (in number of packets)
-   */
-  void
-  setLimit(size_t nMaxPackets);
-
-  /** \return capacity (in number of packets)
-   */
-  size_t
-  getLimit() const;
-
-  /** \brief changes cs replacement policy
-   *  \pre size() == 0
-   */
-  void
-  setPolicy(unique_ptr<Policy> policy);
-
-  /** \return cs replacement policy
-   */
-  Policy*
-  getPolicy() const
-  {
-    return m_policy.get();
-  }
-
-  /** \return number of stored packets
+  /** \brief get number of stored packets
    */
   size_t
   size() const
@@ -123,9 +93,66 @@
     return m_table.size();
   }
 
-PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+public: // configuration
+  /** \brief get capacity (in number of packets)
+   */
+  size_t
+  getLimit() const
+  {
+    return m_policy->getLimit();
+  }
+
+  /** \brief change capacity (in number of packets)
+   */
   void
-  dump();
+  setLimit(size_t nMaxPackets)
+  {
+    return m_policy->setLimit(nMaxPackets);
+  }
+
+  /** \brief get replacement policy
+   */
+  Policy*
+  getPolicy() const
+  {
+    return m_policy.get();
+  }
+
+  /** \brief change replacement policy
+   *  \pre size() == 0
+   */
+  void
+  setPolicy(unique_ptr<Policy> policy);
+
+  /** \brief get CS_ENABLE_ADMIT flag
+   *  \sa https://redmine.named-data.net/projects/nfd/wiki/CsMgmt#Update-config
+   */
+  bool
+  shouldAdmit() const
+  {
+    return m_shouldAdmit;
+  }
+
+  /** \brief set CS_ENABLE_ADMIT flag
+   *  \sa https://redmine.named-data.net/projects/nfd/wiki/CsMgmt#Update-config
+   */
+  void
+  enableAdmit(bool shouldAdmit);
+
+  /** \brief get CS_ENABLE_SERVE flag
+   *  \sa https://redmine.named-data.net/projects/nfd/wiki/CsMgmt#Update-config
+   */
+  bool
+  shouldServe() const
+  {
+    return m_shouldServe;
+  }
+
+  /** \brief set CS_ENABLE_SERVE flag
+   *  \sa https://redmine.named-data.net/projects/nfd/wiki/CsMgmt#Update-config
+   */
+  void
+  enableServe(bool shouldServe);
 
 public: // enumeration
   struct EntryFromEntryImpl
@@ -177,10 +204,17 @@
   void
   setPolicyImpl(unique_ptr<Policy> policy);
 
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+  void
+  dump();
+
 private:
   Table m_table;
   unique_ptr<Policy> m_policy;
-  ndn::util::signal::ScopedConnection m_beforeEvictConnection;
+  signal::ScopedConnection m_beforeEvictConnection;
+
+  bool m_shouldAdmit; ///< if false, no Data will be admitted
+  bool m_shouldServe; ///< if false, all lookups will miss
 };
 
 } // namespace cs
diff --git a/tests/daemon/table/cs.t.cpp b/tests/daemon/table/cs.t.cpp
index 3aa6de4..f63cec7 100644
--- a/tests/daemon/table/cs.t.cpp
+++ b/tests/daemon/table/cs.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017,  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,
@@ -383,6 +383,37 @@
   CHECK_CS_FIND(0);
 }
 
+BOOST_FIXTURE_TEST_CASE(EnablementFlags, FindFixture)
+{
+  BOOST_CHECK_EQUAL(m_cs.shouldAdmit(), true);
+  BOOST_CHECK_EQUAL(m_cs.shouldServe(), true);
+
+  insert(1, "/A");
+  m_cs.enableAdmit(false);
+  insert(2, "/B");
+  m_cs.enableAdmit(true);
+  insert(3, "/C");
+
+  startInterest("/A");
+  CHECK_CS_FIND(1);
+  startInterest("/B");
+  CHECK_CS_FIND(0);
+  startInterest("/C");
+  CHECK_CS_FIND(3);
+
+  m_cs.enableServe(false);
+  startInterest("/A");
+  CHECK_CS_FIND(0);
+  startInterest("/C");
+  CHECK_CS_FIND(0);
+
+  m_cs.enableServe(true);
+  startInterest("/A");
+  CHECK_CS_FIND(1);
+  startInterest("/C");
+  CHECK_CS_FIND(3);
+}
+
 BOOST_FIXTURE_TEST_CASE(CachePolicyNoCache, FindFixture)
 {
   insert(1, "/A", [] (Data& data) {