if sending several pings in parallel, delay them in scheduler
[pingcheck] / src / host / pingscheduler.cpp
index 010b8d5..81149f6 100644 (file)
@@ -40,6 +40,7 @@ using boost::date_time::time_resolution_traits_adapted64_impl;
 using boost::posix_time::microsec_clock;
 using boost::posix_time::ptime;
 using boost::posix_time::seconds;
+using boost::posix_time::milliseconds;
 using boost::shared_ptr;
 using I2n::Logger::GlobalLogger;
 
@@ -73,7 +74,7 @@ PingScheduler::PingScheduler(
         const int ping_reply_timeout,
         LinkStatusItem link_analyzer,
         const int first_delay,
-        const int n_parallel_pings
+        const int n_parallel_pings,
         const int parallel_ping_delay
 ) :
     IoService( io_serv ),
@@ -94,6 +95,7 @@ PingScheduler::PingScheduler(
     NPingers( n_parallel_pings ),
     NPingersDone( 0 ),
     ParallelPingDelay( parallel_ping_delay ),
+    DelayedPingTimer( *io_serv ),
     WantToPing( false ),
     LogPrefix(),
     ContinueOnOutdatedIps( false )
@@ -139,11 +141,11 @@ void PingScheduler::stop_pinging()
 void PingScheduler::clear_pingers()
 {
     PingerItem pinger;
-    while ( !Pingers.empty() )
+    while(!Pingers.empty())
     {
-        pinger = Pingers.front();
+        pinger = Pingers.back();
         pinger->stop_pinging();
-        Pingers.pop_front();
+        Pingers.pop_back();
     }
 }
 
@@ -238,27 +240,37 @@ void PingScheduler::ping_when_ready()
         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";
-        int delay_count = 0;
-        BOOST_FOREACH( const PingerItem &pinger, Pingers )
-        {
-            boost::asio::deadline_timer delayed_ping_timer( IoService );
-            delayed_ping_timer.expires_from_now(
-                                  milliseconds(delay_count * ParallelPingDelay);
-            delayed_ping_timer.async_wait( bind( &PingScheduler::delayed_ping,
-                                                                this, pinger) );
-            ++delay_count;
-        }
-        TimeSentLastPing = microsec_clock::universal_time();
+        delayed_ping(boost::system::error_code(), actual_ip, 0);
         NPingersDone = 0;
+        TimeSentLastPing = microsec_clock::universal_time();
     }
 }
 
-void delayed_ping( const PingerItem &pinger )
+void PingScheduler::delayed_ping( const boost::system::error_code &error,
+                                  const boost::asio::ip::address &ip,
+                                  const int pinger_index )
 {
-    pinger->ping( actual_ip,
-                  DestinationPort,
-                  boost::bind(&PingScheduler::ping_done_handler,
-                                                        this, _1) );
+    if (error)
+    {
+        GlobalLogger.info() << LogPrefix << "delayed ping received an error: "
+                                         << error;
+        return;
+    }
+    if (pinger_index == NPingers)
+    {
+        GlobalLogger.debug() << LogPrefix << "started all delayed pings";
+        return;
+    }
+
+    GlobalLogger.debug() << LogPrefix << "starting delayed ping index "
+                          << pinger_index;
+    Pingers[pinger_index]->ping(ip,
+                                DestinationPort,
+                                boost::bind(&PingScheduler::ping_done_handler,
+                                                                this, _1, _2) );
+    DelayedPingTimer.expires_from_now( milliseconds(ParallelPingDelay) );
+    DelayedPingTimer.async_wait( bind( &PingScheduler::delayed_ping,
+                  this, boost::asio::placeholders::error, ip, pinger_index+1) );
 }