blob: 12168ea0dd80dae006b675392b95f5ba0b096fc8 [file] [log] [blame]
Alexander Afanasyev9a989702012-06-29 17:44:00 -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#ifndef TRIE_WITH_POLICY_H_
22#define TRIE_WITH_POLICY_H_
23
24#include "trie.h"
Alexander Afanasyev9a989702012-06-29 17:44:00 -070025
Alexander Afanasyeve77db792012-08-09 11:10:58 -070026namespace ns3
27{
Alexander Afanasyev30cb1172012-07-06 10:47:39 -070028namespace ndnSIM
29{
30
Alexander Afanasyev9a989702012-06-29 17:44:00 -070031template<typename FullKey,
Alexander Afanasyev9a989702012-06-29 17:44:00 -070032 typename PayloadTraits,
33 typename PolicyTraits
34 >
35class trie_with_policy
36{
37public:
Alexander Afanasyev9e96e362012-07-02 23:04:39 -070038 typedef trie< FullKey,
Alexander Afanasyev9e96e362012-07-02 23:04:39 -070039 PayloadTraits,
40 typename PolicyTraits::policy_hook_type > parent_trie;
41
42 typedef typename parent_trie::iterator iterator;
Alexander Afanasyev1ba09b82012-07-09 09:16:14 -070043 typedef typename parent_trie::const_iterator const_iterator;
Alexander Afanasyev9e96e362012-07-02 23:04:39 -070044
45 typedef typename PolicyTraits::template policy<
46 trie_with_policy<FullKey, PayloadTraits, PolicyTraits>,
47 parent_trie,
48 typename PolicyTraits::template container_hook<parent_trie>::type >::type policy_container;
Alexander Afanasyev9a989702012-06-29 17:44:00 -070049
50 inline
51 trie_with_policy (size_t bucketSize = 10, size_t bucketIncrement = 10)
52 : trie_ ("", bucketSize, bucketIncrement)
Alexander Afanasyev9e96e362012-07-02 23:04:39 -070053 , policy_ (*this)
Alexander Afanasyev9a989702012-06-29 17:44:00 -070054 {
55 }
56
57 inline std::pair< iterator, bool >
Alexander Afanasyev0845c092012-07-13 17:45:33 -070058 insert (const FullKey &key, typename PayloadTraits::insert_type payload)
Alexander Afanasyev9a989702012-06-29 17:44:00 -070059 {
60 std::pair<iterator, bool> item =
61 trie_.insert (key, payload);
62
63 if (item.second) // real insert
64 {
Alexander Afanasyev9e96e362012-07-02 23:04:39 -070065 bool ok = policy_.insert (s_iterator_to (item.first));
66 if (!ok)
67 {
68 item.first->erase (); // cannot insert
69 return std::make_pair (end (), false);
70 }
Alexander Afanasyev9a989702012-06-29 17:44:00 -070071 }
72 else
73 {
Alexander Afanasyev78057c32012-07-06 15:18:46 -070074 return std::make_pair (s_iterator_to (item.first), false);
Alexander Afanasyev9a989702012-06-29 17:44:00 -070075 }
76
77 return item;
78 }
79
80 inline void
Alexander Afanasyev78057c32012-07-06 15:18:46 -070081 erase (const FullKey &key)
82 {
83 iterator foundItem, lastItem;
84 bool reachLast;
85 boost::tie (foundItem, reachLast, lastItem) = trie_.find (key);
86
87 if (!reachLast || lastItem->payload () == PayloadTraits::empty_payload)
88 return; // nothing to invalidate
89
90 erase (lastItem);
91 }
92
93 inline void
Alexander Afanasyev9a989702012-06-29 17:44:00 -070094 erase (iterator node)
95 {
96 if (node == end ()) return;
97
98 policy_.erase (s_iterator_to (node));
99 node->erase (); // will do cleanup here
100 }
101
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700102 inline void
103 clear ()
104 {
105 policy_.clear ();
106 trie_.clear ();
107 }
108
109 template<typename Modifier>
110 bool
111 modify (iterator position, Modifier mod)
112 {
113 if (position == end ()) return false;
114 if (position->payload () == PayloadTraits::empty_payload) return false;
115
116 mod (*position->payload ());
117 policy_.update (position);
118 return true;
119 }
120
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700121 /**
122 * @brief Find a node that has the longest common prefix with key (FIB/PIT lookup)
123 */
124 inline iterator
125 longest_prefix_match (const FullKey &key)
126 {
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700127 iterator foundItem, lastItem;
128 bool reachLast;
129 boost::tie (foundItem, reachLast, lastItem) = trie_.find (key);
130 if (foundItem != trie_.end ())
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700131 {
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700132 policy_.lookup (s_iterator_to (foundItem));
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700133 }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700134 return foundItem;
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700135 }
136
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700137 // /**
138 // * @brief Const version of the longest common prefix match
139 // * (semi-const, because there could be update of the policy anyways)
140 // */
141 // inline const_iterator
142 // longest_prefix_match (const FullKey &key) const
143 // {
144 // return static_cast<trie_with_policy*> (this)->longest_prefix_match (key);
145 // }
146
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700147 /**
148 * @brief Find a node that has prefix at least as the key (cache lookup)
149 */
150 inline iterator
151 deepest_prefix_match (const FullKey &key)
152 {
153 iterator foundItem, lastItem;
154 bool reachLast;
155 boost::tie (foundItem, reachLast, lastItem) = trie_.find (key);
156
157 // guard in case we don't have anything in the trie
158 if (lastItem == trie_.end ())
159 return trie_.end ();
160
161 if (reachLast)
162 {
163 if (foundItem == trie_.end ())
164 {
165 foundItem = lastItem->find (); // should be something
166 }
167 policy_.lookup (s_iterator_to (foundItem));
168 return foundItem;
169 }
170 else
171 { // couldn't find a node that has prefix at least as key
172 return trie_.end ();
173 }
174 }
175
176 /**
177 * @brief Find a node that has prefix at least as the key
178 */
179 template<class Predicate>
180 inline iterator
181 deepest_prefix_match (const FullKey &key, Predicate pred)
182 {
183 iterator foundItem, lastItem;
184 bool reachLast;
185 boost::tie (foundItem, reachLast, lastItem) = trie_.find (key);
186
187 // guard in case we don't have anything in the trie
188 if (lastItem == trie_.end ())
189 return trie_.end ();
190
191 if (reachLast)
192 {
193 foundItem = lastItem->find_if (pred); // may or may not find something
194 if (foundItem == trie_.end ())
195 {
196 return trie_.end ();
197 }
198 policy_.lookup (s_iterator_to (foundItem));
199 return foundItem;
200 }
201 else
202 { // couldn't find a node that has prefix at least as key
203 return trie_.end ();
204 }
205 }
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700206
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700207 iterator end () const
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700208 {
209 return 0;
210 }
211
212 const parent_trie &
213 getTrie () const { return trie_; }
214
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700215 parent_trie &
216 getTrie () { return trie_; }
217
Alexander Afanasyev9e96e362012-07-02 23:04:39 -0700218 const policy_container &
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700219 getPolicy () const { return policy_; }
220
Alexander Afanasyev9e96e362012-07-02 23:04:39 -0700221 policy_container &
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700222 getPolicy () { return policy_; }
223
224 static inline iterator
225 s_iterator_to (typename parent_trie::iterator item)
226 {
227 if (item == 0)
228 return 0;
229 else
230 return &(*item);
231 }
232
233private:
234 parent_trie trie_;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700235 mutable policy_container policy_;
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700236};
237
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700238} // ndnSIM
Alexander Afanasyeve77db792012-08-09 11:10:58 -0700239} // ns3
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700240
241#endif // TRIE_WITH_POLICY_H_