fib: implicitly delete empty Entry
Fib::removeNextHopFromAllEntries automatically deletes fib::Entry
if the last nexthop record is being removed.
refs #1341
Change-Id: I36d42fe8f9fc8f03d194f845020aff408cd70488
diff --git a/daemon/table/fib-entry.cpp b/daemon/table/fib-entry.cpp
index 6a9b686..1628d96 100644
--- a/daemon/table/fib-entry.cpp
+++ b/daemon/table/fib-entry.cpp
@@ -42,7 +42,6 @@
it->setCost(cost);
this->sortNextHops();
-
}
void
diff --git a/daemon/table/fib-entry.hpp b/daemon/table/fib-entry.hpp
index aac8fc5..48b09d6 100644
--- a/daemon/table/fib-entry.hpp
+++ b/daemon/table/fib-entry.hpp
@@ -11,6 +11,11 @@
namespace nfd {
+class NameTree;
+namespace name_tree {
+class Entry;
+}
+
namespace fib {
/** \class NextHopList
@@ -37,6 +42,10 @@
const NextHopList&
getNextHops() const;
+ /// whether this Entry has any nexthop
+ bool
+ hasNextHops() const;
+
bool
hasNextHop(shared_ptr<Face> face) const;
@@ -56,6 +65,10 @@
private:
Name m_prefix;
NextHopList m_nextHops;
+
+ shared_ptr<name_tree::Entry> m_nameTreeEntry;
+ friend class nfd::NameTree;
+ friend class nfd::name_tree::Entry;
};
@@ -71,6 +84,12 @@
return m_nextHops;
}
+inline bool
+Entry::hasNextHops() const
+{
+ return !m_nextHops.empty();
+}
+
} // namespace fib
} // namespace nfd
diff --git a/daemon/table/fib.cpp b/daemon/table/fib.cpp
index eea7641..7397c60 100644
--- a/daemon/table/fib.cpp
+++ b/daemon/table/fib.cpp
@@ -37,7 +37,7 @@
return std::make_pair(entry, false);
entry = make_shared<fib::Entry>(prefix);
nameTreeEntry->setFibEntry(entry);
- m_nItems++;
+ ++m_nItems;
return std::make_pair(entry, true);
}
@@ -79,19 +79,32 @@
shared_ptr<name_tree::Entry> nameTreeEntry = m_nameTree.findExactMatch(prefix);
if (static_cast<bool>(nameTreeEntry))
{
- nameTreeEntry->eraseFibEntry(nameTreeEntry->getFibEntry());
- m_nItems--;
+ nameTreeEntry->setFibEntry(shared_ptr<fib::Entry>());
+ --m_nItems;
+ }
+}
+
+void
+Fib::erase(const fib::Entry& entry)
+{
+ shared_ptr<name_tree::Entry> nameTreeEntry = m_nameTree.findExactMatch(entry);
+ if (static_cast<bool>(nameTreeEntry))
+ {
+ nameTreeEntry->setFibEntry(shared_ptr<fib::Entry>());
+ --m_nItems;
}
}
void
Fib::removeNextHopFromAllEntries(shared_ptr<Face> face)
{
- for (NameTree::const_iterator it =
- m_nameTree.fullEnumerate(&predicate_NameTreeEntry_hasFibEntry); it != m_nameTree.end(); it++)
- {
+ for (NameTree::const_iterator it = m_nameTree.fullEnumerate(
+ &predicate_NameTreeEntry_hasFibEntry); it != m_nameTree.end(); ++it) {
shared_ptr<fib::Entry> entry = it->getFibEntry();
entry->removeNextHop(face);
+ if (!entry->hasNextHops()) {
+ this->erase(*entry);
+ }
}
}
diff --git a/daemon/table/fib.hpp b/daemon/table/fib.hpp
index 0399833..5e2e03d 100644
--- a/daemon/table/fib.hpp
+++ b/daemon/table/fib.hpp
@@ -66,9 +66,13 @@
size() const;
private:
+ void
+ erase(const fib::Entry& entry);
+
+private:
NameTree& m_nameTree;
size_t m_nItems;
-
+
/** \brief The empty FIB entry.
*
* This entry has no nexthops.
diff --git a/daemon/table/name-tree-entry.cpp b/daemon/table/name-tree-entry.cpp
index 673be47..dd7bf4b 100644
--- a/daemon/table/name-tree-entry.cpp
+++ b/daemon/table/name-tree-entry.cpp
@@ -46,18 +46,15 @@
}
void
-Entry::setFibEntry(shared_ptr<fib::Entry> fib)
+Entry::setFibEntry(shared_ptr<fib::Entry> fibEntry)
{
- m_fibEntry = fib;
-}
-
-bool
-Entry::eraseFibEntry(shared_ptr<fib::Entry> fib)
-{
- if (m_fibEntry != fib)
- return false;
- m_fibEntry.reset();
- return true;
+ if (static_cast<bool>(m_fibEntry)) {
+ m_fibEntry->m_nameTreeEntry.reset();
+ }
+ m_fibEntry = fibEntry;
+ if (static_cast<bool>(m_fibEntry)) {
+ m_fibEntry->m_nameTreeEntry = this->shared_from_this();
+ }
}
void
@@ -102,7 +99,13 @@
void
Entry::setStrategyChoiceEntry(shared_ptr<strategy_choice::Entry> strategyChoiceEntry)
{
+ if (static_cast<bool>(m_strategyChoiceEntry)) {
+ m_strategyChoiceEntry->m_nameTreeEntry.reset();
+ }
m_strategyChoiceEntry = strategyChoiceEntry;
+ if (static_cast<bool>(m_strategyChoiceEntry)) {
+ m_strategyChoiceEntry->m_nameTreeEntry = this->shared_from_this();
+ }
}
} // namespace name_tree
diff --git a/daemon/table/name-tree-entry.hpp b/daemon/table/name-tree-entry.hpp
index cca1908..e3c72f2 100644
--- a/daemon/table/name-tree-entry.hpp
+++ b/daemon/table/name-tree-entry.hpp
@@ -45,7 +45,7 @@
/**
* \brief Name Tree Entry Class
*/
-class Entry : noncopyable
+class Entry : public enable_shared_from_this<Entry>, noncopyable
{
// Make private members accessible by Name Tree
friend class nfd::NameTree;
@@ -80,14 +80,11 @@
isEmpty() const;
void
- setFibEntry(shared_ptr<fib::Entry> fib);
+ setFibEntry(shared_ptr<fib::Entry> fibEntry);
shared_ptr<fib::Entry>
getFibEntry() const;
- bool
- eraseFibEntry(shared_ptr<fib::Entry> fib);
-
void
insertPitEntry(shared_ptr<pit::Entry> pit);
diff --git a/daemon/table/name-tree.cpp b/daemon/table/name-tree.cpp
index 5d11c27..430ed3c 100644
--- a/daemon/table/name-tree.cpp
+++ b/daemon/table/name-tree.cpp
@@ -498,8 +498,10 @@
}
// process other buckets
- int newLocation = m_entry->m_hash % m_nameTree.m_nBuckets + 1;
- for (newLocation = newLocation; newLocation < m_nameTree.m_nBuckets; newLocation++)
+
+ for (int newLocation = m_entry->m_hash % m_nameTree.m_nBuckets + 1;
+ newLocation < static_cast<int>(m_nameTree.m_nBuckets);
+ ++newLocation)
{
// process each bucket
name_tree::Node* node = m_nameTree.m_buckets[newLocation];
@@ -637,6 +639,9 @@
m_entry = m_nameTree.m_end;
return *this;
}
+
+ BOOST_ASSERT(false); // unknown type
+ return *this;
}
} // namespace nfd
diff --git a/daemon/table/name-tree.hpp b/daemon/table/name-tree.hpp
index 1a30b2b..3d0de70 100644
--- a/daemon/table/name-tree.hpp
+++ b/daemon/table/name-tree.hpp
@@ -100,6 +100,9 @@
shared_ptr<name_tree::Entry>
findExactMatch(const Name& prefix) const;
+ shared_ptr<name_tree::Entry>
+ findExactMatch(const fib::Entry& fibEntry) const;
+
/**
* \brief Erase a Name Tree Entry if this entry is empty.
* \details If a Name Tree Entry contains no Children, no FIB, no PIT, and
@@ -143,7 +146,8 @@
*/
const_iterator
partialEnumerate(const Name& prefix,
- const name_tree::EntrySubTreeSelector& entrySubTreeSelector = name_tree::AnyEntrySubTree()) const;
+ const name_tree::EntrySubTreeSelector& entrySubTreeSelector =
+ name_tree::AnyEntrySubTree()) const;
/**
* \brief Enumerate all the name prefixes that satisfy the prefix and entrySelector
@@ -203,13 +207,13 @@
operator!=(const const_iterator& other) const;
private:
- bool m_shouldVisitChildren;
const NameTree& m_nameTree;
shared_ptr<name_tree::Entry> m_entry;
shared_ptr<name_tree::Entry> m_subTreeRoot;
shared_ptr<name_tree::EntrySelector> m_entrySelector;
shared_ptr<name_tree::EntrySubTreeSelector> m_entrySubTreeSelector;
NameTree::IteratorType m_type;
+ bool m_shouldVisitChildren;
};
private:
@@ -250,6 +254,12 @@
return m_nBuckets;
}
+inline shared_ptr<name_tree::Entry>
+NameTree::findExactMatch(const fib::Entry& fibEntry) const
+{
+ return fibEntry.m_nameTreeEntry;
+}
+
inline NameTree::const_iterator
NameTree::begin() const
{