Implemented the requirement "Intelligently retry if a host doesn't reply: Try it...
authorGuilherme Maciel Ferreira <guilherme.maciel.ferreira@intra2net.com>
Thu, 24 Mar 2011 13:51:47 +0000 (14:51 +0100)
committerGuilherme Maciel Ferreira <guilherme.maciel.ferreira@intra2net.com>
Thu, 24 Mar 2011 15:25:04 +0000 (16:25 +0100)
- PingAnalyzer::exceeded_ping_failed_count_limit() made public, thus the Analyzer can check when is required to speed up the ping (or back to the original interval)
- Included a PingInterval template class to hide the computation logic of interval speed up and slow down

src/ping/pinganalyzer.cpp
src/ping/pinganalyzer.h
src/ping/pinginterval.h [new file with mode: 0644]
src/ping/pingscheduler.cpp
src/ping/pingscheduler.h

index ff2326e..f54af08 100644 (file)
@@ -23,7 +23,8 @@ PingAnalyzer::PingAnalyzer(
     LimitPingFailPercentage( limit_ping_fail_percentage ),
     ResolvedIpCount( 0 ),
     PingsPerformedCount( 0 ),
-    PingsFailedCount( 0 )
+    PingsFailedCount( 0 ),
+    ExceededPingFailedCountLimit( false )
 {
     BOOST_ASSERT( !host_address.empty() );
     BOOST_ASSERT( ( 0 <= limit_ping_fail_percentage ) && ( limit_ping_fail_percentage <= 100 ) );
@@ -40,6 +41,11 @@ void PingAnalyzer::set_resolved_ip_count( const int resolved_ip_count )
     ResolvedIpCount = resolved_ip_count;
 }
 
+bool PingAnalyzer::exceeded_ping_failed_count_limit() const
+{
+    return ExceededPingFailedCountLimit;
+}
+
 void PingAnalyzer::update_ping_statistics( bool ping_success )
 {
     BOOST_ASSERT( 1 <= ResolvedIpCount );
@@ -57,7 +63,7 @@ void PingAnalyzer::update_ping_statistics( bool ping_success )
     // failed
     if ( tried_all_resolved_ip() )
     {
-        analyze();
+        analyze_ping_statistics();
 
         reset_ping_counters();
     }
@@ -65,7 +71,12 @@ void PingAnalyzer::update_ping_statistics( bool ping_success )
     BOOST_ASSERT( PingsFailedCount <= PingsPerformedCount );
 }
 
-void PingAnalyzer::analyze()
+bool PingAnalyzer::tried_all_resolved_ip() const
+{
+    return ( PingsPerformedCount >= ResolvedIpCount );
+}
+
+void PingAnalyzer::analyze_ping_statistics()
 {
     BOOST_ASSERT( PingsPerformedCount == ResolvedIpCount );
     BOOST_ASSERT( !HostAddress.empty() );
@@ -99,20 +110,17 @@ void PingAnalyzer::increase_ping_failed_count()
 {
     ++PingsFailedCount;
 
+    update_ping_failed_statistics();
+
     BOOST_ASSERT( ( 0 <= PingsFailedCount ) && ( PingsFailedCount <= PingsPerformedCount ) );
 }
 
-bool PingAnalyzer::exceeded_ping_failed_count_limit() const
+void PingAnalyzer::update_ping_failed_statistics()
 {
     BOOST_ASSERT( ( 0 <= LimitPingFailPercentage ) && ( LimitPingFailPercentage <= 100 ) );
     BOOST_ASSERT( ( 0 <= PingsFailedCount ) && ( PingsFailedCount <= PingsPerformedCount ) );
 
     int limit_ping_fail_absolute = LimitPingFailPercentage / 100; // TODO possible precision loss, check with care
 
-    return ( PingsFailedCount > limit_ping_fail_absolute );
-}
-
-bool PingAnalyzer::tried_all_resolved_ip() const
-{
-    return ( PingsPerformedCount >= ResolvedIpCount );
+    ExceededPingFailedCountLimit = ( PingsFailedCount > limit_ping_fail_absolute );
 }
index b9b8c45..f59e339 100644 (file)
@@ -27,15 +27,16 @@ public:
     virtual ~PingAnalyzer();
 
     void set_resolved_ip_count( const int resolved_ip_count );
+    bool exceeded_ping_failed_count_limit() const;
     void update_ping_statistics( bool ping_success );
 
 private:
-    void analyze();
+    bool tried_all_resolved_ip() const;
+    void analyze_ping_statistics();
     void reset_ping_counters();
     void increase_ping_performed_count();
     void increase_ping_failed_count();
-    bool exceeded_ping_failed_count_limit() const;
-    bool tried_all_resolved_ip() const;
+    void update_ping_failed_statistics();
 
 private:
     std::string HostAddress;
@@ -44,6 +45,7 @@ private:
     int ResolvedIpCount;
     int PingsPerformedCount;
     int PingsFailedCount;
+    bool ExceededPingFailedCountLimit;
 
 };
 
diff --git a/src/ping/pinginterval.h b/src/ping/pinginterval.h
new file mode 100644 (file)
index 0000000..0676921
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef PINGINTERVAL_H
+#define PINGINTERVAL_H
+
+//-----------------------------------------------------------------------------
+// PingInterval
+//-----------------------------------------------------------------------------
+
+/**
+ * @brief Class designed to behave like a scalar type (i.e. int, long), but
+ * with helper methods to encapsulate interval computation.
+ * Scope: one object per host.
+ */
+template<typename T>
+class PingInterval
+{
+public:
+    PingInterval( T interval );
+
+    operator T();
+
+    void back_to_original();
+    void speed_up();
+
+private:
+    bool can_speed_up() const;
+
+private:
+    const T OriginalInterval;
+    T Interval;
+
+};
+
+
+template<typename T>
+    PingInterval<T>::PingInterval(
+            T interval
+    ) :
+        OriginalInterval( interval ),
+        Interval( interval )
+    {
+    }
+
+template<typename T>
+    PingInterval<T>::operator T()
+    {
+        return Interval;
+    }
+
+template<typename T>
+    void PingInterval<T>::back_to_original()
+    {
+        Interval = OriginalInterval;
+    }
+
+template<typename T>
+    void PingInterval<T>::speed_up()
+    {
+        if ( can_speed_up() )
+            Interval = Interval / 2;
+    }
+
+template<typename T>
+    bool PingInterval<T>::can_speed_up() const
+    {
+        T half_original = OriginalInterval / 2;
+
+        return (Interval > half_original);
+    }
+
+
+#endif /* PINGINTERVAL_H */
index 0cc0631..05c76b8 100644 (file)
@@ -105,13 +105,38 @@ void PingScheduler::handle_next_ping()
 void PingScheduler::update_ping_statistics( const bool ping_success )
 {
     Analyzer.update_ping_statistics( ping_success );
+
+    // TODO FIX this method, once it has a semantic dependency with the
+    // update_ping_statistics method, because it depends on the PingeAnalyzer
+    // statistics to update the exceeded_ping_failed_count_limit
+    update_ping_interval();
+}
+
+void PingScheduler::update_ping_interval()
+{
+    // must to ping more often?
+    if ( Analyzer.exceeded_ping_failed_count_limit() )
+    {
+        PingIntervalInSec.speed_up();
+
+        cout << "- Speeding up ping interval to: " << PingIntervalInSec
+             << "s" << endl; // TODO output log
+    }
+    else
+    {
+        PingIntervalInSec.back_to_original();
+
+        cout << "- Stick to the original ping interval: " << PingIntervalInSec
+             << "s" << endl; // TODO output log
+    }
 }
 
 void PingScheduler::update_ping_elapsed_time()
 {
     ptime now = microsec_clock::universal_time();
-    cerr << "- Time elapsed since last ping: "
-         << (now - TimeSentLastPing).total_seconds() << "s" << endl; // TODO reformat this message
+    cout << "- Time elapsed since last ping: "
+         << (now - TimeSentLastPing).total_seconds() << "s"
+         << endl; // TODO output log
 
     TimeSentLastPing = microsec_clock::universal_time();
 }
index 24cea1c..7795ba0 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "dns/dnsresolver.h"
 #include "ping/pinganalyzer.h"
+#include "ping/pinginterval.h"
 
 class StatusNotifier;
 
@@ -41,13 +42,14 @@ private:
     void schedule_next_ping();
     void handle_next_ping();
     void update_ping_statistics( const bool ping_success );
+    void update_ping_interval();
     void update_ping_elapsed_time();
 
 private:
     boost::asio::io_service &IoService;
     boost::asio::deadline_timer Timer;
     boost::posix_time::ptime TimeSentLastPing;
-    const long PingIntervalInSec;
+    PingInterval<long> PingIntervalInSec;
     DnsResolver IpList;
     PingAnalyzer Analyzer;