blob: b51e033998b47ae78ca30ff36c4404af8d12f5b2 [file] [log] [blame]
HYuana9b85752014-02-26 02:32:30 -06001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (C) 2014 Named Data Networking Project
4 * See COPYING for copyright and distribution information.
5 */
6
7// Name Tree (Name Prefix Hash Table)
8
9#ifndef NFD_TABLE_NAME_TREE_HPP
10#define NFD_TABLE_NAME_TREE_HPP
11
12#include "common.hpp"
13#include "name-tree-entry.hpp"
14
15namespace nfd {
16namespace name_tree {
17
18/**
Haowei Yuane1079fc2014-03-08 14:41:25 -060019 * \brief Compute the hash value of the given name prefix.
20 * \todo 1) have another parameter that specifies the number of components
HYuana9b85752014-02-26 02:32:30 -060021 * 2) optimize the hash function to return a list of have values for all
22 * the (or a certain number of, like a batch operation) prefixes. 3) move
23 * the hash-related code to a separate file in /core or ndn-cpp-dev lib.
24 */
25uint32_t
26hashName(const Name& prefix);
27
Junxiao Shi40631842014-03-01 13:52:37 -070028/// a predicate to accept or reject an Entry in find operations
29typedef function<bool (const Entry& entry)> EntrySelector;
30
Haowei Yuane1079fc2014-03-08 14:41:25 -060031/**
32 * \brief a predicate to accept or reject an Entry and its children
33 * \return .first indicates whether entry should be accepted;
34 * .second indicates whether entry's children should be visited
35 */
36typedef function<std::pair<bool,bool> (const Entry& entry)> EntrySubTreeSelector;
37
Junxiao Shi40631842014-03-01 13:52:37 -070038struct AnyEntry {
39 bool
40 operator()(const Entry& entry)
41 {
42 return true;
43 }
44};
45
Haowei Yuane1079fc2014-03-08 14:41:25 -060046struct AnyEntrySubTree {
47 std::pair<bool, bool>
48 operator()(const Entry& entry)
49 {
50 return std::make_pair(true, true);
51 }
52};
53
HYuana9b85752014-02-26 02:32:30 -060054} // namespace name_tree
55
56/**
Haowei Yuane1079fc2014-03-08 14:41:25 -060057 * \brief Class Name Tree
HYuana9b85752014-02-26 02:32:30 -060058 */
59class NameTree : noncopyable
60{
61public:
Haowei Yuane1079fc2014-03-08 14:41:25 -060062 class const_iterator;
63
HYuana9b85752014-02-26 02:32:30 -060064 explicit
65 NameTree(size_t nBuckets);
66
67 ~NameTree();
68
69 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -060070 * \brief Get the number of occupied entries in the Name Tree
HYuana9b85752014-02-26 02:32:30 -060071 */
72 size_t
73 size() const;
74
75 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -060076 * \brief Get the number of buckets in the Name Tree (NPHT)
77 * \details The number of buckets is the one that used to create the hash
HYuana9b85752014-02-26 02:32:30 -060078 * table, i.e., m_nBuckets.
79 */
80 size_t
81 getNBuckets() const;
82
83 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -060084 * \brief Look for the Name Tree Entry that contains this name prefix.
85 * \details Starts from the shortest name prefix, and then increase the
HYuana9b85752014-02-26 02:32:30 -060086 * number of name components by one each time. All non-existing Name Tree
87 * Entries will be created.
Haowei Yuane1079fc2014-03-08 14:41:25 -060088 * \param prefix The querying name prefix.
89 * \return The pointer to the Name Tree Entry that contains this full name
HYuana9b85752014-02-26 02:32:30 -060090 * prefix.
91 */
92 shared_ptr<name_tree::Entry>
93 lookup(const Name& prefix);
94
95 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -060096 * \brief Exact match lookup for the given name prefix.
97 * \return a null shared_ptr if this prefix is not found;
HYuana9b85752014-02-26 02:32:30 -060098 * otherwise return the Name Tree Entry address
99 */
100 shared_ptr<name_tree::Entry>
101 findExactMatch(const Name& prefix) const;
102
Junxiao Shiefceadc2014-03-09 18:52:57 -0700103 shared_ptr<name_tree::Entry>
104 findExactMatch(const fib::Entry& fibEntry) const;
105
HYuana9b85752014-02-26 02:32:30 -0600106 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600107 * \brief Erase a Name Tree Entry if this entry is empty.
108 * \details If a Name Tree Entry contains no Children, no FIB, no PIT, and
HYuana9b85752014-02-26 02:32:30 -0600109 * no Measurements entries, then it can be erased. In addition, its parent entry
110 * will also be examined by following the parent pointer until all empty entries
111 * are erased.
Haowei Yuane1079fc2014-03-08 14:41:25 -0600112 * \param entry The pointer to the entry to be erased. The entry pointer should
HYuana9b85752014-02-26 02:32:30 -0600113 * returned by the findExactMatch(), lookup(), or findLongestPrefixMatch() functions.
114 */
115 bool
116 eraseEntryIfEmpty(shared_ptr<name_tree::Entry> entry);
117
118 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600119 * \brief Longest prefix matching for the given name
120 * \details Starts from the full name string, reduce the number of name component
HYuana9b85752014-02-26 02:32:30 -0600121 * by one each time, until an Entry is found.
122 */
123 shared_ptr<name_tree::Entry>
Junxiao Shi40631842014-03-01 13:52:37 -0700124 findLongestPrefixMatch(const Name& prefix,
Haowei Yuane1079fc2014-03-08 14:41:25 -0600125 const name_tree::EntrySelector& entrySelector =
126 name_tree::AnyEntry()) const;
HYuana9b85752014-02-26 02:32:30 -0600127
HangZhangcb4fc832014-03-11 16:57:11 +0800128 shared_ptr<name_tree::Entry>
129 findLongestPrefixMatch(shared_ptr<name_tree::Entry> entry,
130 const name_tree::EntrySelector& entrySelector =
131 name_tree::AnyEntry()) const;
132
HYuana9b85752014-02-26 02:32:30 -0600133 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600134 * \brief Resize the hash table size when its load factor reaches a threshold.
135 * \details As we are currently using a hand-written hash table implementation
HYuana9b85752014-02-26 02:32:30 -0600136 * for the Name Tree, the hash table resize() function should be kept in the
137 * name-tree.hpp file.
Haowei Yuane1079fc2014-03-08 14:41:25 -0600138 * \param newNBuckets The number of buckets for the new hash table.
HYuana9b85752014-02-26 02:32:30 -0600139 */
140 void
141 resize(size_t newNBuckets);
142
143 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600144 * \brief Enumerate all the name prefixes stored in the Name Tree.
HYuana9b85752014-02-26 02:32:30 -0600145 */
Haowei Yuane1079fc2014-03-08 14:41:25 -0600146 const_iterator
147 fullEnumerate(const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry()) const;
HYuana9b85752014-02-26 02:32:30 -0600148
149 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600150 * \brief Enumerate all the name prefixes that satisfies the EntrySubTreeSelector.
151 */
152 const_iterator
Junxiao Shi40631842014-03-01 13:52:37 -0700153 partialEnumerate(const Name& prefix,
Junxiao Shiefceadc2014-03-09 18:52:57 -0700154 const name_tree::EntrySubTreeSelector& entrySubTreeSelector =
155 name_tree::AnyEntrySubTree()) const;
HYuana9b85752014-02-26 02:32:30 -0600156
157 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600158 * \brief Enumerate all the name prefixes that satisfy the prefix and entrySelector
159 */
160 const_iterator
161 findAllMatches(const Name& prefix,
162 const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry()) const;
163
164 /**
165 * \brief Dump all the information stored in the Name Tree for debugging.
HYuana9b85752014-02-26 02:32:30 -0600166 */
167 void
Haowei Yuane1079fc2014-03-08 14:41:25 -0600168 dump(std::ostream& output) const;
169
HangZhangcb4fc832014-03-11 16:57:11 +0800170 shared_ptr<name_tree::Entry>
171 get(const fib::Entry& fibEntry) const;
172
173 shared_ptr<name_tree::Entry>
174 get(const pit::Entry& pitEntry) const;
175
176 shared_ptr<name_tree::Entry>
177 get(const measurements::Entry& measurementsEntry) const;
178
179 shared_ptr<name_tree::Entry>
180 get(const strategy_choice::Entry& strategeChoiceEntry) const;
181
Haowei Yuane1079fc2014-03-08 14:41:25 -0600182 const_iterator
183 begin() const;
184
185 const_iterator
186 end() const;
187
188 enum IteratorType
189 {
190 FULL_ENUMERATE_TYPE,
191 PARTIAL_ENUMERATE_TYPE,
192 FIND_ALL_MATCHES_TYPE
193 };
194
195 class const_iterator : public std::iterator<std::forward_iterator_tag, name_tree::Entry>
196 {
197 public:
198 friend class NameTree;
199
200 const_iterator(NameTree::IteratorType type,
201 const NameTree& nameTree,
202 shared_ptr<name_tree::Entry> entry,
203 const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry(),
204 const name_tree::EntrySubTreeSelector& entrySubTreeSelector = name_tree::AnyEntrySubTree());
205
206 ~const_iterator();
207
208 const name_tree::Entry&
209 operator*() const;
210
211 shared_ptr<name_tree::Entry>
212 operator->() const;
213
214 const_iterator
215 operator++();
216
217 const_iterator
218 operator++(int);
219
220 bool
221 operator==(const const_iterator& other) const;
222
223 bool
224 operator!=(const const_iterator& other) const;
225
226 private:
Haowei Yuane1079fc2014-03-08 14:41:25 -0600227 const NameTree& m_nameTree;
228 shared_ptr<name_tree::Entry> m_entry;
229 shared_ptr<name_tree::Entry> m_subTreeRoot;
230 shared_ptr<name_tree::EntrySelector> m_entrySelector;
231 shared_ptr<name_tree::EntrySubTreeSelector> m_entrySubTreeSelector;
232 NameTree::IteratorType m_type;
Junxiao Shiefceadc2014-03-09 18:52:57 -0700233 bool m_shouldVisitChildren;
Haowei Yuane1079fc2014-03-08 14:41:25 -0600234 };
HYuana9b85752014-02-26 02:32:30 -0600235
236private:
Haowei Yuane1079fc2014-03-08 14:41:25 -0600237 size_t m_nItems; // Number of items being stored
238 size_t m_nBuckets; // Number of hash buckets
239 double m_loadFactor;
240 size_t m_resizeThreshold;
241 int m_resizeFactor;
242 name_tree::Node** m_buckets; // Name Tree Buckets in the NPHT
243 shared_ptr<name_tree::Entry> m_end;
244 const_iterator m_endIterator;
HYuana9b85752014-02-26 02:32:30 -0600245
246 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600247 * \brief Create a Name Tree Entry if it does not exist, or return the existing
HYuana9b85752014-02-26 02:32:30 -0600248 * Name Tree Entry address.
Haowei Yuane1079fc2014-03-08 14:41:25 -0600249 * \details Called by lookup() only.
250 * \return The first item is the Name Tree Entry address, the second item is
HYuana9b85752014-02-26 02:32:30 -0600251 * a bool value indicates whether this is an old entry (false) or a new
252 * entry (true).
253 */
254 std::pair<shared_ptr<name_tree::Entry>, bool>
255 insert(const Name& prefix);
HYuana9b85752014-02-26 02:32:30 -0600256};
257
Haowei Yuane1079fc2014-03-08 14:41:25 -0600258inline NameTree::const_iterator::~const_iterator()
259{
260}
261
HYuana9b85752014-02-26 02:32:30 -0600262inline size_t
263NameTree::size() const
264{
265 return m_nItems;
266}
267
268inline size_t
269NameTree::getNBuckets() const
270{
271 return m_nBuckets;
272}
273
Junxiao Shiefceadc2014-03-09 18:52:57 -0700274inline shared_ptr<name_tree::Entry>
275NameTree::findExactMatch(const fib::Entry& fibEntry) const
276{
277 return fibEntry.m_nameTreeEntry;
278}
279
HangZhangcb4fc832014-03-11 16:57:11 +0800280inline shared_ptr<name_tree::Entry>
281NameTree::get(const fib::Entry& fibEntry) const
282{
283 return fibEntry.m_nameTreeEntry;
284}
285
286inline shared_ptr<name_tree::Entry>
287NameTree::get(const pit::Entry& pitEntry) const
288{
289 return pitEntry.m_nameTreeEntry;
290}
291
292inline shared_ptr<name_tree::Entry>
293NameTree::get(const measurements::Entry& measurementsEntry) const
294{
295 return measurementsEntry.m_nameTreeEntry;
296}
297
298inline shared_ptr<name_tree::Entry>
299NameTree::get(const strategy_choice::Entry& strategeChoiceEntry) const
300{
301 return strategeChoiceEntry.m_nameTreeEntry;
302}
303
Haowei Yuane1079fc2014-03-08 14:41:25 -0600304inline NameTree::const_iterator
305NameTree::begin() const
306{
307 return fullEnumerate();
308}
309
310inline NameTree::const_iterator
311NameTree::end() const
312{
313 return m_endIterator;
314}
315
316inline const name_tree::Entry&
317NameTree::const_iterator::operator*() const
318{
319 return *m_entry;
320}
321
322inline shared_ptr<name_tree::Entry>
323NameTree::const_iterator::operator->() const
324{
325 return m_entry;
326}
327
328inline NameTree::const_iterator
329NameTree::const_iterator::operator++(int)
330{
331 NameTree::const_iterator temp(*this);
332 ++(*this);
333 return temp;
334}
335
336inline bool
337NameTree::const_iterator::operator==(const NameTree::const_iterator& other) const
338{
339 return m_entry == other.m_entry;
340}
341
342inline bool
343NameTree::const_iterator::operator!=(const NameTree::const_iterator& other) const
344{
345 return m_entry != other.m_entry;
346}
347
HYuana9b85752014-02-26 02:32:30 -0600348} // namespace nfd
349
350#endif // NFD_TABLE_NAME_TREE_HPP