#include <boost/math/special_functions/round.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/random/linear_congruential.hpp>
+#include <boost/random/uniform_real.hpp>
+#include <boost/random/variate_generator.hpp>
#include <daemonfunc.hpp>
#include <logfunc.hpp>
* 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.
+ * If interval is chosen at random, will have many pingers with different
+ * intervals; to those will assign a random delay in [0, interval].
*
* Called by init_pingers with
* @param hosts list of hosts as obtained from configuration
delay_shifts[curr_interval] += 1.0f;
}
+ // create random number generator
+ typedef boost::rand48 rand_gen_type;
+ typedef boost::uniform_real<float> rand_dist_type;
+ typedef boost::variate_generator< rand_gen_type&,
+ rand_dist_type > rand_var_type;
+ rand_gen_type random_number_generator(
+ boost::numeric_cast<unsigned int>(time(0)) );
+
// second step: divide intervals by counts, round to int
// --> for 18 pingers with a 30s interval, get 30s/18 = 1.66667
+ // for random intervals, use random delays within intervals
BOOST_FOREACH( IntervalCountPair interval_and_count, delay_shifts )
- delay_shifts[interval_and_count.first] =
- boost::numeric_cast<float>(interval_and_count.first) /
- interval_and_count.second;
+ {
+ if ( interval_and_count.second == 1 )
+ { // there is exactly 1 pinger with exactly that interval
+ // --> assign a random delay within interval
+ rand_dist_type random_distribution(0, interval_and_count.first);
+ rand_var_type random_variate(random_number_generator,
+ random_distribution);
+ delay_shifts[interval_and_count.first] = random_variate();
+ }
+ else
+ { // there are several pingers with same interval
+ // --> distribute evenly
+ delay_shifts[interval_and_count.first] =
+ boost::numeric_cast<float>(interval_and_count.first) /
+ interval_and_count.second;
+ }
+ }
return delay_shifts;
}
// calculate delays between pingers of same interval
DelayMap delay_shifts = calc_pinger_delays(configuration->get_hosts());
- // setup memory for assigned delays
+ // setup memory for assigned delays; init with delay > 0
DelayMap delays;
BOOST_FOREACH( IntervalCountPair interval_and_delay, delay_shifts )
delays[interval_and_delay.first] = 0.0f;
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];
+ int current_delay = boost::math::iround(delays[ping_interval_in_sec]);
+ GlobalLogger.notice() << "TEST: assigning delay of " << current_delay
+ << "s to pinger with interval " << ping_interval_in_sec << "s";
PingSchedulerItem scheduler(
new PingScheduler(