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 ** Author: Juan Farré, jafarre@lsi.upc.edu ** 00020 ***************************************************************************/ 00021 #ifndef __ALGORITHMS_TOPOLOGY_KNEIGH_SYMMETRIC_TOPOLOGY_CONTROL_H__ 00022 #define __ALGORITHMS_TOPOLOGY_KNEIGH_SYMMETRIC_TOPOLOGY_CONTROL_H__ 00023 00024 #include "algorithms/topology/topology_control_base.h" 00025 #include "algorithms/topology/kneigh/kneigh_broadcast_message.h" 00026 #include "algorithms/topology/kneigh/kneigh_list_message.h" 00027 #include "algorithms/topology/kneigh/kneigh_types.h" 00028 #include "util/pstl/algorithm.h" 00029 #include "util/pstl/pair.h" 00030 #include "util/pstl/vector_static.h" 00031 00032 namespace wiselib { 00033 00034 #define DELTA_DEF 60000 00035 #define D_DEF 16000 00036 #define TAU_DEF 1000 00037 #define PRUNE_DEF false 00038 #define ALPHA_DEF 2 00039 00045 template<class OsModel_P, typename OsModel_P::size_t K = 9, 00046 // class DistanceAlg_P, 00047 class Distance_P=uint16_t, 00048 class Radio_P = typename OsModel_P::Radio, 00049 class Timer_P = typename OsModel_P::Timer, 00050 class Rand_P = typename OsModel_P::Rand> 00051 class KneighProtocol: public TopologyBase<OsModel_P> 00052 { 00053 public: 00054 typedef OsModel_P OsModel; 00055 // typedef DistanceAlg_P DistanceAlg; 00056 typedef Distance_P Distance; 00057 typedef Radio_P Radio; 00058 typedef Timer_P Timer; 00059 typedef Rand_P Rand; 00060 #ifdef DEBUG 00061 typedef typename OsModel_P::Debug Debug; 00062 #endif 00063 00064 typedef KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P> self_type; 00065 00066 typedef typename Radio::node_id_t node_id_t; 00067 typedef typename Radio::size_t size_t; 00068 typedef typename Radio::block_data_t block_data_t; 00069 typedef typename Radio::ExtendedData ExtendedData; 00070 00071 typedef typename Timer::millis_t millis_t; 00072 typedef vector_static<OsModel,node_id_t,K> Neighbors; 00073 00076 KneighProtocol(); 00078 00081 void enable(); 00082 void disable(); 00084 00085 Neighbors &topology(); 00086 00087 void set_delta(register millis_t const delta=s_delta_def) { 00088 if(!d_enabled) 00089 d_delta=delta; 00090 } 00091 00092 millis_t delta() const { 00093 return d_delta; 00094 } 00095 00096 void set_d(register millis_t const d=s_d_def) { 00097 if(!d_enabled) 00098 d_d=d; 00099 } 00100 00101 millis_t d() const { 00102 return d_d; 00103 } 00104 00105 void set_tau(register millis_t const tau=s_tau_def) { 00106 if(!d_enabled) 00107 d_tau=tau; 00108 } 00109 00110 millis_t tau() const { 00111 return d_tau; 00112 } 00113 00114 void set_prune(register bool const prune=s_prune_def) { 00115 if(!d_enabled) 00116 d_prune=prune; 00117 } 00118 00119 bool prune() const { 00120 return d_prune; 00121 } 00122 00123 void set_alpha(register int const alpha=s_alpha_def) { 00124 if(!d_enabled) 00125 d_alpha=alpha; 00126 } 00127 00128 int alpha() const { 00129 return d_alpha; 00130 } 00131 00132 static void set_default_delta(millis_t const delta=DELTA_DEF) { 00133 s_delta_def=delta; 00134 } 00135 00136 static millis_t default_delta() { 00137 return s_delta_def; 00138 } 00139 00140 static void set_default_d(millis_t const d=D_DEF) { 00141 s_d_def=d; 00142 } 00143 00144 static millis_t default_d() { 00145 return s_d_def; 00146 } 00147 00148 static void set_default_tau(millis_t const tau=TAU_DEF) { 00149 s_tau_def=tau; 00150 } 00151 00152 static millis_t default_tau() { 00153 return s_tau_def; 00154 } 00155 00156 static void set_default_prune(bool const prune=PRUNE_DEF) { 00157 s_prune_def=prune; 00158 } 00159 00160 static bool default_prune() { 00161 return s_prune_def; 00162 } 00163 00164 static void set_default_alpha(int const alpha=ALPHA_DEF) { 00165 s_alpha_def=alpha; 00166 } 00167 00168 static int default_alpha() { 00169 return s_alpha_def; 00170 } 00171 00172 #ifdef DEBUG 00173 void init( Radio& radio, Timer& timer, Debug& debug ) { 00174 radio_ = &radio; 00175 timer_ = &timer; 00176 debug_ = &debug; 00177 } 00178 #else 00179 void init( Radio& radio, Timer& timer) { 00180 radio_ = &radio; 00181 timer_ = &timer; 00182 } 00183 #endif 00184 00185 void destruct() { 00186 } 00187 00188 private: 00189 Radio& radio() 00190 { return *radio_;} 00191 00192 Timer& timer() 00193 { return *timer_;} 00194 00195 #ifdef DEBUG 00196 Debug& debug() 00197 { return *debug_;} 00198 #endif 00199 00200 Radio * radio_; 00201 Timer * timer_; 00202 #ifdef DEBUG 00203 Debug * debug_; 00204 #endif 00205 00206 typedef pair<node_id_t,Distance> ListEntry; 00207 typedef vector_static<OsModel,ListEntry,K> NodeList; 00208 00209 class CompareListEntries { 00210 public: 00211 bool operator()(ListEntry left, ListEntry right) { 00212 return left.second<right.second; 00213 } 00214 }; 00215 00218 void timer0( void * const userdata ); 00219 void timer1( void * const userdata ); 00220 void timer2( void * const userdata ); 00221 void timer3( void * const userdata ); 00223 00226 void receive( node_id_t from, size_t len, block_data_t *data, ExtendedData const &extended ); 00228 00229 bool d_enabled; 00230 millis_t d_delta; 00231 millis_t d_d; 00232 millis_t d_tau; 00233 bool d_prune; 00234 int d_alpha; 00235 00236 NodeList list; 00237 Neighbors neigh; 00238 // DistanceAlg dist_alg; 00239 Rand rand_gen; 00240 00241 KNeighBroadcastMessage<OsModel,Radio> broadcast_msg; 00242 KNeighListMessage<OsModel,K,Radio> list_msg; 00243 00244 static millis_t s_delta_def; 00245 static millis_t s_d_def; 00246 static millis_t s_tau_def; 00247 static bool s_prune_def; 00248 static int s_alpha_def; 00249 }; 00250 // ----------------------------------------------------------------------- 00251 // ----------------------------------------------------------------------- 00252 template<class OsModel_P, 00253 typename OsModel_P::size_t K, 00254 // class DistanceAlg_P, 00255 class Distance_P, 00256 class Radio_P, 00257 class Timer_P, 00258 class Rand_P> 00259 typename Timer_P::millis_t KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::s_delta_def=DELTA_DEF; 00260 00261 template<class OsModel_P, 00262 typename OsModel_P::size_t K, 00263 // class DistanceAlg_P, 00264 class Distance_P, 00265 class Radio_P, 00266 class Timer_P, 00267 class Rand_P> 00268 typename Timer_P::millis_t KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::s_d_def=D_DEF; 00269 00270 template<class OsModel_P, 00271 typename OsModel_P::size_t K, 00272 // class DistanceAlg_P, 00273 class Distance_P, 00274 class Radio_P, 00275 class Timer_P, 00276 class Rand_P> 00277 typename Timer_P::millis_t KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::s_tau_def=TAU_DEF; 00278 00279 template<class OsModel_P, 00280 typename OsModel_P::size_t K, 00281 // class DistanceAlg_P, 00282 class Distance_P, 00283 class Radio_P, 00284 class Timer_P, 00285 class Rand_P> 00286 bool KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::s_prune_def=PRUNE_DEF; 00287 00288 template<class OsModel_P, 00289 typename OsModel_P::size_t K, 00290 // class DistanceAlg_P, 00291 class Distance_P, 00292 class Radio_P, 00293 class Timer_P, 00294 class Rand_P> 00295 int KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::s_alpha_def=ALPHA_DEF; 00296 // ----------------------------------------------------------------------- 00297 template<class OsModel_P, 00298 typename OsModel_P::size_t K, 00299 // class DistanceAlg_P, 00300 class Distance_P, 00301 class Radio_P, 00302 class Timer_P, 00303 class Rand_P> 00304 KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>:: 00305 KneighProtocol() 00306 : d_enabled(false), 00307 d_delta(s_delta_def), 00308 d_d(s_d_def), 00309 d_tau(s_tau_def), 00310 d_prune(s_prune_def), 00311 d_alpha(s_alpha_def) 00312 { 00313 }; 00314 // ----------------------------------------------------------------------- 00315 template<class OsModel_P, 00316 typename OsModel_P::size_t K, 00317 // class DistanceAlg_P, 00318 class Distance_P, 00319 class Radio_P, 00320 class Timer_P, 00321 class Rand_P> 00322 void 00323 KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>:: 00324 enable( void ) 00325 { 00326 d_enabled=true; 00327 rand_gen.srand(radio().id()); 00328 radio().template reg_recv_callback<self_type, &self_type::receive>( this ); 00329 timer().template set_timer<self_type, &self_type::timer0>( 00330 delta()+rand_gen(d()), this, 0 ); 00331 // dist_alg.enable(); 00332 neigh.clear(); 00333 list.clear(); 00334 #ifdef DEBUG 00335 debug().debug( "KneighProtocol Boots for %i\n", radio().id() ); 00336 #endif 00337 } 00338 // ----------------------------------------------------------------------- 00339 template<class OsModel_P, 00340 typename OsModel_P::size_t K, 00341 // class DistanceAlg_P, 00342 class Distance_P, 00343 class Radio_P, 00344 class Timer_P, 00345 class Rand_P> 00346 void 00347 KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>:: 00348 disable( void ) 00349 { 00350 #ifdef DEBUG 00351 debug().debug( "Called KneighProtocol::disable\n" ); 00352 #endif 00353 d_enabled=false; 00354 } 00355 // ----------------------------------------------------------------------- 00356 template<class OsModel_P, 00357 typename OsModel_P::size_t K, 00358 // class DistanceAlg_P, 00359 class Distance_P, 00360 class Radio_P, 00361 class Timer_P, 00362 class Rand_P> 00363 typename KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::Neighbors & 00364 KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::topology() 00365 { 00366 return neigh; 00367 } 00368 // ----------------------------------------------------------------------- 00369 template<class OsModel_P, 00370 typename OsModel_P::size_t K, 00371 // class DistanceAlg_P, 00372 class Distance_P, 00373 class Radio_P, 00374 class Timer_P, 00375 class Rand_P> 00376 void 00377 KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>:: 00378 timer0( void* userdata ) 00379 { 00380 #ifdef DEBUG 00381 debug().debug( "Timer0 elapsed\n"); 00382 #endif 00383 if(!d_enabled) 00384 return; 00385 broadcast_msg.set_msg_id(KNeighBroadcastMsgId); 00386 radio().send( radio().BROADCAST_ADDRESS, broadcast_msg.buffer_size(), broadcast_msg.buf() ); 00387 timer().template set_timer<self_type, &self_type::timer1>( 00388 delta()+d(), this, 0 ); 00389 #ifdef DEBUG 00390 debug().debug( "Broadcast message sent\n"); 00391 #endif 00392 } 00393 00394 template<class OsModel_P, 00395 typename OsModel_P::size_t K, 00396 // class DistanceAlg_P, 00397 class Distance_P, 00398 class Radio_P, 00399 class Timer_P, 00400 class Rand_P> 00401 void 00402 KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>:: 00403 timer1( void* userdata ) 00404 { 00405 #ifdef DEBUG 00406 debug().debug( "Timer1 elapsed\n"); 00407 #endif 00408 if(!d_enabled) 00409 return; 00410 list_msg.set_msg_id(KNeighListMsgId); 00411 list_msg.set_neighbor_number(list.size()); 00412 for(size_t i=0;i<list.size();i++) 00413 list_msg.set_neighbor(i,list[i].first); 00414 timer().template set_timer<self_type, &self_type::timer2>( 00415 delta()+d()+tau()+rand_gen(d()), this, 0 ); 00416 #ifdef DEBUG 00417 debug().debug( "First list generated\n"); 00418 #endif 00419 } 00420 00421 template<class OsModel_P, 00422 typename OsModel_P::size_t K, 00423 // class DistanceAlg_P, 00424 class Distance_P, 00425 class Radio_P, 00426 class Timer_P, 00427 class Rand_P> 00428 void 00429 KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>:: 00430 timer2( void* userdata ) 00431 { 00432 #ifdef DEBUG 00433 debug().debug( "Timer2 elapsed\n"); 00434 #endif 00435 if(!d_enabled) 00436 return; 00437 radio().send( radio().BROADCAST_ADDRESS, list_msg.buffer_size(), list_msg.buf() ); 00438 timer().template set_timer<self_type, &self_type::timer3>( 00439 delta()+2*d()+tau(), this, 0 ); 00440 #ifdef DEBUG 00441 debug().debug( "List message sent\n"); 00442 #endif 00443 } 00444 00445 template<class OsModel_P, 00446 typename OsModel_P::size_t K, 00447 // class DistanceAlg_P, 00448 class Distance_P, 00449 class Radio_P, 00450 class Timer_P, 00451 class Rand_P> 00452 void 00453 KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>:: 00454 timer3( void* userdata ) 00455 { 00456 #ifdef DEBUG 00457 debug().debug( "Timer3 elapsed\n"); 00458 #endif 00459 if(!d_enabled) 00460 return; 00461 #ifdef DEBUG 00462 debug().debug( "%d neighbors for node %i:\n",neigh.size(),radio().id() ); 00463 for(size_t i=0;i<neigh.size();i++) 00464 debug().debug("%i\n",neigh[i]); 00465 #endif 00466 TopologyBase<OsModel>::notify_listeners(); 00467 } 00468 // ----------------------------------------------------------------------- 00469 template<class OsModel_P, 00470 typename OsModel_P::size_t K, 00471 // class DistanceAlg_P, 00472 class Distance_P, 00473 class Radio_P, 00474 class Timer_P, 00475 class Rand_P> 00476 void 00477 KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>:: 00478 receive( node_id_t from, size_t len, block_data_t *data, ExtendedData const &extended ) 00479 { 00480 typedef typename NodeList::iterator Iter; 00481 switch(*data) { 00482 case KNeighBroadcastMsgId: { 00483 #ifdef DEBUG 00484 debug().debug( "Broadcast message received\n"); 00485 #endif 00486 ListEntry const entry(from,extended.link_metric()); 00487 if(list.size()<K) { 00488 list.push_back(entry); 00489 if(list.size()==1) 00490 return; 00491 } 00492 else if(entry.second>=list[K-1].second) 00493 return; 00494 linear_insert(list.begin(),list.end()-1,entry,CompareListEntries()); 00495 } 00496 break; 00497 case KNeighListMsgId: { 00498 #ifdef DEBUG 00499 debug().debug( "List message received\n"); 00500 #endif 00501 Iter i=list.begin(); 00502 for(;i!=list.end()&&i->first!=from;i++); 00503 if(i!=list.end()) { 00504 KNeighListMessage<OsModel,K,Radio> *const m=reinterpret_cast<KNeighListMessage<OsModel,K,Radio> *>(data); 00505 uint8_t j=0; 00506 for(;j<m->neighbor_number()&&m->neighbor(j)!=radio().id();j++); 00507 if(j<m->neighbor_number()) { 00508 neigh.push_back(from); 00509 } 00510 } 00511 } 00512 break; 00513 } 00514 } 00515 00516 } 00517 #endif