table: add Cs::erase method

This commit also corrects CS's description in Doxygen.

refs #4318

Change-Id: Ie8854a2e2b59a072b98603c0cc31768bb84ea6d2
This commit is contained in:
Junxiao Shi committed 2018-04-09 14:26:47 +00:00
1 parent c14a8acf39
commit 30c37ab9bf
4 files changed
+109 -42

No files matched your search

+20 -16
View File
@@ -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 @@ struct EntryItComparator
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 @@ public:
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 @@ using priority_fifo::PriorityFifoPolicy;
} // namespace cs
} // namespace nfd
#endif // NFD_DAEMON_TABLE_CS_POLICY_FIFO_HPP
#endif // NFD_DAEMON_TABLE_CS_POLICY_PRIORITY_FIFO_HPP
+23
View File
@@ -88,6 +88,29 @@ Cs::insert(const Data& data, bool isUnsolicited)
}
}
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,
+22 -25
View File
@@ -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 @@ public:
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
+44 -1
View File
@@ -85,10 +85,21 @@ protected:
check(0);
}));
// current Cs::find implementation performs lookup synchronously
// current Cs::find implementation is synchronous
BOOST_CHECK(hasResult);
}
size_t
erase(const Name& prefix, size_t limit)
{
ndn::optional<size_t> nErased;
m_cs.erase(prefix, limit, [&] (size_t nErased1) { nErased = nErased1; });
// current Cs::erase implementation is synchronous
// if callback was not invoked, bad_optional_access would occur
return *nErased;
}
protected:
Cs m_cs;
shared_ptr<Interest> m_interest;
@@ -364,6 +375,38 @@ BOOST_AUTO_TEST_CASE(DigestExclude)
BOOST_AUTO_TEST_SUITE_END() // Find
BOOST_FIXTURE_TEST_CASE(Erase, FindFixture)
{
insert(1, "/A/B/1");
insert(2, "/A/B/2");
insert(3, "/A/C/3");
insert(4, "/A/C/4");
insert(5, "/D/5");
insert(6, "/E/6");
BOOST_CHECK_EQUAL(m_cs.size(), 6);
BOOST_CHECK_EQUAL(erase("/A", 3), 3);
BOOST_CHECK_EQUAL(m_cs.size(), 3);
int nDataUnderA = 0;
startInterest("/A/B/1");
find([&] (uint32_t found) { nDataUnderA += static_cast<int>(found > 0); });
startInterest("/A/B/2");
find([&] (uint32_t found) { nDataUnderA += static_cast<int>(found > 0); });
startInterest("/A/C/3");
find([&] (uint32_t found) { nDataUnderA += static_cast<int>(found > 0); });
startInterest("/A/C/4");
find([&] (uint32_t found) { nDataUnderA += static_cast<int>(found > 0); });
BOOST_CHECK_EQUAL(nDataUnderA, 1);
BOOST_CHECK_EQUAL(erase("/D", 2), 1);
BOOST_CHECK_EQUAL(m_cs.size(), 2);
startInterest("/D/5");
CHECK_CS_FIND(0);
BOOST_CHECK_EQUAL(erase("/F", 2), 0);
BOOST_CHECK_EQUAL(m_cs.size(), 2);
}
// When the capacity limit is set to zero, Data cannot be inserted;
// this test case covers this situation.
// The behavior of non-zero capacity limit depends on the eviction policy,