blob: 3d0de70a02894b293d4dbc57aa4e4540f36a9bc2 [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
128 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600129 * \brief Resize the hash table size when its load factor reaches a threshold.
130 * \details As we are currently using a hand-written hash table implementation
HYuana9b85752014-02-26 02:32:30 -0600131 * for the Name Tree, the hash table resize() function should be kept in the
132 * name-tree.hpp file.
Haowei Yuane1079fc2014-03-08 14:41:25 -0600133 * \param newNBuckets The number of buckets for the new hash table.
HYuana9b85752014-02-26 02:32:30 -0600134 */
135 void
136 resize(size_t newNBuckets);
137
138 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600139 * \brief Enumerate all the name prefixes stored in the Name Tree.
HYuana9b85752014-02-26 02:32:30 -0600140 */
Haowei Yuane1079fc2014-03-08 14:41:25 -0600141 const_iterator
142 fullEnumerate(const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry()) const;
HYuana9b85752014-02-26 02:32:30 -0600143
144 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600145 * \brief Enumerate all the name prefixes that satisfies the EntrySubTreeSelector.
146 */
147 const_iterator
Junxiao Shi40631842014-03-01 13:52:37 -0700148 partialEnumerate(const Name& prefix,
Junxiao Shiefceadc2014-03-09 18:52:57 -0700149 const name_tree::EntrySubTreeSelector& entrySubTreeSelector =
150 name_tree::AnyEntrySubTree()) const;
HYuana9b85752014-02-26 02:32:30 -0600151
152 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600153 * \brief Enumerate all the name prefixes that satisfy the prefix and entrySelector
154 */
155 const_iterator
156 findAllMatches(const Name& prefix,
157 const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry()) const;
158
159 /**
160 * \brief Dump all the information stored in the Name Tree for debugging.
HYuana9b85752014-02-26 02:32:30 -0600161 */
162 void
Haowei Yuane1079fc2014-03-08 14:41:25 -0600163 dump(std::ostream& output) const;
164
165 const_iterator
166 begin() const;
167
168 const_iterator
169 end() const;
170
171 enum IteratorType
172 {
173 FULL_ENUMERATE_TYPE,
174 PARTIAL_ENUMERATE_TYPE,
175 FIND_ALL_MATCHES_TYPE
176 };
177
178 class const_iterator : public std::iterator<std::forward_iterator_tag, name_tree::Entry>
179 {
180 public:
181 friend class NameTree;
182
183 const_iterator(NameTree::IteratorType type,
184 const NameTree& nameTree,
185 shared_ptr<name_tree::Entry> entry,
186 const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry(),
187 const name_tree::EntrySubTreeSelector& entrySubTreeSelector = name_tree::AnyEntrySubTree());
188
189 ~const_iterator();
190
191 const name_tree::Entry&
192 operator*() const;
193
194 shared_ptr<name_tree::Entry>
195 operator->() const;
196
197 const_iterator
198 operator++();
199
200 const_iterator
201 operator++(int);
202
203 bool
204 operator==(const const_iterator& other) const;
205
206 bool
207 operator!=(const const_iterator& other) const;
208
209 private:
Haowei Yuane1079fc2014-03-08 14:41:25 -0600210 const NameTree& m_nameTree;
211 shared_ptr<name_tree::Entry> m_entry;
212 shared_ptr<name_tree::Entry> m_subTreeRoot;
213 shared_ptr<name_tree::EntrySelector> m_entrySelector;
214 shared_ptr<name_tree::EntrySubTreeSelector> m_entrySubTreeSelector;
215 NameTree::IteratorType m_type;
Junxiao Shiefceadc2014-03-09 18:52:57 -0700216 bool m_shouldVisitChildren;
Haowei Yuane1079fc2014-03-08 14:41:25 -0600217 };
HYuana9b85752014-02-26 02:32:30 -0600218
219private:
Haowei Yuane1079fc2014-03-08 14:41:25 -0600220 size_t m_nItems; // Number of items being stored
221 size_t m_nBuckets; // Number of hash buckets
222 double m_loadFactor;
223 size_t m_resizeThreshold;
224 int m_resizeFactor;
225 name_tree::Node** m_buckets; // Name Tree Buckets in the NPHT
226 shared_ptr<name_tree::Entry> m_end;
227 const_iterator m_endIterator;
HYuana9b85752014-02-26 02:32:30 -0600228
229 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600230 * \brief Create a Name Tree Entry if it does not exist, or return the existing
HYuana9b85752014-02-26 02:32:30 -0600231 * Name Tree Entry address.
Haowei Yuane1079fc2014-03-08 14:41:25 -0600232 * \details Called by lookup() only.
233 * \return The first item is the Name Tree Entry address, the second item is
HYuana9b85752014-02-26 02:32:30 -0600234 * a bool value indicates whether this is an old entry (false) or a new
235 * entry (true).
236 */
237 std::pair<shared_ptr<name_tree::Entry>, bool>
238 insert(const Name& prefix);
HYuana9b85752014-02-26 02:32:30 -0600239};
240
Haowei Yuane1079fc2014-03-08 14:41:25 -0600241inline NameTree::const_iterator::~const_iterator()
242{
243}
244
HYuana9b85752014-02-26 02:32:30 -0600245inline size_t
246NameTree::size() const
247{
248 return m_nItems;
249}
250
251inline size_t
252NameTree::getNBuckets() const
253{
254 return m_nBuckets;
255}
256
Junxiao Shiefceadc2014-03-09 18:52:57 -0700257inline shared_ptr<name_tree::Entry>
258NameTree::findExactMatch(const fib::Entry& fibEntry) const
259{
260 return fibEntry.m_nameTreeEntry;
261}
262
Haowei Yuane1079fc2014-03-08 14:41:25 -0600263inline NameTree::const_iterator
264NameTree::begin() const
265{
266 return fullEnumerate();
267}
268
269inline NameTree::const_iterator
270NameTree::end() const
271{
272 return m_endIterator;
273}
274
275inline const name_tree::Entry&
276NameTree::const_iterator::operator*() const
277{
278 return *m_entry;
279}
280
281inline shared_ptr<name_tree::Entry>
282NameTree::const_iterator::operator->() const
283{
284 return m_entry;
285}
286
287inline NameTree::const_iterator
288NameTree::const_iterator::operator++(int)
289{
290 NameTree::const_iterator temp(*this);
291 ++(*this);
292 return temp;
293}
294
295inline bool
296NameTree::const_iterator::operator==(const NameTree::const_iterator& other) const
297{
298 return m_entry == other.m_entry;
299}
300
301inline bool
302NameTree::const_iterator::operator!=(const NameTree::const_iterator& other) const
303{
304 return m_entry != other.m_entry;
305}
306
HYuana9b85752014-02-26 02:32:30 -0600307} // namespace nfd
308
309#endif // NFD_TABLE_NAME_TREE_HPP