#include <landmark.h>
Inheritance diagram for PromotionTimer:


Public Types | |
| enum | TimerStatus { TIMER_IDLE, TIMER_PENDING, TIMER_HANDLING } |
Public Member Functions | |
| PromotionTimer (LandmarkAgent *a) | |
| void | sched (double delay) |
| void | resched (double delay) |
| void | cancel () |
| void | force_cancel () |
| int | status () |
Protected Member Functions | |
| virtual void | expire (Event *e) |
| virtual void | handle (Event *) |
Protected Attributes | |
| LandmarkAgent * | a_ |
| int | status_ |
| Event | event_ |
|
|
Definition at line 66 of file timer-handler.h.
00066 { TIMER_IDLE, TIMER_PENDING, TIMER_HANDLING };
|
|
|
Definition at line 527 of file landmark.h. References a_.
00527 : TimerHandler() { a_ = a;} |
|
Here is the call graph for this function:

|
|
Implements TimerHandler. Definition at line 1831 of file landmark.cc. References a_, LandmarkAgent::assign_lmaddress(), LandmarkAgent::be_random_, Scheduler::clock(), CONST_TIMEOUT, LandmarkAgent::debug_, DEMOTION, FALSE, LandmarkAgent::GenerateReHashMsg(), GLOBAL_ADVERT, LandmarkAgent::global_lm_, LandmarkAgent::global_lm_id_, LandmarkAgent::global_lm_level_, HIER_ADVS, LandmarkAgent::highest_level_, Scheduler::instance(), int64_t, IS_CHILD, ParentChildrenList::last_update_sent_, ParentChildrenList::level_, LandmarkAgent::makeUpdate(), MAX_LEVELS, MAX_TIMEOUT, LandmarkAgent::myaddr_, ParentChildrenList::mylmaddrs_, ParentChildrenList::next_, LandmarkAgent::node_, NOW, ParentChildrenList::num_children_, ParentChildrenList::num_heard_, ParentChildrenList::num_pparent_, LandmarkAgent::num_resched_, ParentChildrenList::parent_, LandmarkAgent::parent_children_list_, PERIODIC_ADVERTS, ParentChildrenList::periodic_handler_, ParentChildrenList::periodic_update_event_, PERIODIC_WAIT_TIME, pow(), LandmarkAgent::promo_start_time_, LandmarkAgent::promo_timeout_, PROMO_TIMEOUT_MULTIPLES, LandmarkAgent::promo_timer_, LandmarkAgent::promo_timer_running_, LandmarkAgent::radius(), LandmarkAgent::random_timer(), TimerHandler::resched(), Scheduler::schedule(), LandmarkAgent::SendChangedTagListUpdate(), ParentChildrenList::seqnum_, ParentChildrenList::tag_list_, Connector::target_, LandmarkAgent::total_wait_time_, LandmarkAgent::trace(), TRUE, LandmarkAgent::update_period_, ParentChildrenList::UpdatePotlChild(), ParentChildrenList::UpdatePotlParent(), and LandmarkAgent::wait_state_.
01831 {
01832 ParentChildrenList *pcl = a_->parent_children_list_;
01833 ParentChildrenList *new_pcl, *higher_level_pcl = NULL, *lower_level_pcl;
01834 ParentChildrenList *pcl1 = NULL; // Pointer to new highest_level_-1 object
01835 ParentChildrenList *pcl2 = NULL; // Pointer to new highest_level_+1 object
01836 ParentChildrenList *cur_pcl = NULL;
01837 int found = FALSE, has_parent = FALSE;
01838 int64_t *my_lm_addrs = NULL;
01839 int num_my_lm_addrs = 0;
01840 int num_potl_ch = 0;
01841 int addr_changed = 0;
01842 Scheduler &s = Scheduler::instance();
01843 double now = s.clock();
01844 Packet *p, *newp;
01845
01846 // if(now > 412.5) {
01847 // purify_printf("expire1: %f,%d\n",now,a_->myaddr_);
01848 // purify_new_leaks();
01849 // }
01850
01851 while(pcl != NULL) {
01852 if(pcl->level_ == (a_->highest_level_ + 1)) {
01853 // Exclude ourself from the count of the lower level nodes heard
01854 higher_level_pcl = pcl;
01855 a_->num_resched_ = pcl->num_heard_ - 1;
01856 num_potl_ch = pcl->num_potl_children_;
01857 }
01858 else if(pcl->level_ == a_->highest_level_) {
01859 cur_pcl = pcl;
01860 if(pcl->parent_) {
01861 has_parent = TRUE;
01862 }
01863 }
01864 else if(pcl->level_ == (a_->highest_level_-1)) {
01865 lower_level_pcl = pcl;
01866 }
01867 pcl = pcl->next_;
01868 }
01869
01870 assert(higher_level_pcl);
01871 if(a_->highest_level_)
01872 assert(lower_level_pcl);
01873 assert(cur_pcl);
01874
01875 if(a_->wait_state_) {
01876
01877 if(a_->num_resched_ && !has_parent) {
01878 a_->wait_state_ = 0;
01879 a_->total_wait_time_ = 0;
01880
01881 // Promotion timeout is num_resched_ times the estimated time for
01882 // a message to reach other nodes in its vicinity
01883 // PROM0_TIMEOUT_MULTIPLE is an estimate of time for adv to reach
01884 // all nodes in vicinity
01885 a_->promo_timeout_ = a_->random_timer(double(CONST_TIMEOUT + PROMO_TIMEOUT_MULTIPLES * a_->radius(a_->highest_level_) + MAX_TIMEOUT/((a_->num_resched_+1) * pow(2,a_->highest_level_))), a_->be_random_);
01886
01887 // a_->promo_timeout_ = a_->random_timer(double(CONST_TIMEOUT + PROMO_TIMEOUT_MULTIPLES * a_->radius(a_->highest_level_) + MAX_TIMEOUT/((a_->num_resched_+1) * pow(2,a_->highest_level_))), a_->be_random_) + (MAX_ENERGY - (a_->node_)->energy())*200/MAX_ENERGY;
01888
01889 a_->trace("Node %d: Promotion timeout after wait period in expire1: %f at time %f", a_->myaddr_,a_->promo_timeout_,s.clock());
01890 a_->num_resched_ = 0;
01891 a_->promo_start_time_ = s.clock();
01892 a_->promo_timer_->resched(a_->promo_timeout_);
01893 }
01894 else {
01895 double wait_time = PERIODIC_WAIT_TIME;
01896 a_->total_wait_time_ += wait_time;
01897 // a_->trace("Node %d: Entering wait period in expire1 at time %f, highest level %d", a_->myaddr_,now,a_->highest_level_);
01898 a_->promo_timer_->resched(wait_time);
01899
01900 // Demote ourself we do not have any children (excluding ourself) after
01901 // waiting for 1.5 times the update period
01902 if(a_->highest_level_ && (a_->total_wait_time_ > (a_->update_period_*1.5))) {
01903 // a_->trace("Node %d: cur_pcl's number of children %d",a_->myaddr_,cur_pcl->num_children_);
01904
01905 // Demote ourself from this level if we have only one children
01906 // and we have more than one potential parent at lower level
01907 // If we dont have more than one potl parent at lower level,
01908 // this node will oscillate between the two levels
01909 if(cur_pcl->num_children_ == 1 && lower_level_pcl->num_pparent_ > 1) {
01910 a_->trace("Node %d: Demoting from level %d because of no children at time %f",a_->myaddr_,a_->highest_level_,s.clock());
01911
01912 // Update appropriate lists
01913 int delete_flag = TRUE;
01914 int upd_time = (int) now;
01915 upd_time = (upd_time << 16) | (lower_level_pcl->seqnum_ & 0xFFFF);
01916 ++(lower_level_pcl->seqnum_);
01917 lower_level_pcl->UpdatePotlParent(a_->myaddr_, 0, 0, 0, 0, 0, upd_time, delete_flag);
01918
01919 upd_time = (int) now;
01920 upd_time = (upd_time << 16) | (higher_level_pcl->seqnum_ & 0xFFFF);
01921 ++(higher_level_pcl->seqnum_);
01922 higher_level_pcl->UpdatePotlChild(a_->myaddr_, 0, 0, 0, 0, 0, upd_time, IS_CHILD, delete_flag,NULL);
01923
01924 --(a_->highest_level_);
01925 Packet *p = a_->makeUpdate(cur_pcl, HIER_ADVS, DEMOTION);
01926 s.schedule(a_->target_,p,0);
01927 }
01928 }
01929 else if(!(cur_pcl->parent_) && (a_->total_wait_time_ >= (2*PERIODIC_WAIT_TIME))) {
01930 // We must be the global LM
01931 a_->global_lm_id_ = a_->myaddr_;
01932 a_->global_lm_level_ = a_->highest_level_;
01933
01934 // Get LM addresses if any
01935 (cur_pcl->mylmaddrs_)->get_lm_addrs(&num_my_lm_addrs,&my_lm_addrs);
01936
01937 // Start assigning landmark addresses to child nodes;
01938 // Shift 1, number of levels * 8 times to left for address of root node
01939 int64_t *lmaddr = new int64_t[1];
01940 lmaddr[0] = 1;
01941 lmaddr[0] = (lmaddr[0] << (cur_pcl->level_ * 8));
01942 int num_lm_addrs = 1;
01943
01944 assert(num_my_lm_addrs <= 1);
01945 if(num_my_lm_addrs == 0) {
01946 addr_changed = 1;
01947 }
01948 else {
01949 if(my_lm_addrs[0] != lmaddr[0])
01950 addr_changed = 1;
01951 }
01952
01953 if(num_my_lm_addrs) delete[] my_lm_addrs;
01954
01955 if(addr_changed) {
01956 a_->trace("Node %d: LM addrs being assigned by global LM at time %f, level %d",a_->myaddr_,now,a_->highest_level_);
01957 a_->assign_lmaddress(lmaddr, num_lm_addrs, cur_pcl->level_);
01958 if(a_->global_lm_)
01959 p = a_->makeUpdate(cur_pcl, HIER_ADVS, GLOBAL_ADVERT);
01960 else
01961 p = a_->makeUpdate(cur_pcl, HIER_ADVS, PERIODIC_ADVERTS);
01962 a_->trace("Node %d: Generating ReHash msg at time %f",a_->myaddr_,NOW);
01963 a_->GenerateReHashMsg(lmaddr[0],NOW);
01964 // Generate updates for LM at lower levels as well since their LM
01965 // addresses have also changed
01966 ParentChildrenList *tmp_pcl = a_->parent_children_list_;
01967 while(tmp_pcl) {
01968 if(tmp_pcl->level_ < cur_pcl->level_) {
01969 a_->trace("Node %d: Generating level %d update at time %f",a_->myaddr_,tmp_pcl->level_,now);
01970 newp = a_->makeUpdate(tmp_pcl, HIER_ADVS, PERIODIC_ADVERTS);
01971 s.schedule(a_->target_,newp,0);
01972 tmp_pcl->last_update_sent_ = now;
01973 }
01974 tmp_pcl = tmp_pcl->next_;
01975 }
01976 s.schedule(a_->target_, p, 0);
01977 cur_pcl->last_update_sent_ = now;
01978 }
01979
01980 // The advertisements from the root LM need to be broadcast in the hash
01981 // scheme
01982 if(num_lm_addrs) delete[] lmaddr;
01983 }
01984 }
01985 return;
01986 }
01987
01988 // Promotion timer is off
01989 a_->promo_timer_running_ = 0;
01990
01991 // Only one promotion timer can be running at a node at a given instant.
01992 // On expiry, the node will be promoted one level higher to highest_level_+1
01993 // Add a parentchildrenlist object for the higher level if one doesnt already
01994 // exist
01995 higher_level_pcl = NULL;
01996 pcl = a_->parent_children_list_;
01997 while(pcl != NULL) {
01998 new_pcl = pcl;
01999 if(pcl->level_ == a_->highest_level_+1){
02000 found = TRUE;
02001 higher_level_pcl = pcl;
02002 }
02003 if(pcl->level_ == (a_->highest_level_)){
02004 pcl1 = pcl;
02005 }
02006 if(pcl->level_ == (a_->highest_level_+2)){
02007 pcl2 = pcl;
02008 }
02009 pcl = pcl->next_;
02010 }
02011
02012 // highest_level_-1 object should exist
02013 assert(pcl1);
02014
02015 if(pcl1->parent_ != NULL) {
02016 a_->trace("Node %d: Not promoted to higher level %d\n", a_->myaddr_, a_->highest_level_+1);
02017 return;
02018 }
02019
02020 ++(a_->highest_level_);
02021 assert(a_->highest_level_ < MAX_LEVELS);
02022
02023 if(!found) {
02024 new_pcl->next_ = new ParentChildrenList(a_->highest_level_, a_);
02025 higher_level_pcl = new_pcl->next_;
02026 new_pcl = new_pcl->next_;
02027 }
02028
02029 // Create highest_level_+1 object if it doesnt exist
02030 if(!pcl2) {
02031 new_pcl->next_ = new ParentChildrenList((a_->highest_level_)+1, a_);
02032 pcl2 = new_pcl->next_;
02033 }
02034
02035 assert(pcl2);
02036
02037 if(a_->debug_) {
02038 a_->trace("Node %d: Promoted to level %d, num_potl_children %d at time %f", a_->myaddr_, a_->highest_level_, num_potl_ch, now);
02039
02040 // LMNode *lm = higher_level_pcl->pchildren_;
02041 // a_->trace("Potential Children:");
02042 // while(lm) {
02043 // a_->trace("%d (level %d) Number of hops: %d", lm->id_,lm->level_,lm->num_hops_);
02044 // lm = lm->next_;
02045 // }
02046
02047 // lm = higher_level_pcl->pparent_;
02048 // a_->trace("Potential Parent:");
02049 // while(lm) {
02050 // a_->trace("%d (level %d)", lm->id_,lm->level_);
02051 // lm = lm->next_;
02052 // }
02053 }
02054
02055
02056 // Update tag lists and send out corresponding advertisements
02057 a_->SendChangedTagListUpdate(0,a_->highest_level_-1);
02058
02059 // start off periodic advertisements for this higher level
02060 s.schedule(higher_level_pcl->periodic_handler_, higher_level_pcl->periodic_update_event_, 0);
02061
02062 // add myself as potential parent for highest_level-1 and child for
02063 // highest_level+1
02064 int num_hops = 0;
02065 int energy = (int)((a_->node_)->energy());
02066 int child_flag = IS_CHILD;
02067 int delete_flag = FALSE;
02068
02069 int upd_time = (int) now;
02070 upd_time = (upd_time << 16) | (pcl1->seqnum_ & 0xFFFF);
02071 ++(pcl1->seqnum_);
02072 pcl1->UpdatePotlParent(a_->myaddr_, a_->myaddr_, num_hops, a_->highest_level_, higher_level_pcl->num_children_, energy, upd_time, delete_flag);
02073
02074 // tag_list == NULL doesnt matter because we're at a smaller level than
02075 // pcl2->level_ at this point. periodic_callback_ will update this field
02076 // correctly
02077 upd_time = (int) now;
02078 upd_time = (upd_time << 16) | (pcl2->seqnum_ & 0xFFFF);
02079 ++(pcl2->seqnum_);
02080 pcl2->UpdatePotlChild(a_->myaddr_, a_->myaddr_, num_hops, a_->highest_level_,higher_level_pcl->num_children_, energy, upd_time, child_flag, delete_flag, higher_level_pcl->tag_list_);
02081
02082 // If we havent seen a LM that can be our parent at this higher level, start
02083 // promotion timer for promotion to next level
02084 a_->num_resched_ = pcl2->num_heard_ - 1;
02085 if(higher_level_pcl->parent_ == NULL && a_->num_resched_) {
02086 // if (a_->debug_) printf("PromotionTimer's expire method: Scheduling timer for promo to level %d\n",a_->highest_level_);
02087 // Timer's status is TIMER_HANDLING in handle; so we just reschedule to
02088 // avoid "cant start timer" abort if sched is called
02089
02090 a_->promo_timer_running_ = 1;
02091 a_->wait_state_ = 0;
02092 a_->total_wait_time_ = 0;
02093 a_->promo_timeout_ = a_->random_timer(double(CONST_TIMEOUT + PROMO_TIMEOUT_MULTIPLES * a_->radius(a_->highest_level_+1) + MAX_TIMEOUT/((a_->num_resched_+1) * pow(2,a_->highest_level_+1))), a_->be_random_);
02094 a_->trace("Node %d: Promotion timeout after wait period in expire2: %f at time %f, num_resched_ %d, energy %f", a_->myaddr_,a_->promo_timeout_,s.clock(),a_->num_resched_,(a_->node_)->energy());
02095 a_->num_resched_ = 0;
02096 a_->promo_start_time_ = s.clock();
02097 a_->promo_timer_->resched(a_->promo_timeout_);
02098 }
02099 else {
02100 double wait_time = PERIODIC_WAIT_TIME;
02101 a_->promo_timer_running_ = 1;
02102 a_->total_wait_time_ = 0;
02103 a_->wait_state_ = 1;
02104 a_->total_wait_time_ += wait_time;
02105 // a_->trace("Node %d: Entering wait period in expire1 at time %f", a_->myaddr_,now);
02106 a_->promo_timer_->resched(wait_time);
02107 }
02108
02109
02110 // if(now > 412.5) {
02111 // purify_printf("expire2: %f,%d\n",now,a_->myaddr_);
02112 // purify_new_leaks();
02113 // }
02114
02115 }
|
Here is the call graph for this function:

