blob: b04769604bdd1e7f7d56da2ad79b342b54598c8d [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 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;
83
HYuana9b85752014-02-26 02:32:30 -060084 explicit
Haowei Yuanf52dac72014-03-24 23:35:03 -050085 NameTree(size_t nBuckets = 1024);
HYuana9b85752014-02-26 02:32:30 -060086
87 ~NameTree();
88
Alexander Afanasyevb3033242014-08-04 11:09:05 -070089public: // information
HYuana9b85752014-02-26 02:32:30 -060090 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -060091 * \brief Get the number of occupied entries in the Name Tree
HYuana9b85752014-02-26 02:32:30 -060092 */
93 size_t
94 size() const;
95
96 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -060097 * \brief Get the number of buckets in the Name Tree (NPHT)
98 * \details The number of buckets is the one that used to create the hash
HYuana9b85752014-02-26 02:32:30 -060099 * table, i.e., m_nBuckets.
100 */
101 size_t
102 getNBuckets() const;
103
Junxiao Shib184e532016-05-26 18:09:57 +0000104 /** \return Name Tree Entry on which a table entry is attached
105 */
106 template<typename ENTRY>
107 shared_ptr<name_tree::Entry>
108 getEntry(const ENTRY& tableEntry) const;
109
HYuana9b85752014-02-26 02:32:30 -0600110 /**
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700111 * \brief Dump all the information stored in the Name Tree for debugging.
112 */
113 void
114 dump(std::ostream& output) const;
115
116public: // mutation
117 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600118 * \brief Look for the Name Tree Entry that contains this name prefix.
119 * \details Starts from the shortest name prefix, and then increase the
HYuana9b85752014-02-26 02:32:30 -0600120 * number of name components by one each time. All non-existing Name Tree
121 * Entries will be created.
Haowei Yuane1079fc2014-03-08 14:41:25 -0600122 * \param prefix The querying name prefix.
123 * \return The pointer to the Name Tree Entry that contains this full name
HYuana9b85752014-02-26 02:32:30 -0600124 * prefix.
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700125 * \note Existing iterators are unaffected.
HYuana9b85752014-02-26 02:32:30 -0600126 */
127 shared_ptr<name_tree::Entry>
128 lookup(const Name& prefix);
129
Junxiao Shib184e532016-05-26 18:09:57 +0000130 /** \brief get NameTree entry from FIB entry
131 *
132 * This is equivalent to .lookup(fibEntry.getPrefix())
133 */
134 shared_ptr<name_tree::Entry>
135 lookup(const fib::Entry& fibEntry) const;
136
137 /** \brief get NameTree entry from PIT entry
138 *
139 * This is equivalent to .lookup(pitEntry.getName()).
140 */
141 shared_ptr<name_tree::Entry>
142 lookup(const pit::Entry& pitEntry);
143
144 /** \brief get NameTree entry from Measurements entry
145 *
146 * This is equivalent to .lookup(measurementsEntry.getName())
147 */
148 shared_ptr<name_tree::Entry>
149 lookup(const measurements::Entry& measurementsEntry) const;
150
151 /** \brief get NameTree entry from StrategyChoice entry
152 *
153 * This is equivalent to .lookup(strategyChoiceEntry.getName())
154 */
155 shared_ptr<name_tree::Entry>
156 lookup(const strategy_choice::Entry& strategyChoiceEntry) const;
157
HYuana9b85752014-02-26 02:32:30 -0600158 /**
Junxiao Shiee5a4442014-07-27 17:13:43 -0700159 * \brief Delete a Name Tree Entry if this entry is empty.
160 * \param entry The entry to be deleted if empty.
161 * \note This function must be called after a table entry is detached from Name Tree
162 * entry. The function deletes a Name Tree entry if nothing is attached to it and
163 * it has no children, then repeats the same process on its ancestors.
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700164 * \note Existing iterators, except those pointing to deleted entries, are unaffected.
HYuana9b85752014-02-26 02:32:30 -0600165 */
166 bool
167 eraseEntryIfEmpty(shared_ptr<name_tree::Entry> entry);
168
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700169public: // matching
170 /**
171 * \brief Exact match lookup for the given name prefix.
172 * \return a null shared_ptr if this prefix is not found;
173 * otherwise return the Name Tree Entry address
174 */
175 shared_ptr<name_tree::Entry>
176 findExactMatch(const Name& prefix) const;
177
HYuana9b85752014-02-26 02:32:30 -0600178 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600179 * \brief Longest prefix matching for the given name
180 * \details Starts from the full name string, reduce the number of name component
HYuana9b85752014-02-26 02:32:30 -0600181 * by one each time, until an Entry is found.
182 */
183 shared_ptr<name_tree::Entry>
Junxiao Shi40631842014-03-01 13:52:37 -0700184 findLongestPrefixMatch(const Name& prefix,
Haowei Yuane1079fc2014-03-08 14:41:25 -0600185 const name_tree::EntrySelector& entrySelector =
186 name_tree::AnyEntry()) const;
HYuana9b85752014-02-26 02:32:30 -0600187
HangZhangcb4fc832014-03-11 16:57:11 +0800188 shared_ptr<name_tree::Entry>
189 findLongestPrefixMatch(shared_ptr<name_tree::Entry> entry,
190 const name_tree::EntrySelector& entrySelector =
191 name_tree::AnyEntry()) const;
192
Junxiao Shi4370fde2016-02-24 12:20:46 -0700193 /** \brief longest prefix matching for Interest name of the PIT entry
194 *
195 * This is equivalent to .findLongestPrefixMatch(pitEntry.getName(), AnyEntry()).
196 */
197 shared_ptr<name_tree::Entry>
198 findLongestPrefixMatch(const pit::Entry& pitEntry) const;
199
Junxiao Shi2b73ca32014-11-17 19:16:08 -0700200 /** \brief Enumerate all the name prefixes that satisfy the prefix and entrySelector
201 * \return an unspecified type that have .begin() and .end() methods
202 * and is usable with range-based for
203 *
204 * Example:
205 * \code{.cpp}
206 * auto&& allMatches = nt.findAllMatches(Name("/A/B/C"));
207 * for (const name_tree::Entry& nte : allMatches) {
208 * ...
209 * }
210 * \endcode
Alexander Afanasyev09fc3d92015-01-03 02:02:37 -0800211 * \note Iteration order is implementation-specific and is undefined
212 * \note The returned iterator may get invalidated when NameTree is modified
HYuana9b85752014-02-26 02:32:30 -0600213 */
Junxiao Shi5ccd0c22014-12-02 23:54:42 -0700214 boost::iterator_range<const_iterator>
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700215 findAllMatches(const Name& prefix,
216 const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry()) const;
HYuana9b85752014-02-26 02:32:30 -0600217
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700218public: // enumeration
Junxiao Shi60607c72014-11-26 22:40:36 -0700219 /** \brief Enumerate all entries, optionally filtered by an EntrySelector.
220 * \return an unspecified type that have .begin() and .end() methods
221 * and is usable with range-based for
222 *
223 * Example:
224 * \code{.cpp}
225 * auto&& enumerable = nt.fullEnumerate();
226 * for (const name_tree::Entry& nte : enumerable) {
227 * ...
228 * }
229 * \endcode
Alexander Afanasyev09fc3d92015-01-03 02:02:37 -0800230 * \note Iteration order is implementation-specific and is undefined
231 * \note The returned iterator may get invalidated when NameTree is modified
HYuana9b85752014-02-26 02:32:30 -0600232 */
Junxiao Shi5ccd0c22014-12-02 23:54:42 -0700233 boost::iterator_range<const_iterator>
Haowei Yuane1079fc2014-03-08 14:41:25 -0600234 fullEnumerate(const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry()) const;
HYuana9b85752014-02-26 02:32:30 -0600235
Junxiao Shi60607c72014-11-26 22:40:36 -0700236 /** \brief Enumerate all entries under a prefix, optionally filtered by an EntrySubTreeSelector.
237 * \return an unspecified type that have .begin() and .end() methods
238 * and is usable with range-based for
239 *
240 * Example:
241 * \code{.cpp}
242 * auto&& enumerable = nt.partialEnumerate(Name("/A/B/C"));
243 * for (const name_tree::Entry& nte : enumerable) {
244 * ...
245 * }
246 * \endcode
Alexander Afanasyev09fc3d92015-01-03 02:02:37 -0800247 * \note Iteration order is implementation-specific and is undefined
248 * \note The returned iterator may get invalidated when NameTree is modified
Junxiao Shi60607c72014-11-26 22:40:36 -0700249 */
Junxiao Shi5ccd0c22014-12-02 23:54:42 -0700250 boost::iterator_range<const_iterator>
Junxiao Shi40631842014-03-01 13:52:37 -0700251 partialEnumerate(const Name& prefix,
Junxiao Shiefceadc2014-03-09 18:52:57 -0700252 const name_tree::EntrySubTreeSelector& entrySubTreeSelector =
253 name_tree::AnyEntrySubTree()) const;
HYuana9b85752014-02-26 02:32:30 -0600254
Alexander Afanasyev09fc3d92015-01-03 02:02:37 -0800255 /** \brief Get an iterator pointing to the first NameTree entry
256 * \note Iteration order is implementation-specific and is undefined
257 * \note The returned iterator may get invalidated when NameTree is modified
258 */
Haowei Yuane1079fc2014-03-08 14:41:25 -0600259 const_iterator
260 begin() const;
261
Alexander Afanasyev09fc3d92015-01-03 02:02:37 -0800262 /** \brief Get an iterator referring to the past-the-end FIB entry
263 * \note Iteration order is implementation-specific and is undefined
264 * \note The returned iterator may get invalidated when NameTree is modified
265 */
Haowei Yuane1079fc2014-03-08 14:41:25 -0600266 const_iterator
267 end() const;
268
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700269 enum IteratorType {
Haowei Yuane1079fc2014-03-08 14:41:25 -0600270 FULL_ENUMERATE_TYPE,
271 PARTIAL_ENUMERATE_TYPE,
272 FIND_ALL_MATCHES_TYPE
273 };
274
Alexander Afanasyev09fc3d92015-01-03 02:02:37 -0800275 class const_iterator : public std::iterator<std::forward_iterator_tag, const name_tree::Entry>
Haowei Yuane1079fc2014-03-08 14:41:25 -0600276 {
277 public:
278 friend class NameTree;
279
Alexander Afanasyev09fc3d92015-01-03 02:02:37 -0800280 const_iterator();
281
Haowei Yuane1079fc2014-03-08 14:41:25 -0600282 const_iterator(NameTree::IteratorType type,
283 const NameTree& nameTree,
284 shared_ptr<name_tree::Entry> entry,
285 const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry(),
286 const name_tree::EntrySubTreeSelector& entrySubTreeSelector = name_tree::AnyEntrySubTree());
287
288 ~const_iterator();
289
290 const name_tree::Entry&
291 operator*() const;
292
293 shared_ptr<name_tree::Entry>
294 operator->() const;
295
296 const_iterator
297 operator++();
298
299 const_iterator
300 operator++(int);
301
302 bool
303 operator==(const const_iterator& other) const;
304
305 bool
306 operator!=(const const_iterator& other) const;
307
308 private:
Alexander Afanasyev09fc3d92015-01-03 02:02:37 -0800309 const NameTree* m_nameTree;
Haowei Yuane1079fc2014-03-08 14:41:25 -0600310 shared_ptr<name_tree::Entry> m_entry;
311 shared_ptr<name_tree::Entry> m_subTreeRoot;
312 shared_ptr<name_tree::EntrySelector> m_entrySelector;
313 shared_ptr<name_tree::EntrySubTreeSelector> m_entrySubTreeSelector;
314 NameTree::IteratorType m_type;
Junxiao Shiefceadc2014-03-09 18:52:57 -0700315 bool m_shouldVisitChildren;
Haowei Yuane1079fc2014-03-08 14:41:25 -0600316 };
HYuana9b85752014-02-26 02:32:30 -0600317
318private:
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700319 /**
Junxiao Shib184e532016-05-26 18:09:57 +0000320 * \brief Create a Name Tree Entry if it does not exist, or return the existing
321 * Name Tree Entry address.
322 * \details Called by lookup() only.
323 * \return The first item is the Name Tree Entry address, the second item is
324 * a bool value indicates whether this is an old entry (false) or a new
325 * entry (true).
326 */
327 std::pair<shared_ptr<name_tree::Entry>, bool>
328 insert(const Name& prefix);
329
330 /**
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700331 * \brief Resize the hash table size when its load factor reaches a threshold.
332 * \details As we are currently using a hand-written hash table implementation
333 * for the Name Tree, the hash table resize() function should be kept in the
334 * name-tree.hpp file.
335 * \param newNBuckets The number of buckets for the new hash table.
336 */
337 void
338 resize(size_t newNBuckets);
339
340private:
Haowei Yuane1079fc2014-03-08 14:41:25 -0600341 size_t m_nItems; // Number of items being stored
342 size_t m_nBuckets; // Number of hash buckets
Haowei Yuanf52dac72014-03-24 23:35:03 -0500343 size_t m_minNBuckets; // Minimum number of hash buckets
344 double m_enlargeLoadFactor;
345 size_t m_enlargeThreshold;
346 int m_enlargeFactor;
347 double m_shrinkLoadFactor;
348 size_t m_shrinkThreshold;
349 double m_shrinkFactor;
Haowei Yuane1079fc2014-03-08 14:41:25 -0600350 name_tree::Node** m_buckets; // Name Tree Buckets in the NPHT
351 shared_ptr<name_tree::Entry> m_end;
352 const_iterator m_endIterator;
HYuana9b85752014-02-26 02:32:30 -0600353};
354
Haowei Yuane1079fc2014-03-08 14:41:25 -0600355inline NameTree::const_iterator::~const_iterator()
356{
357}
358
HYuana9b85752014-02-26 02:32:30 -0600359inline size_t
360NameTree::size() const
361{
362 return m_nItems;
363}
364
365inline size_t
366NameTree::getNBuckets() const
367{
368 return m_nBuckets;
369}
370
Junxiao Shib184e532016-05-26 18:09:57 +0000371template<typename ENTRY>
Junxiao Shiefceadc2014-03-09 18:52:57 -0700372inline shared_ptr<name_tree::Entry>
Junxiao Shib184e532016-05-26 18:09:57 +0000373NameTree::getEntry(const ENTRY& tableEntry) const
HangZhangcb4fc832014-03-11 16:57:11 +0800374{
Junxiao Shib184e532016-05-26 18:09:57 +0000375 return tableEntry.m_nameTreeEntry.lock();
HangZhangcb4fc832014-03-11 16:57:11 +0800376}
377
Haowei Yuane1079fc2014-03-08 14:41:25 -0600378inline NameTree::const_iterator
379NameTree::begin() const
380{
Junxiao Shi60607c72014-11-26 22:40:36 -0700381 return fullEnumerate().begin();
Haowei Yuane1079fc2014-03-08 14:41:25 -0600382}
383
384inline NameTree::const_iterator
385NameTree::end() const
386{
387 return m_endIterator;
388}
389
390inline const name_tree::Entry&
391NameTree::const_iterator::operator*() const
392{
393 return *m_entry;
394}
395
396inline shared_ptr<name_tree::Entry>
397NameTree::const_iterator::operator->() const
398{
399 return m_entry;
400}
401
402inline NameTree::const_iterator
403NameTree::const_iterator::operator++(int)
404{
405 NameTree::const_iterator temp(*this);
406 ++(*this);
407 return temp;
408}
409
410inline bool
411NameTree::const_iterator::operator==(const NameTree::const_iterator& other) const
412{
413 return m_entry == other.m_entry;
414}
415
416inline bool
417NameTree::const_iterator::operator!=(const NameTree::const_iterator& other) const
418{
419 return m_entry != other.m_entry;
420}
421
HYuana9b85752014-02-26 02:32:30 -0600422} // namespace nfd
423
Alexander Afanasyev613e2a92014-04-15 13:36:58 -0700424#endif // NFD_DAEMON_TABLE_NAME_TREE_HPP