use line digestion recognition in PingScheduler;
[pingcheck] / src / host / pingscheduler.cpp
index 464373a..7b06778 100644 (file)
@@ -90,6 +90,7 @@ PingScheduler::PingScheduler(
     Protocols( ping_protocol_list ),
     ProtocolIter(),
     PingIntervalInSec( ping_interval_in_sec ),
+    NPingers( n_parallel_pings ),
     FirstDelay( first_delay ),
     NextPingTimer( *io_serv ),
     TimeSentLastPing( microsec_clock::universal_time() ),
@@ -100,7 +101,6 @@ PingScheduler::PingScheduler(
                   link_analyzer ),
     Resolver(),
     Pingers(),
-    NPingers( n_parallel_pings ),
     NPingersDone( 0 ),
     ParallelPingDelay( parallel_ping_delay ),
     DelayedPingTimer( *io_serv ),
@@ -119,6 +119,10 @@ PingScheduler::PingScheduler(
     update_log_prefix();
 
     init_ping_protocol();
+
+    // start resolving already so we are prepared to ping
+    update_dns_resolver();
+
 }
 
 /**
@@ -213,8 +217,11 @@ void PingScheduler::ping_when_ready()
         return;
     }
     else if ( !Resolver )
+    {
         // should not happen, but check anyway
         GlobalLogger.warning() << LogPrefix << "Have no resolver!";
+        return;
+    }
 
     GlobalLogger.info() << LogPrefix << "start ping";
     WantToPing = false;
@@ -245,17 +252,27 @@ void PingScheduler::ping_when_ready()
     }
     else
     {
+        // create new pingers
+        for (int count=0; count<NPingers; ++count)
+            Pingers.push_back(
+                    PingerFactory::createPinger(*ProtocolIter, IoService,
+                                                NetworkInterfaceName,
+                                                PingReplyTimeout) );
+
+        // remember when pinging started
+        TimeSentLastPing = microsec_clock::universal_time();
+
+        // get actual IP
         boost::asio::ip::address actual_ip = ip.get_ip();
         GlobalLogger.info() << LogPrefix << "pinging IP " << actual_ip
             << " with TTL " << ip.get_ttl().get_updated_value() << "s";
-        delayed_ping(boost::system::error_code(), actual_ip, 0);
         NPingersDone = 0;
-        TimeSentLastPing = microsec_clock::universal_time();
+        delayed_ping(boost::system::error_code(), actual_ip, 0);
     }
 }
 
 void PingScheduler::delayed_ping( const boost::system::error_code &error,
-                                  const boost::asio::ip::address &ip,
+                                  const boost::asio::ip::address ip,
                                   const int pinger_index )
 {
     if (error)
@@ -264,11 +281,6 @@ void PingScheduler::delayed_ping( const boost::system::error_code &error,
                                          << error;
         return;
     }
-    if (pinger_index == NPingers)
-    {
-        GlobalLogger.debug() << LogPrefix << "started all delayed pings";
-        return;
-    }
 
     GlobalLogger.debug() << LogPrefix << "starting delayed ping index "
                           << pinger_index;
@@ -276,9 +288,14 @@ void PingScheduler::delayed_ping( const boost::system::error_code &error,
                                 DestinationPort,
                                 boost::bind(&PingScheduler::ping_done_handler,
                                                                 this, _1, _2) );
-    DelayedPingTimer.expires_from_now( milliseconds(ParallelPingDelay) );
-    DelayedPingTimer.async_wait( bind( &PingScheduler::delayed_ping,
+    if (pinger_index >= NPingers-1)
+        GlobalLogger.debug() << LogPrefix << "started all delayed pings";
+    else
+    {
+        DelayedPingTimer.expires_from_now( milliseconds(ParallelPingDelay) );
+        DelayedPingTimer.async_wait( bind( &PingScheduler::delayed_ping,
                   this, boost::asio::placeholders::error, ip, pinger_index+1) );
+    }
 }
 
 
@@ -314,16 +331,27 @@ void PingScheduler::ping_done_handler( const PingStatus &result,
 
     // prepare next ping only after all pingers are done
     if (NPingersDone == NPingers)
+    {
+        // stop and destruct all pingers
+        clear_pingers();
+
+        GlobalLogger.debug() << LogPrefix
+            << "--------------------------------------------------------------";
+
+        // update variables for next ping: number of pings, delay, protocol
+        update_ping_protocol();
+        update_ping_interval();
+        update_ping_number();
+
         prepare_next_ping();
+    }
 }
 
 
 void PingScheduler::prepare_next_ping()
 {
-    update_ping_interval();
-
-    // get next protocol, possibly start resolving IPs
-    update_ping_protocol();
+    // start DNS resolve if necessary
+    update_dns_resolver();
 
     // schedule next ping
     int seconds_since_last_ping = (microsec_clock::universal_time()
@@ -360,6 +388,40 @@ void PingScheduler::update_ping_interval()
     }
 }
 
+/** in case of congested line, increase number of pings
+ *
+ * CAUTION! Only call this after clear_pingers !!!
+ * */
+void PingScheduler::update_ping_number()
+{
+    // make sure we do not loose track of pingers here
+    if ( NPingersDone != NPingers  || !Pingers.empty() )
+    {
+        GlobalLogger.warning() << LogPrefix << "Should only change number of "
+            << "pingers when all are finished and deleted! Have " << NPingers
+            << " pingers, " << NPingersDone << " of which are done and "
+            << Pingers.size() << " in listDone! Will not change NPingers.";
+        return;
+    }
+
+    if ( HostAnalyzer.exceeded_ping_congestion_limit() )
+    {
+        NPingers.increase();
+
+        GlobalLogger.debug() << LogPrefix << "- Increasing ping number to: "
+                             << NPingers;
+    }
+    else
+    {
+        NPingers.back_to_original();
+
+        GlobalLogger.debug() << LogPrefix << "- Stick to the original ping "
+                             << "number: " << NPingers;
+    }
+
+    HostAnalyzer.set_n_parallel_pings(NPingers);
+}
+
 //------------------------------------------------------------------------------
 // Ping Protocol Rotation
 //------------------------------------------------------------------------------
@@ -380,25 +442,9 @@ void PingScheduler::update_ping_protocol()
 
 void PingScheduler::get_next_ping_protocol()
 {
-    // stop and destruct all pingers
-    clear_pingers();
-    GlobalLogger.debug() << LogPrefix
-        << "------------------------------------------------------------------";
-
-    // get next protocol
     ++ProtocolIter;
     if (ProtocolIter == Protocols.end())
         ProtocolIter = Protocols.begin();
-    PingProtocol ping_protocol = *ProtocolIter;
-    // --> ProtocolIter still points to currently used protocol which is
-    //     required in dns_resolve_callback
-
-    // create new pingers
-    for (int count=0; count<NPingers; ++count)
-        Pingers.push_back( PingerFactory::createPinger(ping_protocol, IoService,
-                                      NetworkInterfaceName, PingReplyTimeout) );
-
-    update_dns_resolver( ping_protocol );
 }
 
 bool PingScheduler::can_change_ping_protocol() const
@@ -424,7 +470,7 @@ void PingScheduler::update_log_prefix()
     LogPrefix = temp.str();
 }
 
-void PingScheduler::update_dns_resolver( PingProtocol current_protocol )
+void PingScheduler::update_dns_resolver()
 {
     if (Resolver && Resolver->is_resolving())
         cancel_resolve(false);
@@ -439,7 +485,7 @@ void PingScheduler::update_dns_resolver( PingProtocol current_protocol )
     // probably just return an existing resolver with already resolved IPs for
     // requested protocol ( ICMP/TCP is ignored, only IPv4/v6 is important)
     Resolver = DnsMaster::get_instance()->get_resolver_for(DestinationAddress,
-                                                           current_protocol);
+                                                           *ProtocolIter);
 
     // get number of up-to-date IPs
     // TODO should check here, if they will be up to date in PingIntervalInSec