fw: introduce afterContentStoreHit strategy trigger
Change-Id: I71ca9e21467d2296203eb9686bff7647b1140271
refs: #4290
diff --git a/daemon/fw/forwarder.cpp b/daemon/fw/forwarder.cpp
index cb7ac9d..93be2e9 100644
--- a/daemon/fw/forwarder.cpp
+++ b/daemon/fw/forwarder.cpp
@@ -213,11 +213,12 @@
pitEntry->isSatisfied = true;
pitEntry->dataFreshnessPeriod = data.getFreshnessPeriod();
- // finalize Interest
- this->onInterestFinalize(pitEntry);
+ // set PIT expiry timer to now
+ this->setExpiryTimer(pitEntry, 0_ms);
- // goto outgoing Data pipeline
- this->onOutgoingData(data, *const_pointer_cast<Face>(inFace.shared_from_this()));
+ // dispatch to strategy: after Content Store hit
+ this->dispatchToStrategy(*pitEntry,
+ [&] (fw::Strategy& strategy) { strategy.afterContentStoreHit(pitEntry, inFace, data); });
}
void
diff --git a/daemon/fw/strategy.cpp b/daemon/fw/strategy.cpp
index d4d6827..a05080f 100644
--- a/daemon/fw/strategy.cpp
+++ b/daemon/fw/strategy.cpp
@@ -157,6 +157,16 @@
}
void
+Strategy::afterContentStoreHit(const shared_ptr<pit::Entry>& pitEntry,
+ const Face& inFace, const Data& data)
+{
+ NFD_LOG_DEBUG("afterContentStoreHit pitEntry=" << pitEntry->getName() <<
+ " inFace=" << inFace.getId() << " data=" << data.getName());
+
+ this->sendData(pitEntry, data, inFace);
+}
+
+void
Strategy::afterReceiveNack(const Face& inFace, const lp::Nack& nack,
const shared_ptr<pit::Entry>& pitEntry)
{
diff --git a/daemon/fw/strategy.hpp b/daemon/fw/strategy.hpp
index 12a06e8..e770e27 100644
--- a/daemon/fw/strategy.hpp
+++ b/daemon/fw/strategy.hpp
@@ -161,6 +161,14 @@
beforeSatisfyInterest(const shared_ptr<pit::Entry>& pitEntry,
const Face& inFace, const Data& data);
+ /** \brief trigger after a Data is matched in CS
+ *
+ * In the base class this method sends \p data to \p inFace
+ */
+ virtual void
+ afterContentStoreHit(const shared_ptr<pit::Entry>& pitEntry,
+ const Face& inFace, const Data& data);
+
/** \brief trigger after Nack is received
*
* This trigger is invoked when an incoming Nack is received in response to
@@ -177,7 +185,7 @@
* If a Nack arrives from another upstream during the extended PIT entry lifetime, this trigger will be invoked again.
* At that time, this function must invoke \c setExpiryTimer again to continue collecting more responses.
*
- * In this base class this method does nothing.
+ * In the base class this method does nothing.
*
* \warning The strategy must not retain shared_ptr<pit::Entry>, otherwise undefined behavior
* may occur. However, the strategy is allowed to store weak_ptr<pit::Entry>.
@@ -206,6 +214,19 @@
m_forwarder.onOutgoingInterest(pitEntry, outFace, interest);
}
+ /** \brief send \p data to \p outFace
+ * \param pitEntry PIT entry
+ * \param data the Data packet
+ * \param outFace face through which to send out the Data
+ */
+ VIRTUAL_WITH_TESTS void
+ sendData(const shared_ptr<pit::Entry>& pitEntry, const Data& data, const Face& outFace)
+ {
+ BOOST_ASSERT(pitEntry->getInterest().matchesData(data));
+
+ m_forwarder.onOutgoingData(data, *const_pointer_cast<Face>(outFace.shared_from_this()));
+ }
+
/** \brief schedule the PIT entry for immediate deletion
*
* This helper function sets the PIT entry expiry time to zero.
diff --git a/tests/daemon/fw/dummy-strategy.cpp b/tests/daemon/fw/dummy-strategy.cpp
index 28ca606..b37171f 100644
--- a/tests/daemon/fw/dummy-strategy.cpp
+++ b/tests/daemon/fw/dummy-strategy.cpp
@@ -46,6 +46,7 @@
: Strategy(forwarder)
, afterReceiveInterest_count(0)
, beforeSatisfyInterest_count(0)
+ , afterContentStoreHit_count(0)
, afterReceiveNack_count(0)
{
this->setInstanceName(name);
@@ -73,6 +74,15 @@
}
void
+DummyStrategy::afterContentStoreHit(const shared_ptr<pit::Entry>& pitEntry,
+ const Face& inFace, const Data& data)
+{
+ ++afterContentStoreHit_count;
+
+ this->sendData(pitEntry, data, inFace);
+}
+
+void
DummyStrategy::afterReceiveNack(const Face& inFace, const lp::Nack& nack,
const shared_ptr<pit::Entry>& pitEntry)
{
diff --git a/tests/daemon/fw/dummy-strategy.hpp b/tests/daemon/fw/dummy-strategy.hpp
index 1f168c5..24a432c 100644
--- a/tests/daemon/fw/dummy-strategy.hpp
+++ b/tests/daemon/fw/dummy-strategy.hpp
@@ -69,6 +69,10 @@
const Face& inFace, const Data& data) override;
void
+ afterContentStoreHit(const shared_ptr<pit::Entry>& pitEntry,
+ const Face& inFace, const Data& data) override;
+
+ void
afterReceiveNack(const Face& inFace, const lp::Nack& nack,
const shared_ptr<pit::Entry>& pitEntry) override;
@@ -88,6 +92,7 @@
public:
int afterReceiveInterest_count;
int beforeSatisfyInterest_count;
+ int afterContentStoreHit_count;
int afterReceiveNack_count;
shared_ptr<Face> interestOutFace;
diff --git a/tests/daemon/fw/pit-expiry.t.cpp b/tests/daemon/fw/pit-expiry.t.cpp
index 4eacd9e..1977458 100644
--- a/tests/daemon/fw/pit-expiry.t.cpp
+++ b/tests/daemon/fw/pit-expiry.t.cpp
@@ -29,6 +29,8 @@
#include "tests/test-common.hpp"
+#include <ndn-cxx/lp/tags.hpp>
+
namespace nfd {
namespace fw {
namespace tests {
@@ -63,7 +65,7 @@
afterReceiveInterest(const Face& inFace, const Interest& interest,
const shared_ptr<pit::Entry>& pitEntry) override
{
- ++afterReceiveInterest_count;
+ DummyStrategy::afterReceiveInterest(inFace, interest, pitEntry);
if (afterReceiveInterest_count <= 1) {
setExpiryTimer(pitEntry, 190_ms);
@@ -74,18 +76,29 @@
beforeSatisfyInterest(const shared_ptr<pit::Entry>& pitEntry,
const Face& inFace, const Data& data) override
{
- ++beforeSatisfyInterest_count;
+ DummyStrategy::beforeSatisfyInterest(pitEntry, inFace, data);
- if (beforeSatisfyInterest_count <= 1 ) {
+ if (beforeSatisfyInterest_count <= 1) {
setExpiryTimer(pitEntry, 190_ms);
}
}
void
+ afterContentStoreHit(const shared_ptr<pit::Entry>& pitEntry,
+ const Face& inFace, const Data& data) override
+ {
+ if (afterContentStoreHit_count == 0) {
+ setExpiryTimer(pitEntry, 190_ms);
+ }
+
+ DummyStrategy::afterContentStoreHit(pitEntry, inFace, data);
+ }
+
+ void
afterReceiveNack(const Face& inFace, const lp::Nack& nack,
const shared_ptr<pit::Entry>& pitEntry) override
{
- ++afterReceiveNack_count;
+ DummyStrategy::afterReceiveNack(inFace, nack, pitEntry);
if (afterReceiveNack_count <= 1) {
setExpiryTimer(pitEntry, 50_ms);
@@ -141,6 +154,43 @@
BOOST_CHECK_EQUAL(pit.size(), 0);
}
+BOOST_AUTO_TEST_CASE(CsHit)
+{
+ Forwarder forwarder;
+
+ auto face1 = make_shared<DummyFace>();
+ auto face2 = make_shared<DummyFace>();
+ forwarder.addFace(face1);
+ forwarder.addFace(face2);
+
+ Name strategyA("/strategyA/%FD%01");
+ PitExpiryTestStrategy::registerAs(strategyA);
+ choose<PitExpiryTestStrategy>(forwarder, "/A", strategyA);
+
+ shared_ptr<Interest> interest = makeInterest("/A/0");
+ interest->setInterestLifetime(90_ms);
+
+ shared_ptr<Data> data = makeData("/A/0");
+ data->setTag(make_shared<lp::IncomingFaceIdTag>(face2->getId()));
+
+ Pit& pit = forwarder.getPit();
+ BOOST_CHECK_EQUAL(pit.size(), 0);
+
+ Cs& cs = forwarder.getCs();
+ cs.insert(*data);
+
+ face1->receiveInterest(*interest);
+ this->advanceClocks(1_ms);
+ BOOST_CHECK_EQUAL(pit.size(), 1);
+
+ this->advanceClocks(190_ms);
+ BOOST_CHECK_EQUAL(pit.size(), 0);
+
+ face1->receiveInterest(*interest);
+ this->advanceClocks(1_ms);
+ BOOST_CHECK_EQUAL(pit.size(), 0);
+}
+
BOOST_AUTO_TEST_CASE(ReceiveNack)
{
Forwarder forwarder;