blob: 9056b8a8a018c6505b8c77df1a48e981fb72a386 [file] [log] [blame]
HYuana9b85752014-02-26 02:32:30 -06001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shi4370fde2016-02-24 12:20:46 -07003 * Copyright (c) 2014-2016, Regents of the University of California,
Alexander Afanasyev319f2c82015-01-07 14:56:53 -08004 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Junxiao Shi2b73ca32014-11-17 19:16:08 -070024 */
HYuana9b85752014-02-26 02:32:30 -060025
26#include "name-tree.hpp"
27#include "core/logger.hpp"
Davide Pesavento52a18f92014-04-10 00:55:01 +020028
Alexander Afanasyev09fc3d92015-01-03 02:02:37 -080029#include <boost/concept/assert.hpp>
30#include <boost/concept_check.hpp>
31#include <type_traits>
32
HYuana9b85752014-02-26 02:32:30 -060033namespace nfd {
Junxiao Shi2570f3e2016-07-27 02:48:29 +000034namespace name_tree {
HYuana9b85752014-02-26 02:32:30 -060035
36NFD_LOG_INIT("NameTree");
37
HYuana9b85752014-02-26 02:32:30 -060038NameTree::NameTree(size_t nBuckets)
Junxiao Shib660b4c2016-08-06 20:47:44 +000039 : m_ht(HashtableOptions(nBuckets))
HYuana9b85752014-02-26 02:32:30 -060040{
HYuana9b85752014-02-26 02:32:30 -060041}
42
Junxiao Shi2570f3e2016-07-27 02:48:29 +000043shared_ptr<Entry>
Junxiao Shib660b4c2016-08-06 20:47:44 +000044NameTree::lookup(const Name& name)
HYuana9b85752014-02-26 02:32:30 -060045{
Junxiao Shib660b4c2016-08-06 20:47:44 +000046 NFD_LOG_TRACE("lookup " << name);
HYuana9b85752014-02-26 02:32:30 -060047
Junxiao Shib660b4c2016-08-06 20:47:44 +000048 HashSequence hashes = computeHashes(name);
49 const Node* node = nullptr;
50 Entry* parent = nullptr;
HYuana9b85752014-02-26 02:32:30 -060051
Junxiao Shib660b4c2016-08-06 20:47:44 +000052 for (size_t prefixLen = 0; prefixLen <= name.size(); ++prefixLen) {
Junxiao Shi2570f3e2016-07-27 02:48:29 +000053 bool isNew = false;
Junxiao Shib660b4c2016-08-06 20:47:44 +000054 std::tie(node, isNew) = m_ht.insert(name, prefixLen, hashes);
HYuana9b85752014-02-26 02:32:30 -060055
Junxiao Shib660b4c2016-08-06 20:47:44 +000056 if (isNew && parent != nullptr) {
57 node->entry->setParent(*parent);
HYuana9b85752014-02-26 02:32:30 -060058 }
Junxiao Shib660b4c2016-08-06 20:47:44 +000059 parent = node->entry.get();
Junxiao Shi2570f3e2016-07-27 02:48:29 +000060 }
Junxiao Shib660b4c2016-08-06 20:47:44 +000061 return node->entry;
HYuana9b85752014-02-26 02:32:30 -060062}
63
Junxiao Shi2570f3e2016-07-27 02:48:29 +000064shared_ptr<Entry>
Junxiao Shib184e532016-05-26 18:09:57 +000065NameTree::lookup(const fib::Entry& fibEntry) const
66{
Junxiao Shi2570f3e2016-07-27 02:48:29 +000067 shared_ptr<Entry> nte = this->getEntry(fibEntry);
Junxiao Shia6de4292016-07-12 02:08:10 +000068 BOOST_ASSERT(nte == nullptr || nte->getFibEntry() == &fibEntry);
Junxiao Shib184e532016-05-26 18:09:57 +000069 return nte;
70}
71
Junxiao Shi2570f3e2016-07-27 02:48:29 +000072shared_ptr<Entry>
Junxiao Shib184e532016-05-26 18:09:57 +000073NameTree::lookup(const pit::Entry& pitEntry)
74{
Junxiao Shi2570f3e2016-07-27 02:48:29 +000075 shared_ptr<Entry> nte = this->getEntry(pitEntry);
Junxiao Shib184e532016-05-26 18:09:57 +000076 if (nte == nullptr) {
77 return nullptr;
78 }
79
Junxiao Shie3cf2852016-08-09 03:50:56 +000080 if (nte->getName().size() == pitEntry.getName().size()) {
Junxiao Shib184e532016-05-26 18:09:57 +000081 return nte;
82 }
83
84 BOOST_ASSERT(pitEntry.getName().at(-1).isImplicitSha256Digest());
Junxiao Shie3cf2852016-08-09 03:50:56 +000085 BOOST_ASSERT(nte->getName() == pitEntry.getName().getPrefix(-1));
Junxiao Shib184e532016-05-26 18:09:57 +000086 return this->lookup(pitEntry.getName());
87}
88
Junxiao Shi2570f3e2016-07-27 02:48:29 +000089shared_ptr<Entry>
Junxiao Shib184e532016-05-26 18:09:57 +000090NameTree::lookup(const measurements::Entry& measurementsEntry) const
91{
Junxiao Shi2570f3e2016-07-27 02:48:29 +000092 shared_ptr<Entry> nte = this->getEntry(measurementsEntry);
Junxiao Shi80f9fcd2016-07-23 02:48:36 +000093 BOOST_ASSERT(nte == nullptr || nte->getMeasurementsEntry() == &measurementsEntry);
Junxiao Shib184e532016-05-26 18:09:57 +000094 return nte;
95}
96
Junxiao Shi2570f3e2016-07-27 02:48:29 +000097shared_ptr<Entry>
Junxiao Shib184e532016-05-26 18:09:57 +000098NameTree::lookup(const strategy_choice::Entry& strategyChoiceEntry) const
99{
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000100 shared_ptr<Entry> nte = this->getEntry(strategyChoiceEntry);
Junxiao Shiff10da62016-07-13 17:57:43 +0000101 BOOST_ASSERT(nte == nullptr || nte->getStrategyChoiceEntry() == &strategyChoiceEntry);
Junxiao Shib184e532016-05-26 18:09:57 +0000102 return nte;
103}
104
Junxiao Shib660b4c2016-08-06 20:47:44 +0000105size_t
Junxiao Shie3cf2852016-08-09 03:50:56 +0000106NameTree::eraseIfEmpty(Entry* entry)
Junxiao Shi4370fde2016-02-24 12:20:46 -0700107{
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000108 BOOST_ASSERT(entry != nullptr);
Junxiao Shi4370fde2016-02-24 12:20:46 -0700109
Junxiao Shib660b4c2016-08-06 20:47:44 +0000110 size_t nErased = 0;
111 for (Entry* parent = nullptr; entry != nullptr && entry->isEmpty(); entry = parent) {
112 parent = entry->getParent();
Junxiao Shi4370fde2016-02-24 12:20:46 -0700113
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000114 if (parent != nullptr) {
Junxiao Shib660b4c2016-08-06 20:47:44 +0000115 entry->unsetParent();
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000116 }
Junxiao Shi4370fde2016-02-24 12:20:46 -0700117
Junxiao Shib660b4c2016-08-06 20:47:44 +0000118 m_ht.erase(getNode(*entry));
119 ++nErased;
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000120 }
121
Junxiao Shib660b4c2016-08-06 20:47:44 +0000122 if (nErased == 0) {
123 NFD_LOG_TRACE("not-erase " << entry->getName());
124 }
125 return nErased;
Junxiao Shi4370fde2016-02-24 12:20:46 -0700126}
127
Junxiao Shi811c0102016-08-10 04:12:45 +0000128Entry*
Junxiao Shib660b4c2016-08-06 20:47:44 +0000129NameTree::findExactMatch(const Name& name) const
HYuana9b85752014-02-26 02:32:30 -0600130{
Junxiao Shib660b4c2016-08-06 20:47:44 +0000131 const Node* node = m_ht.find(name, name.size());
Junxiao Shi811c0102016-08-10 04:12:45 +0000132 return node == nullptr ? nullptr : node->entry.get();
HYuana9b85752014-02-26 02:32:30 -0600133}
134
Junxiao Shi811c0102016-08-10 04:12:45 +0000135Entry*
Junxiao Shib660b4c2016-08-06 20:47:44 +0000136NameTree::findLongestPrefixMatch(const Name& name, const EntrySelector& entrySelector) const
HYuana9b85752014-02-26 02:32:30 -0600137{
Junxiao Shib660b4c2016-08-06 20:47:44 +0000138 HashSequence hashes = computeHashes(name);
HYuana9b85752014-02-26 02:32:30 -0600139
Junxiao Shib660b4c2016-08-06 20:47:44 +0000140 for (ssize_t prefixLen = name.size(); prefixLen >= 0; --prefixLen) {
141 const Node* node = m_ht.find(name, prefixLen, hashes);
142 if (node != nullptr && entrySelector(*node->entry)) {
Junxiao Shi811c0102016-08-10 04:12:45 +0000143 return node->entry.get();
HYuana9b85752014-02-26 02:32:30 -0600144 }
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000145 }
HYuana9b85752014-02-26 02:32:30 -0600146
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000147 return nullptr;
HYuana9b85752014-02-26 02:32:30 -0600148}
149
Junxiao Shi811c0102016-08-10 04:12:45 +0000150Entry*
151NameTree::findLongestPrefixMatch(const Entry& entry1, const EntrySelector& entrySelector) const
HangZhangcb4fc832014-03-11 16:57:11 +0800152{
Junxiao Shi811c0102016-08-10 04:12:45 +0000153 Entry* entry = const_cast<Entry*>(&entry1);
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000154 while (entry != nullptr) {
155 if (entrySelector(*entry)) {
Junxiao Shi811c0102016-08-10 04:12:45 +0000156 return entry;
HangZhangcb4fc832014-03-11 16:57:11 +0800157 }
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000158 entry = entry->getParent();
159 }
160 return nullptr;
HangZhangcb4fc832014-03-11 16:57:11 +0800161}
162
Junxiao Shi811c0102016-08-10 04:12:45 +0000163Entry*
Junxiao Shi4370fde2016-02-24 12:20:46 -0700164NameTree::findLongestPrefixMatch(const pit::Entry& pitEntry) const
HYuana9b85752014-02-26 02:32:30 -0600165{
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000166 shared_ptr<Entry> nte = this->getEntry(pitEntry);
Junxiao Shib184e532016-05-26 18:09:57 +0000167 BOOST_ASSERT(nte != nullptr);
Junxiao Shie3cf2852016-08-09 03:50:56 +0000168 if (nte->getName().size() == pitEntry.getName().size()) {
Junxiao Shi811c0102016-08-10 04:12:45 +0000169 return nte.get();
Junxiao Shi4370fde2016-02-24 12:20:46 -0700170 }
HYuana9b85752014-02-26 02:32:30 -0600171
Junxiao Shi811c0102016-08-10 04:12:45 +0000172 // special case: PIT entry whose Interest name ends with an implicit digest
173 // are attached to the name tree entry with one-shorter-prefix.
Junxiao Shi4370fde2016-02-24 12:20:46 -0700174 BOOST_ASSERT(pitEntry.getName().at(-1).isImplicitSha256Digest());
Junxiao Shie3cf2852016-08-09 03:50:56 +0000175 BOOST_ASSERT(nte->getName() == pitEntry.getName().getPrefix(-1));
Junxiao Shi811c0102016-08-10 04:12:45 +0000176 Entry* exact = this->findExactMatch(pitEntry.getName());
177 return exact == nullptr ? nte.get() : exact;
Junxiao Shi4370fde2016-02-24 12:20:46 -0700178}
HYuana9b85752014-02-26 02:32:30 -0600179
Junxiao Shi4370fde2016-02-24 12:20:46 -0700180boost::iterator_range<NameTree::const_iterator>
Junxiao Shie3cf2852016-08-09 03:50:56 +0000181NameTree::findAllMatches(const Name& name, const EntrySelector& entrySelector) const
Junxiao Shi4370fde2016-02-24 12:20:46 -0700182{
Junxiao Shie3cf2852016-08-09 03:50:56 +0000183 NFD_LOG_TRACE("NameTree::findAllMatches" << name);
HYuana9b85752014-02-26 02:32:30 -0600184
Junxiao Shi4370fde2016-02-24 12:20:46 -0700185 // As we are using Name Prefix Hash Table, and the current LPM() is
186 // implemented as starting from full name, and reduce the number of
187 // components by 1 each time, we could use it here.
188 // For trie-like design, it could be more efficient by walking down the
189 // trie from the root node.
HYuana9b85752014-02-26 02:32:30 -0600190
Junxiao Shi811c0102016-08-10 04:12:45 +0000191 Entry* entry = findLongestPrefixMatch(name, entrySelector);
192 return {Iterator(make_shared<PrefixMatchImpl>(*this, entrySelector), entry), end()};
HYuana9b85752014-02-26 02:32:30 -0600193}
194
Junxiao Shi5ccd0c22014-12-02 23:54:42 -0700195boost::iterator_range<NameTree::const_iterator>
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000196NameTree::fullEnumerate(const EntrySelector& entrySelector) const
HYuana9b85752014-02-26 02:32:30 -0600197{
Alexander Afanasyevbf9edee2014-03-31 23:05:27 -0700198 NFD_LOG_TRACE("fullEnumerate");
HYuana9b85752014-02-26 02:32:30 -0600199
Junxiao Shi029401f2016-08-05 12:55:14 +0000200 return {Iterator(make_shared<FullEnumerationImpl>(*this, entrySelector), nullptr), end()};
Haowei Yuane1079fc2014-03-08 14:41:25 -0600201}
202
Junxiao Shi5ccd0c22014-12-02 23:54:42 -0700203boost::iterator_range<NameTree::const_iterator>
Haowei Yuane1079fc2014-03-08 14:41:25 -0600204NameTree::partialEnumerate(const Name& prefix,
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000205 const EntrySubTreeSelector& entrySubTreeSelector) const
Haowei Yuane1079fc2014-03-08 14:41:25 -0600206{
207 // the first step is to process the root node
Junxiao Shi811c0102016-08-10 04:12:45 +0000208 Entry* entry = this->findExactMatch(prefix);
209 return {Iterator(make_shared<PartialEnumerationImpl>(*this, entrySubTreeSelector), entry), end()};
HYuana9b85752014-02-26 02:32:30 -0600210}
211
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000212} // namespace name_tree
HYuana9b85752014-02-26 02:32:30 -0600213} // namespace nfd