source: source/ariba/overlay/modules/chord/detail/chord_routing_table.hpp@ 9770

Last change on this file since 9770 was 8606, checked in by Christoph Mayer, 14 years ago

-memleaks

File size: 8.7 KB
Line 
1// [License]
2// The Ariba-Underlay Copyright
3//
4// Copyright (c) 2008-2009, Institute of Telematics, UniversitÀt Karlsruhe (TH)
5//
6// Institute of Telematics
7// UniversitÀt Karlsruhe (TH)
8// Zirkel 2, 76128 Karlsruhe
9// Germany
10//
11// Redistribution and use in source and binary forms, with or without
12// modification, are permitted provided that the following conditions are
13// met:
14//
15// 1. Redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer.
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
22// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OF TELEMATICS OR
25// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32//
33// The views and conclusions contained in the software and documentation
34// are those of the authors and should not be interpreted as representing
35// official policies, either expressed or implied, of the Institute of
36// Telematics.
37// [License]
38#ifndef CHORD_ROUTING_TABLE_HPP_
39#define CHORD_ROUTING_TABLE_HPP_
40
41#include <vector>
42#include <iostream>
43
44#include <boost/foreach.hpp>
45
46#include "distances.hpp"
47#include "comparators.hpp"
48#include "minimizer_table.hpp"
49
50#include "ariba/Identifiers.h"
51
52using namespace ariba;
53
54using namespace distances;
55using namespace comparators;
56using namespace std;
57
58// placeholders for route info and nodeid type
59typedef ariba::NodeID nodeid_t;
60typedef ariba::LinkID routeinfo_t;
61
62/**
63 * Implementation of a chord routing table.
64*
65 * @author Sebastian Mies <mies@tm.uka.de>
66 */
67class chord_routing_table {
68private:
69 typedef chord_routing_table self;
70 typedef distance_compare<nodeid_t&, nodeid_t, ring_succ_distance>
71 succ_compare_type;
72 typedef distance_compare<nodeid_t&, nodeid_t, ring_pred_distance>
73 pred_compare_type;
74 typedef distance_compare<nodeid_t, nodeid_t, ring_distance>
75 finger_compare_type;
76
77public:
78 typedef minimizer_table<nodeid_t, succ_compare_type, self> succ_table;
79 typedef minimizer_table<nodeid_t, pred_compare_type, self> pred_table;
80 typedef minimizer_table<nodeid_t, finger_compare_type, self> finger_table;
81
82 // a routing table entry
83 class item {
84 public:
85 uint8_t ref_count;
86 nodeid_t id;
87 routeinfo_t info;
88 };
89 typedef vector<item> route_table;
90
91
92private:
93 // maximum number of fingers
94 static const size_t max_fingers = 32;
95
96 // the own node id
97 nodeid_t id;
98
99 // successor and predecessor tables
100 succ_table succ;
101 pred_table pred;
102 finger_table* finger[max_fingers*2];
103
104 // main routing table
105 route_table table;
106
107 // some internal flags
108 item* item_added;
109 item item_removed;
110 bool item_removed_flag;
111 bool simulate;
112
113 // finds an item inside the routing table
114 item* find_item(const nodeid_t& id) {
115 BOOST_FOREACH( item& i, table )
116 if ( i.id == id ) return &i;
117 return NULL;
118 }
119
120 /// Adds a item to the routing table
121 item* add_item( const nodeid_t& id ) {
122 item i;
123 i.id = id;
124 i.ref_count = 1;
125 table.push_back(i);
126 item_added = &table.back();
127 return item_added;
128 }
129
130 /// Removes an item from the routing table
131 bool remove_item( const nodeid_t& id ) {
132 for (route_table::iterator i = table.begin(); i!=table.end(); i++) {
133 if ( (*i).id == id ) {
134 (*i).ref_count--;
135 if ((*i).ref_count == 0) {
136 item_removed = *i;
137 item_removed_flag = true;
138 return true;
139 }
140 break;
141 }
142 }
143 return false;
144 }
145
146public:
147
148 // handles events from minimizers
149 template<class Table>
150 void on_table( table_listener::type_ type, const Table& tab, typename Table::iterator pos ) {
151 switch (type) {
152 case table_listener::insert: {
153 item* i = find_item( *pos );
154 if (i == NULL) i = add_item( *pos ); else i->ref_count++;
155 break;
156 }
157 case table_listener::remove: {
158 remove_item(*pos);
159 break;
160 }
161 case table_listener::update:
162 break;
163 }
164 }
165
166
167public:
168 /// constructs the reactive chord routing table
169 explicit chord_routing_table( const nodeid_t& id, int redundancy = 4 ) :
170 id(id), succ( redundancy, succ_compare_type(this->id), *this ),
171 pred( redundancy, pred_compare_type(this->id), *this ) {
172
173 // create finger tables
174 nodeid_t nid = Identifier(2);
175 for (size_t i=0; i<max_fingers; i++) {
176 finger[i*2+0] =
177 new finger_table( redundancy,
178 finger_compare_type(this->id - nid), *this);
179 finger[i*2+1] =
180 new finger_table( redundancy,
181 finger_compare_type(this->id + nid), *this);
182 nid = nid << 1;
183 }
184 }
185
186 virtual ~chord_routing_table() {
187 BOOST_FOREACH( finger_table* f, this->finger){
188 delete f;
189 }
190 }
191
192 /// check whether a node could fit the routing table
193 bool is_insertable( const nodeid_t& value ) {
194// if (find_item(value)!=NULL) return false;
195 bool is_insertable_ = false;
196 is_insertable_ |= succ.insertable(value);
197 is_insertable_ |= pred.insertable(value);
198 for (size_t i=0; i<max_fingers*2; i++)
199 is_insertable_ |= finger[i]->insertable(value);
200 return is_insertable_;
201 }
202
203 /// searches an item
204 item* get( const nodeid_t& value ) {
205 return find_item(value);
206 }
207
208 inline item* operator[] ( size_t index ) {
209 return &table[index];
210 }
211
212 inline size_t size() const {
213 return table.size();
214 }
215
216 /// adds a node
217 item* insert( const nodeid_t& value ) {
218 if (value==id) return NULL;
219 item_added = NULL;
220 item_removed_flag = false;
221 succ.insert(value);
222 pred.insert(value);
223 for (size_t i=0; i<max_fingers*2; i++) finger[i]->insert(value);
224 return item_added;
225 }
226
227 /// adds an orphan
228 item* insert_orphan( const nodeid_t& value ) {
229 item* it = find_item(value);
230 if (it!=NULL) return it;
231 item i;
232 i.id = id;
233 i.ref_count = 0;
234 table.push_back(i);
235 return &table.back();
236 }
237
238 /// removes an node
239 const item* remove( const nodeid_t& value ) {
240 item_removed_flag = false;
241 succ.remove(value);
242 pred.remove(value);
243 for (size_t i=0; i<max_fingers*2; i++) finger[i]->remove(value);
244 if (!item_removed_flag) remove_orphan(value);
245 return item_removed_flag ? &item_removed : NULL;
246 }
247
248 /// removes an orphan
249 item* remove_orphan( const nodeid_t& value ) {
250 item_removed_flag = false;
251 remove_item(value);
252 return item_removed_flag ? &item_removed : NULL;
253 }
254
255 /// returns the next hop
256 const item* get_next_hop( const nodeid_t& value, bool nts = false) {
257 ring_distance distance;
258 item* best_item = NULL;
259 for (size_t i=0; i<table.size(); i++) {
260 item* curr = &table[i];
261 if (nts && curr->id == value) continue;
262
263 // not not include orphans into routing!
264 if (curr->ref_count==0) continue;
265
266 // check if we found a better item
267 if (best_item==NULL) {
268 best_item = curr;
269 continue;
270 } else {
271 if (distance(value, curr->id)<distance(value, best_item->id))
272 best_item = curr;
273 }
274 }
275 if (best_item != NULL && distance(value, id)<distance(value, best_item->id))
276 return NULL;
277 return best_item;
278 }
279
280 const nodeid_t* get_successor() {
281 if (succ.size()==NULL) return NULL;
282 return &succ.front();
283 }
284
285 const nodeid_t* get_predesessor() {
286 if (pred.size()==NULL) return NULL;
287 return &pred.front();
288 }
289
290 bool is_closest_to( const nodeid_t& value ) {
291 ring_distance distance;
292 nodeid_t delta = distance(value, id);
293 if (get_successor() != NULL &&
294 delta > distance(value, *get_successor() ) ) return false;
295 if (get_predesessor() != NULL &&
296 delta > distance(value, *get_predesessor() ) ) return false;
297 return true;
298 }
299
300 /// returns the whole routing table
301 vector<item>& get_table() {
302 return table;
303 }
304
305 /// returns the last removed item
306 const item* get_removed_item() const {
307 return item_removed_flag ? &item_removed : NULL;
308 }
309
310 /// return successor table
311 const succ_table& get_succ_table() const {
312 return succ;
313 }
314
315 /// return predecessor table
316 const pred_table& get_pred_table() const {
317 return pred;
318 }
319
320 /// return finger table
321 finger_table& get_finger_table( size_t index ) {
322 return *finger[index];
323 }
324
325 /// return number of finger tables
326 size_t get_finger_table_size() const {
327 return max_fingers*2;
328 }
329};
330
331/// output routing table
332std::ostream& operator<<(std::ostream& s, const chord_routing_table& t) {
333 s << "[pred=" << t.get_pred_table() << " succ=" << t.get_succ_table()
334 << "]";
335 return s;
336}
337
338#endif /* CHORD_ROUTING_TABLE_HPP_ */
Note: See TracBrowser for help on using the repository browser.