From c0da6cbb6a662a20f0026210bc7022ad18eb641d Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Tue, 15 Dec 2015 15:29:48 +0100 Subject: [PATCH] Implement support for re-ordering groups of IDO queries fixes #10855 --- lib/db_ido/dbconnection.cpp | 4 +-- lib/db_ido_mysql/idomysqlconnection.cpp | 47 +++++++++++++++++++++++-- lib/db_ido_mysql/idomysqlconnection.hpp | 5 ++- lib/db_ido_pgsql/idopgsqlconnection.cpp | 47 +++++++++++++++++++++++-- lib/db_ido_pgsql/idopgsqlconnection.hpp | 4 ++- 5 files changed, 97 insertions(+), 10 deletions(-) diff --git a/lib/db_ido/dbconnection.cpp b/lib/db_ido/dbconnection.cpp index 754cf3645..81fb681ed 100644 --- a/lib/db_ido/dbconnection.cpp +++ b/lib/db_ido/dbconnection.cpp @@ -395,7 +395,7 @@ void DbConnection::PrepareDatabase(void) */ //ClearConfigTable("commands"); - ClearConfigTable("comments"); + //ClearConfigTable("comments"); ClearConfigTable("contact_addresses"); ClearConfigTable("contact_notificationcommands"); ClearConfigTable("contactgroup_members"); @@ -414,7 +414,7 @@ void DbConnection::PrepareDatabase(void) //ClearConfigTable("hostgroups"); //ClearConfigTable("hosts"); //ClearConfigTable("hoststatus"); - ClearConfigTable("scheduleddowntime"); + //ClearConfigTable("scheduleddowntime"); ClearConfigTable("service_contactgroups"); ClearConfigTable("service_contacts"); ClearConfigTable("servicedependencies"); diff --git a/lib/db_ido_mysql/idomysqlconnection.cpp b/lib/db_ido_mysql/idomysqlconnection.cpp index 4c9fe094c..b18c5be9d 100644 --- a/lib/db_ido_mysql/idomysqlconnection.cpp +++ b/lib/db_ido_mysql/idomysqlconnection.cpp @@ -754,18 +754,59 @@ void IdoMysqlConnection::ExecuteQuery(const DbQuery& query) { ASSERT(query.Category != DbCatInvalid); - boost::mutex::scoped_lock lock(m_QueryQueueMutex); m_QueryQueue.Enqueue(boost::bind(&IdoMysqlConnection::InternalExecuteQuery, this, query, (DbQueryType *)NULL), query.Priority, true); } void IdoMysqlConnection::ExecuteMultipleQueries(const std::vector& queries) { - boost::mutex::scoped_lock lock(m_QueryQueueMutex); + ASSERT(!queries.empty()); + + m_QueryQueue.Enqueue(boost::bind(&IdoMysqlConnection::InternalExecuteMultipleQueries, this, queries), queries[0].Priority, true); +} + +bool IdoMysqlConnection::CanExecuteQuery(const DbQuery& query) +{ + if (query.WhereCriteria) { + ObjectLock olock(query.WhereCriteria); + Value value; + + BOOST_FOREACH(const Dictionary::Pair& kv, query.WhereCriteria) { + if (!FieldToEscapedString(kv.first, kv.second, &value)) + return false; + } + } + + if (query.Fields) { + ObjectLock olock(query.Fields); + + BOOST_FOREACH(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; + } + } + + return true; +} + +void IdoMysqlConnection::InternalExecuteMultipleQueries(const std::vector& queries) +{ + AssertOnWorkQueue(); BOOST_FOREACH(const DbQuery& query, queries) { ASSERT(query.Category != DbCatInvalid); - m_QueryQueue.Enqueue(boost::bind(&IdoMysqlConnection::InternalExecuteQuery, this, query, (DbQueryType *)NULL), query.Priority, true); + if (!CanExecuteQuery(query)) { + m_QueryQueue.Enqueue(boost::bind(&IdoMysqlConnection::InternalExecuteMultipleQueries, this, queries), query.Priority); + } + } + + BOOST_FOREACH(const DbQuery& query, queries) { + InternalExecuteQuery(query, NULL); } } diff --git a/lib/db_ido_mysql/idomysqlconnection.hpp b/lib/db_ido_mysql/idomysqlconnection.hpp index 7f1f6dfbd..71fbc4a6e 100644 --- a/lib/db_ido_mysql/idomysqlconnection.hpp +++ b/lib/db_ido_mysql/idomysqlconnection.hpp @@ -73,7 +73,6 @@ private: int m_SessionToken; WorkQueue m_QueryQueue; - boost::mutex m_QueryQueueMutex; MYSQL m_Connection; int m_AffectedRows; @@ -106,7 +105,11 @@ private: void TxTimerHandler(void); void ReconnectTimerHandler(void); + bool CanExecuteQuery(const DbQuery& query); + void InternalExecuteQuery(const DbQuery& query, DbQueryType *typeOverride = NULL); + void InternalExecuteMultipleQueries(const std::vector& queries); + void FinishExecuteQuery(const DbQuery& query, int type, bool upsert); void InternalCleanUpExecuteQuery(const String& table, const String& time_key, double time_value); void InternalNewTransaction(void); diff --git a/lib/db_ido_pgsql/idopgsqlconnection.cpp b/lib/db_ido_pgsql/idopgsqlconnection.cpp index ae993acfb..fa52eec80 100644 --- a/lib/db_ido_pgsql/idopgsqlconnection.cpp +++ b/lib/db_ido_pgsql/idopgsqlconnection.cpp @@ -634,18 +634,59 @@ void IdoPgsqlConnection::ExecuteQuery(const DbQuery& query) { ASSERT(query.Category != DbCatInvalid); - boost::mutex::scoped_lock lock(m_QueryQueueMutex); m_QueryQueue.Enqueue(boost::bind(&IdoPgsqlConnection::InternalExecuteQuery, this, query, (DbQueryType *)NULL), query.Priority, true); } void IdoPgsqlConnection::ExecuteMultipleQueries(const std::vector& queries) { - boost::mutex::scoped_lock lock(m_QueryQueueMutex); + ASSERT(!queries.empty()); + + m_QueryQueue.Enqueue(boost::bind(&IdoPgsqlConnection::InternalExecuteMultipleQueries, this, queries), queries[0].Priority, true); +} + +bool IdoPgsqlConnection::CanExecuteQuery(const DbQuery& query) +{ + if (query.WhereCriteria) { + ObjectLock olock(query.WhereCriteria); + Value value; + + BOOST_FOREACH(const Dictionary::Pair& kv, query.WhereCriteria) { + if (!FieldToEscapedString(kv.first, kv.second, &value)) + return false; + } + } + + if (query.Fields) { + ObjectLock olock(query.Fields); + + BOOST_FOREACH(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; + } + } + + return true; +} + +void IdoPgsqlConnection::InternalExecuteMultipleQueries(const std::vector& queries) +{ + AssertOnWorkQueue(); BOOST_FOREACH(const DbQuery& query, queries) { ASSERT(query.Category != DbCatInvalid); - m_QueryQueue.Enqueue(boost::bind(&IdoPgsqlConnection::InternalExecuteQuery, this, query, (DbQueryType *)NULL), query.Priority, true); + if (!CanExecuteQuery(query)) { + m_QueryQueue.Enqueue(boost::bind(&IdoPgsqlConnection::InternalExecuteMultipleQueries, this, queries), query.Priority); + } + } + + BOOST_FOREACH(const DbQuery& query, queries) { + InternalExecuteQuery(query, NULL); } } diff --git a/lib/db_ido_pgsql/idopgsqlconnection.hpp b/lib/db_ido_pgsql/idopgsqlconnection.hpp index 135a0b111..d0e2e5673 100644 --- a/lib/db_ido_pgsql/idopgsqlconnection.hpp +++ b/lib/db_ido_pgsql/idopgsqlconnection.hpp @@ -65,7 +65,6 @@ private: int m_SessionToken; WorkQueue m_QueryQueue; - boost::mutex m_QueryQueueMutex; PGconn *m_Connection; int m_AffectedRows; @@ -92,7 +91,10 @@ private: void TxTimerHandler(void); void ReconnectTimerHandler(void); + bool CanExecuteQuery(const DbQuery& query); + void InternalExecuteQuery(const DbQuery& query, DbQueryType *typeOverride = NULL); + void InternalExecuteMultipleQueries(const std::vector& queries); void InternalCleanUpExecuteQuery(const String& table, const String& time_key, double time_value); virtual void ClearConfigTable(const String& table) override; -- 2.40.0