diff --git a/lib/icingadb/icingadb-objects.cpp b/lib/icingadb/icingadb-objects.cpp index c541a7552..db4ab6ab8 100644 --- a/lib/icingadb/icingadb-objects.cpp +++ b/lib/icingadb/icingadb-objects.cpp @@ -117,6 +117,7 @@ void IcingaDB::ConfigStaticInitialize() void IcingaDB::UpdateAllConfigObjects() { + Log(LogInformation, "IcingaDB") << "Starting initial config/status dump"; double startTime = Utility::GetTime(); // Use a Workqueue to pack objects in parallel diff --git a/lib/icingadb/icingadb.cpp b/lib/icingadb/icingadb.cpp index 8e3de34d9..3b90d42e8 100644 --- a/lib/icingadb/icingadb.cpp +++ b/lib/icingadb/icingadb.cpp @@ -63,16 +63,13 @@ void IcingaDB::Start(bool runtimeCreated) m_ConfigDumpInProgress = false; m_ConfigDumpDone = false; - m_Rcon = new RedisConnection(GetHost(), GetPort(), GetPath(), GetPassword(), GetDbIndex()); - m_Rcon->Start(); - m_WorkQueue.SetExceptionCallback([this](boost::exception_ptr exp) { ExceptionHandler(std::move(exp)); }); - m_ReconnectTimer = new Timer(); - m_ReconnectTimer->SetInterval(15); - m_ReconnectTimer->OnTimerExpired.connect([this](const Timer * const&) { ReconnectTimerHandler(); }); - m_ReconnectTimer->Start(); - m_ReconnectTimer->Reschedule(0); + m_Rcon = new RedisConnection(GetHost(), GetPort(), GetPath(), GetPassword(), GetDbIndex()); + m_Rcon->SetConnectedCallback([this](boost::asio::yield_context& yc) { + m_WorkQueue.Enqueue([this]() { OnConnectedHandler(); }); + }); + m_Rcon->Start(); m_StatsTimer = new Timer(); m_StatsTimer->SetInterval(1); @@ -93,23 +90,10 @@ void IcingaDB::ExceptionHandler(boost::exception_ptr exp) << "Exception during redis operation: " << DiagnosticInformation(exp); } -void IcingaDB::ReconnectTimerHandler() -{ - m_WorkQueue.Enqueue([this]() { TryToReconnect(); }); -} - -void IcingaDB::TryToReconnect() +void IcingaDB::OnConnectedHandler() { AssertOnWorkQueue(); - if (m_ConfigDumpDone) - return; - else - m_Rcon->Start(); - - if (!m_Rcon || !m_Rcon->IsConnected()) - return; - if (m_ConfigDumpInProgress || m_ConfigDumpDone) return; diff --git a/lib/icingadb/icingadb.hpp b/lib/icingadb/icingadb.hpp index 41fd0963c..b7edb6f0c 100644 --- a/lib/icingadb/icingadb.hpp +++ b/lib/icingadb/icingadb.hpp @@ -35,8 +35,7 @@ public: virtual void Stop(bool runtimeRemoved) override; private: - void ReconnectTimerHandler(); - void TryToReconnect(); + void OnConnectedHandler(); void PublishStatsTimerHandler(); void PublishStats(); @@ -134,7 +133,6 @@ private: } Timer::Ptr m_StatsTimer; - Timer::Ptr m_ReconnectTimer; WorkQueue m_WorkQueue; String m_PrefixConfigObject; diff --git a/lib/icingadb/redisconnection.cpp b/lib/icingadb/redisconnection.cpp index 94db408d5..9a75885c1 100644 --- a/lib/icingadb/redisconnection.cpp +++ b/lib/icingadb/redisconnection.cpp @@ -233,6 +233,10 @@ void RedisConnection::Connect(asio::yield_context& yc) Log(LogInformation, "IcingaDB", "Connected to Redis server"); + if (m_ConnectedCallback) { + m_ConnectedCallback(yc); + } + break; } catch (const boost::coroutines::detail::forced_unwind&) { throw; @@ -500,3 +504,14 @@ void RedisConnection::WriteOne(RedisConnection::Query& query, asio::yield_contex WriteOne(m_UnixConn, query, yc); } } + +/** + * Specify a callback that is run each time a connection is successfully established + * + * The callback is executed from a Boost.Asio coroutine and should therefore not perform blocking operations. + * + * @param callback Callback to execute + */ +void RedisConnection::SetConnectedCallback(std::function callback) { + m_ConnectedCallback = std::move(callback); +} diff --git a/lib/icingadb/redisconnection.hpp b/lib/icingadb/redisconnection.hpp index 222e99cb3..71777e22e 100644 --- a/lib/icingadb/redisconnection.hpp +++ b/lib/icingadb/redisconnection.hpp @@ -82,6 +82,8 @@ namespace icinga void SuppressQueryKind(QueryPriority kind); void UnsuppressQueryKind(QueryPriority kind); + void SetConnectedCallback(std::function callback); + private: /** * What to do with the responses to Redis queries. @@ -179,6 +181,8 @@ namespace icinga // Indicate that there's something to send/receive AsioConditionVariable m_QueuedWrites, m_QueuedReads; + + std::function m_ConnectedCallback; }; /**