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

Last change on this file since 5902 was 5902, checked in by mies, 15 years ago
File size: 8.6 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 int 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 /// check whether a node could fit the routing table
187 bool is_insertable( const nodeid_t& value ) {
188// if (find_item(value)!=NULL) return false;
189 bool is_insertable_ = false;
190 is_insertable_ |= succ.insertable(value);
191 is_insertable_ |= pred.insertable(value);
192 for (size_t i=0; i<max_fingers*2; i++)
193 is_insertable_ |= finger[i]->insertable(value);
194 return is_insertable_;
195 }
196
197 /// searches an item
198 item* get( const nodeid_t& value ) {
199 return find_item(value);
200 }
201
202 inline item* operator[] ( size_t index ) {
203 return &table[index];
204 }
205
206 inline size_t size() const {
207 return table.size();
208 }
209
210 /// adds a node
211 item* insert( const nodeid_t& value ) {
212 if (value==id) return NULL;
213 item_added = NULL;
214 item_removed_flag = false;
215 succ.insert(value);
216 pred.insert(value);
217 for (size_t i=0; i<max_fingers*2; i++) finger[i]->insert(value);
218 return item_added;
219 }
220
221 /// adds an orphan
222 item* insert_orphan( const nodeid_t& value ) {
223 item* it = find_item(value);
224 if (it!=NULL) return it;
225 item i;
226 i.id = id;
227 i.ref_count = 0;
228 table.push_back(i);
229 return &table.back();
230 }
231
232 /// removes an node
233 const item* remove( const nodeid_t& value ) {
234 item_removed_flag = false;
235 succ.remove(value);
236 pred.remove(value);
237 for (size_t i=0; i<max_fingers*2; i++) finger[i]->remove(value);
238 if (!item_removed_flag) remove_orphan(value);
239 return item_removed_flag ? &item_removed : NULL;
240 }
241
242 /// removes an orphan
243 item* remove_orphan( const nodeid_t& value ) {
244 item_removed_flag = false;
245 remove_item(value);
246 return item_removed_flag ? &item_removed : NULL;
247 }
248
249 /// returns the next hop
250 const item* get_next_hop( const nodeid_t& value, bool nts = false) {
251 ring_distance distance;
252 item* best_item = NULL;
253 for (size_t i=0; i<table.size(); i++) {
254 item* curr = &table[i];
255 if (nts && curr->id == value) continue;
256
257 // not not include orphans into routing!
258 if (curr->ref_count==0) continue;
259
260 // check if we found a better item
261 if (best_item==NULL) {
262 best_item = curr;
263 continue;
264 } else {
265 if (distance(value, curr->id)<distance(value, best_item->id))
266 best_item = curr;
267 }
268 }
269 if (best_item != NULL && distance(value, id)<distance(value, best_item->id))
270 return NULL;
271 return best_item;
272 }
273
274 const nodeid_t* get_successor() {
275 if (succ.size()==NULL) return NULL;
276 return &succ.front();
277 }
278
279 const nodeid_t* get_predesessor() {
280 if (pred.size()==NULL) return NULL;
281 return &pred.front();
282 }
283
284 bool is_closest_to( const nodeid_t& value ) {
285 ring_distance distance;
286 nodeid_t delta = distance(value, id);
287 if (get_successor() != NULL &&
288 delta > distance(value, *get_successor() ) ) return false;
289 if (get_predesessor() != NULL &&
290 delta > distance(value, *get_predesessor() ) ) return false;
291 return true;
292 }
293
294 /// returns the whole routing table
295 vector<item>& get_table() {
296 return table;
297 }
298
299 /// returns the last removed item
300 const item* get_removed_item() const {
301 return item_removed_flag ? &item_removed : NULL;
302 }
303
304 /// return successor table
305 const succ_table& get_succ_table() const {
306 return succ;
307 }
308
309 /// return predecessor table
310 const pred_table& get_pred_table() const {
311 return pred;
312 }
313
314 /// return finger table
315 finger_table& get_finger_table( size_t index ) {
316 return *finger[index];
317 }
318
319 /// return number of finger tables
320 size_t get_finger_table_size() const {
321 return max_fingers*2;
322 }
323};
324
325/// output routing table
326std::ostream& operator<<(std::ostream& s, const chord_routing_table& t) {
327 s << "[pred=" << t.get_pred_table() << " succ=" << t.get_succ_table()
328 << "]";
329 return s;
330}
331
332#endif /* CHORD_ROUTING_TABLE_HPP_ */
Note: See TracBrowser for help on using the repository browser.