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 00020 #ifndef __ALGORITHMS_CLUSTER_HIGHWAY_CLUSTER_H__ 00021 #define __ALGORITHMS_CLUSTER_HIGHWAY_CLUSTER_H__ 00022 00023 00024 #include "algorithms/neighbor_discovery/echo.h" 00025 #include "algorithms/cluster/bfscluster/bfsclustering.h" 00026 #include "algorithms/cluster/clustering_types.h" 00027 #include "util/pstl/vector_static.h" 00028 #include "util/pstl/priority_queue.h" 00029 #include "util/pstl/pair.h" 00030 #include "util/pstl/map_static_vector.h" 00031 #include "internal_interface/routing_table/routing_table_static_array.h" 00032 #include "util/delegates/delegate.hpp" 00033 00034 00035 // Levels of debug info: 00036 // HIGHWAY_METHOD_DEBUG: Adds a Method called notice at the beginning of each 00037 // method. 00038 // HIGHWAY_MSG_RECV_DEBUG: Adds all sorts of debug messages for the tracking 00039 // of sending messages at Highway level. 00040 // VISOR_DEBUG: Adds debug messages that can be processed by the Python visor 00041 // application to generate a picture of the final status of the WSN. 00042 // HIGHWAY_DEBUG: Most general debug messages. 00043 00044 #define HIGHWAY_DEBUG 00045 //#define HIGHWAY_METHOD_DEBUG 00046 #define HIGHWAY_MSG_RECV_DEBUG 00047 #define VISOR_DEBUG 00048 00049 namespace wiselib{ 00050 template<typename OsModel_P, 00051 typename RoutingTable_P, 00052 typename Radio_P = typename OsModel_P::Radio, 00053 typename Timer_P = typename OsModel_P::Timer, 00054 typename Clock_P = typename OsModel_P::Clock, 00055 typename Debug_P = typename OsModel_P::Debug, 00056 typename Cluster_P = typename wiselib::BfsClustering<OsModel_P, Radio_P, Timer_P, Debug_P>, 00057 typename Neighbor_P = typename wiselib::Echo<OsModel_P, Radio_P, Timer_P, Debug_P>, 00058 uint16_t MAX_CLUSTERS = 8> 00059 class HighwayCluster 00060 { 00061 public: 00062 // Type definitions. 00063 // Type definition of the used Templates. 00064 typedef OsModel_P OsModel; 00065 typedef RoutingTable_P RoutingTable; 00066 typedef Radio_P Radio; 00067 typedef Timer_P Timer; 00068 typedef Clock_P Clock; 00069 typedef Debug_P Debug; 00070 typedef Cluster_P Cluster; 00071 typedef Neighbor_P Neighbor; 00072 00073 typedef HighwayCluster<OsModel, RoutingTable, Radio, Timer,Clock, Debug, Cluster, Neighbor, MAX_CLUSTERS> self_type; 00074 typedef wiselib::Echo<OsModel, Radio, Timer, Debug> nb_t; 00075 typedef self_type* self_pointer_t; 00076 00077 // Basic types definition. 00078 typedef typename Radio::node_id_t node_id_t; 00079 typedef typename Radio::size_t size_t; 00080 typedef typename Radio::block_data_t block_data_t; 00081 typedef typename Timer::millis_t millis_t; 00082 00083 // Type definition for the receive callback. 00084 typedef delegate3<void, node_id_t, size_t, block_data_t*> highway_delegate_t; 00085 00086 enum Sizes { 00087 MAX_CLUSTER_PORTS = 4 00088 }; 00089 00090 // Type definition for the special data structures of the highway. 00091 typedef wiselib::pair<int16_t, node_id_t> Hops_Node_id; 00092 typedef wiselib::priority_queue<OsModel, Hops_Node_id, MAX_CLUSTER_PORTS> PQ; 00093 typedef wiselib::pair<PQ, int16_t> PQ_Ack; 00094 typedef wiselib::MapStaticVector<OsModel, node_id_t, PQ_Ack, MAX_CLUSTERS> HighwayTable; 00095 typedef wiselib::MapStaticVector<OsModel, node_id_t, PQ_Ack, MAX_CLUSTERS> PortsQueue; 00096 typedef wiselib::vector_static<OsModel, node_id_t, MAX_CLUSTERS> Node_vect; 00097 typedef wiselib::vector_static<OsModel, Hops_Node_id, MAX_CLUSTER_PORTS> Ports_vect; 00098 00099 // Type definition for the special types iterators. 00100 typedef typename HighwayTable::iterator highway_iterator; 00101 typedef typename PQ::pointer pq_iterator; 00102 00103 // Return types definition. 00104 enum ErrorCodes { 00105 SUCCESS = OsModel::SUCCESS, 00106 ERR_UNSPEC = OsModel::ERR_UNSPEC 00107 }; 00108 00109 // TODO: Move into a highway message class. 00110 enum msg_id { 00111 CANDIDACY = 100, 00112 PORT_REQ = 101, 00113 PORT_REQ2 = 102, 00114 PORT_ACK = 103, 00115 PORT_ACK2 = 104, 00116 PORT_NACK = 105, 00117 PORT_NACK2 = 106, 00118 SEND = 107, 00119 SEND2 = 108 00120 }; 00121 00122 // -------------------------------------------------------------------- 00123 // Public method declaration. | 00124 // -------------------------------------------------------------------- 00125 00128 HighwayCluster(): 00129 radio_ ( 0 ), 00130 timer_ ( 0 ), 00131 debug_ ( 0 ), 00132 cluster_ ( 0 ), 00133 discovery_time_ ( 20000 ), 00134 work_period_ ( 50000 ), 00135 clustering_construction_time_ ( 5000 ), 00136 head_offset_ ( 0 ) 00137 { 00138 #ifdef HIGHWAY_METHOD_DEBUG 00139 debug().debug("@@ %d: METHOD CALLED: HighwayCluster()\n", radio().id()); 00140 #endif 00141 }; 00142 00145 ~HighwayCluster(); 00146 00147 00151 int init( Radio& radio, Timer& timer, Clock& clock, Debug& debug, Cluster& cluster, Neighbor& neighbor ); 00152 00156 void enable( void ); 00157 00164 void send( node_id_t receiver, size_t len, block_data_t *data ); 00165 00173 void send( node_id_t receiver, node_id_t port, size_t len, block_data_t *data ); 00174 00179 Node_vect cluster_neighbors(); 00180 00185 Ports_vect ports(node_id_t sid); 00186 00190 template<class T, void (T::*TMethod)(node_id_t, size_t, block_data_t*)> 00191 uint8_t hwy_reg_recv_callback(T *obj_pnt) { 00192 hwy_recv_callback_ = highway_delegate_t::template from_method<T, TMethod > ( obj_pnt ); 00193 return 0; 00194 } 00195 00198 void unreg_hwy_recv_callback() { 00199 hwy_recv_callback_ = highway_delegate_t(); 00200 } 00201 00202 // -------------------------------------------------------------------- 00203 // Setters | 00204 // -------------------------------------------------------------------- 00205 00209 inline void set_discovery_time( millis_t t ) { 00210 discovery_time_ = t; 00211 }; 00212 00216 inline void set_work_period( millis_t t ) { 00217 work_period_ = t; 00218 }; 00219 00223 inline void set_cluster_construction_time( millis_t t ) { 00224 clustering_construction_time_ = t; 00225 }; 00226 00230 inline void set_head_offset( millis_t t ) { 00231 head_offset_ = t; 00232 }; 00233 00234 private: 00235 // Typenaming the underlying modules. 00236 typename Radio::self_pointer_t radio_; 00237 typename Timer::self_pointer_t timer_; 00238 typename Clock::self_pointer_t clock_; 00239 typename Debug::self_pointer_t debug_; 00240 typename Cluster::self_pointer_t cluster_; 00241 typename Neighbor::self_t* neighbor_; 00242 00243 // TODO: Move into the highway_msg class. 00244 struct msg_highway { 00245 uint8_t msg_id, hops; 00246 node_id_t candidate_id, sid_source, sid_target; 00247 }; 00248 00249 inline void set_msg_highway(uint8_t msg_id, uint8_t hops, node_id_t candidate_id, node_id_t sid_source, node_id_t sid_target) { 00250 msg_highway_.msg_id = msg_id; 00251 msg_highway_.hops = hops; 00252 msg_highway_.candidate_id = candidate_id; 00253 msg_highway_.sid_source = sid_source; 00254 msg_highway_.sid_target = sid_target; 00255 } 00256 // End of highway_msg TODO. 00257 00258 00259 // -------------------------------------------------------------------- 00260 // Private variables declaration. | 00261 // -------------------------------------------------------------------- 00262 00263 //TODO: Change into highway_msg class 00264 msg_highway msg_highway_; 00265 00267 millis_t discovery_time_; 00268 00269 // TODO: Fault tolerance and rebuilding should make this deprecated. 00271 millis_t work_period_; 00272 00274 millis_t clustering_construction_time_; 00275 00277 millis_t head_offset_; 00278 00280 int clustering_callback_; 00281 00283 highway_delegate_t hwy_recv_callback_; 00284 00286 node_id_t connected_to; 00287 00289 RoutingTable routing_table_; 00290 00292 HighwayTable highway_table_; 00293 00295 PortsQueue ports_queue_; 00296 00297 //TODO: Check if this three can be moved inside their respective methods. 00299 vector_static<OsModel, Hops_Node_id, MAX_CLUSTER_PORTS -1 > aux; 00300 00302 Node_vect neighbors_; 00303 00305 Ports_vect ports_; 00306 00308 block_data_t buffer_[Radio::MAX_MESSAGE_LENGTH]; 00309 00310 // -------------------------------------------------------------------- 00311 // Private method declaration. | 00312 // -------------------------------------------------------------------- 00313 00317 Radio& radio() { 00318 return *radio_; 00319 } 00320 00324 Timer& timer() { 00325 return *timer_; 00326 } 00327 00331 Clock& clock() { 00332 return *clock_; 00333 } 00334 00338 Debug& debug() { 00339 return *debug_; 00340 } 00341 00345 Cluster& cluster() { 00346 return *cluster_; 00347 } 00348 00352 Neighbor& neighbor() { 00353 return *neighbor_; 00354 } 00355 00360 void start_wrapper(int state); 00361 00365 void start( void *userdata ); 00366 00370 void cluster_discovery( void ); 00371 00379 void neighbor_callback( uint8_t event, node_id_t from, uint8_t len, uint8_t* data); 00380 00386 void discovery_timeout( void *userdata ); 00387 00393 void start_port_negotiation( highway_iterator it, uint8_t n ); 00394 00400 void port_negotiation( node_id_t sid, node_id_t candidate ); 00401 00408 void receive( node_id_t from, size_t len, block_data_t *data ); 00409 00416 void send_to_leader( node_id_t from, size_t len, block_data_t *data ); 00417 00424 void send_away( node_id_t from, size_t len, block_data_t *data ); 00425 00432 void process_send( node_id_t from, size_t len, block_data_t *data ); 00433 00440 void cluster_head_work( node_id_t from, size_t len, block_data_t *data ); 00441 00447 void displacing_push(PQ& pq, Hops_Node_id pin); 00448 00454 Hops_Node_id pop_port(PQ& pq, node_id_t port); 00455 00456 00457 }; // End of class. 00458 00459 // -------------------------------------------------------------------- 00460 // Start of the method code. | 00461 // -------------------------------------------------------------------- 00462 template<typename OsModel_P, 00463 typename RoutingTable_P, 00464 typename Radio_P, 00465 typename Timer_P, 00466 typename Clock_P, 00467 typename Debug_P, 00468 typename Cluster_P, 00469 typename Neighbor_P, 00470 uint16_t MAX_CLUSTERS> 00471 inline int 00472 HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>:: 00473 init( Radio& radio, Timer& timer, Clock& clock, Debug& debug, Cluster& cluster, Neighbor& neighbor ) { 00474 radio_ = &radio; 00475 timer_ = &timer; 00476 clock_ = &clock; 00477 debug_ = &debug; 00478 cluster_ = &cluster; 00479 neighbor_ = &neighbor; 00480 00481 // Initialize the neighborhood discovery module. 00482 ( *neighbor_ ).init( *radio_, *clock_, *timer_, *debug_ ); 00483 return SUCCESS; 00484 } 00485 00486 // -------------------------------------------------------------------- 00487 00488 template<typename OsModel_P, 00489 typename RoutingTable_P, 00490 typename Radio_P, 00491 typename Timer_P, 00492 typename Clock_P, 00493 typename Debug_P, 00494 typename Cluster_P, 00495 typename Neighbor_P, 00496 uint16_t MAX_CLUSTERS> 00497 void 00498 HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>:: 00499 enable( void ) 00500 { 00501 #ifdef HIGHWAY_METHOD_DEBUG 00502 debug().debug( "@@ %d METHOD CALLED: enable()\n", radio().id() ); 00503 #endif 00504 radio().enable_radio(); 00505 radio().template reg_recv_callback<self_type, &self_type::receive>( this ); 00506 cluster().init( radio(), timer(), debug() ); 00507 clustering_callback_ = cluster().template reg_changed_callback<self_type, &self_type::start_wrapper>( this ); 00508 cluster().enable(); 00509 neighbor().enable(); 00510 } 00511 00512 // -------------------------------------------------------------------- 00513 00514 template<typename OsModel_P, 00515 typename RoutingTable_P, 00516 typename Radio_P, 00517 typename Timer_P, 00518 typename Clock_P, 00519 typename Debug_P, 00520 typename Cluster_P, 00521 typename Neighbor_P, 00522 uint16_t MAX_CLUSTERS> 00523 void 00524 HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>:: 00525 send( node_id_t destination, size_t len, block_data_t *data ) 00526 { 00527 #ifdef HIGHWAY_METHOD_DEBUG 00528 debug().debug( "@@ %d METHOD CALLED: send1()\n", radio().id() ); 00529 #endif 00530 #ifdef HIGHWAY_MSG_RECV_DEBUG 00531 debug().debug( "!! data: %d %d\n", data[0], data[1] ); 00532 #endif 00533 send( destination, highway_table_[destination].first.top().second, len, data ); 00534 } 00535 00536 // ----------------------------------------------------------------------- 00537 00538 template<typename OsModel_P, 00539 typename RoutingTable_P, 00540 typename Radio_P, 00541 typename Timer_P, 00542 typename Clock_P, 00543 typename Debug_P, 00544 typename Cluster_P, 00545 typename Neighbor_P, 00546 uint16_t MAX_CLUSTERS> 00547 void 00548 HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>:: 00549 send( node_id_t destination, node_id_t port, size_t len, block_data_t *data ) 00550 { 00551 #ifdef HIGHWAY_METHOD_DEBUG 00552 debug().debug( "@@ %d METHOD CALLED: send_spec()\n", radio().id() ); 00553 #endif 00554 if (len >= Radio::MAX_MESSAGE_LENGTH-3) 00555 { 00556 debug().debug( "@@ %d: ERROR: message too long\n", radio().id() ); 00557 } 00558 00559 buffer_[0] = SEND; 00560 buffer_[1] = destination; 00561 buffer_[2] = port; 00562 buffer_[3] = radio().id(); 00563 00564 #ifdef HIGHWAY_MSG_RECV_DEBUG 00565 debug().debug( "---------------ENCAPSULATING----------------\n" ); 00566 #endif 00567 00568 for (int i = 4; i < ( len+4 ); ++i) 00569 { 00570 buffer_[i] = data[i-4]; 00571 #ifdef HIGHWAY_MSG_RECV_DEBUG 00572 debug().debug( "Data item %d: %d\n", i-4, data[i-4] ); 00573 #endif 00574 } 00575 00576 00577 #ifdef HIGHWAY_MSG_RECV_DEBUG 00578 for (int i = 0; i < len+4; ++i) 00579 { 00580 debug().debug( "Buffer item %d: %d\n", i, buffer_[i] ); 00581 } 00582 #endif 00583 00584 #ifdef HIGHWAY_MSG_RECV_DEBUG 00585 debug().debug( "---------------/ENCAPSULATING----------------\n" ); 00586 #endif 00587 radio().send( routing_table_[port], len+4, buffer_ ); 00588 } 00589 00590 // ----------------------------------------------------------------------- 00591 00592 template<typename OsModel_P, 00593 typename RoutingTable_P, 00594 typename Radio_P, 00595 typename Timer_P, 00596 typename Clock_P, 00597 typename Debug_P, 00598 typename Cluster_P, 00599 typename Neighbor_P, 00600 uint16_t MAX_CLUSTERS> 00601 typename HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>::Node_vect 00602 HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>:: 00603 cluster_neighbors( void ) 00604 { 00605 #ifdef HIGHWAY_METHOD_DEBUG 00606 debug().debug( "@@ %d METHOD CALLED: cluster_neighbors()\n", radio().id() ); 00607 #endif 00608 00609 neighbors_.clear(); 00610 if ( not cluster().cluster_head() ) 00611 { 00612 return neighbors_; 00613 } 00614 00615 highway_iterator it; 00616 for ( it = highway_table_.begin(); it != highway_table_.end(); ++it ) 00617 { 00618 neighbors_.push_back( it->first ); 00619 } 00620 00621 return neighbors_; 00622 } 00623 00624 // ----------------------------------------------------------------------- 00625 00626 template<typename OsModel_P, 00627 typename RoutingTable_P, 00628 typename Radio_P, 00629 typename Timer_P, 00630 typename Clock_P, 00631 typename Debug_P, 00632 typename Cluster_P, 00633 typename Neighbor_P, 00634 uint16_t MAX_CLUSTERS> 00635 typename HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>::Ports_vect 00636 HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>:: 00637 ports( node_id_t sid ) 00638 { 00639 #ifdef HIGHWAY_METHOD_DEBUG 00640 debug().debug( "@@ %d METHOD CALLED: ports()\n", radio().id() ); 00641 #endif 00642 ports_.clear(); 00643 pq_iterator p = highway_table_[sid].first.data(); 00644 for ( int i = 0; i < highway_table_[sid].first.size(); ++i ) 00645 { 00646 ports_.push_back( *p ); 00647 p++; 00648 } 00649 00650 return ports_; 00651 } 00652 00653 // ----------------------------------------------------------------------- 00654 00655 template<typename OsModel_P, 00656 typename RoutingTable_P, 00657 typename Radio_P, 00658 typename Timer_P, 00659 typename Clock_P, 00660 typename Debug_P, 00661 typename Cluster_P, 00662 typename Neighbor_P, 00663 uint16_t MAX_CLUSTERS> 00664 void 00665 HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>:: 00666 start_wrapper( int state ) 00667 { 00668 #ifdef HIGHWAY_METHOD_DEBUG 00669 debug().debug("@@ %d METHOD_CALLED: start_wrapper()\n", radio().id()); 00670 #endif 00671 00672 //TODO: Adapt when cluster stabilization. 00673 if ( state == CLUSTER_FORMED or state == NODE_JOINED ) 00674 { 00675 // When joined to a cluster, unregister listening to cluster events. 00676 cluster().unreg_changed_callback( clustering_callback_ ); 00677 //TODO: Check that this time is needed. 00678 timer().template set_timer<self_type, &self_type::start>( clustering_construction_time_, this, (void *) 0 ); 00679 } 00680 else if ( state == CLUSTER_HEAD_CHANGED or state == NODE_LEFT ) 00681 { 00682 //TODO: FAULT TOLERANCE. Manage this situation 00683 } 00684 } 00685 00686 // ----------------------------------------------------------------------- 00687 00688 template<typename OsModel_P, 00689 typename RoutingTable_P, 00690 typename Radio_P, 00691 typename Timer_P, 00692 typename Clock_P, 00693 typename Debug_P, 00694 typename Cluster_P, 00695 typename Neighbor_P, 00696 uint16_t MAX_CLUSTERS> 00697 void 00698 HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>:: 00699 start( void *userdata ) 00700 { 00701 #ifdef HIGHWAY_METHOD_DEBUG 00702 debug().debug( "@@ %d METHOD CALLED: start(), %d\n", radio().id(), cluster().cluster_head() ); 00703 #endif 00704 00705 if ( not cluster().cluster_head() ) 00706 { 00707 cluster_discovery(); 00708 } 00709 00710 timer().template set_timer<self_type, &self_type::discovery_timeout>( discovery_time_ + ( cluster().cluster_head() ? head_offset_ : 0 ), this, (void *) 0 ); 00711 00712 #ifdef VISOR_DEBUG 00713 debug().debug("$%d->%d$t\n", cluster().parent(), radio().id()); 00714 #endif 00715 } 00716 00717 // ----------------------------------------------------------------------- 00718 00719 template<typename OsModel_P, 00720 typename RoutingTable_P, 00721 typename Radio_P, 00722 typename Timer_P, 00723 typename Clock_P, 00724 typename Debug_P, 00725 typename Cluster_P, 00726 typename Neighbor_P, 00727 uint16_t MAX_CLUSTERS> 00728 void 00729 HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>:: 00730 cluster_discovery( void ) 00731 { 00732 #ifdef HIGHWAY_METHOD_DEBUG 00733 debug().debug( "@@ %d METHOD CALLED: cluster_discovery()\n", radio().id() ); 00734 #endif 00735 00736 // Add the piggybacking information to the neighborhood discovery module. 00737 node_id_t id = cluster().cluster_id(); 00738 uint8_t length; 00739 00740 // Adapt cluster_id to the node_id_t size of the plattform. 00741 #ifdef ISENSE_APP 00742 uint8_t sid_buf[3]; 00743 sid_buf[0] = id & 0xFF; 00744 sid_buf[1] = id >> 8; 00745 sid_buf[2] = cluster().hops(); 00746 length = 3; 00747 #else 00748 uint8_t sid_buf[5]; 00749 sid_buf[0] = id & 0xFF; 00750 sid_buf[1] = ( id >> 8 ) & 0xFF; 00751 sid_buf[2] = ( id >> 16 ) & 0xFF; 00752 sid_buf[3] = ( id >> 24 ) & 0xFF; 00753 sid_buf[4] = cluster().hops(); 00754 length = 5; 00755 #endif 00756 00757 #ifdef HIGHWAY_DEBUG 00758 debug().debug( "@@ Node %d cluster_disc hops: %d\n", radio().id(), cluster().hops() ); 00759 #endif 00760 00761 // Register and add the payload space to the neighborhood discovery module. 00762 if ( neighbor().register_payload_space( HWY_N ) !=0 ) 00763 { 00764 debug().debug( "Error registering payload space\n" ); 00765 } 00766 else if(neighbor().set_payload( HWY_N, sid_buf, length )!=0) { 00767 debug().debug( "Error adding payload\n" ); 00768 } 00769 else 00770 { 00771 uint8_t flags = nb_t::NEW_NB | nb_t::DROPED_NB | nb_t::NEW_PAYLOAD; 00772 neighbor().template reg_event_callback<HighwayCluster,&HighwayCluster::neighbor_callback>( HWY_N, flags, this ); 00773 } 00774 } 00775 00776 // ----------------------------------------------------------------------- 00777 00778 template<typename OsModel_P, 00779 typename RoutingTable_P, 00780 typename Radio_P, 00781 typename Timer_P, 00782 typename Clock_P, 00783 typename Debug_P, 00784 typename Cluster_P, 00785 typename Neighbor_P, 00786 uint16_t MAX_CLUSTERS> 00787 void 00788 HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>:: 00789 neighbor_callback( uint8_t event, node_id_t from, uint8_t len, uint8_t* data) 00790 { 00791 //TODO: Adapt to payload on new_bidi only if Christos changes it. 00792 #ifdef HIGHWAY_METHOD_DEBUG 00793 debug().debug("@@ %d METHOD CALLED: neighbor_callback()\n", radio().id()); 00794 #endif 00795 00796 node_id_t sid; 00797 uint8_t hops; 00798 00799 // On payload event, process the data according to the plattform 00800 if ( nb_t::NEW_PAYLOAD == event ) { 00801 #ifdef ISENSE_APP 00802 sid = ( data[1] << 8 ) | data[0]; 00803 hops = data[2]; 00804 #else 00805 sid = ( data[3] << 24 ) | ( data[2] << 16 ) | ( data[1] << 8 ) | data[0]; 00806 hops = data[4]; 00807 #endif 00808 00809 #ifdef NEIGHBOR_DEBUG 00810 debug_->debug( "@@Node: %d, cluster_id: %d, hops: %d\n", from, sid, hops ); 00811 #endif 00812 // If not cluster leader and the message is from another cluster add it to the highway table of the now to be port candidate. 00813 if ( !cluster().cluster_head() and cluster().cluster_id() != sid and cluster().cluster_id() != -1 ) 00814 { 00815 displacing_push(highway_table_[sid].first, Hops_Node_id(hops + cluster().hops(), from)); 00816 } 00817 00818 } 00819 00820 #ifdef NEIGHBOR_DEBUG 00821 else if ( nb_t::NEW_NB == event ) { 00822 debug_->debug( "NODE %d: event NEW_NB!! new neighbor added %d \n",radio_->id(), from ); 00823 } 00824 else if ( nb_t::NEW_NB_BIDI == event ) { 00825 debug_->debug( "NODE %d: event NEW_NB_BIDI!! new neighbor added %d \n",radio_->id(), from ); 00826 } 00827 #endif 00828 else if ( nb_t::DROPED_NB == event ) { 00829 //TODO: Work on fault tolerance here! 00830 // If the removed node is in the routing_table (it's path to a highway or a port itself) remove it from there and signal the cluster head of the loss. 00831 debug_->debug( "NODE %d: event DROPED_NB!! neighbor added %d \n",radio_->id(), from); 00832 } 00833 } 00834 00835 // ----------------------------------------------------------------------- 00836 00837 template<typename OsModel_P, 00838 typename RoutingTable_P, 00839 typename Radio_P, 00840 typename Timer_P, 00841 typename Clock_P, 00842 typename Debug_P, 00843 typename Cluster_P, 00844 typename Neighbor_P, 00845 uint16_t MAX_CLUSTERS> 00846 void 00847 HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>:: 00848 discovery_timeout( void *userdata ) 00849 { 00850 #ifdef HIGHWAY_METHOD_DEBUG 00851 debug().debug( "@@ %d METHOD CALLED: discovery_timeout()\n", radio().id() ); 00852 #endif 00853 00854 if ( cluster().cluster_head() ) 00855 { 00856 if ( ports_queue_.empty() ) // If no candidacies were presented we will call the same method after a work period. 00857 { 00858 //IMPROVE: Judge the convenience of shortening this wait into fractions of the work period. 00859 timer().template set_timer<self_type, &self_type::discovery_timeout>( work_period_, this, 0 ); 00860 //IMPROVE: Review if this return is needed. 00861 return; 00862 } 00863 else 00864 { 00865 highway_iterator it; 00866 for ( it = ports_queue_.begin(); it != ports_queue_.end(); ++it ) 00867 { 00868 start_port_negotiation( it, 4 ); // The four sets the amount of connectivity. 00869 } 00870 } 00871 } 00872 else 00873 { 00874 highway_iterator it; 00875 for ( it = highway_table_.begin(); it != highway_table_.end(); ++it ) { 00876 //TODO: Adapt to the new highway_msg. 00877 // Create a CANDIDACY highway message with: hops, id->candidate, cluster_id_own, cluster_id_target. 00878 set_msg_highway( CANDIDACY, it->second.first.top().first, radio().id(), cluster().cluster_id(), it->first ); 00879 // Send it to the parent. 00880 radio().send( cluster().parent(), sizeof( msg_highway ), (uint8_t*)&msg_highway_ ); 00881 } 00882 00883 timer().template set_timer<self_type, &self_type::start>( work_period_, this, 0 ); 00884 } 00885 } 00886 00887 // ----------------------------------------------------------------------- 00888 00889 template<typename OsModel_P, 00890 typename RoutingTable_P, 00891 typename Radio_P, 00892 typename Timer_P, 00893 typename Clock_P, 00894 typename Debug_P, 00895 typename Cluster_P, 00896 typename Neighbor_P, 00897 uint16_t MAX_CLUSTERS> 00898 void 00899 HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>:: 00900 start_port_negotiation( highway_iterator it, uint8_t n ) 00901 { 00902 #ifdef HIGHWAY_METHOD_DEBUG 00903 debug().debug("@@ %d METHOD CALLED: start_port_negotiation()\n", radio().id()); 00904 #endif 00905 00906 aux.clear(); 00907 00908 // If there are less candidates than desired connectivity put the available as ceiling. 00909 if ( n > it->second.first.size() ) 00910 { 00911 n = it->second.first.size(); 00912 } 00913 00914 // Put max(n, size) elements into the aux vector. 00915 for ( int i = 0; i < n; ++i ) 00916 { 00917 aux.push_back( it->second.first.pop() ); 00918 } 00919 00920 // Negotiate all the port candidates in aux. 00921 for ( int i = 0; i < n; ++i ) 00922 { 00923 port_negotiation( it->first, aux[i].second ); 00924 } 00925 00926 // Put back the the port candidates. 00927 for ( int i = 0; i < n; ++i ) 00928 { 00929 it->second.first.push( aux[i] ); 00930 } 00931 00932 aux.clear(); 00933 } 00934 00935 // ----------------------------------------------------------------------- 00936 00937 template<typename OsModel_P, 00938 typename RoutingTable_P, 00939 typename Radio_P, 00940 typename Timer_P, 00941 typename Clock_P, 00942 typename Debug_P, 00943 typename Cluster_P, 00944 typename Neighbor_P, 00945 uint16_t MAX_CLUSTERS> 00946 void 00947 HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>:: 00948 port_negotiation( node_id_t sid, node_id_t candidate ) 00949 { 00950 #ifdef HIGHWAY_METHOD_DEBUG 00951 debug().debug( "@@ %d METHOD_CALLED: port_negotiation()\n", radio().id() ); 00952 #endif 00953 00954 //TODO: Adapt to highway_msg class. 00955 // Create the highway_msg to request the other cluster a new connection. 00956 set_msg_highway( PORT_REQ, msg_highway_.hops, candidate, cluster().cluster_id(), sid ); 00957 00958 // Send the highway_msg to the first node in the path to candidate. 00959 radio().send( routing_table_[candidate], sizeof( msg_highway ), (uint8_t*)&msg_highway_ ); 00960 } 00961 00962 // ----------------------------------------------------------------------- 00963 00964 template<typename OsModel_P, 00965 typename RoutingTable_P, 00966 typename Radio_P, 00967 typename Timer_P, 00968 typename Clock_P, 00969 typename Debug_P, 00970 typename Cluster_P, 00971 typename Neighbor_P, 00972 uint16_t MAX_CLUSTERS> 00973 void 00974 HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>:: 00975 receive( node_id_t from, size_t len, block_data_t *data ) 00976 { 00977 #ifdef HIGHWAY_METHOD_DEBUGG 00978 debug().debug("@@ %d METHOD_CALLED: receive()\n", radio().id()); 00979 #endif 00980 // Ignore if heard oneself's message. 00981 if ( from == radio().id() ) 00982 { 00983 return; 00984 } 00985 00986 #ifdef HIGHWAY_MSG_RECV_DEBUG 00987 if ( *data == CANDIDACY ) debug().debug( "@@ %d<- %d: MSG_RECEIVED: CANDIDACY\n", radio().id(), from ); 00988 else if ( *data == PORT_REQ ) debug().debug( "@@ %d<- %d: MSG_RECEIVED: PORT_REQ\n", radio().id(), from ); 00989 else if ( *data == PORT_REQ2 ) debug().debug( "@@ %d<- %d: MSG_RECEIVED: PORT_REQ2\n", radio().id(), from ); 00990 else if ( *data == PORT_ACK ) debug().debug( "@@ %d<- %d: MSG_RECEIVED: PORT_ACK\n", radio().id(), from ); 00991 else if ( *data == PORT_ACK2 ) debug().debug( "@@ %d<- %d: MSG_RECEIVED: PORT_ACK2\n", radio().id(), from ); 00992 else if ( *data == PORT_NACK ) debug().debug( "@@ %d<- %d: MSG_RECEIVED: PORT_NACK\n", radio().id(), from ); 00993 else if ( *data == PORT_NACK2 ) debug().debug( "@@ %d<- %d: MSG_RECEIVED: PORT_NACK2\n", radio().id(), from ); 00994 else if ( *data == SEND ) debug().debug( "@@ %d<- %d: MSG_RECEIVED: SEND\n", radio().id(), from ); 00995 else if ( *data == SEND2 ) debug().debug( "@@ %d<- %d: MSG_RECEIVED: SEND2\n", radio().id(), from ); 00996 #endif 00997 00998 // Messages travelling to the current node cluster leader are processed in send_to_leader 00999 if ( *data == CANDIDACY or *data == PORT_REQ2 or *data == PORT_ACK2 or *data == PORT_NACK2 or *data == SEND2 ) 01000 { 01001 send_to_leader( from, len, data ); 01002 } 01003 else if ( *data == PORT_REQ or *data == PORT_ACK or *data == PORT_NACK ) // Construction messages travelling outwards 01004 { 01005 send_away( from, len, data ); 01006 } 01007 else if ( *data == SEND) // Data messages travelling outwards. 01008 { 01009 process_send( from, len, data ); 01010 } 01011 } 01012 01013 // ----------------------------------------------------------------------- 01014 01015 template<typename OsModel_P, 01016 typename RoutingTable_P, 01017 typename Radio_P, 01018 typename Timer_P, 01019 typename Clock_P, 01020 typename Debug_P, 01021 typename Cluster_P, 01022 typename Neighbor_P, 01023 uint16_t MAX_CLUSTERS> 01024 void 01025 HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>:: 01026 send_to_leader( node_id_t from, size_t len, block_data_t *data ) 01027 { 01028 #ifdef HIGHWAY_METHOD_DEBUG 01029 debug().debug( "@@ %d METHOD_CALLED: send_to_leader()\n", radio().id()) ; 01030 #endif 01031 01032 #ifdef HIGHWAY_MSG_RECV_DEBUG 01033 if( *data == SEND2 ) 01034 { 01035 debug().debug( "---------------SENDRECV2--------------\n" ); 01036 for( int i = 0; i<len; ++i ) 01037 debug().debug( "Data[%d]: %d\n", i, data[i] ); 01038 debug().debug( "---------------/SENDRECV2--------------\n" ); 01039 } 01040 #endif 01041 01042 msg_highway_ = * ((msg_highway * ) data); 01043 01044 if ( *data == CANDIDACY or *data == PORT_REQ2 ) 01045 { 01046 routing_table_[msg_highway_.candidate_id] = from; 01047 } 01048 else if ( *data == PORT_ACK2 ) 01049 { 01050 #ifdef VISOR_DEBUG 01051 debug().debug( "$%d->%d$h\n", from, radio_->id() ); 01052 #endif 01053 } 01054 01055 if ( cluster().cluster_head() ) 01056 { 01057 cluster_head_work( from, len, data ); 01058 } 01059 else 01060 { 01061 radio().send( cluster().parent(), len, data ); 01062 } 01063 } 01064 01065 // ----------------------------------------------------------------------- 01066 01067 template<typename OsModel_P, 01068 typename RoutingTable_P, 01069 typename Radio_P, 01070 typename Timer_P, 01071 typename Clock_P, 01072 typename Debug_P, 01073 typename Cluster_P, 01074 typename Neighbor_P, 01075 uint16_t MAX_CLUSTERS> 01076 void 01077 HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>:: 01078 send_away( node_id_t from, size_t len, block_data_t *data ) 01079 { 01080 #ifdef HIGHWAY_METHOD_DEBUGG 01081 debug().debug("@@ %d METHOD_CALLED: send_away()\n", radio().id()); 01082 #endif 01083 01084 #ifdef VISOR_DEBUG 01085 if( *data == PORT_ACK ) 01086 debug().debug("$%d->%d$h\n", from, radio_->id()); 01087 #endif 01088 01089 msg_highway_ = * ((msg_highway * ) data); 01090 01091 // Check if we are still in the cluster that originated the request. 01092 if ( from == cluster().parent() ) 01093 { 01094 // If the current node is not the port, continue the way to the port. 01095 if ( msg_highway_.candidate_id != radio().id() ) 01096 { 01097 radio().send( routing_table_[msg_highway_.candidate_id], sizeof( msg_highway ), data ); 01098 } 01099 else // Send the message o the other cluster port and set connected_to. 01100 { 01101 if ( *data == PORT_REQ ) 01102 { 01103 radio().send( highway_table_[msg_highway_.sid_target].first.top().second, sizeof( msg_highway ), data ); 01104 } 01105 else if ( *data == PORT_ACK ) { 01106 connected_to = routing_table_[msg_highway_.sid_source]; 01107 radio().send( connected_to, sizeof( msg_highway ), data ); 01108 } 01109 else //NACK 01110 { 01111 radio().send( routing_table_[msg_highway_.sid_source], sizeof( msg_highway ), data ); 01112 routing_table_.erase( routing_table_.find(msg_highway_.sid_source) ); 01113 } 01114 } 01115 } 01116 else // Create a "2" message. 01117 { 01118 if ( *data == PORT_REQ ) 01119 { 01120 msg_highway_.msg_id = PORT_REQ2; 01121 routing_table_[msg_highway_.sid_source] = from; 01122 msg_highway_.candidate_id = radio().id(); 01123 } 01124 else if ( *data == PORT_ACK ) { 01125 #ifdef VISOR_DEBUG 01126 debug().debug( "+%d#%d#0#1\n", radio().id(), cluster().cluster_id() ); 01127 debug().debug( "+%d#%d#0#1\n", from, msg_highway_.sid_target ); 01128 #endif 01129 msg_highway_.msg_id = PORT_ACK2; 01130 connected_to = from; 01131 01132 } 01133 else //NACK 01134 { 01135 msg_highway_.msg_id = PORT_NACK2; 01136 msg_highway_.candidate_id = radio().id(); 01137 } 01138 01139 msg_highway_.candidate_id = radio().id(); 01140 radio().send( cluster().parent(), sizeof( msg_highway ), (uint8_t *)&msg_highway_ ); 01141 } 01142 } 01143 01144 // ----------------------------------------------------------------------- 01145 01146 template<typename OsModel_P, 01147 typename RoutingTable_P, 01148 typename Radio_P, 01149 typename Timer_P, 01150 typename Clock_P, 01151 typename Debug_P, 01152 typename Cluster_P, 01153 typename Neighbor_P, 01154 uint16_t MAX_CLUSTERS> 01155 void 01156 HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>:: 01157 process_send( node_id_t from, size_t len, block_data_t *data ) 01158 { 01159 #ifdef HIGHWAY_METHOD_DEBUGG 01160 debug().debug("@@ %d METHOD_CALLED: send_process()\n", radio().id()); 01161 #endif 01162 01163 #ifdef HIGHWAY_MSG_RECV_DEBUG 01164 debug().debug("---------------SENDRECV--------------\n"); 01165 for(int i = 0; i<len; ++i) 01166 debug().debug("Data[%d]: %d\n", i, data[i]); 01167 debug().debug("---------------/SENDRECV--------------\n"); 01168 #endif 01169 01170 // Check if we are still in the cluster that originated the request. 01171 if ( from == cluster().parent() ) 01172 { 01173 // If the current node is not the port, continue the way to the port. 01174 if ( data[2] != radio().id() ) 01175 { 01176 radio().send( routing_table_[data[2]], len, data ); 01177 } 01178 else // Send the message o the other cluster port and set connected_to. 01179 { 01180 radio().send( connected_to, len, data ); 01181 } 01182 } 01183 else // Create a SEND2 message. 01184 { 01185 *data = SEND2; 01186 radio().send( cluster().parent(), len, data ); 01187 } 01188 } 01189 01190 // ----------------------------------------------------------------------- 01191 01192 template<typename OsModel_P, 01193 typename RoutingTable_P, 01194 typename Radio_P, 01195 typename Timer_P, 01196 typename Clock_P, 01197 typename Debug_P, 01198 typename Cluster_P, 01199 typename Neighbor_P, 01200 uint16_t MAX_CLUSTERS> 01201 void 01202 HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>:: 01203 cluster_head_work( node_id_t from, size_t len, block_data_t *data ) 01204 { 01205 #ifdef HIGHWAY_METHOD_DEBUG 01206 debug().debug("@@ %d METHOD_CALLED: cluster_head_work()\n", radio().id()); 01207 #endif 01208 msg_highway_ = *((msg_highway * ) data); 01209 01210 if ( *data == CANDIDACY ) // Add the port candidate to the queue. 01211 { 01212 displacing_push( ports_queue_[msg_highway_.sid_target].first, Hops_Node_id( msg_highway_.hops, msg_highway_.candidate_id ) ); 01213 } 01214 else if ( *data == PORT_REQ2 ) // Accept or reject the highway request. 01215 { 01216 if (highway_table_[msg_highway_.sid_source].first.size() < 4) 01217 { 01218 displacing_push( highway_table_[msg_highway_.sid_source].first, Hops_Node_id( msg_highway_.hops, msg_highway_.candidate_id ) ); 01219 highway_table_[msg_highway_.sid_source].second = 0; 01220 msg_highway_.msg_id = PORT_ACK; 01221 } 01222 else //IMPROVE: extra NACK conditions. 01223 { 01224 msg_highway_.msg_id = PORT_NACK; 01225 } 01226 radio().send( from, sizeof( msg_highway ), (uint8_t *)&msg_highway_ ); 01227 } 01228 else if ( msg_highway_.msg_id == PORT_ACK2 ) // Establish the port. 01229 { 01230 displacing_push( highway_table_[msg_highway_.sid_target].first, pop_port( ports_queue_[msg_highway_.sid_target].first, msg_highway_.candidate_id ) ); 01231 highway_table_[msg_highway_.sid_target].second = 0; 01232 } 01233 else if ( msg_highway_.msg_id == PORT_NACK2 ) // Remove the port candidate. 01234 { 01235 pop_port( ports_queue_[msg_highway_.sid_target].first, msg_highway_.candidate_id ); 01236 } 01237 else if ( *data == SEND2 ) // Call the registered (if exists) receiving method. 01238 { 01239 #ifdef HIGHWAY_MSG_RECV_DEBUG 01240 debug().debug( "---------------HEAD_WORK_RECV--------------\n" ); 01241 for( int i = 0; i<len; ++i ) 01242 debug().debug( "Data[%d]: %d\n", i, data[i] ); 01243 debug().debug( "---------------HEAD_WORK_RECV--------------\n" ); 01244 #endif 01245 01246 if( hwy_recv_callback_ ) hwy_recv_callback_((node_id_t)data[3], len-4, &data[4]); 01247 } 01248 } 01249 01250 // ----------------------------------------------------------------------- 01251 // Queue and other helper methods. | 01252 // ----------------------------------------------------------------------- 01253 01254 template<typename OsModel_P, 01255 typename RoutingTable_P, 01256 typename Radio_P, 01257 typename Timer_P, 01258 typename Clock_P, 01259 typename Debug_P, 01260 typename Cluster_P, 01261 typename Neighbor_P, 01262 uint16_t MAX_CLUSTERS> 01263 void 01264 HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>:: 01265 displacing_push( PQ& pq, Hops_Node_id pin ) 01266 { 01267 #ifdef HIGHWAY_METHOD_DEBUG 01268 debug().debug("@@ %d METHOD_CALLED: displacing_push()\n", radio().id()); 01269 #endif 01270 if ( pq.size() < MAX_CLUSTER_PORTS ) 01271 { 01272 pq.push( pin ); 01273 return; 01274 } 01275 01276 aux.clear(); 01277 01278 for ( int i = 0; i < MAX_CLUSTER_PORTS-1; ++i ) 01279 { 01280 aux.push_back( pq.pop() ); 01281 } 01282 01283 if ( pin < pq.top() ) 01284 { 01285 pq.pop(); 01286 pq.push( pin ); 01287 } 01288 01289 for ( int i = 0; i < MAX_CLUSTER_PORTS-1; ++i ) 01290 { 01291 pq.push( aux[aux.size()-1] ); 01292 aux.pop_back(); 01293 } 01294 } 01295 01296 // ----------------------------------------------------------------------- 01297 01298 template<typename OsModel_P, 01299 typename RoutingTable_P, 01300 typename Radio_P, 01301 typename Timer_P, 01302 typename Clock_P, 01303 typename Debug_P, 01304 typename Cluster_P, 01305 typename Neighbor_P, 01306 uint16_t MAX_CLUSTERS> 01307 typename HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>::Hops_Node_id 01308 HighwayCluster<OsModel_P, RoutingTable_P, Radio_P, Timer_P, Clock_P, Debug_P, Cluster_P, Neighbor_P, MAX_CLUSTERS>:: 01309 pop_port( PQ& pq, node_id_t port ) 01310 { 01311 #ifdef HIGHWAY_METHOD_DEBUG 01312 debug().debug( "@@ %d METHOD_CALLED: pop_port()\n", radio().id() ); 01313 #endif 01314 aux.clear(); 01315 Hops_Node_id ret; 01316 for ( int i = 0; i < MAX_CLUSTER_PORTS; ++i ) 01317 { 01318 if ( pq.top().second != port ) 01319 { 01320 aux.push_back( pq.pop() ); 01321 } 01322 else 01323 { 01324 ret = pq.top(); 01325 } 01326 } 01327 01328 for ( uint16_t i = 0; i < aux.size(); ++i ) 01329 { 01330 pq.push(aux[i]); 01331 } 01332 01333 return ret; 01334 } 01335 } 01336 #endif