Commit | Line | Data |
---|---|---|
91fcc471 TJ |
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 | */ | |
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 | |
27 | using namespace std; | |
3f7c921f | 28 | using 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 | 40 | HostStatus::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 | 59 | HostStatus::~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 | 66 | void 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 | 85 | bool 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 |
96 | void 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 | 133 | bool 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 | 141 | void 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 | 165 | void HostStatus::reset_ping_counters() |
c1fff16a GMF |
166 | { |
167 | PingsPerformedCount = 0; | |
168 | PingsFailedCount = 0; | |
169 | } | |
170 | ||
6c14bbee | 171 | void 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 | 179 | void 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 | 186 | void 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 | } |