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 "measurements-entry.hpp"
28 #include "pit-entry.hpp"
29 #include "core/asserts.hpp"
30 #include "core/logger.hpp"
31 #include "fw/strategy.hpp"
32 
33 namespace nfd {
34 namespace strategy_choice {
35 
36 using fw::Strategy;
37 
39 
40 NFD_LOG_INIT("StrategyChoice");
41 
42 static inline bool
44 {
45  return nte.getStrategyChoiceEntry() != nullptr;
46 }
47 
49  : m_forwarder(forwarder)
50  , m_nameTree(m_forwarder.getNameTree())
51  , m_nItems(0)
52 {
53 }
54 
55 void
56 StrategyChoice::setDefaultStrategy(const Name& strategyName)
57 {
58  auto entry = make_unique<Entry>(Name());
59  entry->setStrategy(Strategy::create(strategyName, m_forwarder));
60  NFD_LOG_INFO("setDefaultStrategy " << entry->getStrategyInstanceName());
61 
62  // don't use .insert here, because it will invoke findEffectiveStrategy
63  // which expects an existing root entry
64  name_tree::Entry& nte = m_nameTree.lookup(Name());
65  nte.setStrategyChoiceEntry(std::move(entry));
66  ++m_nItems;
67 }
68 
70 StrategyChoice::insert(const Name& prefix, const Name& strategyName)
71 {
72  unique_ptr<Strategy> strategy;
73  try {
74  strategy = Strategy::create(strategyName, m_forwarder);
75  }
76  catch (const std::invalid_argument& e) {
77  NFD_LOG_ERROR("insert(" << prefix << "," << strategyName << ") cannot create strategy: " << e.what());
78  return InsertResult(InsertResult::EXCEPTION, e.what());
79  }
80 
81  if (strategy == nullptr) {
82  NFD_LOG_ERROR("insert(" << prefix << "," << strategyName << ") strategy not registered");
83  return InsertResult::NOT_REGISTERED;
84  }
85 
86  name_tree::Entry& nte = m_nameTree.lookup(prefix);
87  Entry* entry = nte.getStrategyChoiceEntry();
88  Strategy* oldStrategy = nullptr;
89  if (entry != nullptr) {
90  if (entry->getStrategyInstanceName() == strategy->getInstanceName()) {
91  NFD_LOG_TRACE("insert(" << prefix << ") not changing " << strategy->getInstanceName());
92  return InsertResult::OK;
93  }
94  oldStrategy = &entry->getStrategy();
95  NFD_LOG_TRACE("insert(" << prefix << ") changing from " << oldStrategy->getInstanceName() <<
96  " to " << strategy->getInstanceName());
97  }
98  else {
99  oldStrategy = &this->findEffectiveStrategy(prefix);
100  auto newEntry = make_unique<Entry>(prefix);
101  entry = newEntry.get();
102  nte.setStrategyChoiceEntry(std::move(newEntry));
103  ++m_nItems;
104  NFD_LOG_TRACE("insert(" << prefix << ") new entry " << strategy->getInstanceName());
105  }
106 
107  this->changeStrategy(*entry, *oldStrategy, *strategy);
108  entry->setStrategy(std::move(strategy));
109  return InsertResult::OK;
110 }
111 
112 StrategyChoice::InsertResult::InsertResult(Status status, const std::string& exceptionMessage)
113  : m_status(status)
114  , m_exceptionMessage(exceptionMessage)
115 {
116 }
117 
118 std::ostream&
119 operator<<(std::ostream& os, const StrategyChoice::InsertResult& res)
120 {
121  switch (res.m_status) {
122  case StrategyChoice::InsertResult::OK:
123  return os << "OK";
124  case StrategyChoice::InsertResult::NOT_REGISTERED:
125  return os << "Strategy not registered";
126  case StrategyChoice::InsertResult::EXCEPTION:
127  return os << "Error instantiating strategy: " << res.m_exceptionMessage;
128  }
129  return os;
130 }
131 
132 void
133 StrategyChoice::erase(const Name& prefix)
134 {
135  BOOST_ASSERT(prefix.size() > 0);
136 
137  name_tree::Entry* nte = m_nameTree.findExactMatch(prefix);
138  if (nte == nullptr) {
139  return;
140  }
141 
142  Entry* entry = nte->getStrategyChoiceEntry();
143  if (entry == nullptr) {
144  return;
145  }
146 
147  Strategy& oldStrategy = entry->getStrategy();
148 
149  Strategy& parentStrategy = this->findEffectiveStrategy(prefix.getPrefix(-1));
150  this->changeStrategy(*entry, oldStrategy, parentStrategy);
151 
152  nte->setStrategyChoiceEntry(nullptr);
153  m_nameTree.eraseIfEmpty(nte);
154  --m_nItems;
155 }
156 
157 std::pair<bool, Name>
158 StrategyChoice::get(const Name& prefix) const
159 {
160  name_tree::Entry* nte = m_nameTree.findExactMatch(prefix);
161  if (nte == nullptr) {
162  return {false, Name()};
163  }
164 
165  Entry* entry = nte->getStrategyChoiceEntry();
166  if (entry == nullptr) {
167  return {false, Name()};
168  }
169 
170  return {true, entry->getStrategyInstanceName()};
171 }
172 
173 template<typename K>
174 Strategy&
175 StrategyChoice::findEffectiveStrategyImpl(const K& key) const
176 {
177  const name_tree::Entry* nte = m_nameTree.findLongestPrefixMatch(key, &nteHasStrategyChoiceEntry);
178  BOOST_ASSERT(nte != nullptr);
179  return nte->getStrategyChoiceEntry()->getStrategy();
180 }
181 
182 Strategy&
183 StrategyChoice::findEffectiveStrategy(const Name& prefix) const
184 {
185  return this->findEffectiveStrategyImpl(prefix);
186 }
187 
188 Strategy&
190 {
191  return this->findEffectiveStrategyImpl(pitEntry);
192 }
193 
194 Strategy&
196 {
197  return this->findEffectiveStrategyImpl(measurementsEntry);
198 }
199 
200 static inline void
202 {
203  NFD_LOG_TRACE("clearStrategyInfo " << nte.getName());
204 
205  for (const shared_ptr<pit::Entry>& pitEntry : nte.getPitEntries()) {
206  pitEntry->clearStrategyInfo();
207  for (const pit::InRecord& inRecord : pitEntry->getInRecords()) {
208  const_cast<pit::InRecord&>(inRecord).clearStrategyInfo();
209  }
210  for (const pit::OutRecord& outRecord : pitEntry->getOutRecords()) {
211  const_cast<pit::OutRecord&>(outRecord).clearStrategyInfo();
212  }
213  }
214  if (nte.getMeasurementsEntry() != nullptr) {
216  }
217 }
218 
219 void
220 StrategyChoice::changeStrategy(Entry& entry, Strategy& oldStrategy, Strategy& newStrategy)
221 {
222  const Name& oldInstanceName = oldStrategy.getInstanceName();
223  const Name& newInstanceName = newStrategy.getInstanceName();
224  if (Strategy::areSameType(oldInstanceName, newInstanceName)) {
225  // same Strategy subclass type: no need to clear StrategyInfo
226  NFD_LOG_INFO("changeStrategy(" << entry.getPrefix() << ") "
227  << oldInstanceName << " -> " << newInstanceName
228  << " same-type");
229  return;
230  }
231 
232  NFD_LOG_INFO("changeStrategy(" << entry.getPrefix() << ") "
233  << oldInstanceName << " -> " << newInstanceName);
234 
235  // reset StrategyInfo on a portion of NameTree,
236  // where entry's effective strategy is covered by the changing StrategyChoice entry
237  const name_tree::Entry* rootNte = m_nameTree.getEntry(entry);
238  BOOST_ASSERT(rootNte != nullptr);
239  auto&& ntChanged = m_nameTree.partialEnumerate(entry.getPrefix(),
240  [&rootNte] (const name_tree::Entry& nte) -> std::pair<bool, bool> {
241  if (&nte == rootNte) {
242  return {true, true};
243  }
244  if (nte.getStrategyChoiceEntry() != nullptr) {
245  return {false, false};
246  }
247  return {true, true};
248  });
249  for (const name_tree::Entry& nte : ntChanged) {
250  clearStrategyInfo(nte);
251  }
252 }
253 
255 StrategyChoice::getRange() const
256 {
257  return m_nameTree.fullEnumerate(&nteHasStrategyChoiceEntry) |
258  boost::adaptors::transformed(name_tree::GetTableEntry<Entry>(
260 }
261 
262 } // namespace strategy_choice
263 } // namespace nfd
fw::Strategy & getStrategy() const
main class of NFD
Definition: forwarder.hpp:52
std::pair< bool, Name > get(const Name &prefix) const
get strategy Name of prefix
static void clearStrategyInfo(const name_tree::Entry &nte)
represents a Measurements entry
InsertResult insert(const Name &prefix, const Name &strategyName)
set strategy of prefix to be strategyName
contains information about an Interest toward an outgoing face
strategy_choice::Entry * getStrategyChoiceEntry() const
#define NFD_LOG_ERROR(expression)
Definition: logger.hpp:164
boost::transformed_range< name_tree::GetTableEntry< Entry >, const name_tree::Range > Range
const std::vector< shared_ptr< pit::Entry > > & getPitEntries() const
void clearStrategyInfo()
clear all StrategyInfo items
std::ostream & operator<<(std::ostream &os, const StrategyChoice::InsertResult &res)
boost::range_iterator< Range >::type const_iterator
void setStrategyChoiceEntry(unique_ptr< strategy_choice::Entry > strategyChoiceEntry)
an Interest table entry
Definition: pit-entry.hpp:57
#define NFD_LOG_INFO(expression)
Definition: logger.hpp:162
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents...
contains information about an Interest from an incoming face
void setDefaultStrategy(const Name &strategyName)
set the default strategy
NFD_ASSERT_FORWARD_ITERATOR(StrategyChoice::const_iterator)
const Name & getStrategyInstanceName() const
an entry in the name tree
represents a Strategy Choice entry
measurements::Entry * getMeasurementsEntry() const
#define NFD_LOG_INIT(name)
Definition: logger.hpp:122
#define NFD_LOG_TRACE(expression)
Definition: logger.hpp:160
fw::Strategy & findEffectiveStrategy(const Name &prefix) const
get effective strategy for prefix
const Name & getName() const
static bool nteHasStrategyChoiceEntry(const name_tree::Entry &nte)
void setStrategy(unique_ptr< fw::Strategy > strategy)
void erase(const Name &prefix)
make prefix to inherit strategy from its parent