cs.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "cs.hpp"
28 #include "core/logger.hpp"
29 #include "core/algorithm.hpp"
30 #include <ndn-cxx/lp/tags.hpp>
31 
32 NFD_LOG_INIT("ContentStore");
33 
34 namespace nfd {
35 namespace cs {
36 
37 // http://en.cppreference.com/w/cpp/concept/ForwardIterator
38 BOOST_CONCEPT_ASSERT((boost::ForwardIterator<Cs::const_iterator>));
39 // boost::ForwardIterator follows SGI standard http://www.sgi.com/tech/stl/ForwardIterator.html,
40 // which doesn't require DefaultConstructible
41 #ifdef HAVE_IS_DEFAULT_CONSTRUCTIBLE
42 static_assert(std::is_default_constructible<Cs::const_iterator>::value,
43  "Cs::const_iterator must be default-constructible");
44 #else
45 BOOST_CONCEPT_ASSERT((boost::DefaultConstructible<Cs::const_iterator>));
46 #endif // HAVE_IS_DEFAULT_CONSTRUCTIBLE
47 
48 unique_ptr<Policy>
50 {
51  return make_unique<PriorityFifoPolicy>();
52 }
53 
54 Cs::Cs(size_t nMaxPackets, unique_ptr<Policy> policy)
55 {
56  this->setPolicyImpl(policy);
57  m_policy->setLimit(nMaxPackets);
58 }
59 
60 void
61 Cs::setLimit(size_t nMaxPackets)
62 {
63  m_policy->setLimit(nMaxPackets);
64 }
65 
66 size_t
67 Cs::getLimit() const
68 {
69  return m_policy->getLimit();
70 }
71 
72 void
73 Cs::setPolicy(unique_ptr<Policy> policy)
74 {
75  BOOST_ASSERT(policy != nullptr);
76  BOOST_ASSERT(m_policy != nullptr);
77  size_t limit = m_policy->getLimit();
78  this->setPolicyImpl(policy);
79  m_policy->setLimit(limit);
80 }
81 
82 void
83 Cs::insert(const Data& data, bool isUnsolicited)
84 {
85  NFD_LOG_DEBUG("insert " << data.getName());
86 
87  if (m_policy->getLimit() == 0) {
88  // shortcut for disabled CS
89  return;
90  }
91 
92  // recognize CachePolicy
93  shared_ptr<lp::CachePolicyTag> tag = data.getTag<lp::CachePolicyTag>();
94  if (tag != nullptr) {
95  lp::CachePolicyType policy = tag->get().getPolicy();
96  if (policy == lp::CachePolicyType::NO_CACHE) {
97  return;
98  }
99  }
100 
101  bool isNewEntry = false;
102  iterator it;
103  // use .insert because gcc46 does not support .emplace
104  std::tie(it, isNewEntry) = m_table.insert(EntryImpl(data.shared_from_this(), isUnsolicited));
105  EntryImpl& entry = const_cast<EntryImpl&>(*it);
106 
107  entry.updateStaleTime();
108 
109  if (!isNewEntry) { // existing entry
110  // XXX This doesn't forbid unsolicited Data from refreshing a solicited entry.
111  if (entry.isUnsolicited() && !isUnsolicited) {
112  entry.unsetUnsolicited();
113  }
114 
115  m_policy->afterRefresh(it);
116  }
117  else {
118  m_policy->afterInsert(it);
119  }
120 }
121 
122 void
123 Cs::find(const Interest& interest,
124  const HitCallback& hitCallback,
125  const MissCallback& missCallback) const
126 {
127  BOOST_ASSERT(static_cast<bool>(hitCallback));
128  BOOST_ASSERT(static_cast<bool>(missCallback));
129 
130  const Name& prefix = interest.getName();
131  bool isRightmost = interest.getChildSelector() == 1;
132  NFD_LOG_DEBUG("find " << prefix << (isRightmost ? " R" : " L"));
133 
134  iterator first = m_table.lower_bound(prefix);
135  iterator last = m_table.end();
136  if (prefix.size() > 0) {
137  last = m_table.lower_bound(prefix.getSuccessor());
138  }
139 
140  iterator match = last;
141  if (isRightmost) {
142  match = this->findRightmost(interest, first, last);
143  }
144  else {
145  match = this->findLeftmost(interest, first, last);
146  }
147 
148  if (match == last) {
149  NFD_LOG_DEBUG(" no-match");
150  missCallback(interest);
151  return;
152  }
153  NFD_LOG_DEBUG(" matching " << match->getName());
154  m_policy->beforeUse(match);
155  hitCallback(interest, match->getData());
156 }
157 
158 iterator
159 Cs::findLeftmost(const Interest& interest, iterator first, iterator last) const
160 {
161  return std::find_if(first, last, bind(&cs::EntryImpl::canSatisfy, _1, interest));
162 }
163 
164 iterator
165 Cs::findRightmost(const Interest& interest, iterator first, iterator last) const
166 {
167  // Each loop visits a sub-namespace under a prefix one component longer than Interest Name.
168  // If there is a match in that sub-namespace, the leftmost match is returned;
169  // otherwise, loop continues.
170 
171  size_t interestNameLength = interest.getName().size();
172  for (iterator right = last; right != first;) {
173  iterator prev = std::prev(right);
174 
175  // special case: [first,prev] have exact Names
176  if (prev->getName().size() == interestNameLength) {
177  NFD_LOG_TRACE(" find-among-exact " << prev->getName());
178  iterator matchExact = this->findRightmostAmongExact(interest, first, right);
179  return matchExact == right ? last : matchExact;
180  }
181 
182  Name prefix = prev->getName().getPrefix(interestNameLength + 1);
183  iterator left = m_table.lower_bound(prefix);
184 
185  // normal case: [left,right) are under one-component-longer prefix
186  NFD_LOG_TRACE(" find-under-prefix " << prefix);
187  iterator match = this->findLeftmost(interest, left, right);
188  if (match != right) {
189  return match;
190  }
191  right = left;
192  }
193  return last;
194 }
195 
196 iterator
197 Cs::findRightmostAmongExact(const Interest& interest, iterator first, iterator last) const
198 {
199  return find_last_if(first, last, bind(&EntryImpl::canSatisfy, _1, interest));
200 }
201 
202 void
203 Cs::setPolicyImpl(unique_ptr<Policy>& policy)
204 {
205  m_policy = std::move(policy);
206  m_beforeEvictConnection = m_policy->beforeEvict.connect([this] (iterator it) {
207  m_table.erase(it);
208  });
209 
210  m_policy->setCs(this);
211  BOOST_ASSERT(m_policy->getCs() == this);
212 }
213 
214 void
215 Cs::dump()
216 {
217  NFD_LOG_DEBUG("dump table");
218  for (const EntryImpl& entry : m_table) {
219  NFD_LOG_TRACE(entry.getFullName());
220  }
221 }
222 
223 } // namespace cs
224 } // namespace nfd
size_t getLimit() const
Definition: cs.cpp:67
void updateStaleTime()
refreshes stale time relative to current time
Definition: cs-entry.cpp:48
#define NFD_LOG_DEBUG(expression)
Definition: logger.hpp:161
std::function< void(const Interest &, const Data &data)> HitCallback
Definition: cs.hpp:76
It find_last_if(It first, It last, Pred p)
finds the last element satisfying a predicate
Definition: algorithm.hpp:49
Copyright (c) 2014-2016, Regents of the University of California, Arizona Board of Regents...
Table::const_iterator iterator
Definition: cs-internal.hpp:41
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents...
Definition: algorithm.hpp:32
void insert(const Data &data, bool isUnsolicited=false)
inserts a Data packet
Definition: cs.cpp:83
unique_ptr< Policy > makeDefaultPolicy()
Definition: cs.cpp:49
void setLimit(size_t nMaxPackets)
changes capacity (in number of packets)
Definition: cs.cpp:61
void setPolicy(unique_ptr< Policy > policy)
changes cs replacement policy
Definition: cs.cpp:73
std::function< void(const Interest &)> MissCallback
Definition: cs.hpp:77
an Entry in ContentStore implementation
void unsetUnsolicited()
#define NFD_LOG_INIT(name)
Definition: logger.hpp:122
bool isUnsolicited() const
Definition: cs-entry.hpp:73
#define NFD_LOG_TRACE(expression)
Definition: logger.hpp:160
bool canSatisfy(const Interest &interest) const
determines whether Interest can be satisified by the stored Data
Definition: cs-entry.cpp:60
void find(const Interest &interest, const HitCallback &hitCallback, const MissCallback &missCallback) const
finds the best matching Data packet
Definition: cs.cpp:123
Cs(size_t nMaxPackets=10, unique_ptr< Policy > policy=makeDefaultPolicy())
Definition: cs.cpp:54