blob: 1a30b2b3ddd852c9fd5fca602d02863a8736667d [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
103 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600104 * \brief Erase a Name Tree Entry if this entry is empty.
105 * \details If a Name Tree Entry contains no Children, no FIB, no PIT, and
HYuana9b85752014-02-26 02:32:30 -0600106 * no Measurements entries, then it can be erased. In addition, its parent entry
107 * will also be examined by following the parent pointer until all empty entries
108 * are erased.
Haowei Yuane1079fc2014-03-08 14:41:25 -0600109 * \param entry The pointer to the entry to be erased. The entry pointer should
HYuana9b85752014-02-26 02:32:30 -0600110 * returned by the findExactMatch(), lookup(), or findLongestPrefixMatch() functions.
111 */
112 bool
113 eraseEntryIfEmpty(shared_ptr<name_tree::Entry> entry);
114
115 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600116 * \brief Longest prefix matching for the given name
117 * \details Starts from the full name string, reduce the number of name component
HYuana9b85752014-02-26 02:32:30 -0600118 * by one each time, until an Entry is found.
119 */
120 shared_ptr<name_tree::Entry>
Junxiao Shi40631842014-03-01 13:52:37 -0700121 findLongestPrefixMatch(const Name& prefix,
Haowei Yuane1079fc2014-03-08 14:41:25 -0600122 const name_tree::EntrySelector& entrySelector =
123 name_tree::AnyEntry()) const;
HYuana9b85752014-02-26 02:32:30 -0600124
125 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600126 * \brief Resize the hash table size when its load factor reaches a threshold.
127 * \details As we are currently using a hand-written hash table implementation
HYuana9b85752014-02-26 02:32:30 -0600128 * for the Name Tree, the hash table resize() function should be kept in the
129 * name-tree.hpp file.
Haowei Yuane1079fc2014-03-08 14:41:25 -0600130 * \param newNBuckets The number of buckets for the new hash table.
HYuana9b85752014-02-26 02:32:30 -0600131 */
132 void
133 resize(size_t newNBuckets);
134
135 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600136 * \brief Enumerate all the name prefixes stored in the Name Tree.
HYuana9b85752014-02-26 02:32:30 -0600137 */
Haowei Yuane1079fc2014-03-08 14:41:25 -0600138 const_iterator
139 fullEnumerate(const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry()) const;
HYuana9b85752014-02-26 02:32:30 -0600140
141 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600142 * \brief Enumerate all the name prefixes that satisfies the EntrySubTreeSelector.
143 */
144 const_iterator
Junxiao Shi40631842014-03-01 13:52:37 -0700145 partialEnumerate(const Name& prefix,
Haowei Yuane1079fc2014-03-08 14:41:25 -0600146 const name_tree::EntrySubTreeSelector& entrySubTreeSelector = name_tree::AnyEntrySubTree()) const;
HYuana9b85752014-02-26 02:32:30 -0600147
148 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600149 * \brief Enumerate all the name prefixes that satisfy the prefix and entrySelector
150 */
151 const_iterator
152 findAllMatches(const Name& prefix,
153 const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry()) const;
154
155 /**
156 * \brief Dump all the information stored in the Name Tree for debugging.
HYuana9b85752014-02-26 02:32:30 -0600157 */
158 void
Haowei Yuane1079fc2014-03-08 14:41:25 -0600159 dump(std::ostream& output) const;
160
161 const_iterator
162 begin() const;
163
164 const_iterator
165 end() const;
166
167 enum IteratorType
168 {
169 FULL_ENUMERATE_TYPE,
170 PARTIAL_ENUMERATE_TYPE,
171 FIND_ALL_MATCHES_TYPE
172 };
173
174 class const_iterator : public std::iterator<std::forward_iterator_tag, name_tree::Entry>
175 {
176 public:
177 friend class NameTree;
178
179 const_iterator(NameTree::IteratorType type,
180 const NameTree& nameTree,
181 shared_ptr<name_tree::Entry> entry,
182 const name_tree::EntrySelector& entrySelector = name_tree::AnyEntry(),
183 const name_tree::EntrySubTreeSelector& entrySubTreeSelector = name_tree::AnyEntrySubTree());
184
185 ~const_iterator();
186
187 const name_tree::Entry&
188 operator*() const;
189
190 shared_ptr<name_tree::Entry>
191 operator->() const;
192
193 const_iterator
194 operator++();
195
196 const_iterator
197 operator++(int);
198
199 bool
200 operator==(const const_iterator& other) const;
201
202 bool
203 operator!=(const const_iterator& other) const;
204
205 private:
206 bool m_shouldVisitChildren;
207 const NameTree& m_nameTree;
208 shared_ptr<name_tree::Entry> m_entry;
209 shared_ptr<name_tree::Entry> m_subTreeRoot;
210 shared_ptr<name_tree::EntrySelector> m_entrySelector;
211 shared_ptr<name_tree::EntrySubTreeSelector> m_entrySubTreeSelector;
212 NameTree::IteratorType m_type;
213 };
HYuana9b85752014-02-26 02:32:30 -0600214
215private:
Haowei Yuane1079fc2014-03-08 14:41:25 -0600216 size_t m_nItems; // Number of items being stored
217 size_t m_nBuckets; // Number of hash buckets
218 double m_loadFactor;
219 size_t m_resizeThreshold;
220 int m_resizeFactor;
221 name_tree::Node** m_buckets; // Name Tree Buckets in the NPHT
222 shared_ptr<name_tree::Entry> m_end;
223 const_iterator m_endIterator;
HYuana9b85752014-02-26 02:32:30 -0600224
225 /**
Haowei Yuane1079fc2014-03-08 14:41:25 -0600226 * \brief Create a Name Tree Entry if it does not exist, or return the existing
HYuana9b85752014-02-26 02:32:30 -0600227 * Name Tree Entry address.
Haowei Yuane1079fc2014-03-08 14:41:25 -0600228 * \details Called by lookup() only.
229 * \return The first item is the Name Tree Entry address, the second item is
HYuana9b85752014-02-26 02:32:30 -0600230 * a bool value indicates whether this is an old entry (false) or a new
231 * entry (true).
232 */
233 std::pair<shared_ptr<name_tree::Entry>, bool>
234 insert(const Name& prefix);
HYuana9b85752014-02-26 02:32:30 -0600235};
236
Haowei Yuane1079fc2014-03-08 14:41:25 -0600237inline NameTree::const_iterator::~const_iterator()
238{
239}
240
HYuana9b85752014-02-26 02:32:30 -0600241inline size_t
242NameTree::size() const
243{
244 return m_nItems;
245}
246
247inline size_t
248NameTree::getNBuckets() const
249{
250 return m_nBuckets;
251}
252
Haowei Yuane1079fc2014-03-08 14:41:25 -0600253inline NameTree::const_iterator
254NameTree::begin() const
255{
256 return fullEnumerate();
257}
258
259inline NameTree::const_iterator
260NameTree::end() const
261{
262 return m_endIterator;
263}
264
265inline const name_tree::Entry&
266NameTree::const_iterator::operator*() const
267{
268 return *m_entry;
269}
270
271inline shared_ptr<name_tree::Entry>
272NameTree::const_iterator::operator->() const
273{
274 return m_entry;
275}
276
277inline NameTree::const_iterator
278NameTree::const_iterator::operator++(int)
279{
280 NameTree::const_iterator temp(*this);
281 ++(*this);
282 return temp;
283}
284
285inline bool
286NameTree::const_iterator::operator==(const NameTree::const_iterator& other) const
287{
288 return m_entry == other.m_entry;
289}
290
291inline bool
292NameTree::const_iterator::operator!=(const NameTree::const_iterator& other) const
293{
294 return m_entry != other.m_entry;
295}
296
HYuana9b85752014-02-26 02:32:30 -0600297} // namespace nfd
298
299#endif // NFD_TABLE_NAME_TREE_HPP