]> granicus.if.org Git - icinga2/commitdiff
Compat IDO: add reconnect to ido2db, if not connected (refs #3207)
authorMichael Friedrich <michael.friedrich@gmail.com>
Sun, 7 Oct 2012 19:47:50 +0000 (21:47 +0200)
committerMichael Friedrich <michael.friedrich@gmail.com>
Sun, 7 Oct 2012 20:02:44 +0000 (22:02 +0200)
components/compatido/compatidocomponent.cpp
components/compatido/compatidocomponent.h
components/compatido/idosocket.cpp
components/compatido/idosocket.h

index f4294f4a59d7652f6b1b03c0a4e04ba71813cabe..a3ff9f3671e6a1c4cc6b05d33873a82bc13d7839 100644 (file)
@@ -24,6 +24,8 @@ using namespace icinga;
 const String CompatIdoComponent::DefaultSocketAddress = "127.0.0.1";
 const String CompatIdoComponent::DefaultSocketPort = "5668";
 const String CompatIdoComponent::DefaultInstanceName = "i2-default";
+const int CompatIdoComponent::DefaultReconnectInterval = 15;
+
 
 /**
  * Reads the socket address from the config
@@ -65,6 +67,19 @@ String CompatIdoComponent::GetInstanceName(void) const
                return instance;
 }
 
+/**
+ * Reads the reconnect interval from the config
+ * @returns reconnect_interval The config option, or static default
+ */
+int CompatIdoComponent::GetReconnectInterval(void) const
+{
+        Value interval = GetConfig()->Get("reconnect_interval");
+        if(interval.IsEmpty())
+                return DefaultReconnectInterval;
+        else   
+                return interval;
+}
+
 /**
  * Starts the component.
  */
@@ -73,6 +88,7 @@ void CompatIdoComponent::Start(void)
        const int StatusTimerInterval = 60;
        const int ConfigTimerInterval = 3600;
        const int ProgramStatusTimerInterval = 15;
+       const int ReconnectTimerInterval = GetReconnectInterval();
 
        /* HINTS - XXX
         * - only tcp sockets
@@ -97,22 +113,59 @@ void CompatIdoComponent::Start(void)
        m_ProgramStatusTimer->Start();
        m_ProgramStatusTimer->Reschedule(0);
 
+       /*
+        * scheck for reconnect once in a while
+        */
+       m_ReconnectTimer = boost::make_shared<Timer>();
+       m_ReconnectTimer->SetInterval(ReconnectTimerInterval);
+       m_ReconnectTimer->OnTimerExpired.connect(boost::bind(&CompatIdoComponent::ReconnectTimerHandler, this));
+       m_ReconnectTimer->Start();
        /*
         * open ido socket once
         */
-       OpenSink(GetSocketAddress(), GetSocketPort());
-       SendHello(GetInstanceName());
+       OpenIdoSocket();
 }
 
+
 /**
  * Stops the component.
  */
 void CompatIdoComponent::Stop(void)
+{
+       CloseIdoSocket();
+}
+
+
+/**
+ * Opens the ido socket, and sends hello to ido2db
+ */
+void CompatIdoComponent::OpenIdoSocket(void)
+{
+       OpenSink(GetSocketAddress(), GetSocketPort());
+
+       /* 
+        * if we're connected, do not reconnecte
+        */
+       if(m_IdoSocket->IsConnected()) {
+               m_IdoSocket->SetReconnect(false);
+
+               /* connected means we can greet ido2db */
+               SendHello(GetInstanceName());
+       } else {
+               m_IdoSocket->SetReconnect(true);
+       }
+}
+
+/*
+ * Sends goodbye to ido2db, and closes ido socket
+ */
+void CompatIdoComponent::CloseIdoSocket(void)
 {
        GoodByeSink();
        CloseSink();
 }
 
