blob: b806cd45734ce98096e0cd06bf069b0027956c1a [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 Shi7f358432016-08-11 17:06:33 +000043Entry&
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 Shi7f358432016-08-11 17:06:33 +000061 return *node->entry;
HYuana9b85752014-02-26 02:32:30 -060062}
63
Junxiao Shi7f358432016-08-11 17:06:33 +000064Entry&
Junxiao Shif2420fc2016-08-11 13:18:21 +000065NameTree::lookup(const fib::Entry& fibEntry)
Junxiao Shib184e532016-05-26 18:09:57 +000066{
Junxiao Shi7f358432016-08-11 17:06:33 +000067 Entry* nte = this->getEntry(fibEntry);
Junxiao Shif2420fc2016-08-11 13:18:21 +000068 if (nte == nullptr) {
69 // special case: Fib::s_emptyEntry is unattached
70 BOOST_ASSERT(fibEntry.getPrefix().empty());
71 return this->lookup(fibEntry.getPrefix());
72 }
73
74 BOOST_ASSERT(nte->getFibEntry() == &fibEntry);
Junxiao Shi7f358432016-08-11 17:06:33 +000075 return *nte;
Junxiao Shib184e532016-05-26 18:09:57 +000076}
77
Junxiao Shi7f358432016-08-11 17:06:33 +000078Entry&
Junxiao Shib184e532016-05-26 18:09:57 +000079NameTree::lookup(const pit::Entry& pitEntry)
80{
Junxiao Shi7f358432016-08-11 17:06:33 +000081 Entry* nte = this->getEntry(pitEntry);
Junxiao Shif2420fc2016-08-11 13:18:21 +000082 BOOST_ASSERT(nte != nullptr);
83
84 BOOST_ASSERT(std::count_if(nte->getPitEntries().begin(), nte->getPitEntries().end(),
85 [&pitEntry] (const shared_ptr<pit::Entry>& pitEntry1) {
86 return pitEntry1.get() == &pitEntry;
87 }) == 1);
Junxiao Shib184e532016-05-26 18:09:57 +000088
Junxiao Shie3cf2852016-08-09 03:50:56 +000089 if (nte->getName().size() == pitEntry.getName().size()) {
Junxiao Shi7f358432016-08-11 17:06:33 +000090 return *nte;
Junxiao Shib184e532016-05-26 18:09:57 +000091 }
92
Junxiao Shif2420fc2016-08-11 13:18:21 +000093 // special case: PIT entry whose Interest name ends with an implicit digest
94 // are attached to the name tree entry with one-shorter-prefix.
Junxiao Shib184e532016-05-26 18:09:57 +000095 BOOST_ASSERT(pitEntry.getName().at(-1).isImplicitSha256Digest());
Junxiao Shie3cf2852016-08-09 03:50:56 +000096 BOOST_ASSERT(nte->getName() == pitEntry.getName().getPrefix(-1));
Junxiao Shib184e532016-05-26 18:09:57 +000097 return this->lookup(pitEntry.getName());
98}
99
Junxiao Shi7f358432016-08-11 17:06:33 +0000100Entry&
Junxiao Shif2420fc2016-08-11 13:18:21 +0000101NameTree::lookup(const measurements::Entry& measurementsEntry)
Junxiao Shib184e532016-05-26 18:09:57 +0000102{
Junxiao Shi7f358432016-08-11 17:06:33 +0000103 Entry* nte = this->getEntry(measurementsEntry);
Junxiao Shif2420fc2016-08-11 13:18:21 +0000104 BOOST_ASSERT(nte != nullptr);
105
106 BOOST_ASSERT(nte->getMeasurementsEntry() == &measurementsEntry);
Junxiao Shi7f358432016-08-11 17:06:33 +0000107 return *nte;
Junxiao Shib184e532016-05-26 18:09:57 +0000108}
109
Junxiao Shi7f358432016-08-11 17:06:33 +0000110Entry&
Junxiao Shif2420fc2016-08-11 13:18:21 +0000111NameTree::lookup(const strategy_choice::Entry& strategyChoiceEntry)
Junxiao Shib184e532016-05-26 18:09:57 +0000112{
Junxiao Shi7f358432016-08-11 17:06:33 +0000113 Entry* nte = this->getEntry(strategyChoiceEntry);
Junxiao Shif2420fc2016-08-11 13:18:21 +0000114 BOOST_ASSERT(nte != nullptr);
115
116 BOOST_ASSERT(nte->getStrategyChoiceEntry() == &strategyChoiceEntry);
Junxiao Shi7f358432016-08-11 17:06:33 +0000117 return *nte;
Junxiao Shib184e532016-05-26 18:09:57 +0000118}
119
Junxiao Shib660b4c2016-08-06 20:47:44 +0000120size_t
Junxiao Shie3cf2852016-08-09 03:50:56 +0000121NameTree::eraseIfEmpty(Entry* entry)
Junxiao Shi4370fde2016-02-24 12:20:46 -0700122{
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000123 BOOST_ASSERT(entry != nullptr);
Junxiao Shi4370fde2016-02-24 12:20:46 -0700124
Junxiao Shib660b4c2016-08-06 20:47:44 +0000125 size_t nErased = 0;
126 for (Entry* parent = nullptr; entry != nullptr && entry->isEmpty(); entry = parent) {
127 parent = entry->getParent();
Junxiao Shi4370fde2016-02-24 12:20:46 -0700128
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000129 if (parent != nullptr) {
Junxiao Shib660b4c2016-08-06 20:47:44 +0000130 entry->unsetParent();
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000131 }
Junxiao Shi4370fde2016-02-24 12:20:46 -0700132
Junxiao Shib660b4c2016-08-06 20:47:44 +0000133 m_ht.erase(getNode(*entry));
134 ++nErased;
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000135 }
136
Junxiao Shib660b4c2016-08-06 20:47:44 +0000137 if (nErased == 0) {
138 NFD_LOG_TRACE("not-erase " << entry->getName());
139 }
140 return nErased;
Junxiao Shi4370fde2016-02-24 12:20:46 -0700141}
142
Junxiao Shi811c0102016-08-10 04:12:45 +0000143Entry*
Junxiao Shib660b4c2016-08-06 20:47:44 +0000144NameTree::findExactMatch(const Name& name) const
HYuana9b85752014-02-26 02:32:30 -0600145{
Junxiao Shib660b4c2016-08-06 20:47:44 +0000146 const Node* node = m_ht.find(name, name.size());
Junxiao Shi811c0102016-08-10 04:12:45 +0000147 return node == nullptr ? nullptr : node->entry.get();
HYuana9b85752014-02-26 02:32:30 -0600148}
149
Junxiao Shi811c0102016-08-10 04:12:45 +0000150Entry*
Junxiao Shib660b4c2016-08-06 20:47:44 +0000151NameTree::findLongestPrefixMatch(const Name& name, const EntrySelector& entrySelector) const
HYuana9b85752014-02-26 02:32:30 -0600152{
Junxiao Shib660b4c2016-08-06 20:47:44 +0000153 HashSequence hashes = computeHashes(name);
HYuana9b85752014-02-26 02:32:30 -0600154
Junxiao Shib660b4c2016-08-06 20:47:44 +0000155 for (ssize_t prefixLen = name.size(); prefixLen >= 0; --prefixLen) {
156 const Node* node = m_ht.find(name, prefixLen, hashes);
157 if (node != nullptr && entrySelector(*node->entry)) {
Junxiao Shi811c0102016-08-10 04:12:45 +0000158 return node->entry.get();
HYuana9b85752014-02-26 02:32:30 -0600159 }
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000160 }
HYuana9b85752014-02-26 02:32:30 -0600161
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000162 return nullptr;
HYuana9b85752014-02-26 02:32:30 -0600163}
164
Junxiao Shi811c0102016-08-10 04:12:45 +0000165Entry*
166NameTree::findLongestPrefixMatch(const Entry& entry1, const EntrySelector& entrySelector) const
HangZhangcb4fc832014-03-11 16:57:11 +0800167{
Junxiao Shi811c0102016-08-10 04:12:45 +0000168 Entry* entry = const_cast<Entry*>(&entry1);
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000169 while (entry != nullptr) {
170 if (entrySelector(*entry)) {
Junxiao Shi811c0102016-08-10 04:12:45 +0000171 return entry;
HangZhangcb4fc832014-03-11 16:57:11 +0800172 }
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000173 entry = entry->getParent();
174 }
175 return nullptr;
HangZhangcb4fc832014-03-11 16:57:11 +0800176}
177
Junxiao Shidd8f6612016-08-12 15:42:52 +0000178template<typename ENTRY>
179Entry*
180NameTree::findLongestPrefixMatch(const ENTRY& tableEntry, const EntrySelector& entrySelector) const
181{
182 const Entry* nte = this->getEntry(tableEntry);
183 BOOST_ASSERT(nte != nullptr);
184 return this->findLongestPrefixMatch(*nte, entrySelector);
185}
186
187template Entry*
188NameTree::findLongestPrefixMatch<fib::Entry>(const fib::Entry&, const EntrySelector&) const;
189
190template Entry*
191NameTree::findLongestPrefixMatch<measurements::Entry>(const measurements::Entry&,
192 const EntrySelector&) const;
193
194template Entry*
195NameTree::findLongestPrefixMatch<strategy_choice::Entry>(const strategy_choice::Entry&,
196 const EntrySelector&) const;
197
Junxiao Shi811c0102016-08-10 04:12:45 +0000198Entry*
Junxiao Shif2420fc2016-08-11 13:18:21 +0000199NameTree::findLongestPrefixMatch(const pit::Entry& pitEntry, const EntrySelector& entrySelector) const
HYuana9b85752014-02-26 02:32:30 -0600200{
Junxiao Shi7f358432016-08-11 17:06:33 +0000201 const Entry* nte = this->getEntry(pitEntry);
Junxiao Shib184e532016-05-26 18:09:57 +0000202 BOOST_ASSERT(nte != nullptr);
Junxiao Shif2420fc2016-08-11 13:18:21 +0000203
204 if (nte->getName().size() < pitEntry.getName().size()) {
205 // special case: PIT entry whose Interest name ends with an implicit digest
206 // are attached to the name tree entry with one-shorter-prefix.
207 BOOST_ASSERT(pitEntry.getName().at(-1).isImplicitSha256Digest());
208 BOOST_ASSERT(nte->getName() == pitEntry.getName().getPrefix(-1));
209 const Entry* exact = this->findExactMatch(pitEntry.getName());
210 if (exact != nullptr) {
211 nte = exact;
212 }
Junxiao Shi4370fde2016-02-24 12:20:46 -0700213 }
HYuana9b85752014-02-26 02:32:30 -0600214
Junxiao Shif2420fc2016-08-11 13:18:21 +0000215 return this->findLongestPrefixMatch(*nte, entrySelector);
Junxiao Shi4370fde2016-02-24 12:20:46 -0700216}
HYuana9b85752014-02-26 02:32:30 -0600217
Junxiao Shi4370fde2016-02-24 12:20:46 -0700218boost::iterator_range<NameTree::const_iterator>
Junxiao Shie3cf2852016-08-09 03:50:56 +0000219NameTree::findAllMatches(const Name& name, const EntrySelector& entrySelector) const
Junxiao Shi4370fde2016-02-24 12:20:46 -0700220{
Junxiao Shi4370fde2016-02-24 12:20:46 -0700221 // As we are using Name Prefix Hash Table, and the current LPM() is
222 // implemented as starting from full name, and reduce the number of
223 // components by 1 each time, we could use it here.
224 // For trie-like design, it could be more efficient by walking down the
225 // trie from the root node.
HYuana9b85752014-02-26 02:32:30 -0600226
Junxiao Shi7f358432016-08-11 17:06:33 +0000227 Entry* entry = this->findLongestPrefixMatch(name, entrySelector);
Junxiao Shi811c0102016-08-10 04:12:45 +0000228 return {Iterator(make_shared<PrefixMatchImpl>(*this, entrySelector), entry), end()};
HYuana9b85752014-02-26 02:32:30 -0600229}
230
Junxiao Shi5ccd0c22014-12-02 23:54:42 -0700231boost::iterator_range<NameTree::const_iterator>
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000232NameTree::fullEnumerate(const EntrySelector& entrySelector) const
HYuana9b85752014-02-26 02:32:30 -0600233{
Junxiao Shi029401f2016-08-05 12:55:14 +0000234 return {Iterator(make_shared<FullEnumerationImpl>(*this, entrySelector), nullptr), end()};
Haowei Yuane1079fc2014-03-08 14:41:25 -0600235}
236
Junxiao Shi5ccd0c22014-12-02 23:54:42 -0700237boost::iterator_range<NameTree::const_iterator>
Haowei Yuane1079fc2014-03-08 14:41:25 -0600238NameTree::partialEnumerate(const Name& prefix,
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000239 const EntrySubTreeSelector& entrySubTreeSelector) const
Haowei Yuane1079fc2014-03-08 14:41:25 -0600240{
Junxiao Shi811c0102016-08-10 04:12:45 +0000241 Entry* entry = this->findExactMatch(prefix);
242 return {Iterator(make_shared<PartialEnumerationImpl>(*this, entrySubTreeSelector), entry), end()};
HYuana9b85752014-02-26 02:32:30 -0600243}
244
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000245} // namespace name_tree
HYuana9b85752014-02-26 02:32:30 -0600246} // namespace nfd