table: PIT on NameTree
ref# 1194
Change-Id: I32f103374885445725fc5deeebda60b1b1e54c2f
diff --git a/daemon/table/pit.cpp b/daemon/table/pit.cpp
index 168a64e..6f5acf3 100644
--- a/daemon/table/pit.cpp
+++ b/daemon/table/pit.cpp
@@ -4,12 +4,24 @@
* See COPYING for copyright and distribution information.
*/
+/**
+ * KNOWN ISSUES
+ *
+ * - To remove a PIT entry, we need to first perform a lookup on NameTree
+ * to locate its NameTree Entry, and then call NameTreeEntry->deletePitEntry()
+ * function. Alternatively, we could store a pointer at each PIT-Entry, which
+ * would speed up this procedure with the cost of additional memory space. Maybe
+ * this could also be part of the PIT/FIB/Measurement shortcut, where all of these
+ * entries have pointers to their NameTreeEntry. Which could be part of task
+ * #1202, shortcuts between FIB, PIT, Measurements.
+ *
+ */
+
#include "pit.hpp"
-#include <algorithm>
namespace nfd {
-Pit::Pit()
+Pit::Pit(NameTree& nameTree) : m_nameTree(nameTree), m_nItems(0)
{
}
@@ -43,34 +55,83 @@
std::pair<shared_ptr<pit::Entry>, bool>
Pit::insert(const Interest& interest)
{
- std::list<shared_ptr<pit::Entry> >::iterator it = std::find_if(
- m_table.begin(), m_table.end(),
- bind(&predicate_PitEntry_similar_Interest, _1, interest));
- if (it != m_table.end()) return std::make_pair(*it, false);
-
- shared_ptr<pit::Entry> entry = make_shared<pit::Entry>(interest);
- m_table.push_back(entry);
- return std::make_pair(entry, true);
+ // - first lookup() the Interest Name in the NameTree, which will creates all
+ // the intermedia nodes, starting from the shortest prefix.
+ // - if it is guaranteed that this Interest already has a NameTree Entry, we
+ // could use findExactMatch() instead.
+ // - Alternatively, we could try to do findExactMatch() first, if not found, then
+ // do lookup().
+ shared_ptr<name_tree::Entry> nameTreeEntry = m_nameTree.lookup(interest.getName());
+
+ BOOST_ASSERT(static_cast<bool>(nameTreeEntry));
+
+ std::vector<shared_ptr<pit::Entry> >& pitEntries = nameTreeEntry->getPitEntries();
+
+ // then check if this Interest is already in the PIT entries
+ std::vector<shared_ptr<pit::Entry> >::iterator it = std::find_if(pitEntries.begin(), pitEntries.end(), bind(&predicate_PitEntry_similar_Interest, _1, interest));
+
+ if (it != pitEntries.end())
+ {
+ return std::make_pair(*it, false);
+ }
+ else
+ {
+ shared_ptr<pit::Entry> entry = make_shared<pit::Entry>(interest);
+ nameTreeEntry->insertPitEntry(entry);
+
+ // Increase m_nItmes only if we create a new PIT Entry
+ m_nItems++;
+
+ return std::make_pair(entry, true);
+ }
}
shared_ptr<pit::DataMatchResult>
Pit::findAllDataMatches(const Data& data) const
{
shared_ptr<pit::DataMatchResult> result = make_shared<pit::DataMatchResult>();
- for (std::list<shared_ptr<pit::Entry> >::const_iterator it = m_table.begin();
- it != m_table.end(); ++it) {
- shared_ptr<pit::Entry> entry = *it;
- if (entry->getInterest().matchesName(data.getName())) {
- result->push_back(entry);
+
+ shared_ptr<name_tree::Entry> nameTreeEntry;
+
+ // NOTE: We are using findLongestPrefixMatch() here.
+ // The reason is that findLongestPrefixMatch() starts with the full name
+ // and then remove one component each time, which is the type of behavior we would like
+ // to use here.
+ // If it could be guranteed that the quering Data packet always has a Name Tree
+ // Entry, we could also use findExactMatch().
+ for (nameTreeEntry = m_nameTree.findLongestPrefixMatch(data.getName());
+ static_cast<bool>(nameTreeEntry);
+ nameTreeEntry = nameTreeEntry->getParent())
+ {
+ std::vector<shared_ptr<pit::Entry> >& pitEntries = nameTreeEntry->getPitEntries();
+ for (size_t i = 0; i < pitEntries.size(); i++)
+ {
+ if (pitEntries[i]->getInterest().matchesName(data.getName()))
+ result->push_back(pitEntries[i]);
+ }
}
- }
+
return result;
}
void
-Pit::remove(shared_ptr<pit::Entry> pitEntry)
+Pit::erase(shared_ptr<pit::Entry> pitEntry)
{
- m_table.remove(pitEntry);
+ // first get the NPE
+ // If pit-entry.hpp stores a NameTree Entry for each PIT, we could also use the get() method
+ // directly, saving one hash computation.
+ shared_ptr<name_tree::Entry> nameTreeEntry = m_nameTree.findExactMatch(pitEntry->getName());
+
+ BOOST_ASSERT(static_cast<bool>(nameTreeEntry));
+
+ // erase this PIT entry
+ if (static_cast<bool>(nameTreeEntry))
+ {
+ nameTreeEntry->erasePitEntry(pitEntry);
+ m_nameTree.eraseEntryIfEmpty(nameTreeEntry);
+
+ m_nItems--;
+ }
}
} // namespace nfd
diff --git a/daemon/table/pit.hpp b/daemon/table/pit.hpp
index 9dd2e1e..9ea5aac 100644
--- a/daemon/table/pit.hpp
+++ b/daemon/table/pit.hpp
@@ -7,7 +7,9 @@
#ifndef NFD_TABLE_PIT_HPP
#define NFD_TABLE_PIT_HPP
+#include "name-tree.hpp"
#include "pit-entry.hpp"
+
namespace nfd {
namespace pit {
@@ -27,9 +29,16 @@
class Pit : noncopyable
{
public:
- Pit();
-
+ explicit
+ Pit(NameTree& nameTree);
+
~Pit();
+
+ /**
+ * \brief Get the number of items stored in the PIT.
+ */
+ size_t
+ size() const;
/** \brief inserts a FIB entry for prefix
* If an entry for exact same prefix exists, that entry is returned.
@@ -43,15 +52,24 @@
*/
shared_ptr<pit::DataMatchResult>
findAllDataMatches(const Data& data) const;
-
- /// removes a PIT entry
+
+ /**
+ * \brief Erase a PIT Entry
+ */
void
- remove(shared_ptr<pit::Entry> pitEntry);
+ erase(shared_ptr<pit::Entry> pitEntry);
private:
- std::list<shared_ptr<pit::Entry> > m_table;
+ NameTree& m_nameTree;
+ size_t m_nItems;
};
+inline size_t
+Pit::size() const
+{
+ return m_nItems;
+}
+
} // namespace nfd
#endif // NFD_TABLE_PIT_HPP