Compat IDO: add reconnect to ido2db, if not connected (refs #3207)

This commit is contained in:
Michael Friedrich 2012-10-07 21:47:50 +02:00
parent 7c45e460e6
commit d42dd6e03f
4 changed files with 150 additions and 3 deletions

View 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

View 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 OpenSink(String node, String service );
void OpenIdoSocket(void);
void CloseIdoSocket(void);
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;
};
}

View 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

View 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);
};