blob: a8b32d7ca98c576939bd07d1e3549c0d7603ddae [file] [log] [blame]
Junxiao Shibb5105f2014-03-03 12:06:45 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shib184e532016-05-26 18:09:57 +00003 * Copyright (c) 2014-2016, 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.
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
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/>.
Junxiao Shiee5a4442014-07-27 17:13:43 -070024 */
Junxiao Shibb5105f2014-03-03 12:06:45 -070025
26#include "strategy-choice.hpp"
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060027#include "core/logger.hpp"
Junxiao Shibb5105f2014-03-03 12:06:45 -070028#include "fw/strategy.hpp"
29#include "pit-entry.hpp"
Junxiao Shi7bb01512014-03-05 21:34:09 -070030#include "measurements-entry.hpp"
Junxiao Shibb5105f2014-03-03 12:06:45 -070031
32namespace nfd {
Junxiao Shiff10da62016-07-13 17:57:43 +000033namespace strategy_choice {
Junxiao Shibb5105f2014-03-03 12:06:45 -070034
Junxiao Shibb5105f2014-03-03 12:06:45 -070035using fw::Strategy;
36
37NFD_LOG_INIT("StrategyChoice");
38
Junxiao Shia49a1ab2016-07-15 18:24:36 +000039StrategyChoice::StrategyChoice(NameTree& nameTree, unique_ptr<Strategy> defaultStrategy)
Junxiao Shibb5105f2014-03-03 12:06:45 -070040 : m_nameTree(nameTree)
Junxiao Shib5888d22014-05-26 07:35:22 -070041 , m_nItems(0)
Junxiao Shibb5105f2014-03-03 12:06:45 -070042{
Junxiao Shia49a1ab2016-07-15 18:24:36 +000043 this->setDefaultStrategy(std::move(defaultStrategy));
Junxiao Shibb5105f2014-03-03 12:06:45 -070044}
45
46bool
Junxiao Shie93d6a32014-09-07 16:13:22 -070047StrategyChoice::hasStrategy(const Name& strategyName, bool isExact) const
Junxiao Shibb5105f2014-03-03 12:06:45 -070048{
Junxiao Shie93d6a32014-09-07 16:13:22 -070049 if (isExact) {
50 return m_strategyInstances.count(strategyName) > 0;
51 }
52 else {
Junxiao Shib184e532016-05-26 18:09:57 +000053 return this->getStrategy(strategyName) != nullptr;
Junxiao Shie93d6a32014-09-07 16:13:22 -070054 }
Junxiao Shibb5105f2014-03-03 12:06:45 -070055}
56
Junxiao Shia49a1ab2016-07-15 18:24:36 +000057std::pair<bool, Strategy*>
58StrategyChoice::install(unique_ptr<Strategy> strategy)
Junxiao Shibb5105f2014-03-03 12:06:45 -070059{
Junxiao Shib184e532016-05-26 18:09:57 +000060 BOOST_ASSERT(strategy != nullptr);
Junxiao Shia49a1ab2016-07-15 18:24:36 +000061 Name strategyName = strategy->getName();
62 // copying Name, so that strategyName remains available even if strategy is deallocated
Junxiao Shibb5105f2014-03-03 12:06:45 -070063
Junxiao Shia49a1ab2016-07-15 18:24:36 +000064 bool isInserted = false;
65 StrategyInstanceTable::iterator it;
66 std::tie(it, isInserted) = m_strategyInstances.emplace(strategyName, std::move(strategy));
67
68 if (!isInserted) {
Junxiao Shibb5105f2014-03-03 12:06:45 -070069 NFD_LOG_ERROR("install(" << strategyName << ") duplicate strategyName");
Junxiao Shibb5105f2014-03-03 12:06:45 -070070 }
Junxiao Shia49a1ab2016-07-15 18:24:36 +000071 return std::make_pair(isInserted, it->second.get());
Junxiao Shibb5105f2014-03-03 12:06:45 -070072}
73
Junxiao Shia49a1ab2016-07-15 18:24:36 +000074Strategy*
Junxiao Shie93d6a32014-09-07 16:13:22 -070075StrategyChoice::getStrategy(const Name& strategyName) const
76{
Junxiao Shia49a1ab2016-07-15 18:24:36 +000077 Strategy* candidate = nullptr;
Junxiao Shi838c4f12014-11-03 18:55:24 -070078 for (auto it = m_strategyInstances.lower_bound(strategyName);
Junxiao Shie93d6a32014-09-07 16:13:22 -070079 it != m_strategyInstances.end() && strategyName.isPrefixOf(it->first); ++it) {
80 switch (it->first.size() - strategyName.size()) {
81 case 0: // exact match
Junxiao Shi838c4f12014-11-03 18:55:24 -070082 return it->second.get();
Junxiao Shie93d6a32014-09-07 16:13:22 -070083 case 1: // unversioned strategyName matches versioned strategy
Junxiao Shi838c4f12014-11-03 18:55:24 -070084 candidate = it->second.get();
Junxiao Shie93d6a32014-09-07 16:13:22 -070085 break;
86 }
87 }
88 return candidate;
89}
90
Junxiao Shibb5105f2014-03-03 12:06:45 -070091bool
92StrategyChoice::insert(const Name& prefix, const Name& strategyName)
93{
Junxiao Shi838c4f12014-11-03 18:55:24 -070094 Strategy* strategy = this->getStrategy(strategyName);
95 if (strategy == nullptr) {
Junxiao Shibb5105f2014-03-03 12:06:45 -070096 NFD_LOG_ERROR("insert(" << prefix << "," << strategyName << ") strategy not installed");
97 return false;
98 }
99
Junxiao Shi838c4f12014-11-03 18:55:24 -0700100 shared_ptr<name_tree::Entry> nte = m_nameTree.lookup(prefix);
Junxiao Shiff10da62016-07-13 17:57:43 +0000101 Entry* entry = nte->getStrategyChoiceEntry();
Junxiao Shi838c4f12014-11-03 18:55:24 -0700102 Strategy* oldStrategy = nullptr;
Junxiao Shib184e532016-05-26 18:09:57 +0000103 if (entry != nullptr) {
Junxiao Shie93d6a32014-09-07 16:13:22 -0700104 if (entry->getStrategy().getName() == strategy->getName()) {
105 NFD_LOG_TRACE("insert(" << prefix << ") not changing " << strategy->getName());
106 return true;
107 }
Junxiao Shi838c4f12014-11-03 18:55:24 -0700108 oldStrategy = &entry->getStrategy();
Junxiao Shie93d6a32014-09-07 16:13:22 -0700109 NFD_LOG_TRACE("insert(" << prefix << ") changing from " << oldStrategy->getName() <<
110 " to " << strategy->getName());
111 }
112
Junxiao Shib184e532016-05-26 18:09:57 +0000113 if (entry == nullptr) {
Junxiao Shi838c4f12014-11-03 18:55:24 -0700114 oldStrategy = &this->findEffectiveStrategy(prefix);
Junxiao Shiff10da62016-07-13 17:57:43 +0000115 auto newEntry = make_unique<Entry>(prefix);
116 entry = newEntry.get();
117 nte->setStrategyChoiceEntry(std::move(newEntry));
Junxiao Shibb5105f2014-03-03 12:06:45 -0700118 ++m_nItems;
Junxiao Shie93d6a32014-09-07 16:13:22 -0700119 NFD_LOG_TRACE("insert(" << prefix << ") new entry " << strategy->getName());
Junxiao Shibb5105f2014-03-03 12:06:45 -0700120 }
121
Junxiao Shi838c4f12014-11-03 18:55:24 -0700122 this->changeStrategy(*entry, *oldStrategy, *strategy);
123 entry->setStrategy(*strategy);
Junxiao Shibb5105f2014-03-03 12:06:45 -0700124 return true;
125}
126
127void
128StrategyChoice::erase(const Name& prefix)
129{
130 BOOST_ASSERT(prefix.size() > 0);
131
Junxiao Shi838c4f12014-11-03 18:55:24 -0700132 shared_ptr<name_tree::Entry> nte = m_nameTree.findExactMatch(prefix);
Junxiao Shib184e532016-05-26 18:09:57 +0000133 if (nte == nullptr) {
Junxiao Shibb5105f2014-03-03 12:06:45 -0700134 return;
135 }
136
Junxiao Shiff10da62016-07-13 17:57:43 +0000137 Entry* entry = nte->getStrategyChoiceEntry();
Junxiao Shib184e532016-05-26 18:09:57 +0000138 if (entry == nullptr) {
Junxiao Shibb5105f2014-03-03 12:06:45 -0700139 return;
140 }
141
142 Strategy& oldStrategy = entry->getStrategy();
Junxiao Shie349ea12014-03-12 01:32:42 -0700143
144 Strategy& parentStrategy = this->findEffectiveStrategy(prefix.getPrefix(-1));
Junxiao Shi838c4f12014-11-03 18:55:24 -0700145 this->changeStrategy(*entry, oldStrategy, parentStrategy);
Junxiao Shie349ea12014-03-12 01:32:42 -0700146
Junxiao Shiff10da62016-07-13 17:57:43 +0000147 nte->setStrategyChoiceEntry(nullptr);
Junxiao Shie3cf2852016-08-09 03:50:56 +0000148 m_nameTree.eraseIfEmpty(nte.get());
Junxiao Shibb5105f2014-03-03 12:06:45 -0700149 --m_nItems;
Junxiao Shibb5105f2014-03-03 12:06:45 -0700150}
151
Junxiao Shi838c4f12014-11-03 18:55:24 -0700152std::pair<bool, Name>
Junxiao Shibb5105f2014-03-03 12:06:45 -0700153StrategyChoice::get(const Name& prefix) const
154{
Junxiao Shi838c4f12014-11-03 18:55:24 -0700155 shared_ptr<name_tree::Entry> nte = m_nameTree.findExactMatch(prefix);
Junxiao Shib184e532016-05-26 18:09:57 +0000156 if (nte == nullptr) {
Junxiao Shiff10da62016-07-13 17:57:43 +0000157 return {false, Name()};
Junxiao Shibb5105f2014-03-03 12:06:45 -0700158 }
159
Junxiao Shiff10da62016-07-13 17:57:43 +0000160 Entry* entry = nte->getStrategyChoiceEntry();
Junxiao Shib184e532016-05-26 18:09:57 +0000161 if (entry == nullptr) {
Junxiao Shiff10da62016-07-13 17:57:43 +0000162 return {false, Name()};
Junxiao Shibb5105f2014-03-03 12:06:45 -0700163 }
164
Junxiao Shiff10da62016-07-13 17:57:43 +0000165 return {true, entry->getStrategy().getName()};
Junxiao Shibb5105f2014-03-03 12:06:45 -0700166}
167
168Strategy&
169StrategyChoice::findEffectiveStrategy(const Name& prefix) const
170{
Junxiao Shi838c4f12014-11-03 18:55:24 -0700171 shared_ptr<name_tree::Entry> nte = m_nameTree.findLongestPrefixMatch(prefix,
Junxiao Shiff10da62016-07-13 17:57:43 +0000172 [] (const name_tree::Entry& entry) { return entry.getStrategyChoiceEntry() != nullptr; });
Junxiao Shi838c4f12014-11-03 18:55:24 -0700173
Junxiao Shib184e532016-05-26 18:09:57 +0000174 BOOST_ASSERT(nte != nullptr);
Junxiao Shi838c4f12014-11-03 18:55:24 -0700175 return nte->getStrategyChoiceEntry()->getStrategy();
Junxiao Shibb5105f2014-03-03 12:06:45 -0700176}
177
178Strategy&
Junxiao Shi838c4f12014-11-03 18:55:24 -0700179StrategyChoice::findEffectiveStrategy(shared_ptr<name_tree::Entry> nte) const
HangZhangcb4fc832014-03-11 16:57:11 +0800180{
Junxiao Shiff10da62016-07-13 17:57:43 +0000181 Entry* entry = nte->getStrategyChoiceEntry();
Junxiao Shib184e532016-05-26 18:09:57 +0000182 if (entry != nullptr)
HangZhangcb4fc832014-03-11 16:57:11 +0800183 return entry->getStrategy();
Junxiao Shi838c4f12014-11-03 18:55:24 -0700184
185 nte = m_nameTree.findLongestPrefixMatch(nte,
Junxiao Shiff10da62016-07-13 17:57:43 +0000186 [] (const name_tree::Entry& entry) { return entry.getStrategyChoiceEntry() != nullptr; });
Junxiao Shi838c4f12014-11-03 18:55:24 -0700187
Junxiao Shib184e532016-05-26 18:09:57 +0000188 BOOST_ASSERT(nte != nullptr);
Junxiao Shi838c4f12014-11-03 18:55:24 -0700189 return nte->getStrategyChoiceEntry()->getStrategy();
HangZhangcb4fc832014-03-11 16:57:11 +0800190}
191
192Strategy&
Junxiao Shibb5105f2014-03-03 12:06:45 -0700193StrategyChoice::findEffectiveStrategy(const pit::Entry& pitEntry) const
194{
Junxiao Shib184e532016-05-26 18:09:57 +0000195 shared_ptr<name_tree::Entry> nte = m_nameTree.lookup(pitEntry);
196 BOOST_ASSERT(nte != nullptr);
HangZhangcb4fc832014-03-11 16:57:11 +0800197
Junxiao Shi838c4f12014-11-03 18:55:24 -0700198 return this->findEffectiveStrategy(nte);
Junxiao Shibb5105f2014-03-03 12:06:45 -0700199}
200
Junxiao Shi7bb01512014-03-05 21:34:09 -0700201Strategy&
202StrategyChoice::findEffectiveStrategy(const measurements::Entry& measurementsEntry) const
203{
Junxiao Shib184e532016-05-26 18:09:57 +0000204 shared_ptr<name_tree::Entry> nte = m_nameTree.lookup(measurementsEntry);
205 BOOST_ASSERT(nte != nullptr);
HangZhangcb4fc832014-03-11 16:57:11 +0800206
Junxiao Shi838c4f12014-11-03 18:55:24 -0700207 return this->findEffectiveStrategy(nte);
Junxiao Shi7bb01512014-03-05 21:34:09 -0700208}
209
Junxiao Shibb5105f2014-03-03 12:06:45 -0700210void
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000211StrategyChoice::setDefaultStrategy(unique_ptr<Strategy> strategy)
Junxiao Shibb5105f2014-03-03 12:06:45 -0700212{
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000213 bool isInstalled = false;
214 Strategy* instance = nullptr;
215 std::tie(isInstalled, instance) = this->install(std::move(strategy));
216 BOOST_ASSERT(isInstalled);
Junxiao Shibb5105f2014-03-03 12:06:45 -0700217
Junxiao Shiff10da62016-07-13 17:57:43 +0000218 auto entry = make_unique<Entry>(Name());
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000219 entry->setStrategy(*instance);
Junxiao Shiff10da62016-07-13 17:57:43 +0000220
Junxiao Shibb5105f2014-03-03 12:06:45 -0700221 // don't use .insert here, because it will invoke findEffectiveStrategy
222 // which expects an existing root entry
Junxiao Shi838c4f12014-11-03 18:55:24 -0700223 shared_ptr<name_tree::Entry> nte = m_nameTree.lookup(Name());
Junxiao Shiff10da62016-07-13 17:57:43 +0000224 nte->setStrategyChoiceEntry(std::move(entry));
Junxiao Shibb5105f2014-03-03 12:06:45 -0700225 ++m_nItems;
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000226 NFD_LOG_INFO("setDefaultStrategy " << instance->getName());
Junxiao Shibb5105f2014-03-03 12:06:45 -0700227}
228
Junxiao Shi838c4f12014-11-03 18:55:24 -0700229static inline void
230clearStrategyInfo(const name_tree::Entry& nte)
Junxiao Shie349ea12014-03-12 01:32:42 -0700231{
Junxiao Shie3cf2852016-08-09 03:50:56 +0000232 NFD_LOG_TRACE("clearStrategyInfo " << nte.getName());
Junxiao Shi838c4f12014-11-03 18:55:24 -0700233
234 for (const shared_ptr<pit::Entry>& pitEntry : nte.getPitEntries()) {
235 pitEntry->clearStrategyInfo();
236 for (const pit::InRecord& inRecord : pitEntry->getInRecords()) {
237 const_cast<pit::InRecord&>(inRecord).clearStrategyInfo();
238 }
239 for (const pit::OutRecord& outRecord : pitEntry->getOutRecords()) {
240 const_cast<pit::OutRecord&>(outRecord).clearStrategyInfo();
241 }
Junxiao Shie349ea12014-03-12 01:32:42 -0700242 }
Junxiao Shib184e532016-05-26 18:09:57 +0000243 if (nte.getMeasurementsEntry() != nullptr) {
Junxiao Shi838c4f12014-11-03 18:55:24 -0700244 nte.getMeasurementsEntry()->clearStrategyInfo();
Junxiao Shie349ea12014-03-12 01:32:42 -0700245 }
246}
247
Junxiao Shibb5105f2014-03-03 12:06:45 -0700248void
Junxiao Shia49a1ab2016-07-15 18:24:36 +0000249StrategyChoice::changeStrategy(Entry& entry, Strategy& oldStrategy, Strategy& newStrategy)
Junxiao Shibb5105f2014-03-03 12:06:45 -0700250{
Junxiao Shi838c4f12014-11-03 18:55:24 -0700251 if (&oldStrategy == &newStrategy) {
Junxiao Shibb5105f2014-03-03 12:06:45 -0700252 return;
253 }
254
Junxiao Shi838c4f12014-11-03 18:55:24 -0700255 NFD_LOG_INFO("changeStrategy(" << entry.getPrefix() << ")"
256 << " from " << oldStrategy.getName()
257 << " to " << newStrategy.getName());
258
259 // reset StrategyInfo on a portion of NameTree,
260 // where entry's effective strategy is covered by the changing StrategyChoice entry
Junxiao Shib184e532016-05-26 18:09:57 +0000261 const name_tree::Entry* rootNte = m_nameTree.lookup(entry).get();
Junxiao Shi60607c72014-11-26 22:40:36 -0700262 auto&& ntChanged = m_nameTree.partialEnumerate(entry.getPrefix(),
Junxiao Shi838c4f12014-11-03 18:55:24 -0700263 [&rootNte] (const name_tree::Entry& nte) -> std::pair<bool, bool> {
264 if (&nte == rootNte) {
Junxiao Shi60607c72014-11-26 22:40:36 -0700265 return {true, true};
Junxiao Shi838c4f12014-11-03 18:55:24 -0700266 }
Junxiao Shib184e532016-05-26 18:09:57 +0000267 if (nte.getStrategyChoiceEntry() != nullptr) {
Junxiao Shi60607c72014-11-26 22:40:36 -0700268 return {false, false};
Junxiao Shi838c4f12014-11-03 18:55:24 -0700269 }
Junxiao Shi60607c72014-11-26 22:40:36 -0700270 return {true, true};
Junxiao Shi838c4f12014-11-03 18:55:24 -0700271 });
Junxiao Shi60607c72014-11-26 22:40:36 -0700272 for (const name_tree::Entry& nte : ntChanged) {
273 clearStrategyInfo(nte);
274 }
Junxiao Shibb5105f2014-03-03 12:06:45 -0700275}
276
Junxiao Shib5888d22014-05-26 07:35:22 -0700277StrategyChoice::const_iterator
278StrategyChoice::begin() const
279{
Junxiao Shi60607c72014-11-26 22:40:36 -0700280 auto&& enumerable = m_nameTree.fullEnumerate(
Junxiao Shi838c4f12014-11-03 18:55:24 -0700281 [] (const name_tree::Entry& entry) {
Junxiao Shib184e532016-05-26 18:09:57 +0000282 return entry.getStrategyChoiceEntry() != nullptr;
Junxiao Shi60607c72014-11-26 22:40:36 -0700283 });
284 return const_iterator(enumerable.begin());
Junxiao Shib5888d22014-05-26 07:35:22 -0700285}
286
Junxiao Shiff10da62016-07-13 17:57:43 +0000287} // namespace strategy_choice
Junxiao Shibb5105f2014-03-03 12:06:45 -0700288} // namespace nfd