mirror of https://github.com/Icinga/icinga2.git
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
This commit is contained in:
parent
45786e2b81
commit
0cbedf495a
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -93,3 +93,8 @@ Value DbValue::GetValue(void) const
|
|||
{
|
||||
return m_Value;
|
||||
}
|
||||
|
||||
void DbValue::SetValue(const Value& value)
|
||||
{
|
||||
m_Value = value;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 '"
|
||||
|
|
Loading…
Reference in New Issue