blob: 2ef3bc43491b93019658e068d3b4c64e21900352 [file] [log] [blame]
Alexander Afanasyev60a7b622014-12-20 17:04:07 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2011-2015 Regents of the University of California.
Alexander Afanasyev9a989702012-06-29 17:44:00 -07004 *
Alexander Afanasyev60a7b622014-12-20 17:04:07 -08005 * This file is part of ndnSIM. See AUTHORS for complete list of ndnSIM authors and
6 * contributors.
Alexander Afanasyev9a989702012-06-29 17:44:00 -07007 *
Alexander Afanasyev60a7b622014-12-20 17:04:07 -08008 * ndnSIM is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
Alexander Afanasyev9a989702012-06-29 17:44:00 -070011 *
Alexander Afanasyev60a7b622014-12-20 17:04:07 -080012 * ndnSIM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
Alexander Afanasyev9a989702012-06-29 17:44:00 -070015 *
Alexander Afanasyev60a7b622014-12-20 17:04:07 -080016 * You should have received a copy of the GNU General Public License along with
17 * ndnSIM, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 **/
Alexander Afanasyev9a989702012-06-29 17:44:00 -070019
20#ifndef TRIE_WITH_POLICY_H_
21#define TRIE_WITH_POLICY_H_
22
Alexander Afanasyev0c395372014-12-20 15:54:02 -080023#include "trie.hpp"
Alexander Afanasyev9a989702012-06-29 17:44:00 -070024
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070025namespace ns3 {
26namespace ndn {
27namespace ndnSIM {
Alexander Afanasyev30cb1172012-07-06 10:47:39 -070028
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080029template<typename FullKey, typename PayloadTraits, typename PolicyTraits>
30class trie_with_policy {
Alexander Afanasyev9a989702012-06-29 17:44:00 -070031public:
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080032 typedef trie<FullKey, PayloadTraits, typename PolicyTraits::policy_hook_type> parent_trie;
Alexander Afanasyev9e96e362012-07-02 23:04:39 -070033
34 typedef typename parent_trie::iterator iterator;
Alexander Afanasyev1ba09b82012-07-09 09:16:14 -070035 typedef typename parent_trie::const_iterator const_iterator;
Alexander Afanasyev9e96e362012-07-02 23:04:39 -070036
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080037 typedef typename PolicyTraits::
38 template policy<trie_with_policy<FullKey, PayloadTraits, PolicyTraits>, parent_trie,
39 typename PolicyTraits::template container_hook<parent_trie>::type>::type
40 policy_container;
Alexander Afanasyev9a989702012-06-29 17:44:00 -070041
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080042 inline trie_with_policy(size_t bucketSize = 1, size_t bucketIncrement = 1)
43 : trie_(name::Component(), bucketSize, bucketIncrement)
44 , policy_(*this)
Alexander Afanasyev9a989702012-06-29 17:44:00 -070045 {
46 }
47
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080048 inline std::pair<iterator, bool>
49 insert(const FullKey& key, typename PayloadTraits::insert_type payload)
Alexander Afanasyev9a989702012-06-29 17:44:00 -070050 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080051 std::pair<iterator, bool> item = trie_.insert(key, payload);
Alexander Afanasyev9a989702012-06-29 17:44:00 -070052
53 if (item.second) // real insert
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080054 {
55 bool ok = policy_.insert(s_iterator_to(item.first));
56 if (!ok) {
57 item.first->erase(); // cannot insert
58 return std::make_pair(end(), false);
Alexander Afanasyev9a989702012-06-29 17:44:00 -070059 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080060 }
61 else {
62 return std::make_pair(s_iterator_to(item.first), false);
63 }
Alexander Afanasyev9a989702012-06-29 17:44:00 -070064
65 return item;
66 }
67
68 inline void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080069 erase(const FullKey& key)
Alexander Afanasyev78057c32012-07-06 15:18:46 -070070 {
71 iterator foundItem, lastItem;
72 bool reachLast;
Alexander Afanasyev07179012014-12-21 00:23:04 -080073 std::tie(foundItem, reachLast, lastItem) = trie_.find(key);
Alexander Afanasyeveec66292013-02-06 16:23:21 -080074
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080075 if (!reachLast || lastItem->payload() == PayloadTraits::empty_payload)
Alexander Afanasyev78057c32012-07-06 15:18:46 -070076 return; // nothing to invalidate
77
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080078 erase(lastItem);
Alexander Afanasyev78057c32012-07-06 15:18:46 -070079 }
80
81 inline void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080082 erase(iterator node)
Alexander Afanasyev9a989702012-06-29 17:44:00 -070083 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080084 if (node == end())
85 return;
Alexander Afanasyev9a989702012-06-29 17:44:00 -070086
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080087 policy_.erase(s_iterator_to(node));
88 node->erase(); // will do cleanup here
Alexander Afanasyev9a989702012-06-29 17:44:00 -070089 }
90
Alexander Afanasyev78057c32012-07-06 15:18:46 -070091 inline void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080092 clear()
Alexander Afanasyev78057c32012-07-06 15:18:46 -070093 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080094 policy_.clear();
95 trie_.clear();
Alexander Afanasyev78057c32012-07-06 15:18:46 -070096 }
97
98 template<typename Modifier>
99 bool
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800100 modify(iterator position, Modifier mod)
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700101 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800102 if (position == end())
103 return false;
104 if (position->payload() == PayloadTraits::empty_payload)
105 return false;
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700106
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800107 mod(*position->payload());
108 policy_.update(position);
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700109 return true;
110 }
Alexander Afanasyevadcccf42012-11-26 23:55:34 -0800111
112 /**
113 * @brief Find a node that has the exact match with the key
114 */
115 inline iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800116 find_exact(const FullKey& key)
Alexander Afanasyevadcccf42012-11-26 23:55:34 -0800117 {
118 iterator foundItem, lastItem;
119 bool reachLast;
Alexander Afanasyev07179012014-12-21 00:23:04 -0800120 std::tie(foundItem, reachLast, lastItem) = trie_.find(key);
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800121
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800122 if (!reachLast || lastItem->payload() == PayloadTraits::empty_payload)
123 return end();
Alexander Afanasyevadcccf42012-11-26 23:55:34 -0800124
125 return lastItem;
126 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800127
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700128 /**
129 * @brief Find a node that has the longest common prefix with key (FIB/PIT lookup)
130 */
131 inline iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800132 longest_prefix_match(const FullKey& key)
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700133 {
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700134 iterator foundItem, lastItem;
135 bool reachLast;
Alexander Afanasyev07179012014-12-21 00:23:04 -0800136 std::tie(foundItem, reachLast, lastItem) = trie_.find(key);
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800137 if (foundItem != trie_.end()) {
138 policy_.lookup(s_iterator_to(foundItem));
139 }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700140 return foundItem;
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700141 }
142
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800143 /**
144 * @brief Find a node that has the longest common prefix with key (FIB/PIT lookup)
145 */
146 template<class Predicate>
147 inline iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800148 longest_prefix_match_if(const FullKey& key, Predicate pred)
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800149 {
150 iterator foundItem, lastItem;
151 bool reachLast;
Alexander Afanasyev07179012014-12-21 00:23:04 -0800152 std::tie(foundItem, reachLast, lastItem) = trie_.find_if(key, pred);
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800153 if (foundItem != trie_.end()) {
154 policy_.lookup(s_iterator_to(foundItem));
155 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800156 return foundItem;
157 }
158
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700159 // /**
160 // * @brief Const version of the longest common prefix match
161 // * (semi-const, because there could be update of the policy anyways)
162 // */
163 // inline const_iterator
164 // longest_prefix_match (const FullKey &key) const
165 // {
166 // return static_cast<trie_with_policy*> (this)->longest_prefix_match (key);
167 // }
168
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700169 /**
170 * @brief Find a node that has prefix at least as the key (cache lookup)
171 */
172 inline iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800173 deepest_prefix_match(const FullKey& key)
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700174 {
175 iterator foundItem, lastItem;
176 bool reachLast;
Alexander Afanasyev07179012014-12-21 00:23:04 -0800177 std::tie(foundItem, reachLast, lastItem) = trie_.find(key);
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700178
179 // guard in case we don't have anything in the trie
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800180 if (lastItem == trie_.end())
181 return trie_.end();
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800182
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800183 if (reachLast) {
184 if (foundItem == trie_.end()) {
185 foundItem = lastItem->find(); // should be something
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700186 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800187 policy_.lookup(s_iterator_to(foundItem));
188 return foundItem;
189 }
190 else { // couldn't find a node that has prefix at least as key
191 return trie_.end();
192 }
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700193 }
194
195 /**
196 * @brief Find a node that has prefix at least as the key
197 */
198 template<class Predicate>
199 inline iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800200 deepest_prefix_match_if(const FullKey& key, Predicate pred)
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700201 {
202 iterator foundItem, lastItem;
203 bool reachLast;
Alexander Afanasyev07179012014-12-21 00:23:04 -0800204 std::tie(foundItem, reachLast, lastItem) = trie_.find(key);
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700205
206 // guard in case we don't have anything in the trie
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800207 if (lastItem == trie_.end())
208 return trie_.end();
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800209
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800210 if (reachLast) {
211 foundItem = lastItem->find_if(pred); // may or may not find something
212 if (foundItem == trie_.end()) {
213 return trie_.end();
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700214 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800215 policy_.lookup(s_iterator_to(foundItem));
216 return foundItem;
217 }
218 else { // couldn't find a node that has prefix at least as key
219 return trie_.end();
220 }
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700221 }
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700222
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700223 /**
224 * @brief Find a node that has prefix at least as the key
225 *
226 * This version of find checks predicate for the next level and if
227 * predicate is True, returns first deepest match available
228 */
229 template<class Predicate>
230 inline iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800231 deepest_prefix_match_if_next_level(const FullKey& key, Predicate pred)
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700232 {
233 iterator foundItem, lastItem;
234 bool reachLast;
Alexander Afanasyev07179012014-12-21 00:23:04 -0800235 std::tie(foundItem, reachLast, lastItem) = trie_.find(key);
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700236
237 // guard in case we don't have anything in the trie
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800238 if (lastItem == trie_.end())
239 return trie_.end();
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700240
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800241 if (reachLast) {
242 foundItem = lastItem->find_if_next_level(pred); // may or may not find something
243 if (foundItem == trie_.end()) {
244 return trie_.end();
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700245 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800246 policy_.lookup(s_iterator_to(foundItem));
247 return foundItem;
248 }
249 else { // couldn't find a node that has prefix at least as key
250 return trie_.end();
251 }
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700252 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800253
254 iterator
255 end() const
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700256 {
257 return 0;
258 }
259
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800260 const parent_trie&
261 getTrie() const
262 {
263 return trie_;
264 }
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700265
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800266 parent_trie&
267 getTrie()
268 {
269 return trie_;
270 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700271
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800272 const policy_container&
273 getPolicy() const
274 {
275 return policy_;
276 }
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700277
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800278 policy_container&
279 getPolicy()
280 {
281 return policy_;
282 }
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700283
284 static inline iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800285 s_iterator_to(typename parent_trie::iterator item)
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700286 {
287 if (item == 0)
288 return 0;
289 else
290 return &(*item);
291 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800292
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700293private:
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800294 parent_trie trie_;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700295 mutable policy_container policy_;
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700296};
297
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700298} // ndnSIM
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700299} // ndn
Alexander Afanasyeve77db792012-08-09 11:10:58 -0700300} // ns3
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700301
302#endif // TRIE_WITH_POLICY_H_