diff options
| author | Shauren <shauren.trinity@gmail.com> | 2019-07-27 10:52:33 +0200 |
|---|---|---|
| committer | Giacomo Pozzoni <giacomopoz@gmail.com> | 2020-03-31 13:42:01 +0000 |
| commit | 635b8d52d58f7d502fc249c11c1044923e80935f (patch) | |
| tree | 3305f07a454da2d7385e1cd60fd20a3dde5e2cec /src/server/database | |
| parent | fe1003bdbd88e2bccf2ac91ffd18804a6d9b6fb3 (diff) | |
Core/DBLayer: Prevent committing transactions started on a different database
(cherry picked from commit f6e2b8cdc1c8a3dd291947f67566b41dac116622)
# Conflicts:
# src/server/bnetserver/REST/LoginRESTService.cpp
# src/server/database/Database/DatabaseWorkerPool.cpp
# src/server/database/Database/DatabaseWorkerPool.h
# src/server/database/Database/Implementation/HotfixDatabase.h
# src/server/database/Database/MySQLConnection.h
# src/server/database/Database/Transaction.cpp
# src/server/database/Database/Transaction.h
# src/server/game/Achievements/AchievementMgr.cpp
# src/server/game/Achievements/AchievementMgr.h
# src/server/game/AuctionHouse/AuctionHouseMgr.cpp
# src/server/game/AuctionHouse/AuctionHouseMgr.h
# src/server/game/BattlePets/BattlePetMgr.cpp
# src/server/game/BattlePets/BattlePetMgr.h
# src/server/game/BlackMarket/BlackMarketMgr.cpp
# src/server/game/BlackMarket/BlackMarketMgr.h
# src/server/game/Entities/Creature/Creature.cpp
# src/server/game/Entities/Item/Item.cpp
# src/server/game/Entities/Item/Item.h
# src/server/game/Entities/Player/CollectionMgr.cpp
# src/server/game/Entities/Player/CollectionMgr.h
# src/server/game/Entities/Player/Player.cpp
# src/server/game/Entities/Player/Player.h
# src/server/game/Garrison/Garrison.cpp
# src/server/game/Garrison/Garrison.h
# src/server/game/Groups/Group.cpp
# src/server/game/Guilds/Guild.cpp
# src/server/game/Guilds/Guild.h
# src/server/game/Guilds/GuildFinderMgr.cpp
# src/server/game/Handlers/BlackMarketHandler.cpp
# src/server/game/Handlers/CalendarHandler.cpp
# src/server/game/Handlers/CharacterHandler.cpp
# src/server/game/Handlers/MailHandler.cpp
# src/server/game/Handlers/PetHandler.cpp
# src/server/game/Handlers/PetitionsHandler.cpp
# src/server/game/Mails/Mail.cpp
# src/server/game/Pools/PoolMgr.cpp
# src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp
# src/server/game/Quests/QuestObjectiveCriteriaMgr.h
# src/server/game/Scenarios/InstanceScenario.cpp
# src/server/game/Server/WorldSession.cpp
# src/server/game/Server/WorldSession.h
# src/server/game/Spells/SpellHistory.cpp
# src/server/game/Support/SupportMgr.cpp
# src/server/game/Tools/PlayerDump.cpp
# src/server/scripts/Commands/cs_misc.cpp
Diffstat (limited to 'src/server/database')
10 files changed, 53 insertions, 29 deletions
diff --git a/src/server/database/Database/DatabaseEnvFwd.h b/src/server/database/Database/DatabaseEnvFwd.h index 1fe95c54a5c..f6f7653c3f9 100644 --- a/src/server/database/Database/DatabaseEnvFwd.h +++ b/src/server/database/Database/DatabaseEnvFwd.h @@ -28,11 +28,21 @@ typedef std::shared_ptr<ResultSet> QueryResult; typedef std::future<QueryResult> QueryResultFuture; typedef std::promise<QueryResult> QueryResultPromise; +class CharacterDatabaseConnection; +class HotfixDatabaseConnection; +class LoginDatabaseConnection; +class WorldDatabaseConnection; + class PreparedStatementBase; template<typename T> class PreparedStatement; +using CharacterDatabasePreparedStatement = PreparedStatement<CharacterDatabaseConnection>; +using HotfixDatabasePreparedStatement = PreparedStatement<HotfixDatabaseConnection>; +using LoginDatabasePreparedStatement = PreparedStatement<LoginDatabaseConnection>; +using WorldDatabasePreparedStatement = PreparedStatement<WorldDatabaseConnection>; + class PreparedResultSet; typedef std::shared_ptr<PreparedResultSet> PreparedQueryResult; typedef std::future<PreparedQueryResult> PreparedQueryResultFuture; @@ -40,8 +50,18 @@ typedef std::promise<PreparedQueryResult> PreparedQueryResultPromise; class QueryCallback; +class TransactionBase; + +template<typename T> class Transaction; -typedef std::shared_ptr<Transaction> SQLTransaction; + +template<typename T> +using SQLTransaction = std::shared_ptr<Transaction<T>>; + +using CharacterDatabaseTransaction = SQLTransaction<CharacterDatabaseConnection>; +using HotfixDatabaseTransaction = SQLTransaction<HotfixDatabaseConnection>; +using LoginDatabaseTransaction = SQLTransaction<LoginDatabaseConnection>; +using WorldDatabaseTransaction = SQLTransaction<WorldDatabaseConnection>; class SQLQueryHolder; typedef std::future<SQLQueryHolder*> QueryResultHolderFuture; diff --git a/src/server/database/Database/DatabaseWorkerPool.cpp b/src/server/database/Database/DatabaseWorkerPool.cpp index da30c84a753..ac1cc3c71dc 100644 --- a/src/server/database/Database/DatabaseWorkerPool.cpp +++ b/src/server/database/Database/DatabaseWorkerPool.cpp @@ -232,13 +232,13 @@ QueryResultHolderFuture DatabaseWorkerPool<T>::DelayQueryHolder(SQLQueryHolder* } template <class T> -SQLTransaction DatabaseWorkerPool<T>::BeginTransaction() +SQLTransaction<T> DatabaseWorkerPool<T>::BeginTransaction() { - return std::make_shared<Transaction>(); + return std::make_shared<Transaction<T>>(); } template <class T> -void DatabaseWorkerPool<T>::CommitTransaction(SQLTransaction transaction) +void DatabaseWorkerPool<T>::CommitTransaction(SQLTransaction<T> transaction) { #ifdef TRINITY_DEBUG //! Only analyze transaction weaknesses in Debug mode. @@ -261,7 +261,7 @@ void DatabaseWorkerPool<T>::CommitTransaction(SQLTransaction transaction) } template <class T> -void DatabaseWorkerPool<T>::DirectCommitTransaction(SQLTransaction& transaction) +void DatabaseWorkerPool<T>::DirectCommitTransaction(SQLTransaction<T>& transaction) { T* connection = GetFreeConnection(); int errorCode = connection->ExecuteTransaction(transaction); @@ -447,7 +447,7 @@ void DatabaseWorkerPool<T>::DirectExecute(PreparedStatement<T>* stmt) } template <class T> -void DatabaseWorkerPool<T>::ExecuteOrAppend(SQLTransaction& trans, char const* sql) +void DatabaseWorkerPool<T>::ExecuteOrAppend(SQLTransaction<T>& trans, char const* sql) { if (!trans) Execute(sql); @@ -456,7 +456,7 @@ void DatabaseWorkerPool<T>::ExecuteOrAppend(SQLTransaction& trans, char const* s } template <class T> -void DatabaseWorkerPool<T>::ExecuteOrAppend(SQLTransaction& trans, PreparedStatement<T>* stmt) +void DatabaseWorkerPool<T>::ExecuteOrAppend(SQLTransaction<T>& trans, PreparedStatement<T>* stmt) { if (!trans) Execute(stmt); diff --git a/src/server/database/Database/DatabaseWorkerPool.h b/src/server/database/Database/DatabaseWorkerPool.h index 635670dce08..25cd87bf6cd 100644 --- a/src/server/database/Database/DatabaseWorkerPool.h +++ b/src/server/database/Database/DatabaseWorkerPool.h @@ -167,23 +167,23 @@ class DatabaseWorkerPool */ //! Begins an automanaged transaction pointer that will automatically rollback if not commited. (Autocommit=0) - SQLTransaction BeginTransaction(); + SQLTransaction<T> BeginTransaction(); //! Enqueues a collection of one-way SQL operations (can be both adhoc and prepared). The order in which these operations //! were appended to the transaction will be respected during execution. - void CommitTransaction(SQLTransaction transaction); + void CommitTransaction(SQLTransaction<T> transaction); //! Directly executes a collection of one-way SQL operations (can be both adhoc and prepared). The order in which these operations //! were appended to the transaction will be respected during execution. - void DirectCommitTransaction(SQLTransaction& transaction); + void DirectCommitTransaction(SQLTransaction<T>& transaction); //! Method used to execute ad-hoc statements in a diverse context. //! Will be wrapped in a transaction if valid object is present, otherwise executed standalone. - void ExecuteOrAppend(SQLTransaction& trans, char const* sql); + void ExecuteOrAppend(SQLTransaction<T>& trans, char const* sql); //! Method used to execute prepared statements in a diverse context. //! Will be wrapped in a transaction if valid object is present, otherwise executed standalone. - void ExecuteOrAppend(SQLTransaction& trans, PreparedStatement<T>* stmt); + void ExecuteOrAppend(SQLTransaction<T>& trans, PreparedStatement<T>* stmt); /** Other diff --git a/src/server/database/Database/Implementation/CharacterDatabase.h b/src/server/database/Database/Implementation/CharacterDatabase.h index bb78cdbc542..1367971d697 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.h +++ b/src/server/database/Database/Implementation/CharacterDatabase.h @@ -540,6 +540,4 @@ public: void DoPrepareStatements() override; }; -using CharacterDatabasePreparedStatement = PreparedStatement<CharacterDatabaseConnection>; - #endif diff --git a/src/server/database/Database/Implementation/LoginDatabase.h b/src/server/database/Database/Implementation/LoginDatabase.h index ea9b0d4a30f..f9a18960728 100644 --- a/src/server/database/Database/Implementation/LoginDatabase.h +++ b/src/server/database/Database/Implementation/LoginDatabase.h @@ -137,6 +137,4 @@ public: void DoPrepareStatements() override; }; -using LoginDatabasePreparedStatement = PreparedStatement<LoginDatabaseConnection>; - #endif diff --git a/src/server/database/Database/Implementation/WorldDatabase.h b/src/server/database/Database/Implementation/WorldDatabase.h index d767908244a..7b009320716 100644 --- a/src/server/database/Database/Implementation/WorldDatabase.h +++ b/src/server/database/Database/Implementation/WorldDatabase.h @@ -118,6 +118,4 @@ public: void DoPrepareStatements() override; }; -using WorldDatabasePreparedStatement = PreparedStatement<WorldDatabaseConnection>; - #endif diff --git a/src/server/database/Database/MySQLConnection.cpp b/src/server/database/Database/MySQLConnection.cpp index 06e7f703437..8205b70f38d 100644 --- a/src/server/database/Database/MySQLConnection.cpp +++ b/src/server/database/Database/MySQLConnection.cpp @@ -366,7 +366,7 @@ void MySQLConnection::CommitTransaction() Execute("COMMIT"); } -int MySQLConnection::ExecuteTransaction(SQLTransaction& transaction) +int MySQLConnection::ExecuteTransaction(std::shared_ptr<TransactionBase> transaction) { std::vector<SQLElementData> const& queries = transaction->m_queries; if (queries.empty()) diff --git a/src/server/database/Database/MySQLConnection.h b/src/server/database/Database/MySQLConnection.h index 411f570ba32..e4368db44ba 100644 --- a/src/server/database/Database/MySQLConnection.h +++ b/src/server/database/Database/MySQLConnection.h @@ -76,7 +76,7 @@ class TC_DATABASE_API MySQLConnection void BeginTransaction(); void RollbackTransaction(); void CommitTransaction(); - int ExecuteTransaction(SQLTransaction& transaction); + int ExecuteTransaction(std::shared_ptr<TransactionBase> transaction); size_t EscapeString(char* to, const char* from, size_t length); void Ping(); diff --git a/src/server/database/Database/Transaction.cpp b/src/server/database/Database/Transaction.cpp index 867dcf1f1f0..be5c28bceb3 100644 --- a/src/server/database/Database/Transaction.cpp +++ b/src/server/database/Database/Transaction.cpp @@ -29,7 +29,7 @@ std::mutex TransactionTask::_deadlockLock; #define DEADLOCK_MAX_RETRY_TIME_MS 60000 //- Append a raw ad-hoc query to the transaction -void Transaction::Append(char const* sql) +void TransactionBase::Append(char const* sql) { SQLElementData data; data.type = SQL_ELEMENT_RAW; @@ -38,7 +38,7 @@ void Transaction::Append(char const* sql) } //- Append a prepared statement to the transaction -void Transaction::Append(PreparedStatementBase* stmt) +void TransactionBase::AppendPreparedStatement(PreparedStatementBase* stmt) { SQLElementData data; data.type = SQL_ELEMENT_PREPARED; @@ -46,7 +46,7 @@ void Transaction::Append(PreparedStatementBase* stmt) m_queries.push_back(data); } -void Transaction::Cleanup() +void TransactionBase::Cleanup() { // This might be called by explicit calls to Cleanup or by the auto-destructor if (_cleanedUp) diff --git a/src/server/database/Database/Transaction.h b/src/server/database/Database/Transaction.h index 0a926f1e55d..b11f94ce14e 100644 --- a/src/server/database/Database/Transaction.h +++ b/src/server/database/Database/Transaction.h @@ -26,7 +26,7 @@ #include <vector> /*! Transactions, high level class. */ -class TC_DATABASE_API Transaction +class TC_DATABASE_API TransactionBase { friend class TransactionTask; friend class MySQLConnection; @@ -35,10 +35,9 @@ class TC_DATABASE_API Transaction friend class DatabaseWorkerPool; public: - Transaction() : _cleanedUp(false) { } - ~Transaction() { Cleanup(); } + TransactionBase() : _cleanedUp(false) { } + virtual ~TransactionBase() { Cleanup(); } - void Append(PreparedStatementBase* statement); void Append(char const* sql); template<typename Format, typename... Args> void PAppend(Format&& sql, Args&&... args) @@ -49,12 +48,23 @@ class TC_DATABASE_API Transaction std::size_t GetSize() const { return m_queries.size(); } protected: + void AppendPreparedStatement(PreparedStatementBase* statement); void Cleanup(); std::vector<SQLElementData> m_queries; private: bool _cleanedUp; +}; +template<typename T> +class Transaction : public TransactionBase +{ +public: + using TransactionBase::Append; + void Append(PreparedStatement<T>* statement) + { + AppendPreparedStatement(statement); + } }; /*! Low level class*/ @@ -64,13 +74,13 @@ class TC_DATABASE_API TransactionTask : public SQLOperation friend class DatabaseWorker; public: - TransactionTask(SQLTransaction trans) : m_trans(trans) { } + TransactionTask(std::shared_ptr<TransactionBase> trans) : m_trans(trans) { } ~TransactionTask() { } protected: bool Execute() override; - SQLTransaction m_trans; + std::shared_ptr<TransactionBase> m_trans; static std::mutex _deadlockLock; }; |
