blob: db0e3ff32be9babeb60be30c80fca6f88a6e30de [file] [log] [blame]
HYuana9b85752014-02-26 02:32:30 -06001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesaventoc0a5a392017-08-19 16:49:30 -04002/*
3 * Copyright (c) 2014-2017, 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) {
Junxiao Shi340d5532016-08-13 04:00:35 +000057 node->entry.setParent(*parent);
HYuana9b85752014-02-26 02:32:30 -060058 }
Junxiao Shi340d5532016-08-13 04:00:35 +000059 parent = &node->entry;
Junxiao Shi2570f3e2016-07-27 02:48:29 +000060 }
Junxiao Shi340d5532016-08-13 04:00:35 +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 Shie7258ff2016-08-12 23:55:47 +0000121NameTree::eraseIfEmpty(Entry* entry, bool canEraseAncestors)
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 Shie7258ff2016-08-12 23:55:47 +0000135
136 if (!canEraseAncestors) {
137 break;
138 }
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000139 }
140
Junxiao Shib660b4c2016-08-06 20:47:44 +0000141 if (nErased == 0) {
142 NFD_LOG_TRACE("not-erase " << entry->getName());
143 }
144 return nErased;
Junxiao Shi4370fde2016-02-24 12:20:46 -0700145}
146
Junxiao Shi811c0102016-08-10 04:12:45 +0000147Entry*
Junxiao Shib660b4c2016-08-06 20:47:44 +0000148NameTree::findExactMatch(const Name& name) const
HYuana9b85752014-02-26 02:32:30 -0600149{
Junxiao Shib660b4c2016-08-06 20:47:44 +0000150 const Node* node = m_ht.find(name, name.size());
Junxiao Shi340d5532016-08-13 04:00:35 +0000151 return node == nullptr ? nullptr : &node->entry;
HYuana9b85752014-02-26 02:32:30 -0600152}
153
Junxiao Shi811c0102016-08-10 04:12:45 +0000154Entry*
Junxiao Shib660b4c2016-08-06 20:47:44 +0000155NameTree::findLongestPrefixMatch(const Name& name, const EntrySelector& entrySelector) const
HYuana9b85752014-02-26 02:32:30 -0600156{
Junxiao Shib660b4c2016-08-06 20:47:44 +0000157 HashSequence hashes = computeHashes(name);
HYuana9b85752014-02-26 02:32:30 -0600158
Junxiao Shib660b4c2016-08-06 20:47:44 +0000159 for (ssize_t prefixLen = name.size(); prefixLen >= 0; --prefixLen) {
160 const Node* node = m_ht.find(name, prefixLen, hashes);
Junxiao Shi340d5532016-08-13 04:00:35 +0000161 if (node != nullptr && entrySelector(node->entry)) {
162 return &node->entry;
HYuana9b85752014-02-26 02:32:30 -0600163 }
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000164 }
HYuana9b85752014-02-26 02:32:30 -0600165
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000166 return nullptr;
HYuana9b85752014-02-26 02:32:30 -0600167}
168
Junxiao Shi811c0102016-08-10 04:12:45 +0000169Entry*
170NameTree::findLongestPrefixMatch(const Entry& entry1, const EntrySelector& entrySelector) const
HangZhangcb4fc832014-03-11 16:57:11 +0800171{
Junxiao Shi811c0102016-08-10 04:12:45 +0000172 Entry* entry = const_cast<Entry*>(&entry1);
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000173 while (entry != nullptr) {
174 if (entrySelector(*entry)) {
Junxiao Shi811c0102016-08-10 04:12:45 +0000175 return entry;
HangZhangcb4fc832014-03-11 16:57:11 +0800176 }
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000177 entry = entry->getParent();
178 }
179 return nullptr;
HangZhangcb4fc832014-03-11 16:57:11 +0800180}
181
Junxiao Shi811c0102016-08-10 04:12:45 +0000182Entry*
Junxiao Shif2420fc2016-08-11 13:18:21 +0000183NameTree::findLongestPrefixMatch(const pit::Entry& pitEntry, const EntrySelector& entrySelector) const
HYuana9b85752014-02-26 02:32:30 -0600184{
Junxiao Shi7f358432016-08-11 17:06:33 +0000185 const Entry* nte = this->getEntry(pitEntry);
Junxiao Shib184e532016-05-26 18:09:57 +0000186 BOOST_ASSERT(nte != nullptr);
Junxiao Shif2420fc2016-08-11 13:18:21 +0000187
188 if (nte->getName().size() < pitEntry.getName().size()) {
189 // special case: PIT entry whose Interest name ends with an implicit digest
190 // are attached to the name tree entry with one-shorter-prefix.
191 BOOST_ASSERT(pitEntry.getName().at(-1).isImplicitSha256Digest());
192 BOOST_ASSERT(nte->getName() == pitEntry.getName().getPrefix(-1));
193 const Entry* exact = this->findExactMatch(pitEntry.getName());
194 if (exact != nullptr) {
195 nte = exact;
196 }
Junxiao Shi4370fde2016-02-24 12:20:46 -0700197 }
HYuana9b85752014-02-26 02:32:30 -0600198
Junxiao Shif2420fc2016-08-11 13:18:21 +0000199 return this->findLongestPrefixMatch(*nte, entrySelector);
Junxiao Shi4370fde2016-02-24 12:20:46 -0700200}
HYuana9b85752014-02-26 02:32:30 -0600201
Junxiao Shi4370fde2016-02-24 12:20:46 -0700202boost::iterator_range<NameTree::const_iterator>
Junxiao Shie3cf2852016-08-09 03:50:56 +0000203NameTree::findAllMatches(const Name& name, const EntrySelector& entrySelector) const
Junxiao Shi4370fde2016-02-24 12:20:46 -0700204{
Junxiao Shi4370fde2016-02-24 12:20:46 -0700205 // As we are using Name Prefix Hash Table, and the current LPM() is
206 // implemented as starting from full name, and reduce the number of
207 // components by 1 each time, we could use it here.
208 // For trie-like design, it could be more efficient by walking down the
209 // trie from the root node.
HYuana9b85752014-02-26 02:32:30 -0600210
Junxiao Shi7f358432016-08-11 17:06:33 +0000211 Entry* entry = this->findLongestPrefixMatch(name, entrySelector);
Junxiao Shi811c0102016-08-10 04:12:45 +0000212 return {Iterator(make_shared<PrefixMatchImpl>(*this, entrySelector), entry), end()};
HYuana9b85752014-02-26 02:32:30 -0600213}
214
Junxiao Shi5ccd0c22014-12-02 23:54:42 -0700215boost::iterator_range<NameTree::const_iterator>
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000216NameTree::fullEnumerate(const EntrySelector& entrySelector) const
HYuana9b85752014-02-26 02:32:30 -0600217{
Junxiao Shi029401f2016-08-05 12:55:14 +0000218 return {Iterator(make_shared<FullEnumerationImpl>(*this, entrySelector), nullptr), end()};
Haowei Yuane1079fc2014-03-08 14:41:25 -0600219}
220
Junxiao Shi5ccd0c22014-12-02 23:54:42 -0700221boost::iterator_range<NameTree::const_iterator>
Haowei Yuane1079fc2014-03-08 14:41:25 -0600222NameTree::partialEnumerate(const Name& prefix,
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000223 const EntrySubTreeSelector& entrySubTreeSelector) const
Haowei Yuane1079fc2014-03-08 14:41:25 -0600224{
Junxiao Shi811c0102016-08-10 04:12:45 +0000225 Entry* entry = this->findExactMatch(prefix);
226 return {Iterator(make_shared<PartialEnumerationImpl>(*this, entrySubTreeSelector), entry), end()};
HYuana9b85752014-02-26 02:32:30 -0600227}
228
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000229} // namespace name_tree
HYuana9b85752014-02-26 02:32:30 -0600230} // namespace nfd