blob: 027f8520d4c5bdd2794b6261054319b51686ad96 [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;
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
89 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -060090 * \brief Get the number of occupied entries in the Name Tree
HYuana9b85752014-02-26 02:32:30 -060091 */
92 size_t
93 size() const;
94
95 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -060096 * \brief Get the number of buckets in the Name Tree (NPHT)
97 * \details The number of buckets is the one that used to create the hash
HYuana9b85752014-02-26 02:32:30 -060098 * table, i.e., m_nBuckets.
99 */
100 size_t
101 getNBuckets() const;
102
103 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600104 * \brief Look for the Name Tree Entry that contains this name prefix.
105 * \details Starts from the shortest name prefix, and then increase the
HYuana9b85752014-02-26 02:32:30 -0600106 * number of name components by one each time. All non-existing Name Tree
107 * Entries will be created.
Haowei Yuane1079fc2014-03-08 14:41:25 -0600108 * \param prefix The querying name prefix.
109 * \return The pointer to the Name Tree Entry that contains this full name
HYuana9b85752014-02-26 02:32:30 -0600110 * prefix.
111 */
112 shared_ptr<name_tree::Entry>
113 lookup(const Name& prefix);
114
115 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600116 * \brief Exact match lookup for the given name prefix.
117 * \return a null shared_ptr if this prefix is not found;
HYuana9b85752014-02-26 02:32:30 -0600118 * otherwise return the Name Tree Entry address
119 */
120 shared_ptr<name_tree::Entry>
121 findExactMatch(const Name& prefix) const;
122
123 /**
Junxiao Shiee5a4442014-07-27 17:13:43 -0700124 * \brief Delete a Name Tree Entry if this entry is empty.
125 * \param entry The entry to be deleted if empty.
126 * \note This function must be called after a table entry is detached from Name Tree
127 * entry. The function deletes a Name Tree entry if nothing is attached to it and
128 * it has no children, then repeats the same process on its ancestors.
HYuana9b85752014-02-26 02:32:30 -0600129 */
130 bool
131 eraseEntryIfEmpty(shared_ptr<name_tree::Entry> entry);
132
133 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600134 * \brief Longest prefix matching for the given name
135 * \details Starts from the full name string, reduce the number of name component
HYuana9b85752014-02-26 02:32:30 -0600136 * by one each time, until an Entry is found.
137 */
138 shared_ptr<name_tree::Entry>
Junxiao Shi40631842014-03-01 13:52:37 -0700139 findLongestPrefixMatch(const Name& prefix,
Haowei Yuane1079fc2014-03-08 14:41:25 -0600140 const name_tree::EntrySelector& entrySelector =
141 name_tree::AnyEntry()) const;
HYuana9b85752014-02-26 02:32:30 -0600142
HangZhangcb4fc832014-03-11 16:57:11 +0800143 shared_ptr<name_tree::Entry>
144 findLongestPrefixMatch(shared_ptr<name_tree::Entry> entry,
145 const name_tree::EntrySelector& entrySelector =
146 name_tree::AnyEntry()) const;
147
HYuana9b85752014-02-26 02:32:30 -0600148 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600149 * \brief Resize the hash table size when its load factor reaches a threshold.
150 * \details As we are currently using a hand-written hash table implementation
HYuana9b85752014-02-26 02:32:30 -0600151 * for the Name Tree, the hash table resize() function should be kept in the
152 * name-tree.hpp file.
Haowei Yuane1079fc2014-03-08 14:41:25 -0600153 * \param newNBuckets The number of buckets for the new hash table.
HYuana9b85752014-02-26 02:32:30 -0600154 */
155 void
156 resize(size_t newNBuckets);
157
158 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600159 * \brief Enumerate all the name prefixes stored in the Name Tree.
HYuana9b85752014-02-26 02:32:30 -0600160 */
Haowei Yuane1079fc2014-03-08 14:41:25 -0600161 const_iterator
162 fullEnumerate(const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry()) const;
HYuana9b85752014-02-26 02:32:30 -0600163
164 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600165 * \brief Enumerate all the name prefixes that satisfies the EntrySubTreeSelector.
166 */
167 const_iterator
Junxiao Shi40631842014-03-01 13:52:37 -0700168 partialEnumerate(const Name& prefix,
Junxiao Shiefceadc2014-03-09 18:52:57 -0700169 const name_tree::EntrySubTreeSelector& entrySubTreeSelector =
170 name_tree::AnyEntrySubTree()) const;
HYuana9b85752014-02-26 02:32:30 -0600171
172 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600173 * \brief Enumerate all the name prefixes that satisfy the prefix and entrySelector
174 */
175 const_iterator
176 findAllMatches(const Name& prefix,
177 const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry()) const;
178
179 /**
180 * \brief Dump all the information stored in the Name Tree for debugging.
HYuana9b85752014-02-26 02:32:30 -0600181 */
182 void
Haowei Yuane1079fc2014-03-08 14:41:25 -0600183 dump(std::ostream& output) const;
184
HangZhangcb4fc832014-03-11 16:57:11 +0800185 shared_ptr<name_tree::Entry>
186 get(const fib::Entry& fibEntry) const;
187
188 shared_ptr<name_tree::Entry>
189 get(const pit::Entry& pitEntry) const;
190
191 shared_ptr<name_tree::Entry>
192 get(const measurements::Entry& measurementsEntry) const;
193
194 shared_ptr<name_tree::Entry>
195 get(const strategy_choice::Entry& strategeChoiceEntry) const;
196
Haowei Yuane1079fc2014-03-08 14:41:25 -0600197 const_iterator
198 begin() const;
199
200 const_iterator
201 end() const;
202
203 enum IteratorType
204 {
205 FULL_ENUMERATE_TYPE,
206 PARTIAL_ENUMERATE_TYPE,
207 FIND_ALL_MATCHES_TYPE
208 };
209
210 class const_iterator : public std::iterator<std::forward_iterator_tag, name_tree::Entry>
211 {
212 public:
213 friend class NameTree;
214
215 const_iterator(NameTree::IteratorType type,
216 const NameTree& nameTree,
217 shared_ptr<name_tree::Entry> entry,
218 const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry(),
219 const name_tree::EntrySubTreeSelector& entrySubTreeSelector = name_tree::AnyEntrySubTree());
220
221 ~const_iterator();
222
223 const name_tree::Entry&
224 operator*() const;
225
226 shared_ptr<name_tree::Entry>
227 operator->() const;
228
229 const_iterator
230 operator++();
231
232 const_iterator
233 operator++(int);
234
235 bool
236 operator==(const const_iterator& other) const;
237
238 bool
239 operator!=(const const_iterator& other) const;
240
241 private:
Haowei Yuane1079fc2014-03-08 14:41:25 -0600242 const NameTree& m_nameTree;
243 shared_ptr<name_tree::Entry> m_entry;
244 shared_ptr<name_tree::Entry> m_subTreeRoot;
245 shared_ptr<name_tree::EntrySelector> m_entrySelector;
246 shared_ptr<name_tree::EntrySubTreeSelector> m_entrySubTreeSelector;
247 NameTree::IteratorType m_type;
Junxiao Shiefceadc2014-03-09 18:52:57 -0700248 bool m_shouldVisitChildren;
Haowei Yuane1079fc2014-03-08 14:41:25 -0600249 };
HYuana9b85752014-02-26 02:32:30 -0600250
251private:
Haowei Yuane1079fc2014-03-08 14:41:25 -0600252 size_t m_nItems; // Number of items being stored
253 size_t m_nBuckets; // Number of hash buckets
Haowei Yuanf52dac72014-03-24 23:35:03 -0500254 size_t m_minNBuckets; // Minimum number of hash buckets
255 double m_enlargeLoadFactor;
256 size_t m_enlargeThreshold;
257 int m_enlargeFactor;
258 double m_shrinkLoadFactor;
259 size_t m_shrinkThreshold;
260 double m_shrinkFactor;
Haowei Yuane1079fc2014-03-08 14:41:25 -0600261 name_tree::Node** m_buckets; // Name Tree Buckets in the NPHT
262 shared_ptr<name_tree::Entry> m_end;
263 const_iterator m_endIterator;
HYuana9b85752014-02-26 02:32:30 -0600264
265 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600266 * \brief Create a Name Tree Entry if it does not exist, or return the existing
HYuana9b85752014-02-26 02:32:30 -0600267 * Name Tree Entry address.
Haowei Yuane1079fc2014-03-08 14:41:25 -0600268 * \details Called by lookup() only.
269 * \return The first item is the Name Tree Entry address, the second item is
HYuana9b85752014-02-26 02:32:30 -0600270 * a bool value indicates whether this is an old entry (false) or a new
271 * entry (true).
272 */
273 std::pair<shared_ptr<name_tree::Entry>, bool>
274 insert(const Name& prefix);
HYuana9b85752014-02-26 02:32:30 -0600275};
276
Haowei Yuane1079fc2014-03-08 14:41:25 -0600277inline NameTree::const_iterator::~const_iterator()
278{
279}
280
HYuana9b85752014-02-26 02:32:30 -0600281inline size_t
282NameTree::size() const
283{
284 return m_nItems;
285}
286
287inline size_t
288NameTree::getNBuckets() const
289{
290 return m_nBuckets;
291}
292
Junxiao Shiefceadc2014-03-09 18:52:57 -0700293inline shared_ptr<name_tree::Entry>
HangZhangcb4fc832014-03-11 16:57:11 +0800294NameTree::get(const fib::Entry& fibEntry) const
295{
296 return fibEntry.m_nameTreeEntry;
297}
298
299inline shared_ptr<name_tree::Entry>
300NameTree::get(const pit::Entry& pitEntry) const
301{
302 return pitEntry.m_nameTreeEntry;
303}
304
305inline shared_ptr<name_tree::Entry>
306NameTree::get(const measurements::Entry& measurementsEntry) const
307{
308 return measurementsEntry.m_nameTreeEntry;
309}
310
311inline shared_ptr<name_tree::Entry>
312NameTree::get(const strategy_choice::Entry& strategeChoiceEntry) const
313{
314 return strategeChoiceEntry.m_nameTreeEntry;
315}
316
Haowei Yuane1079fc2014-03-08 14:41:25 -0600317inline NameTree::const_iterator
318NameTree::begin() const
319{
320 return fullEnumerate();
321}
322
323inline NameTree::const_iterator
324NameTree::end() const
325{
326 return m_endIterator;
327}
328
329inline const name_tree::Entry&
330NameTree::const_iterator::operator*() const
331{
332 return *m_entry;
333}
334
335inline shared_ptr<name_tree::Entry>
336NameTree::const_iterator::operator->() const
337{
338 return m_entry;
339}
340
341inline NameTree::const_iterator
342NameTree::const_iterator::operator++(int)
343{
344 NameTree::const_iterator temp(*this);
345 ++(*this);
346 return temp;
347}
348
349inline bool
350NameTree::const_iterator::operator==(const NameTree::const_iterator& other) const
351{
352 return m_entry == other.m_entry;
353}
354
355inline bool
356NameTree::const_iterator::operator!=(const NameTree::const_iterator& other) const
357{
358 return m_entry != other.m_entry;
359}
360
HYuana9b85752014-02-26 02:32:30 -0600361} // namespace nfd
362
Alexander Afanasyev613e2a92014-04-15 13:36:58 -0700363#endif // NFD_DAEMON_TABLE_NAME_TREE_HPP