blob: 460e497b15b19c9679ddf4dfa7382619ac0e4285 [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
Junxiao Shi2570f3e2016-07-27 02:48:29 +000035/** \brief Compute the hash value of the given name prefix's WIRE FORMAT
HYuana9b85752014-02-26 02:32:30 -060036 */
Haowei Yuanf52dac72014-03-24 23:35:03 -050037size_t
38computeHash(const Name& prefix);
39
Junxiao Shi2570f3e2016-07-27 02:48:29 +000040/** \brief Incrementally compute hash values
41 * \return Return a vector of hash values, starting from the root prefix
Haowei Yuanf52dac72014-03-24 23:35:03 -050042 */
43std::vector<size_t>
44computeHashSet(const Name& prefix);
HYuana9b85752014-02-26 02:32:30 -060045
Junxiao Shi2570f3e2016-07-27 02:48:29 +000046/** \brief a predicate to accept or reject an Entry in find operations
Haowei Yuane1079fc2014-03-08 14:41:25 -060047 */
Junxiao Shi2570f3e2016-07-27 02:48:29 +000048typedef function<bool(const Entry& entry)> EntrySelector;
Haowei Yuane1079fc2014-03-08 14:41:25 -060049
Junxiao Shi2570f3e2016-07-27 02:48:29 +000050/** \brief a predicate to accept or reject an Entry and its children
51 * \return .first indicates whether entry should be accepted;
52 * .second indicates whether entry's children should be visited
53 */
54typedef function<std::pair<bool,bool>(const Entry& entry)> EntrySubTreeSelector;
55
56struct AnyEntry
57{
Junxiao Shi40631842014-03-01 13:52:37 -070058 bool
Junxiao Shi2570f3e2016-07-27 02:48:29 +000059 operator()(const Entry& entry) const
Junxiao Shi40631842014-03-01 13:52:37 -070060 {
61 return true;
62 }
63};
64
Junxiao Shi2570f3e2016-07-27 02:48:29 +000065struct AnyEntrySubTree
66{
Haowei Yuane1079fc2014-03-08 14:41:25 -060067 std::pair<bool, bool>
Junxiao Shi2570f3e2016-07-27 02:48:29 +000068 operator()(const Entry& entry) const
Haowei Yuane1079fc2014-03-08 14:41:25 -060069 {
Junxiao Shi2570f3e2016-07-27 02:48:29 +000070 return {true, true};
Haowei Yuane1079fc2014-03-08 14:41:25 -060071 }
72};
73
Junxiao Shi2570f3e2016-07-27 02:48:29 +000074/** \brief shared name-based index for FIB, PIT, Measurements, and StrategyChoice
HYuana9b85752014-02-26 02:32:30 -060075 */
76class NameTree : noncopyable
77{
78public:
Haowei Yuane1079fc2014-03-08 14:41:25 -060079 class const_iterator;
80
HYuana9b85752014-02-26 02:32:30 -060081 explicit
Haowei Yuanf52dac72014-03-24 23:35:03 -050082 NameTree(size_t nBuckets = 1024);
HYuana9b85752014-02-26 02:32:30 -060083
84 ~NameTree();
85
Alexander Afanasyevb3033242014-08-04 11:09:05 -070086public: // information
Junxiao Shi2570f3e2016-07-27 02:48:29 +000087 /** \brief Get the number of occupied entries in the Name Tree
HYuana9b85752014-02-26 02:32:30 -060088 */
89 size_t
90 size() const;
91
Junxiao Shi2570f3e2016-07-27 02:48:29 +000092 /** \brief Get the number of buckets in the Name Tree (NPHT)
93 *
94 * The number of buckets is the one that used to create the hash
95 * table, i.e., m_nBuckets.
HYuana9b85752014-02-26 02:32:30 -060096 */
97 size_t
98 getNBuckets() const;
99
Junxiao Shib184e532016-05-26 18:09:57 +0000100 /** \return Name Tree Entry on which a table entry is attached
101 */
102 template<typename ENTRY>
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000103 shared_ptr<Entry>
Junxiao Shib184e532016-05-26 18:09:57 +0000104 getEntry(const ENTRY& tableEntry) const;
105
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000106 /** \brief Dump all the information stored in the Name Tree for debugging.
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700107 */
108 void
109 dump(std::ostream& output) const;
110
111public: // mutation
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000112 /** \brief Look for the Name Tree Entry that contains this name prefix.
113 *
114 * Starts from the shortest name prefix, and then increase the
115 * number of name components by one each time. All non-existing Name Tree
116 * Entries will be created.
117 *
118 * \param prefix The querying name prefix.
119 * \return The pointer to the Name Tree Entry that contains this full name prefix.
120 * \note Existing iterators are unaffected.
HYuana9b85752014-02-26 02:32:30 -0600121 */
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000122 shared_ptr<Entry>
HYuana9b85752014-02-26 02:32:30 -0600123 lookup(const Name& prefix);
124
Junxiao Shib184e532016-05-26 18:09:57 +0000125 /** \brief get NameTree entry from FIB entry
126 *
127 * This is equivalent to .lookup(fibEntry.getPrefix())
128 */
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000129 shared_ptr<Entry>
Junxiao Shib184e532016-05-26 18:09:57 +0000130 lookup(const fib::Entry& fibEntry) const;
131
132 /** \brief get NameTree entry from PIT entry
133 *
134 * This is equivalent to .lookup(pitEntry.getName()).
135 */
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000136 shared_ptr<Entry>
Junxiao Shib184e532016-05-26 18:09:57 +0000137 lookup(const pit::Entry& pitEntry);
138
139 /** \brief get NameTree entry from Measurements entry
140 *
141 * This is equivalent to .lookup(measurementsEntry.getName())
142 */
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000143 shared_ptr<Entry>
Junxiao Shib184e532016-05-26 18:09:57 +0000144 lookup(const measurements::Entry& measurementsEntry) const;
145
146 /** \brief get NameTree entry from StrategyChoice entry
147 *
148 * This is equivalent to .lookup(strategyChoiceEntry.getName())
149 */
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000150 shared_ptr<Entry>
Junxiao Shib184e532016-05-26 18:09:57 +0000151 lookup(const strategy_choice::Entry& strategyChoiceEntry) const;
152
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000153 /** \brief Delete a Name Tree Entry if this entry is empty.
154 * \param entry The entry to be deleted if empty.
155 * \note This function must be called after a table entry is detached from Name Tree
156 * entry. The function deletes a Name Tree entry if nothing is attached to it and
157 * it has no children, then repeats the same process on its ancestors.
158 * \note Existing iterators, except those pointing to deleted entries, are unaffected.
HYuana9b85752014-02-26 02:32:30 -0600159 */
160 bool
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000161 eraseEntryIfEmpty(shared_ptr<Entry> entry);
HYuana9b85752014-02-26 02:32:30 -0600162
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700163public: // matching
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000164 /** \brief Exact match lookup for the given name prefix.
165 * \return nullptr if this prefix is not found; otherwise return the Name Tree Entry address
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700166 */
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000167 shared_ptr<Entry>
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700168 findExactMatch(const Name& prefix) const;
169
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000170 /** \brief Longest prefix matching for the given name
171 *
172 * Starts from the full name string, reduce the number of name component
173 * by one each time, until an Entry is found.
HYuana9b85752014-02-26 02:32:30 -0600174 */
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000175 shared_ptr<Entry>
Junxiao Shi40631842014-03-01 13:52:37 -0700176 findLongestPrefixMatch(const Name& prefix,
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000177 const EntrySelector& entrySelector = AnyEntry()) const;
HYuana9b85752014-02-26 02:32:30 -0600178
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000179 shared_ptr<Entry>
180 findLongestPrefixMatch(shared_ptr<Entry> entry,
181 const EntrySelector& entrySelector = AnyEntry()) const;
HangZhangcb4fc832014-03-11 16:57:11 +0800182
Junxiao Shi4370fde2016-02-24 12:20:46 -0700183 /** \brief longest prefix matching for Interest name of the PIT entry
184 *
185 * This is equivalent to .findLongestPrefixMatch(pitEntry.getName(), AnyEntry()).
186 */
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000187 shared_ptr<Entry>
Junxiao Shi4370fde2016-02-24 12:20:46 -0700188 findLongestPrefixMatch(const pit::Entry& pitEntry) const;
189
Junxiao Shi2b73ca32014-11-17 19:16:08 -0700190 /** \brief Enumerate all the name prefixes that satisfy the prefix and entrySelector
191 * \return an unspecified type that have .begin() and .end() methods
192 * and is usable with range-based for
193 *
194 * Example:
195 * \code{.cpp}
196 * auto&& allMatches = nt.findAllMatches(Name("/A/B/C"));
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000197 * for (const Entry& nte : allMatches) {
Junxiao Shi2b73ca32014-11-17 19:16:08 -0700198 * ...
199 * }
200 * \endcode
Alexander Afanasyev09fc3d92015-01-03 02:02:37 -0800201 * \note Iteration order is implementation-specific and is undefined
202 * \note The returned iterator may get invalidated when NameTree is modified
HYuana9b85752014-02-26 02:32:30 -0600203 */
Junxiao Shi5ccd0c22014-12-02 23:54:42 -0700204 boost::iterator_range<const_iterator>
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700205 findAllMatches(const Name& prefix,
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000206 const EntrySelector& entrySelector = AnyEntry()) const;
HYuana9b85752014-02-26 02:32:30 -0600207
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700208public: // enumeration
Junxiao Shi60607c72014-11-26 22:40:36 -0700209 /** \brief Enumerate all entries, optionally filtered by an EntrySelector.
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.fullEnumerate();
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000216 * for (const Entry& nte : enumerable) {
Junxiao Shi60607c72014-11-26 22:40:36 -0700217 * ...
218 * }
219 * \endcode
Alexander Afanasyev09fc3d92015-01-03 02:02:37 -0800220 * \note Iteration order is implementation-specific and is undefined
221 * \note The returned iterator may get invalidated when NameTree is modified
HYuana9b85752014-02-26 02:32:30 -0600222 */
Junxiao Shi5ccd0c22014-12-02 23:54:42 -0700223 boost::iterator_range<const_iterator>
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000224 fullEnumerate(const EntrySelector& entrySelector = AnyEntry()) const;
HYuana9b85752014-02-26 02:32:30 -0600225
Junxiao Shi60607c72014-11-26 22:40:36 -0700226 /** \brief Enumerate all entries under a prefix, optionally filtered by an EntrySubTreeSelector.
227 * \return an unspecified type that have .begin() and .end() methods
228 * and is usable with range-based for
229 *
230 * Example:
231 * \code{.cpp}
232 * auto&& enumerable = nt.partialEnumerate(Name("/A/B/C"));
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000233 * for (const Entry& nte : enumerable) {
Junxiao Shi60607c72014-11-26 22:40:36 -0700234 * ...
235 * }
236 * \endcode
Alexander Afanasyev09fc3d92015-01-03 02:02:37 -0800237 * \note Iteration order is implementation-specific and is undefined
238 * \note The returned iterator may get invalidated when NameTree is modified
Junxiao Shi60607c72014-11-26 22:40:36 -0700239 */
Junxiao Shi5ccd0c22014-12-02 23:54:42 -0700240 boost::iterator_range<const_iterator>
Junxiao Shi40631842014-03-01 13:52:37 -0700241 partialEnumerate(const Name& prefix,
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000242 const EntrySubTreeSelector& entrySubTreeSelector = AnyEntrySubTree()) const;
HYuana9b85752014-02-26 02:32:30 -0600243
Alexander Afanasyev09fc3d92015-01-03 02:02:37 -0800244 /** \brief Get an iterator pointing to the first NameTree entry
245 * \note Iteration order is implementation-specific and is undefined
246 * \note The returned iterator may get invalidated when NameTree is modified
247 */
Haowei Yuane1079fc2014-03-08 14:41:25 -0600248 const_iterator
249 begin() const;
250
Alexander Afanasyev09fc3d92015-01-03 02:02:37 -0800251 /** \brief Get an iterator referring to the past-the-end FIB entry
252 * \note Iteration order is implementation-specific and is undefined
253 * \note The returned iterator may get invalidated when NameTree is modified
254 */
Haowei Yuane1079fc2014-03-08 14:41:25 -0600255 const_iterator
256 end() const;
257
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700258 enum IteratorType {
Haowei Yuane1079fc2014-03-08 14:41:25 -0600259 FULL_ENUMERATE_TYPE,
260 PARTIAL_ENUMERATE_TYPE,
261 FIND_ALL_MATCHES_TYPE
262 };
263
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000264 class const_iterator : public std::iterator<std::forward_iterator_tag, const Entry>
Haowei Yuane1079fc2014-03-08 14:41:25 -0600265 {
266 public:
267 friend class NameTree;
268
Alexander Afanasyev09fc3d92015-01-03 02:02:37 -0800269 const_iterator();
270
Haowei Yuane1079fc2014-03-08 14:41:25 -0600271 const_iterator(NameTree::IteratorType type,
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000272 const NameTree& nameTree,
273 shared_ptr<Entry> entry,
274 const EntrySelector& entrySelector = AnyEntry(),
275 const EntrySubTreeSelector& entrySubTreeSelector = AnyEntrySubTree());
Haowei Yuane1079fc2014-03-08 14:41:25 -0600276
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000277 const Entry&
Haowei Yuane1079fc2014-03-08 14:41:25 -0600278 operator*() const;
279
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000280 shared_ptr<Entry>
Haowei Yuane1079fc2014-03-08 14:41:25 -0600281 operator->() const;
282
283 const_iterator
284 operator++();
285
286 const_iterator
287 operator++(int);
288
289 bool
290 operator==(const const_iterator& other) const;
291
292 bool
293 operator!=(const const_iterator& other) const;
294
295 private:
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000296 const NameTree* m_nameTree;
297 shared_ptr<Entry> m_entry;
298 shared_ptr<Entry> m_subTreeRoot;
299 shared_ptr<EntrySelector> m_entrySelector;
300 shared_ptr<EntrySubTreeSelector> m_entrySubTreeSelector;
301 NameTree::IteratorType m_type;
302 bool m_shouldVisitChildren;
Haowei Yuane1079fc2014-03-08 14:41:25 -0600303 };
HYuana9b85752014-02-26 02:32:30 -0600304
305private:
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000306 /** \brief Create a Name Tree Entry if it does not exist, or return the existing
307 * Name Tree Entry address.
308 *
309 * Called by lookup() only.
310 *
311 * \return The first item is the Name Tree Entry address, the second item is
312 * a bool value indicates whether this is an old entry (false) or a new
313 * entry (true).
Junxiao Shib184e532016-05-26 18:09:57 +0000314 */
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000315 std::pair<shared_ptr<Entry>, bool>
Junxiao Shib184e532016-05-26 18:09:57 +0000316 insert(const Name& prefix);
317
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000318 /** \brief Resize the hash table size when its load factor reaches a threshold.
319 *
320 * As we are currently using a hand-written hash table implementation
321 * for the Name Tree, the hash table resize() function should be kept in the
322 * name-tree.hpp file.
323 * \param newNBuckets The number of buckets for the new hash table.
Alexander Afanasyevb3033242014-08-04 11:09:05 -0700324 */
325 void
326 resize(size_t newNBuckets);
327
328private:
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000329 size_t m_nItems; ///< Number of items being stored
330 size_t m_nBuckets; ///< Number of hash buckets
331 size_t m_minNBuckets; ///< Minimum number of hash buckets
332 double m_enlargeLoadFactor;
333 size_t m_enlargeThreshold;
334 int m_enlargeFactor;
335 double m_shrinkLoadFactor;
336 size_t m_shrinkThreshold;
337 double m_shrinkFactor;
338 Node** m_buckets; ///< Name Tree Buckets in the NPHT
339 shared_ptr<Entry> m_end;
340 const_iterator m_endIterator;
HYuana9b85752014-02-26 02:32:30 -0600341};
342
343inline size_t
344NameTree::size() const
345{
346 return m_nItems;
347}
348
349inline size_t
350NameTree::getNBuckets() const
351{
352 return m_nBuckets;
353}
354
Junxiao Shib184e532016-05-26 18:09:57 +0000355template<typename ENTRY>
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000356inline shared_ptr<Entry>
Junxiao Shib184e532016-05-26 18:09:57 +0000357NameTree::getEntry(const ENTRY& tableEntry) const
HangZhangcb4fc832014-03-11 16:57:11 +0800358{
Junxiao Shib184e532016-05-26 18:09:57 +0000359 return tableEntry.m_nameTreeEntry.lock();
HangZhangcb4fc832014-03-11 16:57:11 +0800360}
361
Haowei Yuane1079fc2014-03-08 14:41:25 -0600362inline NameTree::const_iterator
363NameTree::begin() const
364{
Junxiao Shi60607c72014-11-26 22:40:36 -0700365 return fullEnumerate().begin();
Haowei Yuane1079fc2014-03-08 14:41:25 -0600366}
367
368inline NameTree::const_iterator
369NameTree::end() const
370{
371 return m_endIterator;
372}
373
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000374inline const Entry&
Haowei Yuane1079fc2014-03-08 14:41:25 -0600375NameTree::const_iterator::operator*() const
376{
377 return *m_entry;
378}
379
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000380inline shared_ptr<Entry>
Haowei Yuane1079fc2014-03-08 14:41:25 -0600381NameTree::const_iterator::operator->() const
382{
383 return m_entry;
384}
385
386inline NameTree::const_iterator
387NameTree::const_iterator::operator++(int)
388{
389 NameTree::const_iterator temp(*this);
390 ++(*this);
391 return temp;
392}
393
394inline bool
395NameTree::const_iterator::operator==(const NameTree::const_iterator& other) const
396{
397 return m_entry == other.m_entry;
398}
399
400inline bool
401NameTree::const_iterator::operator!=(const NameTree::const_iterator& other) const
402{
403 return m_entry != other.m_entry;
404}
405
Junxiao Shi2570f3e2016-07-27 02:48:29 +0000406} // namespace name_tree
407
408using name_tree::NameTree;
409
HYuana9b85752014-02-26 02:32:30 -0600410} // namespace nfd
411
Alexander Afanasyev613e2a92014-04-15 13:36:58 -0700412#endif // NFD_DAEMON_TABLE_NAME_TREE_HPP