From: Michael Friedrich Date: Mon, 21 Mar 2016 12:37:32 +0000 (+0100) Subject: IDO: Ensure that the notification insert id is passed to contactnotification inserts X-Git-Tag: v2.5.0~438 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=83e0bcddce5855bfe22c3df89adec0610900c58c;p=icinga2 IDO: Ensure that the notification insert id is passed to contactnotification inserts We cannot add the notification insert id directly to the following contactnotifications queries. Instead we need to pass a DbValue reference which gets set after the notification insert id is calculated. The contactnotifications insert queries are fired as query group calling CanExecuteQuery() and FieldToEscapedString(). If the notification id does not exist yet, the queries are moved to the end of the queue. Once the contactnotifications queries are fired the DbValue reference is destroyed. This patch also removes the old notification insert id cache which was broken in many ways. fixes #11387 --- diff --git a/lib/db_ido/dbconnection.cpp b/lib/db_ido/dbconnection.cpp index 514e7bc51..694b9e37f 100644 --- a/lib/db_ido/dbconnection.cpp +++ b/lib/db_ido/dbconnection.cpp @@ -323,26 +323,6 @@ DbReference DbConnection::GetInsertID(const DbType::Ptr& type, const DbReference return it->second; } -void DbConnection::SetNotificationInsertID(const CustomVarObject::Ptr& obj, const DbReference& dbref) -{ - if (dbref.IsValid()) - m_NotificationInsertIDs[obj] = dbref; - else - m_NotificationInsertIDs.erase(obj); -} - -DbReference DbConnection::GetNotificationInsertID(const CustomVarObject::Ptr& obj) const -{ - std::map::const_iterator it; - - it = m_NotificationInsertIDs.find(obj); - - if (it == m_NotificationInsertIDs.end()) - return DbReference(); - - return it->second; -} - void DbConnection::SetObjectActive(const DbObject::Ptr& dbobj, bool active) { if (active) @@ -360,7 +340,6 @@ void DbConnection::ClearIDCache(void) { m_ObjectIDs.clear(); m_InsertIDs.clear(); - m_NotificationInsertIDs.clear(); m_ActiveObjects.clear(); m_ConfigUpdates.clear(); m_StatusUpdates.clear(); diff --git a/lib/db_ido/dbconnection.hpp b/lib/db_ido/dbconnection.hpp index 63c12489c..6f81178f7 100644 --- a/lib/db_ido/dbconnection.hpp +++ b/lib/db_ido/dbconnection.hpp @@ -57,9 +57,6 @@ public: DbReference GetInsertID(const DbObject::Ptr& dbobj) const; DbReference GetInsertID(const DbType::Ptr& type, const DbReference& objid) const; - void SetNotificationInsertID(const CustomVarObject::Ptr& obj, const DbReference& dbref); - DbReference GetNotificationInsertID(const CustomVarObject::Ptr& obj) const; - void SetObjectActive(const DbObject::Ptr& dbobj, bool active); bool GetObjectActive(const DbObject::Ptr& dbobj) const; @@ -101,7 +98,6 @@ protected: private: std::map m_ObjectIDs; std::map, DbReference> m_InsertIDs; - std::map m_NotificationInsertIDs; std::set m_ActiveObjects; std::set m_ConfigUpdates; std::set m_StatusUpdates; diff --git a/lib/db_ido/dbevents.cpp b/lib/db_ido/dbevents.cpp index 3b34974a3..1afbe9c3b 100644 --- a/lib/db_ido/dbevents.cpp +++ b/lib/db_ido/dbevents.cpp @@ -833,8 +833,7 @@ void DbEvents::AddNotificationHistory(const Notification::Ptr& notification, con query1.Table = "notifications"; query1.Type = DbQueryInsert; query1.Category = DbCatNotification; - /* store the object ptr for caching the insert id for this object */ - query1.NotificationObject = notification; + query1.NotificationInsertID = new DbValue(DbValueObjectInsertID, -1); Host::Ptr host; Service::Ptr service; @@ -868,16 +867,17 @@ void DbEvents::AddNotificationHistory(const Notification::Ptr& notification, con query1.Fields = fields1; DbObject::OnQuery(query1); - DbQuery query2; - query2.Table = "contactnotifications"; - query2.Type = DbQueryInsert; - query2.Category = DbCatNotification; + std::vector queries; - /* filtered users */ BOOST_FOREACH(const User::Ptr& user, users) { Log(LogDebug, "DbEvents") << "add contact notification history for service '" << checkable->GetName() << "' and user '" << user->GetName() << "'."; + DbQuery query2; + query2.Table = "contactnotifications"; + query2.Type = DbQueryInsert; + query2.Category = DbCatNotification; + Dictionary::Ptr fields2 = new Dictionary(); fields2->Set("contact_object_id", user); fields2->Set("start_time", DbValue::FromTimestamp(time_bag.first)); @@ -885,12 +885,14 @@ void DbEvents::AddNotificationHistory(const Notification::Ptr& notification, con fields2->Set("end_time", DbValue::FromTimestamp(time_bag.first)); fields2->Set("end_time_usec", time_bag.second); - fields2->Set("notification_id", notification); /* DbConnection class fills in real ID from notification insert id cache */ + fields2->Set("notification_id", query1.NotificationInsertID); fields2->Set("instance_id", 0); /* DbConnection class fills in real ID */ query2.Fields = fields2; - DbObject::OnQuery(query2); + queries.push_back(query2); } + + DbObject::OnMultipleQueries(queries); } /* statehistory */ diff --git a/lib/db_ido/dbquery.hpp b/lib/db_ido/dbquery.hpp index e880d9e69..1dd2d4318 100644 --- a/lib/db_ido/dbquery.hpp +++ b/lib/db_ido/dbquery.hpp @@ -21,6 +21,7 @@ #define DBQUERY_H #include "db_ido/i2-db_ido.hpp" +#include "db_ido/dbvalue.hpp" #include "icinga/customvarobject.hpp" #include "base/dictionary.hpp" #include "base/configobject.hpp" @@ -67,7 +68,7 @@ struct I2_DB_IDO_API DbQuery Dictionary::Ptr Fields; Dictionary::Ptr WhereCriteria; intrusive_ptr Object; - intrusive_ptr NotificationObject; + DbValue::Ptr NotificationInsertID; bool ConfigUpdate; bool StatusUpdate; WorkQueuePriority Priority; diff --git a/lib/db_ido/dbvalue.cpp b/lib/db_ido/dbvalue.cpp index a70fef69e..dcd07f0c9 100644 --- a/lib/db_ido/dbvalue.cpp +++ b/lib/db_ido/dbvalue.cpp @@ -93,3 +93,8 @@ Value DbValue::GetValue(void) const { return m_Value; } + +void DbValue::SetValue(const Value& value) +{ + m_Value = value; +} diff --git a/lib/db_ido/dbvalue.hpp b/lib/db_ido/dbvalue.hpp index d2b394ed6..a5f565944 100644 --- a/lib/db_ido/dbvalue.hpp +++ b/lib/db_ido/dbvalue.hpp @@ -31,7 +31,7 @@ enum DbValueType { DbValueTimestamp, DbValueTimestampNow, - DbValueObjectInsertID, + DbValueObjectInsertID }; /** @@ -58,7 +58,9 @@ public: static Value ExtractValue(const Value& value); DbValueType GetType(void) const; + Value GetValue(void) const; + void SetValue(const Value& value); private: DbValueType m_Type; diff --git a/lib/db_ido_mysql/idomysqlconnection.cpp b/lib/db_ido_mysql/idomysqlconnection.cpp index 840d40003..acfa1841e 100644 --- a/lib/db_ido_mysql/idomysqlconnection.cpp +++ b/lib/db_ido_mysql/idomysqlconnection.cpp @@ -704,14 +704,6 @@ bool IdoMysqlConnection::FieldToEscapedString(const String& key, const Value& va } else if (key == "session_token") { *result = m_SessionToken; return true; - } else if (key == "notification_id") { - DbReference ref = GetNotificationInsertID(value); - - if (!ref.IsValid()) - return false; - - *result = static_cast(ref); - return true; } Value rawvalue = DbValue::ExtractValue(value); @@ -752,6 +744,14 @@ bool IdoMysqlConnection::FieldToEscapedString(const String& key, const Value& va *result = Value(msgbuf.str()); } else if (DbValue::IsTimestampNow(value)) { *result = "NOW()"; + } else if (DbValue::IsObjectInsertID(value)) { + long id = static_cast(rawvalue); + + if (id <= 0) + return false; + + *result = id; + return true; } else { Value fvalue; @@ -969,11 +969,8 @@ void IdoMysqlConnection::FinishExecuteQuery(const DbQuery& query, int type, bool SetStatusUpdate(query.Object, true); } - if (type == DbQueryInsert && query.Table == "notifications" && query.NotificationObject) { // FIXME remove hardcoded table name - SetNotificationInsertID(query.NotificationObject, GetLastInsertID()); - Log(LogDebug, "IdoMysqlConnection") - << "saving contactnotification notification_id=" << static_cast(GetLastInsertID()); - } + if (type == DbQueryInsert && query.Table == "notifications" && query.NotificationInsertID) + query.NotificationInsertID->SetValue(static_cast(GetLastInsertID())); } void IdoMysqlConnection::CleanUpExecuteQuery(const String& table, const String& time_column, double max_age) diff --git a/lib/db_ido_pgsql/idopgsqlconnection.cpp b/lib/db_ido_pgsql/idopgsqlconnection.cpp index 3d5d1a610..9eae07c78 100644 --- a/lib/db_ido_pgsql/idopgsqlconnection.cpp +++ b/lib/db_ido_pgsql/idopgsqlconnection.cpp @@ -583,14 +583,6 @@ bool IdoPgsqlConnection::FieldToEscapedString(const String& key, const Value& va } else if (key == "session_token") { *result = m_SessionToken; return true; - } else if (key == "notification_id") { - DbReference ref = GetNotificationInsertID(value); - - if (!ref.IsValid()) - return false; - - *result = static_cast(ref); - return true; } Value rawvalue = DbValue::ExtractValue(value); @@ -630,6 +622,14 @@ bool IdoPgsqlConnection::FieldToEscapedString(const String& key, const Value& va *result = Value(msgbuf.str()); } else if (DbValue::IsTimestampNow(value)) { *result = "NOW()"; + } else if (DbValue::IsObjectInsertID(value)) { + long id = static_cast(rawvalue); + + if (id <= 0) + return false; + + *result = id; + return true; } else { Value fvalue; @@ -849,12 +849,9 @@ void IdoPgsqlConnection::InternalExecuteQuery(const DbQuery& query, DbQueryType SetStatusUpdate(query.Object, true); } - if (type == DbQueryInsert && query.Table == "notifications" && query.NotificationObject) { // FIXME remove hardcoded table name - String idField = "notification_id"; - DbReference seqval = GetSequenceValue(GetTablePrefix() + query.Table, idField); - SetNotificationInsertID(query.NotificationObject, seqval); - Log(LogDebug, "IdoPgsqlConnection") - << "saving contactnotification notification_id=" << Convert::ToString(seqval); + if (type == DbQueryInsert && query.Table == "notifications" && query.NotificationInsertID) { + DbReference seqval = GetSequenceValue(GetTablePrefix() + query.Table, "notification_id"); + query.NotificationInsertID->SetValue(static_cast(seqval)); } } diff --git a/lib/icinga/notification.cpp b/lib/icinga/notification.cpp index c2cec0ef7..1cfefa0f9 100644 --- a/lib/icinga/notification.cpp +++ b/lib/icinga/notification.cpp @@ -466,7 +466,7 @@ void Notification::ExecuteNotificationHelper(NotificationType type, const User:: if (!command) { Log(LogDebug, "Notification") - << "No notification_command found for notification '" << GetName() << "'. Skipping execution."; + << "No command found for notification '" << GetName() << "'. Skipping execution."; return; } @@ -482,7 +482,9 @@ void Notification::ExecuteNotificationHelper(NotificationType type, const User:: Service::OnNotificationSentToUser(this, GetCheckable(), user, type, cr, author, text, command->GetName()); Log(LogInformation, "Notification") - << "Completed sending notification '" << GetName() << "' for checkable '" << GetCheckable()->GetName() << "'"; + << "Completed sending notification '" << GetName() + << "' for checkable '" << GetCheckable()->GetName() + << "' and user '" << user->GetName() << "'."; } catch (const std::exception& ex) { Log(LogWarning, "Notification") << "Exception occured during notification for checkable '"