Wiselib
wiselib.testing/algorithms/cluster/dfscluster/dfsclustering.h
Go to the documentation of this file.
00001 #ifndef _DFSCLUSTERING_H
00002 #define  _DFSCLUSTERING_H
00003 
00004 #include "util/delegates/delegate.hpp"
00005 #include "util/pstl/vector_static.h"
00006 #include "algorithms/cluster/clustering_types.h"
00007 #include <stack>
00008 
00009 #undef DEBUG
00010 #define DEBUG
00011 
00012 
00013 namespace wiselib {    
00014   
00022     template<typename OsModel_P,
00023     typename Radio_P,
00024     typename Timer_P,
00025     typename Debug_P>
00026 
00027     class DfsClustering {
00028     public:
00029 
00030         //TYPEDEFS
00031         typedef OsModel_P OsModel;
00032         typedef Radio_P Radio;
00033         typedef Timer_P Timer;
00034         typedef Debug_P Debug;
00035         typedef DfsClustering<OsModel_P, Radio_P, Timer_P, Debug_P> self_t;
00036 
00037         //data types
00038         typedef int cluster_id_t;
00039         typedef int cluster_level_t; //quite useless within current scheme, supported for compatibility issues
00040         typedef typename Radio::node_id_t node_id_t;
00041         typedef typename Radio::size_t size_t;
00042         typedef typename Radio::block_data_t block_data_t;
00043         typedef wiselib::vector_static<OsModel, node_id_t, 200 > vector_t;
00044 
00045         //delegates
00046         typedef delegate1<void, int> cluster_delegate_t;
00047 
00048 
00049         /* SET functions */
00050 
00051         //set the clustering parameter
00052 
00053         void set_theta(int theta) {
00054             theta_ = theta;
00055         }
00056 
00057         /* GET functions */
00058 
00059         //get the cluster level
00060 
00061         cluster_level_t cluster_level() {
00062             return 0;
00063         }
00064 
00065         //get the cluster id
00066 
00067         cluster_id_t cluster_id() {
00068             return SID_;
00069         }
00070 
00071         //get if cluster head
00072 
00073         bool cluster_head() {
00074             return cluster_head_;
00075         }
00076 
00077         //get the parent
00078 
00079         node_id_t parent() {
00080             return parent_;
00081         }
00082 
00083         //get hops from cluster head
00084 
00085         size_t hops() {
00086             return hops_;
00087         }
00088 
00089         /* CALLBACKS */
00090 
00091         template<class T, void (T::*TMethod)(int) >
00092         inline int reg_changed_callback(T *obj_pnt) {
00093             state_changed_callback_ = cluster_delegate_t::from_method<T, TMethod > (obj_pnt);
00094             return state_changed_callback_;
00095         }
00096 
00097         void unreg_changed_callback(int idx) {
00098             state_changed_callback_ = cluster_delegate_t();
00099         }
00100 
00101         /* SHOW all the known nodes */
00102 #ifdef DEBUG
00103 
00104         void present_neighbors() {
00105 #ifndef ISENSE_APP
00106             debug().debug("Present Node %d Neighbors:\n", radio().id());
00107             debug().debug("Cluster: ");
00108             for (size_t i = 0; i < cluster_neighbors_.size(); i++) {
00109                 debug().debug("%d ", cluster_neighbors_.at(i));
00110             }
00111             debug().debug("\nNon-Cluster: ");
00112             for (size_t i = 0; i < non_cluster_neighbors_.size(); i++) {
00113                 debug().debug("%d ", non_cluster_neighbors_.at(i));
00114             }
00115             debug().debug("\n");
00116 #else
00117             debug().debug("Present Node %x Neighbors:", radio().id());
00118             debug().debug("Cluster: ");
00119             for (size_t i = 0; i < cluster_neighbors_.size(); i++) {
00120                 debug().debug("%x ", cluster_neighbors_.at(i));
00121             }
00122             debug().debug("Non-Cluster: ");
00123             for (size_t i = 0; i < non_cluster_neighbors_.size(); i++) {
00124                 debug().debug("%x ", non_cluster_neighbors_.at(i));
00125             }
00126 
00127 #endif
00128 
00129         }
00130 #endif
00131 
00132 #ifdef DEBUG
00133         int mess_join_req() {
00134             return mess_join_req_;
00135         };
00136 
00137         int mess_join_deny() {
00138             return mess_join_deny_;
00139         };
00140 
00141         int mess_resume() {
00142             return mess_resume_;
00143         };
00144 
00145         int mess_neighbor_discovery() {
00146             return mess_neighbor_discovery_;
00147         };
00148 
00149         int mess_neighbor_reply() {
00150             return mess_neighbor_reply_;
00151         };
00152 #endif
00153         /*
00154          * Enable
00155          * enables the dfsclustering module
00156          * initializes values
00157          * registers callbacks
00158          * and starts the
00159          * clustering procedure
00160          * */
00161         void enable(void);
00162         /*
00163          * Disable
00164          * disables the bfsclustering module
00165          * unregisters callbacks
00166          * */
00167         void disable(void);
00168 
00169         /*
00170          * Constructor
00171          * */
00172         DfsClustering() :
00173         cluster_head_(false),
00174         SID_(-1),
00175         parent_(-1),
00176         theta_(30),
00177         hops_(0)
00178         {
00179             cluster_neighbors_.clear();
00180             non_cluster_neighbors_.clear();
00181 
00182         }
00183 
00184         /*
00185          * Destructor
00186          * */
00187         ~DfsClustering() {
00188         }
00190 
00191         /*
00192          * INIT
00193          * initializes the values of radio timer and debug
00194          */
00195         void init(Radio& radio, Timer& timer, Debug& debug) {
00196             radio_ = &radio;
00197             timer_ = &timer;
00198             debug_ = &debug;
00199         };
00200 
00201     protected:
00202         /*
00203          * DISCOVER_NEIGHBORS
00204          * sends a message to
00205          * start neighbor discovery
00206          * and sets timer to send a neighbor request message
00207          * */
00208         void discover_neighbors();
00209         /*
00210          * TIMER_EXPIRED
00211          * if any nodes responded to neighbor discovery
00212          * sends a new neighbor request message
00213          * */
00214         void timer_expired(void*);
00215         /*
00216          * RECEIVE
00217          * respond to the new messages received
00218          * callback from the radio
00219          * */
00220         void receive(node_id_t receiver, size_t len, block_data_t *data);
00221 
00222     private:
00223         bool cluster_head_; // if a cluster head
00224         cluster_id_t SID_; // the node's cluster id
00225         int callback_id_; // received messages callback       
00226         cluster_delegate_t state_changed_callback_; // callback to the processor
00227         vector_t neighbors_; // contains the neighbors
00228         vector_t cluster_neighbors_, non_cluster_neighbors_;
00229         node_id_t parent_; //parent of the node
00230         static const int time_slice_ = 2000; // timeout to receive neighbor replies
00231         int theta_; // clustering parameter
00232         size_t hops_; // hops from head
00233 
00234 
00235 #ifdef DEBUG
00236         int mess_neighbor_discovery_;
00237         int mess_neighbor_reply_;
00238         int mess_join_req_;
00239         int mess_join_deny_;
00240         int mess_resume_;
00241 
00242         void reset_mess_counters() {
00243             mess_neighbor_discovery_ = 0;
00244             mess_neighbor_reply_ = 0;
00245             mess_join_req_ = 0;
00246             mess_join_deny_ = 0;
00247             mess_resume_ = 0;
00248         }
00249 #endif
00250 
00251         Radio * radio_; //radio module
00252         Timer * timer_; //timer module
00253         Debug * debug_; //debug module
00254 
00255         Radio& radio() {
00256             return *radio_;
00257         }
00258 
00259         Timer& timer() {
00260             return *timer_;
00261         }
00262 
00263         Debug& debug() {
00264             return *debug_;
00265         }
00266 
00267     };
00268 
00269     template<typename OsModel_P,
00270     typename Radio_P,
00271     typename Timer_P,
00272     typename Debug_P>
00273     void
00274     DfsClustering<OsModel_P, Radio_P, Timer_P, Debug_P>::
00275     enable(void) {
00276 #ifdef DEBUG
00277 #ifndef ISENSE_APP
00278         debug().debug("DFSClustering ENABLED %d\n", radio().id());
00279 #else
00280         debug().debug("DFSClustering ENABLED %x", radio().id());
00281 #endif
00282 #endif
00283         //initilize the variables
00284         SID_ = -1;
00285         cluster_head_ = false;
00286         hops_ = 0;
00287         parent_ = -1;
00288 
00289         
00290 
00291 #ifdef DEBUG
00292         reset_mess_counters();
00293 #endif
00294         //enable the radio
00295         radio().enable_radio();
00296 
00297         //register receive to radio
00298         callback_id_ = radio().template reg_recv_callback<self_t,
00299                 &self_t::receive > (this);
00300 
00301         //-> Cluster Head Decision
00302         if (radio().id() % theta_ == 0) {
00303             cluster_head_ = true;
00304         } else {
00305             cluster_head_ = false;
00306         }
00307 
00308         // if a cluster head
00309         if (cluster_head_) {
00310             //I am cluster_head, set SID_ to id and discover_neighbors
00311             SID_ = radio().id();
00312             parent_ = radio().id();
00313             hops_ = 0;
00314             if (state_changed_callback_) state_changed_callback_(CLUSTER_HEAD_CHANGED);
00315             
00316             discover_neighbors();
00317         }
00318 
00319     }
00320 
00321     template<typename OsModel_P,
00322     typename Radio_P,
00323     typename Timer_P,
00324     typename Debug_P>
00325     void
00326     DfsClustering<OsModel_P, Radio_P, Timer_P, Debug_P>::
00327     disable(void) {
00328 
00329 #ifdef DEBUG
00330 #ifndef ISENSE_APP
00331         debug().debug("DFSClustering Disabled! Node %d\n", radio().id());
00332 #else
00333         debug().debug("DFSClustering Disabled! Node %x", radio().id());
00334 #endif
00335 #endif
00336         radio().unreg_recv_callback(callback_id_);
00337 
00338     }
00339 
00340     template<typename OsModel_P,
00341     typename Radio_P,
00342     typename Timer_P,
00343     typename Debug_P>
00344     void
00345     DfsClustering<OsModel_P, Radio_P, Timer_P, Debug_P>::
00346     discover_neighbors(void) {
00347 #ifdef DEBUG
00348 #ifndef ISENSE_APP
00349         debug().debug("DFSClustering called discover neighbors! Node %d,cluster_head_=%d\n", radio().id(), cluster_head_);
00350 #else
00351         debug().debug("DFSClustering called discover neighbors! Node %x,cluster_head_=%d", radio().id(), cluster_head_);
00352 #endif
00353 #endif
00354         //NEIGHBOR_DISCOVERY MESSAGE
00355 #ifdef ISENSE_APP
00356         debug().debug("START 2");
00357 #endif
00358         block_data_t msg = NEIGHBOR_DISCOVERY;
00359         radio().send(Radio::BROADCAST_ADDRESS, 1, &msg);
00360 #ifdef ISENSE_APP
00361         debug().debug("STOP 2");
00362 #endif
00363 
00364         neighbors_.clear();
00365 #ifdef DEBUG
00366 #ifndef ISENSE_APP
00367         debug().debug("SEND NEIGHBOR_DISCOVERY Node %d\n", radio().id());
00368 #else
00369         debug().debug("SEND NEIGHBOR_DISCOVERY Node %x", radio().id());
00370 #endif
00371         //increase the message counter
00372         mess_neighbor_discovery_++;
00373 #endif
00374         //set timer to wait for responds to neighbor discovery
00375         timer().template set_timer<self_t,
00376                 &self_t::timer_expired > (time_slice_, this, (void*) 0);
00377     }
00378 
00379     template<typename OsModel_P,
00380     typename Radio_P,
00381     typename Timer_P,
00382     typename Debug_P>
00383 
00384     void
00385     DfsClustering<OsModel_P, Radio_P, Timer_P, Debug_P>::
00386     timer_expired(void* data) {
00387 #ifdef DEBUG
00388 #ifndef ISENSE_APP
00389         debug().debug("DFSClustering timer Expired! Node %d,%d\n", radio().id(), cluster_head_);
00390 #else
00391         debug().debug("DFSClustering timer Expired! Node %x,%d", radio().id(), cluster_head_);
00392 #endif
00393 #endif
00394 
00395         // if no more neighbors exist
00396         if (neighbors_.empty()) {
00397             // if not a head
00398             if (!cluster_head_) {
00399                 //send a RESUME message
00400                 block_data_t msg = RESUME;
00401                 //do send the message
00402                 radio().send(parent_, 1, &msg);
00403 #ifdef DEBUG
00404 #ifndef ISENSE_APP
00405                 debug().debug("SEND RESUME %d -> %d\n", radio().id(), parent_);
00406 #else
00407                 debug().debug("SEND RESUME %x -> %x", radio().id(), parent_);
00408 #endif
00409                 //increase the message counter
00410                 mess_resume_++;
00411 #endif
00412             } else {
00413                 if (state_changed_callback_) state_changed_callback_(CLUSTER_FORMED);
00414                 
00415 #ifdef DEBUG
00416 #ifndef ISENSE_APP
00417                 debug().debug("CLUSTER FORMED %d \n", radio().id());
00418 #else
00419                 debug().debug("CLUSTER FORMED %x", radio().id());
00420 #endif
00421 #endif
00422 
00423             }
00424         }//if more neighbors
00425         else {
00426             //get a neighbor
00427             node_id_t dest = neighbors_.back();
00428 
00429             // remove from neighbors
00430             neighbors_.pop_back();
00431             //send a JOIN_REQUEST message
00432             block_data_t msg[4] = {JOIN_REQUEST, SID_ / 256, SID_ % 256, hops_};
00433             //do send the message
00434             radio().send(dest, 4, msg);
00435 
00436 #ifdef DEBUG
00437 #ifndef ISENSE_APP
00438             debug().debug("SEND JOIN_REQUEST %d -> %d cluster= %d \n", radio().id(), dest, SID_);
00439 #else
00440             debug().debug("SEND JOIN_REQUEST %x -> %x cluster= %x ", radio().id(), dest, SID_);
00441 #endif
00442             //increase the message counter
00443             mess_join_req_++;
00444 #endif
00445         }
00446     }
00447 
00448     template<typename OsModel_P,
00449     typename Radio_P,
00450     typename Timer_P,
00451     typename Debug_P>
00452     void
00453     DfsClustering<OsModel_P, Radio_P, Timer_P, Debug_P>::
00454     receive(node_id_t from, size_t len, block_data_t* data) {
00455 
00456         // if own message ignore it
00457         if (from == radio().id()) return;
00458 
00459         //if a NEIGHBOR_DISCOVERY message
00460         if (*data == NEIGHBOR_DISCOVERY) {
00461 #ifdef DEBUG
00462 #ifndef ISENSE_APP
00463             debug().debug("RECEIVED NEIGHBOR_DISCOVERY %d <- %d\n", radio().id(), from);
00464 #else
00465             debug().debug("RECEIVED NEIGHBOR_DISCOVERY %x <- %x", radio().id(), from);
00466 #endif
00467 #endif
00468 
00469             // if not clustered yet
00470             if (SID_ == -1) {
00471                 //create a reply
00472                 block_data_t m_hd = NEIGHBOR_REPLY;
00473                 //do send the reply
00474                 radio().send(from, 1, &m_hd);
00475 
00476 #ifdef DEBUG
00477 #ifndef ISENSE_APP
00478                 debug().debug("SEND NEIGHBOR_REPLY %d -> %d\n", radio().id(), from);
00479 #else
00480                 debug().debug("SEND NEIGHBOR_REPLY %x -> %x", radio().id(), from);
00481 #endif
00482                 //increase the message counter
00483                 mess_neighbor_reply_++;
00484 #endif
00485             }
00486         } else if (*data == NEIGHBOR_REPLY) {
00487 #ifdef DEBUG
00488 #ifndef ISENSE_APP
00489             debug().debug("RECEIVED NEIGHBOR_REPLY %d <- %d \n", radio().id(), from);
00490 #else
00491             debug().debug("RECEIVED NEIGHBOR_REPLY %x <- %x", radio().id(), from);
00492 #endif
00493 #endif
00494             //add sender to neighbors
00495             neighbors_.push_back(from);
00496         } else if (*data == JOIN_REQUEST) {
00497 #ifdef DEBUG
00498 #ifndef ISENSE_APP
00499             debug().debug("RECEIVED JOIN_REQUEST %d <- %d \n", radio().id(), from);
00500 #else
00501             debug().debug("RECEIVED JOIN_REQUEST %x <- %x", radio().id(), from);
00502 #endif
00503 #endif
00504             //if not clustered yet
00505             if (SID_ == -1) {
00506                 //JOIN the cluster
00507                 parent_ = from;
00508                 SID_ = data[1]*256 + data[2];
00509                 hops_ = data[3] + 1;
00510                 //inform the processor
00511                 if (state_changed_callback_) state_changed_callback_(NODE_JOINED);
00512                 
00513                 //discover own neighbors
00514                 discover_neighbors();
00515             } else {
00516                 //create a deny message
00517                 block_data_t msg = JOIN_DENY;
00518                 //do send the message
00519                 radio().send(from, 1, &msg);
00520 #ifdef DEBUG
00521 #ifndef ISENSE_APP
00522                 debug().debug("SEND JOIN_DENY %d -> %d \n", radio().id(), from);
00523 #else
00524                 debug().debug("SEND JOIN_DENY %x -> %x", radio().id(), from);
00525 #endif
00526                 //increase the message counter
00527                 mess_join_deny_++;
00528 #endif
00529             }
00530         } else if (*data == JOIN_DENY) {
00531 #ifdef DEBUG
00532 #ifndef ISENSE_APP
00533             debug().debug("RECEIVED JOIN_DENY %d <- %d \n", radio().id(), from);
00534 #else
00535             debug().debug("RECEIVED JOIN_DENY %x <- %x", radio().id(), from);
00536 #endif
00537 #endif
00538             //check neighbors
00539             discover_neighbors();
00540         } else if (*data == RESUME) {
00541 #ifdef DEBUG
00542 #ifndef ISENSE_APP
00543             debug().debug("RECEIVED RESUME %d <- %d \n", radio().id(), from);
00544 #else
00545             debug().debug("RECEIVED RESUME %x <- %x", radio().id(), from);
00546 #endif
00547 #endif
00548             // check neighbors
00549             discover_neighbors();
00550         }
00551     }
00552 }
00553 #endif
00554 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines