blob: b4e12ede2c451aa51b74a2e2605084cb4a9f2110 [file] [log] [blame]
HYuana9b85752014-02-26 02:32:30 -06001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Junxiao Shiee5a4442014-07-27 17:13:43 -07003 * Copyright (c) 2014, Regents of the University of California,
4 * 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 Shiee5a4442014-07-27 17:13:43 -070024 */
HYuana9b85752014-02-26 02:32:30 -060025
Alexander Afanasyev613e2a92014-04-15 13:36:58 -070026#ifndef NFD_DAEMON_TABLE_NAME_TREE_HPP
27#define NFD_DAEMON_TABLE_NAME_TREE_HPP
HYuana9b85752014-02-26 02:32:30 -060028
29#include "common.hpp"
30#include "name-tree-entry.hpp"
31
32namespace nfd {
33namespace name_tree {
34
35/**
Haowei Yuanf52dac72014-03-24 23:35:03 -050036 * \brief Compute the hash value of the given name prefix's WIRE FORMAT
HYuana9b85752014-02-26 02:32:30 -060037 */
Haowei Yuanf52dac72014-03-24 23:35:03 -050038size_t
39computeHash(const Name& prefix);
40
41/**
42 * \brief Incrementally compute hash values
43 * \return Return a vector of hash values, starting from the root prefix
44 */
45std::vector<size_t>
46computeHashSet(const Name& prefix);
HYuana9b85752014-02-26 02:32:30 -060047
Junxiao Shi40631842014-03-01 13:52:37 -070048/// a predicate to accept or reject an Entry in find operations
49typedef function<bool (const Entry& entry)> EntrySelector;
50
Haowei Yuane1079fc2014-03-08 14:41:25 -060051/**
52 * \brief a predicate to accept or reject an Entry and its children
53 * \return .first indicates whether entry should be accepted;
54 * .second indicates whether entry's children should be visited
55 */
56typedef function<std::pair<bool,bool> (const Entry& entry)> EntrySubTreeSelector;
57
Junxiao Shi40631842014-03-01 13:52:37 -070058struct AnyEntry {
59 bool
60 operator()(const Entry& entry)
61 {
62 return true;
63 }
64};
65
Haowei Yuane1079fc2014-03-08 14:41:25 -060066struct AnyEntrySubTree {
67 std::pair<bool, bool>
68 operator()(const Entry& entry)
69 {
70 return std::make_pair(true, true);
71 }
72};
73
HYuana9b85752014-02-26 02:32:30 -060074} // namespace name_tree
75
76/**
Haowei Yuane1079fc2014-03-08 14:41:25 -060077 * \brief Class Name Tree
HYuana9b85752014-02-26 02:32:30 -060078 */
79class NameTree : noncopyable
80{
81public:
Haowei Yuane1079fc2014-03-08 14:41:25 -060082 class const_iterator;
Junxiao Shi2b73ca32014-11-17 19:16:08 -070083 class Range;
Haowei Yuane1079fc2014-03-08 14:41:25 -060084
HYuana9b85752014-02-26 02:32:30 -060085 explicit
Haowei Yuanf52dac72014-03-24 23:35:03 -050086 NameTree(size_t nBuckets = 1024);
HYuana9b85752014-02-26 02:32:30 -060087
88 ~NameTree();
89
Alexander Afanasyevb3033242014-08-04 11:09:05 -070090public: // information
HYuana9b85752014-02-26 02:32:30 -060091 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -060092 * \brief Get the number of occupied entries in the Name Tree
HYuana9b85752014-02-26 02:32:30 -060093 */
94 size_t
95 size() const;
96
97 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -060098 * \brief Get the number of buckets in the Name Tree (NPHT)
99 * \details The number of buckets is the one that used to create the hash
HYuana9b85752014-02-26 02:32:30 -0600100 * table, i.e., m_nBuckets.
101 */
102 size_t
103 getNBuckets() const;
104
105 /**
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700106 * \brief Dump all the information stored in the Name Tree for debugging.
107 */
108 void
109 dump(std::ostream& output) const;
110
111public: // mutation
112 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600113 * \brief Look for the Name Tree Entry that contains this name prefix.
114 * \details Starts from the shortest name prefix, and then increase the
HYuana9b85752014-02-26 02:32:30 -0600115 * number of name components by one each time. All non-existing Name Tree
116 * Entries will be created.
Haowei Yuane1079fc2014-03-08 14:41:25 -0600117 * \param prefix The querying name prefix.
118 * \return The pointer to the Name Tree Entry that contains this full name
HYuana9b85752014-02-26 02:32:30 -0600119 * prefix.
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700120 * \note Existing iterators are unaffected.
HYuana9b85752014-02-26 02:32:30 -0600121 */
122 shared_ptr<name_tree::Entry>
123 lookup(const Name& prefix);
124
125 /**
Junxiao Shiee5a4442014-07-27 17:13:43 -0700126 * \brief Delete a Name Tree Entry if this entry is empty.
127 * \param entry The entry to be deleted if empty.
128 * \note This function must be called after a table entry is detached from Name Tree
129 * entry. The function deletes a Name Tree entry if nothing is attached to it and
130 * it has no children, then repeats the same process on its ancestors.
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700131 * \note Existing iterators, except those pointing to deleted entries, are unaffected.
HYuana9b85752014-02-26 02:32:30 -0600132 */
133 bool
134 eraseEntryIfEmpty(shared_ptr<name_tree::Entry> entry);
135
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700136public: // shortcut access
137 /// get NameTree entry from attached FIB entry
138 shared_ptr<name_tree::Entry>
139 get(const fib::Entry& fibEntry) const;
140
141 /// get NameTree entry from attached PIT entry
142 shared_ptr<name_tree::Entry>
143 get(const pit::Entry& pitEntry) const;
144
145 /// get NameTree entry from attached Measurements entry
146 shared_ptr<name_tree::Entry>
147 get(const measurements::Entry& measurementsEntry) const;
148
149 /// get NameTree entry from attached StrategyChoice entry
150 shared_ptr<name_tree::Entry>
151 get(const strategy_choice::Entry& strategyChoiceEntry) const;
152
153public: // matching
154 /**
155 * \brief Exact match lookup for the given name prefix.
156 * \return a null shared_ptr if this prefix is not found;
157 * otherwise return the Name Tree Entry address
158 */
159 shared_ptr<name_tree::Entry>
160 findExactMatch(const Name& prefix) const;
161
HYuana9b85752014-02-26 02:32:30 -0600162 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600163 * \brief Longest prefix matching for the given name
164 * \details Starts from the full name string, reduce the number of name component
HYuana9b85752014-02-26 02:32:30 -0600165 * by one each time, until an Entry is found.
166 */
167 shared_ptr<name_tree::Entry>
Junxiao Shi40631842014-03-01 13:52:37 -0700168 findLongestPrefixMatch(const Name& prefix,
Haowei Yuane1079fc2014-03-08 14:41:25 -0600169 const name_tree::EntrySelector& entrySelector =
170 name_tree::AnyEntry()) const;
HYuana9b85752014-02-26 02:32:30 -0600171
HangZhangcb4fc832014-03-11 16:57:11 +0800172 shared_ptr<name_tree::Entry>
173 findLongestPrefixMatch(shared_ptr<name_tree::Entry> entry,
174 const name_tree::EntrySelector& entrySelector =
175 name_tree::AnyEntry()) const;
176
Junxiao Shi2b73ca32014-11-17 19:16:08 -0700177 /** \brief Enumerate all the name prefixes that satisfy the prefix and entrySelector
178 * \return an unspecified type that have .begin() and .end() methods
179 * and is usable with range-based for
180 *
181 * Example:
182 * \code{.cpp}
183 * auto&& allMatches = nt.findAllMatches(Name("/A/B/C"));
184 * for (const name_tree::Entry& nte : allMatches) {
185 * ...
186 * }
187 * \endcode
HYuana9b85752014-02-26 02:32:30 -0600188 */
Junxiao Shi2b73ca32014-11-17 19:16:08 -0700189 Range
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700190 findAllMatches(const Name& prefix,
191 const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry()) const;
HYuana9b85752014-02-26 02:32:30 -0600192
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700193public: // enumeration
Junxiao Shi60607c72014-11-26 22:40:36 -0700194 /** \brief Enumerate all entries, optionally filtered by an EntrySelector.
195 * \return an unspecified type that have .begin() and .end() methods
196 * and is usable with range-based for
197 *
198 * Example:
199 * \code{.cpp}
200 * auto&& enumerable = nt.fullEnumerate();
201 * for (const name_tree::Entry& nte : enumerable) {
202 * ...
203 * }
204 * \endcode
HYuana9b85752014-02-26 02:32:30 -0600205 */
Junxiao Shi60607c72014-11-26 22:40:36 -0700206 Range
Haowei Yuane1079fc2014-03-08 14:41:25 -0600207 fullEnumerate(const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry()) const;
HYuana9b85752014-02-26 02:32:30 -0600208
Junxiao Shi60607c72014-11-26 22:40:36 -0700209 /** \brief Enumerate all entries under a prefix, optionally filtered by an EntrySubTreeSelector.
210 * \return an unspecified type that have .begin() and .end() methods
211 * and is usable with range-based for
212 *
213 * Example:
214 * \code{.cpp}
215 * auto&& enumerable = nt.partialEnumerate(Name("/A/B/C"));
216 * for (const name_tree::Entry& nte : enumerable) {
217 * ...
218 * }
219 * \endcode
220 */
221 Range
Junxiao Shi40631842014-03-01 13:52:37 -0700222 partialEnumerate(const Name& prefix,
Junxiao Shiefceadc2014-03-09 18:52:57 -0700223 const name_tree::EntrySubTreeSelector& entrySubTreeSelector =
224 name_tree::AnyEntrySubTree()) const;
HYuana9b85752014-02-26 02:32:30 -0600225
Haowei Yuane1079fc2014-03-08 14:41:25 -0600226 const_iterator
227 begin() const;
228
229 const_iterator
230 end() const;
231
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700232 enum IteratorType {
Haowei Yuane1079fc2014-03-08 14:41:25 -0600233 FULL_ENUMERATE_TYPE,
234 PARTIAL_ENUMERATE_TYPE,
235 FIND_ALL_MATCHES_TYPE
236 };
237
238 class const_iterator : public std::iterator<std::forward_iterator_tag, name_tree::Entry>
239 {
240 public:
241 friend class NameTree;
242
243 const_iterator(NameTree::IteratorType type,
244 const NameTree& nameTree,
245 shared_ptr<name_tree::Entry> entry,
246 const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry(),
247 const name_tree::EntrySubTreeSelector& entrySubTreeSelector = name_tree::AnyEntrySubTree());
248
249 ~const_iterator();
250
251 const name_tree::Entry&
252 operator*() const;
253
254 shared_ptr<name_tree::Entry>
255 operator->() const;
256
257 const_iterator
258 operator++();
259
260 const_iterator
261 operator++(int);
262
263 bool
264 operator==(const const_iterator& other) const;
265
266 bool
267 operator!=(const const_iterator& other) const;
268
269 private:
Haowei Yuane1079fc2014-03-08 14:41:25 -0600270 const NameTree& m_nameTree;
271 shared_ptr<name_tree::Entry> m_entry;
272 shared_ptr<name_tree::Entry> m_subTreeRoot;
273 shared_ptr<name_tree::EntrySelector> m_entrySelector;
274 shared_ptr<name_tree::EntrySubTreeSelector> m_entrySubTreeSelector;
275 NameTree::IteratorType m_type;
Junxiao Shiefceadc2014-03-09 18:52:57 -0700276 bool m_shouldVisitChildren;
Haowei Yuane1079fc2014-03-08 14:41:25 -0600277 };
HYuana9b85752014-02-26 02:32:30 -0600278
Junxiao Shi2b73ca32014-11-17 19:16:08 -0700279 /** \brief contains a pair of begin and end iterators
280 *
281 * This is to be used with range-based for.
282 */
283 class Range
284 {
285 public:
286 Range(const_iterator begin, const_iterator end);
287
288 const_iterator
289 begin() const
290 {
291 return m_begin;
292 }
293
294 const_iterator
295 end() const
296 {
297 return m_end;
298 }
299
300 private:
301 const_iterator m_begin;
302 const_iterator m_end;
303 };
304
HYuana9b85752014-02-26 02:32:30 -0600305private:
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700306 /**
307 * \brief Resize the hash table size when its load factor reaches a threshold.
308 * \details As we are currently using a hand-written hash table implementation
309 * for the Name Tree, the hash table resize() function should be kept in the
310 * name-tree.hpp file.
311 * \param newNBuckets The number of buckets for the new hash table.
312 */
313 void
314 resize(size_t newNBuckets);
315
316private:
Haowei Yuane1079fc2014-03-08 14:41:25 -0600317 size_t m_nItems; // Number of items being stored
318 size_t m_nBuckets; // Number of hash buckets
Haowei Yuanf52dac72014-03-24 23:35:03 -0500319 size_t m_minNBuckets; // Minimum number of hash buckets
320 double m_enlargeLoadFactor;
321 size_t m_enlargeThreshold;
322 int m_enlargeFactor;
323 double m_shrinkLoadFactor;
324 size_t m_shrinkThreshold;
325 double m_shrinkFactor;
Haowei Yuane1079fc2014-03-08 14:41:25 -0600326 name_tree::Node** m_buckets; // Name Tree Buckets in the NPHT
327 shared_ptr<name_tree::Entry> m_end;
328 const_iterator m_endIterator;
HYuana9b85752014-02-26 02:32:30 -0600329
330 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600331 * \brief Create a Name Tree Entry if it does not exist, or return the existing
HYuana9b85752014-02-26 02:32:30 -0600332 * Name Tree Entry address.
Haowei Yuane1079fc2014-03-08 14:41:25 -0600333 * \details Called by lookup() only.
334 * \return The first item is the Name Tree Entry address, the second item is
HYuana9b85752014-02-26 02:32:30 -0600335 * a bool value indicates whether this is an old entry (false) or a new
336 * entry (true).
337 */
338 std::pair<shared_ptr<name_tree::Entry>, bool>
339 insert(const Name& prefix);
HYuana9b85752014-02-26 02:32:30 -0600340};
341
Haowei Yuane1079fc2014-03-08 14:41:25 -0600342inline NameTree::const_iterator::~const_iterator()
343{
344}
345
HYuana9b85752014-02-26 02:32:30 -0600346inline size_t
347NameTree::size() const
348{
349 return m_nItems;
350}
351
352inline size_t
353NameTree::getNBuckets() const
354{
355 return m_nBuckets;
356}
357
Junxiao Shiefceadc2014-03-09 18:52:57 -0700358inline shared_ptr<name_tree::Entry>
HangZhangcb4fc832014-03-11 16:57:11 +0800359NameTree::get(const fib::Entry& fibEntry) const
360{
361 return fibEntry.m_nameTreeEntry;
362}
363
364inline shared_ptr<name_tree::Entry>
365NameTree::get(const pit::Entry& pitEntry) const
366{
367 return pitEntry.m_nameTreeEntry;
368}
369
370inline shared_ptr<name_tree::Entry>
371NameTree::get(const measurements::Entry& measurementsEntry) const
372{
373 return measurementsEntry.m_nameTreeEntry;
374}
375
376inline shared_ptr<name_tree::Entry>
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700377NameTree::get(const strategy_choice::Entry& strategyChoiceEntry) const
HangZhangcb4fc832014-03-11 16:57:11 +0800378{
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700379 return strategyChoiceEntry.m_nameTreeEntry;
HangZhangcb4fc832014-03-11 16:57:11 +0800380}
381
Haowei Yuane1079fc2014-03-08 14:41:25 -0600382inline NameTree::const_iterator
383NameTree::begin() const
384{
Junxiao Shi60607c72014-11-26 22:40:36 -0700385 return fullEnumerate().begin();
Haowei Yuane1079fc2014-03-08 14:41:25 -0600386}
387
388inline NameTree::const_iterator
389NameTree::end() const
390{
391 return m_endIterator;
392}
393
394inline const name_tree::Entry&
395NameTree::const_iterator::operator*() const
396{
397 return *m_entry;
398}
399
400inline shared_ptr<name_tree::Entry>
401NameTree::const_iterator::operator->() const
402{
403 return m_entry;
404}
405
406inline NameTree::const_iterator
407NameTree::const_iterator::operator++(int)
408{
409 NameTree::const_iterator temp(*this);
410 ++(*this);
411 return temp;
412}
413
414inline bool
415NameTree::const_iterator::operator==(const NameTree::const_iterator& other) const
416{
417 return m_entry == other.m_entry;
418}
419
420inline bool
421NameTree::const_iterator::operator!=(const NameTree::const_iterator& other) const
422{
423 return m_entry != other.m_entry;
424}
425
HYuana9b85752014-02-26 02:32:30 -0600426} // namespace nfd
427
Alexander Afanasyev613e2a92014-04-15 13:36:58 -0700428#endif // NFD_DAEMON_TABLE_NAME_TREE_HPP