]> granicus.if.org Git - icinga2/commitdiff
IDO: Ensure that the notification insert id is passed to contactnotification inserts
authorMichael Friedrich <michael.friedrich@netways.de>
Mon, 21 Mar 2016 12:37:32 +0000 (13:37 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Wed, 20 Apr 2016 08:07:24 +0000 (10:07 +0200)
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

lib/db_ido/dbconnection.cpp
lib/db_ido/dbconnection.hpp
lib/db_ido/dbevents.cpp
lib/db_ido/dbquery.hpp
lib/db_ido/dbvalue.cpp
lib/db_ido/dbvalue.hpp
lib/db_ido_mysql/idomysqlconnection.cpp
lib/db_ido_pgsql/idopgsqlconnection.cpp
lib/icinga/notification.cpp

index 514e7bc519210df9458f86a0638250223e457f35..694b9e37f5999edb2d6c4285efd5439886b4fb87 100644 (file)
@@ -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<CustomVarObject::Ptr, DbReference>::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();
index 63c12489cabd278be18a181fb7bc025d143b204a..6f81178f7176cb141871fd0bdf1c6e84c4fecf99 100644 (file)
@@ -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<DbObject::Ptr, DbReference> m_ObjectIDs;
        std::map<std::pair<DbType::Ptr, DbReference>, DbReference> m_InsertIDs;
-       std::map<CustomVarObject::Ptr, DbReference> m_NotificationInsertIDs;
        std::set<DbObject::Ptr> m_ActiveObjects;
        std::set<DbObject::Ptr> m_ConfigUpdates;
        std::set<DbObject::Ptr> m_StatusUpdates;
index 3b34974a3ff3ef9346f5a85bda80c2b479adb013..1afbe9c3bbca4d33c2586cef71358ebc154b4999 100644 (file)
@@ -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<DbQuery> 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 */
index e880d9e69135f38d261101bc65f8581636631a1c..1dd2d4318c41755ac19548231723bed952a8c1f7 100644 (file)
@@ -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<DbObject> Object;
-       intrusive_ptr<CustomVarObject> NotificationObject;
+       DbValue::Ptr NotificationInsertID;
        bool ConfigUpdate;
        bool StatusUpdate;
        WorkQueuePriority Priority;
index a70fef69e76dd9e9578d72951fb63da57fa35200..dcd07f0c98bc1390b64c23f13e9cc5ed9b952205 100644 (file)
@@ -93,3 +93,8 @@ Value DbValue::GetValue(void) const
 {
        return m_Value;
 }
+
+void DbValue::SetValue(const Value& value)
+{
+       m_Value = value;
+}
index d2b394ed67d8a7fb270bc3740cb02f718852f71f..a5f5659449c57f3ae5e79b87ab6f5d6fbabcdcca 100644 (file)
@@ -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;
index 840d40003b37f5c6a7b00ec56aad5ddf2cd32245..acfa1841e4c91a2987ca4760de2a0f9e26642eac 100644 (file)
@@ -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<long>(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<long>(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<long>(GetLastInsertID());
-       }
+       if (type == DbQueryInsert && query.Table == "notifications" && query.NotificationInsertID)
+               query.NotificationInsertID->SetValue(static_cast<long>(GetLastInsertID()));
 }
 
 void IdoMysqlConnection::CleanUpExecuteQuery(const String& table, const String& time_column, double max_age)
index 3d5d1a610c04ec717423b4b4dccac6fcfff08cb6..9eae07c7855310a05beefdb451985295a655e577 100644 (file)
@@ -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<long>(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<long>(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<long>(seqval));
        }
 }
 
index c2cec0ef7cfa4154c6f6e8e88c10f2f61058f6aa..1cfefa0f98884408b7e037e028873499e41f287f 100644 (file)
@@ -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 '"