|
|
Definition at line 60 of file timer-handler.h. References TimerHandler::_cancel(), TimerHandler::status_, TimerHandler::TIMER_IDLE, and TimerHandler::TIMER_PENDING. Referenced by TcpAgent::cancel_rtx_timer(), TcpSessionAgent::cancel_rtx_timer(), TcpFsAgent::cancel_rtx_timer(), AbsTcpAgent::cancel_timer(), TcpAgent::cancel_timers(), TcpSessionAgent::cancel_timers(), FullTcpAgent::cancel_timers(), TcpFsAgent::cancel_timers(), SinkAgent::command(), UnslottedAlohaMac::end_of_contention(), GAFAgent::processDiscoveryMsg(), RTPAgent::rate_change(), TfrcAgent::stop(), RTPAgent::stop(), and SinkAgent::stop().
00060 { // cancel!
00061 if (status_ == TIMER_PENDING) {
00062 _cancel();
00063 status_ = TIMER_IDLE;
00064 }
00065 }
|
Here is the call graph for this function:

|
|
Implements Handler. Reimplemented in EmpFtpTrafSession, EmpWebPage, EmpWebTrafSession, HBTimer, WebPage, and WebTrafSession. Definition at line 69 of file timer-handler.cc. References abort(), TimerHandler::expire(), TimerHandler::status_, TimerHandler::TIMER_HANDLING, TimerHandler::TIMER_IDLE, and TimerHandler::TIMER_PENDING. Referenced by WebTrafSession::handle(), WebPage::handle(), HBTimer::handle(), EmpWebTrafSession::handle(), EmpWebPage::handle(), and EmpFtpTrafSession::handle().
00070 {
00071 if (status_ != TIMER_PENDING) // sanity check
00072 abort();
00073 status_ = TIMER_HANDLING;
00074 expire(e);
00075 // if it wasn't rescheduled, it's done
00076 if (status_ == TIMER_HANDLING)
00077 status_ = TIMER_IDLE;
00078 }
|
Here is the call graph for this function:

|
Here is the call graph for this function:

|
Here is the call graph for this function:

|
|
|
Definition at line 530 of file landmark.h. Referenced by expire(), and PromotionTimer(). |
|
|
Definition at line 75 of file timer-handler.h. Referenced by TimerHandler::_cancel(), TimerHandler::_sched(), WebPage::start(), and EmpWebPage::start(). |
|
1.3.3