Core/DBLayer: Convert async queries to new query callbacks and remove old callback handling

(cherry picked from commit 8e2634b2b4)

Conflicts:
	src/server/bnetserver/Server/Session.cpp
	src/server/bnetserver/Server/Session.h
	src/server/database/Database/QueryCallback.cpp
	src/server/game/Handlers/CharacterHandler.cpp
	src/server/game/Handlers/SocialHandler.cpp
	src/server/game/Server/WorldSession.cpp
	src/server/game/Server/WorldSession.h
	src/server/game/Server/WorldSocket.cpp
	src/server/game/Server/WorldSocket.h
	src/server/game/World/World.cpp
	src/server/game/World/World.h
This commit is contained in:
Shauren
2017-01-13 21:38:03 +01:00
committed by ariel-
parent 8af3cccc83
commit 4c27203c8f
21 changed files with 561 additions and 827 deletions

View File

@@ -169,8 +169,7 @@ void AuthSession::Start()
stmt->setString(0, ip_address);
stmt->setUInt32(1, inet_addr(ip_address.c_str()));
_queryCallback = std::bind(&AuthSession::CheckIpCallback, this, std::placeholders::_1);
_queryFuture = LoginDatabase.AsyncQuery(stmt);
_queryCallback = std::move(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&AuthSession::CheckIpCallback, this, std::placeholders::_1)));
}
bool AuthSession::Update()
@@ -178,12 +177,8 @@ bool AuthSession::Update()
if (!AuthSocket::Update())
return false;
if (_queryFuture.valid() && _queryFuture.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
{
auto callback = _queryCallback;
_queryCallback = nullptr;
callback(_queryFuture.get());
}
if (_queryCallback && _queryCallback->InvokeIfReady() == QueryCallback::Completed)
_queryCallback = boost::none;
return true;
}
@@ -323,8 +318,7 @@ bool AuthSession::HandleLogonChallenge()
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_LOGONCHALLENGE);
stmt->setString(0, login);
_queryCallback = std::bind(&AuthSession::LogonChallengeCallback, this, std::placeholders::_1);
_queryFuture = LoginDatabase.AsyncQuery(stmt);
_queryCallback = std::move(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&AuthSession::LogonChallengeCallback, this, std::placeholders::_1)));
return true;
}
@@ -737,8 +731,7 @@ bool AuthSession::HandleReconnectChallenge()
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_RECONNECTCHALLENGE);
stmt->setString(0, login);
_queryCallback = std::bind(&AuthSession::ReconnectChallengeCallback, this, std::placeholders::_1);
_queryFuture = LoginDatabase.AsyncQuery(stmt);
_queryCallback = std::move(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&AuthSession::ReconnectChallengeCallback, this, std::placeholders::_1)));
return true;
}
@@ -819,8 +812,7 @@ bool AuthSession::HandleRealmList()
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALM_CHARACTER_COUNTS);
stmt->setUInt32(0, _accountInfo.Id);
_queryCallback = std::bind(&AuthSession::RealmListCallback, this, std::placeholders::_1);
_queryFuture = LoginDatabase.AsyncQuery(stmt);
_queryCallback = std::move(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&AuthSession::RealmListCallback, this, std::placeholders::_1)));
return true;
}

View File

@@ -102,8 +102,7 @@ private:
uint16 _build;
uint8 _expversion;
PreparedQueryResultFuture _queryFuture;
std::function<void(PreparedQueryResult)> _queryCallback;
Optional<QueryCallback> _queryCallback;
};
#pragma pack(push, 1)

View File

@@ -17,6 +17,7 @@
#include "DatabaseWorkerPool.h"
#include "DatabaseEnv.h"
#include "QueryCallback.h"
#define MIN_MYSQL_SERVER_VERSION 50100u
#define MIN_MYSQL_CLIENT_VERSION 50100u
@@ -146,23 +147,23 @@ PreparedQueryResult DatabaseWorkerPool<T>::Query(PreparedStatement* stmt)
}
template <class T>
QueryResultFuture DatabaseWorkerPool<T>::AsyncQuery(const char* sql)
QueryCallback DatabaseWorkerPool<T>::AsyncQuery(const char* sql)
{
BasicStatementTask* task = new BasicStatementTask(sql, true);
// Store future result before enqueueing - task might get already processed and deleted before returning from this method
QueryResultFuture result = task->GetFuture();
Enqueue(task);
return result;
return QueryCallback(std::move(result));
}
template <class T>
PreparedQueryResultFuture DatabaseWorkerPool<T>::AsyncQuery(PreparedStatement* stmt)
QueryCallback DatabaseWorkerPool<T>::AsyncQuery(PreparedStatement* stmt)
{
PreparedStatementTask* task = new PreparedStatementTask(stmt, true);
// Store future result before enqueueing - task might get already processed and deleted before returning from this method
PreparedQueryResultFuture result = task->GetFuture();
Enqueue(task);
return result;
return QueryCallback(std::move(result));
}
template <class T>

View File

