diff --git a/src/server/database/Database/DatabaseEnvFwd.h b/src/server/database/Database/DatabaseEnvFwd.h index f85035cc83a..c72df398cd0 100644 --- a/src/server/database/Database/DatabaseEnvFwd.h +++ b/src/server/database/Database/DatabaseEnvFwd.h @@ -86,6 +86,8 @@ using HotfixDatabaseQueryHolder = SQLQueryHolder; using LoginDatabaseQueryHolder = SQLQueryHolder; using WorldDatabaseQueryHolder = SQLQueryHolder; +class SQLQueryHolderCallback; + // mysql struct MySQLHandle; struct MySQLResult; diff --git a/src/server/database/Database/DatabaseWorkerPool.cpp b/src/server/database/Database/DatabaseWorkerPool.cpp index cc732c7f1cc..07a661d5041 100644 --- a/src/server/database/Database/DatabaseWorkerPool.cpp +++ b/src/server/database/Database/DatabaseWorkerPool.cpp @@ -223,7 +223,7 @@ QueryCallback DatabaseWorkerPool::AsyncQuery(PreparedStatement* stmt) } template -QueryResultHolderFuture DatabaseWorkerPool::DelayQueryHolder(SQLQueryHolder* holder) +SQLQueryHolderCallback DatabaseWorkerPool::DelayQueryHolder(SQLQueryHolder* holder) { SQLQueryHolderTask* task = new SQLQueryHolderTask(holder); // Store future result before enqueueing - task might get already processed and deleted before returning from this method diff --git a/src/server/database/Database/DatabaseWorkerPool.h b/src/server/database/Database/DatabaseWorkerPool.h index f72817c3a8f..d17c45d6cd8 100644 --- a/src/server/database/Database/DatabaseWorkerPool.h +++ b/src/server/database/Database/DatabaseWorkerPool.h @@ -160,7 +160,7 @@ class DatabaseWorkerPool //! return object as soon as the query is executed. //! The return value is then processed in ProcessQueryCallback methods. //! Any prepared statements added to this holder need to be prepared with the CONNECTION_ASYNC flag. - QueryResultHolderFuture DelayQueryHolder(SQLQueryHolder* holder); + SQLQueryHolderCallback DelayQueryHolder(SQLQueryHolder* holder); /** Transaction context methods. diff --git a/src/server/database/Database/QueryHolder.cpp b/src/server/database/Database/QueryHolder.cpp index 92877c97ded..719914c8d5c 100644 --- a/src/server/database/Database/QueryHolder.cpp +++ b/src/server/database/Database/QueryHolder.cpp @@ -92,3 +92,14 @@ bool SQLQueryHolderTask::Execute() m_result.set_value(m_holder); return true; } + +bool SQLQueryHolderCallback::InvokeIfReady() +{ + if (m_future.valid() && m_future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) + { + m_callback(m_future.get()); + return true; + } + + return false; +} diff --git a/src/server/database/Database/QueryHolder.h b/src/server/database/Database/QueryHolder.h index 06b4dbb4916..83b80b79b15 100644 --- a/src/server/database/Database/QueryHolder.h +++ b/src/server/database/Database/QueryHolder.h @@ -64,4 +64,23 @@ class TC_DATABASE_API SQLQueryHolderTask : public SQLOperation QueryResultHolderFuture GetFuture() { return m_result.get_future(); } }; +class TC_DATABASE_API SQLQueryHolderCallback +{ +public: + SQLQueryHolderCallback(QueryResultHolderFuture&& future) : m_future(std::move(future)) { } + SQLQueryHolderCallback(SQLQueryHolderCallback&&) = default; + + SQLQueryHolderCallback& operator=(SQLQueryHolderCallback&&) = default; + + void AfterComplete(std::function callback) & + { + m_callback = std::move(callback); + } + + bool InvokeIfReady(); + + QueryResultHolderFuture m_future; + std::function m_callback; +}; + #endif diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 4dd5eb122de..cda3a08e5b7 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -797,7 +797,10 @@ void WorldSession::HandleContinuePlayerLogin() SendPacket(WorldPackets::Auth::ResumeComms(CONNECTION_TYPE_INSTANCE).Write()); - _charLoginCallback = CharacterDatabase.DelayQueryHolder(holder); + AddQueryHolderCallback(CharacterDatabase.DelayQueryHolder(holder)).AfterComplete([this](SQLQueryHolderBase* holder) + { + HandlePlayerLogin(static_cast(holder)); + }); } void WorldSession::AbortLogin(WorldPackets::Character::LoginFailureReason reason) diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 4174340b640..eb3148e2880 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -1124,13 +1124,7 @@ void WorldSession::ProcessQueryCallbacks() { _queryProcessor.ProcessReadyCallbacks(); _transactionCallbacks.ProcessReadyCallbacks(); - - if (_realmAccountLoginCallback.valid() && _realmAccountLoginCallback.wait_for(std::chrono::seconds(0)) == std::future_status::ready) - InitializeSessionCallback(static_cast(_realmAccountLoginCallback.get())); - - //! HandlePlayerLoginOpcode - if (_charLoginCallback.valid() && _charLoginCallback.wait_for(std::chrono::seconds(0)) == std::future_status::ready) - HandlePlayerLogin(reinterpret_cast(_charLoginCallback.get())); + _queryHolderProcessor.ProcessReadyCallbacks(); } TransactionCallback& WorldSession::AddTransactionCallback(TransactionCallback&& callback) @@ -1138,6 +1132,11 @@ TransactionCallback& WorldSession::AddTransactionCallback(TransactionCallback&& return _transactionCallbacks.AddCallback(std::move(callback)); } +SQLQueryHolderCallback& WorldSession::AddQueryHolderCallback(SQLQueryHolderCallback&& callback) +{ + return _queryHolderProcessor.AddCallback(std::move(callback)); +} + void WorldSession::InitWarden(BigNumber* k, std::string const& os) { if (os == "Win") @@ -1213,10 +1212,13 @@ void WorldSession::InitializeSession() return; } - _realmAccountLoginCallback = CharacterDatabase.DelayQueryHolder(realmHolder); + AddQueryHolderCallback(CharacterDatabase.DelayQueryHolder(realmHolder)).AfterComplete([this](SQLQueryHolderBase* holder) + { + InitializeSessionCallback(static_cast(holder)); + }); } -void WorldSession::InitializeSessionCallback(LoginDatabaseQueryHolder* realmHolder) +void WorldSession::InitializeSessionCallback(CharacterDatabaseQueryHolder* realmHolder) { LoadAccountData(realmHolder->GetPreparedResult(AccountInfoQueryHolderPerRealm::GLOBAL_ACCOUNT_DATA), GLOBAL_CACHE_MASK); LoadTutorialsData(realmHolder->GetPreparedResult(AccountInfoQueryHolderPerRealm::TUTORIALS)); diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index d729ac765e9..12949b5e3cd 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -417,7 +417,7 @@ class TC_GAME_API WorldSession void SendClientCacheVersion(uint32 version); void InitializeSession(); - void InitializeSessionCallback(LoginDatabaseQueryHolder* realmHolder); + void InitializeSessionCallback(CharacterDatabaseQueryHolder* realmHolder); rbac::RBACData* GetRBACData(); bool HasPermission(uint32 permissionId); @@ -1212,6 +1212,7 @@ class TC_GAME_API WorldSession public: QueryCallbackProcessor& GetQueryProcessor() { return _queryProcessor; } TransactionCallback& AddTransactionCallback(TransactionCallback&& callback); + SQLQueryHolderCallback& AddQueryHolderCallback(SQLQueryHolderCallback&& callback); // Compact Unit Frames (4.x) void HandleSaveCUFProfiles(WorldPacket& recvPacket); @@ -1220,12 +1221,9 @@ class TC_GAME_API WorldSession private: void ProcessQueryCallbacks(); - QueryResultHolderFuture _realmAccountLoginCallback; - QueryResultHolderFuture _guildRenameCallback; - QueryResultHolderFuture _charLoginCallback; - QueryCallbackProcessor _queryProcessor; AsyncCallbackProcessor _transactionCallbacks; + AsyncCallbackProcessor _queryHolderProcessor; friend class World; protected: