#include <boost/assert.hpp>
using namespace std;
+using namespace boost::posix_time;
//-----------------------------------------------------------------------------
// LinkStatusAnalyzer
LinkStatusAnalyzer::LinkStatusAnalyzer(
const int hosts_down_limit,
+ const int link_up_interval_in_min,
const string &status_notifier_cmd
) :
HostsDownLimit( hosts_down_limit ),
- StatusNotifierCmd( status_notifier_cmd ),
- HostsDownList()
+ HostsDownList(),
+ LinkUpIntervalInMin( link_up_interval_in_min ),
+ CurrentLinkStatus( LinkStatus_Down ),
+ CurrentNotificationStatus( NotificationStatus_NotReported ),
+ TimeLinkStatusChanged( microsec_clock::universal_time() ),
+ StatusNotifierCmd( status_notifier_cmd )
{
BOOST_ASSERT( 0 <= hosts_down_limit );
+ BOOST_ASSERT( 0 <= link_up_interval_in_min );
BOOST_ASSERT( !status_notifier_cmd.empty() );
}
void LinkStatusAnalyzer::notify_link_up()
{
- StatusNotifierCmd.set_token_value(
- StatusNotifierCommand::StatusToken,
- "up"
- );
+ set_link_status( LinkStatus_Up );
- StatusNotifierCmd.execute();
+ // report the link status only if it is up longer than a configured amount
+ // of time and if we haven't reported the new status yet
+ if ( is_link_up_enough_time() && can_report_link_status() )
+ {
+ BOOST_ASSERT( CurrentLinkStatus == LinkStatus_Up );
+ BOOST_ASSERT( CurrentNotificationStatus == NotificationStatus_NotReported );
+
+ StatusNotifierCmd.set_token_value(
+ StatusNotifierCommand::StatusToken,
+ "up"
+ );
+
+ StatusNotifierCmd.execute();
+
+ CurrentNotificationStatus = NotificationStatus_Reported;
+ }
}
void LinkStatusAnalyzer::notify_link_down()
{
- StatusNotifierCmd.set_token_value(
- StatusNotifierCommand::StatusToken,
- "down"
- );
+ set_link_status( LinkStatus_Down );
+
+ if ( can_report_link_status() )
+ {
+ BOOST_ASSERT( CurrentLinkStatus == LinkStatus_Down );
+ BOOST_ASSERT( CurrentNotificationStatus == NotificationStatus_NotReported );
- StatusNotifierCmd.execute();
+ StatusNotifierCmd.set_token_value(
+ StatusNotifierCommand::StatusToken,
+ "down"
+ );
+
+ StatusNotifierCmd.execute();
+
+ CurrentNotificationStatus = NotificationStatus_Reported;
+ }
+}
+
+bool LinkStatusAnalyzer::is_link_up_enough_time() const
+{
+ if ( CurrentLinkStatus == LinkStatus_Up )
+ {
+ ptime now = microsec_clock::universal_time();
+ long amount_time_link_is_up = (now - TimeLinkStatusChanged).total_seconds();
+ long link_up_interval_in_sec = LinkUpIntervalInMin * 60;
+
+ if ( amount_time_link_is_up >= link_up_interval_in_sec )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool LinkStatusAnalyzer::can_report_link_status() const
+{
+ return ( CurrentNotificationStatus == NotificationStatus_NotReported );
+}
+
+void LinkStatusAnalyzer::set_link_status(
+ const LinkStatusAnalyzer::LinkStatus new_link_status
+)
+{
+ // only reset the control flags if the link status has changed
+ if ( new_link_status != CurrentLinkStatus )
+ {
+ CurrentLinkStatus = new_link_status;
+ TimeLinkStatusChanged = microsec_clock::universal_time();
+
+ // have to report the link status change
+ CurrentNotificationStatus = NotificationStatus_NotReported;
+ }
}
#include <set>
#include <string>
+#include <boost/asio.hpp>
+
#include "notify/statusnotifiercommand.h"
//-----------------------------------------------------------------------------
public:
LinkStatusAnalyzer(
const int hosts_down_limit,
+ const int link_up_interval_in_min,
const std::string &status_notifier_cmd
);
virtual ~LinkStatusAnalyzer();
void notify_host_down( const std::string &host_address );
private:
+ enum LinkStatus
+ {
+ LinkStatus_Up,
+ LinkStatus_Down
+ };
+
+ enum NotificationStatus
+ {
+ NotificationStatus_NotReported,
+ NotificationStatus_Reported
+ };
+
+private:
void add_host_up( const std::string &host_address );
void add_host_down( const std::string &host_address );
void notify_link_up();
void notify_link_down();
+ bool is_link_up_enough_time() const;
+
+ bool can_report_link_status() const;
+ void set_link_status(
+ const LinkStatusAnalyzer::LinkStatus new_link_status
+ );
+
private:
+ /// the maximum amount of hosts which can be down before sound the alarm
const int HostsDownLimit;
- StatusNotifierCommand StatusNotifierCmd;
+ /// list of host down (obvious isn't it?)
std::set<std::string> HostsDownList;
+ /// interval the link have to be stable in order to consider it is functional
+ const int LinkUpIntervalInMin;
+ /// keep track of the actual link status
+ LinkStatusAnalyzer::LinkStatus CurrentLinkStatus;
+ /// indicates if was notified the last link status change
+ LinkStatusAnalyzer::NotificationStatus CurrentNotificationStatus;
+ /// when was the last time the status changed
+ boost::posix_time::ptime TimeLinkStatusChanged;
+ ///
+ StatusNotifierCommand StatusNotifierCmd;
+
};