@@ -19,7 +19,6 @@
#define _DATABASEWORKERPOOL_H
#include "Common.h"
#include "QueryCallback.h"
#include "MySQLConnection.h"
#include "Transaction.h"
#include "DatabaseWorker.h"
@@ -34,6 +33,8 @@
#include <memory>
#include <array>
class QueryCallback;
class PingOperation : public SQLOperation
{
//! Operation for idle delaythreads
@@ -192,12 +193,12 @@ class DatabaseWorkerPool
//! Enqueues a query in string format that will set the value of the QueryResultFuture return object as soon as the query is executed.
//! The return value is then processed in ProcessQueryCallback methods.
QueryResultFuture AsyncQuery(const char* sql);
QueryCallback AsyncQuery(const char* sql);
//! Enqueues a query in string format -with variable args- that will set the value of the QueryResultFuture return object as soon as the query is executed.
//! The return value is then processed in ProcessQueryCallback methods.
template<typename Format, typename... Args>
QueryResultFuture AsyncPQuery(Format&& sql, Args&&... args)
QueryCallback AsyncPQuery(Format&& sql, Args&&... args)
{
return AsyncQuery(Trinity::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str());
}
@@ -205,7 +206,7 @@ class DatabaseWorkerPool
//! Enqueues a query in prepared format that will set the value of the PreparedQueryResultFuture return object as soon as the query is executed.
//! The return value is then processed in ProcessQueryCallback methods.
//! Statement must be prepared with CONNECTION_ASYNC flag.
PreparedQueryResultFuture AsyncQuery(PreparedStatement* stmt);
QueryCallback AsyncQuery(PreparedStatement* stmt);
//! Enqueues a vector of SQL operations (can be both adhoc and prepared) that will set the value of the QueryResultHolderFuture
//! return object as soon as the query is executed.

View File

@@ -51,7 +51,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
"cb.guid, cd.genitive FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? "
"LEFT JOIN character_declinedname AS cd ON c.guid = cd.guid LEFT JOIN guild_member AS gm ON c.guid = gm.guid "
"LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.account = ? AND c.deleteInfos_Name IS NULL ORDER BY c.guid", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_FREE_NAME, "SELECT guid, name FROM characters WHERE guid = ? AND account = ? AND (at_login & ?) = ? AND NOT EXISTS (SELECT NULL FROM characters WHERE name = ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_FREE_NAME, "SELECT guid, name, at_login FROM characters WHERE guid = ? AND account = ? AND NOT EXISTS (SELECT NULL FROM characters WHERE name = ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_GUID_RACE_ACC_BY_NAME, "SELECT guid, race, account FROM characters WHERE name = ?", CONNECTION_BOTH);
PrepareStatement(CHAR_SEL_CHAR_LEVEL, "SELECT level FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_ZONE, "SELECT zone FROM characters WHERE guid = ?", CONNECTION_SYNCH);
@@ -162,7 +162,6 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHARACTER_NAME_CLASS, "SELECT name, class FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_MATCH_MAKER_RATING, "SELECT matchMakerRating FROM character_arena_stats WHERE guid = ? AND slot = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHARACTER_COUNT, "SELECT account, COUNT(guid) FROM characters WHERE account = ? GROUP BY account", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_NAME, "UPDATE characters set name = ?, at_login = at_login & ~ ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_NAME_BY_GUID, "UPDATE characters SET name = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_DECLINED_NAME, "DELETE FROM character_declinedname WHERE guid = ?", CONNECTION_ASYNC);
@@ -399,7 +398,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_UPD_INSTANCE_RESETTIME, "UPDATE instance SET resettime = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_GLOBAL_INSTANCE_RESETTIME, "UPDATE instance_reset SET resettime = ? WHERE mapid = ? AND difficulty = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_ONLINE, "UPDATE characters SET online = 1 WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_NAME_AT_LOGIN, "UPDATE characters set name = ?, at_login = at_login & ~ ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_NAME_AT_LOGIN, "UPDATE characters set name = ?, at_login = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_WORLDSTATE, "UPDATE worldstates SET value = ? WHERE entry = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_WORLDSTATE, "INSERT INTO worldstates (entry, value) VALUES (?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_INSTANCE_BY_INSTANCE_GUID, "DELETE FROM character_instance WHERE guid = ? AND instance = ?", CONNECTION_ASYNC);
@@ -429,7 +428,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_POOL_QUEST_SAVE, "SELECT quest_id FROM pool_quest_save WHERE pool_id = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHARACTER_AT_LOGIN, "SELECT at_login FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_CLASS_LVL_AT_LOGIN, "SELECT class, level, at_login, knownTitles FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_AT_LOGIN_TITLES, "SELECT at_login, knownTitles FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_CUSTOMIZE_INFO, "SELECT name, race, class, gender, at_login FROM characters WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHAR_RACE_OR_FACTION_CHANGE_INFOS, "SELECT at_login, knownTitles FROM characters WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_INSTANCE, "SELECT data, completedEncounters FROM instance WHERE map = ? AND id = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_PERM_BIND_BY_INSTANCE, "SELECT guid FROM character_instance WHERE instance = ? and permanent = 1", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_COD_ITEM_MAIL, "SELECT id, messageType, mailTemplateId, sender, subject, body, money, has_items FROM mail WHERE receiver = ? AND has_items <> 0 AND cod <> 0", CONNECTION_SYNCH);
@@ -477,7 +477,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_PETITION_SIGNATURE_BY_GUID, "DELETE FROM petition_sign WHERE petitionguid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_DECLINED_NAME, "DELETE FROM character_declinedname WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_DECLINED_NAME, "INSERT INTO character_declinedname (guid, genitive, dative, accusative, instrumental, prepositional) VALUES (?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_FACTION_OR_RACE, "UPDATE characters SET name = ?, race = ?, at_login = at_login & ~ ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_RACE, "UPDATE characters SET race = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_SKILL_LANGUAGES, "DELETE FROM character_skills WHERE skill IN (98, 113, 759, 111, 313, 109, 115, 315, 673, 137) AND guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_SKILL_LANGUAGE, "INSERT INTO `character_skills` (guid, skill, value, max) VALUES (?, ?, 300, 300)", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_TAXI_PATH, "UPDATE characters SET taxi_path = '' WHERE guid = ?", CONNECTION_ASYNC);

View File

@@ -148,7 +148,6 @@ enum CharacterDatabaseStatements
CHAR_SEL_CHARACTER_NAME_CLASS,
CHAR_SEL_MATCH_MAKER_RATING,
CHAR_SEL_CHARACTER_COUNT,
CHAR_UPD_NAME,
CHAR_UPD_NAME_BY_GUID,
CHAR_DEL_DECLINED_NAME,
@@ -360,7 +359,8 @@ enum CharacterDatabaseStatements
CHAR_SEL_POOL_QUEST_SAVE,
CHAR_SEL_CHARACTER_AT_LOGIN,
CHAR_SEL_CHAR_CLASS_LVL_AT_LOGIN,
CHAR_SEL_CHAR_AT_LOGIN_TITLES,
CHAR_SEL_CHAR_CUSTOMIZE_INFO,
CHAR_SEL_CHAR_RACE_OR_FACTION_CHANGE_INFOS,
CHAR_SEL_INSTANCE,
CHAR_SEL_PERM_BIND_BY_INSTANCE,
CHAR_SEL_CHAR_COD_ITEM_MAIL,
@@ -403,7 +403,7 @@ enum CharacterDatabaseStatements
CHAR_DEL_PETITION_SIGNATURE_BY_GUID,
CHAR_DEL_CHAR_DECLINED_NAME,
CHAR_INS_CHAR_DECLINED_NAME,
CHAR_UPD_FACTION_OR_RACE,
CHAR_UPD_CHAR_RACE,
CHAR_DEL_CHAR_SKILL_LANGUAGES,
CHAR_INS_CHAR_SKILL_LANGUAGE,
CHAR_UPD_CHAR_TAXI_PATH,

