blob: d0d54f6f9581f367408d2b74a0218612a05ea41a [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
Spyridon Mastorakis460f57c2014-12-17 00:44:14 -080023/// @cond include_hidden
24
Alexander Afanasyev0c395372014-12-20 15:54:02 -080025#include "trie.hpp"
Alexander Afanasyev9a989702012-06-29 17:44:00 -070026
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -070027namespace ns3 {
28namespace ndn {
29namespace ndnSIM {
Alexander Afanasyev30cb1172012-07-06 10:47:39 -070030
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080031template<typename FullKey, typename PayloadTraits, typename PolicyTraits>
32class trie_with_policy {
Alexander Afanasyev9a989702012-06-29 17:44:00 -070033public:
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080034 typedef trie<FullKey, PayloadTraits, typename PolicyTraits::policy_hook_type> parent_trie;
Alexander Afanasyev9e96e362012-07-02 23:04:39 -070035
36 typedef typename parent_trie::iterator iterator;
Alexander Afanasyev1ba09b82012-07-09 09:16:14 -070037 typedef typename parent_trie::const_iterator const_iterator;
Alexander Afanasyev9e96e362012-07-02 23:04:39 -070038
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080039 typedef typename PolicyTraits::
40 template policy<trie_with_policy<FullKey, PayloadTraits, PolicyTraits>, parent_trie,
41 typename PolicyTraits::template container_hook<parent_trie>::type>::type
42 policy_container;
Alexander Afanasyev9a989702012-06-29 17:44:00 -070043
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080044 inline trie_with_policy(size_t bucketSize = 1, size_t bucketIncrement = 1)
45 : trie_(name::Component(), bucketSize, bucketIncrement)
46 , policy_(*this)
Alexander Afanasyev9a989702012-06-29 17:44:00 -070047 {
48 }
49
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080050 inline std::pair<iterator, bool>
51 insert(const FullKey& key, typename PayloadTraits::insert_type payload)
Alexander Afanasyev9a989702012-06-29 17:44:00 -070052 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080053 std::pair<iterator, bool> item = trie_.insert(key, payload);
Alexander Afanasyev9a989702012-06-29 17:44:00 -070054
55 if (item.second) // real insert
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080056 {
57 bool ok = policy_.insert(s_iterator_to(item.first));
58 if (!ok) {
59 item.first->erase(); // cannot insert
60 return std::make_pair(end(), false);
Alexander Afanasyev9a989702012-06-29 17:44:00 -070061 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080062 }
63 else {
64 return std::make_pair(s_iterator_to(item.first), false);
65 }
Alexander Afanasyev9a989702012-06-29 17:44:00 -070066
67 return item;
68 }
69
70 inline void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080071 erase(const FullKey& key)
Alexander Afanasyev78057c32012-07-06 15:18:46 -070072 {
73 iterator foundItem, lastItem;
74 bool reachLast;
Alexander Afanasyev07179012014-12-21 00:23:04 -080075 std::tie(foundItem, reachLast, lastItem) = trie_.find(key);
Alexander Afanasyeveec66292013-02-06 16:23:21 -080076
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080077 if (!reachLast || lastItem->payload() == PayloadTraits::empty_payload)
Alexander Afanasyev78057c32012-07-06 15:18:46 -070078 return; // nothing to invalidate
79
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080080 erase(lastItem);
Alexander Afanasyev78057c32012-07-06 15:18:46 -070081 }
82
83 inline void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080084 erase(iterator node)
Alexander Afanasyev9a989702012-06-29 17:44:00 -070085 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080086 if (node == end())
87 return;
Alexander Afanasyev9a989702012-06-29 17:44:00 -070088
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080089 policy_.erase(s_iterator_to(node));
90 node->erase(); // will do cleanup here
Alexander Afanasyev9a989702012-06-29 17:44:00 -070091 }
92
Alexander Afanasyev78057c32012-07-06 15:18:46 -070093 inline void
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080094 clear()
Alexander Afanasyev78057c32012-07-06 15:18:46 -070095 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -080096 policy_.clear();
97 trie_.clear();
Alexander Afanasyev78057c32012-07-06 15:18:46 -070098 }
99
100 template<typename Modifier>
101 bool
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800102 modify(iterator position, Modifier mod)
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700103 {
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800104 if (position == end())
105 return false;
106 if (position->payload() == PayloadTraits::empty_payload)
107 return false;
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700108
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800109 mod(*position->payload());
110 policy_.update(position);
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700111 return true;
112 }
Alexander Afanasyevadcccf42012-11-26 23:55:34 -0800113
114 /**
115 * @brief Find a node that has the exact match with the key
116 */
117 inline iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800118 find_exact(const FullKey& key)
Alexander Afanasyevadcccf42012-11-26 23:55:34 -0800119 {
120 iterator foundItem, lastItem;
121 bool reachLast;
Alexander Afanasyev07179012014-12-21 00:23:04 -0800122 std::tie(foundItem, reachLast, lastItem) = trie_.find(key);
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800123
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800124 if (!reachLast || lastItem->payload() == PayloadTraits::empty_payload)
125 return end();
Alexander Afanasyevadcccf42012-11-26 23:55:34 -0800126
127 return lastItem;
128 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800129
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700130 /**
131 * @brief Find a node that has the longest common prefix with key (FIB/PIT lookup)
132 */
133 inline iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800134 longest_prefix_match(const FullKey& key)
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700135 {
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700136 iterator foundItem, lastItem;
137 bool reachLast;
Alexander Afanasyev07179012014-12-21 00:23:04 -0800138 std::tie(foundItem, reachLast, lastItem) = trie_.find(key);
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800139 if (foundItem != trie_.end()) {
140 policy_.lookup(s_iterator_to(foundItem));
141 }
Alexander Afanasyev78057c32012-07-06 15:18:46 -0700142 return foundItem;
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700143 }
144
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800145 /**
146 * @brief Find a node that has the longest common prefix with key (FIB/PIT lookup)
147 */
148 template<class Predicate>
149 inline iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800150 longest_prefix_match_if(const FullKey& key, Predicate pred)
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800151 {
152 iterator foundItem, lastItem;
153 bool reachLast;
Alexander Afanasyev07179012014-12-21 00:23:04 -0800154 std::tie(foundItem, reachLast, lastItem) = trie_.find_if(key, pred);
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800155 if (foundItem != trie_.end()) {
156 policy_.lookup(s_iterator_to(foundItem));
157 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800158 return foundItem;
159 }
160
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700161 // /**
162 // * @brief Const version of the longest common prefix match
163 // * (semi-const, because there could be update of the policy anyways)
164 // */
165 // inline const_iterator
166 // longest_prefix_match (const FullKey &key) const
167 // {
168 // return static_cast<trie_with_policy*> (this)->longest_prefix_match (key);
169 // }
170
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700171 /**
172 * @brief Find a node that has prefix at least as the key (cache lookup)
173 */
174 inline iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800175 deepest_prefix_match(const FullKey& key)
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700176 {
177 iterator foundItem, lastItem;
178 bool reachLast;
Alexander Afanasyev07179012014-12-21 00:23:04 -0800179 std::tie(foundItem, reachLast, lastItem) = trie_.find(key);
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700180
181 // guard in case we don't have anything in the trie
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800182 if (lastItem == trie_.end())
183 return trie_.end();
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800184
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800185 if (reachLast) {
186 if (foundItem == trie_.end()) {
187 foundItem = lastItem->find(); // should be something
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700188 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800189 policy_.lookup(s_iterator_to(foundItem));
190 return foundItem;
191 }
192 else { // couldn't find a node that has prefix at least as key
193 return trie_.end();
194 }
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700195 }
196
197 /**
198 * @brief Find a node that has prefix at least as the key
199 */
200 template<class Predicate>
201 inline iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800202 deepest_prefix_match_if(const FullKey& key, Predicate pred)
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700203 {
204 iterator foundItem, lastItem;
205 bool reachLast;
Alexander Afanasyev07179012014-12-21 00:23:04 -0800206 std::tie(foundItem, reachLast, lastItem) = trie_.find(key);
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700207
208 // guard in case we don't have anything in the trie
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800209 if (lastItem == trie_.end())
210 return trie_.end();
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800211
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800212 if (reachLast) {
213 foundItem = lastItem->find_if(pred); // may or may not find something
214 if (foundItem == trie_.end()) {
215 return trie_.end();
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700216 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800217 policy_.lookup(s_iterator_to(foundItem));
218 return foundItem;
219 }
220 else { // couldn't find a node that has prefix at least as key
221 return trie_.end();
222 }
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700223 }
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700224
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700225 /**
226 * @brief Find a node that has prefix at least as the key
227 *
228 * This version of find checks predicate for the next level and if
229 * predicate is True, returns first deepest match available
230 */
231 template<class Predicate>
232 inline iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800233 deepest_prefix_match_if_next_level(const FullKey& key, Predicate pred)
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700234 {
235 iterator foundItem, lastItem;
236 bool reachLast;
Alexander Afanasyev07179012014-12-21 00:23:04 -0800237 std::tie(foundItem, reachLast, lastItem) = trie_.find(key);
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700238
239 // guard in case we don't have anything in the trie
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800240 if (lastItem == trie_.end())
241 return trie_.end();
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700242
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800243 if (reachLast) {
244 foundItem = lastItem->find_if_next_level(pred); // may or may not find something
245 if (foundItem == trie_.end()) {
246 return trie_.end();
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700247 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800248 policy_.lookup(s_iterator_to(foundItem));
249 return foundItem;
250 }
251 else { // couldn't find a node that has prefix at least as key
252 return trie_.end();
253 }
Alexander Afanasyeveec89ba2013-07-19 16:34:30 -0700254 }
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800255
256 iterator
257 end() const
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700258 {
259 return 0;
260 }
261
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800262 const parent_trie&
263 getTrie() const
264 {
265 return trie_;
266 }
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700267
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800268 parent_trie&
269 getTrie()
270 {
271 return trie_;
272 }
Alexander Afanasyev44bb6ea2012-07-09 08:44:41 -0700273
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800274 const policy_container&
275 getPolicy() const
276 {
277 return policy_;
278 }
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700279
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800280 policy_container&
281 getPolicy()
282 {
283 return policy_;
284 }
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700285
286 static inline iterator
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800287 s_iterator_to(typename parent_trie::iterator item)
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700288 {
289 if (item == 0)
290 return 0;
291 else
292 return &(*item);
293 }
Alexander Afanasyeveec66292013-02-06 16:23:21 -0800294
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700295private:
Alexander Afanasyevbe55cf62014-12-20 17:51:09 -0800296 parent_trie trie_;
Alexander Afanasyev30f60e32012-07-10 14:21:16 -0700297 mutable policy_container policy_;
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700298};
299
Alexander Afanasyev30cb1172012-07-06 10:47:39 -0700300} // ndnSIM
Alexander Afanasyev2b4c9472012-08-09 15:00:38 -0700301} // ndn
Alexander Afanasyeve77db792012-08-09 11:10:58 -0700302} // ns3
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700303
Spyridon Mastorakis460f57c2014-12-17 00:44:14 -0800304/// @endcond
305
Alexander Afanasyev9a989702012-06-29 17:44:00 -0700306#endif // TRIE_WITH_POLICY_H_