added option log-file and option FILE to log-output; use in main and adjusted unit...
[pingcheck] / src / config / configuration.cpp
1 /*
2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
4
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
7
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
13
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
16
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
19 */
20 #include "config/configuration.h"
21
22 #include <set>
23 #include <ctime>   // for seeding random number generator
24 #include <boost/math/special_functions/round.hpp>
25 #include <boost/numeric/conversion/cast.hpp>
26 #include <boost/foreach.hpp>
27 #include <boost/random/uniform_int.hpp>
28 #include <boost/random/variate_generator.hpp>
29
30 #include "boost_assert_handler.h"
31
32 using namespace std;
33 using I2n::Logger::LogLevel;
34 using I2n::Logger::GlobalLogger;
35
36 typedef boost::uniform_int<> rand_dist_type;
37 typedef boost::variate_generator<rand_gen_type&, rand_dist_type> rand_var_type;
38
39 //-----------------------------------------------------------------------------
40 // Configuration
41 //-----------------------------------------------------------------------------
42
43 Configuration::Configuration() :
44     Daemon( false ),
45     LoggingLevel( LogLevel::Error ),
46     LoggingOutput( LogOutput_SYSLOG ),
47     LogFileName( "" ),
48     ConfigFileName( "" ),
49     SourceNetworkInterface( "" ),
50     NameServer( "" ),
51     HostsDownLimit( 0 ),
52     MinHostsDownLimit( 0 ),
53     MaxHostsDownLimit( 50 ),
54     PingFailLimit( 0 ),
55     MinPingFailLimit( 0 ),
56     MaxPingFailLimit( 100 ),
57     StatusNotifierCmd( "" ),
58     LinkUpIntervalInMin( 0 ),
59     LinkDownIntervalInMin( 0 ),
60     MinStableLinkIntervalInMin( 0 ),
61     MaxStableLinkIntervalInMin( 60 ),
62     PingReplyTimeout( 30 ),
63     MaxAddressResolutionAttempts( 10 ),
64     ResolvedIpTtlThreshold( 10 ),
65     DnsCacheFile(""),
66     Hosts(),
67     RatioRandomHosts( 1.0f ),
68     PrintVersion( false ),
69     RandomNumberGenerator( boost::numeric_cast<unsigned int>(time(0)) )
70 {
71 }
72
73 Configuration::~Configuration()
74 {
75 }
76
77 bool Configuration::get_daemon() const
78 {
79     return Daemon;
80 }
81
82 void Configuration::set_daemon( bool daemon )
83 { //lint !e578
84     Daemon = daemon;
85 }
86
87 LogLevel Configuration::get_log_level() const
88 {
89     return LoggingLevel;
90 }
91
92 void Configuration::set_log_level( const LogLevel &log_level )
93 {
94     BOOST_ASSERT( (LogLevel::Emergency <= log_level) && (log_level <= LogLevel::Debug) );
95
96     this->LoggingLevel = log_level;
97 }
98
99 LogOutput Configuration::get_log_output() const
100 {
101     return LoggingOutput;
102 }
103
104 void Configuration::set_log_output( const LogOutput &log_output )
105 {
106     BOOST_ASSERT( (LogOutput_First <= log_output) && (log_output <= LogOutput_Last) );
107
108     this->LoggingOutput = log_output;
109 }
110
111 string Configuration::get_log_file() const
112 {
113     return LogFileName;
114 }
115
116 void Configuration::set_log_file( const std::string &log_file )
117 {
118     BOOST_ASSERT( !log_file.empty() );
119
120     this->LogFileName = log_file;
121 }
122
123 string Configuration::get_config_file_name() const
124 {
125     return ConfigFileName;
126 }
127
128 void Configuration::set_config_file_name( const string &config_file_name )
129 {
130     BOOST_ASSERT( !config_file_name.empty() );
131
132     this->ConfigFileName = config_file_name;
133 }
134
135 string Configuration::get_nameserver() const
136 {
137     return NameServer;
138 }
139
140 void Configuration::set_nameserver( const string &nameserver )
141 {
142     NameServer = nameserver;
143 }
144
145 string Configuration::get_source_network_interface() const
146 {
147     return SourceNetworkInterface;
148 }
149
150 void Configuration::set_source_network_interface(
151         const string &source_network_interface
152 )
153 {
154     SourceNetworkInterface = source_network_interface;
155 }
156
157 int Configuration::get_hosts_down_limit() const
158 {
159     return HostsDownLimit;
160 }
161
162 void Configuration::set_hosts_down_limit( const int hosts_down_limit )
163 {
164     BOOST_ASSERT( ( MinHostsDownLimit <= hosts_down_limit ) && ( hosts_down_limit <= MaxHostsDownLimit ) );
165
166     this->HostsDownLimit = hosts_down_limit;
167 }
168
169 int Configuration::get_ping_fail_limit() const
170 {
171     return PingFailLimit;
172 }
173
174 void Configuration::set_ping_fail_limit( const int ping_fail_limit )
175 {
176     BOOST_ASSERT( ( MinPingFailLimit <= ping_fail_limit ) && ( ping_fail_limit <= MaxPingFailLimit ) );
177
178     PingFailLimit = ping_fail_limit;
179 }
180
181 string Configuration::get_status_notifier_cmd() const
182 {
183     return StatusNotifierCmd;
184 }
185
186 void Configuration::set_status_notifier_cmd( const string &status_notifier_cmd )
187 {
188     BOOST_ASSERT( !status_notifier_cmd.empty() );
189
190     StatusNotifierCmd = status_notifier_cmd;
191 }
192
193 int Configuration::get_link_up_interval_in_min() const
194 {
195     return LinkUpIntervalInMin;
196 }
197
198 void Configuration::set_link_up_interval_in_min(
199         const int link_up_interval_in_min
200 )
201 {
202     BOOST_ASSERT( ( MinStableLinkIntervalInMin <= link_up_interval_in_min ) && ( link_up_interval_in_min <= MaxStableLinkIntervalInMin ) );
203
204     LinkUpIntervalInMin = link_up_interval_in_min;
205 }
206
207 int Configuration::get_link_down_interval_in_min() const
208 {
209     return LinkDownIntervalInMin;
210 }
211
212 void Configuration::set_link_down_interval_in_min(
213         const int link_down_interval_in_min
214 )
215 {
216     BOOST_ASSERT( ( MinStableLinkIntervalInMin <= link_down_interval_in_min ) && ( link_down_interval_in_min <= MaxStableLinkIntervalInMin ) );
217
218     LinkDownIntervalInMin = link_down_interval_in_min;
219 }
220
221 int Configuration::get_ping_reply_timeout() const
222 {
223     return PingReplyTimeout;
224 }
225 void Configuration::set_ping_reply_timeout( const int ping_reply_timeout )
226 {
227     BOOST_ASSERT(ping_reply_timeout > 0 );
228     PingReplyTimeout = ping_reply_timeout;
229 }
230
231 int Configuration::get_max_address_resolution_attempts() const
232 {
233     return MaxAddressResolutionAttempts;
234 }
235 void Configuration::set_max_address_resolution_attempts( const int max_address_resolution_attempts )
236 {
237     BOOST_ASSERT(max_address_resolution_attempts > 0 );
238     MaxAddressResolutionAttempts = max_address_resolution_attempts;
239 }
240
241 int Configuration::get_resolved_ip_ttl_threshold() const
242 {
243     return ResolvedIpTtlThreshold;
244 }
245 void Configuration::set_resolved_ip_ttl_threshold( const int resolved_ip_ttl_threshold )
246 {
247     BOOST_ASSERT(resolved_ip_ttl_threshold >= 0 );
248     ResolvedIpTtlThreshold = resolved_ip_ttl_threshold;
249 }
250
251 void Configuration::set_dns_cache_file( const std::string &dns_cache_file)
252 {
253     BOOST_ASSERT( !dns_cache_file.empty() );
254     DnsCacheFile = dns_cache_file;
255 }
256
257 std::string Configuration::get_dns_cache_file() const
258 {
259     return DnsCacheFile;
260 }
261
262 float Configuration::get_ratio_random_hosts() const
263 {
264     return RatioRandomHosts;
265 }
266
267 void Configuration::set_ratio_random_hosts( const float ratio )
268 {
269     BOOST_ASSERT( (ratio > 0.0f) && (ratio <= 1.0f) );
270     RatioRandomHosts = ratio;
271 }
272
273 HostList Configuration::get_hosts() const
274 {
275     return Hosts;
276 }
277
278 void Configuration::set_hosts( const HostList &hosts_list )
279 {
280     Hosts = hosts_list;
281 }
282
283 bool Configuration::get_print_version()
284 {
285     return PrintVersion;
286 }
287
288 void Configuration::set_print_version( const bool do_print )
289 {
290     PrintVersion = do_print;
291 }
292
293 int Configuration::get_random_number(const int lowest, const int highest)
294 {
295     rand_dist_type random_distribution(lowest, highest);
296     rand_var_type random_variate(RandomNumberGenerator, random_distribution);
297     return random_variate();
298 }
299
300 /**
301  * @brief select RatioRandomHosts of the hosts at random.
302  * changes internal list of hosts
303  * @returns false if could not randomize (e.g. only 1 host
304  *   available or ratio=1)
305  */
306 bool Configuration::randomize_hosts()
307 {
308     // need this a few times
309     unsigned int n_hosts = Hosts.size();
310     float n_hosts_float = boost::numeric_cast<float>(n_hosts);
311
312     // check if RatioRandomHosts == 1
313     if ((1. - RatioRandomHosts) < 0.5/n_hosts_float)
314         return false;
315
316     // determine number of hosts to keep
317     unsigned int n_wanted = boost::math::iround(n_hosts_float * RatioRandomHosts);
318     if (n_wanted == 0)
319         n_wanted = 1; // want at least 1 host
320     if (n_wanted == n_hosts)   // e.g. always the case if only 1 host given
321         return false;
322
323     GlobalLogger.info() << "randomizing hosts: keeping "
324                 << n_wanted << " from overall " << n_hosts;
325
326     BOOST_ASSERT(n_wanted <= n_hosts);   // just to be sure
327
328     // create new set of hosts (more efficient than removal from std::vector Hosts)
329     std::set<HostItem> new_hosts;
330     int take_idx;
331
332     // add hosts at random until size is good
333     rand_dist_type random_distribution(0, n_hosts-1);
334     rand_var_type random_variate(RandomNumberGenerator, random_distribution);
335     while (new_hosts.size() < n_wanted)
336     {
337         take_idx = random_variate();
338         new_hosts.insert( Hosts[take_idx] ); // does nothing if host is already in there
339     }
340
341     // convert from set to list
342     HostList new_list;
343     BOOST_FOREACH(HostItem host, new_hosts)
344         new_list.push_back(host);
345
346     this->Hosts = new_list;
347
348     return true;
349 }
350