void WeightedLoadBalancerStrategy::afterReceiveInterest(const Face& inFace, const Interest& interest, shared_ptr<fib::Entry> fibEntry, shared_ptr<pit::Entry> pitEntry) { NFD_LOG_TRACE("Received Interest: " << interest.getName()); // not a new Interest, don't forward if (pitEntry->hasUnexpiredOutRecords()) { NFD_LOG_TRACE("Not a new Interest, " << interest.getName() << ", refusing to forward"); return; } // create timer information and attach to PIT entry pitEntry->setStrategyInfo<MyPitInfo>(make_shared<MyPitInfo>()); shared_ptr<MyMeasurementInfo> measurementsEntryInfo = myGetOrCreateMyMeasurementInfo(fibEntry); // reconcile differences between incoming nexthops and those stored // on our custom measurement entry info measurementsEntryInfo->updateStoredNextHops(fibEntry->getNextHops()); if (!this->mySendInterest(interest, measurementsEntryInfo, pitEntry)) { this->rejectPendingInterest(pitEntry); BOOST_ASSERT(false); } }
void MyMeasurementInfo::updateStoredNextHops(const fib::NextHopList& nexthops) { WeightedFaceSetByFaceId& facesById = weightedFaces.get<MyMeasurementInfo::ByFaceId>(); std::set<FaceId> nexthopFaceIds; for (fib::NextHopList::const_iterator i = nexthops.begin(); i != nexthops.end(); ++i) { const FaceId id = i->getFace()->getId(); if (facesById.find(id) == facesById.end()) { // new nexthop, add to set facesById.insert(WeightedFace(*i->getFace())); NFD_LOG_TRACE("added FaceId: " << id); } nexthopFaceIds.insert(id); } for (WeightedFaceSetByFaceId::const_iterator i = facesById.begin(); i != facesById.end(); ++i) { if (nexthopFaceIds.find(i->getId()) == nexthopFaceIds.end()) { NFD_LOG_TRACE("pruning FaceId: " << i->getId()); facesById.erase(i); } } }
iterator Cs::findRightmost(const Interest& interest, iterator first, iterator last) const { // Each loop visits a sub-namespace under a prefix one component longer than Interest Name. // If there is a match in that sub-namespace, the leftmost match is returned; // otherwise, loop continues. size_t interestNameLength = interest.getName().size(); for (iterator right = last; right != first;) { iterator prev = std::prev(right); // special case: [first,prev] have exact Names if (prev->getName().size() == interestNameLength) { NFD_LOG_TRACE(" find-among-exact " << prev->getName()); iterator matchExact = this->findRightmostAmongExact(interest, first, right); return matchExact == right ? last : matchExact; } Name prefix = prev->getName().getPrefix(interestNameLength + 1); iterator left = m_table.lower_bound(prefix); // normal case: [left,right) are under one-component-longer prefix NFD_LOG_TRACE(" find-under-prefix " << prefix); iterator match = this->findLeftmost(interest, left, right); if (match != right) { return match; } right = left; } return last; }
void PartialMessageStore::receive(const NdnlpData& pkt) { bool isReassembled = false; Block reassembled; if (pkt.fragCount == 1) { // single fragment std::tie(isReassembled, reassembled) = PartialMessage::reassembleSingle(pkt); } else { uint64_t messageIdentifier = pkt.seq - pkt.fragIndex; PartialMessage& pm = m_partialMessages[messageIdentifier]; this->scheduleCleanup(messageIdentifier, pm); pm.add(pkt.fragIndex, pkt.fragCount, pkt.payload); if (pm.isComplete()) { std::tie(isReassembled, reassembled) = pm.reassemble(); m_partialMessages.erase(messageIdentifier); } else { return; } } if (!isReassembled) { NFD_LOG_TRACE(pkt.seq << " reassemble error"); return; } NFD_LOG_TRACE(pkt.seq << " deliver"); this->onReceive(reassembled); }
void WeightedLoadBalancerStrategy::beforeSatisfyInterest(shared_ptr<pit::Entry> pitEntry, const Face& inFace, const Data& data) { NFD_LOG_TRACE("Received Data: " << data.getName()); shared_ptr<MyPitInfo> pitInfo = pitEntry->getStrategyInfo<MyPitInfo>(); // No start time available, cannot compute delay for this retrieval if (!static_cast<bool>(pitInfo)) { NFD_LOG_TRACE("No start time available for Data " << data.getName()); return; } const milliseconds delay = duration_cast<milliseconds>(system_clock::now() - pitInfo->creationTime); NFD_LOG_TRACE("Computed delay of: " << system_clock::now() << " - " << pitInfo->creationTime << " = " << delay); MeasurementsAccessor& accessor = this->getMeasurements(); // Update Face delay measurements and entry lifetimes owned // by this strategy while walking up the NameTree shared_ptr<measurements::Entry> measurementsEntry = accessor.get(*pitEntry); if (static_cast<bool>(measurementsEntry)) { NFD_LOG_TRACE("accessor returned measurements entry " << measurementsEntry->getName() << " for " << pitEntry->getName()); } else { NFD_LOG_WARN ("accessor returned invalid measurements entry for " << pitEntry->getName()); } while (static_cast<bool>(measurementsEntry)) { shared_ptr<MyMeasurementInfo> measurementsEntryInfo = measurementsEntry->getStrategyInfo<MyMeasurementInfo>(); if (static_cast<bool>(measurementsEntryInfo)) { accessor.extendLifetime(*measurementsEntry, seconds(16)); measurementsEntryInfo->updateFaceDelay(inFace, delay); } measurementsEntry = accessor.getParent(*measurementsEntry); } }
void MadmStrategy::probeInterests(const shared_ptr<Face> outFace, const Interest& interest, StrategyRequirements &requirements, const fib::NextHopList& nexthops, shared_ptr<pit::Entry> pitEntry) { for (auto n : nexthops) { const shared_ptr<Face>& thisFace = n.getFace(); bool costTooHigh = false; if (requirements.getLimits(RequirementType::COST).second != -1) { costTooHigh = costMap[thisFace->getId()].getCost() > (requirements.getLimits(RequirementType::COST)).second; if (costTooHigh) { NFD_LOG_DEBUG( "Cost too high: " << costMap[thisFace->getId()].getCost() << " > " << (requirements.getLimits(RequirementType::COST)).second); } } if (thisFace != outFace && !costTooHigh) { NFD_LOG_TRACE("Probing face: " << thisFace->getId()); faceInfoTable[thisFace->getId()].addSentInterest(interest.getName().toUri()); this->sendInterest(pitEntry, thisFace, true); } } }
void FibManager::addNextHop(const Name& topPrefix, const Interest& interest, ControlParameters parameters, const ndn::mgmt::CommandContinuation& done) { setFaceForSelfRegistration(interest, parameters); const Name& prefix = parameters.getName(); FaceId faceId = parameters.getFaceId(); uint64_t cost = parameters.getCost(); NFD_LOG_TRACE("add-nexthop prefix: " << prefix << " faceid: " << faceId << " cost: " << cost); auto face = m_getFace(faceId); if (static_cast<bool>(face)) { auto entry = m_fib.insert(prefix).first; entry->addNextHop(face, cost); NFD_LOG_DEBUG("add-nexthop result: OK" << " prefix:" << prefix << " faceid: " << faceId << " cost: " << cost); return done(ControlResponse(200, "Success").setBody(parameters.wireEncode())); } else { NFD_LOG_INFO("add-nexthop result: FAIL reason: unknown-faceid: " << faceId); return done(ControlResponse(410, "Face not found")); } }
size_t NameTree::eraseIfEmpty(Entry* entry, bool canEraseAncestors) { BOOST_ASSERT(entry != nullptr); size_t nErased = 0; for (Entry* parent = nullptr; entry != nullptr && entry->isEmpty(); entry = parent) { parent = entry->getParent(); if (parent != nullptr) { entry->unsetParent(); } m_ht.erase(getNode(*entry)); ++nErased; if (!canEraseAncestors) { break; } } if (nErased == 0) { NFD_LOG_TRACE("not-erase " << entry->getName()); } return nErased; }
void RandomLoadBalancerStrategy::afterReceiveInterest(const Face& inFace, const Interest& interest, shared_ptr<fib::Entry> fibEntry, shared_ptr<pit::Entry> pitEntry) { NFD_LOG_TRACE("afterReceiveInterest"); if (pitEntry->hasUnexpiredOutRecords()) { // not a new Interest, don't forward return; } const fib::NextHopList& nexthops = fibEntry->getNextHops(); // Ensure there is at least 1 Face is available for forwarding if (!hasFaceForForwarding(nexthops, pitEntry)) { this->rejectPendingInterest(pitEntry); return; } fib::NextHopList::const_iterator selected; do { boost::random::uniform_int_distribution<> dist(0, nexthops.size() - 1); const size_t randomIndex = dist(m_randomGenerator); uint64_t currentIndex = 0; for (selected = nexthops.begin(); selected != nexthops.end() && currentIndex != randomIndex; ++selected, ++currentIndex) { } } while (!canForwardToNextHop(pitEntry, *selected)); this->sendInterest(pitEntry, selected->getFace()); }
void FibManager::removeNextHop(const Name& topPrefix, const Interest& interest, ControlParameters parameters, const ndn::mgmt::CommandContinuation& done) { setFaceForSelfRegistration(interest, parameters); NFD_LOG_TRACE("remove-nexthop prefix: " << parameters.getName() << " faceid: " << parameters.getFaceId()); auto face = m_getFace(parameters.getFaceId()); if (static_cast<bool>(face)) { auto entry = m_fib.findExactMatch(parameters.getName()); if (static_cast<bool>(entry)) { entry->removeNextHop(face); NFD_LOG_DEBUG("remove-nexthop result: OK prefix: " << parameters.getName() << " faceid: " << parameters.getFaceId()); if (!entry->hasNextHops()) { m_fib.erase(*entry); } } else { NFD_LOG_DEBUG("remove-nexthop result: OK"); } } else { NFD_LOG_DEBUG("remove-nexthop result: OK"); } done(ControlResponse(200, "Success").setBody(parameters.wireEncode())); }
static void onConfig(const ConfigSection& configSection, bool isDryRun, const std::string& filename) { // general // { // ; user "ndn-user" // ; group "ndn-user" // } std::string user; std::string group; for (ConfigSection::const_iterator i = configSection.begin(); i != configSection.end(); ++i) { if (i->first == "user") { try { user = i->second.get_value<std::string>("user"); if (user.empty()) { throw ConfigFile::Error("Invalid value for \"user\"" " in \"general\" section"); } } catch (const boost::property_tree::ptree_error& error) { throw ConfigFile::Error("Invalid value for \"user\"" " in \"general\" section"); } } else if (i->first == "group") { try { group = i->second.get_value<std::string>("group"); if (group.empty()) { throw ConfigFile::Error("Invalid value for \"group\"" " in \"general\" section"); } } catch (const boost::property_tree::ptree_error& error) { throw ConfigFile::Error("Invalid value for \"group\"" " in \"general\" section"); } } } NFD_LOG_TRACE("using user \"" << user << "\" group \"" << group << "\""); PrivilegeHelper::initialize(user, group); }
Iterator& Iterator::operator++() { BOOST_ASSERT(m_impl != nullptr); m_impl->advance(*this); NFD_LOG_TRACE("advanced " << *this); return *this; }
void Cs::dump() { NFD_LOG_DEBUG("dump table"); for (const EntryImpl& entry : m_table) { NFD_LOG_TRACE(entry.getFullName()); } }
Face* AsfStrategy::getBestFaceForForwarding(const fib::Entry& fibEntry, const Interest& interest, const Face& inFace) { NFD_LOG_TRACE("Looking for best face for " << fibEntry.getPrefix()); typedef std::function<bool(const FaceStats&, const FaceStats&)> FaceStatsPredicate; typedef std::set<FaceStats, FaceStatsPredicate> FaceStatsSet; FaceStatsSet rankedFaces( [] (const FaceStats& lhs, const FaceStats& rhs) -> bool { // Sort by RTT and then by cost double lhsValue = getValueForSorting(lhs); double rhsValue = getValueForSorting(rhs); if (lhsValue < rhsValue) { return true; } else if (lhsValue == rhsValue) { return lhs.cost < rhs.cost; } else { return false; } }); for (const fib::NextHop& hop : fibEntry.getNextHops()) { Face& hopFace = hop.getFace(); if (hopFace.getId() == inFace.getId() || wouldViolateScope(inFace, interest, hopFace)) { continue; } FaceInfo* info = m_measurements.getFaceInfo(fibEntry, interest, hopFace); if (info == nullptr) { FaceStats stats = {&hopFace, RttStats::RTT_NO_MEASUREMENT, RttStats::RTT_NO_MEASUREMENT, hop.getCost()}; rankedFaces.insert(stats); } else { FaceStats stats = {&hopFace, info->getRtt(), info->getSrtt(), hop.getCost()}; rankedFaces.insert(stats); } } FaceStatsSet::iterator it = rankedFaces.begin(); if (it != rankedFaces.end()) { return it->face; } else { return nullptr; } }
Iterator::Iterator(shared_ptr<EnumerationImpl> impl, const Entry* ref) : m_impl(impl) , m_entry(nullptr) , m_ref(ref) , m_state(0) { m_impl->advance(*this); NFD_LOG_TRACE("initialized " << *this); }
Entry& NameTree::lookup(const strategy_choice::Entry& strategyChoiceEntry) { NFD_LOG_TRACE("lookup(SC " << strategyChoiceEntry.getPrefix() << ')'); Entry* nte = this->getEntry(strategyChoiceEntry); BOOST_ASSERT(nte != nullptr); BOOST_ASSERT(nte->getStrategyChoiceEntry() == &strategyChoiceEntry); return *nte; }
Entry& NameTree::lookup(const measurements::Entry& measurementsEntry) { NFD_LOG_TRACE("lookup(M " << measurementsEntry.getName() << ')'); Entry* nte = this->getEntry(measurementsEntry); BOOST_ASSERT(nte != nullptr); BOOST_ASSERT(nte->getMeasurementsEntry() == &measurementsEntry); return *nte; }
void FaceInfo::recordRtt(const shared_ptr<pit::Entry>& pitEntry, const Face& inFace) { // Calculate RTT pit::OutRecordCollection::const_iterator outRecord = pitEntry->getOutRecord(inFace); if (outRecord == pitEntry->out_end()) { // no out-record NFD_LOG_TRACE(pitEntry->getInterest() << " dataFrom inFace=" << inFace.getId() << " no-out-record"); return; } time::steady_clock::Duration steadyRtt = time::steady_clock::now() - outRecord->getLastRenewed(); RttEstimator::Duration durationRtt = time::duration_cast<RttEstimator::Duration>(steadyRtt); m_rttStats.addRttMeasurement(durationRtt); NFD_LOG_TRACE("Recording RTT for FaceId: " << inFace.getId() << " RTT: " << m_rttStats.getRtt() << " SRTT: " << m_rttStats.getSrtt()); }
void AsfStrategy::onTimeout(const Name& interestName, face::FaceId faceId) { NFD_LOG_TRACE("FaceId: " << faceId << " for " << interestName << " has timed-out"); NamespaceInfo* namespaceInfo = m_measurements.getNamespaceInfo(interestName); if (namespaceInfo == nullptr) { NFD_LOG_TRACE("FibEntry for " << interestName << " has been removed since timeout scheduling"); return; } FaceInfoTable::iterator it = namespaceInfo->find(faceId); if (it == namespaceInfo->end()) { it = namespaceInfo->insert(faceId); } FaceInfo& faceInfo = it->second; faceInfo.recordTimeout(interestName); }
void RibManager::onNotification(const FaceEventNotification& notification) { NFD_LOG_TRACE("onNotification: " << notification); if (notification.getKind() == ndn::nfd::FACE_EVENT_DESTROYED) { NFD_LOG_DEBUG("Received notification for destroyed faceId: " << notification.getFaceId()); scheduler::schedule(time::seconds(0), bind(&RibManager::onFaceDestroyedEvent, this, notification.getFaceId())); } }
bool WeightedLoadBalancerStrategy::mySendInterest(const Interest& interest, shared_ptr<MyMeasurementInfo>& measurementsEntryInfo, shared_ptr<pit::Entry>& pitEntry) { typedef MyMeasurementInfo::WeightedFaceSetByDelay WeightedFaceSetByDelay; const WeightedFaceSetByDelay& facesByDelay = measurementsEntryInfo->weightedFaces.get<MyMeasurementInfo::ByDelay>(); const milliseconds totalDelay = measurementsEntryInfo->totalDelay; const milliseconds inverseTotalDelay = MyMeasurementInfo::calculateInverseDelaySum(measurementsEntryInfo); boost::random::uniform_int_distribution<> dist(0, inverseTotalDelay.count()); const uint64_t selection = dist(m_randomGenerator); NFD_LOG_TRACE("selection = " << selection); uint64_t cumulativeWeight = 0; for (WeightedFaceSetByDelay::const_iterator i = facesByDelay.begin(); i != facesByDelay.end(); ++i) { NFD_LOG_TRACE("cumulative weight = " << cumulativeWeight); // weight = inverted delay measurement const uint64_t weight = totalDelay.count() - i->lastDelay.count(); cumulativeWeight += weight; if(selection <= cumulativeWeight && pitEntry->canForwardTo(i->face)) { NFD_LOG_TRACE("fowarding " << interest.getName() << " out face " << i->face.getId()); this->sendInterest(pitEntry, this->getFace(i->face.getId())); return true; } } return false; }
void AsfStrategy::forwardInterest(const Interest& interest, const fib::Entry& fibEntry, const shared_ptr<pit::Entry>& pitEntry, Face& outFace, bool wantNewNonce) { if (wantNewNonce) { //Send probe: interest with new Nonce Interest probeInterest(interest); probeInterest.refreshNonce(); NFD_LOG_TRACE("Sending probe for " << probeInterest << probeInterest.getNonce() << " to FaceId: " << outFace.getId()); this->sendInterest(pitEntry, outFace, probeInterest); } else { this->sendInterest(pitEntry, outFace, interest); } FaceInfo& faceInfo = m_measurements.getOrCreateFaceInfo(fibEntry, interest, outFace); // Refresh measurements since Face is being used for forwarding NamespaceInfo& namespaceInfo = m_measurements.getOrCreateNamespaceInfo(fibEntry, interest); namespaceInfo.extendFaceInfoLifetime(faceInfo, outFace); if (!faceInfo.isTimeoutScheduled()) { // Estimate and schedule timeout RttEstimator::Duration timeout = faceInfo.computeRto(); NFD_LOG_TRACE("Scheduling timeout for " << fibEntry.getPrefix() << " FaceId: " << outFace.getId() << " in " << time::duration_cast<time::milliseconds>(timeout) << " ms"); scheduler::EventId id = scheduler::schedule(timeout, bind(&AsfStrategy::onTimeout, this, interest.getName(), outFace.getId())); faceInfo.setTimeoutEvent(id, interest.getName()); } }
Entry& NameTree::lookup(const fib::Entry& fibEntry) { NFD_LOG_TRACE("lookup(FIB " << fibEntry.getPrefix() << ')'); Entry* nte = this->getEntry(fibEntry); if (nte == nullptr) { // special case: Fib::s_emptyEntry is unattached BOOST_ASSERT(fibEntry.getPrefix().empty()); return this->lookup(fibEntry.getPrefix()); } BOOST_ASSERT(nte->getFibEntry() == &fibEntry); return *nte; }
Strategy::Registry::const_iterator Strategy::find(const Name& instanceName) { const Registry& registry = getRegistry(); ParsedInstanceName parsed = parseInstanceName(instanceName); if (parsed.version) { // specified version: find exact or next higher version auto found = registry.lower_bound(parsed.strategyName); if (found != registry.end()) { if (parsed.strategyName.getPrefix(-1).isPrefixOf(found->first)) { NFD_LOG_TRACE("find " << instanceName << " versioned found=" << found->first); return found; } } NFD_LOG_TRACE("find " << instanceName << " versioned not-found"); return registry.end(); } // no version specified: find highest version if (!parsed.strategyName.empty()) { // Name().getSuccessor() would be invalid auto found = registry.lower_bound(parsed.strategyName.getSuccessor()); if (found != registry.begin()) { --found; if (parsed.strategyName.isPrefixOf(found->first)) { NFD_LOG_TRACE("find " << instanceName << " unversioned found=" << found->first); return found; } } } NFD_LOG_TRACE("find " << instanceName << " unversioned not-found"); return registry.end(); }
const fib::Entry& Strategy::lookupFib(const pit::Entry& pitEntry) const { const Fib& fib = m_forwarder.getFib(); const Interest& interest = pitEntry.getInterest(); // has forwarding hint? if (interest.getForwardingHint().empty()) { // FIB lookup with Interest name const fib::Entry& fibEntry = fib.findLongestPrefixMatch(pitEntry); NFD_LOG_TRACE("lookupFib noForwardingHint found=" << fibEntry.getPrefix()); return fibEntry; } const DelegationList& fh = interest.getForwardingHint(); // Forwarding hint should have been stripped by incoming Interest pipeline when reaching producer region BOOST_ASSERT(!m_forwarder.getNetworkRegionTable().isInProducerRegion(fh)); const fib::Entry* fibEntry = nullptr; for (const Delegation& del : fh) { fibEntry = &fib.findLongestPrefixMatch(del.name); if (fibEntry->hasNextHops()) { if (fibEntry->getPrefix().size() == 0) { // in consumer region, return the default route NFD_LOG_TRACE("lookupFib inConsumerRegion found=" << fibEntry->getPrefix()); } else { // in default-free zone, use the first delegation that finds a FIB entry NFD_LOG_TRACE("lookupFib delegation=" << del.name << " found=" << fibEntry->getPrefix()); } return *fibEntry; } BOOST_ASSERT(fibEntry->getPrefix().size() == 0); // only ndn:/ FIB entry can have zero nexthop } BOOST_ASSERT(fibEntry != nullptr && fibEntry->getPrefix().size() == 0); return *fibEntry; // only occurs if no delegation finds a FIB nexthop }
void RibManager::onUnRegSuccess(const shared_ptr<const Interest>& request, const ControlParameters& parameters, const Route& route) { ControlResponse response; response.setCode(200); response.setText("Success"); response.setBody(parameters.wireEncode()); NFD_LOG_TRACE("onUnRegSuccess: unregistered " << route); if (static_cast<bool>(request)) { sendResponse(request->getName(), response); } }
RibEntry::RouteList::iterator RibEntry::eraseRoute(RouteList::iterator route) { if (route != m_routes.end()) { if (route->flags & ndn::nfd::ROUTE_FLAG_CAPTURE) { m_nRoutesWithCaptureSet--; } // Cancel any scheduled event NFD_LOG_TRACE("Cancelling expiration eventId: " << route->getExpirationEvent()); scheduler::cancel(route->getExpirationEvent()); return m_routes.erase(route); } return m_routes.end(); }
Entry& NameTree::lookup(const pit::Entry& pitEntry) { const Name& name = pitEntry.getName(); NFD_LOG_TRACE("lookup(PIT " << name << ')'); bool hasDigest = name.size() > 0 && name[-1].isImplicitSha256Digest(); if (hasDigest && name.size() <= getMaxDepth()) { return this->lookup(name); } Entry* nte = this->getEntry(pitEntry); BOOST_ASSERT(nte != nullptr); BOOST_ASSERT(std::count_if(nte->getPitEntries().begin(), nte->getPitEntries().end(), [&pitEntry] (const shared_ptr<pit::Entry>& pitEntry1) { return pitEntry1.get() == &pitEntry; }) == 1); return *nte; }
void FibManager::removeNextHop(ControlParameters& parameters, ControlResponse& response) { ndn::nfd::FibRemoveNextHopCommand command; if (!validateParameters(command, parameters)) { NFD_LOG_DEBUG("remove-nexthop result: FAIL reason: malformed"); setResponse(response, 400, "Malformed command"); return; } NFD_LOG_TRACE("remove-nexthop prefix: " << parameters.getName() << " faceid: " << parameters.getFaceId()); shared_ptr<Face> faceToRemove = m_getFace(parameters.getFaceId()); if (static_cast<bool>(faceToRemove)) { shared_ptr<fib::Entry> entry = m_managedFib.findExactMatch(parameters.getName()); if (static_cast<bool>(entry)) { entry->removeNextHop(faceToRemove); NFD_LOG_DEBUG("remove-nexthop result: OK prefix: " << parameters.getName() << " faceid: " << parameters.getFaceId()); if (!entry->hasNextHops()) { m_managedFib.erase(*entry); } } else { NFD_LOG_DEBUG("remove-nexthop result: OK, but entry for face id " << parameters.getFaceId() << " not found"); } } else { NFD_LOG_DEBUG("remove-nexthop result: OK, but face id " << parameters.getFaceId() << " not found"); } setResponse(response, 200, "Success", parameters.wireEncode()); }
RibEntry::FaceList::iterator RibEntry::eraseFace(FaceList::iterator face) { if (face != m_faces.end()) { if (face->flags & ndn::nfd::ROUTE_FLAG_CAPTURE) { m_nFacesWithCaptureSet--; } //cancel any scheduled event NFD_LOG_TRACE("Cancelling expiration eventId: " << face->getExpirationEvent()); scheduler::cancel(face->getExpirationEvent()); return m_faces.erase(face); } return m_faces.end(); }