From 40c0bfad2307110d3d79f4aa1f213ad82f5cad2f Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 20 Apr 2021 18:11:52 +0200 Subject: [PATCH 1/7] DbConnection#Pause(): call overridden method as last step Otherwise it marks the object as paused and the other steps become no-ops. refs #8727 --- lib/db_ido/dbconnection.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/db_ido/dbconnection.cpp b/lib/db_ido/dbconnection.cpp index cd854bddf..891baa113 100644 --- a/lib/db_ido/dbconnection.cpp +++ b/lib/db_ido/dbconnection.cpp @@ -87,8 +87,6 @@ void DbConnection::Resume() void DbConnection::Pause() { - ConfigObject::Pause(); - Log(LogInformation, "DbConnection") << "Pausing IDO connection: " << GetName(); @@ -113,6 +111,8 @@ void DbConnection::Pause() ExecuteQuery(query1); NewTransaction(); + + ConfigObject::Pause(); } void DbConnection::InitializeDbTimer() From fd9bdb798d3594ffb50a0ef2a2f89bc2e108503e Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 20 Apr 2021 18:31:02 +0200 Subject: [PATCH 2/7] Deduplicate DbConnection#m_QueryQueue.Join() in #Pause() refs #8727 --- lib/db_ido/dbconnection.cpp | 3 +++ lib/db_ido_mysql/idomysqlconnection.cpp | 3 --- lib/db_ido_pgsql/idopgsqlconnection.cpp | 3 --- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/db_ido/dbconnection.cpp b/lib/db_ido/dbconnection.cpp index 891baa113..552c3fed4 100644 --- a/lib/db_ido/dbconnection.cpp +++ b/lib/db_ido/dbconnection.cpp @@ -112,6 +112,9 @@ void DbConnection::Pause() NewTransaction(); + /* Work on remaining tasks but never delete the threads, for HA resuming later. */ + m_QueryQueue.Join(); + ConfigObject::Pause(); } diff --git a/lib/db_ido_mysql/idomysqlconnection.cpp b/lib/db_ido_mysql/idomysqlconnection.cpp index 65fce5fd7..5b0a39326 100644 --- a/lib/db_ido_mysql/idomysqlconnection.cpp +++ b/lib/db_ido_mysql/idomysqlconnection.cpp @@ -107,9 +107,6 @@ void IdoMysqlConnection::Pause() m_QueryQueue.Enqueue([this]() { Disconnect(); }, PriorityLow); - /* Work on remaining tasks but never delete the threads, for HA resuming later. */ - m_QueryQueue.Join(); - Log(LogInformation, "IdoMysqlConnection") << "'" << GetName() << "' paused."; diff --git a/lib/db_ido_pgsql/idopgsqlconnection.cpp b/lib/db_ido_pgsql/idopgsqlconnection.cpp index cb0994cdc..eba81f64f 100644 --- a/lib/db_ido_pgsql/idopgsqlconnection.cpp +++ b/lib/db_ido_pgsql/idopgsqlconnection.cpp @@ -106,9 +106,6 @@ void IdoPgsqlConnection::Pause() m_QueryQueue.Enqueue([this]() { Disconnect(); }, PriorityLow); - /* Work on remaining tasks but never delete the threads, for HA resuming later. */ - m_QueryQueue.Join(); - Log(LogInformation, "IdoPgsqlConnection") << "'" << GetName() << "' paused."; } From 0d34d8951acab7a8077539a8ecd5488d1fc89ba1 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 20 Apr 2021 18:37:09 +0200 Subject: [PATCH 3/7] Abstract Ido*Connection#Disconnect() refs #8727 --- lib/db_ido/dbconnection.hpp | 1 + lib/db_ido_mysql/idomysqlconnection.hpp | 2 +- lib/db_ido_pgsql/idopgsqlconnection.hpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/db_ido/dbconnection.hpp b/lib/db_ido/dbconnection.hpp index b0c04bd73..715f2bdab 100644 --- a/lib/db_ido/dbconnection.hpp +++ b/lib/db_ido/dbconnection.hpp @@ -75,6 +75,7 @@ protected: virtual void CleanUpExecuteQuery(const String& table, const String& time_column, double max_age); virtual void FillIDCache(const DbType::Ptr& type) = 0; virtual void NewTransaction() = 0; + virtual void Disconnect() = 0; void UpdateObject(const ConfigObject::Ptr& object); void UpdateAllObjects(); diff --git a/lib/db_ido_mysql/idomysqlconnection.hpp b/lib/db_ido_mysql/idomysqlconnection.hpp index 851e29d5a..ce0f36f1b 100644 --- a/lib/db_ido_mysql/idomysqlconnection.hpp +++ b/lib/db_ido_mysql/idomysqlconnection.hpp @@ -51,6 +51,7 @@ protected: void CleanUpExecuteQuery(const String& table, const String& time_key, double time_value) override; void FillIDCache(const DbType::Ptr& type) override; void NewTransaction() override; + void Disconnect() override; private: DbReference m_InstanceID; @@ -82,7 +83,6 @@ private: void InternalActivateObject(const DbObject::Ptr& dbobj); void InternalDeactivateObject(const DbObject::Ptr& dbobj); - void Disconnect(); void Reconnect(); void AssertOnWorkQueue(); diff --git a/lib/db_ido_pgsql/idopgsqlconnection.hpp b/lib/db_ido_pgsql/idopgsqlconnection.hpp index 0552f3318..77bfe74c3 100644 --- a/lib/db_ido_pgsql/idopgsqlconnection.hpp +++ b/lib/db_ido_pgsql/idopgsqlconnection.hpp @@ -44,6 +44,7 @@ protected: void CleanUpExecuteQuery(const String& table, const String& time_key, double time_value) override; void FillIDCache(const DbType::Ptr& type) override; void NewTransaction() override; + void Disconnect() override; private: DbReference m_InstanceID; @@ -67,7 +68,6 @@ private: void InternalActivateObject(const DbObject::Ptr& dbobj); void InternalDeactivateObject(const DbObject::Ptr& dbobj); - void Disconnect(); void InternalNewTransaction(); void Reconnect(); From 92df2ce2ca8e62d70509eaa823be520994bf7592 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 20 Apr 2021 18:42:37 +0200 Subject: [PATCH 4/7] Deduplicate DbConnection#Disconnect() in #Pause() refs #8727 --- lib/db_ido/dbconnection.cpp | 2 ++ lib/db_ido_mysql/idomysqlconnection.cpp | 2 -- lib/db_ido_pgsql/idopgsqlconnection.cpp | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/db_ido/dbconnection.cpp b/lib/db_ido/dbconnection.cpp index 552c3fed4..60aab5fde 100644 --- a/lib/db_ido/dbconnection.cpp +++ b/lib/db_ido/dbconnection.cpp @@ -112,6 +112,8 @@ void DbConnection::Pause() NewTransaction(); + m_QueryQueue.Enqueue([this]() { Disconnect(); }, PriorityLow); + /* Work on remaining tasks but never delete the threads, for HA resuming later. */ m_QueryQueue.Join(); diff --git a/lib/db_ido_mysql/idomysqlconnection.cpp b/lib/db_ido_mysql/idomysqlconnection.cpp index 5b0a39326..1f379489f 100644 --- a/lib/db_ido_mysql/idomysqlconnection.cpp +++ b/lib/db_ido_mysql/idomysqlconnection.cpp @@ -105,8 +105,6 @@ void IdoMysqlConnection::Pause() << "Rescheduling disconnect task."; #endif /* I2_DEBUG */ - m_QueryQueue.Enqueue([this]() { Disconnect(); }, PriorityLow); - Log(LogInformation, "IdoMysqlConnection") << "'" << GetName() << "' paused."; diff --git a/lib/db_ido_pgsql/idopgsqlconnection.cpp b/lib/db_ido_pgsql/idopgsqlconnection.cpp index eba81f64f..5bc323335 100644 --- a/lib/db_ido_pgsql/idopgsqlconnection.cpp +++ b/lib/db_ido_pgsql/idopgsqlconnection.cpp @@ -104,8 +104,6 @@ void IdoPgsqlConnection::Pause() m_ReconnectTimer.reset(); - m_QueryQueue.Enqueue([this]() { Disconnect(); }, PriorityLow); - Log(LogInformation, "IdoPgsqlConnection") << "'" << GetName() << "' paused."; } From 3d8586ccec4b32fe415c2c32ad881d78d0e1aef2 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 20 Apr 2021 19:04:49 +0200 Subject: [PATCH 5/7] Ido*Connection: extend IsPaused() check where the difference matters refs #8727 --- lib/db_ido_mysql/idomysqlconnection.cpp | 6 +++--- lib/db_ido_pgsql/idopgsqlconnection.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/db_ido_mysql/idomysqlconnection.cpp b/lib/db_ido_mysql/idomysqlconnection.cpp index 1f379489f..08d427426 100644 --- a/lib/db_ido_mysql/idomysqlconnection.cpp +++ b/lib/db_ido_mysql/idomysqlconnection.cpp @@ -147,7 +147,7 @@ void IdoMysqlConnection::Disconnect() void IdoMysqlConnection::NewTransaction() { - if (IsPaused()) + if (IsPaused() && GetPauseCalled()) return; #ifdef I2_DEBUG /* I2_DEBUG */ @@ -898,7 +898,7 @@ bool IdoMysqlConnection::FieldToEscapedString(const String& key, const Value& va void IdoMysqlConnection::ExecuteQuery(const DbQuery& query) { - if (IsPaused()) + if (IsPaused() && GetPauseCalled()) return; ASSERT(query.Category != DbCatInvalid); @@ -1001,7 +1001,7 @@ void IdoMysqlConnection::InternalExecuteQuery(const DbQuery& query, int typeOver { AssertOnWorkQueue(); - if (IsPaused()) { + if (IsPaused() && GetPauseCalled()) { DecreasePendingQueries(1); return; } diff --git a/lib/db_ido_pgsql/idopgsqlconnection.cpp b/lib/db_ido_pgsql/idopgsqlconnection.cpp index 5bc323335..5e8d6900f 100644 --- a/lib/db_ido_pgsql/idopgsqlconnection.cpp +++ b/lib/db_ido_pgsql/idopgsqlconnection.cpp @@ -713,7 +713,7 @@ bool IdoPgsqlConnection::FieldToEscapedString(const String& key, const Value& va void IdoPgsqlConnection::ExecuteQuery(const DbQuery& query) { - if (IsPaused()) + if (IsPaused() && GetPauseCalled()) return; ASSERT(query.Category != DbCatInvalid); @@ -798,7 +798,7 @@ void IdoPgsqlConnection::InternalExecuteQuery(const DbQuery& query, int typeOver { AssertOnWorkQueue(); - if (IsPaused()) { + if (IsPaused() && GetPauseCalled()) { DecreasePendingQueries(1); return; } From 8918b38deae167df4a5648f6553090b228bdee5c Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 20 Apr 2021 19:07:20 +0200 Subject: [PATCH 6/7] DbConnection#Pause(): also update is_currently_running and process_id refs #8727 --- lib/db_ido/dbconnection.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/db_ido/dbconnection.cpp b/lib/db_ido/dbconnection.cpp index 60aab5fde..218f509d4 100644 --- a/lib/db_ido/dbconnection.cpp +++ b/lib/db_ido/dbconnection.cpp @@ -103,7 +103,9 @@ void DbConnection::Pause() query1.Fields = new Dictionary({ { "instance_id", 0 }, /* DbConnection class fills in real ID */ - { "program_end_time", DbValue::FromTimestamp(Utility::GetTime()) } + { "program_end_time", DbValue::FromTimestamp(Utility::GetTime()) }, + { "is_currently_running", 0 }, + { "process_id", Empty } }); query1.Priority = PriorityHigh; From 306a0f476c06d174f468ac93ad716bfd75c89f40 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 20 Apr 2021 19:30:59 +0200 Subject: [PATCH 7/7] Ido*Connection#FieldToEscapedString(): support NULL refs #8727 --- lib/db_ido_mysql/idomysqlconnection.cpp | 10 +++------- lib/db_ido_pgsql/idopgsqlconnection.cpp | 10 +++------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/lib/db_ido_mysql/idomysqlconnection.cpp b/lib/db_ido_mysql/idomysqlconnection.cpp index 08d427426..ed390a1b7 100644 --- a/lib/db_ido_mysql/idomysqlconnection.cpp +++ b/lib/db_ido_mysql/idomysqlconnection.cpp @@ -837,7 +837,9 @@ bool IdoMysqlConnection::FieldToEscapedString(const String& key, const Value& va Value rawvalue = DbValue::ExtractValue(value); - if (rawvalue.IsObjectType()) { + if (rawvalue.GetType() == ValueEmpty) { + *result = "NULL"; + } else if (rawvalue.IsObjectType()) { DbObject::Ptr dbobjcol = DbObject::GetOrCreateByObject(rawvalue); if (!dbobjcol) { @@ -950,9 +952,6 @@ bool IdoMysqlConnection::CanExecuteQuery(const DbQuery& query) for (const Dictionary::Pair& kv : query.Fields) { Value value; - if (kv.second.IsEmpty() && !kv.second.IsString()) - continue; - if (!FieldToEscapedString(kv.first, kv.second, &value)) return false; } @@ -1129,9 +1128,6 @@ void IdoMysqlConnection::InternalExecuteQuery(const DbQuery& query, int typeOver for (const Dictionary::Pair& kv : query.Fields) { Value value; - if (kv.second.IsEmpty() && !kv.second.IsString()) - continue; - if (!FieldToEscapedString(kv.first, kv.second, &value)) { #ifdef I2_DEBUG /* I2_DEBUG */ diff --git a/lib/db_ido_pgsql/idopgsqlconnection.cpp b/lib/db_ido_pgsql/idopgsqlconnection.cpp index 5e8d6900f..47d4eb599 100644 --- a/lib/db_ido_pgsql/idopgsqlconnection.cpp +++ b/lib/db_ido_pgsql/idopgsqlconnection.cpp @@ -652,7 +652,9 @@ bool IdoPgsqlConnection::FieldToEscapedString(const String& key, const Value& va Value rawvalue = DbValue::ExtractValue(value); - if (rawvalue.IsObjectType()) { + if (rawvalue.GetType() == ValueEmpty) { + *result = "NULL"; + } else if (rawvalue.IsObjectType()) { DbObject::Ptr dbobjcol = DbObject::GetOrCreateByObject(rawvalue); if (!dbobjcol) { @@ -755,9 +757,6 @@ bool IdoPgsqlConnection::CanExecuteQuery(const DbQuery& query) for (const Dictionary::Pair& kv : query.Fields) { Value value; - if (kv.second.IsEmpty() && !kv.second.IsString()) - continue; - if (!FieldToEscapedString(kv.first, kv.second, &value)) return false; } @@ -911,9 +910,6 @@ void IdoPgsqlConnection::InternalExecuteQuery(const DbQuery& query, int typeOver Value value; bool first = true; for (const Dictionary::Pair& kv : query.Fields) { - if (kv.second.IsEmpty() && !kv.second.IsString()) - continue; - if (!FieldToEscapedString(kv.first, kv.second, &value)) { m_QueryQueue.Enqueue([this, query]() { InternalExecuteQuery(query, -1); }, query.Priority); return;