started parallel pings, not quite done yet since need to delay them
[pingcheck] / src / host / hoststatus.cpp
CommitLineData
91fcc471
TJ
1/*
2The software in this package is distributed under the GNU General
3Public License version 2 (with a special exception described below).
4
5A copy of GNU General Public License (GPL) is included in this distribution,
6in the file COPYING.GPL.
7
8As a special exception, if other files instantiate templates or use macros
9or inline functions from this file, or you compile this file and link it
10with other works to produce a work based on this file, this file
11does not by itself cause the resulting work to be covered
12by the GNU General Public License.
13
14However the source code for this file must still be made available
15in accordance with section (3) of the GNU General Public License.
16
17This exception does not invalidate any other reasons why a work based
18on this file might be covered by the GNU General Public License.
19*/
6c14bbee 20#include "host/hoststatus.h"
ddf41c89
GMF
21
22#include <iostream>
3f7c921f 23#include <logfunc.hpp>
ddf41c89 24
780b0bca 25#include "boost_assert_handler.h"
ddf41c89
GMF
26
27using namespace std;
3f7c921f 28using I2n::Logger::GlobalLogger;
ddf41c89
GMF
29
30//-----------------------------------------------------------------------------
6c14bbee 31// HostStatus
ddf41c89
GMF
32//-----------------------------------------------------------------------------
33
c01a6023 34/**
6c14bbee
GMF
35 * @param host_address The address of the host it has to analyze.
36 * @param ping_fail_percentage_limit The percentage threshold of pings that can
c01a6023 37 * fail.
6c14bbee 38 * @param link_analyzer The object used to notify the status of the host.
c01a6023 39 */
6c14bbee 40HostStatus::HostStatus(
ddf41c89 41 const string &host_address,
cd4048df 42 const int ping_fail_limit_percentage,
91aa83f9 43 const int n_parallel_pings,
c6c54dfb 44 const LinkStatusItem link_analyzer
ddf41c89 45) :
c1fff16a 46 HostAddress( host_address ),
fb469ffa 47 LinkAnalyzer( link_analyzer ),
cd4048df 48 PingFailLimitPercentage( ping_fail_limit_percentage ),
ddf41c89
GMF
49 ResolvedIpCount( 0 ),
50 PingsPerformedCount( 0 ),
d8a91bd6 51 PingsFailedCount( 0 ),
91aa83f9
CH
52 ExceededPingFailedLimit( false ),
53 NParallelPingers( n_parallel_pings)
ddf41c89 54{
d4793cc9 55 BOOST_ASSERT( !HostAddress.empty() );
cd4048df 56 BOOST_ASSERT( ( 0 <= PingFailLimitPercentage ) && ( PingFailLimitPercentage <= 100 ) );
ddf41c89
GMF
57}
58
6c14bbee 59HostStatus::~HostStatus()
ddf41c89
GMF
60{
61}
62
c01a6023 63/**
6c14bbee 64 * @param resolved_ip_count The number of IPs resolved for the host.
c01a6023 65 */
6c14bbee 66void HostStatus::set_resolved_ip_count( const int resolved_ip_count )
ddf41c89 67{
838e0acf 68 BOOST_ASSERT( 0 <= resolved_ip_count );
ddf41c89 69
db625177
CH
70 if (resolved_ip_count != ResolvedIpCount)
71 { // assume that the target has changed --> reset counters
72 reset_ping_counters();
73 }
ddf41c89 74 ResolvedIpCount = resolved_ip_count;
3f7c921f 75
03c2a2c3 76 GlobalLogger.debug() << "Stat(" << HostAddress << "): "
3f7c921f 77 << PingsFailedCount << " fail/" << PingsPerformedCount << " pings/"
91aa83f9 78 << ResolvedIpCount << "*" << NParallelPingers << " IPs: #IPs set";
ddf41c89
GMF
79}
80
c01a6023
GMF
81/**
82 * @return true if the amount of failed pings given to the host exceeded the
83 * limit.
84 */
6c14bbee 85bool HostStatus::exceeded_ping_failed_limit() const
d8a91bd6 86{
a341119a 87 return ExceededPingFailedLimit;
d8a91bd6
GMF
88}
89
c01a6023 90/**
96c4e7a4
CH
91 * Tells the status analyzer how the last ping went
92 *
93 * @param result: status of ping specifying success/failure and reason of fail
94 * @param ping_duration_us duration of ping in micro seconds
c01a6023 95 */
96c4e7a4
CH
96void HostStatus::update_ping_statistics( const PingStatus &result,
97 const long ping_duration_us )
ddf41c89 98{
96c4e7a4
CH
99 float ping_duration_ms = static_cast<float>(ping_duration_us) / 1000.;
100
03c2a2c3 101 GlobalLogger.debug() << "Stat(" << HostAddress << "): "
3f7c921f 102 << PingsFailedCount << " fail/" << PingsPerformedCount << " pings/"
91aa83f9
CH
103 << ResolvedIpCount << "*" << NParallelPingers << " IPs: "
104 << "add ping with result " << to_string(result) << " which took "
105 << ping_duration_ms << " ms";
3f7c921f 106
ddf41c89
GMF
107 BOOST_ASSERT( 1 <= ResolvedIpCount );
108 BOOST_ASSERT( 0 <= PingsPerformedCount );
109 BOOST_ASSERT( PingsFailedCount <= PingsPerformedCount );
110
c5e4bfa1 111 increase_ping_performed_count();
ddf41c89 112
96c4e7a4 113 if ( result != PingStatus_SuccessReply )
ddf41c89 114 {
c5e4bfa1 115 increase_ping_failed_count();
ddf41c89
GMF
116 }
117
2c10f87b
GMF
118 analyze_ping_failed_count();
119
c5e4bfa1
GMF
120 // after we tried all IPs resolved for this host, we can analyze how many
121 // failed
122 if ( tried_all_resolved_ip() )
ddf41c89 123 {
d8a91bd6 124 analyze_ping_statistics();
ddf41c89 125
c5e4bfa1 126 reset_ping_counters();
ddf41c89
GMF
127 }
128
129 BOOST_ASSERT( PingsFailedCount <= PingsPerformedCount );
130}
131
c1d776ba 132
6c14bbee 133bool HostStatus::tried_all_resolved_ip() const
d8a91bd6 134{
91aa83f9
CH
135 BOOST_ASSERT( ( 0 < PingsPerformedCount ) &&
136 ( PingsPerformedCount <= ResolvedIpCount*NParallelPingers ) );
d4793cc9 137
91aa83f9 138 return ( PingsPerformedCount == ResolvedIpCount*NParallelPingers );
d8a91bd6
GMF
139}
140
6c14bbee 141void HostStatus::analyze_ping_statistics()
ddf41c89 142{
c1fff16a 143 BOOST_ASSERT( !HostAddress.empty() );
91aa83f9 144 BOOST_ASSERT( PingsPerformedCount == ResolvedIpCount*NParallelPingers );
ddf41c89 145
c1fff16a 146 // notify if the amount of pings that failed exceed the limit
a341119a 147 if ( exceeded_ping_failed_limit() )
ddf41c89 148 {
03c2a2c3 149 GlobalLogger.debug() << "Stat(" << HostAddress << "): "
3f7c921f 150 << PingsFailedCount << " fail/" << PingsPerformedCount << " pings/"
91aa83f9
CH
151 << ResolvedIpCount << "*" << NParallelPingers << " IPs: "
152 << "notify down";
fb469ffa 153 LinkAnalyzer->notify_host_down( HostAddress );
ddf41c89
GMF
154 }
155 else
156 {
03c2a2c3 157 GlobalLogger.debug() << "Stat(" << HostAddress << "): "
3f7c921f 158 << PingsFailedCount << " fail/" << PingsPerformedCount << " pings/"
91aa83f9
CH
159 << ResolvedIpCount << "*" << NParallelPingers << " IPs: "
160 << "notify up";
fb469ffa 161 LinkAnalyzer->notify_host_up( HostAddress );
ddf41c89 162 }
6fd0993e 163} //lint !e1762
ddf41c89 164
6c14bbee 165void HostStatus::reset_ping_counters()
c1fff16a
GMF
166{
167 PingsPerformedCount = 0;
168 PingsFailedCount = 0;
169}
170
6c14bbee 171void HostStatus::increase_ping_performed_count()
c5e4bfa1
GMF
172{
173 ++PingsPerformedCount;
c1fff16a 174
91aa83f9
CH
175 BOOST_ASSERT( ( 0 < PingsPerformedCount ) &&
176 ( PingsPerformedCount <= ResolvedIpCount*NParallelPingers ) );
c5e4bfa1
GMF
177}
178
6c14bbee 179void HostStatus::increase_ping_failed_count()
c5e4bfa1
GMF
180{
181 ++PingsFailedCount;
c1fff16a
GMF
182
183 BOOST_ASSERT( ( 0 <= PingsFailedCount ) && ( PingsFailedCount <= PingsPerformedCount ) );
c5e4bfa1
GMF
184}
185
6c14bbee 186void HostStatus::analyze_ping_failed_count()
ddf41c89 187{
cd4048df 188 BOOST_ASSERT( ( 0 <= PingFailLimitPercentage ) && ( PingFailLimitPercentage <= 100 ) );
c1fff16a
GMF
189 BOOST_ASSERT( ( 0 <= PingsFailedCount ) && ( PingsFailedCount <= PingsPerformedCount ) );
190
91aa83f9
CH
191 int ping_fail_limit_count = ( ResolvedIpCount * PingFailLimitPercentage
192 * NParallelPingers) / 100;
c1fff16a 193
6827496c 194 // keep a boolean variable because the PingsFailedCount can be reseted
cd4048df 195 if ( PingsFailedCount > ping_fail_limit_count )
1d7d7cb2
GMF
196 {
197 ExceededPingFailedLimit = true;
3f7c921f 198
03c2a2c3 199 GlobalLogger.debug() << "Stat(" << HostAddress << "): "
3f7c921f 200 << PingsFailedCount << " fail/" << PingsPerformedCount << " pings/"
91aa83f9
CH
201 << ResolvedIpCount << "*" << NParallelPingers << " IPs: "
202 << "exceed limit=" << ping_fail_limit_count;
1d7d7cb2
GMF
203 }
204 else
205 {
206 ExceededPingFailedLimit = false;
3f7c921f 207
03c2a2c3 208 GlobalLogger.debug() << "Stat(" << HostAddress << "): "
3f7c921f 209 << PingsFailedCount << " fail/" << PingsPerformedCount << " pings/"
91aa83f9
CH
210 << ResolvedIpCount << "*" << NParallelPingers << " IPs: "
211 << "below limit=" << ping_fail_limit_count;
1d7d7cb2 212 }
c5e4bfa1 213}