From cf5735e3df3b717d230da74da8b7840145e243f9 Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Mon, 26 Oct 2015 13:14:41 +0100 Subject: [PATCH] DB IDO: Remove deleted custom variables We cannot clear the custom variable tables on startup and then re-insert all known custom vars. Instead we "fixed" it by leaving them in the database only updating their value if changed. We certainly forgot about deleted custom vars at that point. Since the older fix must stay in place, we'll use a session token stored in the backend to check whether the custom variable has been updated/inserted in the current session, or not. If the session token does not match, the custom vars are deleted at the end of the config dump. Ugly but fairly the only performant solution as CVs don't have an object_id. fixes #10436 --- lib/db_ido/dbobject.cpp | 2 ++ lib/db_ido_mysql/idomysqlconnection.cpp | 18 ++++++++++++++++++ lib/db_ido_mysql/idomysqlconnection.hpp | 2 ++ lib/db_ido_mysql/schema/mysql.sql | 2 ++ lib/db_ido_mysql/schema/upgrade/2.4.0.sql | 7 +++++++ lib/db_ido_pgsql/idopgsqlconnection.cpp | 15 ++++++++++++++- lib/db_ido_pgsql/idopgsqlconnection.hpp | 2 ++ lib/db_ido_pgsql/schema/pgsql.sql | 2 ++ lib/db_ido_pgsql/schema/upgrade/2.4.0.sql | 6 ++++++ 9 files changed, 55 insertions(+), 1 deletion(-) diff --git a/lib/db_ido/dbobject.cpp b/lib/db_ido/dbobject.cpp index 6a6f11201..f201cf60c 100644 --- a/lib/db_ido/dbobject.cpp +++ b/lib/db_ido/dbobject.cpp @@ -186,6 +186,7 @@ void DbObject::SendVarsConfigUpdate(void) fields->Set("varvalue", value); fields->Set("is_json", is_json); fields->Set("config_type", 1); + fields->Set("session_token", 0); /* DbConnection class fills in real ID */ fields->Set("object_id", obj); fields->Set("instance_id", 0); /* DbConnection class fills in real ID */ @@ -240,6 +241,7 @@ void DbObject::SendVarsStatusUpdate(void) fields->Set("varvalue", value); fields->Set("is_json", is_json); fields->Set("status_update_time", DbValue::FromTimestamp(Utility::GetTime())); + fields->Set("session_token", 0); /* DbConnection class fills in real ID */ fields->Set("object_id", obj); fields->Set("instance_id", 0); /* DbConnection class fills in real ID */ diff --git a/lib/db_ido_mysql/idomysqlconnection.cpp b/lib/db_ido_mysql/idomysqlconnection.cpp index 237cf6f2e..731e1e48b 100644 --- a/lib/db_ido_mysql/idomysqlconnection.cpp +++ b/lib/db_ido_mysql/idomysqlconnection.cpp @@ -160,6 +160,8 @@ void IdoMysqlConnection::Reconnect(void) CONTEXT("Reconnecting to MySQL IDO database '" + GetName() + "'"); + m_SessionToken = Utility::NewUniqueID(); + SetShouldConnect(true); std::vector active_dbobjs; @@ -369,6 +371,18 @@ void IdoMysqlConnection::Reconnect(void) DeactivateObject(dbobj); } } + + /* delete all customvariables without current session token */ + ClearCustomVarTable("customvariables"); + ClearCustomVarTable("customvariablestatus"); + + Query("COMMIT"); + Query("BEGIN"); +} + +void IdoMysqlConnection::ClearCustomVarTable(const String& table) +{ + Query("DELETE FROM " + GetTablePrefix() + table + " WHERE session_token <> '" + Escape(m_SessionToken) + "'"); } void IdoMysqlConnection::ClearConfigTable(const String& table) @@ -665,6 +679,10 @@ bool IdoMysqlConnection::FieldToEscapedString(const String& key, const Value& va *result = static_cast(m_InstanceID); return true; } + if (key == "session_token") { + *result = "'" + Escape(m_SessionToken) + "'"; + return true; + } if (key == "notification_id") { *result = static_cast(GetNotificationInsertID(value)); return true; diff --git a/lib/db_ido_mysql/idomysqlconnection.hpp b/lib/db_ido_mysql/idomysqlconnection.hpp index dd414186c..bab16a7a8 100644 --- a/lib/db_ido_mysql/idomysqlconnection.hpp +++ b/lib/db_ido_mysql/idomysqlconnection.hpp @@ -69,6 +69,7 @@ protected: private: DbReference m_InstanceID; + String m_SessionToken; WorkQueue m_QueryQueue; @@ -109,6 +110,7 @@ private: void InternalNewTransaction(void); virtual void ClearConfigTable(const String& table) override; + void ClearCustomVarTable(const String& table); void ExceptionHandler(boost::exception_ptr exp); }; diff --git a/lib/db_ido_mysql/schema/mysql.sql b/lib/db_ido_mysql/schema/mysql.sql index 9eed85373..90db69994 100644 --- a/lib/db_ido_mysql/schema/mysql.sql +++ b/lib/db_ido_mysql/schema/mysql.sql @@ -340,6 +340,7 @@ CREATE TABLE IF NOT EXISTS icinga_customvariables ( varname varchar(255) character set latin1 collate latin1_general_cs default NULL, varvalue TEXT character set latin1 default '', is_json smallint default 0, + session_token varchar(512) character set latin1 default NULL, PRIMARY KEY (customvariable_id), UNIQUE KEY object_id_2 (object_id,config_type,varname), KEY varname (varname) @@ -360,6 +361,7 @@ CREATE TABLE IF NOT EXISTS icinga_customvariablestatus ( varname varchar(255) character set latin1 collate latin1_general_cs default NULL, varvalue TEXT character set latin1 default '', is_json smallint default 0, + session_token varchar(512) character set latin1 default NULL, PRIMARY KEY (customvariablestatus_id), UNIQUE KEY object_id_2 (object_id,varname), KEY varname (varname) diff --git a/lib/db_ido_mysql/schema/upgrade/2.4.0.sql b/lib/db_ido_mysql/schema/upgrade/2.4.0.sql index a5b686b31..36f1447f9 100644 --- a/lib/db_ido_mysql/schema/upgrade/2.4.0.sql +++ b/lib/db_ido_mysql/schema/upgrade/2.4.0.sql @@ -48,6 +48,13 @@ ALTER TABLE icinga_hosts MODIFY freshness_threshold int; ALTER TABLE icinga_servicestatus ADD COLUMN original_attributes TEXT character set latin1 default NULL; ALTER TABLE icinga_hoststatus ADD COLUMN original_attributes TEXT character set latin1 default NULL; +-- ----------------------------------------- +-- #10436 deleted custom vars +-- ----------------------------------------- + +ALTER TABLE icinga_customvariables ADD COLUMN session_token varchar(512) character set latin1 default NULL; +ALTER TABLE icinga_customvariablestatus ADD COLUMN session_token varchar(512) character set latin1 default NULL; + -- ----------------------------------------- -- update dbversion -- ----------------------------------------- diff --git a/lib/db_ido_pgsql/idopgsqlconnection.cpp b/lib/db_ido_pgsql/idopgsqlconnection.cpp index 8c7a10487..cef8ef555 100644 --- a/lib/db_ido_pgsql/idopgsqlconnection.cpp +++ b/lib/db_ido_pgsql/idopgsqlconnection.cpp @@ -160,12 +160,13 @@ void IdoPgsqlConnection::Reconnect(void) CONTEXT("Reconnecting to PostgreSQL IDO database '" + GetName() + "'"); + m_SessionToken = Utility::NewUniqueID(); + SetShouldConnect(true); std::vector active_dbobjs; { - bool reconnect = false; if (GetConnected()) { @@ -365,6 +366,18 @@ void IdoPgsqlConnection::Reconnect(void) DeactivateObject(dbobj); } } + + /* delete all customvariables without current session token */ + ClearCustomVarTable("customvariables"); + ClearCustomVarTable("customvariablestatus"); + + Query("COMMIT"); + Query("BEGIN"); +} + +void IdoPgsqlConnection::ClearCustomVarTable(const String& table) +{ + Query("DELETE FROM " + GetTablePrefix() + table + " WHERE session_token <> '" + Escape(m_SessionToken) + "'"); } void IdoPgsqlConnection::ClearConfigTable(const String& table) diff --git a/lib/db_ido_pgsql/idopgsqlconnection.hpp b/lib/db_ido_pgsql/idopgsqlconnection.hpp index f0998b18f..d3cedff01 100644 --- a/lib/db_ido_pgsql/idopgsqlconnection.hpp +++ b/lib/db_ido_pgsql/idopgsqlconnection.hpp @@ -61,6 +61,7 @@ protected: private: DbReference m_InstanceID; + String m_SessionToken; WorkQueue m_QueryQueue; @@ -93,6 +94,7 @@ private: void InternalCleanUpExecuteQuery(const String& table, const String& time_key, double time_value); virtual void ClearConfigTable(const String& table) override; + void ClearCustomVarTable(const String& table); void ExceptionHandler(boost::exception_ptr exp); }; diff --git a/lib/db_ido_pgsql/schema/pgsql.sql b/lib/db_ido_pgsql/schema/pgsql.sql index 78340e495..1c2dce81b 100644 --- a/lib/db_ido_pgsql/schema/pgsql.sql +++ b/lib/db_ido_pgsql/schema/pgsql.sql @@ -366,6 +366,7 @@ CREATE TABLE icinga_customvariables ( varname TEXT default '', varvalue TEXT default '', is_json INTEGER default 0, + session_token TEXT default NULL, CONSTRAINT PK_customvariable_id PRIMARY KEY (customvariable_id) , CONSTRAINT UQ_customvariables UNIQUE (object_id,config_type,varname) ) ; @@ -386,6 +387,7 @@ CREATE TABLE icinga_customvariablestatus ( varname TEXT default '', varvalue TEXT default '', is_json INTEGER default 0, + session_token TEXT default NULL, CONSTRAINT PK_customvariablestatus_id PRIMARY KEY (customvariablestatus_id) , CONSTRAINT UQ_customvariablestatus UNIQUE (object_id,varname) ) ; diff --git a/lib/db_ido_pgsql/schema/upgrade/2.4.0.sql b/lib/db_ido_pgsql/schema/upgrade/2.4.0.sql index 633351325..d90753947 100644 --- a/lib/db_ido_pgsql/schema/upgrade/2.4.0.sql +++ b/lib/db_ido_pgsql/schema/upgrade/2.4.0.sql @@ -157,6 +157,12 @@ CREATE TABLE icinga_zonestatus ( ALTER TABLE icinga_servicestatus ADD COLUMN original_attributes TEXT default NULL; ALTER TABLE icinga_hoststatus ADD COLUMN original_attributes TEXT default NULL; +-- ----------------------------------------- +-- #10436 deleted custom vars +-- ----------------------------------------- +ALTER TABLE icinga_customvariables ADD COLUMN session_token TEXT default NULL; +ALTER TABLE icinga_customvariablestatus ADD COLUMN session_token TEXT default NULL; + -- ----------------------------------------- -- update dbversion -- -----------------------------------------