blob: 21bc36208aa2b7cee930f4e16b1dacb7b2e9b7c8 [file] [log] [blame]
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -07001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2011 University of California, Los Angeles
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
19 */
20
21#include "ns3/core-module.h"
22#include "ns3/ndnSIM-module.h"
23
24#include <boost/intrusive/unordered_set.hpp>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070025#include <boost/intrusive/list.hpp>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070026#include <boost/functional/hash.hpp>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070027#include <boost/interprocess/smart_ptr/unique_ptr.hpp>
28#include <boost/tuple/tuple.hpp>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070029
30namespace bi = boost::intrusive;
31
32/////////////////////////////////////////////////////
33// Allow customization for payload
34//
35template<typename Payload>
36struct pointer_payload_traits
37{
38 typedef Payload* pointer_type;
39 typedef const Payload* const_pointer_type;
40
41 static const Payload* empty_payload;
42};
43
44template<typename Payload>
45const Payload*
46pointer_payload_traits<Payload>::empty_payload = 0;
47
48template<typename Payload>
49struct smart_pointer_payload_traits
50{
51 typedef ns3::Ptr<Payload> pointer_type;
52 typedef ns3::Ptr<const Payload> const_pointer_type;
53
54 static const ns3::Ptr<const Payload> empty_payload;
55};
56
57template<typename Payload>
58const ns3::Ptr<const Payload>
59smart_pointer_payload_traits<Payload>::empty_payload = 0;
60
61
62////////////////////////////////////////////////////
63// forward declarations
64//
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070065template<typename FullKey,
66 typename Payload,
67 typename PayloadTraits = pointer_payload_traits<Payload>,
68 typename PolicyHook = bi::list_member_hook<> >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070069class trie;
70
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070071template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070072inline std::ostream&
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070073operator << (std::ostream &os,
74 const trie<FullKey, Payload, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070075
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070076template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070077bool
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070078operator== (const trie<FullKey, Payload, PayloadTraits, PolicyHook> &a,
79 const trie<FullKey, Payload, PayloadTraits, PolicyHook> &b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070080
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070081template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070082std::size_t
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070083hash_value (const trie<FullKey, Payload, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070084
85///////////////////////////////////////////////////
86// actual definition
87//
88
89
90template<typename FullKey,
Alexander Afanasyev89fb5352012-06-12 22:43:16 -070091 typename Payload, typename PayloadTraits,
92 typename PolicyHook >
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -070093class trie
94{
95public:
96 typedef typename FullKey::partial_type Key;
97
98 typedef trie* iterator;
99 typedef const trie* const_iterator;
100
101 inline
102 trie (const Key &key, size_t bucketSize = 10, size_t bucketIncrement = 10);
103
104 inline
105 ~trie ();
106
107 // actual entry
108 friend bool
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700109 operator== <> (const trie<FullKey, Payload, PayloadTraits, PolicyHook> &a,
110 const trie<FullKey, Payload, PayloadTraits, PolicyHook> &b);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700111
112 friend std::size_t
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700113 hash_value <> (const trie<FullKey, Payload, PayloadTraits, PolicyHook> &trie_node);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700114
115 inline std::pair<iterator, bool>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700116 insert (const FullKey &key,
117 typename PayloadTraits::const_pointer_type payload);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700118
119 /**
120 * @brief Removes payload (if it exists) and if there are no children, prunes parents trie
121 */
122 inline void
123 erase ();
124
125 /**
126 * @brief Do exactly as erase, but without erasing the payload
127 */
128 inline void
129 prune ();
130
131 /**
132 * @brief Perform the longest prefix match
133 * @param key the key for which to perform the longest prefix match
134 *
135 * @return ->second is true if prefix in ->first is longer than key
136 */
137 inline boost::tuple<iterator, bool, iterator>
138 find (const FullKey &key);
139
140 /**
141 * @brief Find next payload of the sub-trie
142 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
143 */
144 inline iterator
145 find ();
146
147 /**
148 * @brief Find next payload of the sub-trie satisfying the predicate
149 * @param pred predicate
150 * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
151 */
152 template<class Predicate>
153 inline iterator
154 find_if (Predicate pred);
155
156 iterator end ()
157 {
158 return 0;
159 }
160
161 const_iterator end () const
162 {
163 return 0;
164 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700165
166 typename PayloadTraits::const_pointer_type
167 payload () const
168 {
169 return payload_;
170 }
171
172 void
173 set_payload (typename PayloadTraits::const_pointer_type payload)
174 {
175 payload_ = payload;
176 }
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700177
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700178 inline void
179 PrintStat (std::ostream &os) const;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700180
181private:
182 //The disposer object function
183 struct trie_delete_disposer
184 {
185 void operator() (trie *delete_this)
186 {
187 // std::cout << "Deleting " << delete_this << "\n";
188 delete delete_this;
189 }
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700190 };
191
192 template<class D>
193 struct array_disposer
194 {
195 void operator() (D *array)
196 {
197 delete [] array;
198 }
199 };
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700200
201 friend
202 std::ostream&
203 operator<< < > (std::ostream &os, const trie &trie_node);
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700204
205public:
206 PolicyHook policy_hook_;
207
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700208private:
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700209 bi::unordered_set_member_hook<> unordered_set_member_hook_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700210
211 // necessary typedefs
212 typedef trie self_type;
213 typedef bi::member_hook< trie,
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700214 bi::unordered_set_member_hook< >, &trie::unordered_set_member_hook_ > member_hook;
215 typedef bi::unordered_set< trie, member_hook > unordered_set;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700216 typedef typename unordered_set::bucket_type bucket_type;
217 typedef typename unordered_set::bucket_traits bucket_traits;
218
219 ////////////////////////////////////////////////
220 // Actual data
221 ////////////////////////////////////////////////
222
223 Key key_; ///< name component
224
225 size_t initialBucketSize_;
226 size_t bucketIncrement_;
227
228 size_t bucketSize_;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700229 typedef boost::interprocess::unique_ptr< bucket_type, array_disposer<bucket_type> > buckets_array;
230 buckets_array buckets_;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700231 unordered_set children_;
232
233 typename PayloadTraits::const_pointer_type payload_;
234 trie *parent_; // to make cleaning effective
235};
236
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700237template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
238trie<FullKey, Payload, PayloadTraits, PolicyHook>
239::trie (const trie::Key &key, size_t bucketSize, size_t bucketIncrement)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700240 : key_ (key)
241 , initialBucketSize_ (bucketSize)
242 , bucketIncrement_ (bucketIncrement)
243 , bucketSize_ (initialBucketSize_)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700244 , buckets_ (new bucket_type [bucketSize_]) //cannot use normal pointer, because lifetime of buckets should be larger than lifetime of the container
245 , children_ (bucket_traits (buckets_.get (), bucketSize_))
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700246 , payload_ (PayloadTraits::empty_payload)
247 , parent_ (0)
248{
249}
250
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700251template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
252trie<FullKey, Payload, PayloadTraits, PolicyHook>
253::~trie ()
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700254{
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700255 payload_ = PayloadTraits::empty_payload; // necessary for smart pointers...
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700256 children_.clear_and_dispose (trie_delete_disposer ());
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700257}
258
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700259template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700260inline
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700261std::pair<typename trie<FullKey, Payload, PayloadTraits, PolicyHook>::iterator, bool>
262trie<FullKey, Payload, PayloadTraits, PolicyHook>
263::insert (const FullKey &key, typename PayloadTraits::const_pointer_type payload)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700264{
265 trie *trieNode = this;
266
267 BOOST_FOREACH (const Key &subkey, key)
268 {
269 typename unordered_set::iterator item = trieNode->children_.find (subkey);
270 if (item == trieNode->children_.end ())
271 {
272 trie *newNode = new trie (subkey, initialBucketSize_, bucketIncrement_);
273 // std::cout << "new " << newNode << "\n";
274 newNode->parent_ = trieNode;
275
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700276 if (trieNode->children_.size () >= trieNode->bucketSize_)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700277 {
278 trieNode->bucketSize_ += trieNode->bucketIncrement_;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700279 buckets_array newBuckets (new bucket_type [trieNode->bucketSize_]);
280 trieNode->children_.rehash (bucket_traits (newBuckets.get (), trieNode->bucketSize_));
281 trieNode->buckets_.swap (newBuckets);
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700282 }
283
284 std::pair< typename unordered_set::iterator, bool > ret =
285 trieNode->children_.insert (*newNode);
286
287 trieNode = &(*ret.first);
288 }
289 else
290 trieNode = &(*item);
291 }
292
293 if (trieNode->payload_ == 0)
294 {
295 trieNode->payload_ = payload;
296 return std::make_pair (trieNode, true);
297 }
298 else
299 return std::make_pair (trieNode, false);
300}
301
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700302template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700303inline
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700304boost::tuple<typename trie<FullKey, Payload, PayloadTraits, PolicyHook>::iterator,
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700305 bool,
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700306 typename trie<FullKey, Payload, PayloadTraits, PolicyHook>::iterator>
307trie<FullKey, Payload, PayloadTraits, PolicyHook>
308::find (const FullKey &key)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700309{
310 trie *trieNode = this;
311 iterator foundNode = (payload_ != PayloadTraits::empty_payload) ? this : 0;
312 bool reachLast = true;
313
314 BOOST_FOREACH (const Key &subkey, key)
315 {
316 typename unordered_set::iterator item = trieNode->children_.find (subkey);
317 if (item == trieNode->children_.end ())
318 {
319 reachLast = false;
320 break;
321 }
322 else
323 {
324 trieNode = &(*item);
325
326 if (trieNode->payload_ != PayloadTraits::empty_payload)
327 foundNode = trieNode;
328 }
329 }
330
331 return boost::make_tuple (foundNode, reachLast, trieNode);
332}
333
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700334template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
335inline typename trie<FullKey, Payload, PayloadTraits, PolicyHook>::iterator
336trie<FullKey, Payload, PayloadTraits, PolicyHook>
337::find ()
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700338{
339 if (payload_ != PayloadTraits::empty_payload)
340 return this;
341
342 typedef trie<FullKey, Payload, PayloadTraits> trie;
Alexander Afanasyevb0c43892012-06-13 00:52:58 -0700343 BOOST_FOREACH (trie &subnode, children_)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700344 {
345 iterator value = subnode.find ();
346 if (value != 0)
347 return value;
348 }
349
350 return 0;
351}
352
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700353template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700354template<class Predicate>
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700355inline typename trie<FullKey, Payload, PayloadTraits, PolicyHook>::iterator
356trie<FullKey, Payload, PayloadTraits, PolicyHook>
357::find_if (Predicate pred)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700358{
359 if (payload_ != PayloadTraits::empty_payload && pred (payload_))
360 return this;
361
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700362 typedef trie<FullKey, Payload, PayloadTraits, PolicyHook> trie;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700363 BOOST_FOREACH (const trie &subnode, children_)
364 {
365 iterator value = subnode.find ();
366 if (value != 0)
367 return value;
368 }
369
370 return 0;
371}
372
373
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700374template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700375inline void
Alexander Afanasyevb0c43892012-06-13 00:52:58 -0700376trie<FullKey, Payload, PayloadTraits, PolicyHook>
377::erase ()
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700378{
379 payload_ = PayloadTraits::empty_payload;
380 prune ();
381}
382
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700383template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700384inline void
Alexander Afanasyevb0c43892012-06-13 00:52:58 -0700385trie<FullKey, Payload, PayloadTraits, PolicyHook>
386::prune ()
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700387{
388 if (payload_ == 0 && children_.size () == 0)
389 {
390 if (parent_ == 0) return;
391
392 trie *parent = parent_;
393 parent->children_.erase_and_dispose (*this, trie_delete_disposer ()); // delete this; basically, committing a suicide
394
395 parent->prune ();
396 }
397}
398
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700399template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700400inline std::ostream&
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700401operator << (std::ostream &os, const trie<FullKey, Payload, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700402{
403 os << "# " << trie_node.key_ << ((trie_node.payload_ != 0)?"*":"") << std::endl;
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700404 typedef trie<FullKey, Payload, PayloadTraits, PolicyHook> trie;
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700405 BOOST_FOREACH (const trie &subnode, trie_node.children_)
406 {
407 os << "\"" << &trie_node << "\"" << " [label=\"" << trie_node.key_ << ((trie_node.payload_ != 0)?"*":"") << "\"]\n";
408 os << "\"" << &subnode << "\"" << " [label=\"" << subnode.key_ << ((subnode.payload_ != 0)?"*":"") << "\"]""\n";
409
410 os << "\"" << &trie_node << "\"" << " -> " << "\"" << &subnode << "\"" << "\n";
411 os << subnode;
412 }
413
414 return os;
415}
416
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700417template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
418inline void
Alexander Afanasyevb0c43892012-06-13 00:52:58 -0700419trie<FullKey, Payload, PayloadTraits, PolicyHook>
420::PrintStat (std::ostream &os) const
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700421{
422 os << "# " << key_ << ((payload_ != 0)?"*":"") << ": " << children_.size() << " children" << std::endl;
423 for (size_t bucket = 0, maxbucket = children_.bucket_count ();
424 bucket < maxbucket;
425 bucket++)
426 {
427 os << " " << children_.bucket_size (bucket);
428 }
429 os << "\n";
430
431 typedef trie<FullKey, Payload, PayloadTraits, PolicyHook> trie;
432 BOOST_FOREACH (const trie &subnode, children_)
433 {
434 subnode.PrintStat (os);
435 }
436}
437
438
439template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700440inline bool
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700441operator == (const trie<FullKey, Payload, PayloadTraits, PolicyHook> &a,
442 const trie<FullKey, Payload, PayloadTraits, PolicyHook> &b)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700443{
444 return a.key_ == b.key_;
445}
446
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700447template<typename FullKey, typename Payload, typename PayloadTraits, typename PolicyHook>
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700448inline std::size_t
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700449hash_value (const trie<FullKey, Payload, PayloadTraits, PolicyHook> &trie_node)
Alexander Afanasyevfd0c41c2012-06-11 22:15:49 -0700450{
451 return boost::hash_value (trie_node.key_);
452}
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700453
454
455
456template<typename FullKey,
457 typename Payload, typename PayloadTraits
458 >
459struct lru_policy_traits
460{
461 typedef trie< FullKey, Payload, PayloadTraits, bi::list_member_hook<> > parent_trie;
462 typedef typename bi::list< parent_trie,
463 bi::member_hook< parent_trie,
464 bi::list_member_hook<>,
465 &parent_trie::policy_hook_ > > policy_container;
466
467 class policy : public policy_container
468 {
469 public:
470 policy ()
471 : max_size_ (100)
472 {
473 }
474
475 inline void
476 update (typename parent_trie::iterator item)
477 {
478 // do relocation
479 policy_container::splice (policy_container::end (),
480 *this,
481 policy_container::s_iterator_to (*item));
482 }
483
484 inline void
485 insert (typename parent_trie::iterator item)
486 {
487 if (policy_container::size () >= max_size_)
488 {
489 typename parent_trie::iterator oldItem = &(*policy_container::begin ());
490 policy_container::pop_front ();
491 oldItem->erase ();
492 }
493
494 policy_container::push_back (*item);
495 }
496
497 inline void
498 lookup (typename parent_trie::iterator item)
499 {
500 // do relocation
501 policy_container::splice (policy_container::end (),
502 *this,
503 policy_container::s_iterator_to (*item));
504 }
505
506 inline void
507 erase (typename parent_trie::iterator item)
508 {
509 policy_container::erase (policy_container::s_iterator_to (*item));
510 }
511
512 inline void
513 set_max_size (size_t max_size)
514 {
515 max_size_ = max_size;
516 }
517
518 private:
519 size_t max_size_;
520 };
521};
522
523
524
525template<typename FullKey,
526 typename Payload, typename PayloadTraits = pointer_payload_traits<Payload>,
527 typename policy_traits = lru_policy_traits<FullKey, Payload, PayloadTraits>
528 >
529class indexed_trie
530{
531public:
532 typedef trie< FullKey, Payload, PayloadTraits > parent_trie;
533 typedef typename parent_trie::iterator iterator;
534
535 inline
536 indexed_trie (size_t bucketSize = 10, size_t bucketIncrement = 10)
537 : trie_ ("", bucketSize, bucketIncrement)
538 {
539 }
540
541 inline std::pair< iterator, bool >
542 insert (const FullKey &key, typename PayloadTraits::const_pointer_type payload)
543 {
544 std::pair<iterator, bool> item =
545 trie_.insert (key, payload);
546
547 if (item.second) // real insert
548 {
549 policy_.insert (s_iterator_to (item.first));
550 }
551 else
552 {
553 item.first->set_payload (payload);
Alexander Afanasyevb0c43892012-06-13 00:52:58 -0700554 policy_.update (s_iterator_to (item.first));
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700555 }
556
557 return item;
558 }
559
560 inline void
561 erase (iterator node)
562 {
563 if (node == end ()) return;
564
565 policy_.erase (s_iterator_to (node));
566 node->erase (); // will do cleanup here
567 }
568
569 /**
Alexander Afanasyevb0c43892012-06-13 00:52:58 -0700570 * @brief Find a node that has the longest common prefix with key (FIB/PIT lookup)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700571 */
Alexander Afanasyevb0c43892012-06-13 00:52:58 -0700572 inline iterator
573 longest_prefix_match (const FullKey &key)
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700574 {
575 boost::tuple< iterator, bool, iterator > item = trie_.find (key);
576 if (item.template get<0> () != trie_.end ())
577 {
578 policy_.lookup (s_iterator_to (item.template get<0> ()));
579 }
Alexander Afanasyevb0c43892012-06-13 00:52:58 -0700580 return item.template get<0> ();
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700581 }
582
Alexander Afanasyevb0c43892012-06-13 00:52:58 -0700583 /**
584 * @brief Find a node that has prefix at least as the key (cache lookup)
585 */
586 inline iterator
587 deepest_prefix_match (const FullKey &key)
588 {
589 iterator foundItem, lastItem;
590 bool reachLast;
591 boost::tie (foundItem, reachLast, lastItem) = trie_.find (key);
592
593 // guard in case we don't have anything in the trie
594 if (lastItem == trie_.end ())
595 return trie_.end ();
596
597 if (reachLast)
598 {
599 if (foundItem == trie_.end ())
600 {
601 foundItem = lastItem->find (); // should be something
602 }
603 policy_.lookup (s_iterator_to (foundItem));
604 return foundItem;
605 }
606 else
607 { // couldn't find a node that has prefix at least as key
608 return trie_.end ();
609 }
610 }
611
612 /**
613 * @brief Find a node that has prefix at least as the key
614 */
615 template<class Predicate>
616 inline iterator
617 deepest_prefix_match (const FullKey &key, Predicate pred)
618 {
619 iterator foundItem, lastItem;
620 bool reachLast;
621 boost::tie (foundItem, reachLast, lastItem) = trie_.find (key);
622
623 // guard in case we don't have anything in the trie
624 if (lastItem == trie_.end ())
625 return trie_.end ();
626
627 if (reachLast)
628 {
629 foundItem = lastItem->find_if (pred); // may or may not find something
630 if (foundItem == trie_.end ())
631 {
632 return trie_.end ();
633 }
634 policy_.lookup (s_iterator_to (foundItem));
635 return foundItem;
636 }
637 else
638 { // couldn't find a node that has prefix at least as key
639 return trie_.end ();
640 }
641 }
642
643 // /**
644 // * @brief Perform the longest prefix match
645 // * @param key the key for which to perform the longest prefix match
646 // *
647 // * @return ->second is true if prefix in ->first is longer than key
648 // * ->third is always last node searched
649 // */
650 // inline boost::tuple< iterator, bool, iterator >
651 // find (const FullKey &key)
652 // {
653 // boost::tuple< iterator, bool, iterator > item = trie_.find (key);
654 // if (item.template get<0> () != trie_.end ())
655 // {
656 // policy_.lookup (s_iterator_to (item.template get<0> ()));
657 // }
658 // return boost::make_tuple (s_iterator_to (item.template get<0> ()),
659 // item.template get<1> (),
660 // s_iterator_to (item.template get<2> ()));
661 // }
662
663 // /**
664 // * @brief Find next payload of the sub-trie
665 // * @param start Start for the search (root for the sub-trie)
666 // * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
667 // */
668 // inline iterator
669 // find (iterator start)
670 // {
671 // iterator item = start->find ();
672 // if (item != trie_.end ())
673 // {
674 // policy_.lookup (s_iterator_to (item));
675 // }
676 // return item;
677 // }
678
679 // /**
680 // * @brief Find next payload of the sub-trie satisfying the predicate
681 // * @param start Start for the search (root for the sub-trie)
682 // * @param pred predicate
683 // * @returns end() or a valid iterator pointing to the trie leaf (order is not defined, enumeration )
684 // */
685 // template<class Predicate>
686 // inline iterator
687 // find_if (iterator start, Predicate pred)
688 // {
689 // iterator item = start->find (pred);
690 // if (item != trie_.end ())
691 // {
692 // policy_.lookup (s_iterator_to (item));
693 // }
694 // return item;
695 // }
696
Alexander Afanasyev89fb5352012-06-12 22:43:16 -0700697 iterator end ()
698 {
699 return 0;
700 }
701
702 const parent_trie &
703 getTrie () const { return trie_; }
704
705 const typename policy_traits::policy &
706 getPolicy () const { return policy_; }
707
708 typename policy_traits::policy &
709 getPolicy () { return policy_; }
710
711 static inline iterator
712 s_iterator_to (typename parent_trie::iterator item)
713 {
714 if (item == 0)
715 return 0;
716 else
717 return &(*item);
718 }
719
720private:
721 parent_trie trie_;
722 typename policy_traits::policy policy_;
723};
724