From: Christian Herdtweck Date: Tue, 26 May 2015 13:10:43 +0000 (+0200) Subject: use line digestion recognition in PingScheduler; X-Git-Url: http://developer.intra2net.com/git/?p=pingcheck;a=commitdiff_plain;h=242e5fb3c0c7b8c212587886bb92891a7f70cdef use line digestion recognition in PingScheduler; * created new PingNumber based on PingInterval * moved creation of pingers just before calling Pinger->ping * moved creation of DnsResolver to prepare_next_ping * removed unnecessary arg to update_dns_resolver * fixed bug in HostStatus::log_prefix --- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2b6b7e3..d0bd59c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -77,6 +77,7 @@ set(SOURCES host/pinger.cpp host/pingerfactory.cpp host/pinginterval.cpp + host/pingnumber.cpp host/pingprotocol.cpp host/pingscheduler.cpp tools/pcap.cpp diff --git a/src/host/hoststatus.cpp b/src/host/hoststatus.cpp index 4887bdc..7904bd1 100644 --- a/src/host/hoststatus.cpp +++ b/src/host/hoststatus.cpp @@ -75,6 +75,17 @@ HostStatus::~HostStatus() } +void HostStatus::set_n_parallel_pings(const int n_parallel_pings) +{ + if (NParallelPingers != n_parallel_pings) + { + NParallelPingers = n_parallel_pings; + reset_ping_counters(); + } + GlobalLogger.debug() << log_prefix() << "#pingers set"; +} + + std::string HostStatus::log_prefix() { std::stringstream temp; @@ -82,6 +93,7 @@ std::string HostStatus::log_prefix() << PingsFailedCount << " fail," << PingCongestionCount << " cong/" << PingsPerformedCount << " pings/" << ResolvedIpCount << "*" << NParallelPingers << " IPs: "; + return temp.str(); } /** @@ -127,7 +139,7 @@ bool HostStatus::exceeded_ping_congestion_limit() const void HostStatus::update_ping_statistics( const PingStatus &result, const long ping_duration_us ) { - float ping_duration_ms = static_cast(ping_duration_us) / 1000.; + float ping_duration_ms = static_cast(ping_duration_us) / 1000.0f; GlobalLogger.debug() << log_prefix() << "add ping with result " << to_string(result) << " which took " << ping_duration_ms << " ms"; diff --git a/src/host/hoststatus.h b/src/host/hoststatus.h index 1bb5a08..6e3e3d2 100644 --- a/src/host/hoststatus.h +++ b/src/host/hoststatus.h @@ -52,6 +52,7 @@ public: bool exceeded_ping_congestion_limit() const; void update_ping_statistics( const PingStatus &ping_success, const long ping_duration_us ); + void set_n_parallel_pings(const int n_parallel_pings); private: void update_fail_stats( const PingStatus &ping_success ); diff --git a/src/host/pinginterval.cpp b/src/host/pinginterval.cpp index cadc3f4..1b14f6d 100644 --- a/src/host/pinginterval.cpp +++ b/src/host/pinginterval.cpp @@ -69,9 +69,8 @@ void PingInterval::speed_up() BOOST_ASSERT( 0 < Interval ); } +/** returns true if have not speeded up yet */ bool PingInterval::can_speed_up() const { - PingIntervalType half_original = OriginalInterval / 2; - - return ( Interval > half_original ); + return Interval == OriginalInterval; } diff --git a/src/host/pingnumber.cpp b/src/host/pingnumber.cpp new file mode 100644 index 0000000..66af38a --- /dev/null +++ b/src/host/pingnumber.cpp @@ -0,0 +1,71 @@ +/* +The software in this package is distributed under the GNU General +Public License version 2 (with a special exception described below). + +A copy of GNU General Public License (GPL) is included in this distribution, +in the file COPYING.GPL. + +As a special exception, if other files instantiate templates or use macros +or inline functions from this file, or you compile this file and link it +with other works to produce a work based on this file, this file +does not by itself cause the resulting work to be covered +by the GNU General Public License. + +However the source code for this file must still be made available +in accordance with section (3) of the GNU General Public License. + +This exception does not invalidate any other reasons why a work based +on this file might be covered by the GNU General Public License. +*/ +#include "host/pingnumber.h" + +#include "boost_assert_handler.h" + +//----------------------------------------------------------------------------- +// PingNumber +//----------------------------------------------------------------------------- + +PingNumber::PingNumber( + const PingNumberType number +) : + OriginalNumber( number ), + Number( number ) +{ + BOOST_ASSERT( 0 < number ); +} + +PingNumber::~PingNumber() +{ +} + +PingNumber::operator PingNumberType() const +{ + BOOST_ASSERT( 0 < Number ); + + return Number; +} + +void PingNumber::back_to_original() +{ + Number = OriginalNumber; + + BOOST_ASSERT( 0 < Number ); +} + +void PingNumber::increase() +{ + BOOST_ASSERT( 0 < Number ); + + if ( can_increase() ) + { + Number = Number * 5; + } + + BOOST_ASSERT( 0 < Number ); +} + +/** returns true if have not increased yet */ +bool PingNumber::can_increase() const +{ + return Number == OriginalNumber; +} diff --git a/src/host/pingnumber.h b/src/host/pingnumber.h new file mode 100644 index 0000000..1231ed6 --- /dev/null +++ b/src/host/pingnumber.h @@ -0,0 +1,62 @@ +/* +The software in this package is distributed under the GNU General +Public License version 2 (with a special exception described below). + +A copy of GNU General Public License (GPL) is included in this distribution, +in the file COPYING.GPL. + +As a special exception, if other files instantiate templates or use macros +or inline functions from this file, or you compile this file and link it +with other works to produce a work based on this file, this file +does not by itself cause the resulting work to be covered +by the GNU General Public License. + +However the source code for this file must still be made available +in accordance with section (3) of the GNU General Public License. + +This exception does not invalidate any other reasons why a work based +on this file might be covered by the GNU General Public License. +*/ +#ifndef PING_NUMBER_H +#define PING_NUMBER_H + +//----------------------------------------------------------------------------- +// PingNumberType +//----------------------------------------------------------------------------- + +typedef int PingNumberType; + +//----------------------------------------------------------------------------- +// PingNumber +//----------------------------------------------------------------------------- + +/** + * @brief Class designed to behave like a scalar type (i.e. int, long), but + * with helper methods to encapsulate a increase of ping number and a return + * to the original number + * + * Scope: one object per host. + */ +class PingNumber +{ +public: + PingNumber( const PingNumberType number ); + ~PingNumber(); + + operator PingNumberType() const; + + void back_to_original(); + void increase(); + +private: + bool can_increase() const; + +private: + /// the original number to ping, unchangeable + const PingNumberType OriginalNumber; + /// the actual number exported by this object + PingNumberType Number; + +}; + +#endif // PING_NUMBER_H diff --git a/src/host/pingscheduler.cpp b/src/host/pingscheduler.cpp index 464373a..7b06778 100644 --- a/src/host/pingscheduler.cpp +++ b/src/host/pingscheduler.cpp @@ -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-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; countis_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 diff --git a/src/host/pingscheduler.h b/src/host/pingscheduler.h index adb4a97..2916058 100644 --- a/src/host/pingscheduler.h +++ b/src/host/pingscheduler.h @@ -33,6 +33,7 @@ on this file might be covered by the GNU General Public License. #include "host/pingstatus.h" #include "host/pinger.h" #include "host/pinginterval.h" +#include "host/pingnumber.h" #include "host/pingprotocol.h" #include "dns/resolverbase.h" @@ -80,6 +81,7 @@ private: void ping_done_handler(const PingStatus &result, const long ping_duration_us); void update_ping_interval(); + void update_ping_number(); void init_ping_protocol(); void update_ping_protocol(); @@ -87,11 +89,11 @@ private: bool can_change_ping_protocol() const; void prepare_next_ping(); - void update_dns_resolver( PingProtocol current_protocol ); + void update_dns_resolver(); void ping_when_ready(); void delayed_ping( const boost::system::error_code &error, - const boost::asio::ip::address &ip, + const boost::asio::ip::address ip, const int pinger_index ); void dns_resolve_callback(const bool was_success, const int recursion_count); @@ -118,6 +120,8 @@ private: PingProtocolList::const_iterator ProtocolIter; /// Interval between each ping to the same host PingInterval PingIntervalInSec; + /// number of pingers that work in parallel + PingNumber NPingers; /// delay for very first ping to avoid lots of simultaneous pings at startup int FirstDelay; /// Timer to trigger the next ping @@ -132,8 +136,6 @@ private: ResolverItem Resolver; /// vector of 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 diff --git a/src/main.cpp b/src/main.cpp index 940f455..597b143 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -279,7 +279,7 @@ bool init_pingers( // get delay for this scheduler and update assigned delays int current_delay = boost::math::iround(delays[ping_interval_in_sec]); delays[ping_interval_in_sec] += delay_shifts[ping_interval_in_sec]; - int n_parallel_pings = 10; + int n_parallel_pings = 2; int parallel_ping_delay = 100; // ms int congestion_duration_thresh = 10; // seconds int congestion_percentage_thresh = 75;