34 #include <ndn-cxx/util/crypto.hpp> 
   35 #include <ndn-cxx/security/signature-sha256-with-rsa.hpp> 
   37 #include <boost/random/bernoulli_distribution.hpp> 
   38 #include <boost/concept/assert.hpp> 
   39 #include <boost/concept_check.hpp> 
   40 #include <type_traits> 
   52 BOOST_CONCEPT_ASSERT((boost::ForwardIterator<Cs::const_iterator>));
 
   55 #ifdef HAVE_IS_DEFAULT_CONSTRUCTIBLE 
   56 static_assert(std::is_default_constructible<Cs::const_iterator>::value,
 
   57               "Cs::const_iterator must be default-constructible");
 
   59 BOOST_CONCEPT_ASSERT((boost::DefaultConstructible<Cs::const_iterator>));
 
   60 #endif // HAVE_IS_DEFAULT_CONSTRUCTIBLE 
   63   : m_nMaxPackets(nMaxPackets)
 
   67   m_skipList.push_back(zeroLayer);
 
   69   for (
size_t i = 0; i < m_nMaxPackets; i++)
 
   79   BOOST_ASSERT(m_freeCsEntries.size() == m_nMaxPackets);
 
   81   while (!m_freeCsEntries.empty())
 
   83       delete m_freeCsEntries.front();
 
   84       m_freeCsEntries.pop();
 
   97   size_t oldNMaxPackets = m_nMaxPackets;
 
   98   m_nMaxPackets = nMaxPackets;
 
  100   while (
size() > m_nMaxPackets) {
 
  104   if (m_nMaxPackets >= oldNMaxPackets) {
 
  105     for (
size_t i = oldNMaxPackets; i < m_nMaxPackets; i++) {
 
  110     for (
size_t i = oldNMaxPackets; i > m_nMaxPackets; i--) {
 
  111       delete m_freeCsEntries.front();
 
  112       m_freeCsEntries.pop();
 
  120   return m_nMaxPackets;
 
  124 std::pair<cs::skip_list::Entry*, bool>
 
  125 Cs::insertToSkipList(
const Data& data, 
bool isUnsolicited)
 
  127   NFD_LOG_TRACE(
"insertToSkipList() " << data.getFullName() << 
", " 
  128                 << 
"skipList size " << 
size());
 
  130   BOOST_ASSERT(m_cleanupIndex.size() <= 
size());
 
  131   BOOST_ASSERT(m_freeCsEntries.size() > 0);
 
  135   m_freeCsEntries.pop();
 
  137   entry->setData(data, isUnsolicited);
 
  139   bool insertInFront = 
false;
 
  140   bool isIterated = 
false;
 
  141   SkipList::reverse_iterator topLayer = m_skipList.rbegin();
 
  143   SkipListLayer::iterator head = (*topLayer)->begin();
 
  145   if (!(*topLayer)->empty())
 
  148       int layer = m_skipList.size() - 1;
 
  149       for (SkipList::reverse_iterator rit = topLayer; rit != m_skipList.rend(); ++rit)
 
  153             head = (*rit)->begin();
 
  155           updateTable[layer] = head;
 
  157           if (head != (*rit)->end())
 
  160               if (!isIterated && ((*head)->getFullName() >= entry->getFullName()))
 
  162                   --updateTable[layer];
 
  163                   insertInFront = 
true;
 
  167                   SkipListLayer::iterator it = head;
 
  169                   while ((*it)->getFullName() < entry->getFullName())
 
  172                       updateTable[layer] = it;
 
  176                       if (it == (*rit)->end())
 
  183             head = (*head)->getIterators().find(layer - 1)->second; 
 
  190       updateTable[0] = (*topLayer)->begin(); 
 
  193   head = updateTable[0];
 
  196   bool isCsEmpty = (
size() == 0);
 
  197   bool isInBoundaries = (head != (*m_skipList.begin())->
end());
 
  198   bool isNameIdentical = 
false;
 
  199   if (!isCsEmpty && isInBoundaries)
 
  201       isNameIdentical = (*head)->getFullName() == entry->getFullName();
 
  209       (*head)->setData(data, isUnsolicited); 
 
  213       m_freeCsEntries.push(entry);
 
  216       return std::make_pair(*head, 
false);
 
  221   size_t randomLayer = pickRandomLayer();
 
  223   while (m_skipList.size() < randomLayer + 1)
 
  226       m_skipList.push_back(newLayer);
 
  228       updateTable[(m_skipList.size() - 1)] = newLayer->begin();
 
  232   for (SkipList::iterator i = m_skipList.begin();
 
  233        i != m_skipList.end() && layer <= randomLayer; ++i)
 
  235       if (updateTable[layer] == (*i)->end() && !insertInFront)
 
  237           (*i)->push_back(entry);
 
  238           SkipListLayer::iterator last = (*i)->end();
 
  240           entry->setIterator(layer, last);
 
  244       else if (updateTable[layer] == (*i)->end() && insertInFront)
 
  246           (*i)->push_front(entry);
 
  247           entry->setIterator(layer, (*i)->begin());
 
  254           ++updateTable[layer]; 
 
  255           SkipListLayer::iterator position = (*i)->insert(updateTable[layer], entry);
 
  256           entry->setIterator(layer, position); 
 
  261   return std::make_pair(entry, 
true);
 
  275   std::pair<cs::skip_list::Entry*, bool> entry = insertToSkipList(data, isUnsolicited);
 
  278   if (static_cast<bool>(entry.first) && (entry.second == 
true))
 
  280       m_cleanupIndex.push_back(entry.first);
 
  288 Cs::pickRandomLayer()
 const 
  304   if (
size() >= m_nMaxPackets) 
 
  311 Cs::eraseFromSkipList(cs::skip_list::Entry* entry)
 
  313   NFD_LOG_TRACE(
"eraseFromSkipList() "  << entry->getFullName());
 
  316   bool isErased = 
false;
 
  318   const std::map<int, std::list<cs::skip_list::Entry*>::iterator>& iterators = entry->getIterators();
 
  320   if (!iterators.empty())
 
  324       for (SkipList::iterator it = m_skipList.begin(); it != m_skipList.end(); )
 
  326           std::map<int, std::list<cs::skip_list::Entry*>::iterator>::const_iterator i = iterators.find(layer);
 
  328           if (i != iterators.end())
 
  330               (*it)->erase(i->second);
 
  331               entry->removeIterator(layer);
 
  335               if ((layer != 0) && (*it)->empty())
 
  338                   it = m_skipList.erase(it);
 
  354     m_freeCsEntries.push(entry);
 
  366   if (!m_cleanupIndex.get<unsolicited>().empty()) {
 
  367     CleanupIndex::index<unsolicited>::type::const_iterator firstSolicited =
 
  368       m_cleanupIndex.get<unsolicited>().upper_bound(
false);
 
  370     if (firstSolicited != m_cleanupIndex.get<unsolicited>().begin()) {
 
  372       BOOST_ASSERT((*firstSolicited)->isUnsolicited());
 
  375       eraseFromSkipList(*firstSolicited);
 
  376       m_cleanupIndex.get<unsolicited>().
erase(firstSolicited);
 
  380       BOOST_ASSERT(!(*m_cleanupIndex.get<unsolicited>().begin())->isUnsolicited());
 
  384   if (!m_cleanupIndex.get<byStaleness>().empty() &&
 
  385       (*m_cleanupIndex.get<byStaleness>().
begin())->getStaleTime() < time::steady_clock::now())
 
  389     eraseFromSkipList(*m_cleanupIndex.get<byStaleness>().begin());
 
  390     m_cleanupIndex.get<byStaleness>().
erase(m_cleanupIndex.get<byStaleness>().begin());
 
  394   if (!m_cleanupIndex.get<byArrival>().empty())
 
  398     eraseFromSkipList(*m_cleanupIndex.get<byArrival>().begin());
 
  399     m_cleanupIndex.get<byArrival>().
erase(m_cleanupIndex.get<byArrival>().begin());
 
  411   bool isIterated = 
false;
 
  412   SkipList::const_reverse_iterator topLayer = m_skipList.rbegin();
 
  413   SkipListLayer::iterator head = (*topLayer)->begin();
 
  415   if (!(*topLayer)->empty())
 
  418       int layer = m_skipList.size() - 1;
 
  419       for (SkipList::const_reverse_iterator rit = topLayer; rit != m_skipList.rend(); ++rit)
 
  423             head = (*rit)->begin();
 
  425           if (head != (*rit)->end())
 
  428               if (!isIterated && (interest.getName().isPrefixOf((*head)->getFullName())))
 
  442                   SkipListLayer::iterator it = head;
 
  444                   while ((*it)->getFullName() < interest.getName())
 
  446                       NFD_LOG_TRACE((*it)->getFullName() << 
" < " << interest.getName());
 
  451                       if (it == (*rit)->end())
 
  459               head = (*head)->getIterators().find(layer - 1)->second; 
 
  464                 return selectChild(interest, head);
 
  475 Cs::selectChild(
const Interest& interest, SkipListLayer::iterator startingPoint)
 const 
  477   BOOST_ASSERT(startingPoint != (*m_skipList.begin())->
end());
 
  479   if (startingPoint != (*m_skipList.begin())->
begin())
 
  481       BOOST_ASSERT((*startingPoint)->getFullName() < interest.getName());
 
  484   NFD_LOG_TRACE(
"selectChild() " << interest.getChildSelector() << 
" " 
  485                 << (*startingPoint)->getFullName());
 
  487   bool hasLeftmostSelector = (interest.getChildSelector() <= 0);
 
  488   bool hasRightmostSelector = !hasLeftmostSelector;
 
  490   if (hasLeftmostSelector)
 
  492       bool doesInterestContainDigest = recognizeInterestWithDigest(interest, *startingPoint);
 
  493       bool isInPrefix = 
false;
 
  495       if (doesInterestContainDigest)
 
  497           isInPrefix = interest.getName().getPrefix(-1).isPrefixOf((*startingPoint)->getFullName());
 
  501           isInPrefix = interest.getName().isPrefixOf((*startingPoint)->getFullName());
 
  506           if (doesComplyWithSelectors(interest, *startingPoint, doesInterestContainDigest))
 
  508               return &(*startingPoint)->getData();
 
  514   SkipListLayer::iterator rightmost = startingPoint;
 
  515   if (startingPoint != (*m_skipList.begin())->
end())
 
  517       SkipListLayer::iterator rightmostCandidate = startingPoint;
 
  518       Name currentChildPrefix(
"");
 
  522           ++rightmostCandidate;
 
  524           bool isInBoundaries = (rightmostCandidate != (*m_skipList.begin())->
end());
 
  525           bool isInPrefix = 
false;
 
  526           bool doesInterestContainDigest = 
false;
 
  529               doesInterestContainDigest = recognizeInterestWithDigest(interest,
 
  530                                                                       *rightmostCandidate);
 
  532               if (doesInterestContainDigest)
 
  534                   isInPrefix = interest.getName().getPrefix(-1)
 
  535                                  .isPrefixOf((*rightmostCandidate)->getFullName());
 
  539                   isInPrefix = interest.getName().isPrefixOf((*rightmostCandidate)->getFullName());
 
  545               if (doesComplyWithSelectors(interest, *rightmostCandidate, doesInterestContainDigest))
 
  547                   if (hasLeftmostSelector)
 
  549                       return &(*rightmostCandidate)->getData();
 
  552                   if (hasRightmostSelector)
 
  554                       if (doesInterestContainDigest)
 
  558                           const Name& childPrefix = (*rightmostCandidate)->getFullName()
 
  559                                                       .getPrefix(interest.getName().size());
 
  562                           if (currentChildPrefix.empty() || (childPrefix != currentChildPrefix))
 
  564                               currentChildPrefix = childPrefix;
 
  565                               rightmost = rightmostCandidate;
 
  571                           const Name& childPrefix = (*rightmostCandidate)->getFullName()
 
  572                                                       .getPrefix(interest.getName().size() + 1);
 
  575                           if (currentChildPrefix.empty() || (childPrefix != currentChildPrefix))
 
  577                               currentChildPrefix = childPrefix;
 
  578                               rightmost = rightmostCandidate;
 
  589   if (rightmost != startingPoint)
 
  591       return &(*rightmost)->getData();
 
  594   if (hasRightmostSelector) 
 
  596       bool doesInterestContainDigest = recognizeInterestWithDigest(interest, *startingPoint);
 
  597       bool isInPrefix = 
false;
 
  599       if (doesInterestContainDigest)
 
  601           isInPrefix = interest.getName().getPrefix(-1).isPrefixOf((*startingPoint)->getFullName());
 
  605           isInPrefix = interest.getName().isPrefixOf((*startingPoint)->getFullName());
 
  610           if (doesComplyWithSelectors(interest, *startingPoint, doesInterestContainDigest))
 
  612               return &(*startingPoint)->getData();
 
  621 Cs::doesComplyWithSelectors(
const Interest& interest,
 
  622                             cs::skip_list::Entry* entry,
 
  623                             bool doesInterestContainDigest)
 const 
  633   if (doesInterestContainDigest)
 
  635       if (interest.getName().get(-1) != entry->getFullName().get(-1))
 
  642   if (!doesInterestContainDigest)
 
  644       if (interest.getMinSuffixComponents() >= 0)
 
  646           size_t minDataNameLength = interest.getName().size() + interest.getMinSuffixComponents();
 
  648           bool isSatisfied = (minDataNameLength <= entry->getFullName().size());
 
  656       if (interest.getMaxSuffixComponents() >= 0)
 
  658           size_t maxDataNameLength = interest.getName().size() + interest.getMaxSuffixComponents();
 
  660           bool isSatisfied = (maxDataNameLength >= entry->getFullName().size());
 
  669   if (interest.getMustBeFresh() && entry->getStaleTime() < time::steady_clock::now())
 
  675   if (!interest.getPublisherPublicKeyLocator().empty())
 
  677       if (entry->getData().getSignature().getType() == ndn::Signature::Sha256WithRsa)
 
  679           ndn::SignatureSha256WithRsa rsaSignature(entry->getData().getSignature());
 
  680           if (rsaSignature.getKeyLocator() != interest.getPublisherPublicKeyLocator())
 
  693   if (doesInterestContainDigest)
 
  695       const ndn::name::Component& lastComponent = entry->getFullName().get(-1);
 
  697       if (!lastComponent.empty())
 
  699           if (interest.getExclude().isExcluded(lastComponent))
 
  708       if (entry->getFullName().size() >= interest.getName().size() + 1)
 
  710           const ndn::name::Component& nextComponent = entry->getFullName()
 
  711                                                         .get(interest.getName().size());
 
  712           if (!nextComponent.empty())
 
  714               if (interest.getExclude().isExcluded(nextComponent))
 
  728 Cs::recognizeInterestWithDigest(
const Interest& interest, cs::skip_list::Entry* entry)
 const 
  732   if (interest.getMinSuffixComponents() <= 0 &&
 
  733       interest.getName().size() == (entry->getFullName().size()))
 
  735       const ndn::name::Component& last = interest.getName().get(-1);
 
  736       if (last.value_size() == ndn::crypto::SHA256_DIGEST_SIZE)
 
  750                 << 
"skipList size " << 
size());
 
  752   bool isIterated = 
false;
 
  754   SkipList::reverse_iterator topLayer = m_skipList.rbegin();
 
  755   SkipListLayer::iterator head = (*topLayer)->begin();
 
  757   if (!(*topLayer)->empty())
 
  760       int layer = m_skipList.size() - 1;
 
  761       for (SkipList::reverse_iterator rit = topLayer; rit != m_skipList.rend(); ++rit)
 
  765             head = (*rit)->begin();
 
  767           updateTable[layer] = head;
 
  769           if (head != (*rit)->end())
 
  772               if (!isIterated && ((*head)->getFullName() == exactName))
 
  776                   eraseFromSkipList(entryToDelete);
 
  778                   m_cleanupIndex.remove(entryToDelete);
 
  783                   SkipListLayer::iterator it = head;
 
  785                   while ((*it)->getFullName() < exactName)
 
  788                       updateTable[layer] = it;
 
  792                       if (it == (*rit)->end())
 
  799             head = (*head)->getIterators().find(layer - 1)->second; 
 
  809   head = updateTable[0];
 
  812   bool isCsEmpty = (
size() == 0);
 
  813   bool isInBoundaries = (head != (*m_skipList.begin())->
end());
 
  814   bool isNameIdentical = 
false;
 
  815   if (!isCsEmpty && isInBoundaries)
 
  818       isNameIdentical = (*head)->getFullName() == exactName;
 
  825       eraseFromSkipList(entryToDelete);
 
  827       m_cleanupIndex.remove(entryToDelete);
 
  832 Cs::printSkipList()
 const 
  836   int layer = m_skipList.size() - 1;
 
  837   for (SkipList::const_reverse_iterator rit = m_skipList.rbegin(); rit != m_skipList.rend(); ++rit)
 
  839       for (SkipListLayer::iterator it = (*rit)->begin(); it != (*rit)->end(); ++it)
 
  841           NFD_LOG_TRACE(
"Layer " << layer << 
" " << (*it)->getFullName());
 
static const double SKIPLIST_PROBABILITY
probability for an entry in layer N to appear also in layer N+1 
 
void erase(const Name &exactName)
deletes CS entry by the exact name 
 
bool evictItem()
removes one Data packet from Content Store based on replacement policy 
 
const_iterator begin() const 
returns an iterator pointing to the first CS entry 
 
std::list< cs::skip_list::Entry * > SkipListLayer
 
const_iterator end() const 
returns an iterator referring to the past-the-end CS entry 
 
const Data * find(const Interest &interest) const 
finds the best match Data for an Interest 
 
size_t getLimit() const 
returns maximum allowed size of Content Store (in packets) 
 
bool insert(const Data &data, bool isUnsolicited=false)
inserts a Data packet This method does not consider the payload of the Data packet. 
 
const Name & getFullName() const 
returns the full name (including implicit digest) of the Data packet stored in the CS entry ...
 
size_t size() const 
returns current size of Content Store measured in packets 
 
boost::random::mt19937 & getGlobalRng()
 
static const size_t SKIPLIST_MAX_LAYERS
Copyright (c) 2014, Regents of the University of California, Arizona Board of Regents, Colorado State University, University Pierre & Marie Curie, Sorbonne University, Washington University in St. 
 
#define NFD_LOG_INIT(name)
 
#define NFD_LOG_TRACE(expression)
 
represents an entry in a CS with skip list implementation 
 
void setLimit(size_t nMaxPackets)
sets maximum allowed size of Content Store (in packets) 
 
Cs(size_t nMaxPackets=10)