Implemented the requirement "If we notified an external system that a link is down...
authorGuilherme Maciel Ferreira <guilherme.maciel.ferreira@intra2net.com>
Wed, 30 Mar 2011 10:12:21 +0000 (12:12 +0200)
committerGuilherme Maciel Ferreira <guilherme.maciel.ferreira@intra2net.com>
Wed, 30 Mar 2011 10:12:21 +0000 (12:12 +0200)
- the status of the link is reported only once, when it changes from down to up, or vice versa
- allows to configure the minimum amount of time the link must stays stable in order to report its status

src/main.cpp
src/notify/linkstatusanalyzer.cpp
src/notify/linkstatusanalyzer.h

index e9de4bc..0ff8247 100644 (file)
@@ -25,12 +25,17 @@ int main( int argc, char* argv[] )
         Configuration config = config_reader.get_configuration();
 
         int ping_fail_limit = config.get_ping_fail_limit();
+        int link_up_interval = config.get_link_up_interval();
 
         // TODO init_notifier and get_notifier
         int hosts_down_limit = config.get_hosts_down_limit();
         string status_notifier_cmd = config.get_status_notifier_cmd();
         shared_ptr<LinkStatusAnalyzer> link_analyzer(
-                new LinkStatusAnalyzer( hosts_down_limit, status_notifier_cmd )
+                new LinkStatusAnalyzer(
+                        hosts_down_limit,
+                        link_up_interval,
+                        status_notifier_cmd
+                )
         );
 
         // TODO init_pingers()
index 93f9023..ecc1f8f 100644 (file)
@@ -5,6 +5,7 @@
 #include <boost/assert.hpp>
 
 using namespace std;
+using namespace boost::posix_time;
 
 //-----------------------------------------------------------------------------
 // LinkStatusAnalyzer
@@ -12,13 +13,19 @@ using namespace std;
 
 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() );
 }
 
@@ -81,20 +88,79 @@ bool LinkStatusAnalyzer::exceeded_host_down_limit() const
 
 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;
+    }
 }
index dddc81a..5dedceb 100644 (file)
@@ -4,6 +4,8 @@
 #include <set>
 #include <string>
 
+#include <boost/asio.hpp>
+
 #include "notify/statusnotifiercommand.h"
 
 //-----------------------------------------------------------------------------
@@ -20,6 +22,7 @@ class LinkStatusAnalyzer
 public:
     LinkStatusAnalyzer(
             const int hosts_down_limit,
+            const int link_up_interval_in_min,
             const std::string &status_notifier_cmd
     );
     virtual ~LinkStatusAnalyzer();
@@ -28,6 +31,19 @@ public:
     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 );
 
@@ -36,10 +52,29 @@ private:
     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;
+
 
 };