From 959e2501aaffe630245726d8cdcce3c2699e2b4f Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Fri, 15 Jul 2016 09:40:39 +0200 Subject: [PATCH] Avoid duplicate entries in the icinga_objects table for commands refs #12147 --- lib/db_ido/commanddbobject.cpp | 4 +--- lib/db_ido/dbconnection.cpp | 14 ++++++++++++- lib/db_ido/dbconnection.hpp | 4 ++++ lib/db_ido/dbtype.cpp | 26 +++++++++++++++++++++++-- lib/db_ido_mysql/idomysqlconnection.cpp | 13 +++++++++++++ lib/db_ido_pgsql/idopgsqlconnection.cpp | 13 +++++++++++++ 6 files changed, 68 insertions(+), 6 deletions(-) diff --git a/lib/db_ido/commanddbobject.cpp b/lib/db_ido/commanddbobject.cpp index 6f12a6500..6620c8332 100644 --- a/lib/db_ido/commanddbobject.cpp +++ b/lib/db_ido/commanddbobject.cpp @@ -28,9 +28,7 @@ using namespace icinga; -REGISTER_DBTYPE(CheckCommand, "command", DbObjectTypeCommand, "object_id", CommandDbObject); -REGISTER_DBTYPE(EventCommand, "command", DbObjectTypeCommand, "object_id", CommandDbObject); -REGISTER_DBTYPE(NotificationCommand, "command", DbObjectTypeCommand, "object_id", CommandDbObject); +REGISTER_DBTYPE(Command, "command", DbObjectTypeCommand, "object_id", CommandDbObject); CommandDbObject::CommandDbObject(const DbType::Ptr& type, const String& name1, const String& name2) : DbObject(type, name1, name2) diff --git a/lib/db_ido/dbconnection.cpp b/lib/db_ido/dbconnection.cpp index 1e54bfcd6..186e78c7c 100644 --- a/lib/db_ido/dbconnection.cpp +++ b/lib/db_ido/dbconnection.cpp @@ -39,7 +39,7 @@ Timer::Ptr DbConnection::m_ProgramStatusTimer; boost::once_flag DbConnection::m_OnceFlag = BOOST_ONCE_INIT; DbConnection::DbConnection(void) - : m_QueryStats(15 * 60), m_PendingQueries(0), m_PendingQueriesTimestamp(0) + : m_QueryStats(15 * 60), m_PendingQueries(0), m_PendingQueriesTimestamp(0), m_IDCacheValid(false) { } void DbConnection::OnConfigLoaded(void) @@ -352,6 +352,8 @@ bool DbConnection::GetObjectActive(const DbObject::Ptr& dbobj) const void DbConnection::ClearIDCache(void) { + SetIDCacheValid(false); + m_ObjectIDs.clear(); m_InsertIDs.clear(); m_ActiveObjects.clear(); @@ -484,3 +486,13 @@ int DbConnection::GetQueryCount(RingBuffer::SizeType span) const boost::mutex::scoped_lock lock(m_StatsMutex); return m_QueryStats.GetValues(span); } + +bool DbConnection::IsIDCacheValid(void) const +{ + return m_IDCacheValid; +} + +void DbConnection::SetIDCacheValid(bool valid) +{ + m_IDCacheValid = valid; +} diff --git a/lib/db_ido/dbconnection.hpp b/lib/db_ido/dbconnection.hpp index 2f100eeda..ca05a4760 100644 --- a/lib/db_ido/dbconnection.hpp +++ b/lib/db_ido/dbconnection.hpp @@ -95,9 +95,13 @@ protected: void IncreaseQueryCount(void); + bool IsIDCacheValid(void) const; + void SetIDCacheValid(bool valid); + static void UpdateProgramStatus(void); private: + bool m_IDCacheValid; std::map m_ObjectIDs; std::map, DbReference> m_InsertIDs; std::set m_ActiveObjects; diff --git a/lib/db_ido/dbtype.cpp b/lib/db_ido/dbtype.cpp index 44c33fb3e..ea25ec56c 100644 --- a/lib/db_ido/dbtype.cpp +++ b/lib/db_ido/dbtype.cpp @@ -58,8 +58,15 @@ void DbType::RegisterType(const DbType::Ptr& type) DbType::Ptr DbType::GetByName(const String& name) { + String typeName; + + if (name == "CheckCommand" || name == "NotificationCommand" || name == "EventCommand") + typeName = "Command"; + else + typeName = name; + boost::mutex::scoped_lock lock(GetStaticMutex()); - DbType::TypeMap::const_iterator it = GetTypes().find(name); + DbType::TypeMap::const_iterator it = GetTypes().find(typeName); if (it == GetTypes().end()) return DbType::Ptr(); @@ -96,7 +103,22 @@ DbObject::Ptr DbType::GetOrCreateObjectByName(const String& name1, const String& if (!name2.IsEmpty()) objName += "!" + name2; - dbobj->SetObject(ConfigObject::GetObject(m_Name, objName)); + String objType = m_Name; + + if (m_TypeID == DbObjectTypeCommand) { + if (objName.SubStr(0, 6) == "check_") { + objType = "CheckCommand"; + objName = objName.SubStr(6); + } else if (objName.SubStr(0, 13) == "notification_") { + objType = "NotificationCommand"; + objName = objName.SubStr(13); + } else if (objName.SubStr(0, 6) == "event_") { + objType = "EventCommand"; + objName = objName.SubStr(6); + } + } + + dbobj->SetObject(ConfigObject::GetObject(objType, objName)); return dbobj; } diff --git a/lib/db_ido_mysql/idomysqlconnection.cpp b/lib/db_ido_mysql/idomysqlconnection.cpp index d0026826b..6e66075e9 100644 --- a/lib/db_ido_mysql/idomysqlconnection.cpp +++ b/lib/db_ido_mysql/idomysqlconnection.cpp @@ -398,6 +398,8 @@ void IdoMysqlConnection::Reconnect(void) activeDbObjs.push_back(dbobj); } + SetIDCacheValid(true); + BOOST_FOREACH(const DbObject::Ptr& dbobj, activeDbObjs) { if (dbobj->GetObject() == NULL) { Log(LogNotice, "IdoMysqlConnection") @@ -750,6 +752,9 @@ bool IdoMysqlConnection::FieldToEscapedString(const String& key, const Value& va return true; } + if (!IsIDCacheValid()) + return false; + DbReference dbrefcol; if (DbValue::IsObjectInsertID(value)) { @@ -817,6 +822,9 @@ void IdoMysqlConnection::ExecuteMultipleQueries(const std::vector& quer bool IdoMysqlConnection::CanExecuteQuery(const DbQuery& query) { + if (query.Object && !IsIDCacheValid()) + return false; + if (query.WhereCriteria) { ObjectLock olock(query.WhereCriteria); Value value; @@ -877,6 +885,11 @@ void IdoMysqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType return; } + if (!CanExecuteQuery(query)) { + m_QueryQueue.Enqueue(boost::bind(&IdoMysqlConnection::InternalExecuteQuery, this, query, typeOverride), query.Priority); + return; + } + if (GetCategoryFilter() != DbCatEverything && (query.Category & GetCategoryFilter()) == 0) return; diff --git a/lib/db_ido_pgsql/idopgsqlconnection.cpp b/lib/db_ido_pgsql/idopgsqlconnection.cpp index 94976c23a..c9e1ab0fc 100644 --- a/lib/db_ido_pgsql/idopgsqlconnection.cpp +++ b/lib/db_ido_pgsql/idopgsqlconnection.cpp @@ -371,6 +371,8 @@ void IdoPgsqlConnection::Reconnect(void) activeDbObjs.push_back(dbobj); } + SetIDCacheValid(true); + BOOST_FOREACH(const DbObject::Ptr& dbobj, activeDbObjs) { if (dbobj->GetObject() == NULL) { Log(LogNotice, "IdoPgsqlConnection") @@ -607,6 +609,9 @@ bool IdoPgsqlConnection::FieldToEscapedString(const String& key, const Value& va return true; } + if (!IsIDCacheValid()) + return false; + DbReference dbrefcol; if (DbValue::IsObjectInsertID(value)) { @@ -674,6 +679,9 @@ void IdoPgsqlConnection::ExecuteMultipleQueries(const std::vector& quer bool IdoPgsqlConnection::CanExecuteQuery(const DbQuery& query) { + if (query.Object && !IsIDCacheValid()) + return false; + if (query.WhereCriteria) { ObjectLock olock(query.WhereCriteria); Value value; @@ -734,6 +742,11 @@ void IdoPgsqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType return; } + if (!CanExecuteQuery(query)) { + m_QueryQueue.Enqueue(boost::bind(&IdoPgsqlConnection::InternalExecuteQuery, this, query, typeOverride), query.Priority); + return; + } + if (GetCategoryFilter() != DbCatEverything && (query.Category & GetCategoryFilter()) == 0) return;