2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
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.
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.
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.
20 #include "link/linkstatus.h"
24 #include <logfunc.hpp>
26 #include "boost_assert_handler.h"
29 using boost::posix_time::microsec_clock;
30 using boost::posix_time::ptime;
31 using I2n::Logger::GlobalLogger;
33 //-----------------------------------------------------------------------------
35 //-----------------------------------------------------------------------------
38 * @brief Creates a link status object.
40 * @param hosts_down_limit The maximum amount of different hosts that can be
41 * down before the system take any action.
42 * @param link_up_interval_in_min The amount of time required to the link to
43 * stay up before notify.
44 * @param link_down_interval_in_min The amount of time required to the link to
45 * stay down before notify.
46 * @param status_notifier_cmd The command used to notify about link status
49 LinkStatus::LinkStatus(
50 const int hosts_down_limit,
51 const int link_up_interval_in_min,
52 const int link_down_interval_in_min,
53 const string &status_notifier_cmd
55 HostsDownLimit( hosts_down_limit ),
57 LinkUpIntervalInMin( link_up_interval_in_min ),
58 LinkDownIntervalInMin( link_down_interval_in_min ),
59 CurrentLinkStatus( Status_Down ),
60 CurrentNotificationStatus( NotificationStatus_NotReported ),
61 TimeLinkStatusChanged( microsec_clock::universal_time() ),
62 StatusNotifierCmd( new StatusNotifierCommand( status_notifier_cmd ) )
64 BOOST_ASSERT( 0 <= hosts_down_limit );
65 BOOST_ASSERT( 0 <= link_up_interval_in_min );
66 BOOST_ASSERT( 0 <= link_down_interval_in_min );
69 LinkStatus::~LinkStatus()
74 * @brief Notify the system that a given host is up. The object takes an
75 * appropriated action to deal with that.
76 * Note: this object does not resolves IPs, thus you have to send the same host
77 * address in order to the object to consider the same host.
79 * @param host_address the DNS/IP address of the host that is up.
81 void LinkStatus::notify_host_up( const string &host_address )
83 BOOST_ASSERT( !host_address.empty() );
85 GlobalLogger.info() << "- Host up: " << host_address << endl;
87 add_host_up( host_address );
89 if ( !exceeded_host_down_limit() )
94 // removed from the list?
95 BOOST_ASSERT( HostsDownList.count( host_address ) == 0 );
99 * @brief Notify the system that a given host is down. The object takes an
100 * appropriated action to deal with that.
101 * Note: this object does not resolves IPs, thus you have to send the same host
102 * address in order to the object to consider the same host.
104 * @param host_address The DNS/IP address of the host that is down.
106 void LinkStatus::notify_host_down( const string &host_address )
108 BOOST_ASSERT( !host_address.empty() );
110 GlobalLogger.info() << "- Host down: " << host_address << endl;
112 add_host_down( host_address );
114 if ( exceeded_host_down_limit() )
119 // inserted in the list?
120 BOOST_ASSERT( HostsDownList.count( host_address ) == 1 );
123 void LinkStatus::add_host_up( const string &host_address )
125 if ( HostsDownList.count( host_address ) > 0 )
127 size_t erased_host_count = HostsDownList.erase( host_address );
129 BOOST_ASSERT( erased_host_count == 1 );
133 void LinkStatus::add_host_down( const string &host_address )
135 (void) HostsDownList.insert( host_address );
138 bool LinkStatus::exceeded_host_down_limit() const
140 int host_down_count = static_cast<int>( HostsDownList.size() );
142 return ( host_down_count > HostsDownLimit );
145 void LinkStatus::notify_link_up()
147 set_link_status( Status_Up );
149 // report the link status only if: it is up longer than a configured amount
150 // of time, and if we haven't reported the new status yet
151 if ( is_link_up_enough_time() && can_report_link_status() )
153 BOOST_ASSERT( CurrentLinkStatus == Status_Up );
154 BOOST_ASSERT( CurrentNotificationStatus == NotificationStatus_NotReported );
156 StatusNotifierCmd->set_token_value(
157 StatusNotifierCommand::StatusToken,
161 bool executed = StatusNotifierCmd->execute();
165 CurrentNotificationStatus = NotificationStatus_Reported;
170 void LinkStatus::notify_link_down()
172 set_link_status( Status_Down );
174 // report the link status only if: it is down longer than a configured amount
175 // of time, and if we haven't reported the new status yet
176 if ( is_link_down_enough_time() && can_report_link_status() )
178 BOOST_ASSERT( CurrentLinkStatus == Status_Down );
179 BOOST_ASSERT( CurrentNotificationStatus == NotificationStatus_NotReported );
181 StatusNotifierCmd->set_token_value(
182 StatusNotifierCommand::StatusToken,
186 bool executed = StatusNotifierCmd->execute();
190 CurrentNotificationStatus = NotificationStatus_Reported;
195 bool LinkStatus::is_link_up_enough_time() const
197 if ( CurrentLinkStatus == Status_Up )
199 ptime now = microsec_clock::universal_time();
200 long amount_time_link_is_up = (now - TimeLinkStatusChanged).total_seconds();
201 long link_up_interval_in_sec = LinkUpIntervalInMin * 60;
203 if ( amount_time_link_is_up >= link_up_interval_in_sec )
212 bool LinkStatus::is_link_down_enough_time() const
214 if ( CurrentLinkStatus == Status_Down )
216 ptime now = microsec_clock::universal_time();
217 long amount_time_link_is_down = (now - TimeLinkStatusChanged).total_seconds();
218 long link_down_interval_in_sec = LinkDownIntervalInMin * 60;
220 if ( amount_time_link_is_down >= link_down_interval_in_sec )
229 bool LinkStatus::can_report_link_status() const
231 return ( CurrentNotificationStatus == NotificationStatus_NotReported );
234 void LinkStatus::set_link_status(
235 const LinkStatus::Status new_link_status
238 // only reset the control flags if the link status has changed
239 if ( new_link_status != CurrentLinkStatus )
241 CurrentLinkStatus = new_link_status;
242 TimeLinkStatusChanged = microsec_clock::universal_time();
244 // have to report the link status change
245 CurrentNotificationStatus = NotificationStatus_NotReported;