diff options
| author | Giacomo Pozzoni <giacomopoz@gmail.com> | 2020-05-30 15:43:54 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-05-30 17:43:54 +0200 |
| commit | 141ada19b00fb9d0dd1a260d86d97bbb709a0f5e (patch) | |
| tree | 03c8559a245f404d7d84655fe5c5066ec22e2ee7 /src/server/game | |
| parent | 00bc6e7d54e924dabaf4636a4b8084f0db067194 (diff) | |
Cherry pick some db commits (#24713)
* Core/DBLayer: Implement async transaction completion callbacks
(cherry picked from commit 0f0ca3a9194d76afa0227943e86469ad8368c5e2)
# Conflicts:
# src/server/bnetserver/REST/LoginRESTService.cpp
# src/server/bnetserver/Server/Session.cpp
# src/server/bnetserver/Server/Session.h
# src/server/database/Database/Transaction.cpp
# src/server/game/Handlers/CharacterHandler.cpp
# src/server/game/Handlers/SpellHandler.cpp
# src/server/game/Server/WorldSession.cpp
# src/server/game/Server/WorldSocket.cpp
# src/server/game/Server/WorldSocket.h
* Core/Misc: Fixed char enum packet sometimes not showing newly created character when client latency is too low
(cherry picked from commit fc9d2e728e5c21bd2a1645a29be60d0e280ad940)
# Conflicts:
# src/server/game/Handlers/CharacterHandler.cpp
* Fix no-pch build
* Core/Player: Wait for correct transaction on character creation
(cherry picked from commit 01c68b2aa2ed25ea9b4c007f238a0e958f6525b1)
# Conflicts:
# src/server/game/Entities/Player/Player.cpp
* Fix warning
* Remove unused login transaction
Co-authored-by: Shauren <shauren.trinity@gmail.com>
Diffstat (limited to 'src/server/game')
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 14 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.h | 1 | ||||
| -rw-r--r-- | src/server/game/Handlers/CharacterHandler.cpp | 52 | ||||
| -rw-r--r-- | src/server/game/Handlers/NPCHandler.cpp | 8 | ||||
| -rw-r--r-- | src/server/game/Handlers/SpellHandler.cpp | 2 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSession.cpp | 8 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSession.h | 4 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSocket.cpp | 10 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSocket.h | 1 | ||||
| -rw-r--r-- | src/server/game/World/World.cpp | 4 | ||||
| -rw-r--r-- | src/server/game/World/World.h | 2 |
11 files changed, 66 insertions, 40 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 806ffb49c07..a9ef1c5d157 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -19319,6 +19319,15 @@ bool Player::_LoadHomeBind(PreparedQueryResult result) void Player::SaveToDB(bool create /*=false*/) { + CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); + + SaveToDB(trans, create); + + CharacterDatabase.CommitTransaction(trans); +} + +void Player::SaveToDB(CharacterDatabaseTransaction trans, bool create /* = false */) +{ // delay auto save at any saves (manual, in code, or autosave) m_nextSave = sWorld->getIntConfig(CONFIG_INTERVAL_SAVE); @@ -19338,7 +19347,6 @@ void Player::SaveToDB(bool create /*=false*/) if (!create) sScriptMgr->OnPlayerSave(this); - CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction(); CharacterDatabasePreparedStatement* stmt = nullptr; uint8 index = 0; @@ -19630,8 +19638,6 @@ void Player::SaveToDB(bool create /*=false*/) if (m_session->isLogingOut() || !sWorld->getBoolConfig(CONFIG_STATS_SAVE_ONLY_ON_LOGOUT)) _SaveStats(trans); - CharacterDatabase.CommitTransaction(trans); - // save pet (hunter pet level and experience and all type pets health/mana). if (Pet* pet = GetPet()) pet->SavePetToDB(PET_SAVE_AS_CURRENT); @@ -26196,7 +26202,7 @@ void Player::ActivateSpec(uint8 spec) stmt->setUInt8(1, m_activeSpec); WorldSession* mySess = GetSession(); - mySess->GetQueryProcessor().AddQuery(CharacterDatabase.AsyncQuery(stmt) + mySess->GetQueryProcessor().AddCallback(CharacterDatabase.AsyncQuery(stmt) .WithPreparedCallback([mySess](PreparedQueryResult result) { // safe callback, we can't pass this pointer directly diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 97835fb8712..9fc1281158d 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1333,6 +1333,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> /*********************************************************/ void SaveToDB(bool create = false); + void SaveToDB(CharacterDatabaseTransaction trans, bool create = false); void SaveInventoryAndGoldToDB(CharacterDatabaseTransaction& trans); // fast save function for item/money cheating preventing void SaveGoldToDB(CharacterDatabaseTransaction& trans) const; diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 7744301eb98..81e107f2db3 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -265,7 +265,7 @@ void WorldSession::HandleCharEnumOpcode(WorldPacket& /*recvData*/) stmt->setUInt8(0, PET_SAVE_AS_CURRENT); stmt->setUInt32(1, GetAccountId()); - _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleCharEnum, this, std::placeholders::_1))); + _queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleCharEnum, this, std::placeholders::_1))); } void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData) @@ -408,7 +408,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData) CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME); stmt->setString(0, createInfo->Name); - _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt) + _queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt) .WithChainingPreparedCallback([this](QueryCallback& queryCallback, PreparedQueryResult result) { if (result) @@ -563,29 +563,31 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData) return; } - Player newChar(this); - newChar.GetMotionMaster()->Initialize(); - if (!newChar.Create(sObjectMgr->GetGenerator<HighGuid::Player>().Generate(), createInfo.get())) - + std::shared_ptr<Player> newChar(new Player(this), [](Player* ptr) + { + ptr->CleanupsBeforeDelete(); + delete ptr; + }); + newChar->GetMotionMaster()->Initialize(); + if (!newChar->Create(sObjectMgr->GetGenerator<HighGuid::Player>().Generate(), createInfo.get())) { // Player not create (race/class/etc problem?) - newChar.CleanupsBeforeDelete(); - SendCharCreate(CHAR_CREATE_ERROR); return; } if ((haveSameRace && skipCinematics == 1) || skipCinematics == 2) - newChar.setCinematic(1); // not show intro + newChar->setCinematic(1); // not show intro - newChar.SetAtLoginFlag(AT_LOGIN_FIRST); // First login + newChar->SetAtLoginFlag(AT_LOGIN_FIRST); // First login + + CharacterDatabaseTransaction characterTransaction = CharacterDatabase.BeginTransaction(); + LoginDatabaseTransaction trans = LoginDatabase.BeginTransaction(); // Player created, save it now - newChar.SaveToDB(true); + newChar->SaveToDB(characterTransaction, true); createInfo->CharCount += 1; - LoginDatabaseTransaction trans = LoginDatabase.BeginTransaction(); - LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_REALM_CHARACTERS_BY_REALM); stmt->setUInt32(0, GetAccountId()); stmt->setUInt32(1, realm.Id.Realm); @@ -599,13 +601,19 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData) LoginDatabase.CommitTransaction(trans); - SendCharCreate(CHAR_CREATE_SUCCESS); - - TC_LOG_INFO("entities.player.character", "Account: %d (IP: %s) Create Character:[%s] %s", GetAccountId(), GetRemoteAddress().c_str(), createInfo->Name.c_str(), newChar.GetGUID().ToString().c_str()); - sScriptMgr->OnPlayerCreate(&newChar); - sCharacterCache->AddCharacterCacheEntry(newChar.GetGUID(), GetAccountId(), newChar.GetName(), newChar.GetNativeGender(), newChar.GetRace(), newChar.GetClass(), newChar.GetLevel()); + AddTransactionCallback(CharacterDatabase.AsyncCommitTransaction(characterTransaction)).AfterComplete([this, newChar = std::move(newChar)](bool success) + { + if (success) + { + TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Create Character: %s %s", GetAccountId(), GetRemoteAddress().c_str(), newChar->GetName().c_str(), newChar->GetGUID().ToString().c_str()); + sScriptMgr->OnPlayerCreate(newChar.get()); + sCharacterCache->AddCharacterCacheEntry(newChar->GetGUID(), GetAccountId(), newChar->GetName(), newChar->GetNativeGender(), newChar->GetRace(), newChar->GetClass(), newChar->GetLevel()); - newChar.CleanupsBeforeDelete(); + SendCharCreate(CHAR_CREATE_SUCCESS); + } + else + SendCharCreate(CHAR_CREATE_ERROR); + }); }; if (allowTwoSideAccounts && !skipCinematics && createInfo->Class != CLASS_DEATH_KNIGHT) @@ -1135,7 +1143,7 @@ void WorldSession::HandleCharRenameOpcode(WorldPacket& recvData) stmt->setUInt32(1, GetAccountId()); stmt->setString(2, renameInfo->Name); - _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt) + _queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt) .WithPreparedCallback(std::bind(&WorldSession::HandleCharRenameCallBack, this, renameInfo, std::placeholders::_1))); } @@ -1376,7 +1384,7 @@ void WorldSession::HandleCharCustomize(WorldPacket& recvData) CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CUSTOMIZE_INFO); stmt->setUInt32(0, customizeInfo->Guid.GetCounter()); - _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt) + _queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt) .WithPreparedCallback(std::bind(&WorldSession::HandleCharCustomizeCallback, this, customizeInfo, std::placeholders::_1))); } @@ -1632,7 +1640,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData) CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_RACE_OR_FACTION_CHANGE_INFOS); stmt->setUInt32(0, factionChangeInfo->Guid.GetCounter()); - _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt) + _queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt) .WithPreparedCallback(std::bind(&WorldSession::HandleCharFactionOrRaceChangeCallback, this, factionChangeInfo, std::placeholders::_1))); } diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp index 1078de17111..f25efb18b70 100644 --- a/src/server/game/Handlers/NPCHandler.cpp +++ b/src/server/game/Handlers/NPCHandler.cpp @@ -308,7 +308,7 @@ void WorldSession::SendStablePet(ObjectGuid guid) stmt->setUInt8(1, PET_SAVE_FIRST_STABLE_SLOT); stmt->setUInt8(2, PET_SAVE_LAST_STABLE_SLOT); - _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::SendStablePetCallback, this, guid, std::placeholders::_1))); + _queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::SendStablePetCallback, this, guid, std::placeholders::_1))); } void WorldSession::SendStablePetCallback(ObjectGuid guid, PreparedQueryResult result) @@ -409,7 +409,7 @@ void WorldSession::HandleStablePet(WorldPacket& recvData) stmt->setUInt8(1, PET_SAVE_FIRST_STABLE_SLOT); stmt->setUInt8(2, PET_SAVE_LAST_STABLE_SLOT); - _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleStablePetCallback, this, std::placeholders::_1))); + _queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleStablePetCallback, this, std::placeholders::_1))); } void WorldSession::HandleStablePetCallback(PreparedQueryResult result) @@ -471,7 +471,7 @@ void WorldSession::HandleUnstablePet(WorldPacket& recvData) stmt->setUInt8(2, PET_SAVE_FIRST_STABLE_SLOT); stmt->setUInt8(3, PET_SAVE_LAST_STABLE_SLOT); - _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleUnstablePetCallback, this, petnumber, std::placeholders::_1))); + _queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleUnstablePetCallback, this, petnumber, std::placeholders::_1))); } void WorldSession::HandleUnstablePetCallback(uint32 petId, PreparedQueryResult result) @@ -597,7 +597,7 @@ void WorldSession::HandleStableSwapPet(WorldPacket& recvData) stmt->setUInt32(0, _player->GetGUID().GetCounter()); stmt->setUInt32(1, petId); - _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleStableSwapPetCallback, this, petId, std::placeholders::_1))); + _queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleStableSwapPetCallback, this, petId, std::placeholders::_1))); } void WorldSession::HandleStableSwapPetCallback(uint32 petId, PreparedQueryResult result) diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index fc62887894a..740f4144d3b 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -241,7 +241,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) { CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_GIFT_BY_ITEM); stmt->setUInt32(0, item->GetGUID().GetCounter()); - _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt) + _queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt) .WithPreparedCallback(std::bind(&WorldSession::HandleOpenWrappedItemCallback, this, item->GetPos(), item->GetGUID(), std::placeholders::_1))); } else diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 55282e1a7bb..256e818de5f 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -1193,7 +1193,8 @@ void WorldSession::SetPlayer(Player* player) void WorldSession::ProcessQueryCallbacks() { - _queryProcessor.ProcessReadyQueries(); + _queryProcessor.ProcessReadyCallbacks(); + _transactionCallbacks.ProcessReadyCallbacks(); if (_realmAccountLoginCallback.valid() && _realmAccountLoginCallback.wait_for(std::chrono::seconds(0)) == std::future_status::ready) InitializeSessionCallback(static_cast<CharacterDatabaseQueryHolder*>(_realmAccountLoginCallback.get())); @@ -1203,6 +1204,11 @@ void WorldSession::ProcessQueryCallbacks() HandlePlayerLogin(reinterpret_cast<LoginQueryHolder*>(_charLoginCallback.get())); } +TransactionCallback& WorldSession::AddTransactionCallback(TransactionCallback&& callback) +{ + return _transactionCallbacks.AddCallback(std::move(callback)); +} + void WorldSession::InitWarden(BigNumber* k, std::string const& os) { if (os == "Win") diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 57794ac81bf..b9df671a502 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -23,11 +23,11 @@ #define __WORLDSESSION_H #include "Common.h" +#include "AsyncCallbackProcessor.h" #include "DatabaseEnvFwd.h" #include "LockedQueue.h" #include "ObjectGuid.h" #include "Packet.h" -#include "QueryCallbackProcessor.h" #include "SharedDefines.h" #include <string> #include <map> @@ -1091,6 +1091,7 @@ class TC_GAME_API WorldSession public: QueryCallbackProcessor& GetQueryProcessor() { return _queryProcessor; } + TransactionCallback& AddTransactionCallback(TransactionCallback&& callback); private: void ProcessQueryCallbacks(); @@ -1099,6 +1100,7 @@ class TC_GAME_API WorldSession QueryResultHolderFuture _charLoginCallback; QueryCallbackProcessor _queryProcessor; + AsyncCallbackProcessor<TransactionCallback> _transactionCallbacks; friend class World; protected: diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 0e65704076d..ff85f71c769 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -39,13 +39,15 @@ WorldSocket::WorldSocket(tcp::socket&& socket) _headerBuffer.Resize(sizeof(ClientPktHeader)); } +WorldSocket::~WorldSocket() = default; + void WorldSocket::Start() { std::string ip_address = GetRemoteIpAddress().to_string(); LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP_INFO); stmt->setString(0, ip_address); - _queryProcessor.AddQuery(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSocket::CheckIpCallback, this, std::placeholders::_1))); + _queryProcessor.AddCallback(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSocket::CheckIpCallback, this, std::placeholders::_1))); } void WorldSocket::CheckIpCallback(PreparedQueryResult result) @@ -115,7 +117,7 @@ bool WorldSocket::Update() if (!BaseSocket::Update()) return false; - _queryProcessor.ProcessReadyQueries(); + _queryProcessor.ProcessReadyCallbacks(); return true; } @@ -439,7 +441,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket) stmt->setInt32(0, int32(realm.Id.Realm)); stmt->setString(1, authSession->Account); - _queryProcessor.AddQuery(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSocket::HandleAuthSessionCallback, this, authSession, std::placeholders::_1))); + _queryProcessor.AddCallback(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSocket::HandleAuthSessionCallback, this, authSession, std::placeholders::_1))); } void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<AuthSession> authSession, PreparedQueryResult result) @@ -600,7 +602,7 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<AuthSession> authSes if (wardenActive) _worldSession->InitWarden(&account.SessionKey, account.OS); - _queryProcessor.AddQuery(_worldSession->LoadPermissionsAsync().WithPreparedCallback(std::bind(&WorldSocket::LoadSessionPermissionsCallback, this, std::placeholders::_1))); + _queryProcessor.AddCallback(_worldSession->LoadPermissionsAsync().WithPreparedCallback(std::bind(&WorldSocket::LoadSessionPermissionsCallback, this, std::placeholders::_1))); AsyncRead(); } diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h index 6f6b0848423..00d2ec59651 100644 --- a/src/server/game/Server/WorldSocket.h +++ b/src/server/game/Server/WorldSocket.h @@ -71,6 +71,7 @@ class TC_GAME_API WorldSocket : public Socket<WorldSocket> public: WorldSocket(tcp::socket&& socket); + ~WorldSocket(); WorldSocket(WorldSocket const& right) = delete; WorldSocket& operator=(WorldSocket const& right) = delete; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 93f1b919dab..34864e46779 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -3120,7 +3120,7 @@ void World::UpdateRealmCharCount(uint32 accountId) { CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_COUNT); stmt->setUInt32(0, accountId); - _queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&World::_UpdateRealmCharCount, this, std::placeholders::_1))); + _queryProcessor.AddCallback(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&World::_UpdateRealmCharCount, this, std::placeholders::_1))); } void World::_UpdateRealmCharCount(PreparedQueryResult resultCharCount) @@ -3492,7 +3492,7 @@ uint64 World::getWorldState(uint32 index) const void World::ProcessQueryCallbacks() { - _queryProcessor.ProcessReadyQueries(); + _queryProcessor.ProcessReadyCallbacks(); } void World::ReloadRBAC() diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 24338a7eee3..98c3df02ba7 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -23,10 +23,10 @@ #define __WORLD_H #include "Common.h" +#include "AsyncCallbackProcessor.h" #include "DatabaseEnvFwd.h" #include "LockedQueue.h" #include "ObjectGuid.h" -#include "QueryCallbackProcessor.h" #include "SharedDefines.h" #include "Timer.h" |
