table: don't share Strategy instance among StrategyChoice entries
For a Strategy type registered in the strategy registry,
a new instance is created for each StrategyChoice entry that uses it.
StrategyChoice::install is deprecated. An installed strategy instance
is still shared among StrategyChoice entries that use it. This will
be removed after unit tests switch to use the strategy registry.
refs #3868
Change-Id: Ibca685e6b6668f64fa1a503e3575867e8babdfe1
diff --git a/daemon/table/strategy-choice-entry.cpp b/daemon/table/strategy-choice-entry.cpp
index 365fd20..f5d9551 100644
--- a/daemon/table/strategy-choice-entry.cpp
+++ b/daemon/table/strategy-choice-entry.cpp
@@ -32,15 +32,35 @@
Entry::Entry(const Name& prefix)
: m_prefix(prefix)
- , m_strategy(nullptr)
+ , m_strategyPtr(nullptr)
, m_nameTreeEntry(nullptr)
{
}
+Entry::~Entry() = default;
+
const Name&
Entry::getStrategyName() const
{
- return m_strategy->getName();
+ return this->getStrategy().getName();
+}
+
+void
+Entry::setStrategy(fw::Strategy& strategy)
+{
+ /// \todo #3868
+ /// Every entry should have its own Strategy instance in unique_ptr;
+ /// m_strategyPtr and this overload should be eliminated.
+
+ m_strategy.reset();
+ m_strategyPtr = &strategy;
+}
+
+void
+Entry::setStrategy(unique_ptr<fw::Strategy> strategy)
+{
+ m_strategy = std::move(strategy);
+ m_strategyPtr = m_strategy.get();
}
} // namespace strategy_choice
diff --git a/daemon/table/strategy-choice-entry.hpp b/daemon/table/strategy-choice-entry.hpp
index c63676b..5d1497c 100644
--- a/daemon/table/strategy-choice-entry.hpp
+++ b/daemon/table/strategy-choice-entry.hpp
@@ -47,6 +47,8 @@
public:
Entry(const Name& prefix);
+ ~Entry();
+
const Name&
getPrefix() const
{
@@ -59,19 +61,21 @@
fw::Strategy&
getStrategy() const
{
- BOOST_ASSERT(m_strategy != nullptr);
- return *m_strategy;
+ BOOST_ASSERT(m_strategyPtr != nullptr);
+ return *m_strategyPtr;
}
+ DEPRECATED(
void
- setStrategy(fw::Strategy& strategy)
- {
- m_strategy = &strategy;
- }
+ setStrategy(fw::Strategy& strategy));
+
+ void
+ setStrategy(unique_ptr<fw::Strategy> strategy);
private:
Name m_prefix;
- fw::Strategy* m_strategy;
+ unique_ptr<fw::Strategy> m_strategy;
+ fw::Strategy* m_strategyPtr;
name_tree::Entry* m_nameTreeEntry;
diff --git a/daemon/table/strategy-choice.cpp b/daemon/table/strategy-choice.cpp
index 81de636..985d05c 100644
--- a/daemon/table/strategy-choice.cpp
+++ b/daemon/table/strategy-choice.cpp
@@ -52,38 +52,15 @@
void
StrategyChoice::setDefaultStrategy(const Name& strategyName)
{
- unique_ptr<Strategy> strategy = Strategy::create(strategyName, m_forwarder);
-
- bool isInstalled = false;
- Strategy* instance = nullptr;
- std::tie(isInstalled, instance) = this->install(std::move(strategy));
- BOOST_ASSERT(isInstalled);
-
auto entry = make_unique<Entry>(Name());
- entry->setStrategy(*instance);
+ entry->setStrategy(Strategy::create(strategyName, m_forwarder));
+ NFD_LOG_INFO("setDefaultStrategy " << entry->getStrategyName());
// don't use .insert here, because it will invoke findEffectiveStrategy
// which expects an existing root entry
name_tree::Entry& nte = m_nameTree.lookup(Name());
nte.setStrategyChoiceEntry(std::move(entry));
++m_nItems;
- NFD_LOG_INFO("setDefaultStrategy " << instance->getName());
-}
-
-void
-StrategyChoice::installFromRegistry()
-{
- /// \todo #3868
- /// * Give every StrategyChoice entry its own Strategy instance.
- /// Don't share Strategy instances.
- /// * Create Strategy instance with Strategy::create.
- /// * Eliminate install, installFromRegistry, getStrategy functions.
-
- // This is temporary code until the above is done.
-
- for (const Name& strategyName : Strategy::listRegistered()) {
- this->install(Strategy::create(strategyName, m_forwarder));
- }
}
bool
@@ -93,13 +70,18 @@
return m_strategyInstances.count(strategyName) > 0;
}
else {
- return this->getStrategy(strategyName) != nullptr;
+ return Strategy::canCreate(strategyName) ||
+ this->getStrategy(strategyName) != nullptr;
}
}
std::pair<bool, Strategy*>
StrategyChoice::install(unique_ptr<Strategy> strategy)
{
+ /// \todo #3868
+ /// Strategy instance should always be created from Strategy::create;
+ /// m_strategyInstances, install, getStrategy, hasStrategy should be eliminated.
+
BOOST_ASSERT(strategy != nullptr);
Name strategyName = strategy->getName();
// copying Name, so that strategyName remains available even if strategy is deallocated
@@ -134,17 +116,22 @@
bool
StrategyChoice::insert(const Name& prefix, const Name& strategyName)
{
- Strategy* strategy = this->getStrategy(strategyName);
+ unique_ptr<Strategy> createdStrategy = Strategy::create(strategyName, m_forwarder);
+ Strategy* strategy = createdStrategy.get();
if (strategy == nullptr) {
- NFD_LOG_ERROR("insert(" << prefix << "," << strategyName << ") strategy not installed");
- return false;
+ strategy = this->getStrategy(strategyName);
+ if (strategy == nullptr) {
+ NFD_LOG_ERROR("insert(" << prefix << "," << strategyName << ") strategy not registered or installed");
+ return false;
+ }
+ NFD_LOG_WARN("insert(" << prefix << "," << strategyName << ") using shared strategy instance");
}
name_tree::Entry& nte = m_nameTree.lookup(prefix);
Entry* entry = nte.getStrategyChoiceEntry();
Strategy* oldStrategy = nullptr;
if (entry != nullptr) {
- if (entry->getStrategy().getName() == strategy->getName()) {
+ if (entry->getStrategyName() == strategy->getName()) {
NFD_LOG_TRACE("insert(" << prefix << ") not changing " << strategy->getName());
return true;
}
@@ -152,8 +139,7 @@
NFD_LOG_TRACE("insert(" << prefix << ") changing from " << oldStrategy->getName() <<
" to " << strategy->getName());
}
-
- if (entry == nullptr) {
+ else {
oldStrategy = &this->findEffectiveStrategy(prefix);
auto newEntry = make_unique<Entry>(prefix);
entry = newEntry.get();
@@ -163,7 +149,12 @@
}
this->changeStrategy(*entry, *oldStrategy, *strategy);
- entry->setStrategy(*strategy);
+ if (createdStrategy != nullptr) {
+ entry->setStrategy(std::move(createdStrategy));
+ }
+ else {
+ entry->setStrategy(*strategy);
+ }
return true;
}
diff --git a/daemon/table/strategy-choice.hpp b/daemon/table/strategy-choice.hpp
index f2410e2..2c492cd 100644
--- a/daemon/table/strategy-choice.hpp
+++ b/daemon/table/strategy-choice.hpp
@@ -67,26 +67,26 @@
void
setDefaultStrategy(const Name& strategyName);
- /** \brief install all strategies from registry
- */
- void
- installFromRegistry();
-
/** \brief determines if a strategy is installed
* \param strategyName name of the strategy
* \param isExact true to require exact match, false to permit unversioned strategyName
* \return true if strategy is installed
*/
+ DEPRECATED(
bool
- hasStrategy(const Name& strategyName, bool isExact = false) const;
+ hasStrategy(const Name& strategyName, bool isExact = false) const);
+
+ // DEPRECATED macro does not work when this type appears inline on install function.
+ typedef std::pair<bool, fw::Strategy*> InstallResult;
/** \brief install a strategy
* \return if installed, true, and a pointer to the strategy instance;
* if not installed due to duplicate strategyName, false,
* and a pointer to the existing strategy instance
*/
- std::pair<bool, fw::Strategy*>
- install(unique_ptr<fw::Strategy> strategy);
+ DEPRECATED(
+ InstallResult
+ install(unique_ptr<fw::Strategy> strategy));
public: // Strategy Choice table
/** \brief set strategy of prefix to be strategyName