table: cleanupOnFaceRemoval doesn't rely on shared_ptr<name_tree::Entry> anymore

refs #3687

Change-Id: I3901f053bf370ca5a19a0fea72aec8eb58fcfe10
diff --git a/daemon/table/cleanup.cpp b/daemon/table/cleanup.cpp
index 8317099..c31ccc4 100644
--- a/daemon/table/cleanup.cpp
+++ b/daemon/table/cleanup.cpp
@@ -30,7 +30,7 @@
 void
 cleanupOnFaceRemoval(NameTree& nt, Fib& fib, Pit& pit, const Face& face)
 {
-  std::multimap<size_t, weak_ptr<name_tree::Entry>> maybeEmptyNtes;
+  std::multimap<size_t, const name_tree::Entry*> maybeEmptyNtes;
 
   // visit FIB and PIT entries in one pass of NameTree enumeration
   for (const name_tree::Entry& nte : nt) {
@@ -43,19 +43,19 @@
       pit.deleteInOutRecords(pitEntry, face);
     }
 
-    if (nte.getFibEntry() == nullptr && !nte.hasPitEntries()) {
-      maybeEmptyNtes.emplace(nte.getName().size(), const_pointer_cast<name_tree::Entry>(nte.shared_from_this()));
+    if (!nte.hasTableEntries()) {
+      maybeEmptyNtes.emplace(nte.getName().size(), &nte);
     }
   }
 
   // try to erase longer names first, so that children are erased before parent is checked
   for (auto i = maybeEmptyNtes.rbegin(); i != maybeEmptyNtes.rend(); ++i) {
-    shared_ptr<name_tree::Entry> nte = i->second.lock();
-    // nte may have been erased when its last child is erased
-    if (nte != nullptr) {
-      nt.eraseIfEmpty(nte.get());
-    }
+    nt.eraseIfEmpty(const_cast<name_tree::Entry*>(i->second), false);
   }
+
+  BOOST_ASSERT(nt.size() == 0 ||
+               std::none_of(nt.begin(), nt.end(),
+                            [] (const name_tree::Entry& nte) { return nte.isEmpty(); }));
 }
 
 } // namespace nfd
diff --git a/daemon/table/name-tree.cpp b/daemon/table/name-tree.cpp
index b806cd4..adff4b3 100644
--- a/daemon/table/name-tree.cpp
+++ b/daemon/table/name-tree.cpp
@@ -118,7 +118,7 @@
 }
 
 size_t
-NameTree::eraseIfEmpty(Entry* entry)
+NameTree::eraseIfEmpty(Entry* entry, bool canEraseAncestors)
 {
   BOOST_ASSERT(entry != nullptr);
 
@@ -132,6 +132,10 @@
 
     m_ht.erase(getNode(*entry));
     ++nErased;
+
+    if (!canEraseAncestors) {
+      break;
+    }
   }
 
   if (nErased == 0) {
diff --git a/daemon/table/name-tree.hpp b/daemon/table/name-tree.hpp
index 9ddf0ff..8542873 100644
--- a/daemon/table/name-tree.hpp
+++ b/daemon/table/name-tree.hpp
@@ -108,15 +108,16 @@
 
   /** \brief delete the entry if it is empty
    *  \param entry a valid entry
+   *  \param canEraseAncestors whether ancestors should be deleted if they become empty
    *  \return number of deleted entries
    *  \sa Entry::isEmpty()
-   *  \post If the entry is empty, it's deleted.
-   *        Ancestors of the entry are also deleted if they become empty.
+   *  \post If the entry is empty, it's deleted. If canEraseAncestors is true,
+   *        ancestors of the entry are also deleted if they become empty.
    *  \note This function must be called after detaching a table entry from a name tree entry,
    *  \note Existing iterators, except those pointing to deleted entries, are unaffected.
    */
   size_t
-  eraseIfEmpty(Entry* entry);
+  eraseIfEmpty(Entry* entry, bool canEraseAncestors = true);
 
 public: // matching
   /** \brief exact match lookup