View File

@@ -17,6 +17,12 @@
#include "QueryCallback.h"
template<typename T>
inline void Construct(T& t)
{
new (&t) T();
}
template<typename T>
inline void Destroy(T& t)
{
@@ -24,109 +30,174 @@ inline void Destroy(T& t)
}
template<typename T>
void DestroyActiveMember(T& obj)
void ConstructActiveMember(T* obj)
{
if (!obj._isPrepared)
Destroy(obj._string);
if (!obj->_isPrepared)
Construct(obj->_string);
else
Destroy(obj._prepared);
Construct(obj->_prepared);
}
template<typename T>
void MoveFrom(T& to, T&& from)
void DestroyActiveMember(T* obj)
{
DestroyActiveMember(to);
to._isPrepared = from._isPrepared;
if (!to._isPrepared)
to._string = std::move(from._string);
if (!obj->_isPrepared)
Destroy(obj->_string);
else
to._prepared = std::move(from._prepared);
Destroy(obj->_prepared);
}
struct QueryCallbackNew::QueryCallbackData
template<typename T>
void MoveFrom(T* to, T&& from)
{
ASSERT(to->_isPrepared == from._isPrepared);
if (!to->_isPrepared)
to->_string = std::move(from._string);
else
to->_prepared = std::move(from._prepared);
}
struct QueryCallback::QueryCallbackData
{
public:
friend class QueryCallbackNew;
friend class QueryCallback;
QueryCallbackData(std::function<void(QueryResult)>&& callback) : _string(std::move(callback)), _isPrepared(false) { }
QueryCallbackData(std::function<void(PreparedQueryResult)>&& callback) : _prepared(std::move(callback)), _isPrepared(true) { }
QueryCallbackData(QueryCallbackData&& right) { MoveFrom(*this, std::move(right)); }
QueryCallbackData& operator=(QueryCallbackData&& right) { MoveFrom(*this, std::move(right)); }
~QueryCallbackData() { DestroyActiveMember(*this); }
QueryCallbackData(std::function<void(QueryCallback&, QueryResult)>&& callback) : _string(std::move(callback)), _isPrepared(false) { TC_LOG_ERROR(LOGGER_ROOT, "QueryCallbackData [%p]: Constructing from string query", (void*)this); }
QueryCallbackData(std::function<void(QueryCallback&, PreparedQueryResult)>&& callback) : _prepared(std::move(callback)), _isPrepared(true) { TC_LOG_ERROR(LOGGER_ROOT, "QueryCallbackData [%p]: Constructing from prepared query", (void*)this); }
QueryCallbackData(QueryCallbackData&& right)
{
_isPrepared = right._isPrepared;
ConstructActiveMember(this);
MoveFrom(this, std::move(right));
}
QueryCallbackData& operator=(QueryCallbackData&& right)
{
if (this != &right)
{
if (_isPrepared != right._isPrepared)
{
DestroyActiveMember(this);
_isPrepared = right._isPrepared;
ConstructActiveMember(this);
}
MoveFrom(this, std::move(right));
}
return *this;
}
~QueryCallbackData() { DestroyActiveMember(this); }
private:
QueryCallbackData(QueryCallbackData const&) = delete;
QueryCallbackData& operator=(QueryCallbackData const&) = delete;
template<typename T> friend void MoveFrom(T& to, T&& from);
template<typename T> friend void DestroyActiveMember(T& obj);
template<typename T> friend void ConstructActiveMember(T* obj);
template<typename T> friend void DestroyActiveMember(T* obj);
template<typename T> friend void MoveFrom(T* to, T&& from);
union
{
std::function<void(QueryResult)> _string;
std::function<void(PreparedQueryResult)> _prepared;
std::function<void(QueryCallback&, QueryResult)> _string;
std::function<void(QueryCallback&, PreparedQueryResult)> _prepared;
};
bool _isPrepared;
};
QueryCallbackNew::QueryCallbackNew(std::future<QueryResult>&& result) : _string(std::move(result)), _isPrepared(false)
QueryCallback::QueryCallback(std::future<QueryResult>&& result) : _string(std::move(result)), _isPrepared(false)
{
}
QueryCallbackNew::QueryCallbackNew(std::future<PreparedQueryResult>&& result) : _prepared(std::move(result)), _isPrepared(true)
QueryCallback::QueryCallback(std::future<PreparedQueryResult>&& result) : _prepared(std::move(result)), _isPrepared(true)
{
}
QueryCallbackNew::QueryCallbackNew(QueryCallbackNew&& right)
QueryCallback::QueryCallback(QueryCallback&& right)
{
MoveFrom(*this, std::move(right));
_isPrepared = right._isPrepared;
ConstructActiveMember(this);
MoveFrom(this, std::move(right));
_callbacks = std::move(right._callbacks);
}
QueryCallbackNew& QueryCallbackNew::operator=(QueryCallbackNew&& right)
QueryCallback& QueryCallback::operator=(QueryCallback&& right)
{
MoveFrom(*this, std::move(right));
_callbacks = std::move(right._callbacks);
if (this != &right)
{
if (_isPrepared != right._isPrepared)
{
DestroyActiveMember(this);
_isPrepared = right._isPrepared;
ConstructActiveMember(this);
}
MoveFrom(this, std::move(right));
_callbacks = std::move(right._callbacks);
}
return *this;
}
QueryCallbackNew::~QueryCallbackNew()
QueryCallback::~QueryCallback()
{
DestroyActiveMember(*this);
DestroyActiveMember(this);
}
QueryCallbackNew&& QueryCallbackNew::WithCallback(std::function<void(QueryResult)>&& callback)
QueryCallback&& QueryCallback::WithCallback(std::function<void(QueryResult)>&& callback)
{
return WithChainingCallback([callback](QueryCallback& /*this*/, QueryResult result) { callback(std::move(result)); });
}
QueryCallback&& QueryCallback::WithPreparedCallback(std::function<void(PreparedQueryResult)>&& callback)
{
return WithChainingPreparedCallback([callback](QueryCallback& /*this*/, PreparedQueryResult result) { callback(std::move(result)); });
}
QueryCallback&& QueryCallback::WithChainingCallback(std::function<void(QueryCallback&, QueryResult)>&& callback)
{
ASSERT(!_callbacks.empty() || !_isPrepared, "Attempted to set callback function for string query on a prepared async query");
_callbacks.emplace(std::move(callback));
return std::move(*this);
}
QueryCallbackNew&& QueryCallbackNew::WithPreparedCallback(std::function<void(PreparedQueryResult)>&& callback)
QueryCallback&& QueryCallback::WithChainingPreparedCallback(std::function<void(QueryCallback&, PreparedQueryResult)>&& callback)
{
ASSERT(!_callbacks.empty() || _isPrepared, "Attempted to set callback function for prepared query on a string async query");
_callbacks.emplace(std::move(callback));
return std::move(*this);
}
QueryCallbackNew::Status QueryCallbackNew::InvokeIfReady()
void QueryCallback::SetNextQuery(QueryCallback&& next)
{
MoveFrom(this, std::move(next));
}
QueryCallback::Status QueryCallback::InvokeIfReady()
{
QueryCallbackData& callback = _callbacks.front();
auto checkStateAndReturnCompletion = [this]()
{
_callbacks.pop();
bool hasNext = !_isPrepared ? _string.valid() : _prepared.valid();
if (_callbacks.empty())
{
ASSERT(!hasNext);
return Completed;
}
// abort chain
if (!hasNext)
return Completed;
ASSERT(_isPrepared == _callbacks.front()._isPrepared);
return NextStep;
};
if (!_isPrepared)
{
if (_string.valid() && _string.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
{
std::function<void(QueryResult)> cb(std::move(callback._string));
cb(_string.get());
_callbacks.pop();
if (_callbacks.empty())
{
ASSERT(!_isPrepared ? !_string.valid() : !_prepared.valid());
return Completed;
}
ASSERT(_isPrepared == _callbacks.front()._isPrepared);
return NextStep;
std::future<QueryResult> f(std::move(_string));
std::function<void(QueryCallback&, QueryResult)> cb(std::move(callback._string));
cb(*this, f.get());
return checkStateAndReturnCompletion();
}
}
else
@@ -134,17 +205,9 @@ QueryCallbackNew::Status QueryCallbackNew::InvokeIfReady()
if (_prepared.valid() && _prepared.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
{
std::future<PreparedQueryResult> f(std::move(_prepared));
std::function<void(PreparedQueryResult)> cb(std::move(callback._prepared));
cb(_prepared.get());
_callbacks.pop();
if (_callbacks.empty())
{
ASSERT(!_isPrepared ? !_string.valid() : !_prepared.valid());
return Completed;
}
ASSERT(_isPrepared == _callbacks.front()._isPrepared);
return NextStep;
std::function<void(QueryCallback&, PreparedQueryResult)> cb(std::move(callback._prepared));
cb(*this, f.get());
return checkStateAndReturnCompletion();
}
}

View File

@@ -18,27 +18,26 @@
#ifndef _QUERY_CALLBACK_H
#define _QUERY_CALLBACK_H
#include <future>
#include "QueryResult.h"
#include <future>
typedef std::future<QueryResult> QueryResultFuture;
typedef std::promise<QueryResult> QueryResultPromise;
typedef std::future<PreparedQueryResult> PreparedQueryResultFuture;
typedef std::promise<PreparedQueryResult> PreparedQueryResultPromise;
#define CALLBACK_STAGE_INVALID uint8(-1)
class TC_DATABASE_API QueryCallbackNew
class TC_DATABASE_API QueryCallback
{
public:
explicit QueryCallbackNew(std::future<QueryResult>&& result);
explicit QueryCallbackNew(std::future<PreparedQueryResult>&& result);
QueryCallbackNew(QueryCallbackNew&& right);
QueryCallbackNew& operator=(QueryCallbackNew&& right);
~QueryCallbackNew();
explicit QueryCallback(std::future<QueryResult>&& result);
explicit QueryCallback(std::future<PreparedQueryResult>&& result);
QueryCallback(QueryCallback&& right);
QueryCallback& operator=(QueryCallback&& right);
~QueryCallback();
QueryCallbackNew&& WithCallback(std::function<void(QueryResult)>&& callback);
QueryCallbackNew&& WithPreparedCallback(std::function<void(PreparedQueryResult)>&& callback);
QueryCallback&& WithCallback(std::function<void(QueryResult)>&& callback);
QueryCallback&& WithPreparedCallback(std::function<void(PreparedQueryResult)>&& callback);
QueryCallback&& WithChainingCallback(std::function<void(QueryCallback&, QueryResult)>&& callback);
QueryCallback&& WithChainingPreparedCallback(std::function<void(QueryCallback&, PreparedQueryResult)>&& callback);
// Moves std::future from next to this object
void SetNextQuery(QueryCallback&& next);
enum Status
{
@@ -50,11 +49,12 @@ public:
Status InvokeIfReady();
private:
QueryCallbackNew(QueryCallbackNew const& right) = delete;
QueryCallbackNew& operator=(QueryCallbackNew const& right) = delete;
QueryCallback(QueryCallback const& right) = delete;
QueryCallback& operator=(QueryCallback const& right) = delete;
template<typename T> friend void MoveFrom(T& to, T&& from);
template<typename T> friend void DestroyActiveMember(T& obj);
template<typename T> friend void ConstructActiveMember(T* obj);
template<typename T> friend void DestroyActiveMember(T* obj);
template<typename T> friend void MoveFrom(T* to, T&& from);
union
{
@@ -67,182 +67,4 @@ private:
std::queue<QueryCallbackData, std::list<QueryCallbackData>> _callbacks;
};
template <typename Result, typename ParamType, bool chain = false>
class QueryCallback
{
public:
QueryCallback() : _param(), _stage(chain ? 0 : CALLBACK_STAGE_INVALID) { }
//! The parameter of this function should be a resultset returned from either .AsyncQuery or .AsyncPQuery
void SetFutureResult(std::future<Result> value)
{
_result = std::move(value);
}
std::future<Result>& GetFutureResult()
{
return _result;
}
bool IsReady()
{
return _result.valid() && _result.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
}
void GetResult(Result& res)
{
res = _result.get();
}
void FreeResult()
{
// Nothing to do here, the constructor of std::future will take care of the cleanup
}
void SetParam(ParamType value)
{
_param = value;
}
ParamType GetParam()
{
return _param;
}
//! Resets the stage of the callback chain
void ResetStage()
{
if (!chain)
return;
_stage = 0;
}
//! Advances the callback chain to the next stage, so upper level code can act on its results accordingly
void NextStage()
{
if (!chain)
return;
++_stage;
}
//! Returns the callback stage (or CALLBACK_STAGE_INVALID if invalid)
uint8 GetStage()
{
return _stage;
}
//! Resets all underlying variables (param, result and stage)
void Reset()
{
SetParam(ParamType());
FreeResult();
ResetStage();
}
private:
std::future<Result> _result;
ParamType _param;
uint8 _stage;
QueryCallback(QueryCallback const& right) = delete;
QueryCallback& operator=(QueryCallback const& right) = delete;
};
template <typename Result, typename ParamType1, typename ParamType2, bool chain = false>
class QueryCallback_2
{
public:
QueryCallback_2() : _stage(chain ? 0 : CALLBACK_STAGE_INVALID) { }
//! The parameter of this function should be a resultset returned from either .AsyncQuery or .AsyncPQuery
void SetFutureResult(std::future<Result> value)
{
_result = std::move(value);
}
std::future<Result>& GetFutureResult()
{
return _result;
}
bool IsReady()
{
return _result.valid() && _result.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
}
void GetResult(Result& res)
{
res = _result.get();
}
void FreeResult()
{
// Nothing to do here, the constructor of std::future will take care of the cleanup
}
void SetFirstParam(ParamType1 value)
{
_param_1 = value;
}
void SetSecondParam(ParamType2 value)
{
_param_2 = value;
}
ParamType1 GetFirstParam()
{
return _param_1;
}
ParamType2 GetSecondParam()
{
return _param_2;
}
//! Resets the stage of the callback chain
void ResetStage()
{
if (!chain)
return;
_stage = 0;
}
//! Advances the callback chain to the next stage, so upper level code can act on its results accordingly
void NextStage()
{
if (!chain)
return;
++_stage;
}
//! Returns the callback stage (or CALLBACK_STAGE_INVALID if invalid)
uint8 GetStage()
{
return _stage;
}
//! Resets all underlying variables (param, result and stage)
void Reset()
{
SetFirstParam(NULL);
SetSecondParam(NULL);
FreeResult();
ResetStage();
}
private:
std::future<Result> _result;
ParamType1 _param_1;
ParamType2 _param_2;
uint8 _stage;
QueryCallback_2(QueryCallback_2 const& right) = delete;
QueryCallback_2& operator=(QueryCallback_2 const& right) = delete;
};
#endif // _QUERY_CALLBACK_H

View File

@@ -27,15 +27,22 @@ QueryCallbackProcessor::~QueryCallbackProcessor()
{
}
void QueryCallbackProcessor::AddQuery(QueryCallbackNew&& query)
void QueryCallbackProcessor::AddQuery(QueryCallback&& query)
{
_callbacks.emplace_back(std::move(query));
}
void QueryCallbackProcessor::ProcessReadyQueries()
{
_callbacks.erase(std::remove_if(_callbacks.begin(), _callbacks.end(), [](QueryCallbackNew& callback)
if (_callbacks.empty())
return;
std::vector<QueryCallback> updateCallbacks{ std::move(_callbacks) };
updateCallbacks.erase(std::remove_if(updateCallbacks.begin(), updateCallbacks.end(), [](QueryCallback& callback)
{
return callback.InvokeIfReady() == QueryCallbackNew::Completed;
}), _callbacks.end());
return callback.InvokeIfReady() == QueryCallback::Completed;
}), updateCallbacks.end());
_callbacks.insert(_callbacks.end(), std::make_move_iterator(updateCallbacks.begin()), std::make_move_iterator(updateCallbacks.end()));
}

View File

@@ -21,7 +21,7 @@
#include "Define.h"
#include <vector>
class QueryCallbackNew;
class QueryCallback;
class TC_DATABASE_API QueryCallbackProcessor
{
@@ -29,14 +29,14 @@ public:
QueryCallbackProcessor();
~QueryCallbackProcessor();
void AddQuery(QueryCallbackNew&& query);
void AddQuery(QueryCallback&& query);
void ProcessReadyQueries();
private:
QueryCallbackProcessor(QueryCallbackProcessor const&) = delete;
QueryCallbackProcessor& operator=(QueryCallbackProcessor const&) = delete;
std::vector<QueryCallbackNew> _callbacks;
std::vector<QueryCallback> _callbacks;
};
#endif // QueryCallbackProcessor_h__

View File

@@ -18,6 +18,7 @@
#include "RBAC.h"
#include "AccountMgr.h"
#include "Log.h"
#include "QueryCallback.h"
namespace rbac
{
@@ -182,7 +183,7 @@ void RBACData::LoadFromDB()
LoadFromDBCallback(LoginDatabase.Query(stmt));
}
PreparedQueryResultFuture RBACData::LoadFromDBAsync()
QueryCallback RBACData::LoadFromDBAsync()
{
ClearData();

View File

@@ -918,7 +918,7 @@ class TC_GAME_API RBACData
/// Loads all permissions assigned to current account
void LoadFromDB();
PreparedQueryResultFuture LoadFromDBAsync();
QueryCallback LoadFromDBAsync();
void LoadFromDBCallback(PreparedQueryResult result);
/// Sets security level

File diff suppressed because it is too large Load Diff

View File

@@ -19,6 +19,7 @@
#include "Common.h"
#include "Language.h"
#include "DatabaseEnv.h"
#include "QueryCallback.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "Opcodes.h"
@@ -469,11 +470,10 @@ void WorldSession::SendStablePet(ObjectGuid guid)
stmt->setUInt8(1, PET_SAVE_FIRST_STABLE_SLOT);
stmt->setUInt8(2, PET_SAVE_LAST_STABLE_SLOT);
_sendStabledPetCallback.SetParam(guid);
_sendStabledPetCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
_queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::SendStablePetCallback, this, guid, std::placeholders::_1)));
}
void WorldSession::SendStablePetCallback(PreparedQueryResult result, ObjectGuid guid)
void WorldSession::SendStablePetCallback(ObjectGuid guid, PreparedQueryResult result)
{
if (!GetPlayer())
return;
@@ -571,7 +571,7 @@ void WorldSession::HandleStablePet(WorldPacket& recvData)
stmt->setUInt8(1, PET_SAVE_FIRST_STABLE_SLOT);
stmt->setUInt8(2, PET_SAVE_LAST_STABLE_SLOT);
_stablePetCallback = CharacterDatabase.AsyncQuery(stmt);
_queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleStablePetCallback, this, std::placeholders::_1)));
}
void WorldSession::HandleStablePetCallback(PreparedQueryResult result)
@@ -633,11 +633,10 @@ void WorldSession::HandleUnstablePet(WorldPacket& recvData)
stmt->setUInt8(2, PET_SAVE_FIRST_STABLE_SLOT);
stmt->setUInt8(3, PET_SAVE_LAST_STABLE_SLOT);
_unstablePetCallback.SetParam(petnumber);
_unstablePetCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
_queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleUnstablePetCallback, this, petnumber, std::placeholders::_1)));
}
void WorldSession::HandleUnstablePetCallback(PreparedQueryResult result, uint32 petId)
void WorldSession::HandleUnstablePetCallback(uint32 petId, PreparedQueryResult result)
{
if (!GetPlayer())
return;
@@ -760,11 +759,10 @@ void WorldSession::HandleStableSwapPet(WorldPacket& recvData)
stmt->setUInt32(0, _player->GetGUID().GetCounter());
stmt->setUInt32(1, petId);
_stableSwapCallback.SetParam(petId);
_stableSwapCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
_queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleStableSwapPetCallback, this, petId, std::placeholders::_1)));
}
void WorldSession::HandleStableSwapPetCallback(PreparedQueryResult result, uint32 petId)
void WorldSession::HandleStableSwapPetCallback(uint32 petId, PreparedQueryResult result)
{
if (!GetPlayer())
return;

View File

@@ -18,6 +18,7 @@
#include "WorldSession.h"
#include "Player.h"
#include "QueryCallback.h"
#include "SocialMgr.h"
#include "ObjectMgr.h"
@@ -42,11 +43,11 @@ void WorldSession::HandleAddFriendOpcode(WorldPacket& recvData)
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_RACE_ACC_BY_NAME);
stmt->setString(0, friendName);
_addFriendCallback.SetParam(friendNote);
_addFriendCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt));
_queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt)
.WithPreparedCallback(std::bind(&WorldSession::HandleAddFriendOpcodeCallback, this, std::move(friendNote), std::placeholders::_1)));
}
void WorldSession::HandleAddFriendOpcodeCallback(PreparedQueryResult result, std::string const& friendNote)
void WorldSession::HandleAddFriendOpcodeCallback(std::string const& friendNote, PreparedQueryResult result)
{
if (!GetPlayer())
return;
@@ -116,7 +117,7 @@ void WorldSession::HandleAddIgnoreOpcode(WorldPacket& recvData)
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_BY_NAME);
stmt->setString(0, ignoreName);
_addIgnoreCallback = CharacterDatabase.AsyncQuery(stmt);
_queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSession::HandleAddIgnoreOpcodeCallback, this, std::placeholders::_1)));
}
void WorldSession::HandleAddIgnoreOpcodeCallback(PreparedQueryResult result)

