config/option/sourcenetworkinterfaceoption.cpp
config/option/statusnotifiercmdoption.cpp
config/option/versionoption.cpp
+ config/option/ratiorandomhostsoption.cpp
dns/dnsresolver.cpp
dns/dnsresolverfactory.cpp
dns/hostaddress.cpp
*/
#include "config/configuration.h"
+#include <set>
+#include <ctime> // for seeding random number generator
#include <boost/assert.hpp>
+#include <boost/math/special_functions/round.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/foreach.hpp>
+#include <boost/random/uniform_int.hpp>
+#include <boost/random/variate_generator.hpp>
using namespace std;
using I2n::Logger::LogLevel;
+using I2n::Logger::GlobalLogger;
+
+typedef boost::uniform_int<> rand_dist_type;
+typedef boost::variate_generator<rand_gen_type&, rand_dist_type> rand_var_type;
//-----------------------------------------------------------------------------
// Configuration
LinkDownIntervalInMin( 0 ),
MinStableLinkIntervalInMin( 0 ),
MaxStableLinkIntervalInMin( 60 ),
- Hosts()
+ Hosts(),
+ RatioRandomHosts( 1.0f ),
+ RandomNumberGenerator( boost::numeric_cast<unsigned int>(time(0)) )
{
}
LinkDownIntervalInMin = link_down_interval_in_min;
}
+float Configuration::get_ratio_random_hosts() const
+{
+ return RatioRandomHosts;
+}
+
+void Configuration::set_ratio_random_hosts( const float ratio )
+{
+ BOOST_ASSERT( (ratio > 0.0f) && (ratio <= 1.0f) );
+ this->RatioRandomHosts = ratio;
+}
+
HostList Configuration::get_hosts() const
{
return Hosts;
this->Hosts = hosts_list;
}
+int Configuration::get_random_number(const int lowest, const int highest)
+{
+ rand_dist_type random_distribution(lowest, highest);
+ rand_var_type random_variate(RandomNumberGenerator, random_distribution);
+ return random_variate();
+}
+
+/**
+ * @brief select RatioRandomHosts of the hosts at random.
+ * changes internal list of hosts
+ * @returns false if could not randomize (e.g. only 1 host
+ * available or ratio=1)
+ */
+bool Configuration::randomize_hosts()
+{
+ // need this a few times
+ unsigned int n_hosts = Hosts.size();
+ float n_hosts_float = boost::numeric_cast<float>(n_hosts);
+
+ // check if RatioRandomHosts == 1
+ if ((1. - RatioRandomHosts) < 0.5/n_hosts_float)
+ return false;
+
+ // determine number of hosts to keep
+ unsigned int n_wanted = boost::math::iround(n_hosts_float * RatioRandomHosts);
+ if (n_wanted == 0)
+ n_wanted = 1; // want at least 1 host
+ if (n_wanted == n_hosts) // e.g. always the case if only 1 host given
+ return false;
+
+ GlobalLogger.info() << "randomizing hosts: keeping "
+ << n_wanted << " from overall " << n_hosts;
+
+ BOOST_ASSERT(n_wanted <= n_hosts); // just to be sure
+
+ // create new set of hosts (more efficient than removal from std::vector Hosts)
+ std::set<HostItem> new_hosts;
+ int take_idx;
+
+ // add hosts at random until size is good
+ rand_dist_type random_distribution(0, n_hosts-1);
+ rand_var_type random_variate(RandomNumberGenerator, random_distribution);
+ while (new_hosts.size() < n_wanted)
+ {
+ take_idx = random_variate();
+ new_hosts.insert( Hosts[take_idx] ); // does nothing if host is already in there
+ }
+
+ // convert from set to list
+ HostList new_list;
+ BOOST_FOREACH(HostItem host, new_hosts)
+ new_list.push_back(host);
+
+ this->Hosts = new_list;
+
+ return true;
+}
+
#include <logfunc.hpp>
#include <boost/shared_ptr.hpp>
+#include <boost/random/linear_congruential.hpp>
#include "config/host.h"
#include "host/loglevel.h"
// Configuration
//-----------------------------------------------------------------------------
+typedef boost::rand48 rand_gen_type;
+
/**
* @brief This class works like a POD (Plain Old Data) for configuration options.
*/
int get_link_down_interval_in_min() const;
void set_link_down_interval_in_min( const int link_down_interval_in_min );
+ float get_ratio_random_hosts() const;
+ void set_ratio_random_hosts( const float ratio );
+
HostList get_hosts() const;
void set_hosts( const HostList &hosts_list );
+ bool randomize_hosts();
+
+ int get_random_number(const int lowest, const int highest);
+
private:
bool Daemon;
I2n::Logger::LogLevel LoggingLevel;
int LinkDownIntervalInMin;
int MinStableLinkIntervalInMin;
int MaxStableLinkIntervalInMin;
+ float RatioRandomHosts;
HostList Hosts;
-
+ rand_gen_type RandomNumberGenerator;
};
//-----------------------------------------------------------------------------
#include "config/option/sourcenetworkinterfaceoption.h"
#include "config/option/statusnotifiercmdoption.h"
#include "config/option/versionoption.h"
+#include "config/option/ratiorandomhostsoption.h"
using namespace std;
using boost::program_options::option_description;
ConfigurationOptionItem status_notifier_cmd( new StatusNotifierCmdOption );
ConfigOptions.push_back( status_notifier_cmd );
+ ConfigurationOptionItem ratio_random_hosts( new RatioRandomHostsOption );
+ ConfigOptions.push_back( ratio_random_hosts );
+
HostConfigurationOptionItem host_name( new HostNameOption );
HostOptions.push_back( host_name );
#include <boost/assert.hpp>
#include <boost/foreach.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include <stringfunc.hxx> // I2n::trim
#include <logfunc.hpp>
// HostPingIntervalOption
//-----------------------------------------------------------------------------
+const std::string range_separator = "...";
+const int failure_interval = 60;
+
HostPingIntervalOption::HostPingIntervalOption() :
HostConfigurationOption(
"host.interval",
- value< vector<int> >(),//->default_value( 60 ), // 60 seconds
+ value< vector<std::string> >(),
"Interval between each ping to the host."
)
{
size_t hosts_count = 0;
size_t hosts_intervals_count = 0;
bool parsed_success = false;
+ size_t range_separator_pos = 0;
+ std::string interval_part;
+ int host_interval = 0;
+ int host_interval_lower = 0;
+ int host_interval_upper = 0;
// [host] interval
if ( 1 <= vm.count( get_command_string() ) )
HostList::iterator hosts_list_iterator = hosts_list.begin();
hosts_count = hosts_list.size();
- vector<int> hosts_intervals_list = vm[ get_command_string() ].as< vector<int> >();
+ vector<std::string> hosts_intervals_list =
+ vm[ get_command_string() ].as< vector<std::string> >();
hosts_intervals_count = hosts_intervals_list.size();
BOOST_ASSERT( hosts_count >= hosts_intervals_count );
- BOOST_FOREACH( int host_interval_in_sec, hosts_intervals_list )
- {
- BOOST_ASSERT( 0 < host_interval_in_sec );
+ parsed_success = true;
+ BOOST_FOREACH( std::string host_interval_str, hosts_intervals_list )
+ {
HostItem host_item = *hosts_list_iterator;
- host_item->set_interval_in_sec( host_interval_in_sec );
- ++hosts_list_iterator;
- GlobalLogger.info() << get_command_string() << "="
- << host_interval_in_sec << endl;
- }
+ // look for range_separator
+ host_interval_str = I2n::trim(host_interval_str);
+ range_separator_pos = host_interval_str.find(range_separator);
+
+ try
+ {
+ if (range_separator_pos == std::string::npos)
+ {
+ // no separator --> assume a fixed interval as single number
+ host_interval = boost::lexical_cast<int>(host_interval_str);
+ BOOST_ASSERT( 0 < host_interval );
+ GlobalLogger.info() << get_command_string() << "="
+ << host_interval << endl;
+ }
+ else
+ {
+ // found separator --> chose interval value from interval
+ interval_part = I2n::trim(host_interval_str.substr(0, range_separator_pos));
+ host_interval_lower = boost::lexical_cast<int>(interval_part);
+ interval_part = I2n::trim(host_interval_str.substr(range_separator_pos+3));
+ host_interval_upper = boost::lexical_cast<int>(interval_part);
+
+ BOOST_ASSERT( (0 < host_interval_lower) &&
+ (host_interval_lower <= host_interval_upper) );
+
+ // create random number within this interval
+ host_interval = configuration->get_random_number(host_interval_lower,
+ host_interval_upper);
+
+ GlobalLogger.info() << get_command_string() << "=" << host_interval
+ << " from range " << host_interval_lower << "..." << host_interval_upper
+ << endl;
+ }
+ host_item->set_interval_in_sec( host_interval );
+ }
+
+ catch (boost::bad_lexical_cast &exc)
+ {
+ GlobalLogger.error() << "Error interpreting host ping interval: could not interprete \""
+ << host_interval_str << "\"! Set interval to 60s";
+ host_item->set_interval_in_sec( failure_interval );
+ parsed_success = false;
+ }
- parsed_success = true;
+ ++hosts_list_iterator;
+ } //eo foreach host interval
}
set_hosts_count( hosts_intervals_count );
--- /dev/null
+/*
+ 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 "config/option/ratiorandomhostsoption.h"
+
+#include <logfunc.hpp>
+
+using namespace std;
+using boost::program_options::value;
+using boost::program_options::variables_map;
+using I2n::Logger::GlobalLogger;
+
+//-----------------------------------------------------------------------------
+// RatioRandomHostsOption
+//-----------------------------------------------------------------------------
+
+RatioRandomHostsOption::RatioRandomHostsOption() :
+ ConfigurationOption(
+ "ratio-random-hosts",
+ value<float>()->default_value( 1.0f ),
+ "Ratio in (0,1] of hosts to use, picking them at random from host list"
+ )
+{
+}
+
+RatioRandomHostsOption::~RatioRandomHostsOption()
+{
+}
+
+bool RatioRandomHostsOption::parse(
+ const variables_map& vm,
+ Configuration *configuration
+)
+{
+ // default-source-network-interface
+ if ( 1 <= vm.count( get_command_string() ) )
+ {
+ float ratio_random_hosts = vm[ get_command_string() ].as<float> ();
+ configuration->set_ratio_random_hosts( ratio_random_hosts );
+
+ GlobalLogger.info() << get_command_string() << "="
+ << ratio_random_hosts << endl;
+
+ return true;
+ }
+
+ return false;
+}
--- /dev/null
+/*
+ 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 RATIO_RANDOM_HOSTS_OPTION_H
+#define RATIO_RANDOM_HOSTS_OPTION_H
+
+#include <boost/program_options.hpp>
+
+#include "config/option/configurationoption.h"
+
+//-----------------------------------------------------------------------------
+// RatioRandomHostsOption
+//-----------------------------------------------------------------------------
+
+/**
+ * @brief This class represents the ""Ratio in (0,1] of hosts to use, picking
+ * them at random from host list" configuration option.
+ */
+class RatioRandomHostsOption : public ConfigurationOption
+{
+public:
+ RatioRandomHostsOption();
+ virtual ~RatioRandomHostsOption();
+
+ virtual bool parse(
+ const boost::program_options::variables_map &vm,
+ Configuration *configuration
+ );
+
+};
+
+#endif // RATIO_RANDOM_HOSTS_OPTION_H
string nameserver = configuration->get_nameserver();
int ping_fail_limit = configuration->get_ping_fail_limit();
+ // remove some hosts at random
+ configuration->randomize_hosts();
+
// calculate delays between pingers of same interval
DelayMap delay_shifts = calc_pinger_delays(configuration->get_hosts());
${CMAKE_SOURCE_DIR}/src/config/option/sourcenetworkinterfaceoption.cpp
${CMAKE_SOURCE_DIR}/src/config/option/statusnotifiercmdoption.cpp
${CMAKE_SOURCE_DIR}/src/config/option/versionoption.cpp
+ ${CMAKE_SOURCE_DIR}/src/config/option/ratiorandomhostsoption.cpp
${CMAKE_SOURCE_DIR}/src/host/loglevel.cpp
${CMAKE_SOURCE_DIR}/src/host/logoutput.cpp
${CMAKE_SOURCE_DIR}/src/host/pingprotocol.cpp
${CMAKE_SOURCE_DIR}/src/config/option/sourcenetworkinterfaceoption.cpp
${CMAKE_SOURCE_DIR}/src/config/option/statusnotifiercmdoption.cpp
${CMAKE_SOURCE_DIR}/src/config/option/versionoption.cpp
+ ${CMAKE_SOURCE_DIR}/src/config/option/ratiorandomhostsoption.cpp
${CMAKE_SOURCE_DIR}/src/host/loglevel.cpp
${CMAKE_SOURCE_DIR}/src/host/logoutput.cpp
${CMAKE_SOURCE_DIR}/src/host/pingprotocol.cpp
${CMAKE_SOURCE_DIR}/src/config/option/sourcenetworkinterfaceoption.cpp
${CMAKE_SOURCE_DIR}/src/config/option/statusnotifiercmdoption.cpp
${CMAKE_SOURCE_DIR}/src/config/option/versionoption.cpp
+ ${CMAKE_SOURCE_DIR}/src/config/option/ratiorandomhostsoption.cpp
${CMAKE_SOURCE_DIR}/src/host/loglevel.cpp
${CMAKE_SOURCE_DIR}/src/host/logoutput.cpp
${CMAKE_SOURCE_DIR}/src/host/pingprotocol.cpp