30 #include <boost/concept/assert.hpp> 31 #include <boost/concept_check.hpp> 32 #include <type_traits> 39 BOOST_CONCEPT_ASSERT((boost::ForwardIterator<NameTree::const_iterator>));
42 #ifdef HAVE_IS_DEFAULT_CONSTRUCTIBLE 43 static_assert(std::is_default_constructible<NameTree::const_iterator>::value,
44 "NameTree::const_iterator must be default-constructible");
46 BOOST_CONCEPT_ASSERT((boost::DefaultConstructible<NameTree::const_iterator>));
47 #endif // HAVE_IS_DEFAULT_CONSTRUCTIBLE 55 compute(
const char* buffer,
size_t length)
57 return static_cast<size_t>(
CityHash32(buffer, length));
65 compute(
const char* buffer,
size_t length)
67 return static_cast<size_t>(
CityHash64(buffer, length));
72 typedef boost::mpl::if_c<sizeof(size_t) >= 8,
Hash64,
Hash32>::type CityHash;
82 size_t hashUpdate = 0;
86 const char* wireFormat =
reinterpret_cast<const char*
>( it->wire() );
87 hashUpdate = CityHash::compute(wireFormat, it->size());
88 hashValue ^= hashUpdate;
100 size_t hashUpdate = 0;
102 std::vector<size_t> hashValueSet;
103 hashValueSet.push_back(hashValue);
107 const char* wireFormat =
reinterpret_cast<const char*
>( it->wire() );
108 hashUpdate = CityHash::compute(wireFormat, it->size());
109 hashValue ^= hashUpdate;
110 hashValueSet.push_back(hashValue);
120 , m_nBuckets(nBuckets)
121 , m_minNBuckets(nBuckets)
122 , m_enlargeLoadFactor(0.5)
124 , m_shrinkLoadFactor(0.1)
125 , m_shrinkFactor(0.5)
126 , m_endIterator(FULL_ENUMERATE_TYPE, *this, m_end)
128 m_enlargeThreshold =
static_cast<size_t>(m_enlargeLoadFactor *
129 static_cast<double>(m_nBuckets));
131 m_shrinkThreshold =
static_cast<size_t>(m_shrinkLoadFactor *
132 static_cast<double>(m_nBuckets));
137 for (
size_t i = 0; i < m_nBuckets; i++)
143 for (
size_t i = 0; i < m_nBuckets; i++)
145 if (m_buckets[i] != 0) {
154 std::pair<shared_ptr<name_tree::Entry>,
bool>
155 NameTree::insert(
const Name& prefix)
160 size_t loc = hashValue % m_nBuckets;
162 NFD_LOG_TRACE(
"Name " << prefix <<
" hash value = " << hashValue <<
" location = " << loc);
168 for (node = m_buckets[loc]; node != 0; node = node->
m_next)
170 if (static_cast<bool>(node->
m_entry))
172 if (prefix == node->
m_entry->m_prefix)
174 return std::make_pair(node->
m_entry,
false);
180 NFD_LOG_TRACE(
"Did not find " << prefix <<
", need to insert it to the table");
189 m_buckets[loc] = node;
197 shared_ptr<name_tree::Entry> entry(make_shared<name_tree::Entry>(prefix));
198 entry->setHash(hashValue);
200 entry->m_node = node;
202 return std::make_pair(entry,
true);
206 shared_ptr<name_tree::Entry>
211 shared_ptr<name_tree::Entry> entry;
212 shared_ptr<name_tree::Entry> parent;
214 for (
size_t i = 0; i <= prefix.
size(); i++)
219 std::pair<shared_ptr<name_tree::Entry>,
bool> ret = insert(temp);
222 if (ret.second ==
true)
225 entry->m_parent = parent;
227 if (static_cast<bool>(parent))
229 parent->m_children.push_back(entry);
233 if (m_nItems > m_enlargeThreshold)
235 resize(m_enlargeFactor * m_nBuckets);
247 BOOST_ASSERT(static_cast<bool>(entry));
252 if (entry->isEmpty())
255 shared_ptr<name_tree::Entry> parent = entry->getParent();
257 if (static_cast<bool>(parent))
259 std::vector<shared_ptr<name_tree::Entry> >& parentChildrenList =
260 parent->getChildren();
262 bool isFound =
false;
263 size_t size = parentChildrenList.size();
264 for (
size_t i = 0; i <
size; i++)
266 if (parentChildrenList[i] == entry)
268 parentChildrenList[i] = parentChildrenList[size - 1];
269 parentChildrenList.pop_back();
275 BOOST_VERIFY(isFound ==
true);
290 m_buckets[entry->getHash() % m_nBuckets] = node->
m_next;
300 BOOST_ASSERT(node->
m_next == 0);
305 if (static_cast<bool>(parent))
308 size_t newNBuckets =
static_cast<size_t>(m_shrinkFactor *
309 static_cast<double>(m_nBuckets));
311 if (newNBuckets >= m_minNBuckets && m_nItems < m_shrinkThreshold)
323 shared_ptr<name_tree::Entry>
326 shared_ptr<name_tree::Entry> nte = pitEntry.m_nameTreeEntry;
327 if (nte ==
nullptr) {
331 if (nte->getPrefix().size() == pitEntry.
getName().
size()) {
341 shared_ptr<name_tree::Entry>
347 size_t loc = hashValue % m_nBuckets;
349 NFD_LOG_TRACE(
"Name " << prefix <<
" hash value = " << hashValue <<
350 " location = " << loc);
352 shared_ptr<name_tree::Entry> entry;
355 for (node = m_buckets[loc]; node != 0; node = node->
m_next)
358 if (static_cast<bool>(entry))
360 if (hashValue == entry->getHash() && prefix == entry->
getPrefix())
373 shared_ptr<name_tree::Entry>
378 shared_ptr<name_tree::Entry> entry;
381 size_t hashValue = 0;
384 for (
int i = static_cast<int>(prefix.
size()); i >= 0; i--)
386 hashValue = hashValueSet[i];
387 loc = hashValue % m_nBuckets;
390 for (node = m_buckets[loc]; node != 0; node = node->
m_next)
393 if (static_cast<bool>(entry))
396 if (hashValue == entry->getHash() &&
397 entry->getPrefix().isPrefixOf(prefix) &&
398 entrySelector(*entry))
411 shared_ptr<name_tree::Entry>
415 while (static_cast<bool>(entry))
417 if (entrySelector(*entry))
419 entry = entry->getParent();
421 return shared_ptr<name_tree::Entry>();
424 shared_ptr<name_tree::Entry>
427 shared_ptr<name_tree::Entry> nte = pitEntry.m_nameTreeEntry;
428 if (nte->getPrefix().size() == pitEntry.
getName().
size()) {
435 return exact ==
nullptr ? nte : exact;
438 boost::iterator_range<NameTree::const_iterator>
452 if (static_cast<bool>(entry)) {
460 boost::iterator_range<NameTree::const_iterator>
466 for (
size_t i = 0; i < m_nBuckets; i++) {
468 if (static_cast<bool>(node->m_entry) && entrySelector(*node->m_entry)) {
479 boost::iterator_range<NameTree::const_iterator>
485 if (!static_cast<bool>(entry)) {
489 std::pair<bool, bool>result = entrySubTreeSelector(*entry);
494 entrySubTreeSelector);
496 it.m_shouldVisitChildren = (result.second && entry->hasChildren());
510 NameTree::resize(
size_t newNBuckets)
526 for (i = 0; i < newNBuckets; i++)
531 for (i = 0; i < m_nBuckets; i++)
533 for (p = m_buckets[i]; p != 0; p = q)
537 BOOST_ASSERT(static_cast<bool>(p->
m_entry));
541 for (pp = &newBuckets[b]; *pp != 0; pp = &((*pp)->m_next))
552 BOOST_ASSERT(count == m_nItems);
555 m_buckets = newBuckets;
556 delete [] oldBuckets;
558 m_nBuckets = newNBuckets;
560 m_enlargeThreshold =
static_cast<size_t>(m_enlargeLoadFactor *
561 static_cast<double>(m_nBuckets));
562 m_shrinkThreshold =
static_cast<size_t>(m_shrinkLoadFactor *
563 static_cast<double>(m_nBuckets));
573 shared_ptr<name_tree::Entry> entry;
577 for (
size_t i = 0; i < m_nBuckets; i++)
579 for (node = m_buckets[i]; node != 0; node = node->
m_next)
584 if (static_cast<bool>(entry))
586 output <<
"Bucket" << i <<
"\t" << entry->m_prefix.toUri() << endl;
587 output <<
"\t\tHash " << entry->m_hash << endl;
589 if (static_cast<bool>(entry->m_parent))
591 output <<
"\t\tparent->" << entry->m_parent->m_prefix.toUri();
595 output <<
"\t\tROOT";
599 if (entry->m_children.size() != 0)
601 output <<
"\t\tchildren = " << entry->m_children.size() << endl;
603 for (
size_t j = 0; j < entry->m_children.size(); j++)
605 output <<
"\t\t\tChild " << j <<
" " <<
606 entry->m_children[j]->getPrefix() << endl;
615 output <<
"Bucket count = " << m_nBuckets << endl;
616 output <<
"Stored item = " << m_nItems << endl;
617 output <<
"--------------------------\n";
621 : m_nameTree(nullptr)
627 shared_ptr<name_tree::Entry> entry,
630 : m_nameTree(&nameTree)
632 , m_subTreeRoot(entry)
633 , m_entrySelector(make_shared<name_tree::
EntrySelector>(entrySelector))
636 , m_shouldVisitChildren(true)
646 BOOST_ASSERT(m_entry != m_nameTree->m_end);
651 while (m_entry->m_node->m_next != 0)
653 m_entry = m_entry->m_node->m_next->m_entry;
654 if ((*m_entrySelector)(*m_entry))
662 for (
int newLocation = m_entry->m_hash % m_nameTree->m_nBuckets + 1;
663 newLocation < static_cast<int>(m_nameTree->m_nBuckets);
671 if ((*m_entrySelector)(*m_entry))
680 m_entry = m_nameTree->m_end;
693 if (m_entry == m_subTreeRoot)
695 if (m_shouldVisitChildren)
697 m_entry = m_entry->getChildren()[0];
698 std::pair<bool, bool> result = ((*m_entrySubTreeSelector)(*m_entry));
699 m_shouldVisitChildren = (result.second && m_entry->hasChildren());
720 while (m_entry != m_subTreeRoot)
722 if (m_shouldVisitChildren)
725 m_entry = m_entry->getChildren()[0];
726 std::pair<bool, bool> result = ((*m_entrySubTreeSelector)(*m_entry));
727 m_shouldVisitChildren = (result.second && m_entry->hasChildren());
741 shared_ptr<name_tree::Entry> parent = m_entry->getParent();
743 std::vector<shared_ptr<name_tree::Entry> >& parentChildrenList = parent->getChildren();
744 bool isFound =
false;
746 for (i = 0; i < parentChildrenList.size(); i++)
748 if (parentChildrenList[i] == m_entry)
755 BOOST_VERIFY(isFound ==
true);
756 if (i < parentChildrenList.size() - 1)
758 m_entry = parentChildrenList[i + 1];
759 std::pair<bool, bool> result = ((*m_entrySubTreeSelector)(*m_entry));
760 m_shouldVisitChildren = (result.second && m_entry->hasChildren());
774 m_shouldVisitChildren =
false;
780 m_entry = m_nameTree->m_end;
790 while (static_cast<bool>(m_entry->getParent()))
792 m_entry = m_entry->getParent();
793 if ((*m_entrySelector)(*m_entry))
798 m_entry = m_nameTree->m_end;
size_t computeHash(const Name &prefix)
Compute the hash value of the given name prefix's WIRE FORMAT.
PartialName getPrefix(ssize_t nComponents) const
Extract a prefix (PartialName) of the name, containing first nComponents components.
NameTree(size_t nBuckets=1024)
static size_t compute(const char *buffer, size_t length)
shared_ptr< Entry > m_entry
const Component & at(ssize_t i) const
Get component at the specified index.
const_iterator end() const
End iterator (const).
bool eraseEntryIfEmpty(shared_ptr< name_tree::Entry > entry)
Delete a Name Tree Entry if this entry is empty.
uint32 CityHash32(const char *s, size_t len)
function< std::pair< bool, bool >const Entry &entry)> EntrySubTreeSelector
a predicate to accept or reject an Entry and its children
shared_ptr< name_tree::Entry > get(const fib::Entry &fibEntry) const
get NameTree entry from FIB entry
const Name & getName() const
std::vector< size_t > computeHashSet(const Name &prefix)
Incrementally compute hash values.
void dump(std::ostream &output) const
Dump all the information stored in the Name Tree for debugging.
size_t size() const
Get the number of occupied entries in the Name Tree.
shared_ptr< name_tree::Entry > findLongestPrefixMatch(const Name &prefix, const name_tree::EntrySelector &entrySelector=name_tree::AnyEntry()) const
Longest prefix matching for the given name.
uint64 CityHash64(const char *s, size_t len)
const_iterator begin() const
Get an iterator pointing to the first NameTree entry.
Copyright (c) 2011-2015 Regents of the University of California.
shared_ptr< name_tree::Entry > findExactMatch(const Name &prefix) const
Exact match lookup for the given name prefix.
bool isImplicitSha256Digest() const
Check if the component is ImplicitSha256DigestComponent.
Name abstraction to represent an absolute name.
const_iterator begin() const
Begin iterator (const).
shared_ptr< name_tree::Entry > lookup(const Name &prefix)
Look for the Name Tree Entry that contains this name prefix.
boost::iterator_range< const_iterator > findAllMatches(const Name &prefix, const name_tree::EntrySelector &entrySelector=name_tree::AnyEntry()) const
Enumerate all the name prefixes that satisfy the prefix and entrySelector.
const_iterator operator++()
size_t size() const
Get the number of components.
Component holds a read-only name component value.
static size_t compute(const char *buffer, size_t length)
#define NFD_LOG_INIT(name)
const_iterator end() const
Get an iterator referring to the past-the-end FIB entry.
#define NFD_LOG_TRACE(expression)
function< bool(const Entry &entry)> EntrySelector
a predicate to accept or reject an Entry in find operations
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
boost::iterator_range< const_iterator > partialEnumerate(const Name &prefix, const name_tree::EntrySubTreeSelector &entrySubTreeSelector=name_tree::AnyEntrySubTree()) const
Enumerate all entries under a prefix, optionally filtered by an EntrySubTreeSelector.
boost::iterator_range< const_iterator > fullEnumerate(const name_tree::EntrySelector &entrySelector=name_tree::AnyEntry()) const
Enumerate all entries, optionally filtered by an EntrySelector.