NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.5: NDN, CCN, CCNx, content centric networks
API Documentation
cs.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014-2018, Regents of the University of California,
4  * Arizona Board of Regents,
5  * Colorado State University,
6  * University Pierre & Marie Curie, Sorbonne University,
7  * Washington University in St. Louis,
8  * Beijing Institute of Technology,
9  * The University of Memphis.
10  *
11  * This file is part of NFD (Named Data Networking Forwarding Daemon).
12  * See AUTHORS.md for complete list of NFD authors and contributors.
13  *
14  * NFD is free software: you can redistribute it and/or modify it under the terms
15  * of the GNU General Public License as published by the Free Software Foundation,
16  * either version 3 of the License, or (at your option) any later version.
17  *
18  * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20  * PURPOSE. See the GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License along with
23  * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24  */
25 
26 #include "cs.hpp"
27 #include "core/algorithm.hpp"
28 #include "core/logger.hpp"
29 
30 #include <ndn-cxx/lp/tags.hpp>
31 #include <ndn-cxx/util/concepts.hpp>
32 
33 namespace nfd {
34 namespace cs {
35 
37 
38 NFD_LOG_INIT("ContentStore");
39 
40 unique_ptr<Policy>
42 {
43  const std::string DEFAULT_POLICY = "priority_fifo";
44  return Policy::create(DEFAULT_POLICY);
45 }
46 
47 Cs::Cs(size_t nMaxPackets)
48  : m_shouldAdmit(true)
49  , m_shouldServe(true)
50 {
51  this->setPolicyImpl(makeDefaultPolicy());
52  m_policy->setLimit(nMaxPackets);
53 }
54 
55 void
56 Cs::insert(const Data& data, bool isUnsolicited)
57 {
58  if (!m_shouldAdmit || m_policy->getLimit() == 0) {
59  return;
60  }
61  NFD_LOG_DEBUG("insert " << data.getName());
62 
63  // recognize CachePolicy
64  shared_ptr<lp::CachePolicyTag> tag = data.getTag<lp::CachePolicyTag>();
65  if (tag != nullptr) {
66  lp::CachePolicyType policy = tag->get().getPolicy();
67  if (policy == lp::CachePolicyType::NO_CACHE) {
68  return;
69  }
70  }
71 
72  iterator it;
73  bool isNewEntry = false;
74  std::tie(it, isNewEntry) = m_table.emplace(data.shared_from_this(), isUnsolicited);
75  EntryImpl& entry = const_cast<EntryImpl&>(*it);
76 
77  entry.updateStaleTime();
78 
79  if (!isNewEntry) { // existing entry
80  // XXX This doesn't forbid unsolicited Data from refreshing a solicited entry.
81  if (entry.isUnsolicited() && !isUnsolicited) {
82  entry.unsetUnsolicited();
83  }
84 
85  m_policy->afterRefresh(it);
86  }
87  else {
88  m_policy->afterInsert(it);
89  }
90 }
91 
92 void
93 Cs::erase(const Name& prefix, size_t limit, const AfterEraseCallback& cb)
94 {
95  BOOST_ASSERT(static_cast<bool>(cb));
96 
97  iterator first = m_table.lower_bound(prefix);
98  iterator last = m_table.end();
99  if (prefix.size() > 0) {
100  last = m_table.lower_bound(prefix.getSuccessor());
101  }
102 
103  size_t nErased = 0;
104  while (first != last && nErased < limit) {
105  m_policy->beforeErase(first);
106  first = m_table.erase(first);
107  ++nErased;
108  }
109 
110  if (cb) {
111  cb(nErased);
112  }
113 }
114 
115 void
116 Cs::find(const Interest& interest,
117  const HitCallback& hitCallback,
118  const MissCallback& missCallback) const
119 {
120  BOOST_ASSERT(static_cast<bool>(hitCallback));
121  BOOST_ASSERT(static_cast<bool>(missCallback));
122 
123  if (!m_shouldServe || m_policy->getLimit() == 0) {
124  missCallback(interest);
125  return;
126  }
127  const Name& prefix = interest.getName();
128  bool isRightmost = interest.getChildSelector() == 1;
129  NFD_LOG_DEBUG("find " << prefix << (isRightmost ? " R" : " L"));
130 
131  iterator first = m_table.lower_bound(prefix);
132  iterator last = m_table.end();
133  if (prefix.size() > 0) {
134  last = m_table.lower_bound(prefix.getSuccessor());
135  }
136 
137  iterator match = last;
138  if (isRightmost) {
139  match = this->findRightmost(interest, first, last);
140  }
141  else {
142  match = this->findLeftmost(interest, first, last);
143  }
144 
145  if (match == last) {
146  NFD_LOG_DEBUG(" no-match");
147  missCallback(interest);
148  return;
149  }
150  NFD_LOG_DEBUG(" matching " << match->getName());
151  m_policy->beforeUse(match);
152  hitCallback(interest, match->getData());
153 }
154 
155 iterator
156 Cs::findLeftmost(const Interest& interest, iterator first, iterator last) const
157 {
158  return std::find_if(first, last, bind(&cs::EntryImpl::canSatisfy, _1, interest));
159 }
160 
161 iterator
162 Cs::findRightmost(const Interest& interest, iterator first, iterator last) const
163 {
164  // Each loop visits a sub-namespace under a prefix one component longer than Interest Name.
165  // If there is a match in that sub-namespace, the leftmost match is returned;
166  // otherwise, loop continues.
167 
168  size_t interestNameLength = interest.getName().size();
169  for (iterator right = last; right != first;) {
170  iterator prev = std::prev(right);
171 
172  // special case: [first,prev] have exact Names
173  if (prev->getName().size() == interestNameLength) {
174  NFD_LOG_TRACE(" find-among-exact " << prev->getName());
175  iterator matchExact = this->findRightmostAmongExact(interest, first, right);
176  return matchExact == right ? last : matchExact;
177  }
178 
179  Name prefix = prev->getName().getPrefix(interestNameLength + 1);
180  iterator left = m_table.lower_bound(prefix);
181 
182  // normal case: [left,right) are under one-component-longer prefix
183  NFD_LOG_TRACE(" find-under-prefix " << prefix);
184  iterator match = this->findLeftmost(interest, left, right);
185  if (match != right) {
186  return match;
187  }
188  right = left;
189  }
190  return last;
191 }
192 
193 iterator
194 Cs::findRightmostAmongExact(const Interest& interest, iterator first, iterator last) const
195 {
196  return find_last_if(first, last, bind(&EntryImpl::canSatisfy, _1, interest));
197 }
198 
199 void
200 Cs::dump()
201 {
202  NFD_LOG_DEBUG("dump table");
203  for (const EntryImpl& entry : m_table) {
204  NFD_LOG_TRACE(entry.getFullName());
205  }
206 }
207 
208 void
209 Cs::setPolicy(unique_ptr<Policy> policy)
210 {
211  BOOST_ASSERT(policy != nullptr);
212  BOOST_ASSERT(m_policy != nullptr);
213  size_t limit = m_policy->getLimit();
214  this->setPolicyImpl(std::move(policy));
215  m_policy->setLimit(limit);
216 }
217 
218 void
219 Cs::setPolicyImpl(unique_ptr<Policy> policy)
220 {
221  NFD_LOG_DEBUG("set-policy " << policy->getName());
222  m_policy = std::move(policy);
223  m_beforeEvictConnection = m_policy->beforeEvict.connect([this] (iterator it) {
224  m_table.erase(it);
225  });
226 
227  m_policy->setCs(this);
228  BOOST_ASSERT(m_policy->getCs() == this);
229 }
230 
231 void
232 Cs::enableAdmit(bool shouldAdmit)
233 {
234  if (m_shouldAdmit == shouldAdmit) {
235  return;
236  }
237  m_shouldAdmit = shouldAdmit;
238  NFD_LOG_INFO((shouldAdmit ? "Enabling" : "Disabling") << " Data admittance");
239 }
240 
241 void
242 Cs::enableServe(bool shouldServe)
243 {
244  if (m_shouldServe == shouldServe) {
245  return;
246  }
247  m_shouldServe = shouldServe;
248  NFD_LOG_INFO((shouldServe ? "Enabling" : "Disabling") << " Data serving");
249 }
250 
251 } // namespace cs
252 } // namespace nfd
std::function< void(size_t nErased)> AfterEraseCallback
Definition: cs.hpp:59
shared_ptr< T > getTag() const
get a tag item
Definition: tag-host.hpp:67
const Name & getName() const
Get name.
Definition: data.hpp:128
bool isUnsolicited() const
Definition: cs-entry.hpp:73
static unique_ptr< Policy > create(const std::string &policyName)
Definition: cs-policy.cpp:45
Name getSuccessor() const
Get the successor of a name.
Definition: name.cpp:242
bool shouldAdmit() const
get CS_ENABLE_ADMIT flag
Definition: cs.hpp:128
It find_last_if(It first, It last, Pred p)
Definition: algorithm.hpp:49
Represents an Interest packet.
Definition: interest.hpp:42
#define NFD_LOG_DEBUG(expression)
Definition: logger.hpp:55
bool shouldServe() const
get CS_ENABLE_SERVE flag
Definition: cs.hpp:143
void enableAdmit(bool shouldAdmit)
set CS_ENABLE_ADMIT flag
Definition: cs.cpp:232
#define NFD_LOG_INFO(expression)
Definition: logger.hpp:56
NDN_CXX_ASSERT_FORWARD_ITERATOR(Cs::const_iterator)
an Entry in ContentStore implementation
provides a tag type for simple types
Definition: tag.hpp:58
Table::const_iterator iterator
Definition: cs-internal.hpp:41
#define NFD_LOG_TRACE(expression)
Definition: logger.hpp:54
void insert(const Data &data, bool isUnsolicited=false)
inserts a Data packet
Definition: cs.cpp:56
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:40
void erase(const Name &prefix, size_t limit, const AfterEraseCallback &cb)
asynchronously erases entries under prefix
Definition: cs.cpp:93
boost::transform_iterator< EntryFromEntryImpl, iterator, const Entry & > const_iterator
ContentStore iterator (public API)
Definition: cs.hpp:168
void setPolicy(unique_ptr< Policy > policy)
change replacement policy
Definition: cs.cpp:209
Cs(size_t nMaxPackets=10)
Definition: cs.cpp:47
unique_ptr< Policy > makeDefaultPolicy()
Definition: cs.cpp:41
CachePolicyType
indicates the cache policy applied to a Data packet
Represents an absolute name.
Definition: name.hpp:42
void find(const Interest &interest, const HitCallback &hitCallback, const MissCallback &missCallback) const
finds the best matching Data packet
Definition: cs.cpp:116
size_t size() const
Get number of components.
Definition: name.hpp:154
void updateStaleTime()
refreshes stale time relative to current time
Definition: cs-entry.cpp:48
NDN_CXX_DEPRECATED int getChildSelector() const
Definition: interest.hpp:364
std::function< void(const Interest &, const Data &)> HitCallback
Definition: cs.hpp:70
const T & get() const
Definition: tag.hpp:86
#define NFD_LOG_INIT(name)
Definition: logger.hpp:34
Represents a Data packet.
Definition: data.hpp:35
std::function< void(const Interest &)> MissCallback
Definition: cs.hpp:71
bool canSatisfy(const Interest &interest) const
determines whether Interest can be satisified by the stored Data
Definition: cs-entry.cpp:55
void enableServe(bool shouldServe)
set CS_ENABLE_SERVE flag
Definition: cs.cpp:242
const Name & getName() const
Definition: interest.hpp:137