View File

@@ -24,6 +24,7 @@
#include "Config.h"
#include "Common.h"
#include "DatabaseEnv.h"
#include "QueryCallback.h"
#include "AccountMgr.h"
#include "Log.h"
#include "Opcodes.h"
@@ -137,7 +138,6 @@ WorldSession::WorldSession(uint32 id, std::string&& name, std::shared_ptr<WorldS
LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = %u;", GetAccountId()); // One-time query
}
InitializeQueryCallbackParameters();
}
/// WorldSession destructor
@@ -1085,99 +1085,16 @@ void WorldSession::SetPlayer(Player* player)
m_GUIDLow = _player->GetGUID().GetCounter();
}
void WorldSession::InitializeQueryCallbackParameters()
{
// Callback parameters that have pointers in them should be properly
// initialized to NULL here.
_charCreateCallback.SetParam(NULL);
}
void WorldSession::ProcessQueryCallbacks()
{
PreparedQueryResult result;
_queryProcessor.ProcessReadyQueries();
if (_realmAccountLoginCallback.valid() && _realmAccountLoginCallback.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
InitializeSessionCallback(_realmAccountLoginCallback.get());
//! HandleCharEnumOpcode
if (_charEnumCallback.valid() && _charEnumCallback.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
{
result = _charEnumCallback.get();
HandleCharEnum(result);
}
if (_charCreateCallback.IsReady())
{
_charCreateCallback.GetResult(result);
HandleCharCreateCallback(result, _charCreateCallback.GetParam());
}
//! HandlePlayerLoginOpcode
if (_charLoginCallback.valid() && _charLoginCallback.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
{
SQLQueryHolder* param = _charLoginCallback.get();
HandlePlayerLogin((LoginQueryHolder*)param);
}
//! HandleAddFriendOpcode
if (_addFriendCallback.IsReady())
{
std::string param = _addFriendCallback.GetParam();
_addFriendCallback.GetResult(result);
HandleAddFriendOpcodeCallback(result, param);
_addFriendCallback.FreeResult();
}
//- HandleCharRenameOpcode
if (_charRenameCallback.IsReady())
{
_charRenameCallback.GetResult(result);
CharacterRenameInfo* renameInfo = _charRenameCallback.GetParam();
HandleChangePlayerNameOpcodeCallBack(result, renameInfo);
delete renameInfo;
_charRenameCallback.Reset();
}
//- HandleCharAddIgnoreOpcode
if (_addIgnoreCallback.valid() && _addIgnoreCallback.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
{
result = _addIgnoreCallback.get();
HandleAddIgnoreOpcodeCallback(result);
}
//- SendStabledPet
if (_sendStabledPetCallback.IsReady())
{
ObjectGuid param = _sendStabledPetCallback.GetParam();
_sendStabledPetCallback.GetResult(result);
SendStablePetCallback(result, param);
_sendStabledPetCallback.FreeResult();
}
//- HandleStablePet
if (_stablePetCallback.valid() && _stablePetCallback.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
{
result = _stablePetCallback.get();
HandleStablePetCallback(result);
}
//- HandleUnstablePet
if (_unstablePetCallback.IsReady())
{
uint32 param = _unstablePetCallback.GetParam();
_unstablePetCallback.GetResult(result);
HandleUnstablePetCallback(result, param);
_unstablePetCallback.FreeResult();
}
//- HandleStableSwapPet
if (_stableSwapCallback.IsReady())
{
uint32 param = _stableSwapCallback.GetParam();
_stableSwapCallback.GetResult(result);
HandleStableSwapPetCallback(result, param);
_stableSwapCallback.FreeResult();
}
HandlePlayerLogin(reinterpret_cast<LoginQueryHolder*>(_charLoginCallback.get()));
}
void WorldSession::InitWarden(BigNumber* k, std::string const& os)
@@ -1204,7 +1121,7 @@ void WorldSession::LoadPermissions()
_RBACData->LoadFromDB();
}
PreparedQueryResultFuture WorldSession::LoadPermissionsAsync()
QueryCallback WorldSession::LoadPermissionsAsync()
{
uint32 id = GetAccountId();
uint8 secLevel = GetSecurity();

View File

@@ -239,6 +239,7 @@ struct CharacterFactionChangeInfo : public CharacterCustomizeInfo
protected:
uint8 Race = 0;
bool FactionChange = false;
};
struct PacketCounter
@@ -284,7 +285,7 @@ class TC_GAME_API WorldSession
rbac::RBACData* GetRBACData();
bool HasPermission(uint32 permissionId);
void LoadPermissions();
PreparedQueryResultFuture LoadPermissionsAsync();
QueryCallback LoadPermissionsAsync();
void InvalidateRBACData(); // Used to force LoadPermissions at next HasPermission check
AccountTypes GetSecurity() const { return _security; }
@@ -356,7 +357,7 @@ class TC_GAME_API WorldSession
// Pet
void SendPetNameQuery(ObjectGuid guid, uint32 petnumber);
void SendStablePet(ObjectGuid guid);
void SendStablePetCallback(PreparedQueryResult result, ObjectGuid guid);
void SendStablePetCallback(ObjectGuid guid, PreparedQueryResult result);
void SendStableResult(uint8 guid);
bool CheckStableMaster(ObjectGuid guid);
@@ -449,16 +450,23 @@ class TC_GAME_API WorldSession
void HandleCharEnumOpcode(WorldPacket& recvPacket);
void HandleCharDeleteOpcode(WorldPacket& recvPacket);
void HandleCharCreateOpcode(WorldPacket& recvPacket);
void HandleCharCreateCallback(PreparedQueryResult result, CharacterCreateInfo* createInfo);
void HandlePlayerLoginOpcode(WorldPacket& recvPacket);
void HandleCharEnum(PreparedQueryResult result);
void HandlePlayerLogin(LoginQueryHolder * holder);
void HandlePlayerLogin(LoginQueryHolder* holder);
void HandleCharFactionOrRaceChange(WorldPacket& recvData);
void HandleCharFactionOrRaceChangeCallback(std::shared_ptr<CharacterFactionChangeInfo> factionChangeInfo, PreparedQueryResult result);
void HandleCharRenameOpcode(WorldPacket& recvData);
void HandleCharRenameCallback(std::shared_ptr<CharacterRenameInfo> renameInfo, PreparedQueryResult result);
void HandleSetPlayerDeclinedNames(WorldPacket& recvData);
void HandleAlterAppearance(WorldPacket& recvData);
void HandleCharCustomize(WorldPacket& recvData);
void HandleCharCustomizeCallback(std::shared_ptr<CharacterCustomizeInfo> customizeInfo, PreparedQueryResult result);
void SendCharCreate(ResponseCodes result);
void SendCharDelete(ResponseCodes result);
void SendCharRename(ResponseCodes result, CharacterRenameInfo const& renameInfo);
void SendCharCustomize(ResponseCodes result, CharacterCustomizeInfo const& customizeInfo);
void SendCharFactionChange(ResponseCodes result, CharacterFactionChangeInfo const& factionChangeInfo);
void SendCharRename(ResponseCodes result, CharacterRenameInfo const* renameInfo);
void SendCharCustomize(ResponseCodes result, CharacterCustomizeInfo const* customizeInfo);
void SendCharFactionChange(ResponseCodes result, CharacterFactionChangeInfo const* factionChangeInfo);
void SendSetPlayerDeclinedNamesResult(DeclinedNameResult result, ObjectGuid guid);
void SendBarberShopResult(BarberShopResult result);
@@ -528,7 +536,7 @@ class TC_GAME_API WorldSession
// Social
void HandleContactListOpcode(WorldPacket& recvPacket);
void HandleAddFriendOpcode(WorldPacket& recvPacket);
void HandleAddFriendOpcodeCallback(PreparedQueryResult result, std::string const& friendNote);
void HandleAddFriendOpcodeCallback(std::string const& friendNote, PreparedQueryResult result);
void HandleDelFriendOpcode(WorldPacket& recvPacket);
void HandleAddIgnoreOpcode(WorldPacket& recvPacket);
void HandleAddIgnoreOpcodeCallback(PreparedQueryResult result);
@@ -651,11 +659,11 @@ class TC_GAME_API WorldSession
void HandleStablePet(WorldPacket& recvPacket);
void HandleStablePetCallback(PreparedQueryResult result);
void HandleUnstablePet(WorldPacket& recvPacket);
void HandleUnstablePetCallback(PreparedQueryResult result, uint32 petId);
void HandleUnstablePetCallback(uint32 petId, PreparedQueryResult result);
void HandleBuyStableSlot(WorldPacket& recvPacket);
void HandleStableRevivePet(WorldPacket& recvPacket);
void HandleStableSwapPet(WorldPacket& recvPacket);
void HandleStableSwapPetCallback(PreparedQueryResult result, uint32 petId);
void HandleStableSwapPetCallback(uint32 petId, PreparedQueryResult result);
void HandleDuelAcceptedOpcode(WorldPacket& recvPacket);
void HandleDuelCancelledOpcode(WorldPacket& recvPacket);
@@ -805,10 +813,6 @@ class TC_GAME_API WorldSession
void HandleSetActionBarToggles(WorldPacket& recvData);
void HandleCharRenameOpcode(WorldPacket& recvData);
void HandleChangePlayerNameOpcodeCallBack(PreparedQueryResult result, CharacterRenameInfo const* renameInfo);
void HandleSetPlayerDeclinedNames(WorldPacket& recvData);
void HandleTotemDestroyed(WorldPacket& recvData);
void HandleDismissCritter(WorldPacket& recvData);
@@ -952,9 +956,7 @@ class TC_GAME_API WorldSession
void HandleSpellClick(WorldPacket& recvData);
void HandleMirrorImageDataRequest(WorldPacket& recvData);
void HandleAlterAppearance(WorldPacket& recvData);
void HandleRemoveGlyph(WorldPacket& recvData);
void HandleCharCustomize(WorldPacket& recvData);
void HandleQueryInspectAchievements(WorldPacket& recvData);
void HandleEquipmentSetSave(WorldPacket& recvData);
void HandleEquipmentSetDelete(WorldPacket& recvData);
@@ -969,21 +971,13 @@ class TC_GAME_API WorldSession
void HandleUpdateMissileTrajectory(WorldPacket& recvPacket);
private:
void InitializeQueryCallbackParameters();
void ProcessQueryCallbacks();
QueryResultHolderFuture _realmAccountLoginCallback;
PreparedQueryResultFuture _charEnumCallback;
PreparedQueryResultFuture _addIgnoreCallback;
PreparedQueryResultFuture _stablePetCallback;
QueryCallback<PreparedQueryResult, CharacterRenameInfo*> _charRenameCallback;
QueryCallback<PreparedQueryResult, std::string> _addFriendCallback;
QueryCallback<PreparedQueryResult, uint32> _unstablePetCallback;
QueryCallback<PreparedQueryResult, uint32> _stableSwapCallback;
QueryCallback<PreparedQueryResult, ObjectGuid> _sendStabledPetCallback;
QueryCallback<PreparedQueryResult, CharacterCreateInfo*, true> _charCreateCallback;
QueryResultHolderFuture _charLoginCallback;
QueryCallbackProcessor _queryProcessor;
friend class World;
protected:
class DosProtection

View File

@@ -19,6 +19,7 @@
#include "WorldSocket.h"
#include "BigNumber.h"
#include "Opcodes.h"
#include "QueryCallback.h"
#include "ScriptMgr.h"
#include "SHA1.h"
#include "PacketLog.h"
@@ -51,8 +52,7 @@ void WorldSocket::Start()
stmt->setString(0, ip_address);
stmt->setUInt32(1, inet_addr(ip_address.c_str()));
_queryCallback = std::bind(&WorldSocket::CheckIpCallback, this, std::placeholders::_1);
_queryFuture = LoginDatabase.AsyncQuery(stmt);
_queryProcessor.AddQuery(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSocket::CheckIpCallback, this, std::placeholders::_1)));
}
void WorldSocket::CheckIpCallback(PreparedQueryResult result)
@@ -125,12 +125,7 @@ bool WorldSocket::Update()
if (!BaseSocket::Update())
return false;
if (_queryFuture.valid() && _queryFuture.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
{
auto callback = _queryCallback;
_queryCallback = nullptr;
callback(_queryFuture.get());
}
_queryProcessor.ProcessReadyQueries();
return true;
}
@@ -444,8 +439,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
stmt->setInt32(0, int32(realm.Id.Realm));
stmt->setString(1, authSession->Account);
_queryCallback = std::bind(&WorldSocket::HandleAuthSessionCallback, this, authSession, std::placeholders::_1);
_queryFuture = LoginDatabase.AsyncQuery(stmt);
_queryProcessor.AddQuery(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSocket::HandleAuthSessionCallback, this, authSession, std::placeholders::_1)));
}
void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<AuthSession> authSession, PreparedQueryResult result)
@@ -603,8 +597,7 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<AuthSession> authSes
if (wardenActive)
_worldSession->InitWarden(&account.SessionKey, account.OS);
_queryCallback = std::bind(&WorldSocket::LoadSessionPermissionsCallback, this, std::placeholders::_1);
_queryFuture = _worldSession->LoadPermissionsAsync();
_queryProcessor.AddQuery(_worldSession->LoadPermissionsAsync().WithPreparedCallback(std::bind(&WorldSocket::LoadSessionPermissionsCallback, this, std::placeholders::_1)));
AsyncRead();
}

