blob: c210a768d732ce6fe6025534a0fe25004a827dfe [file] [log] [blame]
HYuana9b85752014-02-26 02:32:30 -06001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -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 *
10 * This file is part of NFD (Named Data Networking Forwarding Daemon).
11 * See AUTHORS.md for complete list of NFD authors and contributors.
12 *
13 * NFD is free software: you can redistribute it and/or modify it under the terms
14 * of the GNU General Public License as published by the Free Software Foundation,
15 * either version 3 of the License, or (at your option) any later version.
16 *
17 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
19 * PURPOSE. See the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along with
22 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
23 **/
HYuana9b85752014-02-26 02:32:30 -060024
25// Name Tree (Name Prefix Hash Table)
26
27#ifndef NFD_TABLE_NAME_TREE_HPP
28#define NFD_TABLE_NAME_TREE_HPP
29
30#include "common.hpp"
31#include "name-tree-entry.hpp"
32
33namespace nfd {
34namespace name_tree {
35
36/**
Haowei Yuane1079fc2014-03-08 14:41:25 -060037 * \brief Compute the hash value of the given name prefix.
38 * \todo 1) have another parameter that specifies the number of components
HYuana9b85752014-02-26 02:32:30 -060039 * 2) optimize the hash function to return a list of have values for all
40 * the (or a certain number of, like a batch operation) prefixes. 3) move
41 * the hash-related code to a separate file in /core or ndn-cpp-dev lib.
42 */
43uint32_t
44hashName(const Name& prefix);
45
Junxiao Shi40631842014-03-01 13:52:37 -070046/// a predicate to accept or reject an Entry in find operations
47typedef function<bool (const Entry& entry)> EntrySelector;
48
Haowei Yuane1079fc2014-03-08 14:41:25 -060049/**
50 * \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
Junxiao Shi40631842014-03-01 13:52:37 -070056struct AnyEntry {
57 bool
58 operator()(const Entry& entry)
59 {
60 return true;
61 }
62};
63
Haowei Yuane1079fc2014-03-08 14:41:25 -060064struct AnyEntrySubTree {
65 std::pair<bool, bool>
66 operator()(const Entry& entry)
67 {
68 return std::make_pair(true, true);
69 }
70};
71
HYuana9b85752014-02-26 02:32:30 -060072} // namespace name_tree
73
74/**
Haowei Yuane1079fc2014-03-08 14:41:25 -060075 * \brief Class Name Tree
HYuana9b85752014-02-26 02:32:30 -060076 */
77class NameTree : noncopyable
78{
79public:
Haowei Yuane1079fc2014-03-08 14:41:25 -060080 class const_iterator;
81
HYuana9b85752014-02-26 02:32:30 -060082 explicit
83 NameTree(size_t nBuckets);
84
85 ~NameTree();
86
87 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -060088 * \brief Get the number of occupied entries in the Name Tree
HYuana9b85752014-02-26 02:32:30 -060089 */
90 size_t
91 size() const;
92
93 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -060094 * \brief Get the number of buckets in the Name Tree (NPHT)
95 * \details The number of buckets is the one that used to create the hash
HYuana9b85752014-02-26 02:32:30 -060096 * table, i.e., m_nBuckets.
97 */
98 size_t
99 getNBuckets() const;
100
101 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600102 * \brief Look for the Name Tree Entry that contains this name prefix.
103 * \details Starts from the shortest name prefix, and then increase the
HYuana9b85752014-02-26 02:32:30 -0600104 * number of name components by one each time. All non-existing Name Tree
105 * Entries will be created.
Haowei Yuane1079fc2014-03-08 14:41:25 -0600106 * \param prefix The querying name prefix.
107 * \return The pointer to the Name Tree Entry that contains this full name
HYuana9b85752014-02-26 02:32:30 -0600108 * prefix.
109 */
110 shared_ptr<name_tree::Entry>
111 lookup(const Name& prefix);
112
113 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600114 * \brief Exact match lookup for the given name prefix.
115 * \return a null shared_ptr if this prefix is not found;
HYuana9b85752014-02-26 02:32:30 -0600116 * otherwise return the Name Tree Entry address
117 */
118 shared_ptr<name_tree::Entry>
119 findExactMatch(const Name& prefix) const;
120
Junxiao Shiefceadc2014-03-09 18:52:57 -0700121 shared_ptr<name_tree::Entry>
122 findExactMatch(const fib::Entry& fibEntry) const;
123
HYuana9b85752014-02-26 02:32:30 -0600124 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600125 * \brief Erase a Name Tree Entry if this entry is empty.
126 * \details If a Name Tree Entry contains no Children, no FIB, no PIT, and
HYuana9b85752014-02-26 02:32:30 -0600127 * no Measurements entries, then it can be erased. In addition, its parent entry
128 * will also be examined by following the parent pointer until all empty entries
129 * are erased.
Haowei Yuane1079fc2014-03-08 14:41:25 -0600130 * \param entry The pointer to the entry to be erased. The entry pointer should
HYuana9b85752014-02-26 02:32:30 -0600131 * returned by the findExactMatch(), lookup(), or findLongestPrefixMatch() functions.
132 */
133 bool
134 eraseEntryIfEmpty(shared_ptr<name_tree::Entry> entry);
135
136 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600137 * \brief Longest prefix matching for the given name
138 * \details Starts from the full name string, reduce the number of name component
HYuana9b85752014-02-26 02:32:30 -0600139 * by one each time, until an Entry is found.
140 */
141 shared_ptr<name_tree::Entry>
Junxiao Shi40631842014-03-01 13:52:37 -0700142 findLongestPrefixMatch(const Name& prefix,
Haowei Yuane1079fc2014-03-08 14:41:25 -0600143 const name_tree::EntrySelector& entrySelector =
144 name_tree::AnyEntry()) const;
HYuana9b85752014-02-26 02:32:30 -0600145
HangZhangcb4fc832014-03-11 16:57:11 +0800146 shared_ptr<name_tree::Entry>
147 findLongestPrefixMatch(shared_ptr<name_tree::Entry> entry,
148 const name_tree::EntrySelector& entrySelector =
149 name_tree::AnyEntry()) const;
150
HYuana9b85752014-02-26 02:32:30 -0600151 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600152 * \brief Resize the hash table size when its load factor reaches a threshold.
153 * \details As we are currently using a hand-written hash table implementation
HYuana9b85752014-02-26 02:32:30 -0600154 * for the Name Tree, the hash table resize() function should be kept in the
155 * name-tree.hpp file.
Haowei Yuane1079fc2014-03-08 14:41:25 -0600156 * \param newNBuckets The number of buckets for the new hash table.
HYuana9b85752014-02-26 02:32:30 -0600157 */
158 void
159 resize(size_t newNBuckets);
160
161 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600162 * \brief Enumerate all the name prefixes stored in the Name Tree.
HYuana9b85752014-02-26 02:32:30 -0600163 */
Haowei Yuane1079fc2014-03-08 14:41:25 -0600164 const_iterator
165 fullEnumerate(const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry()) const;
HYuana9b85752014-02-26 02:32:30 -0600166
167 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600168 * \brief Enumerate all the name prefixes that satisfies the EntrySubTreeSelector.
169 */
170 const_iterator
Junxiao Shi40631842014-03-01 13:52:37 -0700171 partialEnumerate(const Name& prefix,
Junxiao Shiefceadc2014-03-09 18:52:57 -0700172 const name_tree::EntrySubTreeSelector& entrySubTreeSelector =
173 name_tree::AnyEntrySubTree()) const;
HYuana9b85752014-02-26 02:32:30 -0600174
175 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600176 * \brief Enumerate all the name prefixes that satisfy the prefix and entrySelector
177 */
178 const_iterator
179 findAllMatches(const Name& prefix,
180 const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry()) const;
181
182 /**
183 * \brief Dump all the information stored in the Name Tree for debugging.
HYuana9b85752014-02-26 02:32:30 -0600184 */
185 void
Haowei Yuane1079fc2014-03-08 14:41:25 -0600186 dump(std::ostream& output) const;
187
HangZhangcb4fc832014-03-11 16:57:11 +0800188 shared_ptr<name_tree::Entry>
189 get(const fib::Entry& fibEntry) const;
190
191 shared_ptr<name_tree::Entry>
192 get(const pit::Entry& pitEntry) const;
193
194 shared_ptr<name_tree::Entry>
195 get(const measurements::Entry& measurementsEntry) const;
196
197 shared_ptr<name_tree::Entry>
198 get(const strategy_choice::Entry& strategeChoiceEntry) const;
199
Haowei Yuane1079fc2014-03-08 14:41:25 -0600200 const_iterator
201 begin() const;
202
203 const_iterator
204 end() const;
205
206 enum IteratorType
207 {
208 FULL_ENUMERATE_TYPE,
209 PARTIAL_ENUMERATE_TYPE,
210 FIND_ALL_MATCHES_TYPE
211 };
212
213 class const_iterator : public std::iterator<std::forward_iterator_tag, name_tree::Entry>
214 {
215 public:
216 friend class NameTree;
217
218 const_iterator(NameTree::IteratorType type,
219 const NameTree& nameTree,
220 shared_ptr<name_tree::Entry> entry,
221 const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry(),
222 const name_tree::EntrySubTreeSelector& entrySubTreeSelector = name_tree::AnyEntrySubTree());
223
224 ~const_iterator();
225
226 const name_tree::Entry&
227 operator*() const;
228
229 shared_ptr<name_tree::Entry>
230 operator->() const;
231
232 const_iterator
233 operator++();
234
235 const_iterator
236 operator++(int);
237
238 bool
239 operator==(const const_iterator& other) const;
240
241 bool
242 operator!=(const const_iterator& other) const;
243
244 private:
Haowei Yuane1079fc2014-03-08 14:41:25 -0600245 const NameTree& m_nameTree;
246 shared_ptr<name_tree::Entry> m_entry;
247 shared_ptr<name_tree::Entry> m_subTreeRoot;
248 shared_ptr<name_tree::EntrySelector> m_entrySelector;
249 shared_ptr<name_tree::EntrySubTreeSelector> m_entrySubTreeSelector;
250 NameTree::IteratorType m_type;
Junxiao Shiefceadc2014-03-09 18:52:57 -0700251 bool m_shouldVisitChildren;
Haowei Yuane1079fc2014-03-08 14:41:25 -0600252 };
HYuana9b85752014-02-26 02:32:30 -0600253
254private:
Haowei Yuane1079fc2014-03-08 14:41:25 -0600255 size_t m_nItems; // Number of items being stored
256 size_t m_nBuckets; // Number of hash buckets
257 double m_loadFactor;
258 size_t m_resizeThreshold;
259 int m_resizeFactor;
260 name_tree::Node** m_buckets; // Name Tree Buckets in the NPHT
261 shared_ptr<name_tree::Entry> m_end;
262 const_iterator m_endIterator;
HYuana9b85752014-02-26 02:32:30 -0600263
264 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600265 * \brief Create a Name Tree Entry if it does not exist, or return the existing
HYuana9b85752014-02-26 02:32:30 -0600266 * Name Tree Entry address.
Haowei Yuane1079fc2014-03-08 14:41:25 -0600267 * \details Called by lookup() only.
268 * \return The first item is the Name Tree Entry address, the second item is
HYuana9b85752014-02-26 02:32:30 -0600269 * a bool value indicates whether this is an old entry (false) or a new
270 * entry (true).
271 */
272 std::pair<shared_ptr<name_tree::Entry>, bool>
273 insert(const Name& prefix);
HYuana9b85752014-02-26 02:32:30 -0600274};
275
Haowei Yuane1079fc2014-03-08 14:41:25 -0600276inline NameTree::const_iterator::~const_iterator()
277{
278}
279
HYuana9b85752014-02-26 02:32:30 -0600280inline size_t
281NameTree::size() const
282{
283 return m_nItems;
284}
285
286inline size_t
287NameTree::getNBuckets() const
288{
289 return m_nBuckets;
290}
291
Junxiao Shiefceadc2014-03-09 18:52:57 -0700292inline shared_ptr<name_tree::Entry>
293NameTree::findExactMatch(const fib::Entry& fibEntry) const
294{
295 return fibEntry.m_nameTreeEntry;
296}
297
HangZhangcb4fc832014-03-11 16:57:11 +0800298inline shared_ptr<name_tree::Entry>
299NameTree::get(const fib::Entry& fibEntry) const
300{
301 return fibEntry.m_nameTreeEntry;
302}
303
304inline shared_ptr<name_tree::Entry>
305NameTree::get(const pit::Entry& pitEntry) const
306{
307 return pitEntry.m_nameTreeEntry;
308}
309
310inline shared_ptr<name_tree::Entry>
311NameTree::get(const measurements::Entry& measurementsEntry) const
312{
313 return measurementsEntry.m_nameTreeEntry;
314}
315
316inline shared_ptr<name_tree::Entry>
317NameTree::get(const strategy_choice::Entry& strategeChoiceEntry) const
318{
319 return strategeChoiceEntry.m_nameTreeEntry;
320}
321
Haowei Yuane1079fc2014-03-08 14:41:25 -0600322inline NameTree::const_iterator
323NameTree::begin() const
324{
325 return fullEnumerate();
326}
327
328inline NameTree::const_iterator
329NameTree::end() const
330{
331 return m_endIterator;
332}
333
334inline const name_tree::Entry&
335NameTree::const_iterator::operator*() const
336{
337 return *m_entry;
338}
339
340inline shared_ptr<name_tree::Entry>
341NameTree::const_iterator::operator->() const
342{
343 return m_entry;
344}
345
346inline NameTree::const_iterator
347NameTree::const_iterator::operator++(int)
348{
349 NameTree::const_iterator temp(*this);
350 ++(*this);
351 return temp;
352}
353
354inline bool
355NameTree::const_iterator::operator==(const NameTree::const_iterator& other) const
356{
357 return m_entry == other.m_entry;
358}
359
360inline bool
361NameTree::const_iterator::operator!=(const NameTree::const_iterator& other) const
362{
363 return m_entry != other.m_entry;
364}
365
HYuana9b85752014-02-26 02:32:30 -0600366} // namespace nfd
367
368#endif // NFD_TABLE_NAME_TREE_HPP