+
 /* TODO
  * subscribe to all status updates and checkresults and dump them
  * should remove the periodic statusdata dump
@@ -150,6 +203,34 @@ void CompatIdoComponent::ProgramStatusTimerHandler(void)
         DumpProgramStatusData();
 }
 
+/**
+ * Periodically check if idosocket requires a reconnect
+ */
+void CompatIdoComponent::ReconnectTimerHandler(void)
+{
+        Logger::Write(LogInformation, "compatido", "Checking if ido socket requires reconnect");
+
+       if(m_IdoSocket->GetReconnect()) {
+
+               /* check if we aren't already connected */
+               if(m_IdoSocket->IsConnected()) {
+                       Logger::Write(LogInformation, "compatido", "Already connected to ido socket ... no reconnect necessary.");
+                       return;
+               }
+
+               /* socket was disconnected, recconnect */
+               OpenIdoSocket();
+
+               if(m_IdoSocket->IsConnected()) {
+                       Logger::Write(LogInformation, "compatido", "Successfully reconnected to ido socket");
+               } else {
+                       stringstream message;
+                       message << "Unable to reconnect to ido socket. Trying again in " << GetReconnectInterval() << " sec.";
+                       Logger::Write(LogWarning, "compatido", message.str());
+               }
+       }
+}
+
 
 /**
  * opens a tcp connection to the ido socket
index 4a3fd33457277b8bbb898ed02b302aedaa01682e..148d014750649b0701691c4b2d96061c8bc5299f 100644 (file)
@@ -36,17 +36,24 @@ private:
        Timer::Ptr m_StatusTimer;
        Timer::Ptr m_ConfigTimer;
        Timer::Ptr m_ProgramStatusTimer;
+       Timer::Ptr m_ReconnectTimer;
+
        IdoSocket::Ptr m_IdoSocket;
 
        String GetSocketAddress(void) const;
        String GetSocketPort(void) const;
        String GetInstanceName(void) const;
+       int GetReconnectInterval(void) const;
 
        void ConfigTimerHandler(void);
        void StatusTimerHandler(void);
        void ProgramStatusTimerHandler(void);
+       void ReconnectTimerHandler(void);
+
+       void OpenIdoSocket(void);
+       void CloseIdoSocket(void);
 
-       void OpenSink(String node, String service );
+       void OpenSink(String node, String service);
        void SendHello(String instancename);
        void GoodByeSink(void);
        void CloseSink(void);
@@ -78,6 +85,8 @@ private:
        static const String DefaultSocketAddress;
        static const String DefaultSocketPort;
        static const String DefaultInstanceName;
+       static const int DefaultReconnectInterval;
+
 };
 
 }
index 6e8102a7c260055a1e56062ef41a6d18ca754d5e..b028f2da07ccd48ea90032d4ea10353ee9501593 100644 (file)
@@ -36,6 +36,12 @@ IdoSocket::IdoSocket(TcpClientRole role)
         * signal telling about new data
         */
        OnDataAvailable.connect(boost::bind(&IdoSocket::DataAvailableHandler, this));
+
+       /* 
+        * what to do on disconnect
+        */
+       OnClosed.connect(boost::bind(&IdoSocket::ClientClosedHandler, this));
+
 }
 
 /**
@@ -53,6 +59,49 @@ void IdoSocket::SendMessage(const String& message)
        Write(message.CStr(), message.GetLength());
 }
 
+
+/**
+ *  Handles closed client connect
+ */
+void IdoSocket::ClientClosedHandler(void)
+{
+        try {  
+                CheckException();
+        } catch (const exception& ex) {
+                stringstream message;
+                message << "Error occured for ido socket: " << ex.what();
+
+                Logger::Write(LogWarning, "compatido", message.str());
+        }
+
+        Logger::Write(LogWarning, "compatido", "Lost connection to ido socket");
+
+       SetReconnect(true);
+
+        OnDisconnected(GetSelf());
+}
+
+
+/**
+ * Set reconnect vstate
+ *
+ * @aparam enable Enables the reconnect.
+ */
+void IdoSocket::SetReconnect(bool reconnect)
+{
+       m_Reconnect = reconnect;
+}
+
+/**
+ * Get reconnect state
+ *
+ * @returns reconnect  The reconnect variable
+ */
+bool IdoSocket::GetReconnect(void)
+{
+       return m_Reconnect;
+}
+
 /**
  * Processes inbound data.
  * Currently not used, as we do not receive data from ido sockets
index 890518cfdf2c0b0040b71d8a561564413bd18f62..498677bf566bd347e62ad8c72d31756deda17395 100644 (file)
@@ -39,11 +39,19 @@ public:
        IdoSocket(TcpClientRole role);
 
        void SendMessage(const String& message);
+       void SetReconnect(bool reconnect);
+       bool GetReconnect(void);
 
        boost::signal<void (const IdoSocket::Ptr&, const stringstream&)> OnNewMessage;
 
+        boost::signal<void (const IdoSocket::Ptr&)> OnConnected;
+       boost::signal<void (const IdoSocket::Ptr&)> OnDisconnected;
+
 private:
        void DataAvailableHandler(void);
+       void ClientClosedHandler(void);
+
+       bool m_Reconnect;
 
        friend IdoSocket::Ptr IdoSocketFactory(SOCKET fd, TcpClientRole role);
 };