NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.3: NDN, CCN, CCNx, content centric networks
API Documentation
strategy-choice.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "strategy-choice.hpp"
27 #include "core/logger.hpp"
28 #include "fw/strategy.hpp"
29 #include "pit-entry.hpp"
30 #include "measurements-entry.hpp"
31 
32 namespace nfd {
33 namespace strategy_choice {
34 
35 using fw::Strategy;
36 
37 NFD_LOG_INIT("StrategyChoice");
38 
39 static inline bool
41 {
42  return nte.getStrategyChoiceEntry() != nullptr;
43 }
44 
45 StrategyChoice::StrategyChoice(NameTree& nameTree, unique_ptr<Strategy> defaultStrategy)
46  : m_nameTree(nameTree)
47  , m_nItems(0)
48 {
49  this->setDefaultStrategy(std::move(defaultStrategy));
50 }
51 
52 bool
53 StrategyChoice::hasStrategy(const Name& strategyName, bool isExact) const
54 {
55  if (isExact) {
56  return m_strategyInstances.count(strategyName) > 0;
57  }
58  else {
59  return this->getStrategy(strategyName) != nullptr;
60  }
61 }
62 
63 std::pair<bool, Strategy*>
64 StrategyChoice::install(unique_ptr<Strategy> strategy)
65 {
66  BOOST_ASSERT(strategy != nullptr);
67  Name strategyName = strategy->getName();
68  // copying Name, so that strategyName remains available even if strategy is deallocated
69 
70  bool isInserted = false;
72  std::tie(it, isInserted) = m_strategyInstances.emplace(strategyName, std::move(strategy));
73 
74  if (!isInserted) {
75  NFD_LOG_ERROR("install(" << strategyName << ") duplicate strategyName");
76  }
77  return std::make_pair(isInserted, it->second.get());
78 }
79 
80 Strategy*
81 StrategyChoice::getStrategy(const Name& strategyName) const
82 {
83  Strategy* candidate = nullptr;
84  for (auto it = m_strategyInstances.lower_bound(strategyName);
85  it != m_strategyInstances.end() && strategyName.isPrefixOf(it->first); ++it) {
86  switch (it->first.size() - strategyName.size()) {
87  case 0: // exact match
88  return it->second.get();
89  case 1: // unversioned strategyName matches versioned strategy
90  candidate = it->second.get();
91  break;
92  }
93  }
94  return candidate;
95 }
96 
97 bool
98 StrategyChoice::insert(const Name& prefix, const Name& strategyName)
99 {
100  Strategy* strategy = this->getStrategy(strategyName);
101  if (strategy == nullptr) {
102  NFD_LOG_ERROR("insert(" << prefix << "," << strategyName << ") strategy not installed");
103  return false;
104  }
105 
106  name_tree::Entry& nte = m_nameTree.lookup(prefix);
107  Entry* entry = nte.getStrategyChoiceEntry();
108  Strategy* oldStrategy = nullptr;
109  if (entry != nullptr) {
110  if (entry->getStrategy().getName() == strategy->getName()) {
111  NFD_LOG_TRACE("insert(" << prefix << ") not changing " << strategy->getName());
112  return true;
113  }
114  oldStrategy = &entry->getStrategy();
115  NFD_LOG_TRACE("insert(" << prefix << ") changing from " << oldStrategy->getName() <<
116  " to " << strategy->getName());
117  }
118 
119  if (entry == nullptr) {
120  oldStrategy = &this->findEffectiveStrategy(prefix);
121  auto newEntry = make_unique<Entry>(prefix);
122  entry = newEntry.get();
123  nte.setStrategyChoiceEntry(std::move(newEntry));
124  ++m_nItems;
125  NFD_LOG_TRACE("insert(" << prefix << ") new entry " << strategy->getName());
126  }
127 
128  this->changeStrategy(*entry, *oldStrategy, *strategy);
129  entry->setStrategy(*strategy);
130  return true;
131 }
132 
133 void
135 {
136  BOOST_ASSERT(prefix.size() > 0);
137 
138  name_tree::Entry* nte = m_nameTree.findExactMatch(prefix);
139  if (nte == nullptr) {
140  return;
141  }
142 
143  Entry* entry = nte->getStrategyChoiceEntry();
144  if (entry == nullptr) {
145  return;
146  }
147 
148  Strategy& oldStrategy = entry->getStrategy();
149 
150  Strategy& parentStrategy = this->findEffectiveStrategy(prefix.getPrefix(-1));
151  this->changeStrategy(*entry, oldStrategy, parentStrategy);
152 
153  nte->setStrategyChoiceEntry(nullptr);
154  m_nameTree.eraseIfEmpty(nte);
155  --m_nItems;
156 }
157 
158 std::pair<bool, Name>
159 StrategyChoice::get(const Name& prefix) const
160 {
161  name_tree::Entry* nte = m_nameTree.findExactMatch(prefix);
162  if (nte == nullptr) {
163  return {false, Name()};
164  }
165 
166  Entry* entry = nte->getStrategyChoiceEntry();
167  if (entry == nullptr) {
168  return {false, Name()};
169  }
170 
171  return {true, entry->getStrategy().getName()};
172 }
173 
174 template<typename K>
175 Strategy&
176 StrategyChoice::findEffectiveStrategyImpl(const K& key) const
177 {
179  BOOST_ASSERT(nte != nullptr);
180  return nte->getStrategyChoiceEntry()->getStrategy();
181 }
182 
183 Strategy&
185 {
186  return this->findEffectiveStrategyImpl(prefix);
187 }
188 
189 Strategy&
191 {
192  return this->findEffectiveStrategyImpl(pitEntry);
193 }
194 
195 Strategy&
197 {
198  return this->findEffectiveStrategyImpl(measurementsEntry);
199 }
200 
201 void
202 StrategyChoice::setDefaultStrategy(unique_ptr<Strategy> strategy)
203 {
204  bool isInstalled = false;
205  Strategy* instance = nullptr;
206  std::tie(isInstalled, instance) = this->install(std::move(strategy));
207  BOOST_ASSERT(isInstalled);
208 
209  auto entry = make_unique<Entry>(Name());
210  entry->setStrategy(*instance);
211 
212  // don't use .insert here, because it will invoke findEffectiveStrategy
213  // which expects an existing root entry
214  name_tree::Entry& nte = m_nameTree.lookup(Name());
215  nte.setStrategyChoiceEntry(std::move(entry));
216  ++m_nItems;
217  NFD_LOG_INFO("setDefaultStrategy " << instance->getName());
218 }
219 
220 static inline void
222 {
223  NFD_LOG_TRACE("clearStrategyInfo " << nte.getName());
224 
225  for (const shared_ptr<pit::Entry>& pitEntry : nte.getPitEntries()) {
226  pitEntry->clearStrategyInfo();
227  for (const pit::InRecord& inRecord : pitEntry->getInRecords()) {
228  const_cast<pit::InRecord&>(inRecord).clearStrategyInfo();
229  }
230  for (const pit::OutRecord& outRecord : pitEntry->getOutRecords()) {
231  const_cast<pit::OutRecord&>(outRecord).clearStrategyInfo();
232  }
233  }
234  if (nte.getMeasurementsEntry() != nullptr) {
236  }
237 }
238 
239 void
240 StrategyChoice::changeStrategy(Entry& entry, Strategy& oldStrategy, Strategy& newStrategy)
241 {
242  if (&oldStrategy == &newStrategy) {
243  return;
244  }
245 
246  NFD_LOG_INFO("changeStrategy(" << entry.getPrefix() << ")"
247  << " from " << oldStrategy.getName()
248  << " to " << newStrategy.getName());
249 
250  // reset StrategyInfo on a portion of NameTree,
251  // where entry's effective strategy is covered by the changing StrategyChoice entry
252  const name_tree::Entry* rootNte = m_nameTree.getEntry(entry);
253  BOOST_ASSERT(rootNte != nullptr);
254  auto&& ntChanged = m_nameTree.partialEnumerate(entry.getPrefix(),
255  [&rootNte] (const name_tree::Entry& nte) -> std::pair<bool, bool> {
256  if (&nte == rootNte) {
257  return {true, true};
258  }
259  if (nte.getStrategyChoiceEntry() != nullptr) {
260  return {false, false};
261  }
262  return {true, true};
263  });
264  for (const name_tree::Entry& nte : ntChanged) {
265  clearStrategyInfo(nte);
266  }
267 }
268 
270 StrategyChoice::getRange() const
271 {
272  return m_nameTree.fullEnumerate(&nteHasStrategyChoiceEntry) |
273  boost::adaptors::transformed(name_tree::GetTableEntry<Entry>(
275 }
276 
277 } // namespace strategy_choice
278 } // namespace nfd
void setStrategy(fw::Strategy &strategy)
PartialName getPrefix(ssize_t nComponents) const
Extract a prefix (PartialName) of the name, containing first nComponents components.
Definition: name.hpp:241
bool hasStrategy(const Name &strategyName, bool isExact=false) const
determines if a strategy is installed
static void clearStrategyInfo(const name_tree::Entry &nte)
const std::vector< shared_ptr< pit::Entry > > & getPitEntries() const
Entry * findExactMatch(const Name &name) const
exact match lookup
Definition: name-tree.cpp:148
contains information about an Interest from an incoming face
void erase(const Name &prefix)
make prefix to inherit strategy from its parent
std::pair< bool, Name > get(const Name &prefix) const
get strategy Name of prefix
const Name & getName() const
Definition: strategy.hpp:56
#define NFD_LOG_INFO(expression)
Definition: logger.hpp:56
std::pair< bool, fw::Strategy * > install(unique_ptr< fw::Strategy > strategy)
install a strategy
Entry * findLongestPrefixMatch(const Name &name, const EntrySelector &entrySelector=AnyEntry()) const
longest prefix matching
Definition: name-tree.cpp:155
represents a Measurements entry
Range partialEnumerate(const Name &prefix, const EntrySubTreeSelector &entrySubTreeSelector=AnyEntrySubTree()) const
enumerate all entries under a prefix
Definition: name-tree.cpp:242
Table::const_iterator iterator
Definition: cs-internal.hpp:41
measurements::Entry * getMeasurementsEntry() const
#define NFD_LOG_TRACE(expression)
Definition: logger.hpp:54
#define NFD_LOG_ERROR(expression)
Definition: logger.hpp:57
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:40
an Interest table entry
Definition: pit-entry.hpp:57
Entry & lookup(const Name &name)
find or insert an entry with specified name
Definition: name-tree.cpp:44
fw::Strategy & findEffectiveStrategy(const Name &prefix) const
get effective strategy for prefix
void clearStrategyInfo()
clear all StrategyInfo items
Name abstraction to represent an absolute name.
Definition: name.hpp:46
bool isPrefixOf(const Name &name) const
Check if the N components of this name are the same as the first N components of the given name...
Definition: name.cpp:308
represents a Strategy Choice entry
Range fullEnumerate(const EntrySelector &entrySelector=AnyEntry()) const
enumerate all entries
Definition: name-tree.cpp:236
size_t size() const
Get the number of components.
Definition: name.hpp:400
represents a forwarding strategy
Definition: strategy.hpp:38
bool insert(const Name &prefix, const Name &strategyName)
set strategy of prefix to be strategyName
size_t eraseIfEmpty(Entry *entry, bool canEraseAncestors=true)
delete the entry if it is empty
Definition: name-tree.cpp:121
boost::transformed_range< name_tree::GetTableEntry< Entry >, const name_tree::Range > Range
a common index structure for FIB, PIT, StrategyChoice, and Measurements
Definition: name-tree.hpp:36
fw::Strategy & getStrategy() const
contains information about an Interest toward an outgoing face
Entry * getEntry(const ENTRY &tableEntry) const
Definition: name-tree.hpp:64
strategy_choice::Entry * getStrategyChoiceEntry() const
#define NFD_LOG_INIT(name)
Definition: logger.hpp:34
a functor to get a table entry from a name tree entry
static bool nteHasStrategyChoiceEntry(const name_tree::Entry &nte)
const Name & getName() const
void setStrategyChoiceEntry(unique_ptr< strategy_choice::Entry > strategyChoiceEntry)
StrategyChoice(NameTree &nameTree, unique_ptr< fw::Strategy > defaultStrategy)
an entry in the name tree