View File

@@ -111,8 +111,7 @@ private:
MessageBuffer _packetBuffer;
MPSCQueue<EncryptablePacket> _bufferQueue;
PreparedQueryResultFuture _queryFuture;
std::function<void(PreparedQueryResult&&)> _queryCallback;
QueryCallbackProcessor _queryProcessor;
std::string _ipCountry;
};

View File

@@ -39,6 +39,7 @@
#include "DisableMgr.h"
#include "GameEventMgr.h"
#include "GameObjectModel.h"
#include "GitRevision.h"
#include "GridNotifiersImpl.h"
#include "GroupMgr.h"
#include "GuildMgr.h"
@@ -52,7 +53,7 @@
#include "OutdoorPvPMgr.h"
#include "Player.h"
#include "PoolMgr.h"
#include "GitRevision.h"
#include "QueryCallback.h"
#include "ScriptMgr.h"
#include "ScriptReloadMgr.h"
#include "SkillDiscovery.h"
@@ -2909,7 +2910,7 @@ void World::UpdateRealmCharCount(uint32 accountId)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_COUNT);
stmt->setUInt32(0, accountId);
m_realmCharCallbacks.push_back(CharacterDatabase.AsyncQuery(stmt));
_queryProcessor.AddQuery(CharacterDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&World::_UpdateRealmCharCount, this, std::placeholders::_1)));
}
void World::_UpdateRealmCharCount(PreparedQueryResult resultCharCount)
@@ -3271,20 +3272,7 @@ uint64 World::getWorldState(uint32 index) const
void World::ProcessQueryCallbacks()
{
PreparedQueryResult result;
for (std::deque<std::future<PreparedQueryResult>>::iterator itr = m_realmCharCallbacks.begin(); itr != m_realmCharCallbacks.end(); )
{
if ((*itr).wait_for(std::chrono::seconds(0)) != std::future_status::ready)
{
++itr;
continue;
}
result = (*itr).get();
_UpdateRealmCharCount(result);
itr = m_realmCharCallbacks.erase(itr);
}
_queryProcessor.ProcessReadyQueries();
}
CharacterInfo const* World::GetCharacterInfo(ObjectGuid const& guid) const

View File

@@ -28,7 +28,7 @@
#include "Timer.h"
#include "SharedDefines.h"
#include "QueryResult.h"
#include "QueryCallback.h"
#include "QueryCallbackProcessor.h"
#include "Realm/Realm.h"
#include <atomic>
@@ -882,7 +882,7 @@ class TC_GAME_API World
void LoadCharacterInfoStore();
void ProcessQueryCallbacks();
std::deque<std::future<PreparedQueryResult>> m_realmCharCallbacks;
QueryCallbackProcessor _queryProcessor;
};
TC_GAME_API extern Realm realm;