NSIS-ka
A free C++ implementation of NSIS protocols

Changeset 4497


Ignore:
Timestamp:
Sep 28, 2009, 7:52:36 PM (8 years ago)
Author:
stud-lenk
Message:

Re-work NoResponse? timer handling for multicast.

The NoResponse? timer has been moved to a separate »slot« in order to be able to continue to run when the refresh_QNode has to start. This makes the recently introduced additional timer »mcast_collect« (alias MULTICAST_COLLECT) obsolete and the state machine more consistent with the current NTLP draft.

Location:
ntlp/branches/20090723-multicast/src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • ntlp/branches/20090723-multicast/src/ntlp_statemodule_main.cpp

    r4485 r4497  
    407407        break;
    408408
    409       // Purge all unresponsive multicast peers NOW
    410       case mcast_collect:
    411         rk = static_cast<routingkey*>(timermsg->get_param2());
    412         to_mcast_collect(rk, timermsg);
    413         break;
    414 
    415409      // Stopped
    416410      case none:
     
    13721366 
    13731367   
    1374   // timers on slot #2 (no_response (QN) or refresh_qnode (QN))
    1375   if ((timer == noresponse) || (timer==refresh_qnode))
     1368  // timers on slot #2 (refresh_qnode (QN))
     1369  if (timer==refresh_qnode)
    13761370  {
    13771371    if ((r_entry->get_timer_id_2() != 0) && stop)
     
    13901384
    13911385    msg->send_to(message::qaddr_timer);
    1392     if (timer == noresponse) {
    1393       r_entry->save_no_response_deadline(sec, msec);
    1394     }
    13951386  }
    13961387
     
    14151406  }   
    14161407
    1417   // separate timer for collecting more responses (in reseponse to multicast queries)
    1418   if (timer == mcast_collect)
    1419   {
    1420     if ((r_entry->get_timer_id_multicast() != 0) && stop)
     1408  // separate noresponse timer
     1409  // this must be separate for multicast, when collecting responses does not end with the first response
     1410  if (timer == noresponse)
     1411  {
     1412    if ((r_entry->get_timer_id_noresponse() != 0) && stop)
    14211413    {
    14221414      // stop the current timer
    14231415      TimerMsg* stopmsg = new TimerMsg(message::qaddr_coordination, true);
    1424       stopmsg->stop(r_entry->get_timer_id_multicast());
     1416      stopmsg->stop(r_entry->get_timer_id_noresponse());
    14251417      stopmsg->send_to(message::qaddr_timer);
    14261418    }
     
    14281420    TimerMsg* msg = new RoutingTableTimerMsg(*r_key, timer, sec, msec);
    14291421
    1430     r_entry->set_timer_type_multicast(timer);
    1431     r_entry->set_timer_id_multicast(msg->get_id());
    1432     mid = r_entry->get_timer_id_multicast();
     1422    r_entry->set_timer_type_noresponse(timer);
     1423    r_entry->set_timer_id_noresponse(msg->get_id());
     1424    mid = r_entry->get_timer_id_noresponse();
    14331425
    14341426    msg->send_to(message::qaddr_timer);
     
    14461438  {
    14471439          r_entry->set_timer_type_2(none);
     1440  }
     1441
     1442  // NoResponse timer
     1443  if (timer == noresponse)
     1444  {
     1445    EVLog(param.name, color[magenta] << "Trying to stop NoResponse timer with id " << r_entry->get_timer_id_noresponse() << color[off]);
     1446    TimerMsg* stopmsg = new TimerMsg(message::qaddr_coordination, true);
     1447    stopmsg->stop(r_entry->get_timer_id_noresponse());
     1448    stopmsg->send_to(message::qaddr_timer);
     1449    // invalidate timer data
     1450    r_entry->set_timer_type_noresponse(none);
    14481451  }
    14491452}
     
    14821485  }
    14831486
    1484   // timers on multicast slot
    1485   if (r_entry->get_timer_type_multicast() != none)
     1487  // timers on noresponse slot
     1488  if (r_entry->get_timer_type_noresponse() != none)
    14861489  {
    14871490    // this will cause only ignoring any timer
    1488     r_entry->set_timer_type_multicast(none);
    1489 
    1490     EVLog(param.name, color[magenta] << "Trying to stop timer for multicast" << color[off]);
     1491    r_entry->set_timer_type_noresponse(none);
     1492
     1493    EVLog(param.name, color[magenta] << "Trying to stop NoResponse timer" << color[off]);
    14911494    // really stop the current timer
    14921495    TimerMsg* stopmsg = new TimerMsg(message::qaddr_coordination, true);
    1493     stopmsg->stop(r_entry->get_timer_id_multicast());
     1496    stopmsg->stop(r_entry->get_timer_id_noresponse());
    14941497    stopmsg->send_to(message::qaddr_timer);
    14951498  }
  • ntlp/branches/20090723-multicast/src/ntlp_statemodule_querier.cpp

    r4496 r4497  
    411411      r_entry->set_peer_nli(NULL);
    412412      r_entry->set_sii_handle(0);
    413 
    414       uint32 remaining_responses_time = r_entry->get_remaining_response_time();
    415       DLog(param.name, "Remaining time for other responses: " << remaining_responses_time << " ms");
    416       if (r_entry->get_min_peer_rs_validity_time() < remaining_responses_time) {
    417         WLog(param.name, "Trimming remaining time for more responses ("
    418                          << remaining_responses_time << " ms) to shorter peer RS validity time: "
    419                          << r_entry->get_min_peer_rs_validity_time() << " ms");
    420         remaining_responses_time = r_entry->get_min_peer_rs_validity_time();
    421       }
    422       if (remaining_responses_time == 0) {
    423         // purge list of unresponding peers now
    424         if (r_entry->get_timer_type_multicast() != none) {
    425           ERRCLog(param.name, "timer_type_multicast is not 'none' - this should never happen");
    426           r_entry->set_timer_type_multicast(none);
    427         }
    428         r_entry->purge_multicast_peers();
    429       } else {
    430         // purge list of unresponsive peers later
    431         starttimer(r_key, r_entry, mcast_collect, 0, remaining_responses_time, false);
    432       }
    433413    }
    434414    else
     
    453433    if (r_entry->get_timer_type_1() != inactive_qnode)
    454434            starttimer(r_key, r_entry, inactive_qnode, 0, r_entry->get_rs_validity_time());
    455                
     435
     436    // stop NoResponse timer if not needed any more
     437    if (r_entry->is_multicast_QNode() == false)
     438      stoptimer(r_entry, noresponse);
    456439    // start Refresh_QNode timer on timer slot #2
    457440    uint32 refresh_timeout = r_entry->is_multicast_QNode() ? r_entry->get_min_peer_rs_validity_time() : r_entry->get_peer_nli()->get_rs_validity_time();
     
    556539    // Add peer to list of multicast peers
    557540    r_entry->add_multicast_peer(peer_nli);
    558      
    559     // Calculate remaining time for other responses
    560     uint32 remaining_responses_time = r_entry->get_remaining_response_time();
    561     DLog(param.name, "Remaining time for other responses: " << remaining_responses_time << " ms");
    562     if (r_entry->get_min_peer_rs_validity_time() < remaining_responses_time) {
    563       WLog(param.name, "Trimming remaining time for more responses ("
    564                         << remaining_responses_time << " ms) to shorter peer RS validity time: "
    565                         << r_entry->get_min_peer_rs_validity_time() << " ms");
    566       remaining_responses_time = r_entry->get_min_peer_rs_validity_time();
    567     }
    568     if (remaining_responses_time == 0) {
    569       // purge list of unresponding peers now
    570       if (r_entry->get_timer_type_multicast() != none) {
    571         ERRCLog(param.name, "timer_type_multicast is not 'none' - this should never happen");
    572         r_entry->set_timer_type_multicast(none);
    573       }
    574       r_entry->purge_multicast_peers();
    575     } else {
    576       // purge list of unresponsive peers later
    577       starttimer(r_key, r_entry, mcast_collect, 0, remaining_responses_time, false);
    578     }
    579541
    580542    //******************************************************************************
     
    695657  DLog(param.name, "Installed peer's RS-Validity time of " << refresh_timeout <<"ms");
    696658
     659  // stop NoResponse timer if not needed any more
     660  if (r_entry->is_multicast_QNode() == false)
     661    stoptimer(r_entry, noresponse);
    697662  // (re)Start refresh_QNode timer
    698663  starttimer(r_key, r_entry, refresh_qnode, 0, randomized(refresh_timeout, gconf.getpar<float>(gistconf_retryfactor)));
     
    10561021  if (r_entry)
    10571022  {
    1058     if (r_entry->get_timer_type_2() != noresponse) {
     1023    if (r_entry->get_timer_type_noresponse() != noresponse) {
    10591024      DLog(param.name, "Deliberately stopped timer, ignoring");
    10601025      param.rt.unlock(r_key);
    10611026      return;
    10621027    }
    1063 
    1064     if (r_entry->get_timer_id_2() == timermsg->get_id())
    1065     {
    1066       DLog(param.name, "Timer slot 2, timer is valid, id: " << timermsg->get_id());
    1067 
    1068 
     1028    // reset timer type to avoid that it unneccessarily gets stopped in canceltimers
     1029    r_entry->set_timer_type_noresponse(none);
     1030
     1031    if (r_entry->get_timer_id_noresponse() == timermsg->get_id())
     1032    {
     1033      DLog(param.name, "Timer slot noresponse, timer is valid, id: " << timermsg->get_id());
    10691034      EVLog(param.name, color[magenta] << "NoResponse Timer went off" << color[off]);
    1070       // NoResponse timer retransmits Queries until state changes to rn_established and timer is stopped
     1035     
     1036      // If this is a Querying Node doing multicast, unresponsive nodes get purged now
     1037      if (r_entry->is_multicast_QNode()) {
     1038        DLog(param.name, "This node is a multicasting QN in state ESTABLISHED. Purging unresponsive peers now.");
     1039        r_entry->purge_multicast_peers();
     1040
     1041        // if in state ESTABLISHED, purging unresponsive multicast peers is all we have to do
     1042        if (r_entry->get_state() == qn_established) {
     1043          param.rt.unlock(r_key);
     1044          return;
     1045        }
     1046      } else {
     1047        if (r_entry->get_state() == qn_established) {
     1048          ERRCLog(param.name, color[red] << "NoResponse timeout in state ESTABLISHED, unicasting QNode -- ignoring (already got a response)" << color[off]);
     1049          param.rt.unlock(r_key);
     1050          return;
     1051        }
     1052      }
     1053
     1054      // NoResponse timer retransmits Queries until state changes to qn_established and timer is stopped
    10711055      if (! r_entry->retry_limit_reached() &&
    10721056          (param.addresses.addr_is(*r_entry->get_local_src(), AddressList::LocalAddr_P) ||
     
    11681152      if (r_entry->is_multicast_QNode())
    11691153      {
    1170         if (r_entry->get_timer_type_multicast() == mcast_collect) {
    1171           ERRCLog(param.name, "List of multicast peers hasn't been purged (mcast_collect timer should have fired before but didn't). Skipping purge for this time");
     1154        if (r_entry->get_timer_type_noresponse() == noresponse) {
     1155          ERRCLog(param.name, "List of multicast peers hasn't been purged (noresponse timer should have fired before but didn't). Skipping purge for this time");
    11721156          // We do not need to stoptimer() because timer handling checks for
    11731157          // the correct routing state. If the node isn't in ESTABLISHED
     
    11961180      // transition to qn_awaiting_refresh
    11971181      r_entry->set_state(qn_awaiting_refresh);
     1182
     1183      // clear timer slot #2
     1184      r_entry->set_timer_type_2(none);
     1185      r_entry->set_timer_id_2(0);
    11981186           
    11991187      // kickstart NoResponse timer
     
    12071195}
    12081196
    1209 
    1210 /**
    1211  * McastCollect Timer processing. Purge unresponsive peers from multicast peer list
    1212  * @param r_key -- the routing key (may NOT be NULL)
    1213  * @param timermsg -- the timer message
    1214  */
    1215 void Statemodule::to_mcast_collect(const routingkey* r_key, TimerMsg* timermsg)
    1216 {
    1217   assert( r_key != NULL );
    1218 
    1219   DLog(param.name, "to_mcast_collect(): looking up routing key");
    1220    
    1221   routingentry* r_entry = param.rt.lookup(r_key);
    1222    
    1223   if (r_entry)
    1224   {
    1225     if (r_entry->get_timer_type_multicast() != mcast_collect) {
    1226       DLog(param.name, "Deliberately stopped timer, ignoring");
    1227       param.rt.unlock(r_key);
    1228       return;
    1229     }
    1230     r_entry->set_timer_type_multicast(none);
    1231 
    1232     if (r_entry->get_state() != qn_established) {
    1233       ERRLog(param.name, "Got a timeout on timer " << timerstring[mcast_collect]
    1234                         << " but I am in state " << r_entry->get_state_name()
    1235                         << " (expected to be in state " << statestring[qn_established] << ")");
    1236       param.rt.unlock(r_key);
    1237       return;
    1238     }
    1239 
    1240     if (r_entry->get_timer_id_multicast() == timermsg->get_id())
    1241     {
    1242       DLog(param.name, "Timer slot multicast, timer is valid, id: " << timermsg->get_id());
    1243 
    1244       EVLog(param.name, color[magenta] << "MCastCollect Timer went off" << color[off]);
    1245       r_entry->purge_multicast_peers();
    1246            
    1247       r_entry->set_timer_id_multicast(0);
    1248       param.rt.unlock(r_key);
    1249     } // end if timer valid
    1250   } // if r_entry
    1251 }
    1252 
    12531197//@}
    12541198
  • ntlp/branches/20090723-multicast/src/routingentry.cpp

    r4493 r4497  
    199199}
    200200
    201 void
    202 routingentry::save_no_response_deadline(uint32 sec, uint32 msec)
    203 {
    204   struct timeval now = {0,0};
    205   struct timeval delta = {sec, msec * 1000};
    206   gettimeofday(&now, NULL);
    207   timeradd(&now, &delta, &no_response_deadline);
    208 }
    209 
    210 uint32
    211 routingentry::get_remaining_response_time()
    212 {
    213   // shortcut gettimeofday() if there is no valid no_response_deadline
    214   if (no_response_deadline.tv_sec == 0 && no_response_deadline.tv_usec == 0) return 0;
    215 
    216   uint32 remaining_time = 0;
    217   struct timeval now = {0,0};
    218   gettimeofday(&now, NULL);
    219   if (timercmp(&now, &no_response_deadline, <))
    220   {
    221     struct timeval delta;
    222     timersub(&no_response_deadline, &now, &delta);
    223     assert(delta.tv_sec >= 0 && delta.tv_usec >= 0);
    224     remaining_time = delta.tv_sec * 1000 + delta.tv_usec / 1000;
    225   }
    226   else
    227   { // invalidate expired no_response_deadline
    228     no_response_deadline.tv_sec = 0;
    229     no_response_deadline.tv_usec = 0;
    230   }
    231   return remaining_time;
    232 }
    233 
    234201// returns the number of missed responses a multicast peer is allowed
    235202// before being purged from the multicast peer list
  • ntlp/branches/20090723-multicast/src/routingentry.h

    r4485 r4497  
    6060  timer_stopped  = 12,
    6161  send_mresponse = 13,
    62   mcast_collect  = 14,
    63   last_timer_type= 15,
     62  last_timer_type= 14,
    6463  none           = 255
    6564} timer_type_t;
     
    107106  "STOPPED",
    108107  "SEND_MCAST_RESPONSE",
    109   "MULTICAST_COLLECT",
    110108  "INVALID_TYPE_LAST_TIMER"
    111109}; // end timerstring
     
    164162          timer_type_2(none), // NOTE: not a true copy
    165163          timer_type_3(none), // NOTE: not a true copy
    166           timer_type_multicast(none), // NOTE: not a true copy
     164          timer_type_noresponse(none), // NOTE: not a true copy
    167165          timer_id(0), // NOTE: not a true copy
    168166          timer_id_2(0), // NOTE: not a true copy
    169167          timer_id_3(0), // NOTE: not a true copy
    170           timer_id_multicast(0), // NOTE: not a true copy
     168          timer_id_noresponse(0), // NOTE: not a true copy
    171169          rs_validity_time(n.rs_validity_time),
    172170          min_peer_rs_validity_time(n.min_peer_rs_validity_time),
     
    187185  {
    188186    dataqueue.clear();
    189     no_response_deadline.tv_sec = 0;
    190     no_response_deadline.tv_usec = 0;
    191187  } // end copy constructor
    192188
     
    300296        timer_type_t get_timer_type_3() const { return timer_type_3; }
    301297        void set_timer_type_3(timer_type_t type) { timer_type_3= type; }
    302         timer_type_t get_timer_type_multicast() const { return timer_type_multicast; }
    303         void set_timer_type_multicast(timer_type_t type) { timer_type_multicast= type; }
     298        timer_type_t get_timer_type_noresponse() const { return timer_type_noresponse; }
     299        void set_timer_type_noresponse(timer_type_t type) { timer_type_noresponse= type; }
    304300
    305301        uint64 get_timer_id_1() const { return timer_id; }
     
    309305        uint64 get_timer_id_3() const { return timer_id_3; }
    310306        void set_timer_id_3(uint64 id) { timer_id_3= id; }
    311         uint64 get_timer_id_multicast() const { return timer_id_multicast; }
    312         void set_timer_id_multicast(uint64 id) { timer_id_multicast= id; }
     307        uint64 get_timer_id_noresponse() const { return timer_id_noresponse; }
     308        void set_timer_id_noresponse(uint64 id) { timer_id_noresponse= id; }
    313309
    314310        const char* get_state_name() const { return (state<rt_state_max) ? statestring[state] : "state variable invalid - internal error"; };
     
    336332        void expire_multicast_peers();
    337333        void purge_multicast_peers();
    338 
    339         // calculates the absolute deadline from the given relative deadline
    340         // (sec, msec like in starttimer()) and saves the result to
    341         // routingentry::no_response_deadline (a timeval)
    342         void save_no_response_deadline(uint32 sec, uint32 msec);
    343 
    344         // checks the absolute deadline previously saved by
    345         // save_no_response_deadline() and returns the remaining time (ms)
    346         uint32 get_remaining_response_time();
    347334
    348335        // returns the number of missed responses a multicast peer is allowed
     
    373360  nli* peer_nli;
    374361
     362  bool is_multicast_querier;
    375363  // Hashmap containing multicast peer status
    376   // key for each multicast_peerstatus: sii_handle
    377   bool is_multicast_querier;
     364  // key for each multicast_peerstatus: NLI
    378365  mcast_peer_list_t multicast_peers;
    379366
     
    398385  timer_type_t timer_type_3;
    399386  // used for timeout of collecting multicast responses
    400   timer_type_t timer_type_multicast;
     387  timer_type_t timer_type_noresponse;
    401388   
    402389  /// the ID of the timers 1 and 2
     
    405392  uint64 timer_id_3;   
    406393  // used for timeout of collecting multicast responses
    407   uint64 timer_id_multicast;
    408   // needed for calculation of remaining no_response_timeout time
    409   // when receiving first response to multicast query
    410   struct timeval no_response_deadline;
     394  uint64 timer_id_noresponse;
    411395   
    412396  /// RSV time (ms)
     
    474458    timer_type_2(none),
    475459    timer_type_3(none),
    476     timer_type_multicast(none),
     460    timer_type_noresponse(none),
    477461    timer_id(0),
    478462    timer_id_2(0),
    479463    timer_id_3(0),
    480     timer_id_multicast(0),
     464    timer_id_noresponse(0),
    481465    rs_validity_time(0),
    482466    min_peer_rs_validity_time(0),
     
    497481{
    498482  dataqueue.clear();
    499   no_response_deadline.tv_sec = 0;
    500   no_response_deadline.tv_usec = 0;
    501483} // end constructor
    502484
Note: See TracChangeset for help on using the changeset viewer.