if sending several pings in parallel, delay them in scheduler
authorChristian Herdtweck <christian.herdtweck@intra2net.com>
Tue, 26 May 2015 08:17:12 +0000 (10:17 +0200)
committerChristian Herdtweck <christian.herdtweck@intra2net.com>
Tue, 26 May 2015 08:17:12 +0000 (10:17 +0200)
src/host/pingscheduler.cpp
src/host/pingscheduler.h

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) );
 }
 
 
index 34ee755..54392c3 100644 (file)
@@ -36,7 +36,7 @@ on this file might be covered by the GNU General Public License.
 #include "host/pingprotocol.h"
 #include "dns/resolverbase.h"
 
-typedef std::list<PingerItem> pinger_list;
+typedef std::vector<PingerItem> pinger_vec;
 
 //-----------------------------------------------------------------------------
 // PingScheduler
@@ -88,6 +88,9 @@ private:
     void update_dns_resolver( PingProtocol current_protocol );
 
     void ping_when_ready();
+    void delayed_ping( const boost::system::error_code &error,
+                       const boost::asio::ip::address &ip,
+                       const int pinger_index );
     void dns_resolve_callback(const bool was_success,
                               const int recursion_count);
     void start_resolving_ping_address();
@@ -126,13 +129,15 @@ private:
     /// The Dns resolver
     ResolverItem Resolver;
     /// vector of pingers
-    pinger_list Pingers;
+    pinger_vec Pingers;
     /// number of pingers that work in parallel
     int NPingers;
     /// number of results from pingers
     int NPingersDone;
     /// delay (in ms) between pings to same IP
     int ParallelPingDelay;
+    /// timers for delayed pings
+    boost::asio::deadline_timer DelayedPingTimer;
     /// a flag whether we should ping as soon as dns is ready
     bool WantToPing;
     /// Prefix to log messages for quicker analysis/debugging