blob: 993a58abb702d3a1d28cee14041f46cf8dd30f35 [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 Shi2570f3e2016-07-27 02:48:29 +0000128shared_ptr<Entry>
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());
132 return node == nullptr ? nullptr : node->entry;
HYuana9b85752014-02-26 02:32:30 -0600133}
134
135// Longest Prefix Match
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000136shared_ptr<Entry>
Junxiao Shib660b4c2016-08-06 20:47:44 +0000137NameTree::findLongestPrefixMatch(const Name& name, const EntrySelector& entrySelector) const
HYuana9b85752014-02-26 02:32:30 -0600138{
Junxiao Shib660b4c2016-08-06 20:47:44 +0000139 HashSequence hashes = computeHashes(name);
HYuana9b85752014-02-26 02:32:30 -0600140
Junxiao Shib660b4c2016-08-06 20:47:44 +0000141 for (ssize_t prefixLen = name.size(); prefixLen >= 0; --prefixLen) {
142 const Node* node = m_ht.find(name, prefixLen, hashes);
143 if (node != nullptr && entrySelector(*node->entry)) {
144 return node->entry;
HYuana9b85752014-02-26 02:32:30 -0600145 }
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000146 }
HYuana9b85752014-02-26 02:32:30 -0600147
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000148 return nullptr;
HYuana9b85752014-02-26 02:32:30 -0600149}
150
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000151shared_ptr<Entry>
Junxiao Shib660b4c2016-08-06 20:47:44 +0000152NameTree::findLongestPrefixMatch(shared_ptr<Entry> entry1,
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000153 const EntrySelector& entrySelector) const
HangZhangcb4fc832014-03-11 16:57:11 +0800154{
Junxiao Shib660b4c2016-08-06 20:47:44 +0000155 Entry* entry = entry1.get();
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000156 while (entry != nullptr) {
157 if (entrySelector(*entry)) {
Junxiao Shib660b4c2016-08-06 20:47:44 +0000158 return entry->shared_from_this();
HangZhangcb4fc832014-03-11 16:57:11 +0800159 }
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000160 entry = entry->getParent();
161 }
162 return nullptr;
HangZhangcb4fc832014-03-11 16:57:11 +0800163}
164
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000165shared_ptr<Entry>
Junxiao Shi4370fde2016-02-24 12:20:46 -0700166NameTree::findLongestPrefixMatch(const pit::Entry& pitEntry) const
HYuana9b85752014-02-26 02:32:30 -0600167{
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000168 shared_ptr<Entry> nte = this->getEntry(pitEntry);
Junxiao Shib184e532016-05-26 18:09:57 +0000169 BOOST_ASSERT(nte != nullptr);
Junxiao Shie3cf2852016-08-09 03:50:56 +0000170 if (nte->getName().size() == pitEntry.getName().size()) {
Junxiao Shi4370fde2016-02-24 12:20:46 -0700171 return nte;
172 }
HYuana9b85752014-02-26 02:32:30 -0600173
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 Shi2570f3e2016-07-27 02:48:29 +0000176 shared_ptr<Entry> exact = this->findExactMatch(pitEntry.getName());
Junxiao Shi4370fde2016-02-24 12:20:46 -0700177 return exact == nullptr ? nte : exact;
178}
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 Shie3cf2852016-08-09 03:50:56 +0000191 shared_ptr<Entry> entry = findLongestPrefixMatch(name, entrySelector);
Junxiao Shib660b4c2016-08-06 20:47:44 +0000192 return {Iterator(make_shared<PrefixMatchImpl>(*this, entrySelector), entry.get()), 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 Shi2570f3e2016-07-27 02:48:29 +0000208 shared_ptr<Entry> entry = findExactMatch(prefix);
Junxiao Shib660b4c2016-08-06 20:47:44 +0000209 return {Iterator(make_shared<PartialEnumerationImpl>(*this, entrySubTreeSelector), entry.get()), 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