From: Christian Herdtweck Date: Thu, 8 May 2014 14:32:58 +0000 (+0200) Subject: introduced delays between starts of pingers, so they are evenly distributed in time... X-Git-Url: http://developer.intra2net.com/git/?a=commitdiff_plain;h=59733431f2552351710652ad798c6e77346ae8d1;p=pingcheck introduced delays between starts of pingers, so they are evenly distributed in time right away --- diff --git a/src/host/pingscheduler.cpp b/src/host/pingscheduler.cpp index 9306467..a525399 100644 --- a/src/host/pingscheduler.cpp +++ b/src/host/pingscheduler.cpp @@ -66,7 +66,8 @@ PingScheduler::PingScheduler( const long ping_interval_in_sec, const int ping_fail_percentage_limit, const string &nameserver, - LinkStatusItem link_analyzer + LinkStatusItem link_analyzer, + const int first_delay ) : IoService(), @@ -95,6 +96,7 @@ PingScheduler::PingScheduler( nameserver ); AddressResolvedFirstTime = false; + FirstDelay = first_delay; } /** @@ -145,7 +147,14 @@ bool PingScheduler::start_pinging() else AddressResolvedFirstTime = true; - setup_next_ping(); + if (FirstDelay > 0) + { + GlobalLogger.info() << "Delaying first ping by " << FirstDelay << "s"; + (void) NextPingTimer.expires_from_now( seconds( FirstDelay ) ); + NextPingTimer.async_wait( bind( &PingScheduler::setup_next_ping, this ) ); + } + else + setup_next_ping(); // event processing loop, it is a blocking call! IoService.run(); //lint !e534 diff --git a/src/host/pingscheduler.h b/src/host/pingscheduler.h index e29af24..88888dc 100644 --- a/src/host/pingscheduler.h +++ b/src/host/pingscheduler.h @@ -56,7 +56,8 @@ public: const long ping_interval_in_sec, const int ping_fail_percentage_limit, const std::string &nameserver, - LinkStatusItem link_analyzer + LinkStatusItem link_analyzer, + const int first_delay ); ~PingScheduler(); @@ -110,6 +111,8 @@ private: boost::thread Thread; /// flag that address is resolved, so can start pinging bool AddressResolvedFirstTime; + /// delay for very first ping to avoid lots of simultaneous pings + int FirstDelay; }; diff --git a/src/main.cpp b/src/main.cpp index 586c76b..bd2f004 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -26,6 +26,8 @@ on this file might be covered by the GNU General Public License. #include #include #include +#include +#include #include #include @@ -43,6 +45,10 @@ using boost::asio::io_service; using boost::shared_ptr; using I2n::Logger::GlobalLogger; +// a map from interval (in seconds) to delay (in seconds) +typedef std::pair IntervalCountPair; +typedef std::map DelayMap; + //----------------------------------------------------------------------------- // Declarations //----------------------------------------------------------------------------- @@ -51,6 +57,7 @@ ConfigurationItem get_configuration(int, const char**); LinkStatusItem get_status_notifier(const ConfigurationItem&); void init_logger(); void set_log_output(const ConfigurationItem &); +DelayMap calc_pinger_delays(const HostList &hosts); void init_pingers(const ConfigurationItem&, const LinkStatusItem&, PingSchedulerList*); void start_pingers(const PingSchedulerList&); void stop_pingers(const PingSchedulerList&); @@ -127,6 +134,45 @@ void set_log_output( } } +/** + * @brief calculate delay between pingers to evenly distribute them in time + * + * If there are many pingers with same interval, will get bursts of pings + * and none in-between. This function calculates delays for large numbers + * of hosts with same ping intervals, to distribute them as evenly as + * possible, right from the start (might diverge over time, anyway). + * + * Will not do much good for pingers with many different intervals, but + * then is not required anyway and does no(t much) harm. + * + * Called by init_pingers with + * @param hosts list of hosts as obtained from configuration + * @returns a map from ping interval to delay between pingers of that interval + */ +DelayMap calc_pinger_delays(const HostList &hosts) +{ + // first step: count number of hosts with same intervals + DelayMap delay_shifts; + int curr_interval; + BOOST_FOREACH( HostItem host, hosts ) + { + curr_interval = host->get_interval_in_sec(); + if (! curr_interval) + delay_shifts[curr_interval] = 1.0f; + else + delay_shifts[curr_interval] += 1.0f; + } + + // second step: divide intervals by counts, round to int + // --> for 18 pingers with a 30s interval, get 30s/18 = 1.66667 + BOOST_FOREACH( IntervalCountPair interval_and_count, delay_shifts ) + delay_shifts[interval_and_count.first] = + boost::numeric_cast(interval_and_count.first) / + interval_and_count.second; + + return delay_shifts; +} + void init_pingers( const ConfigurationItem &configuration, const LinkStatusItem &status_notifier, @@ -137,6 +183,14 @@ void init_pingers( string nameserver = configuration->get_nameserver(); int ping_fail_limit = configuration->get_ping_fail_limit(); + // calculate delays between pingers of same interval + DelayMap delay_shifts = calc_pinger_delays(configuration->get_hosts()); + + // setup memory for assigned delays + DelayMap delays; + BOOST_FOREACH( IntervalCountPair interval_and_delay, delay_shifts ) + delays[interval_and_delay.first] = 0.0f; + HostList hosts = configuration->get_hosts(); BOOST_FOREACH( HostItem host, hosts ) { @@ -148,6 +202,11 @@ void init_pingers( host_network_interface; PingProtocolList protocol_list = host->get_ping_protocol_list(); int ping_interval_in_sec = host->get_interval_in_sec(); + + // 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]; + PingSchedulerItem scheduler( new PingScheduler( network_interface, @@ -157,7 +216,8 @@ void init_pingers( ping_interval_in_sec, ping_fail_limit, nameserver, - status_notifier + status_notifier, + current_delay ) ); scheduler_list->push_back( scheduler );