From: Guilherme Maciel Ferreira Date: Thu, 24 Mar 2011 13:51:47 +0000 (+0100) Subject: Implemented the requirement "Intelligently retry if a host doesn't reply: Try it... X-Git-Tag: v1.0~115 X-Git-Url: http://developer.intra2net.com/git/?a=commitdiff_plain;h=d8a91bd6354c40b1e671c2ec3a19e626db4a172b;p=pingcheck Implemented the requirement "Intelligently retry if a host doesn't reply: Try it more often" - 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 --- diff --git a/src/ping/pinganalyzer.cpp b/src/ping/pinganalyzer.cpp index ff2326e..f54af08 100644 --- a/src/ping/pinganalyzer.cpp +++ b/src/ping/pinganalyzer.cpp @@ -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 ); } diff --git a/src/ping/pinganalyzer.h b/src/ping/pinganalyzer.h index b9b8c45..f59e339 100644 --- a/src/ping/pinganalyzer.h +++ b/src/ping/pinganalyzer.h @@ -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 index 0000000..0676921 --- /dev/null +++ b/src/ping/pinginterval.h @@ -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 +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 + PingInterval::PingInterval( + T interval + ) : + OriginalInterval( interval ), + Interval( interval ) + { + } + +template + PingInterval::operator T() + { + return Interval; + } + +template + void PingInterval::back_to_original() + { + Interval = OriginalInterval; + } + +template + void PingInterval::speed_up() + { + if ( can_speed_up() ) + Interval = Interval / 2; + } + +template + bool PingInterval::can_speed_up() const + { + T half_original = OriginalInterval / 2; + + return (Interval > half_original); + } + + +#endif /* PINGINTERVAL_H */ diff --git a/src/ping/pingscheduler.cpp b/src/ping/pingscheduler.cpp index 0cc0631..05c76b8 100644 --- a/src/ping/pingscheduler.cpp +++ b/src/ping/pingscheduler.cpp @@ -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(); } diff --git a/src/ping/pingscheduler.h b/src/ping/pingscheduler.h index 24cea1c..7795ba0 100644 --- a/src/ping/pingscheduler.h +++ b/src/ping/pingscheduler.h @@ -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 PingIntervalInSec; DnsResolver IpList; PingAnalyzer Analyzer;