An Overlay-based
Virtual Network Substrate
SpoVNet

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

Last change on this file since 6919 was 6919, checked in by mies, 14 years ago

Fixed tons of warnings when using CXXFLAGS="-Wall"!

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 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        /// 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.