Wiselib
|
00001 /*************************************************************************** 00002 ** This file is part of the generic algorithm library Wiselib. ** 00003 ** Copyright (C) 2008,2009 by the Wisebed (www.wisebed.eu) project. ** 00004 ** ** 00005 ** The Wiselib is free software: you can redistribute it and/or modify ** 00006 ** it under the terms of the GNU Lesser General Public License as ** 00007 ** published by the Free Software Foundation, either version 3 of the ** 00008 ** License, or (at your option) any later version. ** 00009 ** ** 00010 ** The Wiselib is distributed in the hope that it will be useful, ** 00011 ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** 00012 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** 00013 ** GNU Lesser General Public License for more details. ** 00014 ** ** 00015 ** You should have received a copy of the GNU Lesser General Public ** 00016 ** License along with the Wiselib. ** 00017 ** If not, see <http://www.gnu.org/licenses/>. ** 00018 ***************************************************************************/ 00019 #ifndef __LAZY_H__ 00020 #define __LAZY_H__ 00021 #include "util/base_classes/routing_base.h" 00022 #include "lazy_message.h" 00023 00024 namespace wiselib 00025 { 00036 template< typename Os_P, 00037 typename Radio_P, 00038 typename Timer_P, 00039 typename Rand_P, 00040 typename Node_P, 00041 typename NodeList_P, 00042 typename Connectivity_P, 00043 typename ConnectivityList_P, 00044 typename Debug_P> 00045 class LazyType 00046 : public RoutingBase<Os_P, Radio_P> 00047 { 00048 public: 00049 typedef Os_P Os; 00050 typedef Radio_P Radio; 00051 typedef Timer_P Timer; 00052 typedef Rand_P Rand; 00053 typedef Debug_P Debug; 00054 typedef Node_P Node; 00055 typedef NodeList_P NodeList; 00056 typedef Connectivity_P Connectivity; 00057 typedef ConnectivityList_P ConnectivityList; 00058 typedef LazyType<Os, Radio, Timer, Rand, Node, NodeList, Connectivity, ConnectivityList, Debug> self_type; 00059 typedef typename NodeList::iterator NodeListIterator; 00060 typedef typename ConnectivityList::iterator ConnectivityListIterator; 00061 typedef typename Node::Position Position; 00062 typedef typename Node::Position::CoordinatesNumber CoordinatesNumber; 00063 typedef typename Radio::node_id_t node_id_t; 00064 typedef typename Radio::size_t size_t; 00065 typedef typename Radio::block_data_t block_data_t; 00066 typedef typename Radio::message_id_t message_id_t; 00067 typedef typename Timer::millis_t millis_t; 00068 typedef LazyMessageType<Os, Radio> Message; 00069 00070 // -------------------------------------------------------------------- 00071 enum ErrorCodes 00072 { 00073 SUCCESS = Os::SUCCESS, 00074 ERR_UNSPEC = Os::ERR_UNSPEC, 00075 ERR_NETDOWN = Os::ERR_NETDOWN 00076 }; 00077 // -------------------------------------------------------------------- 00078 enum SpecialNodeIds 00079 { 00080 BROADCAST_ADDRESS = Radio_P::BROADCAST_ADDRESS, 00081 NULL_NODE_ID = Radio_P::NULL_NODE_ID 00082 }; 00083 // -------------------------------------------------------------------- 00084 enum Restrictions 00085 { 00086 MAX_MESSAGE_LENGTH = Radio_P::MAX_MESSAGE_LENGTH - Message::PAYLOAD_POS 00087 }; 00088 // -------------------------------------------------------------------- 00089 00090 LazyType(); 00091 ~LazyType(); 00092 void enable( void ); 00093 void disable( void ); 00094 uint8_t decision_lazy( Node, node_id_t ); 00095 void send_neighbor_discovery( void* ); 00096 void send_vicinity_discovery( void* ); 00097 void send_greedy( void* ); 00098 void send( node_id_t, size_t, block_data_t*, message_id_t ); 00099 void receive( node_id_t, size_t, block_data_t* ); 00100 void store_neighbor( Node ); 00101 void store_vicinity( Connectivity ); 00102 void print_neighbors( void* ); 00103 void print_vicinity( void* ); 00104 void filter_vicinity( void* ); 00105 void init( Radio& radio, Timer& timer, Debug& debug, Rand& rand ) 00106 { 00107 radio_ = &radio; 00108 debug_ = &debug; 00109 timer_ = &timer; 00110 rand_ = &rand; 00111 } 00112 inline void set_self( Node _n, NodeList _nl ) 00113 { 00114 self.set_node(_n ); 00115 self.set_vicinity_list( _nl ); 00116 } 00117 inline void set_self( Node _n ) 00118 { 00119 self.set_node(_n ); 00120 } 00121 inline void set_neighbor_discovery_timer( millis_t _t ) 00122 { 00123 neighbor_discovery_timer = _t; 00124 } 00125 inline void set_vicinity_discovery_timer( millis_t _t ) 00126 { 00127 vicinity_discovery_timer = _t; 00128 } 00129 inline Connectivity* get_self( void ) 00130 { 00131 return &self; 00132 } 00133 inline millis_t get_neighbor_discovery_timer( void ) 00134 { 00135 return neighbor_discovery_timer; 00136 } 00137 inline millis_t get_vicinity_discovery_timer( void ) 00138 { 00139 return vicinity_discovery_timer; 00140 } 00141 inline millis_t get_ready_time( void ) 00142 { 00143 return neighbor_discovery_timer + vicinity_discovery_timer + vicinity_filter_timer; 00144 } 00145 inline void set_destination ( const Position& _p ) 00146 { 00147 destination = _p; 00148 } 00149 void destruct() 00150 {} 00151 Radio& radio() 00152 { 00153 return *radio_; 00154 } 00155 Debug& debug() 00156 { 00157 return *debug_; 00158 } 00159 Timer& timer() 00160 { 00161 return *timer_; 00162 } 00163 Rand& rand() 00164 { 00165 return *rand_; 00166 } 00167 private: 00168 00169 Radio* radio_; 00170 Debug* debug_; 00171 Timer* timer_; 00172 Rand* rand_; 00173 enum MessageIds 00174 { 00175 LAZY_NEIGHBOR_DISCOVERY = 31, 00176 LAZY_VICINITY_DISCOVERY = 32, 00177 LAZY_GREEDY_MESSAGE = 33 00178 }; 00179 int callback_id_; 00180 Connectivity self; 00181 ConnectivityList vicinity; 00182 ConnectivityList filtered_vicinity; 00183 millis_t neighbor_discovery_timer; 00184 millis_t vicinity_discovery_timer; 00185 millis_t vicinity_filter_timer; 00186 Position destination; 00187 }; 00188 // ----------------------------------------------------------------------- 00189 template< typename Os_P, 00190 typename Radio_P, 00191 typename Timer_P, 00192 typename Rand_P, 00193 typename Node_P, 00194 typename NodeList_P, 00195 typename Connectivity_P, 00196 typename ConnectivityList_P, 00197 typename Debug_P> 00198 LazyType<Os_P, Radio_P, Timer_P, Rand_P, Node_P, NodeList_P, Connectivity_P, ConnectivityList_P, Debug_P>:: 00199 LazyType() 00200 : callback_id_ ( 0 ) 00201 {} 00202 // ----------------------------------------------------------------------- 00203 template< typename Os_P, 00204 typename Radio_P, 00205 typename Timer_P, 00206 typename Rand_P, 00207 typename Node_P, 00208 typename NodeList_P, 00209 typename Connectivity_P, 00210 typename ConnectivityList_P, 00211 typename Debug_P> 00212 LazyType<Os_P, Radio_P, Timer_P, Rand_P, Node_P, NodeList_P, Connectivity_P, ConnectivityList_P, Debug_P>:: 00213 ~LazyType() 00214 {} 00215 // ----------------------------------------------------------------------- 00216 template< typename Os_P, 00217 typename Radio_P, 00218 typename Timer_P, 00219 typename Rand_P, 00220 typename Node_P, 00221 typename NodeList_P, 00222 typename Connectivity_P, 00223 typename ConnectivityList_P, 00224 typename Debug_P> 00225 void 00226 LazyType<Os_P, Radio_P, Timer_P, Rand_P, Node_P, NodeList_P, Connectivity_P, ConnectivityList_P, Debug_P>:: 00227 enable( void ) 00228 { 00229 radio().enable_radio(); 00230 debug().debug( "Lazy %x: Boot \n", self.get_node().get_id() ); 00231 callback_id_ = radio().template reg_recv_callback<self_type, &self_type::receive>( this ); 00232 millis_t ndt = rand()()%neighbor_discovery_timer; 00233 timer().template set_timer<self_type, &self_type::send_neighbor_discovery>( ndt, this, 0); 00234 millis_t vdt = rand()()%vicinity_discovery_timer; 00235 timer().template set_timer<self_type, &self_type::send_vicinity_discovery>( vdt + neighbor_discovery_timer, this, 0); 00236 vicinity_filter_timer = vicinity_discovery_timer + neighbor_discovery_timer + 2000; 00237 timer().template set_timer<self_type, &self_type::filter_vicinity>( vicinity_filter_timer, this, 0); 00238 //timer().template set_timer<self_type, &self_type::print_neighbors>( vicinity_discovery_timer + neighbor_discovery_timer + 5000, this, 0); 00239 //timer().template set_timer<self_type, &self_type::print_vicinity>( vicinity_discovery_timer + neighbor_discovery_timer + 15000, this, 0); 00240 00241 00242 } 00243 // ----------------------------------------------------------------------- 00244 template< typename Os_P, 00245 typename Radio_P, 00246 typename Timer_P, 00247 typename Rand_P, 00248 typename Node_P, 00249 typename NodeList_P, 00250 typename Connectivity_P, 00251 typename ConnectivityList_P, 00252 typename Debug_P> 00253 void 00254 LazyType<Os_P, Radio_P, Timer_P, Rand_P, Node_P, NodeList_P, Connectivity_P, ConnectivityList_P, Debug_P>:: 00255 disable( void ) 00256 { 00257 debug().debug( "Lazy %x: Disable \n", self.get_node().get_id() ); 00258 radio().unreg_recv_callback( callback_id_ ); 00259 radio().disable(); 00260 } 00261 // ----------------------------------------------------------------------- 00262 template< typename Os_P, 00263 typename Radio_P, 00264 typename Timer_P, 00265 typename Rand_P, 00266 typename Node_P, 00267 typename NodeList_P, 00268 typename Connectivity_P, 00269 typename ConnectivityList_P, 00270 typename Debug_P> 00271 void 00272 LazyType<Os_P, Radio_P, Timer_P, Rand_P, Node_P, NodeList_P, Connectivity_P, ConnectivityList_P, Debug_P>:: 00273 send( node_id_t destination, size_t len, block_data_t *data, message_id_t msg_id ) 00274 { 00275 Message message; 00276 message.set_msg_id( msg_id ); 00277 message.set_payload( len, data ); 00278 radio().send( destination, message.buffer_size(), (uint8_t*)&message ); 00279 } 00280 // ----------------------------------------------------------------------- 00281 template< typename Os_P, 00282 typename Radio_P, 00283 typename Timer_P, 00284 typename Rand_P, 00285 typename Node_P, 00286 typename NodeList_P, 00287 typename Connectivity_P, 00288 typename ConnectivityList_P, 00289 typename Debug_P> 00290 void 00291 LazyType<Os_P, Radio_P, Timer_P, Rand_P, Node_P, NodeList_P, Connectivity_P, ConnectivityList_P, Debug_P>:: 00292 send_neighbor_discovery( void* userdata ) 00293 { 00294 debug().debug( "Lazy %x: Entered Send Neighbor Discovery Message\n", self.get_node().get_id() ); 00295 size_t len = self.get_node().get_buffer_size(); 00296 block_data_t buf[Radio::MAX_MESSAGE_LENGTH]; 00297 block_data_t* buff = buf; 00298 self.get_node().set_buffer_from( buff ); 00299 send( Radio::BROADCAST_ADDRESS, len, (uint8_t*)buff, LAZY_NEIGHBOR_DISCOVERY ); 00300 } 00301 // ----------------------------------------------------------------------- 00302 template< typename Os_P, 00303 typename Radio_P, 00304 typename Timer_P, 00305 typename Rand_P, 00306 typename Node_P, 00307 typename NodeList_P, 00308 typename Connectivity_P, 00309 typename ConnectivityList_P, 00310 typename Debug_P> 00311 void 00312 LazyType<Os_P, Radio_P, Timer_P, Rand_P, Node_P, NodeList_P, Connectivity_P, ConnectivityList_P, Debug_P>:: 00313 send_vicinity_discovery( void* userdata ) 00314 { 00315 debug().debug( "Lazy %x: Entered Send Vicinity Discovery Message\n", self.get_node().get_id() ); 00316 self.print( debug() ); 00317 size_t len = self.get_buffer_size(); 00318 block_data_t buf[Radio::MAX_MESSAGE_LENGTH]; 00319 block_data_t* buff = buf; 00320 self.set_buffer_from( buff ); 00321 send( Radio::BROADCAST_ADDRESS, len, (uint8_t*)buff, LAZY_VICINITY_DISCOVERY ); 00322 } 00323 // ----------------------------------------------------------------------- 00324 template< typename Os_P, 00325 typename Radio_P, 00326 typename Timer_P, 00327 typename Rand_P, 00328 typename Node_P, 00329 typename NodeList_P, 00330 typename Connectivity_P, 00331 typename ConnectivityList_P, 00332 typename Debug_P> 00333 void 00334 LazyType<Os_P, Radio_P, Timer_P, Rand_P, Node_P, NodeList_P, Connectivity_P, ConnectivityList_P, Debug_P>:: 00335 receive( node_id_t from, size_t len, block_data_t *data ) 00336 { 00337 00338 debug().debug( "Lazy %x: Entered Receive\n", self.get_node().get_id() ); 00339 message_id_t msg_id = *data; 00340 Message* message = (Message*)data; 00341 if (msg_id == LAZY_NEIGHBOR_DISCOVERY ) 00342 { 00343 debug().debug( "Lazy %x: Received neighbor discovery message from %x of size %i \n", self.get_node().get_id(), from, len ); 00344 store_neighbor( Node( message->payload() ) ); 00345 } 00346 else if (msg_id == LAZY_VICINITY_DISCOVERY ) 00347 { 00348 debug().debug( "Lazy %x: Received vicinity discovery message from %x of size %i \n", self.get_node().get_id(), from, len ); 00349 store_vicinity( Connectivity( message->payload() ) ); 00350 } 00351 else if (msg_id == LAZY_GREEDY_MESSAGE ) 00352 { 00353 debug().debug( "Lazy %x: Received lazy greedy message from %x of size %i \n", self.get_node().get_id(), from, len ); 00354 Node rec_n = Node( message->payload() ); 00355 if ( decision_lazy( rec_n, from ) ) 00356 { 00357 void* tmp; 00358 send_greedy( tmp ); 00359 } 00360 } 00361 } 00362 // ----------------------------------------------------------------------- 00363 template< typename Os_P, 00364 typename Radio_P, 00365 typename Timer_P, 00366 typename Rand_P, 00367 typename Node_P, 00368 typename NodeList_P, 00369 typename Connectivity_P, 00370 typename ConnectivityList_P, 00371 typename Debug_P> 00372 uint8_t 00373 LazyType<Os_P, Radio_P, Timer_P, Rand_P, Node_P, NodeList_P, Connectivity_P, ConnectivityList_P, Debug_P>:: 00374 decision_lazy( Node n, node_id_t from ) 00375 { 00376 CoordinatesNumber current_distance = n.get_position().distsq( self.get_node().get_position() ); 00377 CoordinatesNumber min_distance = current_distance; 00378 CoordinatesNumber candidate_distance; 00379 node_id_t candidate_id = self.get_node().get_id(); 00380 for ( ConnectivityListIterator i = filtered_vicinity.begin(); i != filtered_vicinity.end(); ++i ) 00381 { 00382 if ( from == i->get_node().get_id() ) 00383 { 00384 for ( NodeListIterator j = ( *i->get_node_list() ).begin(); j != ( *i->get_node_list() ).end(); ++j ) 00385 { 00386 candidate_distance = n.get_position().distsq( j->get_position() ); 00387 if (min_distance >= candidate_distance ) 00388 { 00389 return 0; 00390 } 00391 } 00392 } 00393 } 00394 return 1; 00395 } 00396 // ----------------------------------------------------------------------- 00397 template< typename Os_P, 00398 typename Radio_P, 00399 typename Timer_P, 00400 typename Rand_P, 00401 typename Node_P, 00402 typename NodeList_P, 00403 typename Connectivity_P, 00404 typename ConnectivityList_P, 00405 typename Debug_P> 00406 void 00407 LazyType<Os_P, Radio_P, Timer_P, Rand_P, Node_P, NodeList_P, Connectivity_P, ConnectivityList_P, Debug_P>:: 00408 store_neighbor( Node _n ) 00409 { 00410 NodeListIterator i = ( *self.get_node_list() ).begin(); 00411 while ( i != ( *self.get_node_list() ).end() ) 00412 { 00413 if ( i->get_id() == _n.get_id() ) 00414 { 00415 ( *self.get_node_list() ).erase( i ); 00416 ( *self.get_node_list() ).push_back( _n ); 00417 return; 00418 } 00419 ++i; 00420 } 00421 ( *self.get_node_list() ).push_back( _n ); 00422 } 00423 // ----------------------------------------------------------------------- 00424 template< typename Os_P, 00425 typename Radio_P, 00426 typename Timer_P, 00427 typename Rand_P, 00428 typename Node_P, 00429 typename NodeList_P, 00430 typename Connectivity_P, 00431 typename ConnectivityList_P, 00432 typename Debug_P> 00433 void 00434 LazyType<Os_P, Radio_P, Timer_P, Rand_P, Node_P, NodeList_P, Connectivity_P, ConnectivityList_P, Debug_P>:: 00435 store_vicinity( Connectivity _c ) 00436 { 00437 ConnectivityListIterator i = vicinity.begin(); 00438 while ( i != vicinity.end() ) 00439 { 00440 if ( i->get_node().get_id() == _c.get_node().get_id() ) 00441 { 00442 vicinity.erase( i ); 00443 vicinity.push_back( _c ); 00444 return; 00445 } 00446 ++i; 00447 } 00448 vicinity.push_back( _c ); 00449 } 00450 // ----------------------------------------------------------------------- 00451 template< typename Os_P, 00452 typename Radio_P, 00453 typename Timer_P, 00454 typename Rand_P, 00455 typename Node_P, 00456 typename NodeList_P, 00457 typename Connectivity_P, 00458 typename ConnectivityList_P, 00459 typename Debug_P> 00460 void 00461 LazyType<Os_P, Radio_P, Timer_P, Rand_P, Node_P, NodeList_P, Connectivity_P, ConnectivityList_P, Debug_P>:: 00462 print_neighbors( void* userdata ) 00463 { 00464 self.print( debug() ); 00465 } 00466 // ----------------------------------------------------------------------- 00467 template< typename Os_P, 00468 typename Radio_P, 00469 typename Timer_P, 00470 typename Rand_P, 00471 typename Node_P, 00472 typename NodeList_P, 00473 typename Connectivity_P, 00474 typename ConnectivityList_P, 00475 typename Debug_P> 00476 void 00477 LazyType<Os_P, Radio_P, Timer_P, Rand_P, Node_P, NodeList_P, Connectivity_P, ConnectivityList_P, Debug_P>:: 00478 print_vicinity( void* userdata ) 00479 { 00480 debug().debug( "Lazy %x: Printing filtered vicinity: \n", self.get_node().get_id() ); 00481 for ( ConnectivityListIterator i = filtered_vicinity.begin(); i!=filtered_vicinity.end(); ++i ) 00482 { 00483 i->print( debug() ); 00484 } 00485 } 00486 // ----------------------------------------------------------------------- 00487 template< typename Os_P, 00488 typename Radio_P, 00489 typename Timer_P, 00490 typename Rand_P, 00491 typename Node_P, 00492 typename NodeList_P, 00493 typename Connectivity_P, 00494 typename ConnectivityList_P, 00495 typename Debug_P> 00496 void 00497 LazyType<Os_P, Radio_P, Timer_P, Rand_P, Node_P, NodeList_P, Connectivity_P, ConnectivityList_P, Debug_P>:: 00498 filter_vicinity( void* userdata ) 00499 { 00500 for ( NodeListIterator ni = ( *self.get_node_list() ).begin(); ni != ( *self.get_node_list() ).end(); ++ni ) 00501 { 00502 Connectivity element; 00503 element.set_node( *ni ); 00504 for ( ConnectivityListIterator cli = vicinity.begin(); cli != vicinity.end(); ++cli ) 00505 { 00506 if ( ni->get_id() == cli->get_node().get_id() ) 00507 { 00508 for ( NodeListIterator nli = ( *cli->get_node_list() ).begin(); nli != ( *cli->get_node_list() ).end(); ++nli ) 00509 { 00510 for ( NodeListIterator ni_in = ( *self.get_node_list() ).begin(); ni_in != ( *self.get_node_list() ).end(); ++ni_in ) 00511 { 00512 if ( ni_in->get_id() == nli->get_id() ) 00513 { 00514 ( *element.get_node_list() ).push_back( *nli ); 00515 } 00516 } 00517 } 00518 } 00519 } 00520 filtered_vicinity.push_back( element ); 00521 } 00522 } 00523 // ----------------------------------------------------------------------- 00524 template< typename Os_P, 00525 typename Radio_P, 00526 typename Timer_P, 00527 typename Rand_P, 00528 typename Node_P, 00529 typename NodeList_P, 00530 typename Connectivity_P, 00531 typename ConnectivityList_P, 00532 typename Debug_P> 00533 void 00534 LazyType<Os_P, Radio_P, Timer_P, Rand_P, Node_P, NodeList_P, Connectivity_P, ConnectivityList_P, Debug_P>:: 00535 send_greedy( void* userdata ) 00536 { 00537 debug().debug( "Lazy %x: Entered Send Greedy Message\n", self.get_node().get_id() ); 00538 Node msg_node = Node ( self.get_node().get_id(), destination ); 00539 size_t len = msg_node.get_buffer_size(); 00540 block_data_t buf[Radio::MAX_MESSAGE_LENGTH]; 00541 block_data_t* buff = buf; 00542 msg_node.set_buffer_from( buff ); 00543 send( Radio::BROADCAST_ADDRESS, len, (uint8_t*)buff, LAZY_GREEDY_MESSAGE ); 00544 } 00545 } 00546 #endif