solocraft + dynamicxp
This commit is contained in:
16
src/CMakeLists.txt
Normal file
16
src/CMakeLists.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
# Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
#
|
||||
# This file is free software; as a special exception the author gives
|
||||
# unlimited permission to copy and/or distribute it, with or without
|
||||
# modifications, as long as this notice is preserved.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
add_subdirectory(genrev)
|
||||
add_subdirectory(common)
|
||||
add_subdirectory(server)
|
||||
if(TOOLS)
|
||||
add_subdirectory(tools)
|
||||
endif()
|
||||
89
src/common/CMakeLists.txt
Normal file
89
src/common/CMakeLists.txt
Normal file
@@ -0,0 +1,89 @@
|
||||
# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
|
||||
#
|
||||
# This file is free software; as a special exception the author gives
|
||||
# unlimited permission to copy and/or distribute it, with or without
|
||||
# modifications, as long as this notice is preserved.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
CollectSourceFiles(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
PRIVATE_SOURCES
|
||||
# Exclude
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Debugging
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Platform
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders)
|
||||
|
||||
# Manually set sources for Debugging directory as we don't want to include WheatyExceptionReport in common project
|
||||
# It needs to be included both in authserver and worldserver for the static global variable to be properly initialized
|
||||
# and to handle crash logs on windows
|
||||
list(APPEND PRIVATE_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Debugging/Errors.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Debugging/Errors.h)
|
||||
|
||||
if (USE_COREPCH)
|
||||
set(PRIVATE_PCH_HEADER PrecompiledHeaders/commonPCH.h)
|
||||
set(PRIVATE_PCH_SOURCE PrecompiledHeaders/commonPCH.cpp)
|
||||
if (MSVC)
|
||||
list(INSERT PRIVATE_SOURCES 0 PrecompiledHeaders/commonPCH.cpp)
|
||||
endif (MSVC)
|
||||
endif (USE_COREPCH)
|
||||
|
||||
GroupSources(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
add_library(common
|
||||
${PRIVATE_SOURCES}
|
||||
)
|
||||
|
||||
# Do NOT add any extra include directory here, as we don't want the common
|
||||
# library to depend on anything else than TC deps, and itself.
|
||||
# This way we ensure that if either a PR does that without modifying this file,
|
||||
# a compile error will be generated, either this file will be modified so it
|
||||
# is detected more easily.
|
||||
# While it is OK to include files from other libs as long as they don't require
|
||||
# linkage (enums, defines...) it is discouraged to do so unless necessary, as it will pullute
|
||||
# include_directories leading to further unnoticed dependency aditions
|
||||
# Linker Depencency requirements: none
|
||||
CollectIncludeDirectories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
PUBLIC_INCLUDES
|
||||
# Exclude
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders)
|
||||
|
||||
target_include_directories(common
|
||||
PUBLIC
|
||||
# Provide the binary dir for all child targets
|
||||
${CMAKE_BINARY_DIR}
|
||||
${PUBLIC_INCLUDES}
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
target_link_libraries(common
|
||||
PRIVATE
|
||||
process
|
||||
PUBLIC
|
||||
mysql
|
||||
cds
|
||||
boost
|
||||
fmt
|
||||
g3dlib
|
||||
Detour
|
||||
sfmt
|
||||
utf8cpp
|
||||
openssl
|
||||
threads
|
||||
)
|
||||
|
||||
add_dependencies(common revision_data.h)
|
||||
|
||||
set_target_properties(common
|
||||
PROPERTIES
|
||||
FOLDER
|
||||
"server")
|
||||
|
||||
# Generate precompiled header
|
||||
if (USE_COREPCH)
|
||||
add_cxx_pch(common ${PRIVATE_PCH_HEADER} ${PRIVATE_PCH_SOURCE})
|
||||
endif ()
|
||||
68
src/common/Common.cpp
Normal file
68
src/common/Common.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
char const* localeNames[MAX_LOCALES] =
|
||||
{
|
||||
"enUS",
|
||||
"koKR",
|
||||
"frFR",
|
||||
"deDE",
|
||||
"zhCN",
|
||||
"zhTW",
|
||||
"esES",
|
||||
"esMX",
|
||||
"ruRU",
|
||||
"none",
|
||||
"ptBR",
|
||||
"itIT"
|
||||
};
|
||||
|
||||
LocaleConstant GetLocaleByName(const std::string& name)
|
||||
{
|
||||
for (uint8 i = 0; i < MAX_LOCALES; ++i)
|
||||
if (name == localeNames[i])
|
||||
return LocaleConstant(i);
|
||||
|
||||
return LOCALE_enUS; // including enGB case
|
||||
}
|
||||
|
||||
LocalizedString::LocalizedString()
|
||||
{
|
||||
for (uint32 i = 0; i < TOTAL_LOCALES; i++)
|
||||
Str[i] = "";
|
||||
}
|
||||
|
||||
LocalizedString::LocalizedString(char const* val)
|
||||
{
|
||||
for (uint32 i = 0; i < TOTAL_LOCALES; i++)
|
||||
Str[i] = val;
|
||||
}
|
||||
|
||||
char const* LocalizedString::Get(uint32 locale) const
|
||||
{
|
||||
if ((Str[locale] == nullptr || strlen(Str[locale]) == 0) && Str[LOCALE_enUS] != nullptr)
|
||||
return Str[LOCALE_enUS];
|
||||
|
||||
if (Str[locale] == nullptr)
|
||||
return "";
|
||||
|
||||
return Str[locale];
|
||||
}
|
||||
|
||||
233
src/common/Common.h
Normal file
233
src/common/Common.h
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#include "Define.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if PLATFORM == TC_PLATFORM_WINDOWS
|
||||
#define STRCASECMP stricmp
|
||||
#else
|
||||
#define STRCASECMP strcasecmp
|
||||
#endif
|
||||
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <queue>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/utility/in_place_factory.hpp>
|
||||
#include <boost/algorithm/clamp.hpp>
|
||||
#include "Debugging/Errors.h"
|
||||
|
||||
#if PLATFORM == TC_PLATFORM_WINDOWS
|
||||
# include <ws2tcpip.h>
|
||||
|
||||
# if defined(__INTEL_COMPILER)
|
||||
# if !defined(BOOST_ASIO_HAS_MOVE)
|
||||
# define BOOST_ASIO_HAS_MOVE
|
||||
# endif // !defined(BOOST_ASIO_HAS_MOVE)
|
||||
# endif // if defined(__INTEL_COMPILER)
|
||||
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
# include <sys/ioctl.h>
|
||||
# include <sys/socket.h>
|
||||
# include <netinet/in.h>
|
||||
# include <unistd.h>
|
||||
# include <netdb.h>
|
||||
#endif
|
||||
|
||||
#if COMPILER == COMPILER_MICROSOFT
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#define I32FMT "%08I32X"
|
||||
#define I64FMT "%016I64X"
|
||||
#define snprintf _snprintf
|
||||
#define atoll _atoi64
|
||||
#define vsnprintf _vsnprintf
|
||||
#define finite(X) _finite(X)
|
||||
#define llabs _abs64
|
||||
|
||||
#else
|
||||
|
||||
#define stricmp strcasecmp
|
||||
#define strnicmp strncasecmp
|
||||
#define I32FMT "%08X"
|
||||
#define I64FMT "%016llX"
|
||||
|
||||
#endif
|
||||
|
||||
inline float finiteAlways(float f) { return finite(f) ? f : 0.0f; }
|
||||
|
||||
inline unsigned long atoul(char const* str) { return strtoul(str, nullptr, 10); }
|
||||
inline unsigned long long atoull(char const* str) { return strtoull(str, nullptr, 10); }
|
||||
|
||||
#define STRINGIZE(a) #a
|
||||
|
||||
enum TimeConstants
|
||||
{
|
||||
ONE_SECOND = 1,
|
||||
THREE_SECONDS = 3,
|
||||
FIVE_SECONDS = 5,
|
||||
HALF_MINUTE = 30,
|
||||
MINUTE = 60,
|
||||
HOUR = MINUTE*60,
|
||||
DAY = HOUR*24,
|
||||
WEEK = DAY*7,
|
||||
MONTH = DAY*30,
|
||||
YEAR = MONTH*12,
|
||||
IN_MILLISECONDS = 1000
|
||||
};
|
||||
|
||||
enum AccountTypes : uint8
|
||||
{
|
||||
SEC_PLAYER = 0,
|
||||
SEC_MODERATOR = 1,
|
||||
SEC_GAMEMASTER = 2,
|
||||
SEC_CONFIRMED_GAMEMASTER = 3,
|
||||
SEC_REALM_LEADER = 4,
|
||||
SEC_GM_LEADER = 5,
|
||||
SEC_ADMINISTRATOR = 6,
|
||||
SEC_CONSOLE = 7 // must be always last in list, accounts must have less security level always also
|
||||
};
|
||||
|
||||
enum LocaleConstant
|
||||
{
|
||||
LOCALE_enUS = 0,
|
||||
LOCALE_koKR = 1,
|
||||
LOCALE_frFR = 2,
|
||||
LOCALE_deDE = 3,
|
||||
LOCALE_zhCN = 4,
|
||||
LOCALE_zhTW = 5,
|
||||
LOCALE_esES = 6,
|
||||
LOCALE_esMX = 7,
|
||||
LOCALE_ruRU = 8,
|
||||
LOCALE_none = 9,
|
||||
LOCALE_ptBR = 10,
|
||||
LOCALE_itIT = 11,
|
||||
|
||||
MAX_LOCALES
|
||||
};
|
||||
|
||||
const uint8 TOTAL_LOCALES = 11;
|
||||
const LocaleConstant DEFAULT_LOCALE = LOCALE_enUS;
|
||||
|
||||
const uint8 MAX_ACCOUNT_TUTORIAL_VALUES = 8;
|
||||
|
||||
extern char const* localeNames[MAX_LOCALES];
|
||||
|
||||
LocaleConstant GetLocaleByName(const std::string& name);
|
||||
|
||||
typedef std::vector<std::string> StringVector;
|
||||
typedef std::set<std::string> StringSet;
|
||||
typedef std::unordered_set<std::string> StringUnorderedSet;
|
||||
|
||||
struct LocalizedString
|
||||
{
|
||||
char const* Str[MAX_LOCALES];
|
||||
|
||||
LocalizedString();
|
||||
explicit LocalizedString(char const* val);
|
||||
char const* Get(uint32 locale) const;
|
||||
};
|
||||
|
||||
// we always use stdlibc++ std::max/std::min, undefine some not C++ standard defines (Win API and some other platforms)
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846f
|
||||
#endif
|
||||
|
||||
#ifndef M_PI_F
|
||||
# define M_PI_F float(M_PI)
|
||||
#endif
|
||||
|
||||
#ifndef M_RAD
|
||||
#define M_RAD 57.295779513082320876846364344191f
|
||||
#endif
|
||||
|
||||
static uint32 constexpr MAX_QUERY_LEN = 32 * 1024;
|
||||
|
||||
//! Optional helper class to wrap optional values within.
|
||||
template <typename T>
|
||||
using Optional = boost::optional<T>;
|
||||
|
||||
namespace Trinity
|
||||
{
|
||||
// using std::make_unique;
|
||||
//! std::make_unique implementation (TODO: remove this once C++14 is supported)
|
||||
// Overload for non-array types. Arguments are forwarded to T's constructor.
|
||||
|
||||
template <class T>
|
||||
struct _Unique_if {
|
||||
typedef std::unique_ptr<T> _Single_object;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct _Unique_if<T[]> {
|
||||
typedef std::unique_ptr<T[]> _Unknown_bound;
|
||||
};
|
||||
|
||||
template <class T, size_t N>
|
||||
struct _Unique_if<T[N]> {
|
||||
typedef void _Known_bound;
|
||||
};
|
||||
|
||||
template <class T, class... Args>
|
||||
typename _Unique_if<T>::_Single_object make_unique(Args&&... args) {
|
||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename _Unique_if<T>::_Unknown_bound make_unique(size_t n) {
|
||||
typedef typename std::remove_extent<T>::type U;
|
||||
return std::unique_ptr<T>(new U[n]());
|
||||
}
|
||||
|
||||
template <class T, class... Args>
|
||||
typename _Unique_if<T>::_Known_bound make_unique(Args&&...) = delete;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
71
src/common/CompilerDefs.h
Normal file
71
src/common/CompilerDefs.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TRINITY_COMPILERDEFS_H
|
||||
#define TRINITY_COMPILERDEFS_H
|
||||
|
||||
#define TC_PLATFORM_WINDOWS 0
|
||||
#define TC_PLATFORM_UNIX 1
|
||||
#define TC_PLATFORM_APPLE 2
|
||||
#define TC_PLATFORM_INTEL 3
|
||||
|
||||
// must be first (win 64 also define _WIN32)
|
||||
#if defined( _WIN64 )
|
||||
# define PLATFORM TC_PLATFORM_WINDOWS
|
||||
#elif defined( __WIN32__ ) || defined( WIN32 ) || defined( _WIN32 )
|
||||
# define PLATFORM TC_PLATFORM_WINDOWS
|
||||
#elif defined( __APPLE_CC__ )
|
||||
# define PLATFORM TC_PLATFORM_APPLE
|
||||
#elif defined( __INTEL_COMPILER )
|
||||
# define PLATFORM TC_PLATFORM_INTEL
|
||||
#else
|
||||
# define PLATFORM TC_PLATFORM_UNIX
|
||||
#endif
|
||||
|
||||
#define COMPILER_MICROSOFT 0
|
||||
#define COMPILER_GNU 1
|
||||
#define COMPILER_BORLAND 2
|
||||
#define COMPILER_INTEL 3
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define COMPILER COMPILER_MICROSOFT
|
||||
#elif defined( __BORLANDC__ )
|
||||
# define COMPILER COMPILER_BORLAND
|
||||
#elif defined( __INTEL_COMPILER )
|
||||
# define COMPILER COMPILER_INTEL
|
||||
#elif defined( __GNUC__ )
|
||||
# define COMPILER COMPILER_GNU
|
||||
# define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
||||
#else
|
||||
# error "FATAL ERROR: Unknown compiler."
|
||||
#endif
|
||||
|
||||
#if COMPILER == COMPILER_MICROSOFT
|
||||
# pragma warning( disable : 4267 ) // conversion from 'size_t' to 'int', possible loss of data
|
||||
# pragma warning( disable : 4786 ) // identifier was truncated to '255' characters in the debug information
|
||||
# pragma warning( disable : 4800 )
|
||||
# pragma warning( disable : 4477 )
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus) && __cplusplus == 201103L
|
||||
# define COMPILER_HAS_CPP11_SUPPORT 1
|
||||
#else
|
||||
# define COMPILER_HAS_CPP11_SUPPORT 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
125
src/common/Configuration/Config.cpp
Normal file
125
src/common/Configuration/Config.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/ini_parser.hpp>
|
||||
#include "Config.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
boost::property_tree::ptree _config;
|
||||
std::string _filename;
|
||||
std::mutex _configLock;
|
||||
}
|
||||
|
||||
namespace bpt = boost::property_tree;
|
||||
|
||||
bool ConfigMgr::LoadInitial(std::string const& file, std::string& error)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_configLock);
|
||||
|
||||
_filename = file;
|
||||
|
||||
try
|
||||
{
|
||||
bpt::ptree fullTree;
|
||||
read_ini(file, fullTree);
|
||||
|
||||
if (fullTree.empty())
|
||||
{
|
||||
error = "empty file (" + file + ")";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Since we're using only one section per config file, we skip the section and have direct property access
|
||||
_config = fullTree.begin()->second;
|
||||
}
|
||||
catch (bpt::ini_parser::ini_parser_error const& e)
|
||||
{
|
||||
if (e.line() == 0)
|
||||
error = e.message() + " (" + e.filename() + ")";
|
||||
else
|
||||
error = e.message() + " (" + e.filename() + ":" + std::to_string(e.line()) + ")";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ConfigMgr* ConfigMgr::instance()
|
||||
{
|
||||
static ConfigMgr instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
bool ConfigMgr::Reload(std::string& error)
|
||||
{
|
||||
return LoadInitial(_filename, error);
|
||||
}
|
||||
|
||||
std::string ConfigMgr::GetStringDefault(std::string const& name, const std::string& def)
|
||||
{
|
||||
auto value = _config.get<std::string>(bpt::ptree::path_type(name, '/'), def);
|
||||
value.erase(std::remove(value.begin(), value.end(), '"'), value.end());
|
||||
return value;
|
||||
}
|
||||
|
||||
bool ConfigMgr::GetBoolDefault(std::string const& name, bool def)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto val = _config.get<std::string>(bpt::ptree::path_type(name, '/'));
|
||||
val.erase(std::remove(val.begin(), val.end(), '"'), val.end());
|
||||
return (val == "true" || val == "TRUE" || val == "yes" || val == "YES" || val == "1");
|
||||
}
|
||||
catch (std::exception const& /*ex*/)
|
||||
{
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
int ConfigMgr::GetIntDefault(std::string const& name, int def)
|
||||
{
|
||||
return _config.get<int>(bpt::ptree::path_type(name, '/'), def);
|
||||
}
|
||||
|
||||
float ConfigMgr::GetFloatDefault(std::string const& name, float def)
|
||||
{
|
||||
return _config.get<float>(bpt::ptree::path_type(name, '/'), def);
|
||||
}
|
||||
|
||||
std::string const& ConfigMgr::GetFilename()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_configLock);
|
||||
return _filename;
|
||||
}
|
||||
|
||||
std::vector<std::string> ConfigMgr::GetKeysByString(std::string const& name)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_configLock);
|
||||
|
||||
std::vector<std::string> keys;
|
||||
for (const auto& child : _config)
|
||||
if (child.first.compare(0, name.length(), name) == 0)
|
||||
keys.push_back(child.first);
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
52
src/common/Configuration/Config.h
Normal file
52
src/common/Configuration/Config.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#include "Define.h"
|
||||
#include <vector>
|
||||
|
||||
class ConfigMgr
|
||||
{
|
||||
ConfigMgr() = default;
|
||||
~ConfigMgr() = default;
|
||||
|
||||
public:
|
||||
|
||||
ConfigMgr(ConfigMgr const&) = delete;
|
||||
ConfigMgr& operator=(ConfigMgr const&) = delete;
|
||||
|
||||
bool LoadInitial(std::string const& file, std::string& error);
|
||||
|
||||
static ConfigMgr* instance();
|
||||
|
||||
bool Reload(std::string& error);
|
||||
|
||||
std::string GetStringDefault(std::string const& name, const std::string& def);
|
||||
bool GetBoolDefault(std::string const& name, bool def);
|
||||
int GetIntDefault(std::string const& name, int def);
|
||||
float GetFloatDefault(std::string const& name, float def);
|
||||
|
||||
std::string const& GetFilename();
|
||||
std::vector<std::string> GetKeysByString(std::string const& name);
|
||||
};
|
||||
|
||||
#define sConfigMgr ConfigMgr::instance()
|
||||
|
||||
#endif
|
||||
83
src/common/Cryptography/ARC4.cpp
Normal file
83
src/common/Cryptography/ARC4.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ARC4.h"
|
||||
|
||||
ARC4::ARC4(uint32 len) : m_ctx(EVP_CIPHER_CTX_new())
|
||||
{
|
||||
EVP_CIPHER_CTX_init(m_ctx);
|
||||
EVP_EncryptInit_ex(m_ctx, EVP_rc4(), nullptr, nullptr, nullptr);
|
||||
EVP_CIPHER_CTX_set_key_length(m_ctx, len);
|
||||
}
|
||||
|
||||
ARC4::ARC4(uint8* seed, uint32 len) : m_ctx(EVP_CIPHER_CTX_new())
|
||||
{
|
||||
EVP_CIPHER_CTX_init(m_ctx);
|
||||
EVP_EncryptInit_ex(m_ctx, EVP_rc4(), nullptr, nullptr, nullptr);
|
||||
EVP_CIPHER_CTX_set_key_length(m_ctx, len);
|
||||
EVP_EncryptInit_ex(m_ctx, nullptr, nullptr, seed, nullptr);
|
||||
}
|
||||
|
||||
ARC4::~ARC4()
|
||||
{
|
||||
EVP_CIPHER_CTX_free(m_ctx);
|
||||
}
|
||||
|
||||
void ARC4::Init(uint8* seed)
|
||||
{
|
||||
EVP_EncryptInit_ex(m_ctx, nullptr, nullptr, seed, nullptr);
|
||||
}
|
||||
|
||||
void ARC4::UpdateData(int len, uint8* data)
|
||||
{
|
||||
int outlen = 0;
|
||||
EVP_EncryptUpdate(m_ctx, data, &outlen, data, len);
|
||||
EVP_EncryptFinal_ex(m_ctx, data, &outlen);
|
||||
}
|
||||
|
||||
void ARC4::rc4_init(RC4_Context * ctx, const uint8 * seed, int seedlen)
|
||||
{
|
||||
for (int i = 0; i < 256; ++i)
|
||||
ctx->S[i] = i;
|
||||
|
||||
ctx->x = 0;
|
||||
ctx->y = 0;
|
||||
|
||||
int j = 0;
|
||||
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
j = (j + ctx->S[i] + seed[i % seedlen]) % 256;
|
||||
std::swap(ctx->S[i], ctx->S[j]);
|
||||
}
|
||||
}
|
||||
|
||||
void ARC4::rc4_process(RC4_Context * ctx, uint8 * data, int datalen)
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
for (i = 0; i < datalen; ++i)
|
||||
{
|
||||
ctx->x = (ctx->x + 1) % 256;
|
||||
ctx->y = (ctx->y + ctx->S[ctx->x]) % 256;
|
||||
std::swap(ctx->S[ctx->x], ctx->S[ctx->y]);
|
||||
j = (ctx->S[ctx->x] + ctx->S[ctx->y]) % 256;
|
||||
data[i] ^= ctx->S[j];
|
||||
}
|
||||
}
|
||||
47
src/common/Cryptography/ARC4.h
Normal file
47
src/common/Cryptography/ARC4.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _AUTH_SARC4_H
|
||||
#define _AUTH_SARC4_H
|
||||
|
||||
#include "Define.h"
|
||||
#include <openssl/evp.h>
|
||||
|
||||
struct RC4_Context
|
||||
{
|
||||
uint8 S[256] = {};
|
||||
uint8 x = 0;
|
||||
uint8 y = 0;
|
||||
};
|
||||
|
||||
class ARC4
|
||||
{
|
||||
public:
|
||||
ARC4(uint32 len);
|
||||
ARC4(uint8* seed, uint32 len);
|
||||
~ARC4();
|
||||
void Init(uint8* seed);
|
||||
void UpdateData(int len, uint8* data);
|
||||
|
||||
static void rc4_init(RC4_Context * ctx, const uint8 * seed, int seedlen);
|
||||
static void rc4_process(RC4_Context * ctx, uint8 * data, int datalen);
|
||||
private:
|
||||
EVP_CIPHER_CTX* m_ctx;
|
||||
};
|
||||
|
||||
#endif
|
||||
39
src/common/Cryptography/Authentication/PacketCrypt.cpp
Normal file
39
src/common/Cryptography/Authentication/PacketCrypt.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PacketCrypt.h"
|
||||
|
||||
PacketCrypt::PacketCrypt(uint32 rc4InitSize)
|
||||
: _clientDecrypt(rc4InitSize), _serverEncrypt(rc4InitSize), _initialized(false)
|
||||
{
|
||||
}
|
||||
|
||||
void PacketCrypt::DecryptRecv(uint8* data, size_t len)
|
||||
{
|
||||
if (!_initialized)
|
||||
return;
|
||||
|
||||
_clientDecrypt.UpdateData(len, data);
|
||||
}
|
||||
|
||||
void PacketCrypt::EncryptSend(uint8* data, size_t len)
|
||||
{
|
||||
if (!_initialized)
|
||||
return;
|
||||
|
||||
_serverEncrypt.UpdateData(len, data);
|
||||
}
|
||||
43
src/common/Cryptography/Authentication/PacketCrypt.h
Normal file
43
src/common/Cryptography/Authentication/PacketCrypt.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _PACKETCRYPT_H
|
||||
#define _PACKETCRYPT_H
|
||||
|
||||
#include "Cryptography/ARC4.h"
|
||||
|
||||
class BigNumber;
|
||||
|
||||
class PacketCrypt
|
||||
{
|
||||
public:
|
||||
PacketCrypt(uint32 rc4InitSize);
|
||||
virtual ~PacketCrypt() { }
|
||||
|
||||
virtual void Init(BigNumber* K) = 0;
|
||||
void DecryptRecv(uint8* data, size_t length);
|
||||
void EncryptSend(uint8* data, size_t length);
|
||||
|
||||
bool IsInitialized() const { return _initialized; }
|
||||
|
||||
protected:
|
||||
ARC4 _clientDecrypt;
|
||||
ARC4 _serverEncrypt;
|
||||
bool _initialized;
|
||||
};
|
||||
|
||||
#endif // _PACKETCRYPT_H
|
||||
58
src/common/Cryptography/Authentication/WorldPacketCrypt.cpp
Normal file
58
src/common/Cryptography/Authentication/WorldPacketCrypt.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "WorldPacketCrypt.h"
|
||||
#include "Cryptography/HmacHash.h"
|
||||
#include "Cryptography/BigNumber.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
WorldPacketCrypt::WorldPacketCrypt() : PacketCrypt(SHA_DIGEST_LENGTH)
|
||||
{
|
||||
}
|
||||
|
||||
void WorldPacketCrypt::Init(BigNumber* K)
|
||||
{
|
||||
uint8 ServerEncryptionKey[SEED_KEY_SIZE] = { 0x08, 0xF1, 0x95, 0x9F, 0x47, 0xE5, 0xD2, 0xDB, 0xA1, 0x3D, 0x77, 0x8F, 0x3F, 0x3E, 0xE7, 0x00 };
|
||||
uint8 ServerDecryptionKey[SEED_KEY_SIZE] = { 0x40, 0xAA, 0xD3, 0x92, 0x26, 0x71, 0x43, 0x47, 0x3A, 0x31, 0x08, 0xA6, 0xE7, 0xDC, 0x98, 0x2A };
|
||||
Init(K, ServerEncryptionKey, ServerDecryptionKey);
|
||||
}
|
||||
|
||||
void WorldPacketCrypt::Init(BigNumber* k, uint8 const* serverKey, uint8 const* clientKey)
|
||||
{
|
||||
HmacSha1 serverEncryptHmac(SEED_KEY_SIZE, (uint8*)serverKey);
|
||||
uint8 *encryptHash = serverEncryptHmac.ComputeHash(k);
|
||||
|
||||
HmacSha1 clientDecryptHmac(SEED_KEY_SIZE, (uint8*)clientKey);
|
||||
uint8 *decryptHash = clientDecryptHmac.ComputeHash(k);
|
||||
|
||||
_clientDecrypt.Init(decryptHash);
|
||||
_serverEncrypt.Init(encryptHash);
|
||||
|
||||
// Drop first 1024 bytes, as WoW uses ARC4-drop1024.
|
||||
uint8 syncBuf[1024];
|
||||
memset(syncBuf, 0, 1024);
|
||||
|
||||
_serverEncrypt.UpdateData(1024, syncBuf);
|
||||
|
||||
memset(syncBuf, 0, 1024);
|
||||
|
||||
_clientDecrypt.UpdateData(1024, syncBuf);
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
35
src/common/Cryptography/Authentication/WorldPacketCrypt.h
Normal file
35
src/common/Cryptography/Authentication/WorldPacketCrypt.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _WORLDPACKETCRYPT_H
|
||||
#define _WORLDPACKETCRYPT_H
|
||||
|
||||
#include "PacketCrypt.h"
|
||||
|
||||
class BigNumber;
|
||||
|
||||
class WorldPacketCrypt : public PacketCrypt
|
||||
{
|
||||
public:
|
||||
WorldPacketCrypt();
|
||||
|
||||
void Init(BigNumber* K) override;
|
||||
void Init(BigNumber* k, uint8 const* serverKey, uint8 const* clientKey);
|
||||
};
|
||||
|
||||
#endif // _WORLDPACKETCRYPT_H
|
||||
233
src/common/Cryptography/BigNumber.cpp
Normal file
233
src/common/Cryptography/BigNumber.cpp
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Cryptography/BigNumber.h"
|
||||
#include <openssl/bn.h>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
BigNumber::BigNumber() : _bn(BN_new()) { }
|
||||
|
||||
BigNumber::BigNumber(BigNumber const& bn) : _bn(BN_dup(bn._bn)) { }
|
||||
|
||||
BigNumber::BigNumber(uint32 val) : _bn(BN_new())
|
||||
{
|
||||
BN_set_word(_bn, val);
|
||||
}
|
||||
|
||||
BigNumber::~BigNumber()
|
||||
{
|
||||
BN_free(_bn);
|
||||
}
|
||||
|
||||
void BigNumber::SetDword(uint32 val)
|
||||
{
|
||||
BN_set_word(_bn, val);
|
||||
}
|
||||
|
||||
void BigNumber::SetQword(uint64 val)
|
||||
{
|
||||
BN_set_word(_bn, (uint32)(val >> 32));
|
||||
BN_lshift(_bn, _bn, 32);
|
||||
BN_add_word(_bn, (uint32)(val & 0xFFFFFFFF));
|
||||
}
|
||||
|
||||
void BigNumber::SetBinary(uint8 const* bytes, int32 len)
|
||||
{
|
||||
auto array = new uint8[len];
|
||||
|
||||
for (auto i = 0; i < len; i++)
|
||||
array[i] = bytes[len - 1 - i];
|
||||
|
||||
BN_bin2bn(array, len, _bn);
|
||||
|
||||
delete[] array;
|
||||
}
|
||||
|
||||
void BigNumber::SetHexStr(char const* str)
|
||||
{
|
||||
BN_hex2bn(&_bn, str);
|
||||
}
|
||||
|
||||
void BigNumber::SetRand(int32 numbits)
|
||||
{
|
||||
BN_rand(_bn, numbits, 0, 1);
|
||||
}
|
||||
|
||||
BigNumber& BigNumber::operator=(BigNumber const& bn)
|
||||
{
|
||||
if (this == &bn)
|
||||
return *this;
|
||||
|
||||
BN_copy(_bn, bn._bn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigNumber BigNumber::operator+=(BigNumber const& bn)
|
||||
{
|
||||
BN_add(_bn, _bn, bn._bn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigNumber BigNumber::operator+(BigNumber const& bn)
|
||||
{
|
||||
BigNumber t(*this);
|
||||
return t += bn;
|
||||
}
|
||||
|
||||
BigNumber BigNumber::operator-(BigNumber const& bn)
|
||||
{
|
||||
BigNumber t(*this);
|
||||
return t -= bn;
|
||||
}
|
||||
|
||||
BigNumber BigNumber::operator*(BigNumber const& bn)
|
||||
{
|
||||
BigNumber t(*this);
|
||||
return t *= bn;
|
||||
}
|
||||
|
||||
BigNumber BigNumber::operator/(BigNumber const& bn)
|
||||
{
|
||||
BigNumber t(*this);
|
||||
return t /= bn;
|
||||
}
|
||||
|
||||
BigNumber BigNumber::operator%(BigNumber const& bn)
|
||||
{
|
||||
BigNumber t(*this);
|
||||
return t %= bn;
|
||||
}
|
||||
|
||||
bignum_st* BigNumber::BN()
|
||||
{
|
||||
return _bn;
|
||||
}
|
||||
|
||||
BigNumber BigNumber::operator-=(BigNumber const& bn)
|
||||
{
|
||||
BN_sub(_bn, _bn, bn._bn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigNumber BigNumber::operator*=(BigNumber const& bn)
|
||||
{
|
||||
BN_CTX* bnctx = BN_CTX_new();
|
||||
BN_mul(_bn, _bn, bn._bn, bnctx);
|
||||
BN_CTX_free(bnctx);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigNumber BigNumber::operator/=(BigNumber const& bn)
|
||||
{
|
||||
BN_CTX* bnctx = BN_CTX_new();
|
||||
BN_div(_bn, NULL, _bn, bn._bn, bnctx);
|
||||
BN_CTX_free(bnctx);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigNumber BigNumber::operator%=(BigNumber const& bn)
|
||||
{
|
||||
BN_CTX* bnctx = BN_CTX_new();
|
||||
BN_mod(_bn, _bn, bn._bn, bnctx);
|
||||
BN_CTX_free(bnctx);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigNumber BigNumber::Exp(BigNumber const& bn)
|
||||
{
|
||||
BigNumber ret;
|
||||
|
||||
BN_CTX* bnctx = BN_CTX_new();
|
||||
BN_exp(ret._bn, _bn, bn._bn, bnctx);
|
||||
BN_CTX_free(bnctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BigNumber BigNumber::ModExp(BigNumber const& bn1, BigNumber const& bn2)
|
||||
{
|
||||
BigNumber ret;
|
||||
|
||||
BN_CTX* bnctx = BN_CTX_new();
|
||||
BN_mod_exp(ret._bn, _bn, bn1._bn, bn2._bn, bnctx);
|
||||
BN_CTX_free(bnctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32 BigNumber::GetNumBytes(void)
|
||||
{
|
||||
return BN_num_bytes(_bn);
|
||||
}
|
||||
|
||||
uint32 BigNumber::AsDword()
|
||||
{
|
||||
return (uint32)BN_get_word(_bn);
|
||||
}
|
||||
|
||||
bool BigNumber::IsZero() const
|
||||
{
|
||||
return BN_is_zero(_bn);
|
||||
}
|
||||
|
||||
bool BigNumber::IsNegative() const
|
||||
{
|
||||
return BN_is_negative(_bn);
|
||||
}
|
||||
|
||||
std::unique_ptr<uint8[]> BigNumber::AsByteArray(int32 minSize, bool littleEndian)
|
||||
{
|
||||
int numBytes = GetNumBytes();
|
||||
int length = (minSize >= numBytes) ? minSize : numBytes;
|
||||
|
||||
uint8* array = new uint8[length];
|
||||
|
||||
// If we need more bytes than length of BigNumber set the rest to 0
|
||||
if (length > numBytes)
|
||||
memset((void*)array, 0, length);
|
||||
|
||||
BN_bn2bin(_bn, (unsigned char *)array);
|
||||
|
||||
// openssl's BN stores data internally in big endian format, reverse if little endian desired
|
||||
if (littleEndian)
|
||||
std::reverse(array, array + numBytes);
|
||||
|
||||
std::unique_ptr<uint8[]> ret(array);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string BigNumber::AsHexStr() const
|
||||
{
|
||||
char* ch = BN_bn2hex(_bn);
|
||||
std::string ret = ch;
|
||||
OPENSSL_free(ch);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string BigNumber::AsDecStr() const
|
||||
{
|
||||
char* ch = BN_bn2dec(_bn);
|
||||
std::string ret = ch;
|
||||
OPENSSL_free(ch);
|
||||
return ret;
|
||||
}
|
||||
82
src/common/Cryptography/BigNumber.h
Normal file
82
src/common/Cryptography/BigNumber.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _AUTH_BIGNUMBER_H
|
||||
#define _AUTH_BIGNUMBER_H
|
||||
|
||||
#include "Define.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
struct bignum_st;
|
||||
|
||||
class BigNumber
|
||||
{
|
||||
public:
|
||||
BigNumber();
|
||||
BigNumber(BigNumber const& bn);
|
||||
BigNumber(uint32);
|
||||
~BigNumber();
|
||||
|
||||
void SetDword(uint32);
|
||||
void SetQword(uint64);
|
||||
void SetBinary(uint8 const* bytes, int32 len);
|
||||
void SetHexStr(char const* str);
|
||||
|
||||
void SetRand(int32 numbits);
|
||||
|
||||
BigNumber& operator=(BigNumber const& bn);
|
||||
|
||||
BigNumber operator+=(BigNumber const& bn);
|
||||
BigNumber operator+(BigNumber const& bn);
|
||||
|
||||
BigNumber operator-=(BigNumber const& bn);
|
||||
BigNumber operator-(BigNumber const& bn);
|
||||
|
||||
BigNumber operator*=(BigNumber const& bn);
|
||||
BigNumber operator*(BigNumber const& bn);
|
||||
|
||||
BigNumber operator/=(BigNumber const& bn);
|
||||
BigNumber operator/(BigNumber const& bn);
|
||||
|
||||
BigNumber operator%=(BigNumber const& bn);
|
||||
BigNumber operator%(BigNumber const& bn);
|
||||
|
||||
bool IsZero() const;
|
||||
bool IsNegative() const;
|
||||
|
||||
BigNumber ModExp(BigNumber const& bn1, BigNumber const& bn2);
|
||||
BigNumber Exp(BigNumber const&);
|
||||
|
||||
int32 GetNumBytes(void);
|
||||
|
||||
struct bignum_st* BN();
|
||||
|
||||
uint32 AsDword();
|
||||
|
||||
std::unique_ptr<uint8[]> AsByteArray(int32 minSize = 0, bool littleEndian = true);
|
||||
|
||||
std::string AsHexStr() const;
|
||||
std::string AsDecStr() const;
|
||||
|
||||
private:
|
||||
struct bignum_st *_bn;
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
81
src/common/Cryptography/HmacHash.cpp
Normal file
81
src/common/Cryptography/HmacHash.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "HmacHash.h"
|
||||
#include "BigNumber.h"
|
||||
#include "Errors.h"
|
||||
#include <cstring>
|
||||
|
||||
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
HMAC_CTX* HMAC_CTX_new()
|
||||
{
|
||||
HMAC_CTX *ctx = new HMAC_CTX();
|
||||
HMAC_CTX_init(ctx);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void HMAC_CTX_free(HMAC_CTX* ctx)
|
||||
{
|
||||
HMAC_CTX_cleanup(ctx);
|
||||
delete ctx;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<HashCreateFn HashCreator, uint32 DigestLength>
|
||||
HmacHash<HashCreator, DigestLength>::HmacHash(uint32 len, uint8 const* seed) : _ctx(HMAC_CTX_new())
|
||||
{
|
||||
HMAC_Init_ex(_ctx, seed, len, HashCreator(), nullptr);
|
||||
memset(_digest, 0, DigestLength);
|
||||
}
|
||||
|
||||
template<HashCreateFn HashCreator, uint32 DigestLength>
|
||||
HmacHash<HashCreator, DigestLength>::~HmacHash()
|
||||
{
|
||||
HMAC_CTX_free(_ctx);
|
||||
}
|
||||
|
||||
template<HashCreateFn HashCreator, uint32 DigestLength>
|
||||
void HmacHash<HashCreator, DigestLength>::UpdateData(std::string const& str)
|
||||
{
|
||||
HMAC_Update(_ctx, reinterpret_cast<uint8 const*>(str.c_str()), str.length());
|
||||
}
|
||||
|
||||
template<HashCreateFn HashCreator, uint32 DigestLength>
|
||||
void HmacHash<HashCreator, DigestLength>::UpdateData(uint8 const* data, size_t len)
|
||||
{
|
||||
HMAC_Update(_ctx, data, len);
|
||||
}
|
||||
|
||||
template<HashCreateFn HashCreator, uint32 DigestLength>
|
||||
void HmacHash<HashCreator, DigestLength>::Finalize()
|
||||
{
|
||||
uint32 length = 0;
|
||||
HMAC_Final(_ctx, _digest, &length);
|
||||
ASSERT(length == DigestLength);
|
||||
}
|
||||
|
||||
template<HashCreateFn HashCreator, uint32 DigestLength>
|
||||
uint8* HmacHash<HashCreator, DigestLength>::ComputeHash(BigNumber* bn)
|
||||
{
|
||||
HMAC_Update(_ctx, bn->AsByteArray().get(), bn->GetNumBytes());
|
||||
Finalize();
|
||||
return _digest;
|
||||
}
|
||||
|
||||
template class HmacHash<EVP_sha1, SHA_DIGEST_LENGTH>;
|
||||
template class HmacHash<EVP_sha256, SHA256_DIGEST_LENGTH>;
|
||||
53
src/common/Cryptography/HmacHash.h
Normal file
53
src/common/Cryptography/HmacHash.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _AUTH_HMAC_H
|
||||
#define _AUTH_HMAC_H
|
||||
|
||||
#include "Define.h"
|
||||
#include <string>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
class BigNumber;
|
||||
|
||||
#define SEED_KEY_SIZE 16
|
||||
|
||||
typedef EVP_MD const* (*HashCreateFn)();
|
||||
|
||||
template<HashCreateFn HashCreator, uint32 DigestLength>
|
||||
class HmacHash
|
||||
{
|
||||
public:
|
||||
HmacHash(uint32 len, uint8 const* seed);
|
||||
~HmacHash();
|
||||
void UpdateData(std::string const& str);
|
||||
void UpdateData(uint8 const* data, size_t len);
|
||||
void Finalize();
|
||||
uint8* ComputeHash(BigNumber* bn);
|
||||
uint8* GetDigest() { return _digest; }
|
||||
uint32 GetLength() const { return DigestLength; }
|
||||
private:
|
||||
HMAC_CTX* _ctx;
|
||||
uint8 _digest[DigestLength];
|
||||
};
|
||||
|
||||
typedef HmacHash<EVP_sha1, SHA_DIGEST_LENGTH> HmacSha1;
|
||||
typedef HmacHash<EVP_sha256, SHA256_DIGEST_LENGTH> HmacSha256;
|
||||
|
||||
#endif
|
||||
64
src/common/Cryptography/OpenSSLCrypto.cpp
Normal file
64
src/common/Cryptography/OpenSSLCrypto.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <OpenSSLCrypto.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
std::vector<std::mutex*> cryptoLocks;
|
||||
|
||||
static void lockingCallback(int mode, int type, const char* /*file*/, int /*line*/)
|
||||
{
|
||||
if (mode & CRYPTO_LOCK)
|
||||
cryptoLocks[type]->lock();
|
||||
else
|
||||
cryptoLocks[type]->unlock();
|
||||
}
|
||||
|
||||
static void threadIdCallback(CRYPTO_THREADID * id)
|
||||
{
|
||||
(void)id;
|
||||
CRYPTO_THREADID_set_numeric(id, std::hash<std::thread::id>()(std::this_thread::get_id()));
|
||||
}
|
||||
|
||||
void OpenSSLCrypto::threadsSetup()
|
||||
{
|
||||
cryptoLocks.resize(CRYPTO_num_locks());
|
||||
for(int i = 0 ; i < CRYPTO_num_locks(); ++i)
|
||||
{
|
||||
cryptoLocks[i] = new std::mutex();
|
||||
}
|
||||
|
||||
(void)&threadIdCallback;
|
||||
CRYPTO_THREADID_set_callback(threadIdCallback);
|
||||
|
||||
(void)&lockingCallback;
|
||||
CRYPTO_set_locking_callback(lockingCallback);
|
||||
}
|
||||
|
||||
void OpenSSLCrypto::threadsCleanup()
|
||||
{
|
||||
CRYPTO_set_locking_callback(NULL);
|
||||
CRYPTO_THREADID_set_callback(NULL);
|
||||
for(int i = 0 ; i < CRYPTO_num_locks(); ++i)
|
||||
{
|
||||
delete cryptoLocks[i];
|
||||
}
|
||||
cryptoLocks.resize(0);
|
||||
}
|
||||
35
src/common/Cryptography/OpenSSLCrypto.h
Normal file
35
src/common/Cryptography/OpenSSLCrypto.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OPENSSL_CRYPTO_H
|
||||
#define OPENSSL_CRYPTO_H
|
||||
|
||||
#include "Define.h"
|
||||
|
||||
/**
|
||||
* A group of functions which setup openssl crypto module to work properly in multithreaded enviroment
|
||||
* If not setup properly - it will crash
|
||||
*/
|
||||
namespace OpenSSLCrypto
|
||||
{
|
||||
/// Needs to be called before threads using openssl are spawned
|
||||
void threadsSetup();
|
||||
/// Needs to be called after threads using openssl are despawned
|
||||
void threadsCleanup();
|
||||
}
|
||||
|
||||
#endif
|
||||
133
src/common/Cryptography/RSA.cpp
Normal file
133
src/common/Cryptography/RSA.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "RSA.h"
|
||||
#include "BigNumber.h"
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <boost/iterator/reverse_iterator.hpp>
|
||||
|
||||
#define CHECK_AND_DECLARE_FUNCTION_TYPE(name, publicKey, privateKey) \
|
||||
static_assert(std::is_same<decltype(&publicKey), decltype(&privateKey)>::value, \
|
||||
"Public key and private key functions must have the same signature"); \
|
||||
using name ## _t = decltype(&publicKey); \
|
||||
template <typename KeyTag> inline name ## _t get_ ## name () { return nullptr; } \
|
||||
template <> inline name ## _t get_ ## name<Trinity::Crypto::RSA::PublicKey>() { return &publicKey; } \
|
||||
template <> inline name ## _t get_ ## name<Trinity::Crypto::RSA::PrivateKey>() { return &privateKey; }
|
||||
|
||||
namespace
|
||||
{
|
||||
struct BIODeleter
|
||||
{
|
||||
void operator()(BIO* bio)
|
||||
{
|
||||
BIO_free(bio);
|
||||
}
|
||||
};
|
||||
|
||||
CHECK_AND_DECLARE_FUNCTION_TYPE(PEM_read, PEM_read_bio_RSAPublicKey, PEM_read_bio_RSAPrivateKey);
|
||||
CHECK_AND_DECLARE_FUNCTION_TYPE(RSA_encrypt, RSA_public_encrypt, RSA_private_encrypt);
|
||||
}
|
||||
|
||||
Trinity::Crypto::RSA::RSA()
|
||||
{
|
||||
_rsa = RSA_new();
|
||||
}
|
||||
|
||||
Trinity::Crypto::RSA::RSA(RSA&& rsa)
|
||||
{
|
||||
_rsa = rsa._rsa;
|
||||
rsa._rsa = RSA_new();
|
||||
}
|
||||
|
||||
Trinity::Crypto::RSA::~RSA()
|
||||
{
|
||||
RSA_free(_rsa);
|
||||
}
|
||||
|
||||
template <typename KeyTag>
|
||||
bool Trinity::Crypto::RSA::LoadFromFile(std::string const& fileName, KeyTag)
|
||||
{
|
||||
std::unique_ptr<BIO, BIODeleter> keyBIO(BIO_new_file(fileName.c_str(), "r"));
|
||||
if (!keyBIO)
|
||||
return false;
|
||||
|
||||
if (!get_PEM_read<KeyTag>()(keyBIO.get(), &_rsa, nullptr, nullptr))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename KeyTag>
|
||||
bool Trinity::Crypto::RSA::LoadFromString(std::string const& keyPem, KeyTag)
|
||||
{
|
||||
std::unique_ptr<BIO, BIODeleter> keyBIO(BIO_new_mem_buf(const_cast<char*>(keyPem.c_str()), keyPem.length() + 1));
|
||||
if (!keyBIO)
|
||||
return false;
|
||||
|
||||
if (!get_PEM_read<KeyTag>()(keyBIO.get(), &_rsa, nullptr, nullptr))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
BigNumber Trinity::Crypto::RSA::GetModulus() const
|
||||
{
|
||||
BigNumber bn;
|
||||
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||
const BIGNUM* rsa_n;
|
||||
RSA_get0_key(_rsa, &rsa_n, nullptr, nullptr);
|
||||
BN_copy(bn.BN(), rsa_n);
|
||||
#else
|
||||
BN_copy(bn.BN(), _rsa->n);
|
||||
#endif
|
||||
return bn;
|
||||
}
|
||||
|
||||
template <typename KeyTag>
|
||||
bool Trinity::Crypto::RSA::Encrypt(uint8 const* data, std::size_t dataLength, uint8* output, int32 paddingType)
|
||||
{
|
||||
std::vector<uint8> inputData(boost::make_reverse_iterator(data + dataLength), boost::make_reverse_iterator(data));
|
||||
int result = get_RSA_encrypt<KeyTag>()(inputData.size(), inputData.data(), output, _rsa, paddingType);
|
||||
std::reverse(output, output + GetOutputSize());
|
||||
return result != -1;
|
||||
}
|
||||
|
||||
bool Trinity::Crypto::RSA::Sign(int32 hashType, uint8 const* dataHash, std::size_t dataHashLength, uint8* output)
|
||||
{
|
||||
uint32 signatureLength = 0;
|
||||
auto result = RSA_sign(hashType, dataHash, dataHashLength, output, &signatureLength, _rsa);
|
||||
std::reverse(output, output + GetOutputSize());
|
||||
return result != -1;
|
||||
}
|
||||
|
||||
namespace Trinity
|
||||
{
|
||||
namespace Crypto
|
||||
{
|
||||
template bool RSA::LoadFromFile(std::string const& fileName, RSA::PublicKey);
|
||||
template bool RSA::LoadFromFile(std::string const& fileName, RSA::PrivateKey);
|
||||
template bool RSA::LoadFromString(std::string const& keyPem, RSA::PublicKey);
|
||||
template bool RSA::LoadFromString(std::string const& keyPem, RSA::PrivateKey);
|
||||
template bool RSA::Encrypt<RSA::PublicKey>(uint8 const* data, std::size_t dataLength, uint8* output, int32 paddingType);
|
||||
template bool RSA::Encrypt<RSA::PrivateKey>(uint8 const* data, std::size_t dataLength, uint8* output, int32 paddingType);
|
||||
}
|
||||
}
|
||||
78
src/common/Cryptography/RSA.h
Normal file
78
src/common/Cryptography/RSA.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Define.h"
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
class BigNumber;
|
||||
|
||||
namespace Trinity
|
||||
{
|
||||
namespace Crypto
|
||||
{
|
||||
class RSA
|
||||
{
|
||||
public:
|
||||
RSA(RSA const& rsa) = delete;
|
||||
RSA& operator=(RSA const& rsa) = delete;
|
||||
|
||||
struct PublicKey {};
|
||||
struct PrivateKey {};
|
||||
|
||||
struct NoPadding : std::integral_constant<int32, RSA_NO_PADDING> {};
|
||||
struct PKCS1Padding : std::integral_constant<int32, RSA_PKCS1_PADDING> {};
|
||||
|
||||
struct SHA256 : std::integral_constant<int32, NID_sha256> {};
|
||||
|
||||
RSA();
|
||||
RSA(RSA&& rsa);
|
||||
~RSA();
|
||||
|
||||
template <typename KeyTag>
|
||||
bool LoadFromFile(std::string const& fileName, KeyTag);
|
||||
|
||||
template <typename KeyTag>
|
||||
bool LoadFromString(std::string const& keyPem, KeyTag);
|
||||
|
||||
uint32 GetOutputSize() const { return uint32(RSA_size(_rsa)); }
|
||||
BigNumber GetModulus() const;
|
||||
|
||||
template <typename KeyTag, typename PaddingTag>
|
||||
bool Encrypt(uint8 const* data, std::size_t dataLength, uint8* output, KeyTag, PaddingTag)
|
||||
{
|
||||
return Encrypt<KeyTag>(data, dataLength, output, PaddingTag::value);
|
||||
}
|
||||
|
||||
template <typename HashTag>
|
||||
bool Sign(uint8 const* dataHash, std::size_t dataHashLength, uint8* output, HashTag)
|
||||
{
|
||||
return Sign(HashTag::value, dataHash, dataHashLength, output);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename KeyTag>
|
||||
bool Encrypt(uint8 const* data, std::size_t dataLength, uint8* output, int32 paddingType);
|
||||
|
||||
bool Sign(int32 hashType, uint8 const* dataHash, std::size_t dataHashLength, uint8* output);
|
||||
|
||||
::RSA* _rsa;
|
||||
};
|
||||
}
|
||||
}
|
||||
76
src/common/Cryptography/SHA1.cpp
Normal file
76
src/common/Cryptography/SHA1.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "SHA1.h"
|
||||
#include "BigNumber.h"
|
||||
#include "Util.h"
|
||||
#include <cstring>
|
||||
#include <stdarg.h>
|
||||
|
||||
SHA1Hash::SHA1Hash()
|
||||
{
|
||||
SHA1_Init(&mC);
|
||||
memset(mDigest, 0, SHA_DIGEST_LENGTH * sizeof(uint8));
|
||||
}
|
||||
|
||||
SHA1Hash::~SHA1Hash()
|
||||
{
|
||||
SHA1_Init(&mC);
|
||||
}
|
||||
|
||||
void SHA1Hash::UpdateData(const uint8 *dta, int len)
|
||||
{
|
||||
SHA1_Update(&mC, dta, len);
|
||||
}
|
||||
|
||||
void SHA1Hash::UpdateData(const std::string &str)
|
||||
{
|
||||
UpdateData((uint8 const*)str.c_str(), str.length());
|
||||
}
|
||||
|
||||
void SHA1Hash::UpdateBigNumbers(BigNumber* bn0, ...)
|
||||
{
|
||||
va_list v;
|
||||
|
||||
va_start(v, bn0);
|
||||
auto bn = bn0;
|
||||
while (bn)
|
||||
{
|
||||
UpdateData(bn->AsByteArray().get(), bn->GetNumBytes());
|
||||
bn = va_arg(v, BigNumber*);
|
||||
}
|
||||
va_end(v);
|
||||
}
|
||||
|
||||
void SHA1Hash::Initialize()
|
||||
{
|
||||
SHA1_Init(&mC);
|
||||
}
|
||||
|
||||
void SHA1Hash::Finalize(void)
|
||||
{
|
||||
SHA1_Final(mDigest, &mC);
|
||||
}
|
||||
|
||||
std::string CalculateSHA1Hash(std::string const& content)
|
||||
{
|
||||
unsigned char digest[SHA_DIGEST_LENGTH];
|
||||
SHA1((unsigned char*)content.c_str(), content.length(), (unsigned char*)&digest);
|
||||
|
||||
return ByteArrayToHexStr(digest, SHA_DIGEST_LENGTH);
|
||||
}
|
||||
56
src/common/Cryptography/SHA1.h
Normal file
56
src/common/Cryptography/SHA1.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _AUTH_SHA1_H
|
||||
#define _AUTH_SHA1_H
|
||||
|
||||
#include "Define.h"
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
class BigNumber;
|
||||
|
||||
class SHA1Hash
|
||||
{
|
||||
public:
|
||||
typedef std::integral_constant<uint32, SHA_DIGEST_LENGTH> DigestLength;
|
||||
|
||||
SHA1Hash();
|
||||
~SHA1Hash();
|
||||
|
||||
void UpdateBigNumbers(BigNumber* bn0, ...);
|
||||
|
||||
void UpdateData(const uint8 *dta, int len);
|
||||
void UpdateData(const std::string &str);
|
||||
|
||||
void Initialize();
|
||||
void Finalize();
|
||||
|
||||
uint8 *GetDigest(void) { return mDigest; }
|
||||
int GetLength(void) const { return SHA_DIGEST_LENGTH; }
|
||||
|
||||
private:
|
||||
SHA_CTX mC;
|
||||
uint8 mDigest[SHA_DIGEST_LENGTH];
|
||||
};
|
||||
|
||||
/// Returns the SHA1 hash of the given content as hex string.
|
||||
std::string CalculateSHA1Hash(std::string const& content);
|
||||
|
||||
#endif
|
||||
77
src/common/Cryptography/SHA256.cpp
Normal file
77
src/common/Cryptography/SHA256.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "SHA256.h"
|
||||
#include "BigNumber.h"
|
||||
#include <cstring>
|
||||
#include <cstdarg>
|
||||
|
||||
SHA256Hash::SHA256Hash()
|
||||
{
|
||||
SHA256_Init(&mC);
|
||||
memset(mDigest, 0, SHA256_DIGEST_LENGTH * sizeof(uint8));
|
||||
}
|
||||
|
||||
SHA256Hash::~SHA256Hash()
|
||||
{
|
||||
SHA256_Init(&mC);
|
||||
}
|
||||
|
||||
void SHA256Hash::UpdateData(uint8 const* data, size_t len)
|
||||
{
|
||||
SHA256_Update(&mC, data, len);
|
||||
}
|
||||
|
||||
void SHA256Hash::UpdateData(const std::string &str)
|
||||
{
|
||||
UpdateData((uint8 const*)str.c_str(), str.length());
|
||||
}
|
||||
|
||||
void SHA256Hash::UpdateBigNumbers(BigNumber* bn0, ...)
|
||||
{
|
||||
va_list v;
|
||||
|
||||
va_start(v, bn0);
|
||||
auto bn = bn0;
|
||||
while (bn)
|
||||
{
|
||||
UpdateData(bn->AsByteArray().get(), bn->GetNumBytes());
|
||||
bn = va_arg(v, BigNumber*);
|
||||
}
|
||||
va_end(v);
|
||||
}
|
||||
|
||||
void SHA256Hash::Initialize()
|
||||
{
|
||||
SHA256_Init(&mC);
|
||||
}
|
||||
|
||||
void SHA256Hash::Finalize(void)
|
||||
{
|
||||
SHA256_Final(mDigest, &mC);
|
||||
}
|
||||
|
||||
uint8* SHA256Hash::GetDigest()
|
||||
{
|
||||
return mDigest;
|
||||
}
|
||||
|
||||
uint32 SHA256Hash::GetLength() const
|
||||
{
|
||||
return SHA256_DIGEST_LENGTH;
|
||||
}
|
||||
53
src/common/Cryptography/SHA256.h
Normal file
53
src/common/Cryptography/SHA256.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SHA256_h__
|
||||
#define SHA256_h__
|
||||
|
||||
#include "Define.h"
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
class BigNumber;
|
||||
|
||||
class SHA256Hash
|
||||
{
|
||||
public:
|
||||
typedef std::integral_constant<uint32, SHA256_DIGEST_LENGTH> DigestLength;
|
||||
|
||||
SHA256Hash();
|
||||
~SHA256Hash();
|
||||
|
||||
void UpdateBigNumbers(BigNumber* bn0, ...);
|
||||
|
||||
void UpdateData(uint8 const* data, size_t len);
|
||||
void UpdateData(std::string const& str);
|
||||
|
||||
void Initialize();
|
||||
void Finalize();
|
||||
|
||||
uint8* GetDigest();
|
||||
uint32 GetLength() const;
|
||||
|
||||
private:
|
||||
SHA256_CTX mC;
|
||||
uint8 mDigest[SHA256_DIGEST_LENGTH];
|
||||
};
|
||||
|
||||
#endif // SHA256_h__
|
||||
83
src/common/Cryptography/SessionKeyGeneration.h
Normal file
83
src/common/Cryptography/SessionKeyGeneration.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SessionKeyGeneration_h__
|
||||
#define SessionKeyGeneration_h__
|
||||
|
||||
#include "Define.h"
|
||||
#include <cstring>
|
||||
|
||||
template<class Hash>
|
||||
class SessionKeyGenerator
|
||||
{
|
||||
public:
|
||||
SessionKeyGenerator(uint8* buff, uint32 size)
|
||||
{
|
||||
uint32 halfSize = size / 2;
|
||||
|
||||
sh.Initialize();
|
||||
sh.UpdateData(buff, halfSize);
|
||||
sh.Finalize();
|
||||
|
||||
memcpy(o1, sh.GetDigest(), Hash::DigestLength::value);
|
||||
|
||||
sh.Initialize();
|
||||
sh.UpdateData(buff + halfSize, size - halfSize);
|
||||
sh.Finalize();
|
||||
|
||||
memcpy(o2, sh.GetDigest(), Hash::DigestLength::value);
|
||||
|
||||
memset(o0, 0x00, Hash::DigestLength::value);
|
||||
|
||||
FillUp();
|
||||
}
|
||||
|
||||
void Generate(uint8* buf, uint32 sz)
|
||||
{
|
||||
for (uint32 i = 0; i < sz; ++i)
|
||||
{
|
||||
if (taken == Hash::DigestLength::value)
|
||||
FillUp();
|
||||
|
||||
buf[i] = o0[taken];
|
||||
taken++;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void FillUp()
|
||||
{
|
||||
sh.Initialize();
|
||||
sh.UpdateData(o1, Hash::DigestLength::value);
|
||||
sh.UpdateData(o0, Hash::DigestLength::value);
|
||||
sh.UpdateData(o2, Hash::DigestLength::value);
|
||||
sh.Finalize();
|
||||
|
||||
memcpy(o0, sh.GetDigest(), Hash::DigestLength::value);
|
||||
|
||||
taken = 0;
|
||||
}
|
||||
|
||||
Hash sh;
|
||||
uint32 taken;
|
||||
uint8 o0[Hash::DigestLength::value];
|
||||
uint8 o1[Hash::DigestLength::value];
|
||||
uint8 o2[Hash::DigestLength::value];
|
||||
};
|
||||
|
||||
#endif // SessionKeyGeneration_h__
|
||||
68
src/common/Database/AdhocStatement.cpp
Normal file
68
src/common/Database/AdhocStatement.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "AdhocStatement.h"
|
||||
#include "MySQLConnection.h"
|
||||
|
||||
BasicStatementTask::BasicStatementTask(const char* sql, bool async, bool iscallback, std::function<void(QueryResult)> && callback) : m_result(nullptr), m_Callback(std::move(callback))
|
||||
{
|
||||
m_sql = strdup(sql);
|
||||
m_has_result = async; // If the operation is async, then there's a result
|
||||
m_has_callback = iscallback;
|
||||
if (async)
|
||||
m_result = new QueryResultPromise();
|
||||
}
|
||||
|
||||
BasicStatementTask::~BasicStatementTask()
|
||||
{
|
||||
free((void*)m_sql);
|
||||
if (m_has_result && m_result != nullptr)
|
||||
delete m_result;
|
||||
}
|
||||
|
||||
bool BasicStatementTask::Execute()
|
||||
{
|
||||
if (m_has_result)
|
||||
{
|
||||
ResultSet* result = m_conn->Query(m_sql);
|
||||
if (!result || !result->GetRowCount() || !result->NextRow())
|
||||
{
|
||||
delete result;
|
||||
if (m_has_callback)
|
||||
m_Callback(QueryResult(NULL));
|
||||
else
|
||||
m_result->set_value(QueryResult(NULL));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_has_callback)
|
||||
m_Callback(QueryResult(result));
|
||||
else
|
||||
m_result->set_value(QueryResult(result));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _executed = m_conn->Execute(m_sql);
|
||||
if (_executed && m_has_callback)
|
||||
m_Callback(QueryResult(NULL));
|
||||
return _executed;
|
||||
}
|
||||
|
||||
QueryResultFuture BasicStatementTask::GetFuture() const
|
||||
{
|
||||
return m_result->get_future();
|
||||
}
|
||||
41
src/common/Database/AdhocStatement.h
Normal file
41
src/common/Database/AdhocStatement.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _ADHOCSTATEMENT_H
|
||||
#define _ADHOCSTATEMENT_H
|
||||
|
||||
#include "SQLOperation.h"
|
||||
#include "DatabaseEnvFwd.h"
|
||||
|
||||
class BasicStatementTask : public SQLOperation
|
||||
{
|
||||
public:
|
||||
BasicStatementTask(const char* sql, bool async = false, bool iscallback = false, std::function<void(QueryResult)> && callback = [](QueryResult) -> void {});
|
||||
~BasicStatementTask();
|
||||
|
||||
bool Execute() override;
|
||||
QueryResultFuture GetFuture() const;
|
||||
|
||||
private:
|
||||
const char* m_sql; //- Raw query to be executed
|
||||
bool m_has_result;
|
||||
bool m_has_callback;
|
||||
QueryResultPromise* m_result;
|
||||
std::function<void(QueryResult)> m_Callback;
|
||||
};
|
||||
|
||||
#endif
|
||||
23
src/common/Database/DatabaseEnv.cpp
Normal file
23
src/common/Database/DatabaseEnv.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "DatabaseEnv.h"
|
||||
|
||||
WorldDatabaseWorkerPool WorldDatabase;
|
||||
CharacterDatabaseWorkerPool CharacterDatabase;
|
||||
LoginDatabaseWorkerPool LoginDatabase;
|
||||
HotfixDatabaseWorkerPool HotfixDatabase;
|
||||
48
src/common/Database/DatabaseEnv.h
Normal file
48
src/common/Database/DatabaseEnv.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DATABASEENV_H
|
||||
#define DATABASEENV_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Errors.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include "Field.h"
|
||||
#include "QueryResult.h"
|
||||
|
||||
#include "MySQLThreading.h"
|
||||
#include "Transaction.h"
|
||||
|
||||
#define _LIKE_ "LIKE"
|
||||
#define _TABLE_SIM_ "`"
|
||||
#define _CONCAT3_(A, B, C) "CONCAT( " A ", " B ", " C " )"
|
||||
#define _OFFSET_ "LIMIT %d, 1"
|
||||
|
||||
#include "Implementation/LoginDatabase.h"
|
||||
#include "Implementation/CharacterDatabase.h"
|
||||
#include "Implementation/WorldDatabase.h"
|
||||
#include "Implementation/HotfixDatabase.h"
|
||||
|
||||
extern WorldDatabaseWorkerPool WorldDatabase;
|
||||
extern CharacterDatabaseWorkerPool CharacterDatabase;
|
||||
extern LoginDatabaseWorkerPool LoginDatabase;
|
||||
extern HotfixDatabaseWorkerPool HotfixDatabase;
|
||||
|
||||
#endif
|
||||
|
||||
54
src/common/Database/DatabaseEnvFwd.h
Normal file
54
src/common/Database/DatabaseEnvFwd.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DatabaseEnvFwd_h__
|
||||
#define DatabaseEnvFwd_h__
|
||||
|
||||
#include <future>
|
||||
#include <memory>
|
||||
|
||||
class Field;
|
||||
|
||||
class ResultSet;
|
||||
typedef std::shared_ptr<ResultSet> QueryResult;
|
||||
typedef std::future<QueryResult> QueryResultFuture;
|
||||
typedef std::promise<QueryResult> QueryResultPromise;
|
||||
|
||||
class PreparedStatement;
|
||||
|
||||
class PreparedResultSet;
|
||||
typedef std::shared_ptr<PreparedResultSet> PreparedQueryResult;
|
||||
typedef std::future<PreparedQueryResult> PreparedQueryResultFuture;
|
||||
typedef std::promise<PreparedQueryResult> PreparedQueryResultPromise;
|
||||
|
||||
class QueryCallback;
|
||||
|
||||
class Transaction;
|
||||
typedef std::shared_ptr<Transaction> SQLTransaction;
|
||||
|
||||
class SQLQueryHolder;
|
||||
typedef std::future<SQLQueryHolder*> QueryResultHolderFuture;
|
||||
typedef std::promise<SQLQueryHolder*> QueryResultHolderPromise;
|
||||
|
||||
// mysql
|
||||
typedef struct st_mysql MYSQL;
|
||||
typedef struct st_mysql_res MYSQL_RES;
|
||||
typedef struct st_mysql_field MYSQL_FIELD;
|
||||
typedef struct st_mysql_bind MYSQL_BIND;
|
||||
typedef struct st_mysql_stmt MYSQL_STMT;
|
||||
|
||||
#endif // DatabaseEnvFwd_h__
|
||||
67
src/common/Database/DatabaseWorker.cpp
Normal file
67
src/common/Database/DatabaseWorker.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DatabaseWorker.h"
|
||||
#include "SQLOperation.h"
|
||||
#include "MySQLConnection.h"
|
||||
#include "MySQLThreading.h"
|
||||
#include "ProducerConsumerQueue.h"
|
||||
|
||||
#include <cds/init.h>
|
||||
#include <cds/gc/hp.h>
|
||||
|
||||
DatabaseWorker::DatabaseWorker(ProducerConsumerQueue<SQLOperation*>* newQueue, MySQLConnection* connection)
|
||||
{
|
||||
_connection = connection;
|
||||
_queue = newQueue;
|
||||
_cancelationToken = false;
|
||||
_workerThread = std::thread(&DatabaseWorker::WorkerThread, this);
|
||||
}
|
||||
|
||||
DatabaseWorker::~DatabaseWorker()
|
||||
{
|
||||
_cancelationToken = true;
|
||||
|
||||
_queue->Cancel();
|
||||
|
||||
_workerThread.join();
|
||||
}
|
||||
|
||||
void DatabaseWorker::WorkerThread()
|
||||
{
|
||||
if (!_queue)
|
||||
return;
|
||||
|
||||
cds::threading::Manager::attachThread();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
SQLOperation* operation = nullptr;
|
||||
|
||||
_queue->WaitAndPop(operation);
|
||||
|
||||
if (_cancelationToken || !operation)
|
||||
return;
|
||||
|
||||
operation->SetConnection(_connection);
|
||||
operation->call();
|
||||
|
||||
delete operation;
|
||||
}
|
||||
cds::threading::Manager::detachThread();
|
||||
}
|
||||
47
src/common/Database/DatabaseWorker.h
Normal file
47
src/common/Database/DatabaseWorker.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _WORKERTHREAD_H
|
||||
#define _WORKERTHREAD_H
|
||||
|
||||
#include "Define.h"
|
||||
#include "SQLOperation.h"
|
||||
#include <thread>
|
||||
#include "ProducerConsumerQueue.h"
|
||||
|
||||
class MySQLConnection;
|
||||
|
||||
class DatabaseWorker
|
||||
{
|
||||
public:
|
||||
DatabaseWorker(ProducerConsumerQueue<SQLOperation*>* newQueue, MySQLConnection* connection);
|
||||
~DatabaseWorker();
|
||||
|
||||
private:
|
||||
ProducerConsumerQueue<SQLOperation*>* _queue;
|
||||
MySQLConnection* _connection;
|
||||
|
||||
void WorkerThread();
|
||||
std::thread _workerThread;
|
||||
|
||||
std::atomic_bool _cancelationToken;
|
||||
|
||||
DatabaseWorker(DatabaseWorker const& right) = delete;
|
||||
DatabaseWorker& operator=(DatabaseWorker const& right) = delete;
|
||||
};
|
||||
|
||||
#endif
|
||||
528
src/common/Database/DatabaseWorkerPool.h
Normal file
528
src/common/Database/DatabaseWorkerPool.h
Normal file
@@ -0,0 +1,528 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _DATABASEWORKERPOOL_H
|
||||
#define _DATABASEWORKERPOOL_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "MySQLConnection.h"
|
||||
#include "Transaction.h"
|
||||
#include "DatabaseWorker.h"
|
||||
#include "PreparedStatement.h"
|
||||
#include "Log.h"
|
||||
#include "QueryResult.h"
|
||||
#include "QueryHolder.h"
|
||||
#include "AdhocStatement.h"
|
||||
#include <mysqld_error.h>
|
||||
#include "DatabaseEnvFwd.h"
|
||||
#include "QueryCallback.h"
|
||||
|
||||
#define MIN_MYSQL_SERVER_VERSION 50100u
|
||||
#define MIN_MYSQL_CLIENT_VERSION 50100u
|
||||
|
||||
class PingOperation : public SQLOperation
|
||||
{
|
||||
bool Execute() override
|
||||
{
|
||||
m_conn->Ping();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class DatabaseWorkerPool
|
||||
{
|
||||
enum InternalIndex
|
||||
{
|
||||
IDX_ASYNC,
|
||||
IDX_SYNCH,
|
||||
IDX_SIZE
|
||||
};
|
||||
|
||||
ProducerConsumerQueue<SQLOperation*>* _queue; //! Queue shared by async worker threads.
|
||||
std::vector<std::vector<T*>> _connections;
|
||||
uint32 _connectionCount[2]; //! Counter of MySQL connections;
|
||||
MySQLConnectionInfo _connectionInfo;
|
||||
|
||||
public:
|
||||
DatabaseWorkerPool()
|
||||
{
|
||||
_queue = new ProducerConsumerQueue<SQLOperation*>();
|
||||
memset(_connectionCount, 0, sizeof(_connectionCount));
|
||||
_connections.resize(IDX_SIZE);
|
||||
|
||||
WPFatal(mysql_thread_safe(), "Used MySQL library isn't thread-safe.");
|
||||
}
|
||||
|
||||
~DatabaseWorkerPool()
|
||||
{
|
||||
_queue->Cancel();
|
||||
delete _queue;
|
||||
}
|
||||
|
||||
bool Open(const std::string& infoString, uint8 async_threads, uint8 synch_threads)
|
||||
{
|
||||
bool res = true;
|
||||
_connectionInfo = MySQLConnectionInfo(infoString);
|
||||
|
||||
TC_LOG_INFO(LOG_FILTER_SQL_DRIVER, "Opening DatabasePool '%s'. Asynchronous connections: %u, synchronous connections: %u.", GetDatabaseName(), async_threads, synch_threads);
|
||||
|
||||
res = OpenConnections(IDX_ASYNC, async_threads);
|
||||
|
||||
if (!res)
|
||||
return res;
|
||||
|
||||
res = OpenConnections(IDX_SYNCH, synch_threads);
|
||||
|
||||
if (res)
|
||||
TC_LOG_INFO(LOG_FILTER_SQL_DRIVER, "DatabasePool '%s' opened successfully. %u total connections running.", GetDatabaseName(), (_connectionCount[IDX_SYNCH] + _connectionCount[IDX_ASYNC]));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
TC_LOG_INFO(LOG_FILTER_SQL_DRIVER, "Closing down DatabasePool '%s'.", GetDatabaseName());
|
||||
|
||||
for (uint8 i = 0; i < _connectionCount[IDX_ASYNC]; ++i)
|
||||
{
|
||||
T* t = _connections[IDX_ASYNC][i];
|
||||
t->Close(); //! Closes the actualy MySQL connection.
|
||||
}
|
||||
|
||||
TC_LOG_INFO(LOG_FILTER_SQL_DRIVER, "Asynchronous connections on DatabasePool '%s' terminated. Proceeding with synchronous connections.",
|
||||
GetDatabaseName());
|
||||
|
||||
//! Shut down the synchronous connections
|
||||
//! There's no need for locking the connection, because DatabaseWorkerPool<>::Close
|
||||
//! should only be called after any other thread tasks in the core have exited,
|
||||
//! meaning there can be no concurrent access at this point.
|
||||
for (uint8 i = 0; i < _connectionCount[IDX_SYNCH]; ++i)
|
||||
_connections[IDX_SYNCH][i]->Close();
|
||||
|
||||
TC_LOG_INFO(LOG_FILTER_SQL_DRIVER, "All connections on DatabasePool '%s' closed.", GetDatabaseName());
|
||||
}
|
||||
|
||||
/**
|
||||
Delayed one-way statement methods.
|
||||
*/
|
||||
|
||||
//! Enqueues a one-way SQL operation in string format that will be executed asynchronously.
|
||||
//! This method should only be used for queries that are only executed once, e.g during startup.
|
||||
void Execute(const char* sql)
|
||||
{
|
||||
if (!sql)
|
||||
return;
|
||||
|
||||
BasicStatementTask* task = new BasicStatementTask(sql);
|
||||
Enqueue(task);
|
||||
}
|
||||
|
||||
//! Enqueues a one-way SQL operation in string format -with variable args- that will be executed asynchronously.
|
||||
//! This method should only be used for queries that are only executed once, e.g during startup.
|
||||
template<typename Format, typename... Args>
|
||||
void PExecute(Format&& sql, Args&&... args)
|
||||
{
|
||||
if (Trinity::IsFormatEmptyOrNull(sql))
|
||||
return;
|
||||
|
||||
Execute(Trinity::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str());
|
||||
}
|
||||
|
||||
//! Enqueues a one-way SQL operation in prepared statement format that will be executed asynchronously.
|
||||
//! Statement must be prepared with CONNECTION_ASYNC flag.
|
||||
void Execute(PreparedStatement* stmt)
|
||||
{
|
||||
PreparedStatementTask* task = new PreparedStatementTask(stmt);
|
||||
Enqueue(task);
|
||||
}
|
||||
|
||||
/**
|
||||
Direct synchronous one-way statement methods.
|
||||
*/
|
||||
|
||||
//! Directly executes a one-way SQL operation in string format, that will block the calling thread until finished.
|
||||
//! This method should only be used for queries that are only executed once, e.g during startup.
|
||||
void DirectExecute(const char* sql)
|
||||
{
|
||||
if (!sql)
|
||||
return;
|
||||
|
||||
T* t = GetFreeConnection();
|
||||
t->Execute(sql);
|
||||
t->Unlock();
|
||||
}
|
||||
|
||||
//! Directly executes a one-way SQL operation in string format -with variable args-, that will block the calling thread until finished.
|
||||
//! This method should only be used for queries that are only executed once, e.g during startup.
|
||||
template<typename Format, typename... Args>
|
||||
void DirectPExecute(Format&& sql, Args&&... args)
|
||||
{
|
||||
if (Trinity::IsFormatEmptyOrNull(sql))
|
||||
return;
|
||||
|
||||
DirectExecute(Trinity::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str());
|
||||
}
|
||||
|
||||
//! Directly executes a one-way SQL operation in prepared statement format, that will block the calling thread until finished.
|
||||
//! Statement must be prepared with the CONNECTION_SYNCH flag.
|
||||
void DirectExecute(PreparedStatement* stmt)
|
||||
{
|
||||
T* t = GetFreeConnection();
|
||||
t->Execute(stmt);
|
||||
t->Unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
Synchronous query (with resultset) methods.
|
||||
*/
|
||||
|
||||
//! Directly executes an SQL query in string format that will block the calling thread until finished.
|
||||
//! Returns reference counted auto pointer, no need for manual memory management in upper level code.
|
||||
QueryResult Query(const char* sql, MySQLConnection* conn = NULL)
|
||||
{
|
||||
if (!conn)
|
||||
conn = GetFreeConnection();
|
||||
|
||||
ResultSet* result = conn->Query(sql);
|
||||
conn->Unlock();
|
||||
if (!result || !result->GetRowCount())
|
||||
{
|
||||
delete result;
|
||||
return QueryResult(NULL);
|
||||
}
|
||||
result->NextRow();
|
||||
return QueryResult(result);
|
||||
}
|
||||
|
||||
//! Directly executes an SQL query in string format -with variable args- that will block the calling thread until finished.
|
||||
//! Returns reference counted auto pointer, no need for manual memory management in upper level code.
|
||||
template<typename Format, typename... Args>
|
||||
QueryResult PQuery(Format&& sql, T* conn, Args&&... args)
|
||||
{
|
||||
if (Trinity::IsFormatEmptyOrNull(sql))
|
||||
return QueryResult(nullptr);
|
||||
|
||||
return Query(Trinity::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str(), conn);
|
||||
}
|
||||
|
||||
//! Directly executes an SQL query in string format -with variable args- that will block the calling thread until finished.
|
||||
//! Returns reference counted auto pointer, no need for manual memory management in upper level code.
|
||||
template<typename Format, typename... Args>
|
||||
QueryResult PQuery(Format&& sql, Args&&... args)
|
||||
{
|
||||
if (Trinity::IsFormatEmptyOrNull(sql))
|
||||
return QueryResult(nullptr);
|
||||
|
||||
return Query(Trinity::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str());
|
||||
}
|
||||
|
||||
//! Directly executes an SQL query in prepared format that will block the calling thread until finished.
|
||||
//! Returns reference counted auto pointer, no need for manual memory management in upper level code.
|
||||
//! Statement must be prepared with CONNECTION_SYNCH flag.
|
||||
PreparedQueryResult Query(PreparedStatement* stmt)
|
||||
{
|
||||
T* t = GetFreeConnection();
|
||||
PreparedResultSet* ret = t->Query(stmt);
|
||||
t->Unlock();
|
||||
|
||||
//! Delete proxy-class. Not needed anymore
|
||||
delete stmt;
|
||||
|
||||
if (!ret || !ret->GetRowCount())
|
||||
|
||||
{
|
||||
delete ret;
|
||||
return PreparedQueryResult(NULL);
|
||||
}
|
||||
return PreparedQueryResult(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
Asynchronous query (with resultset) methods.
|
||||
*/
|
||||
|
||||
//! 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.
|
||||
QueryCallback 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 QueryCallback(std::move(result));
|
||||
}
|
||||
|
||||
void CallBackQuery(const char* sql, std::function<void(QueryResult)> callback)
|
||||
{
|
||||
BasicStatementTask* task = new BasicStatementTask(sql, true, true, std::move(callback));
|
||||
Enqueue(task);
|
||||
}
|
||||
|
||||
//! 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.
|
||||
QueryCallback AsyncQuery(PreparedStatement* stmt)
|
||||
{
|
||||
PreparedStatementTask* task = new PreparedStatementTask(stmt, true);
|
||||
PreparedQueryResultFuture result = task->GetFuture();
|
||||
Enqueue(task);
|
||||
return QueryCallback(std::move(result));
|
||||
}
|
||||
|
||||
void CallBackQuery(PreparedStatement* stmt, std::function<void(PreparedQueryResult)> callback)
|
||||
{
|
||||
PreparedStatementTask* task = new PreparedStatementTask(stmt, true, true, std::move(callback));
|
||||
Enqueue(task);
|
||||
}
|
||||
|
||||
//! 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.
|
||||
//! 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)
|
||||
{
|
||||
SQLQueryHolderTask* task = new SQLQueryHolderTask(holder);
|
||||
// Store future result before enqueueing - task might get already processed and deleted before returning from this method
|
||||
QueryResultHolderFuture result = task->GetFuture();
|
||||
Enqueue(task);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
Transaction context methods.
|
||||
*/
|
||||
|
||||
//! Begins an automanaged transaction pointer that will automatically rollback if not commited. (Autocommit=0)
|
||||
SQLTransaction BeginTransaction()
|
||||
{
|
||||
return std::make_shared<Transaction>();
|
||||
}
|
||||
|
||||
//! 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, std::function<void()>&& callback = []() -> void {})
|
||||
{
|
||||
#ifdef TRINITY_DEBUG
|
||||
//! Only analyze transaction weaknesses in Debug mode.
|
||||
//! Ideally we catch the faults in Debug mode and then correct them,
|
||||
//! so there's no need to waste these CPU cycles in Release mode.
|
||||
switch (transaction->GetSize())
|
||||
{
|
||||
case 0:
|
||||
TC_LOG_DEBUG(LOG_FILTER_SQL_DRIVER, "Transaction contains 0 queries. Not executing.");
|
||||
return;
|
||||
case 1:
|
||||
TC_LOG_DEBUG(LOG_FILTER_SQL_DRIVER, "Warning: Transaction only holds 1 query, consider removing Transaction context in code.");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif // TRINITY_DEBUG
|
||||
|
||||
Enqueue(new TransactionTask(transaction, std::move(callback)));
|
||||
}
|
||||
|
||||
//! 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)
|
||||
{
|
||||
MySQLConnection* con = GetFreeConnection();
|
||||
int errorCode = con->ExecuteTransaction(transaction);
|
||||
if (!errorCode)
|
||||
{
|
||||
con->Unlock(); // OK, operation succesful
|
||||
return;
|
||||
}
|
||||
|
||||
//! Handle MySQL Errno 1213 without extending deadlock to the core itself
|
||||
//! TODO: More elegant way
|
||||
if (errorCode == ER_LOCK_DEADLOCK)
|
||||
{
|
||||
uint8 loopBreaker = 5;
|
||||
for (uint8 i = 0; i < loopBreaker; ++i)
|
||||
{
|
||||
if (!con->ExecuteTransaction(transaction))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//! Clean up now.
|
||||
transaction->Cleanup();
|
||||
|
||||
con->Unlock();
|
||||
}
|
||||
|
||||
//! 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* stmt)
|
||||
{
|
||||
if (!trans)
|
||||
Execute(stmt);
|
||||
else
|
||||
trans->Append(stmt);
|
||||
}
|
||||
|
||||
//! 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, const char* sql)
|
||||
{
|
||||
if (!trans)
|
||||
Execute(sql);
|
||||
else
|
||||
trans->Append(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
Other
|
||||
*/
|
||||
|
||||
//! Automanaged (internally) pointer to a prepared statement object for usage in upper level code.
|
||||
//! Pointer is deleted in this->Query(PreparedStatement*) or PreparedStatementTask::~PreparedStatementTask.
|
||||
//! This object is not tied to the prepared statement on the MySQL context yet until execution.
|
||||
PreparedStatement* GetPreparedStatement(uint32 index)
|
||||
{
|
||||
return new PreparedStatement(index, _connections[IDX_SYNCH][0]->m_queries[index].capacity);
|
||||
}
|
||||
|
||||
//! Apply escape string'ing for current collation. (utf8)
|
||||
void EscapeString(std::string& str)
|
||||
{
|
||||
if (str.empty())
|
||||
return;
|
||||
|
||||
char* buf = new char[str.size() * 2 + 1];
|
||||
EscapeString(buf, str.c_str(), str.size());
|
||||
str = buf;
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
//! Keeps all our MySQL connections alive, prevent the server from disconnecting us.
|
||||
void KeepAlive()
|
||||
{
|
||||
//! Ping synchronous connections
|
||||
for (uint8 i = 0; i < _connectionCount[IDX_SYNCH]; ++i)
|
||||
{
|
||||
T* t = _connections[IDX_SYNCH][i];
|
||||
if (t->LockIfReady())
|
||||
{
|
||||
t->Ping();
|
||||
t->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
//! Assuming all worker threads are free, every worker thread will receive 1 ping operation request
|
||||
//! If one or more worker threads are busy, the ping operations will not be split evenly, but this doesn't matter
|
||||
//! as the sole purpose is to prevent connections from idling.
|
||||
for (size_t i = 0; i < _connections[IDX_ASYNC].size(); ++i)
|
||||
Enqueue(new PingOperation);
|
||||
}
|
||||
|
||||
char const* GetDatabaseName() const
|
||||
{
|
||||
return _connectionInfo.database.c_str();
|
||||
}
|
||||
|
||||
void WaitExecution()
|
||||
{
|
||||
while (!_queue->Empty())
|
||||
{
|
||||
}
|
||||
}
|
||||
private:
|
||||
bool OpenConnections(InternalIndex type, uint8 numConnections)
|
||||
{
|
||||
_connections[type].resize(numConnections);
|
||||
for (uint8 i = 0; i < numConnections; ++i)
|
||||
{
|
||||
T* t;
|
||||
|
||||
if (type == IDX_ASYNC)
|
||||
t = new T(_queue, _connectionInfo);
|
||||
else if (type == IDX_SYNCH)
|
||||
t = new T(_connectionInfo);
|
||||
else
|
||||
ASSERT(false);
|
||||
|
||||
_connections[type][i] = t;
|
||||
++_connectionCount[type];
|
||||
|
||||
bool res = t->Open();
|
||||
|
||||
if (res)
|
||||
{
|
||||
if (mysql_get_server_version(t->GetHandle()) < MIN_MYSQL_SERVER_VERSION)
|
||||
{
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL_DRIVER, "TrinityCore does not support MySQL versions below 5.1");
|
||||
res = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Failed to open a connection or invalid version, abort and cleanup
|
||||
if (!res)
|
||||
{
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL_DRIVER, "DatabasePool %s NOT opened. There were errors opening the MySQL connections. Check your SQLDriverLogFile "
|
||||
"for specific errors. Read wiki at http://collab.kpsn.org/display/tc/TrinityCore+Home", GetDatabaseName());
|
||||
|
||||
while (_connectionCount[type] != 0)
|
||||
{
|
||||
T* t = _connections[type][i--];
|
||||
delete t;
|
||||
--_connectionCount[type];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned long EscapeString(char *to, const char *from, unsigned long length)
|
||||
{
|
||||
if (!to || !from || !length)
|
||||
return 0;
|
||||
|
||||
return mysql_real_escape_string(_connections[IDX_SYNCH][0]->GetHandle(), to, from, length);
|
||||
}
|
||||
|
||||
void Enqueue(SQLOperation* op)
|
||||
{
|
||||
_queue->Push(op);
|
||||
}
|
||||
|
||||
//! Gets a free connection in the synchronous connection pool.
|
||||
//! Caller MUST call t->Unlock() after touching the MySQL context to prevent deadlocks.
|
||||
T* GetFreeConnection()
|
||||
{
|
||||
uint8 i = 0;
|
||||
size_t num_cons = _connectionCount[IDX_SYNCH];
|
||||
//! Block forever until a connection is free
|
||||
for (;;)
|
||||
{
|
||||
T* t = _connections[IDX_SYNCH][++i % num_cons];
|
||||
//! Must be matched with t->Unlock() or you will get deadlocks
|
||||
if (t->LockIfReady())
|
||||
return t;
|
||||
}
|
||||
|
||||
//! This will be called when Celine Dion learns to sing
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
365
src/common/Database/Field.cpp
Normal file
365
src/common/Database/Field.cpp
Normal file
@@ -0,0 +1,365 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Field.h"
|
||||
|
||||
bool Field::GetBool() const
|
||||
{
|
||||
return GetUInt8() == 1 ? true : false;
|
||||
}
|
||||
|
||||
uint8 Field::GetUInt8() const
|
||||
{
|
||||
if (!data.value)
|
||||
return 0;
|
||||
|
||||
#ifdef TRINITY_DEBUG
|
||||
if (!IsNumeric())
|
||||
{
|
||||
TC_LOG_WARN(LOG_FILTER_SQL, "Warning: GetUInt8() on non-tinyint field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (data.raw)
|
||||
return *reinterpret_cast<uint8*>(data.value);
|
||||
return static_cast<uint8>(strtoul(static_cast<char*>(data.value), nullptr, 10));
|
||||
}
|
||||
|
||||
int8 Field::GetInt8() const
|
||||
{
|
||||
if (!data.value)
|
||||
return 0;
|
||||
|
||||
#ifdef TRINITY_DEBUG
|
||||
if (!IsNumeric())
|
||||
{
|
||||
TC_LOG_WARN(LOG_FILTER_SQL, "Warning: GetInt8() on non-tinyint field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (data.raw)
|
||||
return *reinterpret_cast<int8*>(data.value);
|
||||
return static_cast<int8>(strtol(static_cast<char*>(data.value), NULL, 10));
|
||||
}
|
||||
|
||||
uint16 Field::GetUInt16() const
|
||||
{
|
||||
if (!data.value)
|
||||
return 0;
|
||||
|
||||
#ifdef TRINITY_DEBUG
|
||||
if (!IsNumeric())
|
||||
{
|
||||
TC_LOG_WARN(LOG_FILTER_SQL, "Warning: GetUInt16() on non-smallint field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (data.raw)
|
||||
return *reinterpret_cast<uint16*>(data.value);
|
||||
return static_cast<uint16>(strtoul(static_cast<char*>(data.value), nullptr, 10));
|
||||
}
|
||||
|
||||
int16 Field::GetInt16() const
|
||||
{
|
||||
if (!data.value)
|
||||
return 0;
|
||||
|
||||
#ifdef TRINITY_DEBUG
|
||||
if (!IsNumeric())
|
||||
{
|
||||
TC_LOG_WARN(LOG_FILTER_SQL, "Warning: GetInt16() on non-smallint field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (data.raw)
|
||||
return *reinterpret_cast<int16*>(data.value);
|
||||
return static_cast<int16>(strtol(static_cast<char*>(data.value), NULL, 10));
|
||||
}
|
||||
|
||||
uint32 Field::GetUInt32() const
|
||||
{
|
||||
if (!data.value)
|
||||
return 0;
|
||||
|
||||
#ifdef TRINITY_DEBUG
|
||||
if (!IsNumeric())
|
||||
{
|
||||
TC_LOG_WARN(LOG_FILTER_SQL, "Warning: GetUInt32() on non-(medium)int field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (data.raw)
|
||||
return *reinterpret_cast<uint32*>(data.value);
|
||||
return static_cast<uint32>(strtoul(static_cast<char*>(data.value), nullptr, 10));
|
||||
}
|
||||
|
||||
int32 Field::GetInt32() const
|
||||
{
|
||||
if (!data.value)
|
||||
return 0;
|
||||
|
||||
#ifdef TRINITY_DEBUG
|
||||
if (!IsNumeric())
|
||||
{
|
||||
TC_LOG_WARN(LOG_FILTER_SQL, "Warning: GetInt32() on non-(medium)int field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (data.raw)
|
||||
return *reinterpret_cast<int32*>(data.value);
|
||||
return static_cast<int32>(strtol(static_cast<char*>(data.value), NULL, 10));
|
||||
}
|
||||
|
||||
uint64 Field::GetUInt64() const
|
||||
{
|
||||
if (!data.value)
|
||||
return 0;
|
||||
|
||||
#ifdef TRINITY_DEBUG
|
||||
if (!IsNumeric())
|
||||
{
|
||||
TC_LOG_WARN(LOG_FILTER_SQL, "Warning: GetUInt64() on non-bigint field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (data.raw)
|
||||
return *reinterpret_cast<uint64*>(data.value);
|
||||
return static_cast<uint64>(strtoull(static_cast<char*>(data.value), nullptr, 10));
|
||||
}
|
||||
|
||||
int64 Field::GetInt64() const
|
||||
{
|
||||
if (!data.value)
|
||||
return 0;
|
||||
|
||||
#ifdef TRINITY_DEBUG
|
||||
if (!IsNumeric())
|
||||
{
|
||||
TC_LOG_WARN(LOG_FILTER_SQL, "Warning: GetInt64() on non-bigint field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (data.raw)
|
||||
return *reinterpret_cast<int64*>(data.value);
|
||||
return static_cast<int64>(strtoll(static_cast<char*>(data.value), NULL, 10));
|
||||
}
|
||||
|
||||
float Field::GetFloat() const
|
||||
{
|
||||
if (!data.value)
|
||||
return 0.0f;
|
||||
|
||||
#ifdef TRINITY_DEBUG
|
||||
if (!IsNumeric())
|
||||
{
|
||||
TC_LOG_WARN(LOG_FILTER_SQL, "Warning: GetFloat() on non-float field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return 0.0f;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (data.raw)
|
||||
return *reinterpret_cast<float*>(data.value);
|
||||
return static_cast<float>(atof(static_cast<char*>(data.value)));
|
||||
}
|
||||
|
||||
double Field::GetDouble() const
|
||||
{
|
||||
if (!data.value)
|
||||
return 0.0f;
|
||||
|
||||
#ifdef TRINITY_DEBUG
|
||||
if (!IsNumeric())
|
||||
{
|
||||
TC_LOG_WARN(LOG_FILTER_SQL, "Warning: GetDouble() on non-double field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return 0.0f;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (data.raw)
|
||||
return *reinterpret_cast<double*>(data.value);
|
||||
return static_cast<double>(atof(static_cast<char*>(data.value)));
|
||||
}
|
||||
|
||||
char const* Field::GetCString() const
|
||||
{
|
||||
if (!data.value)
|
||||
return NULL;
|
||||
|
||||
#ifdef TRINITY_DEBUG
|
||||
if (IsNumeric())
|
||||
{
|
||||
TC_LOG_WARN(LOG_FILTER_SQL, "Error: GetCString() on numeric field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
return static_cast<char const*>(data.value);
|
||||
}
|
||||
|
||||
std::string Field::GetString() const
|
||||
{
|
||||
if (!data.value)
|
||||
return "";
|
||||
|
||||
char const* string = GetCString();
|
||||
if (!string)
|
||||
return "";
|
||||
|
||||
return std::string(string, data.length);
|
||||
}
|
||||
|
||||
std::vector<uint8> Field::GetBinary() const
|
||||
{
|
||||
std::vector<uint8> result;
|
||||
if (!data.value || !data.length)
|
||||
return result;
|
||||
|
||||
result.resize(data.length);
|
||||
memcpy(result.data(), data.value, data.length);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Field::IsNull() const
|
||||
{
|
||||
return data.value == NULL;
|
||||
}
|
||||
|
||||
Field::Field()
|
||||
{
|
||||
data.value = NULL;
|
||||
data.type = MYSQL_TYPE_NULL;
|
||||
data.length = 0;
|
||||
data.raw = false;
|
||||
}
|
||||
|
||||
Field::~Field()
|
||||
{
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
void Field::SetByteValue(const void* newValue, const size_t newSize, enum_field_types newType, uint32 length)
|
||||
{
|
||||
if (data.value)
|
||||
CleanUp();
|
||||
|
||||
// This value stores raw bytes that have to be explicitly cast later
|
||||
if (newValue)
|
||||
{
|
||||
data.value = new char[newSize];
|
||||
memcpy(data.value, newValue, newSize);
|
||||
data.length = length;
|
||||
}
|
||||
data.type = newType;
|
||||
data.raw = true;
|
||||
}
|
||||
|
||||
void Field::SetStructuredValue(char* newValue, enum_field_types newType, uint32 length)
|
||||
{
|
||||
if (data.value)
|
||||
CleanUp();
|
||||
|
||||
// This value stores somewhat structured data that needs function style casting
|
||||
if (newValue)
|
||||
{
|
||||
data.value = new char[length + 1];
|
||||
memcpy(data.value, newValue, length);
|
||||
*(reinterpret_cast<char*>(data.value) + length) = '\0';
|
||||
data.length = length;
|
||||
}
|
||||
|
||||
data.type = newType;
|
||||
data.raw = false;
|
||||
}
|
||||
|
||||
void Field::CleanUp()
|
||||
{
|
||||
delete[]static_cast<char*>(data.value);
|
||||
data.value = NULL;
|
||||
}
|
||||
|
||||
size_t Field::SizeForType(MYSQL_FIELD* field)
|
||||
{
|
||||
switch (field->type)
|
||||
{
|
||||
case MYSQL_TYPE_NULL:
|
||||
return 0;
|
||||
case MYSQL_TYPE_TINY:
|
||||
return 1;
|
||||
case MYSQL_TYPE_YEAR:
|
||||
case MYSQL_TYPE_SHORT:
|
||||
return 2;
|
||||
case MYSQL_TYPE_INT24:
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_FLOAT:
|
||||
return 4;
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
case MYSQL_TYPE_BIT:
|
||||
return 8;
|
||||
|
||||
case MYSQL_TYPE_TIMESTAMP:
|
||||
case MYSQL_TYPE_DATE:
|
||||
case MYSQL_TYPE_TIME:
|
||||
case MYSQL_TYPE_DATETIME:
|
||||
return sizeof(MYSQL_TIME);
|
||||
|
||||
case MYSQL_TYPE_TINY_BLOB:
|
||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
case MYSQL_TYPE_BLOB:
|
||||
case MYSQL_TYPE_STRING:
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
return field->max_length + 1;
|
||||
|
||||
case MYSQL_TYPE_DECIMAL:
|
||||
case MYSQL_TYPE_NEWDECIMAL:
|
||||
return 64;
|
||||
|
||||
case MYSQL_TYPE_GEOMETRY:
|
||||
/*
|
||||
Following types are not sent over the wire:
|
||||
MYSQL_TYPE_ENUM:
|
||||
MYSQL_TYPE_SET:
|
||||
*/
|
||||
default:
|
||||
TC_LOG_WARN(LOG_FILTER_SQL, "SQL::SizeForType(): invalid field type %u", uint32(field->type));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool Field::IsType(enum_field_types type) const
|
||||
{
|
||||
return data.type == type;
|
||||
}
|
||||
|
||||
bool Field::IsNumeric() const
|
||||
{
|
||||
return (data.type == MYSQL_TYPE_TINY ||
|
||||
data.type == MYSQL_TYPE_SHORT ||
|
||||
data.type == MYSQL_TYPE_INT24 ||
|
||||
data.type == MYSQL_TYPE_LONG ||
|
||||
data.type == MYSQL_TYPE_FLOAT ||
|
||||
data.type == MYSQL_TYPE_DOUBLE ||
|
||||
data.type == MYSQL_TYPE_LONGLONG);
|
||||
}
|
||||
119
src/common/Database/Field.h
Normal file
119
src/common/Database/Field.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _FIELD_H
|
||||
#define _FIELD_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <mysql.h>
|
||||
|
||||
class Field
|
||||
{
|
||||
friend class ResultSet;
|
||||
friend class PreparedResultSet;
|
||||
|
||||
public:
|
||||
bool GetBool() const; // Wrapper, actually gets integer
|
||||
uint8 GetUInt8() const;
|
||||
int8 GetInt8() const;
|
||||
uint16 GetUInt16() const;
|
||||
int16 GetInt16() const;
|
||||
uint32 GetUInt32() const;
|
||||
int32 GetInt32() const;
|
||||
uint64 GetUInt64() const;
|
||||
int64 GetInt64() const;
|
||||
float GetFloat() const;
|
||||
double GetDouble() const;
|
||||
char const* GetCString() const;
|
||||
std::string GetString() const;
|
||||
std::vector<uint8> GetBinary() const;
|
||||
bool IsNull() const;
|
||||
|
||||
protected:
|
||||
Field();
|
||||
~Field();
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma pack(1)
|
||||
#else
|
||||
#pragma pack(push, 1)
|
||||
#endif
|
||||
struct
|
||||
{
|
||||
uint32 length; // Length (prepared strings only)
|
||||
void* value; // Actual data in memory
|
||||
enum_field_types type; // Field type
|
||||
bool raw; // Raw bytes? (Prepared statement or ad hoc)
|
||||
} data;
|
||||
#if defined(__GNUC__)
|
||||
#pragma pack()
|
||||
#else
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
void SetByteValue(void const* newValue, size_t newSize, enum_field_types newType, uint32 length);
|
||||
void SetStructuredValue(char* newValue, enum_field_types newType, uint32 length);
|
||||
|
||||
void CleanUp();
|
||||
|
||||
static size_t SizeForType(MYSQL_FIELD* field);
|
||||
|
||||
bool IsType(enum_field_types type) const;
|
||||
bool IsNumeric() const;
|
||||
|
||||
private:
|
||||
#ifdef TRINITY_DEBUG
|
||||
static char const* FieldTypeToString(enum_field_types type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MYSQL_TYPE_BIT: return "BIT";
|
||||
case MYSQL_TYPE_BLOB: return "BLOB";
|
||||
case MYSQL_TYPE_DATE: return "DATE";
|
||||
case MYSQL_TYPE_DATETIME: return "DATETIME";
|
||||
case MYSQL_TYPE_NEWDECIMAL: return "NEWDECIMAL";
|
||||
case MYSQL_TYPE_DECIMAL: return "DECIMAL";
|
||||
case MYSQL_TYPE_DOUBLE: return "DOUBLE";
|
||||
case MYSQL_TYPE_ENUM: return "ENUM";
|
||||
case MYSQL_TYPE_FLOAT: return "FLOAT";
|
||||
case MYSQL_TYPE_GEOMETRY: return "GEOMETRY";
|
||||
case MYSQL_TYPE_INT24: return "INT24";
|
||||
case MYSQL_TYPE_LONG: return "LONG";
|
||||
case MYSQL_TYPE_LONGLONG: return "LONGLONG";
|
||||
case MYSQL_TYPE_LONG_BLOB: return "LONG_BLOB";
|
||||
case MYSQL_TYPE_MEDIUM_BLOB: return "MEDIUM_BLOB";
|
||||
case MYSQL_TYPE_NEWDATE: return "NEWDATE";
|
||||
case MYSQL_TYPE_NULL: return "NULL";
|
||||
case MYSQL_TYPE_SET: return "SET";
|
||||
case MYSQL_TYPE_SHORT: return "SHORT";
|
||||
case MYSQL_TYPE_STRING: return "STRING";
|
||||
case MYSQL_TYPE_TIME: return "TIME";
|
||||
case MYSQL_TYPE_TIMESTAMP: return "TIMESTAMP";
|
||||
case MYSQL_TYPE_TINY: return "TINY";
|
||||
case MYSQL_TYPE_TINY_BLOB: return "TINY_BLOB";
|
||||
case MYSQL_TYPE_VAR_STRING: return "VAR_STRING";
|
||||
case MYSQL_TYPE_YEAR: return "YEAR";
|
||||
default: return "-Unknown-";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
877
src/common/Database/Implementation/CharacterDatabase.cpp
Normal file
877
src/common/Database/Implementation/CharacterDatabase.cpp
Normal file
@@ -0,0 +1,877 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "CharacterDatabase.h"
|
||||
|
||||
void CharacterDatabaseConnection::DoPrepareStatements()
|
||||
{
|
||||
if (!m_reconnecting)
|
||||
m_stmts.resize(MAX_CHARACTERDATABASE_STATEMENTS);
|
||||
|
||||
#define SelectItemInstanceContent "ii.guid, ii.itemEntry, ii.creatorGuid, ii.giftCreatorGuid, ii.count, ii.duration, ii.charges, ii.flags, ii.enchantments, ii.randomPropertyType, ii.randomPropertyId, " \
|
||||
"ii.durability, ii.playedTime, ii.text, ii.upgradeId, ii.battlePetSpeciesId, ii.battlePetBreedData, ii.battlePetLevel, ii.battlePetDisplayId, ii.bonusListIDs, " \
|
||||
"iit.itemModifiedAppearanceAllSpecs, iit.itemModifiedAppearanceSpec1, iit.itemModifiedAppearanceSpec2, iit.itemModifiedAppearanceSpec3, iit.itemModifiedAppearanceSpec4, " \
|
||||
"iit.spellItemEnchantmentAllSpecs, iit.spellItemEnchantmentSpec1, iit.spellItemEnchantmentSpec2, iit.spellItemEnchantmentSpec3, iit.spellItemEnchantmentSpec4, " \
|
||||
"ig.gemItemId1, ig.gemBonuses1, ig.gemContext1, ig.gemScalingLevel1, ig.gemItemId2, ig.gemBonuses2, ig.gemContext2, ig.gemScalingLevel2, ig.gemItemId3, ig.gemBonuses3, ig.gemContext3, ig.gemScalingLevel3, " \
|
||||
"im.fixedScalingLevel, im.artifactKnowledgeLevel, iia.xp, iia.artifactAppearanceId, iia.tier, ii.dungeonEncounterID, ii.contextID, ii.createdTime"
|
||||
|
||||
PrepareStatement(CHAR_DEL_QUEST_POOL_SAVE, "DELETE FROM pool_quest_save WHERE pool_id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_QUEST_POOL_SAVE, "INSERT INTO pool_quest_save (pool_id, quest_id) VALUES (?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_NONEXISTENT_GUILD_BANK_ITEM, "DELETE FROM guild_bank_item WHERE guildid = ? AND TabId = ? AND SlotId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_EXPIRED_BANS, "UPDATE character_banned SET active = 0 WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate <> bandate", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_GUID_BY_NAME, "SELECT guid FROM characters WHERE BINARY name = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_SEL_CHECK_NAME, "SELECT 1 FROM characters WHERE BINARY name = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_SEL_CHECK_GUID, "SELECT 1 FROM characters WHERE guid = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_SEL_SUM_CHARS, "SELECT COUNT(guid) FROM characters WHERE account = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_SEL_CHAR_CREATE_INFO, "SELECT level, race, class FROM characters WHERE account = ? LIMIT 0, ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHARACTER_BAN, "INSERT INTO character_banned VALUES (?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+?, ?, ?, 1)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHARACTER_BAN, "UPDATE character_banned SET active = 0 WHERE guid = ? AND active != 0", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_BAN, "DELETE cb FROM character_banned cb INNER JOIN characters c ON c.guid = cb.guid WHERE c.account = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_BANINFO, "SELECT FROM_UNIXTIME(bandate), unbandate-bandate, active, unbandate, banreason, bannedby FROM character_banned WHERE guid = ? ORDER BY bandate ASC", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_GUID_BY_NAME_FILTER, "SELECT guid, name FROM characters WHERE name LIKE CONCAT('%%', ?, '%%')", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_BANINFO_LIST, "SELECT bandate, unbandate, bannedby, banreason FROM character_banned WHERE guid = ? ORDER BY unbandate", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_BANNED_NAME, "SELECT characters.name FROM characters, character_banned WHERE character_banned.guid = ? AND character_banned.guid = characters.guid", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_MAIL_LIST_COUNT, "SELECT COUNT(id) FROM mail WHERE receiver = ? ", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_MAIL_LIST_INFO, "SELECT id, sender, (SELECT name FROM characters WHERE guid = sender) AS sendername, receiver, (SELECT name FROM characters WHERE guid = receiver) AS receivername,"
|
||||
"SUBJECT, deliver_time, expire_time, money, has_items FROM mail WHERE receiver = ? ", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_MAIL_LIST_ITEMS, "SELECT itemEntry,count FROM item_instance WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_ENUM, "SELECT c.guid, c.name, c.race, c.class, c.skin, c.face, c.hairStyle, c.hairColor, c.facialStyle, c.blindfold, c.gender, c.tattoo, c.horn, c.level, c.zone, c.map, c.position_x, c.position_y, c.position_z, gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, cb.guid, c.slot, c.logout_time, c.specialization FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.id = c.currentpetnumber 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 = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_ENUM_DELETED, "SELECT c.guid, c.name, c.race, c.class, c.skin, c.face, c.hairStyle, c.hairColor, c.facialStyle, c.blindfold, c.gender, c.tattoo, c.horn, c.level, c.zone, c.map, c.position_x, c.position_y, c.position_z, gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, cb.guid, c.slot, c.logout_time, c.specialization FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.id = c.currentpetnumber 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.deleteInfos_Account = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_ENUM_DECLINED_NAME, "SELECT c.guid, c.name, c.race, c.class, c.skin, c.face, c.hairStyle, c.hairColor, c.facialStyle, c.blindfold, c.gender, c.tattoo, c.horn, c.level, c.zone, c.map, c.position_x, c.position_y, c.position_z, gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, cb.guid, c.slot, cd.genitive, c.logout_time, c.specialization FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.id = c.currentpetnumber 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 = ?", CONNECTION_ASYNC);
|
||||
|
||||
// Pet
|
||||
PrepareStatement(CHAR_INS_PET, "REPLACE INTO character_pet (id, entry, owner, modelid, level, exp, Reactstate, name, renamed, curhealth, curmana, abdata, savetime, CreatedBySpell, PetType, specialization) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_PET_DETAIL, "SELECT id, entry, level, name, modelid FROM character_pet WHERE owner = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_PET_BY_ID, "SELECT entry, id, PetType FROM character_pet WHERE owner = ? AND id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_PET, "SELECT `id`, `entry`, `owner`, `modelid`, `level`, `exp`, `Reactstate`, `name`, `renamed`, `curhealth`, `curmana`, `abdata`, `savetime`, `CreatedBySpell`, `PetType`, `specialization` FROM character_pet WHERE `owner` = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_PET_BY_ID, "DELETE FROM character_pet WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_PET_DECLINED_BY_ID, "DELETE FROM character_pet_declinedname WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_PET_AURA_BY_ID, "DELETE FROM pet_aura WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_PET_SPELL_BY_ID, "DELETE FROM pet_spell WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_PET_SPELL_COOLDOWN_BY_ID, "DELETE FROM pet_spell_cooldown WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_INVALID_PET_SPELL, "DELETE FROM pet_spell WHERE spell = ?", 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_GUID_RACE_ACC_BY_NAME, "SELECT guid, race, account FROM characters WHERE BINARY name = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_SEL_CHAR_RACE, "SELECT race FROM characters WHERE guid = ?", CONNECTION_SYNCH);
|
||||
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);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_NAME_DATA, "SELECT race, class, gender, level FROM characters WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHAR_POSITION_XYZ, "SELECT map, position_x, position_y, position_z FROM characters WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHAR_POSITION, "SELECT position_x, position_y, position_z, orientation, map, taxi_path FROM characters WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_DEL_QUEST_STATUS_DAILY, "DELETE FROM character_queststatus_daily", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_QUEST_STATUS_WEEKLY, "TRUNCATE character_queststatus_weekly", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_QUEST_STATUS_SEASONAL, "DELETE FROM character_queststatus_seasonal WHERE event = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_QUEST_STATUS_DAILY_CHAR, "DELETE FROM character_queststatus_daily WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_QUEST_STATUS_DAILY_ACC, "DELETE FROM character_queststatus_daily WHERE guid = 0 AND account = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_QUEST_STATUS_WEEKLY_CHAR, "DELETE FROM character_queststatus_weekly WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_QUEST_STATUS_WEEKLY_ACC, "DELETE FROM character_queststatus_weekly WHERE guid = 0 AND account = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_QUEST_STATUS_SEASONAL_CHAR, "DELETE FROM character_queststatus_seasonal WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_QUEST_STATUS_SEASONAL_ACC, "DELETE FROM character_queststatus_seasonal WHERE guid = 0 AND account = ?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_DEL_QUEST_STATUS_C, "DELETE FROM character_queststatus_rewarded WHERE guid = ? AND quest = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_QUEST_STATUS_DAILY_C, "DELETE FROM character_queststatus_daily WHERE guid = ? AND quest = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_QUEST_STATUS_WEEKLY_C, "DELETE FROM character_queststatus_weekly WHERE guid = ? AND quest = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_QUEST_STATUS_SEASONAL_C, "DELETE FROM character_queststatus_seasonal WHERE guid = ? AND quest = ?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_DEL_BATTLEGROUND_RANDOM, "DELETE FROM character_battleground_random", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_BATTLEGROUND_RANDOM, "REPLACE INTO character_battleground_random (guid, bg, rbg, arena2v2, arena3v3, skirmish, brawl, brawlArena) VALUES (?,?,?,?,?,?,?,?)", CONNECTION_ASYNC);
|
||||
|
||||
// Start LoginQueryHolder content
|
||||
PrepareStatement(CHAR_SEL_CHARACTER, "SELECT guid, account, name, race, class, level, xp, money, skin, face, hairStyle, hairColor, facialStyle, blindfold, gender, tattoo, horn, inventorySlots, bankSlots, drunk, playerFlags, "
|
||||
"playerFlagsEx, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, "
|
||||
"trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, at_login, zone, online, death_expire_time, taxi_path, dungeonDifficulty, "
|
||||
"totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, "
|
||||
"health, mana, instance_id, activespec, specialization, lootspecialization, exploredZones, equipmentCache, knownTitles, actionBars, "
|
||||
"currentpetnumber, petslot, grantableLevels, lfgBonusFaction, raidDifficulty, legacyRaidDifficulty, created_time, killPoints FROM characters WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_GROUP_MEMBER, "SELECT guid FROM group_member WHERE memberGuid = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_AURAS, "SELECT caster_guid, slot, spell, effect_mask, recalculate_mask, stackcount, maxduration, remaintime, remaincharges FROM character_aura WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_AURAS_EFFECTS, "SELECT slot, effect, baseamount, amount FROM character_aura_effect WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_SPELL, "SELECT spell, active, disabled FROM character_spell WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS, "SELECT quest, status, timer, guid FROM character_queststatus WHERE account = ? AND status <> 0 AND (guid = 0 OR guid = ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_OBJECTIVES, "SELECT quest, objective, data FROM character_queststatus_objectives WHERE account = ? AND (guid = 0 OR guid = ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_DAILYQUESTSTATUS, "SELECT quest, time, guid FROM character_queststatus_daily WHERE account = ? AND (guid = 0 OR guid = ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_WEEKLYQUESTSTATUS, "SELECT quest, guid FROM character_queststatus_weekly WHERE account = ? AND (guid = 0 OR guid = ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_SEASONALQUESTSTATUS, "SELECT quest, event, guid FROM character_queststatus_seasonal WHERE account = ? AND (guid = 0 OR guid = ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHARACTER_DAILYQUESTSTATUS, "REPLACE INTO character_queststatus_daily (guid, quest, time, account) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHARACTER_WEEKLYQUESTSTATUS, "REPLACE INTO character_queststatus_weekly (guid, quest, account) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHARACTER_SEASONALQUESTSTATUS, "REPLACE INTO character_queststatus_seasonal (guid, quest, event, account) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_REPUTATION, "SELECT faction, standing, flags FROM character_reputation WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_INVENTORY, "SELECT " SelectItemInstanceContent ", bag, slot, ii.isdonateitem FROM character_inventory ci JOIN item_instance ii ON ci.item = ii.guid "
|
||||
"LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid "
|
||||
"LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid "
|
||||
"LEFT JOIN item_instance_artifact iia ON ii.itemEntry = iia.itemEntry and ci.guid = iia.char_guid "
|
||||
"LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid WHERE ci.guid = ? ORDER BY bag, slot", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_NOT_INVENTORY, "SELECT " SelectItemInstanceContent ", ii.isdonateitem FROM item_instance ii "
|
||||
"LEFT JOIN character_inventory ci ON ci.item = ii.guid "
|
||||
"LEFT JOIN mail_items mi ON mi.item_guid = ii.guid "
|
||||
"LEFT JOIN auctionhouse ah ON ah.itemguid = ii.guid "
|
||||
"LEFT JOIN character_void_storage cvs ON cvs.itemGuid = ii.guid "
|
||||
"LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid "
|
||||
"LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid "
|
||||
"LEFT JOIN item_instance_artifact iia ON ii.itemEntry = iia.itemEntry and ii.owner_guid = iia.char_guid "
|
||||
"LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid WHERE ii.owner_guid = ? AND ci.item IS NULL AND mi.item_guid IS NULL AND cvs.itemGuid IS NULL AND ah.itemguid IS NULL", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_ITEM_INFO, "SELECT " SelectItemInstanceContent " FROM item_instance ii "
|
||||
"LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid "
|
||||
"LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid "
|
||||
"LEFT JOIN item_instance_artifact iia ON ii.itemEntry = iia.itemEntry and ii.owner_guid = iia.char_guid "
|
||||
"LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid WHERE ii.guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_ACTIONS, "SELECT a.button, a.action, a.type FROM character_action as a, characters as c WHERE a.guid = c.guid AND a.spec = c.activespec AND a.guid = ? ORDER BY button", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_MAILCOUNT, "SELECT COUNT(id) FROM mail WHERE receiver = ? AND (checked & 1) = 0 AND deliver_time <= ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_MAILDATE, "SELECT MIN(deliver_time) FROM mail WHERE receiver = ? AND (checked & 1) = 0", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_MAIL_COUNT, "SELECT COUNT(*) FROM mail WHERE receiver = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_SOCIALLIST, "SELECT friend, flags, note FROM character_social JOIN characters ON characters.guid = character_social.friend WHERE character_social.guid = ? AND deleteinfos_name IS NULL LIMIT 255", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_HOMEBIND, "SELECT mapId, zoneId, posX, posY, posZ FROM character_homebind WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_SPELLCOOLDOWNS, "SELECT spell, item, time FROM character_spell_cooldown WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_DECLINEDNAMES, "SELECT genitive, dative, accusative, instrumental, prepositional FROM character_declinedname WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_GUILD_MEMBER, "SELECT guildid, rank FROM guild_member WHERE guid = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_ACHIEVEMENTS, "SELECT achievement, date FROM character_achievement WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_ACCOUNT_ACHIEVEMENTS, "SELECT first_guid, achievement, date FROM account_achievement WHERE account = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_CRITERIAPROGRESS, "SELECT criteria, counter, date, achievID, completed FROM character_achievement_progress WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_ACCOUNT_CRITERIAPROGRESS, "SELECT criteria, counter, date, achievID, completed FROM account_achievement_progress WHERE account = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_BGDATA, "SELECT instanceId, team, joinX, joinY, joinZ, joinO, joinMapId, taxiStart, taxiEnd, mountSpell, lastActiveSpec FROM character_battleground_data WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_GLYPHS, "SELECT talentGroup, glyphId FROM character_glyphs WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_TALENTS, "SELECT talent, spec FROM character_talent WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_PVP_TALENTS, "SELECT talent, spec FROM character_pvp_talent WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_SKILLS, "SELECT skill, value, max FROM character_skills WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_RANDOMBG, "SELECT bg, rbg, arena2v2, arena3v3, skirmish, brawl, brawlArena FROM character_battleground_random WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_BANNED, "SELECT guid FROM character_banned WHERE guid = ? AND active = 1", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUSREW, "SELECT quest, guid FROM character_queststatus_rewarded WHERE account = ? AND (guid = 0 OR guid = ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_ACCOUNT_QUEST, "SELECT quest FROM character_queststatus_rewarded WHERE account = ? GROUP BY quest", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUSREW_NON_ACC, "SELECT quest, guid FROM character_queststatus_rewarded WHERE account = ? AND guid = ?", CONNECTION_SYNCH);
|
||||
// End LoginQueryHolder content
|
||||
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_ACTIONS_SPEC, "SELECT button, action, type FROM character_action WHERE guid = ? AND spec = ? ORDER BY button", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_MAILITEMS, "SELECT " SelectItemInstanceContent ", ii.owner_guid FROM mail_items mi JOIN item_instance ii ON mi.item_guid = ii.guid "
|
||||
"LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid "
|
||||
"LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid "
|
||||
"LEFT JOIN item_instance_artifact iia ON ii.itemEntry = iia.itemEntry and ii.owner_guid = iia.char_guid "
|
||||
"LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid WHERE mail_id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_AUCTION_ITEMS, "SELECT " SelectItemInstanceContent " FROM auctionhouse ah JOIN item_instance ii ON ah.itemguid = ii.guid "
|
||||
"LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid "
|
||||
"LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid "
|
||||
"LEFT JOIN item_instance_artifact iia ON ii.itemEntry = iia.itemEntry and ii.owner_guid = iia.char_guid "
|
||||
"LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_AUCTIONS, "SELECT id, auctioneerguid, itemguid, itemEntry, count, itemowner, buyoutprice, time, buyguid, lastbid, startbid, deposit FROM auctionhouse ah INNER JOIN item_instance ii ON ii.guid = ah.itemguid", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_INS_AUCTION, "INSERT INTO auctionhouse (id, auctioneerguid, itemguid, itemowner, buyoutprice, time, buyguid, lastbid, startbid, deposit) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_AUCTION, "DELETE FROM auctionhouse WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_AUCTION_BY_TIME, "SELECT id FROM auctionhouse WHERE time <= ? ORDER BY TIME ASC", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_UPD_AUCTION_BID, "UPDATE auctionhouse SET buyguid = ?, lastbid = ? WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_MAIL, "INSERT INTO mail(id, messageType, stationery, mailTemplateId, sender, receiver, subject, body, has_items, expire_time, deliver_time, money, cod, checked) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_MAIL_BY_ID, "DELETE FROM mail WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_MAIL_ITEM, "REPLACE INTO mail_items(mail_id, item_guid, receiver) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_MAIL_ITEM, "DELETE FROM mail_items WHERE item_guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_INVALID_MAIL_ITEM, "DELETE FROM mail_items WHERE item_guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_EMPTY_EXPIRED_MAIL, "DELETE FROM mail WHERE expire_time < ? AND has_items = 0 AND body = ''", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_EXPIRED_MAIL, "SELECT id, messageType, sender, receiver, has_items, expire_time, cod, checked, mailTemplateId FROM mail WHERE expire_time < ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_EXPIRED_MAIL_ITEMS, "SELECT item_guid, itemEntry, mail_id FROM mail_items mi INNER JOIN item_instance ii ON ii.guid = mi.item_guid LEFT JOIN mail mm ON mi.mail_id = mm.id WHERE mm.id IS NOT NULL AND mm.expire_time < ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_UPD_MAIL_RETURNED, "UPDATE mail SET sender = ?, receiver = ?, expire_time = ?, deliver_time = ?, cod = 0, checked = ? WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_MAIL_ITEM_RECEIVER, "UPDATE mail_items SET receiver = ? WHERE item_guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_ITEM_OWNER, "UPDATE item_instance SET owner_guid = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_ITEM_REFUNDS, "SELECT player_guid, paidMoney, paidExtendedCost FROM item_refund_instance WHERE item_guid = ? AND player_guid = ? LIMIT 1", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_ITEM_BOP_TRADE, "SELECT allowedPlayers FROM item_soulbound_trade_data WHERE itemGuid = ? LIMIT 1", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_DEL_ITEM_BOP_TRADE, "DELETE FROM item_soulbound_trade_data WHERE itemGuid = ? LIMIT 1", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_ITEM_BOP_TRADE, "INSERT INTO item_soulbound_trade_data VALUES (?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_INVENTORY_ITEM, "REPLACE INTO character_inventory (guid, bag, slot, item) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_ITEM_INSTANCE, "REPLACE INTO item_instance (itemEntry, owner_guid, creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyType, randomPropertyId, durability, playedTime, text, upgradeId, battlePetSpeciesId, battlePetBreedData, battlePetLevel, battlePetDisplayId, bonusListIDs, itemLevel, dungeonEncounterID, contextID, createdTime, isdonateitem, guid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_ITEM_INSTANCE, "UPDATE item_instance SET itemEntry = ?, owner_guid = ?, creatorGuid = ?, giftCreatorGuid = ?, count = ?, duration = ?, charges = ?, flags = ?, enchantments = ?, randomPropertyType = ?, randomPropertyId = ?, durability = ?, playedTime = ?, text = ?, upgradeId = ?, battlePetSpeciesId = ?, battlePetBreedData = ?, battlePetLevel = ?, battlePetDisplayId = ?, bonusListIDs = ?, itemLevel = ?, dungeonEncounterID = ?, contextID = ?, isdonateitem = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_ITEM_INSTANCE_ON_LOAD, "UPDATE item_instance SET duration = ?, flags = ?, durability = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ITEM_INSTANCE, "DELETE FROM item_instance WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_ITEM_INSTANCE_GEMS, "REPLACE INTO item_instance_gems (itemGuid, gemItemId1, gemBonuses1, gemContext1, gemScalingLevel1, gemItemId2, gemBonuses2, gemContext2, gemScalingLevel2, gemItemId3, gemBonuses3, gemContext3, gemScalingLevel3) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ITEM_INSTANCE_GEMS, "DELETE FROM item_instance_gems WHERE itemGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ITEM_INSTANCE_GEMS_BY_OWNER, "DELETE iig FROM item_instance_gems iig LEFT JOIN item_instance ii ON iig.itemGuid = ii.guid WHERE ii.owner_guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_ITEM_INSTANCE_TRANSMOG, "INSERT INTO item_instance_transmog (itemGuid, itemModifiedAppearanceAllSpecs, itemModifiedAppearanceSpec1, itemModifiedAppearanceSpec2, itemModifiedAppearanceSpec3, itemModifiedAppearanceSpec4, spellItemEnchantmentAllSpecs, spellItemEnchantmentSpec1, spellItemEnchantmentSpec2, spellItemEnchantmentSpec3, spellItemEnchantmentSpec4) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ITEM_INSTANCE_TRANSMOG, "DELETE FROM item_instance_transmog WHERE itemGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ITEM_INSTANCE_TRANSMOG_BY_OWNER, "DELETE iit FROM item_instance_transmog iit LEFT JOIN item_instance ii ON iit.itemGuid = ii.guid WHERE ii.owner_guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GIFT_OWNER, "UPDATE character_gifts SET guid = ? WHERE item_guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GIFT, "DELETE FROM character_gifts WHERE item_guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_GIFT_BY_ITEM, "SELECT entry, flags FROM character_gifts WHERE item_guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_ACCOUNT_BY_NAME, "SELECT account FROM characters WHERE BINARY name = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_ACCOUNT_BY_GUID, "SELECT account FROM characters WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_ACCOUNT_NAME_BY_GUID, "SELECT account, name FROM characters WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_NAME_CLASS, "SELECT name, class FROM characters WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_NAME, "SELECT name FROM characters WHERE guid = ?", 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_LOG, "INSERT INTO log_rename (`guid`, `date`, `oldName`, `newName`) VALUES (?, NOW(), ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
// Guild handling
|
||||
// 0: uint32, 1: string, 2: uint32, 3: string, 4: string, 5: uint64, 6-10: uint32, 11: uint64
|
||||
PrepareStatement(CHAR_INS_GUILD, "INSERT INTO guild (guildid, name, leaderguid, flags, info, motd, createdate, EmblemStyle, EmblemColor, BorderStyle, BorderColor, BackgroundColor, BankMoney, level) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GUILD, "DELETE FROM guild WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32
|
||||
// 0: uint32, 1: uint32, 2: uint8, 4: string, 5: string
|
||||
PrepareStatement(CHAR_INS_GUILD_MEMBER, "INSERT INTO guild_member (guildid, guid, rank, pnote, offnote) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GUILD_MEMBER, "DELETE FROM guild_member WHERE guid = ?", CONNECTION_ASYNC); // 0: uint32
|
||||
PrepareStatement(CHAR_DEL_GUILD_MEMBERS, "DELETE FROM guild_member WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBERS_RANK, "UPDATE guild_member SET rank = ? WHERE guildid = ? AND rank = ?", CONNECTION_ASYNC); // 0: uint32
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_STATS, "UPDATE guild_member SET AchPoint = ?, profId1 = ?, profValue1 = ?, profRank1 = ?, recipesMask1 = ?, profId2 = ?, profValue2 = ?, profRank2 = ?, recipesMask2 = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
// 0: uint32, 1: uint8, 3: string, 4: uint32
|
||||
PrepareStatement(CHAR_INS_GUILD_RANK, "INSERT INTO guild_rank (guildid, rid, rname, rights) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GUILD_RANKS, "DELETE FROM guild_rank WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32
|
||||
PrepareStatement(CHAR_DEL_GUILD_RANK, "DELETE FROM guild_rank WHERE guildid = ? AND rid = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint8
|
||||
PrepareStatement(CHAR_UPD_GUILD_RANK_ID, "UPDATE guild_rank SET rid = ? WHERE guildid = ? AND rid = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint8
|
||||
PrepareStatement(CHAR_INS_GUILD_BANK_TAB, "INSERT INTO guild_bank_tab (guildid, TabId) VALUES (?, ?)", CONNECTION_ASYNC); // 0: uint32, 1: uint8
|
||||
PrepareStatement(CHAR_DEL_GUILD_BANK_TAB, "DELETE FROM guild_bank_tab WHERE guildid = ? AND TabId = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint8
|
||||
PrepareStatement(CHAR_DEL_GUILD_BANK_TABS, "DELETE FROM guild_bank_tab WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32
|
||||
// 0: uint32, 1: uint8, 2: uint8, 3: uint32, 4: uint32
|
||||
PrepareStatement(CHAR_INS_GUILD_BANK_ITEM, "INSERT INTO guild_bank_item (guildid, TabId, SlotId, item_guid) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GUILD_BANK_ITEM, "DELETE FROM guild_bank_item WHERE guildid = ? AND TabId = ? AND SlotId = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint8, 2: uint8
|
||||
PrepareStatement(CHAR_DEL_GUILD_BANK_ITEMS, "DELETE FROM guild_bank_item WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32
|
||||
PrepareStatement(CHAR_SEL_GUILD_BANK_ITEMS, "SELECT " SelectItemInstanceContent ", guildid, TabId, SlotId FROM guild_bank_item gbi INNER JOIN item_instance ii ON gbi.item_guid = ii.guid "
|
||||
"LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid "
|
||||
"LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid "
|
||||
"LEFT JOIN item_instance_artifact iia ON ii.itemEntry = iia.itemEntry and ii.owner_guid = iia.char_guid "
|
||||
"LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_INS_GUILD_BANK_RIGHT_DEFAULT, "INSERT INTO guild_bank_right (guildid, TabId, rid) VALUES (?, ?, ?)", CONNECTION_ASYNC); // 0: uint32, 1: uint8, 2: uint8
|
||||
// 0: uint32, 1: uint8, 2: uint8, 3: uint8, 4: uint32
|
||||
PrepareStatement(CHAR_INS_GUILD_BANK_RIGHT, "INSERT INTO guild_bank_right (guildid, TabId, rid, gbright, SlotPerDay) VALUES (?, ?, ?, ?, ?) "
|
||||
"ON DUPLICATE KEY UPDATE gbright = VALUES(gbright), SlotPerDay = VALUES(SlotPerDay)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GUILD_BANK_RIGHT, "DELETE FROM guild_bank_right WHERE guildid = ? AND TabId = ? AND rid = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint8, 2: uint8
|
||||
PrepareStatement(CHAR_DEL_GUILD_BANK_RIGHTS, "DELETE FROM guild_bank_right WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32
|
||||
PrepareStatement(CHAR_DEL_GUILD_BANK_RIGHTS_FOR_RANK, "DELETE FROM guild_bank_right WHERE guildid = ? AND rid = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint8
|
||||
PrepareStatement(CHAR_UPD_GUILD_BANK_RIGHTS_ID, "UPDATE guild_bank_right SET rid = ? WHERE guildid = ? AND rid = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint8
|
||||
// 0-1: uint32, 2-3: uint8, 4-5: uint32, 6: uint16, 7: uint8, 8: uint64
|
||||
PrepareStatement(CHAR_INS_GUILD_BANK_EVENTLOG, "INSERT INTO guild_bank_eventlog (guildid, LogGuid, TabId, EventType, PlayerGuid, ItemOrMoney, ItemStackCount, DestTabId, TimeStamp) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GUILD_BANK_EVENTLOG, "DELETE FROM guild_bank_eventlog WHERE guildid = ? AND LogGuid = ? AND TabId = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint32, 2: uint8
|
||||
PrepareStatement(CHAR_DEL_GUILD_BANK_EVENTLOGS, "DELETE FROM guild_bank_eventlog WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32
|
||||
// 0-1: uint32, 2: uint8, 3-4: uint32, 5: uint8, 6: uint64
|
||||
PrepareStatement(CHAR_INS_GUILD_EVENTLOG, "INSERT INTO guild_eventlog (guildid, LogGuid, EventType, PlayerGuid1, PlayerGuid2, NewRank, TimeStamp) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GUILD_EVENTLOG, "DELETE FROM guild_eventlog WHERE guildid = ? AND LogGuid = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint32
|
||||
PrepareStatement(CHAR_DEL_GUILD_EVENTLOGS, "DELETE FROM guild_eventlog WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_PNOTE, "UPDATE guild_member SET pnote = ? WHERE guid = ?", CONNECTION_ASYNC); // 0: string, 1: uint32
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_OFFNOTE, "UPDATE guild_member SET offnote = ? WHERE guid = ?", CONNECTION_ASYNC); // 0: string, 1: uint32
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_RANK, "UPDATE guild_member SET rank = ? WHERE guid = ?", CONNECTION_ASYNC); // 0: uint8, 1: uint32
|
||||
PrepareStatement(CHAR_UPD_GUILD_NAME, "UPDATE guild SET name = ? WHERE guildid = ?", CONNECTION_ASYNC); // 0: string, 1: uint32
|
||||
PrepareStatement(CHAR_UPD_GUILD_MOTD, "UPDATE guild SET motd = ? WHERE guildid = ?", CONNECTION_ASYNC); // 0: string, 1: uint32
|
||||
PrepareStatement(CHAR_UPD_GUILD_INFO, "UPDATE guild SET info = ? WHERE guildid = ?", CONNECTION_ASYNC); // 0: string, 1: uint32
|
||||
PrepareStatement(CHAR_UPD_GUILD_FLAGS, "UPDATE guild SET flags = ? WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint32
|
||||
PrepareStatement(CHAR_UPD_GUILD_LEADER, "UPDATE guild SET leaderguid = ? WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint32
|
||||
PrepareStatement(CHAR_UPD_GUILD_RANK_NAME, "UPDATE guild_rank SET rname = ? WHERE rid = ? AND guildid = ?", CONNECTION_ASYNC); // 0: string, 1: uint8, 2: uint32
|
||||
PrepareStatement(CHAR_UPD_GUILD_RANK_RIGHTS, "UPDATE guild_rank SET rights = ? WHERE rid = ? AND guildid = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint8, 2: uint32
|
||||
// 0-5: uint32
|
||||
PrepareStatement(CHAR_UPD_GUILD_EMBLEM_INFO, "UPDATE guild SET EmblemStyle = ?, EmblemColor = ?, BorderStyle = ?, BorderColor = ?, BackgroundColor = ? WHERE guildid = ?", CONNECTION_ASYNC);
|
||||
// 0: string, 1: string, 2: uint32, 3: uint8
|
||||
PrepareStatement(CHAR_UPD_GUILD_BANK_TAB_INFO, "UPDATE guild_bank_tab SET TabName = ?, TabIcon = ? WHERE guildid = ? AND TabId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_BANK_MONEY, "UPDATE guild SET BankMoney = ? WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint64, 1: uint32
|
||||
// 0: uint8, 1: uint32, 2: uint8, 3: uint32
|
||||
PrepareStatement(CHAR_UPD_GUILD_BANK_EVENTLOG_TAB, "UPDATE guild_bank_eventlog SET TabId = ? WHERE guildid = ? AND TabId = ? AND LogGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_BANK_REM_MONEY, "UPDATE guild_member SET BankRemMoney = ? WHERE guildid = ? AND guid = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint32, 2: uint32
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_BANK_TIME_MONEY, "UPDATE guild_member SET BankResetTimeMoney = ?, BankRemMoney = ? WHERE guildid = ? AND guid = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint32, 2: uint32, 3: uint32
|
||||
PrepareStatement(CHAR_UPD_GUILD_RANK_BANK_RESET_TIME, "UPDATE guild_member SET BankResetTimeMoney = 0 WHERE guildid = ? AND rank = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint8
|
||||
PrepareStatement(CHAR_UPD_GUILD_RANK_BANK_MONEY, "UPDATE guild_rank SET BankMoneyPerDay = ? WHERE rid = ? AND guildid = ?", CONNECTION_ASYNC); // 0: uint32, 1: uint8, 2: uint32
|
||||
PrepareStatement(CHAR_UPD_GUILD_BANK_TAB_TEXT, "UPDATE guild_bank_tab SET TabText = ? WHERE guildid = ? AND TabId = ?", CONNECTION_ASYNC); // 0: string, 1: uint32, 2: uint8
|
||||
// 0: uint32, 1: uint32, 2: uint32
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_BANK_REM_SLOTS0, "UPDATE guild_member SET BankRemSlotsTab0 = ? WHERE guildid = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_BANK_REM_SLOTS1, "UPDATE guild_member SET BankRemSlotsTab1 = ? WHERE guildid = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_BANK_REM_SLOTS2, "UPDATE guild_member SET BankRemSlotsTab2 = ? WHERE guildid = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_BANK_REM_SLOTS3, "UPDATE guild_member SET BankRemSlotsTab3 = ? WHERE guildid = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_BANK_REM_SLOTS4, "UPDATE guild_member SET BankRemSlotsTab4 = ? WHERE guildid = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_BANK_REM_SLOTS5, "UPDATE guild_member SET BankRemSlotsTab5 = ? WHERE guildid = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_BANK_REM_SLOTS6, "UPDATE guild_member SET BankRemSlotsTab6 = ? WHERE guildid = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_BANK_REM_SLOTS7, "UPDATE guild_member SET BankRemSlotsTab7 = ? WHERE guildid = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
// 0: uint32, 1: uint32, 2: uint32, 3: uint32
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_BANK_TIME_REM_SLOTS0, "UPDATE guild_member SET BankResetTimeTab0 = ?, BankRemSlotsTab0 = ? WHERE guildid = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_BANK_TIME_REM_SLOTS1, "UPDATE guild_member SET BankResetTimeTab1 = ?, BankRemSlotsTab1 = ? WHERE guildid = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_BANK_TIME_REM_SLOTS2, "UPDATE guild_member SET BankResetTimeTab2 = ?, BankRemSlotsTab2 = ? WHERE guildid = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_BANK_TIME_REM_SLOTS3, "UPDATE guild_member SET BankResetTimeTab3 = ?, BankRemSlotsTab3 = ? WHERE guildid = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_BANK_TIME_REM_SLOTS4, "UPDATE guild_member SET BankResetTimeTab4 = ?, BankRemSlotsTab4 = ? WHERE guildid = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_BANK_TIME_REM_SLOTS5, "UPDATE guild_member SET BankResetTimeTab5 = ?, BankRemSlotsTab5 = ? WHERE guildid = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_BANK_TIME_REM_SLOTS6, "UPDATE guild_member SET BankResetTimeTab6 = ?, BankRemSlotsTab6 = ? WHERE guildid = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_MEMBER_BANK_TIME_REM_SLOTS7, "UPDATE guild_member SET BankResetTimeTab7 = ?, BankRemSlotsTab7 = ? WHERE guildid = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
// 0: uint32, 1: uint8
|
||||
PrepareStatement(CHAR_UPD_GUILD_RANK_BANK_TIME0, "UPDATE guild_member SET BankResetTimeTab0 = 0 WHERE guildid = ? AND rank = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_RANK_BANK_TIME1, "UPDATE guild_member SET BankResetTimeTab1 = 0 WHERE guildid = ? AND rank = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_RANK_BANK_TIME2, "UPDATE guild_member SET BankResetTimeTab2 = 0 WHERE guildid = ? AND rank = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_RANK_BANK_TIME3, "UPDATE guild_member SET BankResetTimeTab3 = 0 WHERE guildid = ? AND rank = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_RANK_BANK_TIME4, "UPDATE guild_member SET BankResetTimeTab4 = 0 WHERE guildid = ? AND rank = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_RANK_BANK_TIME5, "UPDATE guild_member SET BankResetTimeTab5 = 0 WHERE guildid = ? AND rank = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_RANK_BANK_TIME6, "UPDATE guild_member SET BankResetTimeTab6 = 0 WHERE guildid = ? AND rank = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_RANK_BANK_TIME7, "UPDATE guild_member SET BankResetTimeTab7 = 0 WHERE guildid = ? AND rank = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHAR_DATA_FOR_GUILD, "SELECT name, level, class, zone, account, re.standing, gender FROM characters c LEFT JOIN character_reputation re ON re.guid = c.guid AND re.faction = 1168 WHERE c.guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_REP_GUILD_ACHIEVEMENT, "REPLACE INTO guild_achievement (guildId, achievement, date, guids) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_GUILD_ACHIEVEMENT_CRITERIA, "REPLACE INTO guild_achievement_progress (guildId, criteria, counter, date, completedGuid, achievID, completed) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GUILD_ACHIEVEMENT_CRITERIA, "UPDATE guild_achievement_progress SET counter = ?, `date` = ?, achievID = ?, completed = ? WHERE guildId = ? AND criteria = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GUILD_INVALID_ACHIEV_PROGRESS_CRITERIA, "DELETE FROM guild_achievement_progress WHERE criteria = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GUILD_ACHIEV_PROGRESS_CRITERIA, "DELETE FROM guild_achievement_progress WHERE criteria = ? AND guildId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ALL_GUILD_ACHIEVEMENTS, "DELETE FROM guild_achievement WHERE guildId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ALL_GUILD_ACHIEVEMENT_CRITERIA, "DELETE FROM guild_achievement_progress WHERE guildId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_GUILD_ACHIEVEMENT, "SELECT achievement, date, guids FROM guild_achievement WHERE guildId = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_GUILD_ACHIEVEMENT_CRITERIA, "SELECT criteria, counter, date, completedGuid, achievID, completed FROM guild_achievement_progress WHERE guildId = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_INS_GUILD_NEWS, "INSERT INTO guild_newslog (guildid, LogGuid, EventType, PlayerGuid, Flags, Value, Timestamp, Data) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
|
||||
" ON DUPLICATE KEY UPDATE LogGuid = VALUES (LogGuid), EventType = VALUES (EventType), PlayerGuid = VALUES (PlayerGuid), Flags = VALUES (Flags), Value = VALUES (Value), Timestamp = VALUES (Timestamp)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_LOAD_GUILD_CHALLENGES, "SELECT GuildId, ChallengeType, ChallengeCount FROM guild_challenges", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_INIT_GUILD_CHALLENGES, "INSERT INTO guild_challenges VALUES (?, ?, 0)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_COMPLETE_GUILD_CHALLENGE, "UPDATE guild_challenges SET ChallengeCount = ? WHERE GuildId = ? AND ChallengeType = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REMOVE_GUILD_CHALLENGES, "DELETE FROM guild_challenges WHERE GuildId = ?", CONNECTION_ASYNC);
|
||||
|
||||
// Archaelogy
|
||||
PrepareStatement(CHAR_SEL_PLAYER_ARCHAELOGY, "SELECT sites, counts, projects FROM character_archaeology WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_PLAYER_ARCHAEOLOGY_FINDS, "SELECT id, count, UNIX_TIMESTAMP(date) FROM character_archaeology_finds WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_PLAYER_ARCHAEOLOGY, "REPLACE INTO character_archaeology (guid, sites, counts, projects) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_PLAYER_ARCHAEOLOGY_FINDS, "REPLACE INTO character_archaeology_finds (guid, id, count, date) VALUES (?, ?, ?, FROM_UNIXTIME(?))", CONNECTION_ASYNC);
|
||||
|
||||
// Chat channel handling
|
||||
PrepareStatement(CHAR_SEL_CHANNEL, "SELECT announce, ownership, password, bannedList FROM channels WHERE name = ? AND team = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_INS_CHANNEL, "INSERT INTO channels(name, team, lastUsed) VALUES (?, ?, UNIX_TIMESTAMP())", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHANNEL, "UPDATE channels SET announce = ?, ownership = ?, password = ?, bannedList = ?, lastUsed = UNIX_TIMESTAMP() WHERE name = ? AND team = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHANNEL_USAGE, "UPDATE channels SET lastUsed = UNIX_TIMESTAMP() WHERE name = ? AND team = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHANNEL_OWNERSHIP, "UPDATE channels SET ownership = ? WHERE name LIKE ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_OLD_CHANNELS, "DELETE FROM channels WHERE ownership = 1 AND lastUsed + ? < UNIX_TIMESTAMP()", CONNECTION_ASYNC);
|
||||
|
||||
// Equipment sets
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_EQUIPMENTSETS, "SELECT setguid, setindex, name, iconname, ignore_mask, AssignedSpecIndex, item0, item1, item2, item3, item4, item5, item6, item7, item8, item9, item10, item11, item12, item13, item14, item15, item16, item17, item18 FROM character_equipmentsets WHERE guid = ? ORDER BY setindex", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_EQUIP_SET, "UPDATE character_equipmentsets SET name=?, iconname=?, ignore_mask=?, AssignedSpecIndex=?, item0=?, item1=?, item2=?, item3=?, item4=?, item5=?, item6=?, item7=?, item8=?, item9=?, item10=?, item11=?, item12=?, item13=?, item14=?, item15=?, item16=?, item17=?, item18=? WHERE guid=? AND setguid=? AND setindex=?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_EQUIP_SET, "INSERT INTO character_equipmentsets (guid, setguid, setindex, name, iconname, ignore_mask, AssignedSpecIndex, item0, item1, item2, item3, item4, item5, item6, item7, item8, item9, item10, item11, item12, item13, item14, item15, item16, item17, item18) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_EQUIP_SET, "DELETE FROM character_equipmentsets WHERE setguid=?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_TRANSMOG_OUTFITS, "SELECT setguid, setindex, name, iconname, ignore_mask, appearance0, appearance1, appearance2, appearance3, appearance4, appearance5, appearance6, appearance7, appearance8, appearance9, appearance10, appearance11, appearance12, appearance13, appearance14, appearance15, appearance16, appearance17, appearance18, mainHandEnchant, offHandEnchant FROM character_transmog_outfits WHERE guid = ? ORDER BY setindex", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_TRANSMOG_OUTFIT, "UPDATE character_transmog_outfits SET name=?, iconname=?, ignore_mask=?, appearance0=?, appearance1=?, appearance2=?, appearance3=?, appearance4=?, appearance5=?, appearance6=?, appearance7=?, appearance8=?, appearance9=?, appearance10=?, appearance11=?, appearance12=?, appearance13=?, appearance14=?, appearance15=?, appearance16=?, appearance17=?, appearance18=?, mainHandEnchant=?, offHandEnchant=? WHERE guid=? AND setguid=? AND setindex=?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_TRANSMOG_OUTFIT, "INSERT INTO character_transmog_outfits (guid, setguid, setindex, name, iconname, ignore_mask, appearance0, appearance1, appearance2, appearance3, appearance4, appearance5, appearance6, appearance7, appearance8, appearance9, appearance10, appearance11, appearance12, appearance13, appearance14, appearance15, appearance16, appearance17, appearance18, mainHandEnchant, offHandEnchant) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_TRANSMOG_OUTFIT, "DELETE FROM character_transmog_outfits WHERE setguid=?", CONNECTION_ASYNC);
|
||||
|
||||
// Auras
|
||||
PrepareStatement(CHAR_INS_AURA, "INSERT INTO character_aura (guid, slot, caster_guid, item_guid, spell, effect_mask, recalculate_mask, stackcount, maxduration, remaintime, remaincharges) "
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_INS_AURA_EFFECT, "INSERT INTO character_aura_effect (guid, slot, effect, baseamount, amount) "
|
||||
"VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
// Currency
|
||||
PrepareStatement(CHAR_SEL_PLAYER_CURRENCY, "SELECT currency, week_count, total_count, season_total, flags, curentcap FROM character_currency WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_PLAYER_CURRENCY, "UPDATE character_currency SET week_count = ?, total_count = ?, season_total = ?, flags = ?, curentcap = ? WHERE guid = ? AND currency = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_PLAYER_CURRENCY, "REPLACE INTO character_currency (guid, currency, week_count, total_count, season_total, flags, curentcap) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
|
||||
// Account data
|
||||
PrepareStatement(CHAR_SEL_ACCOUNT_DATA, "SELECT type, time, data FROM account_data WHERE accountId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_ACCOUNT_DATA, "REPLACE INTO account_data (accountId, type, time, data) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ACCOUNT_DATA, "DELETE FROM account_data WHERE accountId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_PLAYER_ACCOUNT_DATA, "SELECT type, time, data FROM character_account_data WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_PLAYER_ACCOUNT_DATA, "REPLACE INTO character_account_data(guid, type, time, data) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_PLAYER_ACCOUNT_DATA, "DELETE FROM character_account_data WHERE guid = ?", CONNECTION_ASYNC);
|
||||
|
||||
// Tutorials
|
||||
PrepareStatement(CHAR_SEL_TUTORIALS, "SELECT tut0, tut1, tut2, tut3, tut4, tut5, tut6, tut7 FROM account_tutorial WHERE accountId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_HAS_TUTORIALS, "SELECT 1 FROM account_tutorial WHERE accountId = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_INS_TUTORIALS, "INSERT INTO account_tutorial(tut0, tut1, tut2, tut3, tut4, tut5, tut6, tut7, accountId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_TUTORIALS, "UPDATE account_tutorial SET tut0 = ?, tut1 = ?, tut2 = ?, tut3 = ?, tut4 = ?, tut5 = ?, tut6 = ?, tut7 = ? WHERE accountId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_TUTORIALS, "DELETE FROM account_tutorial WHERE accountId = ?", CONNECTION_ASYNC);
|
||||
|
||||
// Instance saves char
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_INSTANCE, "SELECT instance, map, difficulty, permanent, completedEncounters, data, resetTime, Extended FROM character_instance WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_INSTANCE_BY_INSTANCE_GUID, "DELETE FROM character_instance WHERE guid = ? AND instance = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHAR_INSTANCE, "UPDATE character_instance SET instance = ?, permanent = ? WHERE guid = ? AND instance = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_CHAR_INSTANCE, "REPLACE INTO character_instance (guid, instance, map, difficulty, permanent, completedEncounters, data, resetTime, Extended) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_INSTANCE_BY_INSTANCE, "DELETE FROM character_instance WHERE instance = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_DEL_CHAR_INSTANCE_BY_MAP_DIFF, "DELETE FROM character_instance WHERE map = ? AND difficulty = ? AND Extended = 0 AND (resetTime + 2592000) <= ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_INSTANCE, "DELETE FROM character_instance WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHAR_INSTANCE_EXTENDED, "UPDATE character_instance SET Extended = 0, resetTime = ? WHERE map = ? AND difficulty = ? AND Extended = 1", CONNECTION_ASYNC);
|
||||
|
||||
// Instance saves group
|
||||
PrepareStatement(CHAR_DEL_GROUP_INSTANCE_BY_INSTANCE, "DELETE FROM group_instance WHERE instance = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_DEL_GROUP_INSTANCE_BY_GUID, "DELETE FROM group_instance WHERE guid = ? AND instance = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_GROUP_INSTANCE, "REPLACE INTO group_instance (guid, instance, map, difficulty, permanent, completedEncounters, data, resetTime) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GROUP_INSTANCE_BY_MAP_DIFF, "DELETE FROM group_instance WHERE map = ? AND difficulty = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GROUP_INSTANCE_PERM_BINDING, "DELETE FROM group_instance WHERE guid = ? AND (permanent = 1 OR instance IN (SELECT instance FROM character_instance WHERE guid = ?))", CONNECTION_ASYNC);
|
||||
|
||||
// Game event saves
|
||||
PrepareStatement(CHAR_DEL_GAME_EVENT_SAVE, "DELETE FROM game_event_save WHERE eventEntry = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_GAME_EVENT_SAVE, "INSERT INTO game_event_save (eventEntry, state, next_start) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
// Game event condition saves
|
||||
PrepareStatement(CHAR_DEL_ALL_GAME_EVENT_CONDITION_SAVE, "DELETE FROM game_event_condition_save WHERE eventEntry = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GAME_EVENT_CONDITION_SAVE, "DELETE FROM game_event_condition_save WHERE eventEntry = ? AND condition_id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_GAME_EVENT_CONDITION_SAVE, "INSERT INTO game_event_condition_save (eventEntry, condition_id, done) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
// Petitions
|
||||
PrepareStatement(CHAR_SEL_PETITION, "SELECT ownerguid, name FROM petition WHERE petitionguid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_PETITION_SIGNATURE, "SELECT playerguid FROM petition_sign WHERE petitionguid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_DEL_ALL_PETITION_SIGNATURES, "DELETE FROM petition_sign WHERE playerguid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_PETITION_SIGNATURE, "DELETE FROM petition_sign WHERE playerguid = ? AND type = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_PETITION_BY_OWNER, "SELECT petitionguid FROM petition WHERE ownerguid = ? AND type = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_PETITION_TYPE, "SELECT type FROM petition WHERE petitionguid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_PETITION_SIGNATURES, "SELECT ownerguid, (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = ?) AS signs, type FROM petition WHERE petitionguid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_PETITION_SIG_BY_ACCOUNT, "SELECT playerguid FROM petition_sign WHERE player_account = ? AND petitionguid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_PETITION_OWNER_BY_GUID, "SELECT ownerguid FROM petition WHERE petitionguid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_PETITION_SIG_BY_GUID, "SELECT ownerguid, petitionguid FROM petition_sign WHERE playerguid = ?", CONNECTION_SYNCH);
|
||||
|
||||
// Brackets
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_BRACKETS, "SELECT `bracket`, `rating`, `best`, `bestWeek`, `mmr`, `games`, `wins`, `weekGames`, `weekWins` FROM `character_brackets_info` WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_CHARACTER_BRACKETS_STATS, "REPLACE INTO `character_brackets_info` (`guid`, `bracket`, `rating`, `best`, `bestWeek`, `mmr`, `games`, `wins`, `weekGames`, `weekWins`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHARACTER_BRACKETS_STATS, "UPDATE `character_brackets_info` SET `rating` = ?, `best` = ?, `bestWeek` = ?, `mmr` = ?, `games` = ?, `wins` = ?, `weekGames` = ?, `weekWins` = ? WHERE `guid` = ? AND `bracket` = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_PLAYER_BRACKETS_INFO, "DELETE FROM character_brackets_info WHERE guid = ?", CONNECTION_ASYNC);
|
||||
|
||||
// Character battleground data
|
||||
PrepareStatement(CHAR_INS_PLAYER_BGDATA, "INSERT INTO character_battleground_data (guid, instanceId, team, joinX, joinY, joinZ, joinO, joinMapId, taxiStart, taxiEnd, mountSpell, lastActiveSpec) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_PLAYER_BGDATA, "DELETE FROM character_battleground_data WHERE guid = ?", CONNECTION_ASYNC);
|
||||
|
||||
// Character homebind
|
||||
PrepareStatement(CHAR_INS_PLAYER_HOMEBIND, "INSERT INTO character_homebind (guid, mapId, zoneId, posX, posY, posZ) VALUES (?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_PLAYER_HOMEBIND, "UPDATE character_homebind SET mapId = ?, zoneId = ?, posX = ?, posY = ?, posZ = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_PLAYER_HOMEBIND, "DELETE FROM character_homebind WHERE guid = ?", CONNECTION_ASYNC);
|
||||
|
||||
// Corpse
|
||||
PrepareStatement(CHAR_SEL_CORPSES, "SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, phaseMask, corpseGuid, guid FROM corpse WHERE corpseType <> 0", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_INS_CORPSE, "INSERT INTO corpse (corpseGuid, guid, posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, phaseMask) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CORPSE, "DELETE FROM corpse WHERE corpseGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_PLAYER_CORPSES, "DELETE FROM corpse WHERE guid = ? AND corpseType <> 0", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_OLD_CORPSES, "DELETE FROM corpse WHERE corpseType = 0 OR time < (UNIX_TIMESTAMP(NOW()) - ?)", CONNECTION_ASYNC);
|
||||
|
||||
// Creature respawn
|
||||
PrepareStatement(CHAR_SEL_CREATURE_RESPAWNS, "SELECT guid, respawnTime FROM creature_respawn WHERE mapId = ? AND instanceId = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_REP_CREATURE_RESPAWN, "REPLACE INTO creature_respawn (guid, respawnTime, mapId, instanceId) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CREATURE_RESPAWN, "DELETE FROM creature_respawn WHERE guid = ? AND mapId = ? AND instanceId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CREATURE_RESPAWN_BY_INSTANCE, "DELETE FROM creature_respawn WHERE mapId = ? AND instanceId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_MAX_CREATURE_RESPAWNS, "SELECT MAX(respawnTime), instanceId FROM creature_respawn WHERE instanceId > 0 GROUP BY instanceId", CONNECTION_SYNCH);
|
||||
|
||||
// Gameobject respawn
|
||||
PrepareStatement(CHAR_SEL_GO_RESPAWNS, "SELECT guid, respawnTime FROM gameobject_respawn WHERE mapId = ? AND instanceId = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_REP_GO_RESPAWN, "REPLACE INTO gameobject_respawn (guid, respawnTime, mapId, instanceId) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GO_RESPAWN, "DELETE FROM gameobject_respawn WHERE guid = ? AND mapId = ? AND instanceId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GO_RESPAWN_BY_INSTANCE, "DELETE FROM gameobject_respawn WHERE mapId = ? AND instanceId = ?", CONNECTION_ASYNC);
|
||||
|
||||
// GM Tickets
|
||||
PrepareStatement(CHAR_SEL_GM_TICKETS, "SELECT ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, completed, escalated, viewed FROM gm_tickets", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_REP_GM_TICKET, "REPLACE INTO gm_tickets (ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, completed, escalated, viewed) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GM_TICKET, "DELETE FROM gm_tickets WHERE ticketId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_PLAYER_GM_TICKETS, "DELETE FROM gm_tickets WHERE guid = ?", CONNECTION_ASYNC);
|
||||
|
||||
// GM Survey/subsurvey/lag report
|
||||
PrepareStatement(CHAR_INS_GM_SURVEY, "INSERT INTO gm_surveys (guid, surveyId, mainSurvey, overallComment, createTime) VALUES (?, ?, ?, ?, UNIX_TIMESTAMP(NOW()))", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_GM_SUBSURVEY, "INSERT INTO gm_subsurveys (surveyId, subsurveyId, rank, comment) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
// For loading and deleting expired auctions at startup
|
||||
PrepareStatement(CHAR_SEL_EXPIRED_AUCTIONS, "SELECT id, auctioneerguid, itemguid, itemEntry, count, itemowner, buyoutprice, time, buyguid, lastbid, startbid, deposit FROM auctionhouse ah INNER JOIN item_instance ii ON ii.guid = ah.itemguid WHERE ah.time <= ?", CONNECTION_SYNCH);
|
||||
|
||||
// LFG Data
|
||||
PrepareStatement(CHAR_INS_LFG_DATA, "INSERT INTO lfg_data (guid, dungeon, state) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_LFG_DATA, "DELETE FROM lfg_data WHERE guid = ?", CONNECTION_ASYNC);
|
||||
|
||||
// Player saving
|
||||
PrepareStatement(CHAR_INS_CHARACTER, "INSERT INTO characters (guid, account, name, race, class, level, xp, money, skin, face, hairStyle, hairColor, facialStyle, blindfold, gender, tattoo, horn, inventorySlots, bankSlots, drunk, playerFlags, "
|
||||
"playerFlagsEx, map, instance_id, dungeonDifficulty, raidDifficulty, legacyRaidDifficulty, position_x, position_y, position_z, orientation, trans_x, trans_y, trans_z, trans_o, transguid, "
|
||||
"taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, extra_flags, at_login, zone, "
|
||||
"death_expire_time, taxi_path, totalKills, todayKills, yesterdayKills, chosenTitle, watchedFaction, health, mana, "
|
||||
"latency, activespec, specialization, lootspecialization, exploredZones, equipmentCache, knownTitles, actionBars, currentpetnumber, petslot, grantableLevels, created_time, killPoints) VALUES "
|
||||
"(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_UPD_CHARACTER, "UPDATE characters SET name=?,race=?,class=?,level=?,xp=?,money=?,skin=?,face=?,hairStyle=?,hairColor=?,facialStyle=?,blindfold=?,gender=?,tattoo=?,horn=?,inventorySlots=?,bankSlots=?,drunk=?,playerFlags=?,"
|
||||
"playerFlagsEx=?,map=?,instance_id=?,dungeonDifficulty=?,raidDifficulty=?,legacyRaidDifficulty=?,position_x=?,position_y=?,position_z=?,orientation=?,trans_x=?,trans_y=?,trans_z=?,trans_o=?,transguid=?,taximask=?,cinematic=?,totaltime=?,leveltime=?,rest_bonus=?,"
|
||||
"logout_time=?,is_logout_resting=?,extra_flags=?,at_login=?,zone=?,death_expire_time=?,taxi_path=?,"
|
||||
"totalKills=?,todayKills=?,yesterdayKills=?,chosenTitle=?,"
|
||||
"watchedFaction=?,health=?,mana=?,latency=?,activespec=?,specialization=?,lootspecialization=?,exploredZones=?,"
|
||||
"equipmentCache=?,knownTitles=?,actionBars=?,currentpetnumber=?,petslot=?,grantableLevels=?,online=?,lfgBonusFaction=?,killPoints=? WHERE guid=?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG, "UPDATE characters SET at_login = at_login | ? WHERE guid = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_UPD_REM_AT_LOGIN_FLAG, "UPDATE characters set at_login = at_login & ~ ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_ALL_AT_LOGIN_FLAGS, "UPDATE characters SET at_login = at_login | ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_PETITION_NAME, "UPDATE petition SET name = ? WHERE petitionguid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_PETITION_SIGNATURE, "INSERT INTO petition_sign (ownerguid, petitionguid, playerguid, player_account) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_ACCOUNT_ONLINE, "UPDATE characters SET online = 0 WHERE account = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_GROUP, "INSERT INTO groups (guid, leaderGuid, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, groupType, difficulty, legacyRaidDifficulty, raiddifficulty) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_GROUP_MEMBER, "INSERT INTO group_member (guid, memberGuid, memberFlags, subgroup, roles) VALUES(?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GROUP_MEMBER, "DELETE FROM group_member WHERE memberGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GROUP_LEADER, "UPDATE groups SET leaderGuid = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GROUP_TYPE, "UPDATE groups SET groupType = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GROUP_MEMBER_SUBGROUP, "UPDATE group_member SET subgroup = ? WHERE memberGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GROUP_MEMBER_FLAG, "UPDATE group_member SET memberFlags = ? WHERE memberGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GROUP_MEMBER_ROLE, "UPDATE group_member SET roles = ? WHERE memberGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GROUP_DIFFICULTY, "UPDATE groups SET difficulty = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GROUP_RAID_DIFFICULTY, "UPDATE groups SET raiddifficulty = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GROUP_LEGACY_RAID_DIFFICULTY, "UPDATE groups SET legacyRaidDifficulty = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ALL_GM_TICKETS, "TRUNCATE TABLE gm_tickets", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_INVALID_SPELL, "DELETE FROM character_spell WHERE spell = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_INVALID_TALENT, "DELETE FROM character_talent WHERE talent = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_INVALID_TALENT_PVP, "DELETE FROM character_pvp_talent WHERE talent = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_DELETE_INFO, "UPDATE characters SET deleteInfos_Name = name, deleteInfos_Account = account, deleteDate = UNIX_TIMESTAMP(), name = '', account = 0 WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UDP_RESTORE_DELETE_INFO, "UPDATE characters SET name = ?, account = ?, deleteDate = NULL, deleteInfos_Name = NULL, deleteInfos_Account = NULL WHERE deleteDate IS NOT NULL AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_ZONE, "UPDATE characters SET zone = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_LEVEL, "UPDATE characters SET level = ?, xp = 0 WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA, "DELETE FROM character_achievement_progress WHERE criteria = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_ACHIEV_PROGRESS_CRITERIA, "DELETE FROM character_achievement_progress WHERE criteria = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_INVALID_ACC_ACHIEV_PROGRESS_CRITERIA, "DELETE FROM account_achievement_progress WHERE criteria = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ACC_ACHIEV_PROGRESS_CRITERIA, "DELETE FROM account_achievement_progress WHERE criteria = ? AND account = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_INVALID_ACHIEVMENT, "DELETE FROM character_achievement WHERE achievement = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_ADDON, "INSERT INTO addons (name, crc) VALUES (?, ?)", 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_WORLDSTATE, "UPDATE worldstates SET value = ? WHERE entry = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_WORLDSTATE, "REPLACE INTO worldstates (entry, value) VALUES (?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_GENDER_PLAYERBYTES, "UPDATE characters SET skin = ?, gender = ?, face = ?, hairStyle = ?, hairColor = ?, facialStyle = ?, tattoo = ?, horn = ?, blindfold = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_SKILL, "DELETE FROM character_skills WHERE guid = ? AND skill = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_ADD_CHARACTER_SOCIAL_FLAGS, "UPDATE character_social SET flags = flags | ? WHERE guid = ? AND friend = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_REM_CHARACTER_SOCIAL_FLAGS, "UPDATE character_social SET flags = flags & ~ ? WHERE guid = ? AND friend = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHARACTER_SOCIAL, "INSERT INTO character_social (guid, friend, flags) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_SOCIAL, "DELETE FROM character_social WHERE guid = ? AND friend = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHARACTER_SOCIAL_NOTE, "UPDATE character_social SET note = ? WHERE guid = ? AND friend = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHARACTER_POSITION, "UPDATE characters SET position_x = ?, position_y = ?, position_z = ?, orientation = ?, map = ?, zone = ?, trans_x = 0, trans_y = 0, trans_z = 0, transguid = 0, taxi_path = '' WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_AURA_FROZEN, "SELECT characters.name FROM characters LEFT JOIN character_aura ON (characters.guid = character_aura.guid) WHERE character_aura.spell = 9454", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_ONLINE, "SELECT name, account, map, zone FROM characters WHERE online > 0", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHAR_DEL_INFO_BY_GUID, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL AND guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHAR_DEL_INFO_BY_NAME, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL AND deleteInfos_Name LIKE CONCAT('%%', ?, '%%')", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHAR_DEL_INFO, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHARS_BY_ACCOUNT_ID, "SELECT guid FROM characters WHERE account = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHAR_PINFO, "SELECT totaltime, level, money, account, race, class, map, zone, logout_time FROM characters WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_PINFO_BANS, "SELECT unbandate, bandate = unbandate, bannedby, banreason FROM character_banned WHERE guid = ? AND active ORDER BY bandate ASC LIMIT 1", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHAR_HOMEBIND, "SELECT mapId, zoneId, posX, posY, posZ FROM character_homebind WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHAR_GUID_NAME_BY_ACC, "SELECT guid, name FROM characters WHERE account = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_POOL_QUEST_SAVE, "SELECT quest_id FROM pool_quest_save WHERE pool_id = ?", 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_CLASS_LVL_AT_LOGIN, "SELECT race, class, level, at_login, knownTitles, name FROM characters WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_PET_SPELL_LIST, "SELECT DISTINCT pet_spell.spell FROM pet_spell, character_pet WHERE character_pet.owner = ? AND character_pet.id = pet_spell.guid AND character_pet.id <> ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHAR_PET, "SELECT id FROM character_pet WHERE owner = ? AND id <> ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHAR_PETS, "SELECT id FROM character_pet WHERE owner = ?", 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);
|
||||
PrepareStatement(CHAR_SEL_CHAR_SOCIAL, "SELECT DISTINCT guid FROM character_social WHERE friend = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_PET_AURA, "SELECT slot, caster_guid, spell, effect_mask, recalculate_mask, stackcount, maxduration, remaintime, remaincharges FROM pet_aura WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_PET_AURA_EFFECT, "SELECT slot, effect, amount, baseamount FROM pet_aura_effect WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHAR_OLD_CHARS, "SELECT guid, deleteInfos_Account FROM characters WHERE deleteDate IS NOT NULL AND deleteDate < ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_MAIL, "SELECT id, messageType, sender, receiver, subject, body, has_items, expire_time, deliver_time, money, cod, checked, stationery, mailTemplateId FROM mail WHERE receiver = ? ORDER BY id DESC", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_SEL_PET_SPELL, "SELECT spell, active FROM pet_spell WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_PET_SPELL_COOLDOWN, "SELECT spell, time FROM pet_spell_cooldown WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_PET_DECLINED_NAME, "SELECT genitive, dative, accusative, instrumental, prepositional FROM character_pet_declinedname WHERE owner = ? AND id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHAR_GUID_BY_NAME, "SELECT guid FROM characters WHERE BINARY name = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_DEL_CHAR_AURA_FROZEN, "DELETE FROM character_aura WHERE spell = 9454 AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHAR_INVENTORY_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM character_inventory ci INNER JOIN item_instance ii ON ii.guid = ci.item WHERE itemEntry = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_MAIL_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM mail_items mi INNER JOIN item_instance ii ON ii.guid = mi.item_guid WHERE itemEntry = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_AUCTIONHOUSE_COUNT_ITEM,"SELECT COUNT(itemEntry) FROM auctionhouse ah INNER JOIN item_instance ii ON ii.guid = ah.itemguid WHERE itemEntry = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_GUILD_BANK_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM guild_bank_item gbi INNER JOIN item_instance ii ON ii.guid = gbi.item_guid WHERE itemEntry = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_CHAR_INVENTORY_ITEM_BY_ENTRY, "SELECT ci.item, cb.slot AS bag, ci.slot, ci.guid, c.account, c.name FROM characters c INNER JOIN character_inventory ci ON ci.guid = c.guid INNER JOIN item_instance ii ON ii.guid = ci.item LEFT JOIN character_inventory cb ON cb.item = ci.bag WHERE ii.itemEntry = ? LIMIT ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_MAIL_ITEMS_BY_ENTRY, "SELECT mi.item_guid, m.sender, m.receiver, cs.account, cs.name, cr.account, cr.name FROM mail m INNER JOIN mail_items mi ON mi.mail_id = m.id INNER JOIN item_instance ii ON ii.guid = mi.item_guid INNER JOIN characters cs ON cs.guid = m.sender INNER JOIN characters cr ON cr.guid = m.receiver WHERE ii.itemEntry = ? LIMIT ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_AUCTIONHOUSE_ITEM_BY_ENTRY, "SELECT ah.itemguid, ah.itemowner, c.account, c.name FROM auctionhouse ah INNER JOIN characters c ON c.guid = ah.itemowner INNER JOIN item_instance ii ON ii.guid = ah.itemguid WHERE ii.itemEntry = ? LIMIT ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_GUILD_BANK_ITEM_BY_ENTRY, "SELECT gi.item_guid, gi.guildid, g.name FROM guild_bank_item gi INNER JOIN guild g ON g.guildid = gi.guildid INNER JOIN item_instance ii ON ii.guid = gi.item_guid WHERE ii.itemEntry = ? LIMIT ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_DEL_ACCOUNT_ACHIEVEMENT, "DELETE FROM account_achievement WHERE account = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_ACHIEVEMENT, "DELETE FROM character_achievement WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_ACHIEVEMENT_PROGRESS, "DELETE FROM character_achievement_progress WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_CHAR_REPUTATION_BY_FACTION, "REPLACE INTO character_reputation (guid, faction, standing, flags) VALUES (?, ?, ? , ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ITEM_REFUND_INSTANCE, "DELETE FROM item_refund_instance WHERE item_guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_ITEM_REFUND_INSTANCE, "INSERT INTO item_refund_instance (item_guid, player_guid, paidMoney, paidExtendedCost) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GROUP, "DELETE FROM groups WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GROUP_MEMBER_ALL, "DELETE FROM group_member WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHAR_GIFT, "INSERT INTO character_gifts (guid, item_guid, entry, flags) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_MAIL_ITEM_BY_ID, "DELETE FROM mail_items WHERE mail_id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_PET_DECLINEDNAME, "DELETE FROM character_pet_declinedname WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_ADD_CHAR_PET_DECLINEDNAME, "INSERT INTO character_pet_declinedname (id, owner, genitive, dative, accusative, instrumental, prepositional) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHAR_PET_NAME, "UPDATE character_pet SET name = ?, renamed = 1 WHERE owner = ? AND id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_PETITION, "INSERT INTO petition (ownerguid, petitionguid, name) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_PETITION_BY_GUID, "DELETE FROM petition WHERE petitionguid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_PETITION_SIGNATURE_BY_GUID, "DELETE FROM petition_sign WHERE petitionguid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_PET_AURAS, "DELETE FROM pet_aura WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_PET_AURAS_EFFECTS, "DELETE FROM pet_aura_effect WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_PET_SPELLS, "DELETE FROM pet_spell WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_PET_SPELL_COOLDOWNS, "DELETE FROM pet_spell_cooldown WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_PET_SPELL_COOLDOWN, "INSERT INTO pet_spell_cooldown (guid, spell, time) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_PET_SPELL_BY_SPELL, "DELETE FROM pet_spell WHERE guid = ? and spell = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_PET_SPELL, "INSERT IGNORE INTO pet_spell (guid, spell, active) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_PET_AURA, "INSERT IGNORE INTO pet_aura (guid, slot, caster_guid, spell, effect_mask, recalculate_mask, stackcount, maxduration, remaintime, remaincharges) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_PET_AURA_EFFECT, "INSERT IGNORE INTO pet_aura_effect (guid, slot, effect, baseamount, amount) VALUES (?, ?, ?, ?, ?)", 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_FACTION_OR_RACE_LOG, "INSERT INTO `log_faction_change` (`id`, `guid`, `account`, `OldRace`, `NewRace`, `date`) VALUES (0, ?, ?, ?, ?, NOW())", 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, "REPLACE 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);
|
||||
PrepareStatement(CHAR_UPD_CHAR_TAXIMASK, "UPDATE characters SET taximask = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS, "DELETE FROM character_queststatus WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES, "DELETE FROM character_queststatus_objectives WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_SOCIAL_BY_GUID, "DELETE FROM character_social WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_SOCIAL_BY_FRIEND, "DELETE FROM character_social WHERE friend = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_ACHIEVEMENT_BY_ACHIEVEMENT, "DELETE FROM character_achievement WHERE achievement = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHAR_ACHIEVEMENT, "UPDATE character_achievement SET achievement = ? where achievement = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHAR_INVENTORY_FACTION_CHANGE, "UPDATE item_instance ii, character_inventory ci SET ii.itemEntry = ? WHERE ii.itemEntry = ? AND ci.guid = ? AND ci.item = ii.guid", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_SPELL_BY_SPELL, "DELETE FROM character_spell WHERE spell = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHAR_SPELL_FACTION_CHANGE, "UPDATE character_spell SET spell = ? where spell = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_REP_BY_FACTION, "DELETE FROM character_reputation WHERE faction = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHAR_REP_FACTION_CHANGE, "UPDATE character_reputation SET faction = ? where faction = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHAR_REP_STANDING_CHANGE, "UPDATE character_reputation SET standing = ? where faction = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHAR_REP_FLAGS_CHANGE, "UPDATE character_reputation SET flags = ? where faction = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHAR_TITLES_FACTION_CHANGE, "UPDATE characters SET knownTitles = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_RES_CHAR_TITLES_FACTION_CHANGE, "UPDATE characters SET chosenTitle = 0 WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_SPELL_COOLDOWN, "DELETE FROM character_spell_cooldown WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER, "DELETE FROM characters WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_ACTION, "DELETE FROM character_action WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_AURA, "DELETE FROM character_aura WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_AURA_EFFECT, "DELETE FROM character_aura_effect WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_GIFT, "DELETE FROM character_gifts WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_INVENTORY, "DELETE FROM character_inventory WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_REWARDED, "DELETE FROM character_queststatus_rewarded WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_REPUTATION, "DELETE FROM character_reputation WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_SPELL, "DELETE FROM character_spell WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_MAIL, "DELETE FROM mail WHERE receiver = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_MAIL_ITEMS, "DELETE FROM mail_items WHERE receiver = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_PET_BY_OWNER, "DELETE FROM character_pet WHERE owner = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_PET_DECLINEDNAME_BY_OWNER, "DELETE FROM character_pet_declinedname WHERE owner = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_ACHIEVEMENTS, "DELETE FROM character_achievement WHERE guid = ? AND achievement NOT BETWEEN '456' AND '467' AND achievement NOT BETWEEN '1400' AND '1427' AND achievement NOT IN(1463, 3117, 3259)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_EQUIPMENTSETS, "DELETE FROM character_equipmentsets WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GUILD_EVENTLOG_BY_PLAYER, "DELETE FROM guild_eventlog WHERE PlayerGuid1 = ? OR PlayerGuid2 = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GUILD_BANK_EVENTLOG_BY_PLAYER, "DELETE FROM guild_bank_eventlog WHERE PlayerGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_GLYPHS, "DELETE FROM character_glyphs WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_DAILY, "DELETE FROM character_queststatus_daily WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_TALENT, "DELETE FROM character_talent WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_TALENT_PVP, "DELETE FROM character_pvp_talent WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_SKILLS, "DELETE FROM character_skills WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UDP_CHAR_MONEY, "UPDATE characters SET money = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHAR_ACTION, "REPLACE INTO character_action (guid, spec, button, action, type) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHAR_ACTION, "UPDATE character_action SET action = ?, type = ? WHERE guid = ? AND button = ? AND spec = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_ACTION_BY_BUTTON_SPEC, "DELETE FROM character_action WHERE guid = ? and button = ? and spec = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_INVENTORY_BY_ITEM, "DELETE FROM character_inventory WHERE item = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_INVENTORY_BY_BAG_SLOT, "DELETE FROM character_inventory WHERE bag = ? AND slot = ? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_MAIL, "UPDATE mail SET has_items = ?, expire_time = ?, deliver_time = ?, money = ?, cod = ?, checked = ? WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_CHAR_QUESTSTATUS, "REPLACE INTO character_queststatus (guid, quest, status, timer, account) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_BY_QUEST, "DELETE FROM character_queststatus WHERE guid = ? AND quest = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_CHAR_QUESTSTATUS_OBJECTIVES, "REPLACE INTO character_queststatus_objectives (guid, quest, objective, data, account) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_BY_QUEST, "DELETE FROM character_queststatus_objectives WHERE guid = ? AND quest = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ACC_QUESTSTATUS_BY_QUEST, "DELETE FROM character_queststatus WHERE account = ? AND quest = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ACC_QUESTSTATUS_OBJECTIVES_BY_QUEST, "DELETE FROM character_queststatus_objectives WHERE account = ? AND quest = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHAR_QUESTSTATUS, "REPLACE INTO character_queststatus_rewarded (guid, quest, account) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_REWARDED_BY_QUEST, "DELETE FROM character_queststatus_rewarded WHERE guid = ? AND quest = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ACC_QUESTSTATUS_REWARDED_BY_QUEST, "DELETE FROM character_queststatus_rewarded WHERE account = ? AND quest = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_SKILL_BY_SKILL, "DELETE FROM character_skills WHERE guid = ? AND skill = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHAR_SKILLS, "REPLACE INTO character_skills (guid, skill, value, max) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UDP_CHAR_SKILLS, "UPDATE character_skills SET value = ?, max = ? WHERE guid = ? AND skill = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHAR_SPELL, "REPLACE INTO character_spell (guid, spell, active, disabled) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_PETITION_BY_OWNER, "DELETE FROM petition WHERE ownerguid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_PETITION_SIGNATURE_BY_OWNER, "DELETE FROM petition_sign WHERE ownerguid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHAR_GLYPHS, "INSERT INTO character_glyphs VALUES(?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_TALENT_BY_SPELL_SPEC, "DELETE FROM character_talent WHERE guid = ? and talent = ? and spec = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHAR_TALENT, "INSERT INTO character_talent (guid, talent, spec) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_TALENT_PVP_BY_SPELL_SPEC, "DELETE FROM character_pvp_talent WHERE guid = ? and talent = ? and spec = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHAR_TALENT_PVP, "INSERT INTO character_pvp_talent (guid, talent, spec) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_ACTION_EXCEPT_SPEC, "DELETE FROM character_action WHERE spec<>? AND guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHAR_LIST_SLOT, "UPDATE characters SET slot = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHAR_VOID_STORAGE, "SELECT itemId, itemEntry, slot, creatorGuid, randomPropertyType, randomProperty, suffixFactor FROM character_void_storage WHERE playerGuid = ? AND itemGuid = 0", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_CHAR_VOID_STORAGE_ITEM, "REPLACE INTO character_void_storage (itemId, playerGuid, itemEntry, slot, creatorGuid, randomPropertyType, randomProperty, suffixFactor, itemGuid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_VOID_STORAGE_ITEM_BY_SLOT, "DELETE FROM character_void_storage WHERE slot = ? AND playerGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHAR_VOID_STORAGE_ITEM, "DELETE FROM character_void_storage WHERE itemId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHAR_VOID_STORAGE_ITEM, "SELECT " SelectItemInstanceContent ", vo.slot, vo.itemId FROM character_void_storage vo JOIN item_instance ii ON vo.itemGuid = ii.guid "
|
||||
"LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid "
|
||||
"LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid "
|
||||
"LEFT JOIN item_instance_artifact iia ON ii.itemEntry = iia.itemEntry and vo.playerGuid = iia.char_guid "
|
||||
"LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid WHERE vo.playerGuid = ? AND vo.itemGuid != 0 ORDER BY slot", CONNECTION_ASYNC);
|
||||
|
||||
// Guild Finder
|
||||
PrepareStatement(CHAR_REP_GUILD_FINDER_APPLICANT, "REPLACE INTO guild_finder_applicant (guildId, playerGuid, availability, classRole, interests, comment, submitTime) VALUES(?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GUILD_FINDER_APPLICANT, "DELETE FROM guild_finder_applicant WHERE guildId = ? AND playerGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_GUILD_FINDER_GUILD_SETTINGS, "REPLACE INTO guild_finder_guild_settings (guildId, availability, classRoles, interests, level, listed, comment) VALUES(?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_GUILD_FINDER_GUILD_SETTINGS, "DELETE FROM guild_finder_guild_settings WHERE guildId = ?", CONNECTION_ASYNC);
|
||||
|
||||
// Challenge
|
||||
PrepareStatement(CHAR_INS_CHALLENGE, "INSERT INTO challenge (`ID`, `GuildID`, `MapID`, `RecordTime`, `Date`, `ChallengeLevel`, `TimerLevel`, `Affixes`, `ChestID`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHALLENGE_MEMBER, "INSERT INTO challenge_member (`id`, `member`, `specID`, `ChallengeLevel`, `Date`, `ChestID`) VALUES (?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHALLENGE_OPLOTE_LOOT, "REPLACE INTO challenge_oplote_loot (`guid`, `chestListID`, `date`, `ChallengeLevel`) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHALLENGE_OPLOTE_LOOT, "DELETE FROM challenge_oplote_loot WHERE date <= UNIX_TIMESTAMP()", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHALLENGE_OPLOTE_LOOT_BY_GUID, "DELETE FROM challenge_oplote_loot WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHALLENGE_MEMBER, "DELETE FROM challenge_member WHERE member = ?", CONNECTION_ASYNC);
|
||||
|
||||
// CUF
|
||||
PrepareStatement(CHAR_SEL_CUF_PROFILES, "SELECT profileId, profileName, frameHeight, frameWidth, sortBy, healthText, someOptions, unk146, unk147, unk148, unk150, unk152, unk154 FROM character_cuf_profiles WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_CUF_PROFILES, "REPLACE INTO character_cuf_profiles (guid, profileId, profileName, frameHeight, frameWidth, sortBy, healthText, someOptions, unk146, unk147, unk148, unk150, unk152, unk154) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_BOTH);
|
||||
|
||||
// Battle Pets
|
||||
#define PETBATTLE_FIELDS "slot, name, nameTimeStamp, species, quality, breed, level, xp, display, health, flags, infoPower, infoMaxHealth, infoSpeed, infoGender, account, declinedGenitive, declinedNative, declinedAccusative, declinedInstrumental, declinedPrepositional"
|
||||
#define PETBATTLE_FULL_FIELDS "id, " PETBATTLE_FIELDS
|
||||
PrepareStatement(CHAR_SEL_PETBATTLE_ACCOUNT, "SELECT " PETBATTLE_FULL_FIELDS " FROM account_battlepet WHERE account = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_REP_PETBATTLE, "REPLACE INTO account_battlepet(id, " PETBATTLE_FIELDS ") VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_INS_PETBATTLE, "INSERT INTO account_battlepet(" PETBATTLE_FIELDS ") VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_DEL_PETBATTLE, "DELETE FROM account_battlepet WHERE id = ?", CONNECTION_BOTH);
|
||||
|
||||
// Else
|
||||
PrepareStatement(CHAR_SEL_PERSONAL_RATE, "SELECT rate FROM character_rates WHERE guid=? LIMIT 1", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_PLAYER_VISUAL, "SELECT head, shoulders, chest, waist, legs, feet, wrists, hands, back, main, off, ranged, tabard, shirt FROM character_visuals WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_MAILBOX_QUEUE, "SELECT id, messageType, stationery, sender_guid, receiver_guid, subject, message, money, item, item_count FROM mailbox_queue LIMIT 500", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_DEL_MAILBOX_QUEUE, "DELETE FROM mailbox_queue WHERE id = ?", CONNECTION_ASYNC);
|
||||
|
||||
// character_donate
|
||||
PrepareStatement(CHAR_ADD_ITEM_DONATE, "REPLACE INTO character_donate (`owner_guid`, `itemguid`, `itemEntry`, `efircount`, `count`, `state`) VALUES (?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_ITEM_DONATE_SET_STATE, "UPDATE character_donate SET state = ?, deletedate = ? WHERE itemguid = ?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_PLAYER_KILL, "SELECT victim_guid, count FROM character_kill WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_PLAYER_KILL, "DELETE FROM character_kill WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_PLAYER_KILL, "REPLACE INTO character_kill (guid, victim_guid, count) VALUES (?, ? ,?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_PLAYER_KILL, "UPDATE character_kill SET count=? WHERE guid = ? AND victim_guid = ?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_HONOR_INFO, "SELECT CurrentHonorAtLevel, PrestigeLevel, HonorLevel FROM character_honor WHERE Guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_HONOR_INFO_HONOR, "UPDATE character_honor SET CurrentHonorAtLevel = ? WHERE Guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_HONOR_INFO_HONOR_LEVEL, "UPDATE character_honor SET HonorLevel = ? WHERE Guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_HONOR_INFO_PRESTIGE_LEVEL, "UPDATE character_honor SET PrestigeLevel = ? WHERE Guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_HONOR_INFO, "REPLACE INTO character_honor (Guid, CurrentHonorAtLevel, PrestigeLevel, HonorLevel) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
//Loot cooldown system
|
||||
PrepareStatement(CHAR_SEL_PLAYER_LOOTCOOLDOWN, "SELECT entry, type, difficultyID, respawnTime FROM character_loot_cooldown WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_PLAYER_LOOTCOOLDOWN, "REPLACE INTO character_loot_cooldown (`guid`, `entry`, `type`, `difficultyID`, `respawnTime`) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_PLAYER_LFGCOOLDOWN, "SELECT dungeonId, respawnTime FROM character_lfg_cooldown WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_PLAYER_LFGCOOLDOWN, "REPLACE INTO character_lfg_cooldown (`guid`, `dungeonId`, `respawnTime`) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_LAST_CHAR_UNDELETE, "SELECT LastCharacterUndelete FROM characters WHERE account = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_LAST_CHAR_UNDELETE, "UPDATE characters SET LastCharacterUndelete = UNIX_TIMESTAMP() WHERE account = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_RESTORE_DELETE_INFO, "UPDATE characters SET name = ?, account = ?, deleteDate = NULL, deleteInfos_Name = NULL, deleteInfos_Account = NULL WHERE deleteDate IS NOT NULL AND guid = ?", CONNECTION_ASYNC);
|
||||
|
||||
// Black Market
|
||||
PrepareStatement(CHAR_SEL_BLACKMARKET_AUCTIONS, "SELECT marketId, currentBid, time, numBids, bidder FROM blackmarket_auctions", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_DEL_BLACKMARKET_AUCTIONS, "DELETE FROM blackmarket_auctions WHERE marketId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_BLACKMARKET_AUCTIONS, "UPDATE blackmarket_auctions SET currentBid = ?, time = ?, numBids = ?, bidder = ? WHERE marketId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_BLACKMARKET_AUCTIONS, "INSERT INTO blackmarket_auctions (marketId, currentBid, time, numBids, bidder) VALUES (?, ?, ?, ? ,?)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_REP_CALENDAR_EVENT, "REPLACE INTO calendar_events (EventID, Owner, Title, Description, EventType, TextureID, Date, Flags, LockDate) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CALENDAR_EVENT, "DELETE FROM calendar_events WHERE EventID = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_CALENDAR_INVITE, "REPLACE INTO calendar_invites (InviteID, EventID, Invitee, Sender, Status, ResponseTime, ModerationRank, Note) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CALENDAR_INVITE, "DELETE FROM calendar_invites WHERE InviteID = ?", CONNECTION_ASYNC);
|
||||
|
||||
// Garrison
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_GARRISON, "SELECT SiteLevelId, FollowerActivationsRemainingToday, CacheLastUsage, _MissionGen FROM character_garrison WHERE CharacterGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHARACTER_GARRISON, "REPLACE INTO character_garrison (CharacterGuid, SiteLevelId, FollowerActivationsRemainingToday, CacheLastUsage, _MissionGen) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHARACTER_GARRISON, "UPDATE character_garrison SET SiteLevelId = ? WHERE CharacterGuid = ? AND SiteLevelId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON, "DELETE FROM character_garrison WHERE CharacterGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_ONLY, "DELETE FROM character_garrison WHERE CharacterGuid = ? and SiteLevelId in (5, 258, 444, 445, 6, 259)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_BY_SITE, "DELETE FROM character_garrison WHERE CharacterGuid = ? AND SiteLevelId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHARACTER_GARRISON_FOLLOWER_ACTIVATIONS, "UPDATE character_garrison SET FollowerActivationsRemainingToday = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_BLUEPRINTS, "SELECT buildingId FROM character_garrison_blueprints WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHARACTER_GARRISON_BLUEPRINTS, "REPLACE INTO character_garrison_blueprints (guid, buildingId) VALUES (?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_BLUEPRINTS, "DELETE FROM character_garrison_blueprints WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_BLUEPRINTS_BY_BUILD, "DELETE FROM character_garrison_blueprints WHERE guid = ? AND buildingId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_BUILDINGS, "SELECT plotInstanceId, buildingId, timeBuilt, active, data FROM character_garrison_buildings WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHARACTER_GARRISON_BUILDINGS, "REPLACE INTO character_garrison_buildings (guid, plotInstanceId, buildingId, timeBuilt, active, data) VALUES (?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_BUILDINGS, "DELETE FROM character_garrison_buildings WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_BUILDINGS_BY_PLOT, "DELETE FROM character_garrison_buildings WHERE guid = ? AND plotInstanceId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_FOLLOWERS, "SELECT dbId, followerId, quality, level, itemLevelWeapon, itemLevelArmor, xp, currentBuilding, currentMission, status, Durability FROM character_garrison_followers WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHARACTER_GARRISON_FOLLOWERS, "REPLACE INTO character_garrison_followers (dbId, guid, followerId, quality, level, itemLevelWeapon, itemLevelArmor, xp, currentBuilding, currentMission, status, Durability) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_FOLLOWERS, "DELETE gfab, gf FROM character_garrison_follower_abilities gfab INNER JOIN character_garrison_followers gf ON gfab.dbId = gf.dbId WHERE gf.guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_FOLLOWER, "DELETE FROM character_garrison_followers WHERE dbId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_FOLLOWER_BY_DBID, "DELETE gfab, gf FROM character_garrison_follower_abilities gfab INNER JOIN character_garrison_followers gf ON gfab.dbId = gf.dbId WHERE gf.dbId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_FOLLOWER_ABILITIES, "SELECT gfab.dbId, gfab.abilityId FROM character_garrison_follower_abilities gfab INNER JOIN character_garrison_followers gf ON gfab.dbId = gf.dbId WHERE guid = ? ORDER BY gfab.slot", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHARACTER_GARRISON_FOLLOWER_ABILITIES, "REPLACE INTO character_garrison_follower_abilities (dbId, abilityId, slot) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_FOLLOWER_ABILITIES, "DELETE FROM character_garrison_follower_abilities WHERE dbId = ?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_MISSIONS, "SELECT dbId, missionRecID, offerTime, offerDuration, startTime, travelDuration, missionDuration, missionState, chance FROM character_garrison_missions WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHARACTER_GARRISON_MISSIONS, "REPLACE INTO character_garrison_missions (dbId, guid, missionRecID, offerTime, offerDuration, startTime, travelDuration, missionDuration, missionState, chance) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_MISSIONS, "DELETE FROM character_garrison_missions WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_MISSIONS_DB_ID, "DELETE FROM character_garrison_missions WHERE dbId = ?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_SHIPMENTS, "SELECT dbId, shipmentID, start, end FROM character_garrison_shipment WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHARACTER_GARRISON_SHIPMENTS, "REPLACE INTO character_garrison_shipment (dbId, guid, shipmentID, start, end) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_SHIPMENTS, "DELETE FROM character_garrison_shipment WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_SHIPMENTS_DBID, "DELETE FROM character_garrison_shipment WHERE dbId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_SHIPMENTS_BY_DB_ID, "DELETE FROM character_garrison_shipment WHERE dbId = ?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_GARRISON_TALENTS, "SELECT talentID, orderTime, flags FROM character_garrison_talents WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHARACTER_GARRISON_TALENTS, "REPLACE INTO character_garrison_talents (guid, talentID, orderTime, flags) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_TALENTS, "DELETE FROM character_garrison_talents WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_GARRISON_TALENT_BY_ID, "DELETE FROM character_garrison_talents WHERE guid = ? AND talentID = ?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_TOYS, "SELECT itemId, isFavourite FROM account_toys WHERE accountId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_TOYS, "REPLACE INTO account_toys (accountId, itemId, isFavourite) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_HEIRLOOMS, "SELECT itemId, flags FROM account_heirlooms WHERE accountId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_HEIRLOOMS, "REPLACE INTO account_heirlooms (accountId, itemId, flags) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_COMPLAINTS, "SELECT ID, SpammerGuid, ComplaintType, MailID, TimeSinceOffence, MessageLog FROM report_complaints WHERE SpammerGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHARACTER_COMPLAINTS, "INSERT INTO report_complaints (ID, ReportPlayer, ReportAccount, ReportTime, SpammerGuid, ComplaintType, MailID, TimeSinceOffence, MessageLog) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_TRANSMOGS, "SELECT `ModelID`, `Condition` FROM account_transmogs WHERE account = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_TRANSMOGS, "REPLACE INTO account_transmogs (`account`, `guid`, `ModelID`, `Condition`) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_TRANSMOG, "DELETE FROM account_transmogs WHERE account = ? AND ModelID = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_BNET_ITEM_FAVORITE_APPEARANCES, "SELECT itemModifiedAppearanceId FROM account_item_favorite_appearances WHERE battlenetAccountId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_BNET_ITEM_FAVORITE_APPEARANCE, "INSERT INTO account_item_favorite_appearances (battlenetAccountId, itemModifiedAppearanceId) VALUES (?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_BNET_ITEM_FAVORITE_APPEARANCE, "DELETE FROM account_item_favorite_appearances WHERE battlenetAccountId = ? AND itemModifiedAppearanceId = ?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_ITEM_INSTANCE_ARTIFACT, "SELECT ap.itemEntry, a.xp, a.artifactAppearanceId, ap.artifactPowerId, ap.purchasedRank, a.itemGuid FROM item_instance_artifact_powers ap LEFT JOIN item_instance_artifact a ON ap.itemEntry = a.itemEntry and ap.char_guid = a.char_guid where ap.char_guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_ITEM_INSTANCE_ARTIFACT, "REPLACE INTO item_instance_artifact (itemGuid, xp, artifactAppearanceId, itemEntry, tier, char_guid, totalrank) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ITEM_INSTANCE_ARTIFACT, "DELETE FROM item_instance_artifact WHERE itemGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ITEM_INSTANCE_ARTIFACT_BY_OWNER, "DELETE iia FROM item_instance_artifact iia LEFT JOIN item_instance ii ON iia.itemGuid = ii.guid WHERE ii.owner_guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_ITEM_INSTANCE_ARTIFACT_XP, "SELECT xp FROM item_instance_artifact where char_guid = ? AND itemEntry = ?", CONNECTION_SYNCH);
|
||||
|
||||
PrepareStatement(CHAR_SEL_ITEM_INSTANCE_ARTIFACT_POWERS, "SELECT artifactPowerId, purchasedRank FROM item_instance_artifact_powers iiap inner join item_instance ii on ii.itemEntry = iiap.itemEntry and ii.owner_guid = iiap.char_guid WHERE ii.guid = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(CHAR_REP_ITEM_INSTANCE_ARTIFACT_POWERS, "REPLACE INTO item_instance_artifact_powers (itemGuid, artifactPowerId, purchasedRank, itemEntry, char_guid) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ITEM_INSTANCE_ARTIFACT_POWERS, "DELETE FROM item_instance_artifact_powers WHERE itemGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ITEM_INSTANCE_ARTIFACT_POWERS_BY_OWNER, "DELETE iiap FROM item_instance_artifact_powers iiap LEFT JOIN item_instance ii ON iiap.itemGuid = ii.guid WHERE ii.owner_guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_ITEM_INSTANCE_MODIFIERS, "INSERT INTO item_instance_modifiers (itemGuid, fixedScalingLevel, artifactKnowledgeLevel) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_REP_ITEM_INSTANCE_RELICS, "REPLACE INTO item_instance_relics (itemGuid, char_guid, first_relic, second_relic, third_relic) VALUES (?, ?, ?, ?, ?);", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ITEM_INSTANCE_RELICS, "DELETE FROM item_instance_relics where itemGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_ITEM_INSTANCE_RELICS, "SELECT first_relic, second_relic, third_relic FROM item_instance_relics where itemGuid = ?", CONNECTION_BOTH);
|
||||
|
||||
PrepareStatement(CHAR_DEL_ITEM_INSTANCE_MODIFIERS, "DELETE FROM item_instance_modifiers WHERE itemGuid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_ITEM_INSTANCE_MODIFIERS_BY_OWNER, "DELETE im FROM item_instance_modifiers im LEFT JOIN item_instance ii ON im.itemGuid = ii.guid WHERE ii.owner_guid = ?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_MOUNTS, "SELECT spell, flags FROM account_mounts WHERE account = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_MOUNTS, "REPLACE INTO account_mounts (account, spell, flags) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_ADVENTURE_QUEST, "SELECT questID FROM character_adventure_quest WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHARACTER_ADVENTURE_QUEST, "DELETE FROM character_adventure_quest WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_CHARACTER_ADVENTURE_QUEST, "REPLACE INTO character_adventure_quest (guid, questID) VALUES (?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_REP_WORLD_QUEST, "REPLACE INTO world_quest (`QuestID`, `QuestInfoID`, `QuestSortID`, `VariableID`, `Value`, `Timer`, `StartTime`, `ResetTime`, `CurrencyID`, `CurrencyCount`, `Gold`, `ItemList`, `RewardType`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_WORLD_QUEST_BY_ID, "DELETE FROM world_quest WHERE QuestID = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_WORLD_QUEST_BY_TIMER, "DELETE FROM world_quest WHERE ResetTime <= UNIX_TIMESTAMP()", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_QUEST_STATUS_WORLD, "DELETE FROM character_queststatus_world WHERE ResetTime <= UNIX_TIMESTAMP()", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_CHARACTER_WORLDQUESTSTATUS, "SELECT quest, guid, resetTime FROM character_queststatus_world WHERE account = ? AND (guid = 0 OR guid = ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHARACTER_WORLDQUESTSTATUS, "REPLACE INTO character_queststatus_world (guid, quest, account, resetTime) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_DEL_WORLD_STATE_BY_STATE_INSTANCE, "DELETE FROM worldstate_data WHERE VariableID = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_WORLD_STAT, "INSERT INTO `worldstate_data` (`VariableID`, `Type`, `ConditionID`, `Flags`, `Value`) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_CHALLENGE_KEY, "SELECT ID, Level, Affix, Affix1, Affix2, KeyIsCharded, timeReset, InstanceID FROM challenge_key WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_CHALLENGE_KEY, "UPDATE challenge_key SET ID = ?, Level = ?, Affix = ?, Affix1 = ?, Affix2 = ?, KeyIsCharded = ?, timeReset = ?, InstanceID = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_CHALLENGE_KEY, "REPLACE INTO challenge_key (ID, Level, Affix, Affix1, Affix2, KeyIsCharded, timeReset, InstanceID, guid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_DEL_CHALLENGE_KEY, "DELETE FROM challenge_key WHERE guid = ?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_PLAYER_DEATHMATCH, "SELECT kills, deaths, damage, rating, matches FROM character_deathmatch WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_PLAYER_DEATHMATCH, "REPLACE INTO character_deathmatch (guid, kills, deaths, damage, rating, matches) values (?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_PLAYER_DEATHMATCH_STORE, "SELECT total_kills, selected_morph, buyed_morphs FROM character_deathmatch_store WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_PLAYER_DEATHMATCH_STORE, "REPLACE INTO character_deathmatch_store (guid, total_kills, selected_morph, buyed_morphs) values (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_PLAYER_CHAT_LOGOS, "SELECT buyed_logo, active from character_chat_logos where guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_PLAYER_CHAT_LOGOS, "REPLACE INTO character_chat_logos (guid, buyed_logo, active) values (?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_ARMY_TRAINING_INFO, "SELECT `opened_berserk`, `opened_mana_wanted`, `opened_mage`, `opened_hp`, `opened_dmg`, `opened_fixate`, `opened_brave`, `opened_chests` from character_army_training_info where guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_ARMY_TRAINING_INFO, "REPLACE INTO character_army_training_info (`guid`, `opened_berserk`, `opened_mana_wanted`, `opened_mage`, `opened_hp`, `opened_dmg`, `opened_fixate`, `opened_brave`, `opened_chests`) values (?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_ACCOUNT_PROGRESS, "SELECT totaltime, leveltime from account_progress where account = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_REP_ACCOUNT_PROGRESS, "REPLACE INTO account_progress (account, totaltime, leveltime) values (?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_REP_BAD_SENTENCES, "REPLACE INTO bad_sentences (`id`, `sentence`, `hash`, `penalty`, `sourceMask`,`output`) values (?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_BAD_SENTENCES, "update bad_sentences set penalty = ? where id = ?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_UPD_WEEKLY_BRACKET, "UPDATE character_brackets_info SET bestWeekLast = bestWeek, bestWeek = 0, weekGames = 0, weekWins = 0", CONNECTION_ASYNC);
|
||||
|
||||
// Warden and anticheat (in future) augmenting ban
|
||||
PrepareStatement(CHAR_DEL_WARDEN_BAN_ATTEMPTS, "DELETE FROM account_ban_attempts WHERE accountId = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_WARDEN_BAN_ATTEMPTS, "INSERT INTO account_ban_attempts (accountId, banAttempts) VALUES (?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_SEL_WARDEN_BAN_ATTEMPTS, "SELECT banAttempts FROM account_ban_attempts WHERE accountId = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_UPD_WARDEN_BAN_ATTEMPTS, "UPDATE account_ban_attempts SET banAttempts = banAttempts + 1 WHERE accountId = ?", CONNECTION_ASYNC);
|
||||
|
||||
// Flag account system
|
||||
PrepareStatement(CHAR_SEL_ACCOUNT_FLAGGED, "SELECT banduration FROM account_flagged WHERE id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_SEL_ACCOUNT_FLAGGED_ALL, "SELECT id, banduration, bannedby, banreason FROM account_flagged", CONNECTION_SYNCH);
|
||||
PrepareStatement(CHAR_DEL_ACCOUNT_FLAGGED, "DELETE FROM account_flagged WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_ACCOUNT_FLAGGED, "INSERT IGNORE INTO account_flagged VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
// Temp for bots
|
||||
PrepareStatement(CHAR_INS_BOT_ACCOUNT, "INSERT IGNORE INTO account_bot_detected VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
// Stat System
|
||||
PrepareStatement(CHAR_SEL_KILL_CREATURE, "SELECT entry, count, point FROM character_stat_kill_creature WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_INS_KILL_CREATURE, "REPLACE INTO character_stat_kill_creature (`guid`, `entry`, `count`, `point`) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(CHAR_UPD_KILL_CREATURE, "UPDATE character_stat_kill_creature SET count = ?, point = ? WHERE guid = ? AND entry = ?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(CHAR_SEL_NUM_ACCOUNT_CHARS_REACHED_LEVEL, "SELECT COUNT(guid) FROM characters WHERE account = ? AND level >= ?", CONNECTION_BOTH);
|
||||
}
|
||||
789
src/common/Database/Implementation/CharacterDatabase.h
Normal file
789
src/common/Database/Implementation/CharacterDatabase.h
Normal file
@@ -0,0 +1,789 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _CHARACTERDATABASE_H
|
||||
#define _CHARACTERDATABASE_H
|
||||
|
||||
#include "DatabaseWorkerPool.h"
|
||||
#include "MySQLConnection.h"
|
||||
|
||||
class CharacterDatabaseConnection : public MySQLConnection
|
||||
{
|
||||
public:
|
||||
//- Constructors for sync and async connections
|
||||
CharacterDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) { }
|
||||
CharacterDatabaseConnection(ProducerConsumerQueue<SQLOperation*>* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) { }
|
||||
|
||||
//- Loads database type specific prepared statements
|
||||
void DoPrepareStatements();
|
||||
};
|
||||
|
||||
typedef DatabaseWorkerPool<CharacterDatabaseConnection> CharacterDatabaseWorkerPool;
|
||||
|
||||
enum CharacterDatabaseStatements
|
||||
{
|
||||
/* Naming standard for defines:
|
||||
{DB}_{SEL/INS/UPD/DEL/REP}_{Summary of data changed}
|
||||
When updating more than one field, consider looking at the calling function
|
||||
name for a suiting suffix.
|
||||
*/
|
||||
|
||||
CHAR_DEL_QUEST_POOL_SAVE,
|
||||
CHAR_INS_QUEST_POOL_SAVE,
|
||||
CHAR_DEL_NONEXISTENT_GUILD_BANK_ITEM,
|
||||
CHAR_DEL_EXPIRED_BANS,
|
||||
CHAR_SEL_GUID_BY_NAME,
|
||||
CHAR_SEL_CHECK_NAME,
|
||||
CHAR_SEL_CHECK_GUID,
|
||||
CHAR_SEL_SUM_CHARS,
|
||||
CHAR_SEL_CHAR_CREATE_INFO,
|
||||
CHAR_INS_CHARACTER_BAN,
|
||||
CHAR_UPD_CHARACTER_BAN,
|
||||
CHAR_DEL_CHARACTER_BAN,
|
||||
CHAR_SEL_BANINFO,
|
||||
CHAR_SEL_GUID_BY_NAME_FILTER,
|
||||
CHAR_SEL_BANINFO_LIST,
|
||||
CHAR_SEL_BANNED_NAME,
|
||||
CHAR_SEL_MAIL_LIST_COUNT,
|
||||
CHAR_SEL_MAIL_LIST_INFO,
|
||||
CHAR_SEL_MAIL_LIST_ITEMS,
|
||||
CHAR_SEL_ENUM,
|
||||
CHAR_SEL_ENUM_DELETED,
|
||||
CHAR_SEL_ENUM_DECLINED_NAME,
|
||||
|
||||
// Pet
|
||||
CHAR_SEL_PET,
|
||||
CHAR_INS_PET,
|
||||
CHAR_SEL_PET_DETAIL,
|
||||
CHAR_SEL_PET_BY_ID,
|
||||
CHAR_DEL_CHAR_PET_BY_ID,
|
||||
CHAR_DEL_CHAR_PET_DECLINED_BY_ID,
|
||||
CHAR_DEL_CHAR_PET_AURA_BY_ID,
|
||||
CHAR_DEL_CHAR_PET_SPELL_BY_ID,
|
||||
CHAR_DEL_CHAR_PET_SPELL_COOLDOWN_BY_ID,
|
||||
CHAR_DEL_INVALID_PET_SPELL,
|
||||
|
||||
CHAR_SEL_FREE_NAME,
|
||||
CHAR_SEL_GUID_RACE_ACC_BY_NAME,
|
||||
CHAR_SEL_CHAR_RACE,
|
||||
CHAR_SEL_CHAR_LEVEL,
|
||||
CHAR_SEL_CHAR_ZONE,
|
||||
CHAR_SEL_CHARACTER_NAME_DATA,
|
||||
CHAR_SEL_CHAR_POSITION_XYZ,
|
||||
CHAR_SEL_CHAR_POSITION,
|
||||
CHAR_DEL_QUEST_STATUS_DAILY,
|
||||
CHAR_DEL_QUEST_STATUS_WEEKLY,
|
||||
CHAR_DEL_QUEST_STATUS_SEASONAL,
|
||||
CHAR_DEL_QUEST_STATUS_DAILY_CHAR,
|
||||
CHAR_DEL_QUEST_STATUS_DAILY_ACC,
|
||||
CHAR_DEL_QUEST_STATUS_WEEKLY_CHAR,
|
||||
CHAR_DEL_QUEST_STATUS_WEEKLY_ACC,
|
||||
CHAR_DEL_QUEST_STATUS_SEASONAL_CHAR,
|
||||
CHAR_DEL_QUEST_STATUS_SEASONAL_ACC,
|
||||
|
||||
CHAR_DEL_QUEST_STATUS_C,
|
||||
CHAR_DEL_QUEST_STATUS_DAILY_C,
|
||||
CHAR_DEL_QUEST_STATUS_WEEKLY_C,
|
||||
CHAR_DEL_QUEST_STATUS_SEASONAL_C,
|
||||
|
||||
CHAR_DEL_BATTLEGROUND_RANDOM,
|
||||
CHAR_REP_BATTLEGROUND_RANDOM,
|
||||
|
||||
CHAR_SEL_CHARACTER,
|
||||
CHAR_SEL_GROUP_MEMBER,
|
||||
CHAR_SEL_CHARACTER_INSTANCE,
|
||||
CHAR_SEL_CHARACTER_AURAS,
|
||||
CHAR_SEL_CHARACTER_AURAS_EFFECTS,
|
||||
CHAR_SEL_CHARACTER_SPELL,
|
||||
CHAR_SEL_CHARACTER_QUESTSTATUS,
|
||||
CHAR_SEL_CHARACTER_QUESTSTATUS_OBJECTIVES,
|
||||
CHAR_SEL_CHARACTER_DAILYQUESTSTATUS,
|
||||
CHAR_SEL_CHARACTER_WEEKLYQUESTSTATUS,
|
||||
CHAR_SEL_CHARACTER_SEASONALQUESTSTATUS,
|
||||
CHAR_INS_CHARACTER_DAILYQUESTSTATUS,
|
||||
CHAR_INS_CHARACTER_WEEKLYQUESTSTATUS,
|
||||
CHAR_INS_CHARACTER_SEASONALQUESTSTATUS,
|
||||
CHAR_SEL_CHARACTER_REPUTATION,
|
||||
CHAR_SEL_CHARACTER_INVENTORY,
|
||||
CHAR_SEL_CHARACTER_NOT_INVENTORY,
|
||||
CHAR_SEL_ITEM_INFO,
|
||||
CHAR_SEL_CHARACTER_ACTIONS,
|
||||
CHAR_SEL_CHARACTER_ACTIONS_SPEC,
|
||||
CHAR_SEL_CHARACTER_MAILCOUNT,
|
||||
CHAR_SEL_CHARACTER_MAILDATE,
|
||||
CHAR_SEL_MAIL_COUNT,
|
||||
CHAR_SEL_CHARACTER_SOCIALLIST,
|
||||
CHAR_SEL_CHARACTER_HOMEBIND,
|
||||
CHAR_SEL_CHARACTER_SPELLCOOLDOWNS,
|
||||
CHAR_SEL_CHARACTER_DECLINEDNAMES,
|
||||
CHAR_SEL_GUILD_MEMBER,
|
||||
CHAR_SEL_CHARACTER_BRACKETS,
|
||||
CHAR_REP_CHARACTER_BRACKETS_STATS,
|
||||
CHAR_UPD_CHARACTER_BRACKETS_STATS,
|
||||
CHAR_DEL_PLAYER_BRACKETS_INFO,
|
||||
CHAR_SEL_CHARACTER_ACHIEVEMENTS,
|
||||
CHAR_SEL_ACCOUNT_ACHIEVEMENTS,
|
||||
CHAR_SEL_CHARACTER_CRITERIAPROGRESS,
|
||||
CHAR_SEL_ACCOUNT_CRITERIAPROGRESS,
|
||||
CHAR_SEL_CHARACTER_BGDATA,
|
||||
CHAR_SEL_CHARACTER_GLYPHS,
|
||||
CHAR_SEL_CHARACTER_TALENTS,
|
||||
CHAR_SEL_CHARACTER_PVP_TALENTS,
|
||||
CHAR_SEL_CHARACTER_SKILLS,
|
||||
CHAR_SEL_CHARACTER_RANDOMBG,
|
||||
CHAR_SEL_CHARACTER_BANNED,
|
||||
CHAR_SEL_CHARACTER_QUESTSTATUSREW,
|
||||
CHAR_SEL_ACCOUNT_QUEST,
|
||||
CHAR_SEL_CHARACTER_QUESTSTATUSREW_NON_ACC,
|
||||
CHAR_SEL_MAILITEMS,
|
||||
CHAR_SEL_AUCTION_ITEMS,
|
||||
CHAR_INS_AUCTION,
|
||||
CHAR_DEL_AUCTION,
|
||||
CHAR_SEL_AUCTION_BY_TIME,
|
||||
CHAR_UPD_AUCTION_BID,
|
||||
CHAR_SEL_AUCTIONS,
|
||||
CHAR_INS_MAIL,
|
||||
CHAR_DEL_MAIL_BY_ID,
|
||||
CHAR_INS_MAIL_ITEM,
|
||||
CHAR_DEL_MAIL_ITEM,
|
||||
CHAR_DEL_INVALID_MAIL_ITEM,
|
||||
CHAR_DEL_EMPTY_EXPIRED_MAIL,
|
||||
CHAR_SEL_EXPIRED_MAIL,
|
||||
CHAR_SEL_EXPIRED_MAIL_ITEMS,
|
||||
CHAR_UPD_MAIL_RETURNED,
|
||||
CHAR_UPD_MAIL_ITEM_RECEIVER,
|
||||
CHAR_UPD_ITEM_OWNER,
|
||||
CHAR_SEL_ITEM_REFUNDS,
|
||||
CHAR_SEL_ITEM_BOP_TRADE,
|
||||
CHAR_DEL_ITEM_BOP_TRADE,
|
||||
CHAR_INS_ITEM_BOP_TRADE,
|
||||
CHAR_REP_INVENTORY_ITEM,
|
||||
CHAR_REP_ITEM_INSTANCE,
|
||||
CHAR_UPD_ITEM_INSTANCE,
|
||||
CHAR_UPD_ITEM_INSTANCE_ON_LOAD,
|
||||
CHAR_DEL_ITEM_INSTANCE,
|
||||
CHAR_INS_ITEM_INSTANCE_GEMS,
|
||||
CHAR_DEL_ITEM_INSTANCE_GEMS,
|
||||
CHAR_DEL_ITEM_INSTANCE_GEMS_BY_OWNER,
|
||||
CHAR_INS_ITEM_INSTANCE_TRANSMOG,
|
||||
CHAR_DEL_ITEM_INSTANCE_TRANSMOG,
|
||||
CHAR_DEL_ITEM_INSTANCE_TRANSMOG_BY_OWNER,
|
||||
CHAR_UPD_GIFT_OWNER,
|
||||
CHAR_DEL_GIFT,
|
||||
CHAR_SEL_CHARACTER_GIFT_BY_ITEM,
|
||||
CHAR_SEL_ACCOUNT_BY_NAME,
|
||||
CHAR_SEL_ACCOUNT_BY_GUID,
|
||||
CHAR_SEL_CHARACTER_NAME_CLASS,
|
||||
CHAR_SEL_CHARACTER_NAME,
|
||||
CHAR_SEL_CHARACTER_COUNT,
|
||||
CHAR_UPD_NAME,
|
||||
CHAR_UPD_NAME_LOG,
|
||||
CHAR_SEL_ACCOUNT_NAME_BY_GUID,
|
||||
|
||||
CHAR_INS_GUILD,
|
||||
CHAR_DEL_GUILD,
|
||||
CHAR_INS_GUILD_MEMBER,
|
||||
CHAR_DEL_GUILD_MEMBER,
|
||||
CHAR_DEL_GUILD_MEMBERS,
|
||||
CHAR_UPD_GUILD_MEMBERS_RANK,
|
||||
CHAR_UPD_GUILD_MEMBER_STATS,
|
||||
CHAR_INS_GUILD_RANK,
|
||||
CHAR_DEL_GUILD_RANKS,
|
||||
CHAR_DEL_GUILD_RANK,
|
||||
CHAR_UPD_GUILD_RANK_ID,
|
||||
CHAR_INS_GUILD_BANK_TAB,
|
||||
CHAR_DEL_GUILD_BANK_TAB,
|
||||
CHAR_DEL_GUILD_BANK_TABS,
|
||||
CHAR_INS_GUILD_BANK_ITEM,
|
||||
CHAR_DEL_GUILD_BANK_ITEM,
|
||||
CHAR_DEL_GUILD_BANK_ITEMS,
|
||||
CHAR_SEL_GUILD_BANK_ITEMS,
|
||||
CHAR_INS_GUILD_BANK_RIGHT_DEFAULT,
|
||||
CHAR_INS_GUILD_BANK_RIGHT,
|
||||
CHAR_DEL_GUILD_BANK_RIGHT,
|
||||
CHAR_DEL_GUILD_BANK_RIGHTS,
|
||||
CHAR_DEL_GUILD_BANK_RIGHTS_FOR_RANK,
|
||||
CHAR_UPD_GUILD_BANK_RIGHTS_ID,
|
||||
CHAR_INS_GUILD_BANK_EVENTLOG,
|
||||
CHAR_DEL_GUILD_BANK_EVENTLOG,
|
||||
CHAR_DEL_GUILD_BANK_EVENTLOGS,
|
||||
CHAR_INS_GUILD_EVENTLOG,
|
||||
CHAR_DEL_GUILD_EVENTLOG,
|
||||
CHAR_DEL_GUILD_EVENTLOGS,
|
||||
CHAR_UPD_GUILD_MEMBER_PNOTE,
|
||||
CHAR_UPD_GUILD_MEMBER_OFFNOTE,
|
||||
CHAR_UPD_GUILD_MEMBER_RANK,
|
||||
CHAR_UPD_GUILD_NAME,
|
||||
CHAR_UPD_GUILD_MOTD,
|
||||
CHAR_UPD_GUILD_INFO,
|
||||
CHAR_UPD_GUILD_FLAGS,
|
||||
CHAR_UPD_GUILD_LEADER,
|
||||
CHAR_UPD_GUILD_RANK_NAME,
|
||||
CHAR_UPD_GUILD_RANK_RIGHTS,
|
||||
CHAR_UPD_GUILD_EMBLEM_INFO,
|
||||
CHAR_UPD_GUILD_BANK_TAB_INFO,
|
||||
CHAR_UPD_GUILD_BANK_MONEY,
|
||||
CHAR_UPD_GUILD_BANK_EVENTLOG_TAB,
|
||||
CHAR_UPD_GUILD_MEMBER_BANK_REM_MONEY,
|
||||
CHAR_UPD_GUILD_MEMBER_BANK_TIME_MONEY,
|
||||
CHAR_UPD_GUILD_RANK_BANK_RESET_TIME,
|
||||
CHAR_UPD_GUILD_RANK_BANK_MONEY,
|
||||
CHAR_UPD_GUILD_BANK_TAB_TEXT,
|
||||
CHAR_UPD_GUILD_MEMBER_BANK_TIME_REM_SLOTS0,
|
||||
CHAR_UPD_GUILD_MEMBER_BANK_TIME_REM_SLOTS1,
|
||||
CHAR_UPD_GUILD_MEMBER_BANK_TIME_REM_SLOTS2,
|
||||
CHAR_UPD_GUILD_MEMBER_BANK_TIME_REM_SLOTS3,
|
||||
CHAR_UPD_GUILD_MEMBER_BANK_TIME_REM_SLOTS4,
|
||||
CHAR_UPD_GUILD_MEMBER_BANK_TIME_REM_SLOTS5,
|
||||
CHAR_UPD_GUILD_MEMBER_BANK_TIME_REM_SLOTS6,
|
||||
CHAR_UPD_GUILD_MEMBER_BANK_TIME_REM_SLOTS7,
|
||||
CHAR_UPD_GUILD_MEMBER_BANK_REM_SLOTS0,
|
||||
CHAR_UPD_GUILD_MEMBER_BANK_REM_SLOTS1,
|
||||
CHAR_UPD_GUILD_MEMBER_BANK_REM_SLOTS2,
|
||||
CHAR_UPD_GUILD_MEMBER_BANK_REM_SLOTS3,
|
||||
CHAR_UPD_GUILD_MEMBER_BANK_REM_SLOTS4,
|
||||
CHAR_UPD_GUILD_MEMBER_BANK_REM_SLOTS5,
|
||||
CHAR_UPD_GUILD_MEMBER_BANK_REM_SLOTS6,
|
||||
CHAR_UPD_GUILD_MEMBER_BANK_REM_SLOTS7,
|
||||
CHAR_UPD_GUILD_RANK_BANK_TIME0,
|
||||
CHAR_UPD_GUILD_RANK_BANK_TIME1,
|
||||
CHAR_UPD_GUILD_RANK_BANK_TIME2,
|
||||
CHAR_UPD_GUILD_RANK_BANK_TIME3,
|
||||
CHAR_UPD_GUILD_RANK_BANK_TIME4,
|
||||
CHAR_UPD_GUILD_RANK_BANK_TIME5,
|
||||
CHAR_UPD_GUILD_RANK_BANK_TIME6,
|
||||
CHAR_UPD_GUILD_RANK_BANK_TIME7,
|
||||
CHAR_SEL_CHAR_DATA_FOR_GUILD,
|
||||
CHAR_REP_GUILD_ACHIEVEMENT,
|
||||
CHAR_REP_GUILD_ACHIEVEMENT_CRITERIA,
|
||||
CHAR_UPD_GUILD_ACHIEVEMENT_CRITERIA,
|
||||
CHAR_DEL_GUILD_INVALID_ACHIEV_PROGRESS_CRITERIA,
|
||||
CHAR_DEL_GUILD_ACHIEV_PROGRESS_CRITERIA,
|
||||
CHAR_DEL_ALL_GUILD_ACHIEVEMENTS,
|
||||
CHAR_DEL_ALL_GUILD_ACHIEVEMENT_CRITERIA,
|
||||
CHAR_SEL_GUILD_ACHIEVEMENT,
|
||||
CHAR_SEL_GUILD_ACHIEVEMENT_CRITERIA,
|
||||
CHAR_UPD_GUILD_EXPERIENCE,
|
||||
CHAR_UPD_GUILD_RESET_TODAY_EXPERIENCE,
|
||||
CHAR_LOAD_GUILD_CHALLENGES,
|
||||
CHAR_INIT_GUILD_CHALLENGES,
|
||||
CHAR_COMPLETE_GUILD_CHALLENGE,
|
||||
CHAR_REMOVE_GUILD_CHALLENGES,
|
||||
|
||||
CHAR_INS_GUILD_NEWS,
|
||||
|
||||
CHAR_SEL_PLAYER_ARCHAELOGY,
|
||||
CHAR_SEL_PLAYER_ARCHAEOLOGY_FINDS,
|
||||
CHAR_REP_PLAYER_ARCHAEOLOGY,
|
||||
CHAR_REP_PLAYER_ARCHAEOLOGY_FINDS,
|
||||
|
||||
CHAR_SEL_CHANNEL,
|
||||
CHAR_INS_CHANNEL,
|
||||
CHAR_UPD_CHANNEL,
|
||||
CHAR_UPD_CHANNEL_USAGE,
|
||||
CHAR_UPD_CHANNEL_OWNERSHIP,
|
||||
CHAR_DEL_OLD_CHANNELS,
|
||||
|
||||
CHAR_SEL_CHARACTER_EQUIPMENTSETS,
|
||||
CHAR_SEL_CHARACTER_TRANSMOG_OUTFITS,
|
||||
CHAR_UPD_EQUIP_SET,
|
||||
CHAR_INS_EQUIP_SET,
|
||||
CHAR_DEL_EQUIP_SET,
|
||||
CHAR_UPD_TRANSMOG_OUTFIT,
|
||||
CHAR_INS_TRANSMOG_OUTFIT,
|
||||
CHAR_DEL_TRANSMOG_OUTFIT,
|
||||
|
||||
CHAR_INS_AURA,
|
||||
CHAR_INS_AURA_EFFECT,
|
||||
|
||||
CHAR_SEL_PLAYER_CURRENCY,
|
||||
CHAR_UPD_PLAYER_CURRENCY,
|
||||
CHAR_REP_PLAYER_CURRENCY,
|
||||
|
||||
CHAR_SEL_ACCOUNT_DATA,
|
||||
CHAR_REP_ACCOUNT_DATA,
|
||||
CHAR_DEL_ACCOUNT_DATA,
|
||||
CHAR_SEL_PLAYER_ACCOUNT_DATA,
|
||||
CHAR_REP_PLAYER_ACCOUNT_DATA,
|
||||
CHAR_DEL_PLAYER_ACCOUNT_DATA,
|
||||
|
||||
CHAR_SEL_TUTORIALS,
|
||||
CHAR_SEL_HAS_TUTORIALS,
|
||||
CHAR_INS_TUTORIALS,
|
||||
CHAR_UPD_TUTORIALS,
|
||||
CHAR_DEL_TUTORIALS,
|
||||
|
||||
CHAR_DEL_GAME_EVENT_SAVE,
|
||||
CHAR_INS_GAME_EVENT_SAVE,
|
||||
|
||||
CHAR_DEL_ALL_GAME_EVENT_CONDITION_SAVE,
|
||||
CHAR_DEL_GAME_EVENT_CONDITION_SAVE,
|
||||
CHAR_INS_GAME_EVENT_CONDITION_SAVE,
|
||||
|
||||
CHAR_SEL_PETITION,
|
||||
CHAR_SEL_PETITION_SIGNATURE,
|
||||
CHAR_DEL_ALL_PETITION_SIGNATURES,
|
||||
CHAR_DEL_PETITION_SIGNATURE,
|
||||
CHAR_SEL_PETITION_BY_OWNER,
|
||||
CHAR_SEL_PETITION_TYPE,
|
||||
CHAR_SEL_PETITION_SIGNATURES,
|
||||
CHAR_SEL_PETITION_SIG_BY_ACCOUNT,
|
||||
CHAR_SEL_PETITION_OWNER_BY_GUID,
|
||||
CHAR_SEL_PETITION_SIG_BY_GUID,
|
||||
|
||||
CHAR_INS_PLAYER_BGDATA,
|
||||
CHAR_DEL_PLAYER_BGDATA,
|
||||
|
||||
CHAR_INS_PLAYER_HOMEBIND,
|
||||
CHAR_UPD_PLAYER_HOMEBIND,
|
||||
CHAR_DEL_PLAYER_HOMEBIND,
|
||||
|
||||
CHAR_SEL_CORPSES,
|
||||
CHAR_INS_CORPSE,
|
||||
CHAR_DEL_CORPSE,
|
||||
CHAR_DEL_PLAYER_CORPSES,
|
||||
CHAR_DEL_OLD_CORPSES,
|
||||
|
||||
CHAR_SEL_CREATURE_RESPAWNS,
|
||||
CHAR_REP_CREATURE_RESPAWN,
|
||||
CHAR_DEL_CREATURE_RESPAWN,
|
||||
CHAR_DEL_CREATURE_RESPAWN_BY_INSTANCE,
|
||||
CHAR_SEL_MAX_CREATURE_RESPAWNS,
|
||||
|
||||
CHAR_SEL_GO_RESPAWNS,
|
||||
CHAR_REP_GO_RESPAWN,
|
||||
CHAR_DEL_GO_RESPAWN,
|
||||
CHAR_DEL_GO_RESPAWN_BY_INSTANCE,
|
||||
|
||||
CHAR_SEL_GM_TICKETS,
|
||||
CHAR_REP_GM_TICKET,
|
||||
CHAR_DEL_GM_TICKET,
|
||||
CHAR_DEL_ALL_GM_TICKETS,
|
||||
CHAR_DEL_PLAYER_GM_TICKETS,
|
||||
|
||||
CHAR_INS_GM_SURVEY,
|
||||
CHAR_INS_GM_SUBSURVEY,
|
||||
|
||||
CHAR_SEL_EXPIRED_AUCTIONS,
|
||||
|
||||
CHAR_INS_CHARACTER,
|
||||
CHAR_UPD_CHARACTER,
|
||||
|
||||
CHAR_UPD_ADD_AT_LOGIN_FLAG,
|
||||
CHAR_UPD_REM_AT_LOGIN_FLAG,
|
||||
CHAR_UPD_ALL_AT_LOGIN_FLAGS,
|
||||
CHAR_INS_BUG_REPORT,
|
||||
CHAR_UPD_PETITION_NAME,
|
||||
CHAR_INS_PETITION_SIGNATURE,
|
||||
CHAR_UPD_ACCOUNT_ONLINE,
|
||||
CHAR_INS_GROUP,
|
||||
CHAR_INS_GROUP_MEMBER,
|
||||
CHAR_DEL_GROUP_MEMBER,
|
||||
CHAR_DEL_GROUP_INSTANCE_PERM_BINDING,
|
||||
CHAR_UPD_GROUP_LEADER,
|
||||
CHAR_UPD_GROUP_TYPE,
|
||||
CHAR_UPD_GROUP_MEMBER_SUBGROUP,
|
||||
CHAR_UPD_GROUP_MEMBER_FLAG,
|
||||
CHAR_UPD_GROUP_MEMBER_ROLE,
|
||||
CHAR_UPD_GROUP_DIFFICULTY,
|
||||
CHAR_UPD_GROUP_RAID_DIFFICULTY,
|
||||
CHAR_UPD_GROUP_LEGACY_RAID_DIFFICULTY,
|
||||
CHAR_DEL_INVALID_SPELL,
|
||||
CHAR_DEL_INVALID_TALENT,
|
||||
CHAR_DEL_INVALID_TALENT_PVP,
|
||||
CHAR_UPD_DELETE_INFO,
|
||||
CHAR_UDP_RESTORE_DELETE_INFO,
|
||||
CHAR_UPD_ZONE,
|
||||
CHAR_UPD_LEVEL,
|
||||
CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA,
|
||||
CHAR_DEL_CHAR_ACHIEV_PROGRESS_CRITERIA,
|
||||
CHAR_DEL_INVALID_ACC_ACHIEV_PROGRESS_CRITERIA,
|
||||
CHAR_DEL_ACC_ACHIEV_PROGRESS_CRITERIA,
|
||||
CHAR_DEL_INVALID_ACHIEVMENT,
|
||||
CHAR_INS_ADDON,
|
||||
CHAR_DEL_GROUP_INSTANCE_BY_INSTANCE,
|
||||
CHAR_DEL_GROUP_INSTANCE_BY_GUID,
|
||||
CHAR_REP_GROUP_INSTANCE,
|
||||
CHAR_UPD_CHAR_ONLINE,
|
||||
CHAR_UPD_CHAR_NAME_AT_LOGIN,
|
||||
CHAR_UPD_WORLDSTATE,
|
||||
CHAR_INS_WORLDSTATE,
|
||||
CHAR_DEL_CHAR_INSTANCE_BY_INSTANCE_GUID,
|
||||
CHAR_UPD_CHAR_INSTANCE,
|
||||
CHAR_REP_CHAR_INSTANCE,
|
||||
CHAR_UPD_CHAR_INSTANCE_EXTENDED,
|
||||
CHAR_UPD_GENDER_PLAYERBYTES,
|
||||
CHAR_DEL_CHARACTER_SKILL,
|
||||
CHAR_UPD_ADD_CHARACTER_SOCIAL_FLAGS,
|
||||
CHAR_UPD_REM_CHARACTER_SOCIAL_FLAGS,
|
||||
CHAR_INS_CHARACTER_SOCIAL,
|
||||
CHAR_DEL_CHARACTER_SOCIAL,
|
||||
CHAR_UPD_CHARACTER_SOCIAL_NOTE,
|
||||
CHAR_UPD_CHARACTER_POSITION,
|
||||
|
||||
CHAR_INS_LFG_DATA,
|
||||
CHAR_DEL_LFG_DATA,
|
||||
|
||||
CHAR_SEL_CHARACTER_AURA_FROZEN,
|
||||
CHAR_SEL_CHARACTER_ONLINE,
|
||||
|
||||
CHAR_SEL_CHAR_DEL_INFO_BY_GUID,
|
||||
CHAR_SEL_CHAR_DEL_INFO_BY_NAME,
|
||||
CHAR_SEL_CHAR_DEL_INFO,
|
||||
|
||||
CHAR_SEL_CHARS_BY_ACCOUNT_ID,
|
||||
CHAR_SEL_CHAR_PINFO,
|
||||
CHAR_SEL_PINFO_BANS,
|
||||
CHAR_SEL_CHAR_HOMEBIND,
|
||||
CHAR_SEL_CHAR_GUID_NAME_BY_ACC,
|
||||
CHAR_SEL_POOL_QUEST_SAVE,
|
||||
CHAR_SEL_CHAR_CUSTOMIZE_INFO,
|
||||
CHAR_SEL_CHAR_CLASS_LVL_AT_LOGIN,
|
||||
CHAR_SEL_PET_SPELL_LIST,
|
||||
CHAR_SEL_CHAR_PET,
|
||||
CHAR_SEL_CHAR_PETS,
|
||||
CHAR_SEL_CHAR_COD_ITEM_MAIL,
|
||||
CHAR_SEL_CHAR_SOCIAL,
|
||||
CHAR_SEL_PET_AURA,
|
||||
CHAR_SEL_PET_AURA_EFFECT,
|
||||
CHAR_SEL_CHAR_OLD_CHARS,
|
||||
CHAR_SEL_MAIL,
|
||||
CHAR_SEL_PET_SPELL,
|
||||
CHAR_SEL_PET_SPELL_COOLDOWN,
|
||||
CHAR_SEL_PET_DECLINED_NAME,
|
||||
CHAR_SEL_CHAR_GUID_BY_NAME,
|
||||
CHAR_DEL_CHAR_AURA_FROZEN,
|
||||
CHAR_SEL_CHAR_INVENTORY_COUNT_ITEM,
|
||||
CHAR_SEL_MAIL_COUNT_ITEM,
|
||||
CHAR_SEL_AUCTIONHOUSE_COUNT_ITEM,
|
||||
CHAR_SEL_GUILD_BANK_COUNT_ITEM,
|
||||
CHAR_SEL_CHAR_INVENTORY_ITEM_BY_ENTRY,
|
||||
CHAR_SEL_MAIL_ITEMS_BY_ENTRY,
|
||||
CHAR_SEL_AUCTIONHOUSE_ITEM_BY_ENTRY,
|
||||
CHAR_SEL_GUILD_BANK_ITEM_BY_ENTRY,
|
||||
CHAR_DEL_ACCOUNT_ACHIEVEMENT,
|
||||
CHAR_DEL_CHAR_ACHIEVEMENT,
|
||||
CHAR_DEL_CHAR_ACHIEVEMENT_PROGRESS,
|
||||
CHAR_REP_CHAR_REPUTATION_BY_FACTION,
|
||||
CHAR_DEL_ITEM_REFUND_INSTANCE,
|
||||
CHAR_INS_ITEM_REFUND_INSTANCE,
|
||||
CHAR_DEL_GROUP,
|
||||
CHAR_DEL_GROUP_MEMBER_ALL,
|
||||
CHAR_INS_CHAR_GIFT,
|
||||
CHAR_DEL_CHAR_INSTANCE_BY_INSTANCE,
|
||||
CHAR_DEL_CHAR_INSTANCE_BY_MAP_DIFF,
|
||||
CHAR_DEL_GROUP_INSTANCE_BY_MAP_DIFF,
|
||||
CHAR_DEL_MAIL_ITEM_BY_ID,
|
||||
CHAR_DEL_CHAR_PET_DECLINEDNAME,
|
||||
CHAR_ADD_CHAR_PET_DECLINEDNAME,
|
||||
CHAR_UPD_CHAR_PET_NAME,
|
||||
CHAR_INS_PETITION,
|
||||
CHAR_DEL_PETITION_BY_GUID,
|
||||
CHAR_DEL_PETITION_SIGNATURE_BY_GUID,
|
||||
CHAR_DEL_PET_AURAS,
|
||||
CHAR_DEL_PET_AURAS_EFFECTS,
|
||||
CHAR_DEL_PET_SPELLS,
|
||||
CHAR_DEL_PET_SPELL_COOLDOWNS,
|
||||
CHAR_INS_PET_SPELL_COOLDOWN,
|
||||
CHAR_DEL_PET_SPELL_BY_SPELL,
|
||||
CHAR_INS_PET_SPELL,
|
||||
CHAR_INS_PET_AURA,
|
||||
CHAR_INS_PET_AURA_EFFECT,
|
||||
CHAR_DEL_CHAR_DECLINED_NAME,
|
||||
CHAR_INS_CHAR_DECLINED_NAME,
|
||||
CHAR_UPD_FACTION_OR_RACE,
|
||||
CHAR_UPD_FACTION_OR_RACE_LOG,
|
||||
CHAR_DEL_CHAR_SKILL_LANGUAGES,
|
||||
CHAR_INS_CHAR_SKILL_LANGUAGE,
|
||||
CHAR_UPD_CHAR_TAXI_PATH,
|
||||
CHAR_UPD_CHAR_TAXIMASK,
|
||||
CHAR_DEL_CHAR_QUESTSTATUS,
|
||||
CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES,
|
||||
CHAR_DEL_CHAR_SOCIAL_BY_GUID,
|
||||
CHAR_DEL_CHAR_SOCIAL_BY_FRIEND,
|
||||
CHAR_DEL_CHAR_ACHIEVEMENT_BY_ACHIEVEMENT,
|
||||
CHAR_UPD_CHAR_ACHIEVEMENT,
|
||||
CHAR_UPD_CHAR_INVENTORY_FACTION_CHANGE,
|
||||
CHAR_DEL_CHAR_SPELL_BY_SPELL,
|
||||
CHAR_UPD_CHAR_SPELL_FACTION_CHANGE,
|
||||
CHAR_DEL_CHAR_REP_BY_FACTION,
|
||||
CHAR_UPD_CHAR_REP_FACTION_CHANGE,
|
||||
CHAR_UPD_CHAR_REP_STANDING_CHANGE,
|
||||
CHAR_UPD_CHAR_REP_FLAGS_CHANGE,
|
||||
CHAR_UPD_CHAR_TITLES_FACTION_CHANGE,
|
||||
CHAR_RES_CHAR_TITLES_FACTION_CHANGE,
|
||||
CHAR_DEL_CHAR_SPELL_COOLDOWN,
|
||||
CHAR_DEL_CHARACTER,
|
||||
CHAR_DEL_CHAR_ACTION,
|
||||
CHAR_DEL_CHAR_AURA,
|
||||
CHAR_DEL_CHAR_AURA_EFFECT,
|
||||
CHAR_DEL_CHAR_GIFT,
|
||||
CHAR_DEL_CHAR_INSTANCE,
|
||||
CHAR_DEL_CHAR_INVENTORY,
|
||||
CHAR_DEL_CHAR_QUESTSTATUS_REWARDED,
|
||||
CHAR_DEL_CHAR_REPUTATION,
|
||||
CHAR_DEL_CHAR_SPELL,
|
||||
CHAR_DEL_MAIL,
|
||||
CHAR_DEL_MAIL_ITEMS,
|
||||
CHAR_DEL_CHAR_PET_BY_OWNER,
|
||||
CHAR_DEL_CHAR_PET_DECLINEDNAME_BY_OWNER,
|
||||
CHAR_DEL_CHAR_ACHIEVEMENTS,
|
||||
CHAR_DEL_CHAR_EQUIPMENTSETS,
|
||||
CHAR_DEL_GUILD_EVENTLOG_BY_PLAYER,
|
||||
CHAR_DEL_GUILD_BANK_EVENTLOG_BY_PLAYER,
|
||||
CHAR_DEL_CHAR_GLYPHS,
|
||||
CHAR_DEL_CHAR_QUESTSTATUS_DAILY,
|
||||
CHAR_DEL_CHAR_TALENT,
|
||||
CHAR_DEL_CHAR_TALENT_PVP,
|
||||
CHAR_DEL_CHAR_SKILLS,
|
||||
CHAR_UDP_CHAR_MONEY,
|
||||
CHAR_INS_CHAR_ACTION,
|
||||
CHAR_UPD_CHAR_ACTION,
|
||||
CHAR_DEL_CHAR_ACTION_BY_BUTTON_SPEC,
|
||||
CHAR_DEL_CHAR_INVENTORY_BY_ITEM,
|
||||
CHAR_DEL_CHAR_INVENTORY_BY_BAG_SLOT,
|
||||
CHAR_UPD_MAIL,
|
||||
CHAR_REP_CHAR_QUESTSTATUS,
|
||||
CHAR_DEL_CHAR_QUESTSTATUS_BY_QUEST,
|
||||
CHAR_REP_CHAR_QUESTSTATUS_OBJECTIVES,
|
||||
CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_BY_QUEST,
|
||||
CHAR_DEL_ACC_QUESTSTATUS_BY_QUEST,
|
||||
CHAR_DEL_ACC_QUESTSTATUS_OBJECTIVES_BY_QUEST,
|
||||
CHAR_INS_CHAR_QUESTSTATUS,
|
||||
CHAR_DEL_CHAR_QUESTSTATUS_REWARDED_BY_QUEST,
|
||||
CHAR_DEL_ACC_QUESTSTATUS_REWARDED_BY_QUEST,
|
||||
CHAR_DEL_CHAR_SKILL_BY_SKILL,
|
||||
CHAR_INS_CHAR_SKILLS,
|
||||
CHAR_UDP_CHAR_SKILLS,
|
||||
CHAR_INS_CHAR_SPELL,
|
||||
CHAR_DEL_PETITION_BY_OWNER,
|
||||
CHAR_DEL_PETITION_SIGNATURE_BY_OWNER,
|
||||
CHAR_INS_CHAR_GLYPHS,
|
||||
CHAR_DEL_CHAR_TALENT_BY_SPELL_SPEC,
|
||||
CHAR_INS_CHAR_TALENT,
|
||||
CHAR_DEL_CHAR_ACTION_EXCEPT_SPEC,
|
||||
CHAR_UPD_CHAR_LIST_SLOT,
|
||||
CHAR_DEL_CHAR_TALENT_PVP_BY_SPELL_SPEC,
|
||||
CHAR_INS_CHAR_TALENT_PVP,
|
||||
|
||||
CHAR_SEL_CHAR_VOID_STORAGE,
|
||||
CHAR_SEL_CHAR_VOID_STORAGE_ITEM,
|
||||
CHAR_REP_CHAR_VOID_STORAGE_ITEM,
|
||||
CHAR_DEL_CHAR_VOID_STORAGE_ITEM_BY_SLOT,
|
||||
CHAR_DEL_CHAR_VOID_STORAGE_ITEM,
|
||||
|
||||
CHAR_REP_GUILD_FINDER_APPLICANT,
|
||||
CHAR_DEL_GUILD_FINDER_APPLICANT,
|
||||
CHAR_REP_GUILD_FINDER_GUILD_SETTINGS,
|
||||
CHAR_DEL_GUILD_FINDER_GUILD_SETTINGS,
|
||||
|
||||
CHAR_INS_CHALLENGE,
|
||||
CHAR_INS_CHALLENGE_MEMBER,
|
||||
CHAR_DEL_CHALLENGE_MEMBER,
|
||||
CHAR_INS_CHALLENGE_OPLOTE_LOOT,
|
||||
CHAR_DEL_CHALLENGE_OPLOTE_LOOT,
|
||||
CHAR_DEL_CHALLENGE_OPLOTE_LOOT_BY_GUID,
|
||||
|
||||
CHAR_SEL_CUF_PROFILES,
|
||||
CHAR_REP_CUF_PROFILES,
|
||||
|
||||
CHAR_SEL_PETBATTLE_ACCOUNT,
|
||||
CHAR_REP_PETBATTLE,
|
||||
CHAR_INS_PETBATTLE,
|
||||
CHAR_DEL_PETBATTLE,
|
||||
|
||||
CHAR_SEL_PERSONAL_RATE,
|
||||
CHAR_SEL_PLAYER_VISUAL,
|
||||
CHAR_SEL_MAILBOX_QUEUE,
|
||||
CHAR_DEL_MAILBOX_QUEUE,
|
||||
|
||||
CHAR_ADD_ITEM_DONATE,
|
||||
CHAR_ITEM_DONATE_SET_STATE,
|
||||
|
||||
CHAR_SEL_PLAYER_KILL,
|
||||
CHAR_DEL_PLAYER_KILL,
|
||||
CHAR_REP_PLAYER_KILL,
|
||||
CHAR_UPD_PLAYER_KILL,
|
||||
|
||||
CHAR_SEL_HONOR_INFO,
|
||||
CHAR_UPD_HONOR_INFO_HONOR,
|
||||
CHAR_UPD_HONOR_INFO_HONOR_LEVEL,
|
||||
CHAR_UPD_HONOR_INFO_PRESTIGE_LEVEL,
|
||||
CHAR_REP_HONOR_INFO,
|
||||
|
||||
CHAR_SEL_PLAYER_LOOTCOOLDOWN,
|
||||
CHAR_INS_PLAYER_LOOTCOOLDOWN,
|
||||
CHAR_SEL_PLAYER_LFGCOOLDOWN,
|
||||
CHAR_INS_PLAYER_LFGCOOLDOWN,
|
||||
|
||||
CHAR_SEL_LAST_CHAR_UNDELETE,
|
||||
CHAR_UPD_LAST_CHAR_UNDELETE,
|
||||
CHAR_UPD_RESTORE_DELETE_INFO,
|
||||
|
||||
CHAR_SEL_BLACKMARKET_AUCTIONS,
|
||||
CHAR_DEL_BLACKMARKET_AUCTIONS,
|
||||
CHAR_UPD_BLACKMARKET_AUCTIONS,
|
||||
CHAR_INS_BLACKMARKET_AUCTIONS,
|
||||
|
||||
CHAR_REP_CALENDAR_EVENT,
|
||||
CHAR_DEL_CALENDAR_EVENT,
|
||||
CHAR_REP_CALENDAR_INVITE,
|
||||
CHAR_DEL_CALENDAR_INVITE,
|
||||
|
||||
CHAR_SEL_CHARACTER_GARRISON,
|
||||
CHAR_INS_CHARACTER_GARRISON,
|
||||
CHAR_UPD_CHARACTER_GARRISON,
|
||||
CHAR_DEL_CHARACTER_GARRISON,
|
||||
CHAR_DEL_CHARACTER_GARRISON_ONLY,
|
||||
CHAR_DEL_CHARACTER_GARRISON_BY_SITE,
|
||||
|
||||
CHAR_UPD_CHARACTER_GARRISON_FOLLOWER_ACTIVATIONS,
|
||||
|
||||
CHAR_SEL_CHARACTER_GARRISON_BLUEPRINTS,
|
||||
CHAR_INS_CHARACTER_GARRISON_BLUEPRINTS,
|
||||
CHAR_DEL_CHARACTER_GARRISON_BLUEPRINTS,
|
||||
CHAR_DEL_CHARACTER_GARRISON_BLUEPRINTS_BY_BUILD,
|
||||
|
||||
CHAR_SEL_CHARACTER_GARRISON_BUILDINGS,
|
||||
CHAR_INS_CHARACTER_GARRISON_BUILDINGS,
|
||||
CHAR_DEL_CHARACTER_GARRISON_BUILDINGS,
|
||||
CHAR_DEL_CHARACTER_GARRISON_BUILDINGS_BY_PLOT,
|
||||
|
||||
CHAR_SEL_CHARACTER_GARRISON_FOLLOWERS,
|
||||
CHAR_INS_CHARACTER_GARRISON_FOLLOWERS,
|
||||
CHAR_DEL_CHARACTER_GARRISON_FOLLOWERS,
|
||||
CHAR_DEL_CHARACTER_GARRISON_FOLLOWER,
|
||||
CHAR_DEL_CHARACTER_GARRISON_FOLLOWER_BY_DBID,
|
||||
|
||||
CHAR_SEL_CHARACTER_GARRISON_FOLLOWER_ABILITIES,
|
||||
CHAR_INS_CHARACTER_GARRISON_FOLLOWER_ABILITIES,
|
||||
CHAR_DEL_CHARACTER_GARRISON_FOLLOWER_ABILITIES,
|
||||
|
||||
CHAR_SEL_CHARACTER_GARRISON_MISSIONS,
|
||||
CHAR_INS_CHARACTER_GARRISON_MISSIONS,
|
||||
CHAR_DEL_CHARACTER_GARRISON_MISSIONS,
|
||||
CHAR_DEL_CHARACTER_GARRISON_MISSIONS_DB_ID,
|
||||
|
||||
CHAR_SEL_CHARACTER_GARRISON_SHIPMENTS,
|
||||
CHAR_INS_CHARACTER_GARRISON_SHIPMENTS,
|
||||
CHAR_DEL_CHARACTER_GARRISON_SHIPMENTS,
|
||||
CHAR_DEL_CHARACTER_GARRISON_SHIPMENTS_DBID,
|
||||
CHAR_DEL_CHARACTER_GARRISON_SHIPMENTS_BY_DB_ID,
|
||||
|
||||
CHAR_SEL_CHARACTER_GARRISON_TALENTS,
|
||||
CHAR_INS_CHARACTER_GARRISON_TALENTS,
|
||||
CHAR_DEL_CHARACTER_GARRISON_TALENTS,
|
||||
CHAR_DEL_CHARACTER_GARRISON_TALENT_BY_ID,
|
||||
|
||||
CHAR_SEL_TOYS,
|
||||
CHAR_REP_TOYS,
|
||||
|
||||
CHAR_SEL_HEIRLOOMS,
|
||||
CHAR_REP_HEIRLOOMS,
|
||||
|
||||
CHAR_SEL_CHARACTER_COMPLAINTS,
|
||||
CHAR_INS_CHARACTER_COMPLAINTS,
|
||||
|
||||
CHAR_SEL_TRANSMOGS,
|
||||
CHAR_REP_TRANSMOGS,
|
||||
CHAR_DEL_TRANSMOG,
|
||||
CHAR_SEL_BNET_ITEM_FAVORITE_APPEARANCES,
|
||||
CHAR_INS_BNET_ITEM_FAVORITE_APPEARANCE,
|
||||
CHAR_DEL_BNET_ITEM_FAVORITE_APPEARANCE,
|
||||
|
||||
CHAR_SEL_ITEM_INSTANCE_ARTIFACT,
|
||||
CHAR_REP_ITEM_INSTANCE_ARTIFACT,
|
||||
CHAR_DEL_ITEM_INSTANCE_ARTIFACT,
|
||||
CHAR_DEL_ITEM_INSTANCE_ARTIFACT_BY_OWNER,
|
||||
CHAR_SEL_ITEM_INSTANCE_ARTIFACT_XP,
|
||||
|
||||
CHAR_SEL_ITEM_INSTANCE_ARTIFACT_POWERS,
|
||||
CHAR_REP_ITEM_INSTANCE_ARTIFACT_POWERS,
|
||||
CHAR_DEL_ITEM_INSTANCE_ARTIFACT_POWERS,
|
||||
CHAR_DEL_ITEM_INSTANCE_ARTIFACT_POWERS_BY_OWNER,
|
||||
CHAR_INS_ITEM_INSTANCE_MODIFIERS,
|
||||
CHAR_DEL_ITEM_INSTANCE_MODIFIERS,
|
||||
CHAR_DEL_ITEM_INSTANCE_MODIFIERS_BY_OWNER,
|
||||
CHAR_REP_ITEM_INSTANCE_RELICS,
|
||||
CHAR_DEL_ITEM_INSTANCE_RELICS,
|
||||
CHAR_SEL_ITEM_INSTANCE_RELICS,
|
||||
|
||||
CHAR_SEL_MOUNTS,
|
||||
CHAR_REP_MOUNTS,
|
||||
|
||||
CHAR_SEL_CHARACTER_ADVENTURE_QUEST,
|
||||
CHAR_DEL_CHARACTER_ADVENTURE_QUEST,
|
||||
CHAR_REP_CHARACTER_ADVENTURE_QUEST,
|
||||
|
||||
CHAR_REP_WORLD_QUEST,
|
||||
CHAR_DEL_WORLD_QUEST_BY_ID,
|
||||
CHAR_DEL_WORLD_QUEST_BY_TIMER,
|
||||
|
||||
CHAR_SEL_CHARACTER_WORLDQUESTSTATUS,
|
||||
CHAR_INS_CHARACTER_WORLDQUESTSTATUS,
|
||||
CHAR_DEL_QUEST_STATUS_WORLD,
|
||||
|
||||
CHAR_DEL_WORLD_STATE_BY_STATE_INSTANCE,
|
||||
CHAR_INS_WORLD_STAT,
|
||||
|
||||
CHAR_SEL_CHALLENGE_KEY,
|
||||
CHAR_UPD_CHALLENGE_KEY,
|
||||
CHAR_INS_CHALLENGE_KEY,
|
||||
CHAR_DEL_CHALLENGE_KEY,
|
||||
|
||||
CHAR_SEL_PLAYER_DEATHMATCH,
|
||||
CHAR_REP_PLAYER_DEATHMATCH,
|
||||
|
||||
CHAR_SEL_PLAYER_DEATHMATCH_STORE,
|
||||
CHAR_REP_PLAYER_DEATHMATCH_STORE,
|
||||
|
||||
CHAR_SEL_PLAYER_CHAT_LOGOS,
|
||||
CHAR_REP_PLAYER_CHAT_LOGOS,
|
||||
|
||||
CHAR_SEL_ARMY_TRAINING_INFO,
|
||||
CHAR_REP_ARMY_TRAINING_INFO,
|
||||
|
||||
CHAR_SEL_ACCOUNT_PROGRESS,
|
||||
CHAR_REP_ACCOUNT_PROGRESS,
|
||||
|
||||
CHAR_REP_BAD_SENTENCES,
|
||||
CHAR_UPD_BAD_SENTENCES,
|
||||
|
||||
CHAR_UPD_WEEKLY_BRACKET,
|
||||
|
||||
CHAR_DEL_WARDEN_BAN_ATTEMPTS,
|
||||
CHAR_INS_WARDEN_BAN_ATTEMPTS,
|
||||
CHAR_SEL_WARDEN_BAN_ATTEMPTS,
|
||||
CHAR_UPD_WARDEN_BAN_ATTEMPTS,
|
||||
|
||||
CHAR_SEL_ACCOUNT_FLAGGED,
|
||||
CHAR_SEL_ACCOUNT_FLAGGED_ALL,
|
||||
CHAR_DEL_ACCOUNT_FLAGGED,
|
||||
CHAR_INS_ACCOUNT_FLAGGED,
|
||||
|
||||
CHAR_INS_BOT_ACCOUNT,
|
||||
|
||||
CHAR_SEL_KILL_CREATURE,
|
||||
CHAR_INS_KILL_CREATURE,
|
||||
CHAR_UPD_KILL_CREATURE,
|
||||
|
||||
CHAR_SEL_NUM_ACCOUNT_CHARS_REACHED_LEVEL,
|
||||
|
||||
MAX_CHARACTERDATABASE_STATEMENTS
|
||||
};
|
||||
|
||||
#endif
|
||||
2651
src/common/Database/Implementation/HotfixDatabase.cpp
Normal file
2651
src/common/Database/Implementation/HotfixDatabase.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1469
src/common/Database/Implementation/HotfixDatabase.h
Normal file
1469
src/common/Database/Implementation/HotfixDatabase.h
Normal file
File diff suppressed because it is too large
Load Diff
116
src/common/Database/Implementation/LoginDatabase.cpp
Normal file
116
src/common/Database/Implementation/LoginDatabase.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "LoginDatabase.h"
|
||||
|
||||
void LoginDatabaseConnection::DoPrepareStatements()
|
||||
{
|
||||
if (!m_reconnecting)
|
||||
m_stmts.resize(MAX_LOGINDATABASE_STATEMENTS);
|
||||
|
||||
PrepareStatement(LOGIN_SEL_REALMLIST, "SELECT id, name, address, localAddress, localSubnetMask, port, icon, flag, timezone, allowedSecurityLevel, population, gamebuild, Region, Battlegroup FROM realmlist WHERE flag <> 3 ORDER BY name", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_DEL_EXPIRED_IP_BANS, "DELETE FROM ip_banned WHERE unbandate<>bandate AND unbandate<=UNIX_TIMESTAMP()", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_UPD_EXPIRED_ACCOUNT_BANS, "UPDATE account_banned SET active = 0 WHERE active = 1 AND unbandate<>bandate AND unbandate<=UNIX_TIMESTAMP()", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_SEL_IP_INFO, "SELECT * FROM ip_banned WHERE ip = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_IP_BANNED_ALL, "SELECT ip, bandate, unbandate, bannedby, banreason FROM ip_banned WHERE (bandate = unbandate OR unbandate > UNIX_TIMESTAMP()) ORDER BY unbandate", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_IP_BANNED_BY_IP, "SELECT ip, bandate, unbandate, bannedby, banreason FROM ip_banned WHERE (bandate = unbandate OR unbandate > UNIX_TIMESTAMP()) AND ip LIKE CONCAT('%%', ?, '%%') ORDER BY unbandate", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_BANNED, "SELECT bandate, unbandate FROM account_banned WHERE id = ? AND active = 1", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_BANNED_ALL, "SELECT account.id, username FROM account, account_banned WHERE account.id = account_banned.id AND active = 1 GROUP BY account.id", CONNECTION_BOTH);
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_BANNED_BY_USERNAME, "SELECT account.id, username FROM account, account_banned WHERE account.id = account_banned.id AND active = 1 AND username LIKE CONCAT('%%', ?, '%%') GROUP BY account.id", CONNECTION_BOTH);
|
||||
PrepareStatement(LOGIN_DEL_ACCOUNT_BANNED, "DELETE FROM account_banned WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_ID_BY_NAME, "SELECT id, hwid FROM account WHERE username = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_LIST_BY_NAME, "SELECT id, username FROM account WHERE username = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME, "SELECT a.id, a.sessionkey, a.last_ip, a.first_ip, a.locked, a.lock_country, a.expansion, a.mutetime, a.locale, a.recruiter, a.os, aa.gmLevel, a.AtAuthFlag, a.referer, ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, r.id, a.hwid FROM account a LEFT JOIN account r ON a.id = r.recruiter LEFT JOIN account_access aa ON a.id = aa.id AND aa.RealmID IN (-1, ?) LEFT JOIN account_banned ab ON a.id = ab.id AND ab.active = 1 WHERE a.username = ? ORDER BY aa.RealmID DESC LIMIT 1", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_BY_IP, "SELECT id, username FROM account WHERE last_ip = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_BY_ID, "SELECT 1 FROM account WHERE id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_INS_IP_BANNED, "INSERT INTO ip_banned VALUES (?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_DEL_IP_NOT_BANNED, "DELETE FROM ip_banned WHERE ip = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_INS_ACCOUNT_BANNED, "INSERT INTO account_banned VALUES (?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+?, ?, ?, 1)", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_UPD_ACCOUNT_BANNED, "UPDATE account_banned SET unbandate = unbandate + ? WHERE id = ? AND active = 1", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_UPD_ACCOUNT_NOT_BANNED, "UPDATE account_banned SET active = 0 WHERE id = ? AND active != 0", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_DEL_REALM_CHARACTERS_BY_REALM, "DELETE FROM realmcharacters WHERE acctid = ? AND realmid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_DEL_REALM_CHARACTERS, "DELETE FROM realmcharacters WHERE acctid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_INS_REALM_CHARACTERS, "REPLACE INTO realmcharacters (numchars, acctid, realmid) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_SEL_SUM_REALM_CHARACTERS, "SELECT SUM(numchars) FROM realmcharacters WHERE acctid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_INS_ACCOUNT, "INSERT INTO account(username, sha_pass_hash, joindate) VALUES(?, ?, NOW())", CONNECTION_BOTH);
|
||||
PrepareStatement(LOGIN_INS_REALM_CHARACTERS_INIT, "INSERT INTO realmcharacters (realmid, acctid, numchars) SELECT realmlist.id, account.id, 0 FROM realmlist, account LEFT JOIN realmcharacters ON acctid=account.id WHERE acctid IS NULL", CONNECTION_BOTH);
|
||||
PrepareStatement(LOGIN_UPD_EXPANSION, "UPDATE account SET expansion = ? WHERE id = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(LOGIN_UPD_ACCOUNT_LOCK, "UPDATE account SET locked = ? WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_INS_LOG, "INSERT INTO logs (time, realm, type, level, string) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_UPD_USERNAME, "UPDATE account SET v = 0, s = 0, username = ?, sha_pass_hash = ? WHERE id = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(LOGIN_UPD_PASSWORD, "UPDATE account SET v = 0, s = 0, sha_pass_hash = ? WHERE id = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(LOGIN_UPD_MUTE_TIME, "UPDATE account SET mutetime = ? WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_UPD_LAST_IP, "UPDATE account SET last_ip = ? WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_UPD_FIRST_IP, "UPDATE account SET first_ip = ? WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_SEL_EXPANSION_FIRST_IP, "SELECT 1 FROM account WHERE first_ip = ? AND expansion = 6", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_UPD_ACCOUNT_ONLINE, "UPDATE account SET online = 1 WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_UPD_UPTIME_PLAYERS, "UPDATE uptime SET uptime = ?, maxplayers = ? WHERE realmid = ? AND starttime = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_DEL_OLD_LOGS, "DELETE FROM logs WHERE (time + ?) < ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_DEL_ACCOUNT_ACCESS, "DELETE FROM account_access WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_DEL_ACCOUNT_ACCESS_BY_REALM, "DELETE FROM account_access WHERE id = ? AND (RealmID = ? OR RealmID = -1)", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_INS_ACCOUNT_ACCESS, "INSERT INTO account_access (id,gmlevel,RealmID) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_GET_ACCOUNT_ID_BY_USERNAME, "SELECT id FROM account WHERE username = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_GET_ACCOUNT_ID_FOR_ACCOUNT_CONVERT, "SELECT id FROM account WHERE (username = ? OR email = ?) AND expansion < 5 LIMIT 1", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_GET_ACCOUNT_ACCESS_GMLEVEL, "SELECT gmlevel FROM account_access WHERE id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_GET_GMLEVEL_BY_REALMID, "SELECT gmlevel FROM account_access WHERE id = ? AND (RealmID = ? OR RealmID = -1)", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_GET_USERNAME_BY_ID, "SELECT username FROM account WHERE id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_GET_EMAIL_BY_ID_FOR_ACCOUNT_CONVERT, "SELECT email FROM account WHERE id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_CHECK_PASSWORD, "SELECT 1 FROM account WHERE id = ? AND sha_pass_hash = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_CHECK_PASSWORD_BY_NAME, "SELECT 1 FROM account WHERE username = ? AND sha_pass_hash = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_PINFO, "SELECT a.username, aa.gmlevel, a.email, a.last_ip, DATE_FORMAT(a.last_login, '%Y-%m-%d %T'), a.mutetime FROM account a LEFT JOIN account_access aa ON (a.id = aa.id AND (aa.RealmID = ? OR aa.RealmID = -1)) WHERE a.id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_PINFO_BANS, "SELECT unbandate, bandate = unbandate, bannedby, banreason FROM account_banned WHERE id = ? AND active ORDER BY bandate ASC LIMIT 1", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_GM_ACCOUNTS, "SELECT a.username, aa.gmlevel FROM account a, account_access aa WHERE a.id=aa.id AND aa.gmlevel >= ? AND (aa.realmid = -1 OR aa.realmid = ?)", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_INFO, "SELECT a.username, a.last_ip, aa.gmlevel, a.expansion FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_ACCESS_GMLEVEL_TEST, "SELECT 1 FROM account_access WHERE id = ? AND gmlevel > ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_ACCESS, "SELECT a.id, aa.gmlevel, aa.RealmID FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.username = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_WHOIS, "SELECT username, email, last_ip FROM account WHERE id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_REALMLIST_SECURITY_LEVEL, "SELECT allowedSecurityLevel from realmlist WHERE id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_DEL_ACCOUNT, "DELETE FROM account WHERE id = ?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(LOGIN_SET_DUMP, "INSERT INTO `transferts` (`account`, `perso_guid`, `from`, `to`, `state`, `dump`) VALUES (?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_UPD_DUMP, "UPDATE transferts SET dump = ? ,state = ? WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_ADD_TRANSFERTS_LOGS, "INSERT INTO transferts_logs (`id`, `account`, `perso_guid`, `from`, `to`, `dump`, `toacc`, `newguid`, `transferId`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(LOGIN_SEL_BNET_ACCOUNT_INFO, "SELECT a.id, a.username, a.locked, a.lock_country, a.last_ip, a.failed_logins, ab.unbandate > UNIX_TIMESTAMP(), ab.unbandate = ab.bandate, a.activate, a.access_ip, ab.unbandate, aa.gmlevel FROM account a LEFT JOIN account_banned ab ON a.id = ab.id AND ab.active = 1 LEFT JOIN account_access aa ON a.id = aa.id AND aa.RealmID = -1 WHERE a.username = ? AND a.sha_pass_hash = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_UPD_LAST_LOGIN_INFO, "UPDATE account SET last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE id = ?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(LOGIN_UPD_AT_AUTH_FLAG, "UPDATE account SET AtAuthFlag = ? WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_SEL_BATTLEPAY_COINS, "SELECT coins FROM account WHERE id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_UPD_BATTLEPAY_CHANGE_COINS_COUNT, "UPDATE account SET coins = coins - ? WHERE id = ?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(LOGIN_UPD_ACCOUNT_INFO_CONTINUED_SESSION, "UPDATE account SET sessionkey = ? WHERE id = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_CONTINUED_SESSION, "SELECT username, sessionkey FROM account WHERE id = ?", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(LOGIN_UPD_ACCOUNT_LOGIN_INFO, "UPDATE account SET sessionkey = ?, last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE username = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_BNET_LAST_PLAYER_CHARACTERS, "SELECT lpc.accountId, lpc.region, lpc.battlegroup, lpc.realmId, lpc.characterName, lpc.characterGUID, lpc.lastPlayedTime FROM account_last_played_character lpc WHERE lpc.accountId = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_DEL_BNET_LAST_PLAYER_CHARACTERS, "DELETE FROM account_last_played_character WHERE accountId = ? AND region = ? AND battlegroup = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_INS_BNET_LAST_PLAYER_CHARACTERS, "INSERT INTO account_last_played_character (accountId, region, battlegroup, realmId, characterName, characterGUID, lastPlayedTime) VALUES (?,?,?,?,?,?,?)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS_BY_ACCOUNT_ID, "SELECT rc.acctid, rc.numchars, r.id, r.Region, r.Battlegroup FROM realmcharacters rc INNER JOIN realmlist r ON rc.realmid = r.id WHERE rc.acctid = ?", CONNECTION_BOTH);
|
||||
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_IP_ACCESS, "select min, max from account_ip_access WHERE pid = ? AND enable = 1", CONNECTION_SYNCH);
|
||||
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_TOKENS, "SELECT tokenType, amount FROM account_tokens WHERE account_id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_TOKEN, "SELECT amount FROM account_tokens WHERE account_id = ? AND tokenType = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(LOGIN_INS_OR_UPD_TOKEN, "INSERT INTO account_tokens (account_id, tokenType, amount) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE amount = amount + ?;", CONNECTION_BOTH);
|
||||
PrepareStatement(LOGIN_UPD_REFERER, "UPDATE account SET referer = ? WHERE id = ?", CONNECTION_BOTH);
|
||||
PrepareStatement(LOGIN_INS_LOG_USE_DONATE_TOKEN, "INSERT INTO `account_donate_token_log` (`accountId`, `realmId`, `characterId`, `change`, `tokenType`, `buyType`, `productId`) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
|
||||
PrepareStatement(LOGIN_SEL_ACCOUNT_CHARACTER_TEMPLATE, "SELECT `id`, `level`, `iLevel`, `money`, `artifact`, `transferId`, `templateId` FROM account_character_template WHERE account = ? AND realm = ? AND charGuid = 0", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_UPD_ACCOUNT_CHARACTER_TEMPLATE, "UPDATE `account_character_template` SET charGuid = ? WHERE id = ?;", CONNECTION_ASYNC);
|
||||
PrepareStatement(LOGIN_UPD_TRANSFER_REQUESTS, "UPDATE `transfer_requests` SET guid = ?, `status` = '0', `char_class` = ?, `char_faction` = ? WHERE id = ?", CONNECTION_ASYNC);
|
||||
}
|
||||
137
src/common/Database/Implementation/LoginDatabase.h
Normal file
137
src/common/Database/Implementation/LoginDatabase.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _LOGINDATABASE_H
|
||||
#define _LOGINDATABASE_H
|
||||
|
||||
#include "DatabaseWorkerPool.h"
|
||||
#include "MySQLConnection.h"
|
||||
|
||||
class LoginDatabaseConnection : public MySQLConnection
|
||||
{
|
||||
public:
|
||||
//- Constructors for sync and async connections
|
||||
LoginDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) { }
|
||||
LoginDatabaseConnection(ProducerConsumerQueue<SQLOperation*>* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) { }
|
||||
|
||||
//- Loads database type specific prepared statements
|
||||
void DoPrepareStatements();
|
||||
};
|
||||
|
||||
typedef DatabaseWorkerPool<LoginDatabaseConnection> LoginDatabaseWorkerPool;
|
||||
|
||||
enum LoginDatabaseStatements
|
||||
{
|
||||
/* Naming standard for defines:
|
||||
{DB}_{SEL/INS/UPD/DEL/REP}_{Summary of data changed}
|
||||
When updating more than one field, consider looking at the calling function
|
||||
name for a suiting suffix.
|
||||
*/
|
||||
|
||||
LOGIN_SEL_REALMLIST,
|
||||
LOGIN_DEL_EXPIRED_IP_BANS,
|
||||
LOGIN_UPD_EXPIRED_ACCOUNT_BANS,
|
||||
LOGIN_SEL_IP_INFO,
|
||||
LOGIN_SEL_ACCOUNT_BANNED,
|
||||
LOGIN_SEL_ACCOUNT_BANNED_ALL,
|
||||
LOGIN_SEL_ACCOUNT_BANNED_BY_USERNAME,
|
||||
LOGIN_DEL_ACCOUNT_BANNED,
|
||||
LOGIN_SEL_ACCOUNT_ID_BY_NAME,
|
||||
LOGIN_SEL_ACCOUNT_LIST_BY_NAME,
|
||||
LOGIN_SEL_ACCOUNT_INFO_BY_NAME,
|
||||
LOGIN_SEL_ACCOUNT_BY_IP,
|
||||
LOGIN_INS_IP_BANNED,
|
||||
LOGIN_DEL_IP_NOT_BANNED,
|
||||
LOGIN_SEL_IP_BANNED_ALL,
|
||||
LOGIN_SEL_IP_BANNED_BY_IP,
|
||||
LOGIN_SEL_ACCOUNT_BY_ID,
|
||||
LOGIN_INS_ACCOUNT_BANNED,
|
||||
LOGIN_UPD_ACCOUNT_BANNED,
|
||||
LOGIN_UPD_ACCOUNT_NOT_BANNED,
|
||||
LOGIN_DEL_REALM_CHARACTERS_BY_REALM,
|
||||
LOGIN_DEL_REALM_CHARACTERS,
|
||||
LOGIN_INS_REALM_CHARACTERS,
|
||||
LOGIN_SEL_SUM_REALM_CHARACTERS,
|
||||
LOGIN_INS_ACCOUNT,
|
||||
LOGIN_INS_REALM_CHARACTERS_INIT,
|
||||
LOGIN_UPD_EXPANSION,
|
||||
LOGIN_UPD_ACCOUNT_LOCK,
|
||||
LOGIN_INS_LOG,
|
||||
LOGIN_UPD_USERNAME,
|
||||
LOGIN_UPD_PASSWORD,
|
||||
LOGIN_UPD_MUTE_TIME,
|
||||
LOGIN_UPD_LAST_IP,
|
||||
LOGIN_UPD_FIRST_IP,
|
||||
LOGIN_SEL_EXPANSION_FIRST_IP,
|
||||
LOGIN_UPD_ACCOUNT_ONLINE,
|
||||
LOGIN_UPD_UPTIME_PLAYERS,
|
||||
LOGIN_DEL_OLD_LOGS,
|
||||
LOGIN_DEL_ACCOUNT_ACCESS,
|
||||
LOGIN_DEL_ACCOUNT_ACCESS_BY_REALM,
|
||||
LOGIN_INS_ACCOUNT_ACCESS,
|
||||
LOGIN_GET_ACCOUNT_ID_BY_USERNAME,
|
||||
LOGIN_GET_ACCOUNT_ID_FOR_ACCOUNT_CONVERT,
|
||||
LOGIN_GET_ACCOUNT_ACCESS_GMLEVEL,
|
||||
LOGIN_GET_GMLEVEL_BY_REALMID,
|
||||
LOGIN_GET_USERNAME_BY_ID,
|
||||
LOGIN_GET_EMAIL_BY_ID_FOR_ACCOUNT_CONVERT,
|
||||
LOGIN_SEL_CHECK_PASSWORD,
|
||||
LOGIN_SEL_CHECK_PASSWORD_BY_NAME,
|
||||
LOGIN_SEL_PINFO,
|
||||
LOGIN_SEL_PINFO_BANS,
|
||||
LOGIN_SEL_GM_ACCOUNTS,
|
||||
LOGIN_SEL_ACCOUNT_INFO,
|
||||
LOGIN_SEL_ACCOUNT_ACCESS_GMLEVEL_TEST,
|
||||
LOGIN_SEL_ACCOUNT_ACCESS,
|
||||
LOGIN_SEL_ACCOUNT_WHOIS,
|
||||
LOGIN_SEL_REALMLIST_SECURITY_LEVEL,
|
||||
LOGIN_DEL_ACCOUNT,
|
||||
|
||||
LOGIN_SET_DUMP,
|
||||
LOGIN_UPD_DUMP,
|
||||
LOGIN_ADD_TRANSFERTS_LOGS,
|
||||
|
||||
LOGIN_SEL_BNET_ACCOUNT_INFO,
|
||||
LOGIN_UPD_LAST_LOGIN_INFO,
|
||||
|
||||
LOGIN_UPD_AT_AUTH_FLAG,
|
||||
LOGIN_SEL_BATTLEPAY_COINS,
|
||||
LOGIN_UPD_BATTLEPAY_CHANGE_COINS_COUNT,
|
||||
|
||||
LOGIN_SEL_ACCOUNT_INFO_CONTINUED_SESSION,
|
||||
LOGIN_UPD_ACCOUNT_INFO_CONTINUED_SESSION,
|
||||
LOGIN_UPD_ACCOUNT_LOGIN_INFO,
|
||||
LOGIN_SEL_BNET_LAST_PLAYER_CHARACTERS,
|
||||
LOGIN_DEL_BNET_LAST_PLAYER_CHARACTERS,
|
||||
LOGIN_INS_BNET_LAST_PLAYER_CHARACTERS,
|
||||
LOGIN_SEL_BNET_CHARACTER_COUNTS_BY_ACCOUNT_ID,
|
||||
LOGIN_SEL_ACCOUNT_IP_ACCESS,
|
||||
|
||||
LOGIN_SEL_ACCOUNT_TOKENS,
|
||||
LOGIN_SEL_ACCOUNT_TOKEN,
|
||||
LOGIN_INS_OR_UPD_TOKEN,
|
||||
LOGIN_UPD_REFERER,
|
||||
LOGIN_INS_LOG_USE_DONATE_TOKEN,
|
||||
|
||||
LOGIN_SEL_ACCOUNT_CHARACTER_TEMPLATE,
|
||||
LOGIN_UPD_ACCOUNT_CHARACTER_TEMPLATE,
|
||||
LOGIN_UPD_TRANSFER_REQUESTS,
|
||||
|
||||
MAX_LOGINDATABASE_STATEMENTS,
|
||||
};
|
||||
|
||||
#endif
|
||||
103
src/common/Database/Implementation/WorldDatabase.cpp
Normal file
103
src/common/Database/Implementation/WorldDatabase.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "WorldDatabase.h"
|
||||
|
||||
void WorldDatabaseConnection::DoPrepareStatements()
|
||||
{
|
||||
if (!m_reconnecting)
|
||||
m_stmts.resize(MAX_WORLDDATABASE_STATEMENTS);
|
||||
|
||||
PrepareStatement(WORLD_SEL_QUEST_POOLS, "SELECT entry, pool_entry FROM pool_quest", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_DEL_CRELINKED_RESPAWN, "DELETE FROM linked_respawn WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_REP_CREATURE_LINKED_RESPAWN, "REPLACE INTO linked_respawn (guid, linkedGuid) VALUES (?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_SEL_SMART_SCRIPTS, "SELECT entryorguid, source_type, id, link, event_type, event_phase_mask, event_chance, event_flags, event_param1, event_param2, event_param3, event_param4, action_type, action_param1, action_param2, action_param3, action_param4, action_param5, action_param6, target_type, target_param1, target_param2, target_param3, target_x, target_y, target_z, target_o FROM smart_scripts ORDER BY entryorguid, source_type, id, link", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_SMARTAI_WP, "SELECT entry, pointid, position_x, position_y, position_z FROM waypoints ORDER BY entry, pointid", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_DEL_GAMEOBJECT, "DELETE FROM gameobject WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_DEL_EVENT_GAMEOBJECT, "DELETE FROM game_event_gameobject WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_INS_GRAVEYARD_ZONE, "INSERT INTO game_graveyard_zone (id, ghost_zone, faction) VALUES (?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_DEL_GRAVEYARD_ZONE, "DELETE FROM game_graveyard_zone WHERE id = ? AND ghost_zone = ? AND faction = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_INS_GAME_TELE, "INSERT INTO game_tele (id, position_x, position_y, position_z, orientation, map, name) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_DEL_GAME_TELE, "DELETE FROM game_tele WHERE name = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_INS_NPC_VENDOR, "INSERT INTO npc_vendor (entry, item, maxcount, incrtime, extendedcost, type) VALUES(?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_DEL_NPC_VENDOR, "DELETE FROM npc_vendor WHERE entry = ? AND item = ? AND type = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_SEL_NPC_VENDOR_REF, "SELECT item, maxcount, incrtime, ExtendedCost, type, money, RandomPropertiesSeed, RandomPropertiesID, BonusListID, ItemModifiers, IgnoreFiltering, Context, PlayerConditionID FROM npc_vendor WHERE entry = ? AND type = ? ORDER BY slot ASC", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_UPD_CREATURE_MOVEMENT_TYPE, "UPDATE creature SET MovementType = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_UPD_CREATURE_FACTION, "UPDATE creature_template SET faction = ? WHERE entry = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_UPD_CREATURE_NPCFLAG, "UPDATE creature_template SET npcflag = ? WHERE entry = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_UPD_CREATURE_POSITION, "UPDATE creature SET position_x = ?, position_y = ?, position_z = ?, orientation = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_UPD_CREATURE_SPAWN_DISTANCE, "UPDATE creature SET spawndist = ?, MovementType = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_UPD_CREATURE_SPAWN_TIME_SECS, "UPDATE creature SET spawntimesecs = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_INS_CREATURE_FORMATION, "INSERT INTO creature_formations (leaderGUID, memberGUID, dist, angle, groupAI) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_INS_WAYPOINT_DATA, "INSERT INTO waypoint_data (id, point, position_x, position_y, position_z) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_DEL_WAYPOINT_DATA, "DELETE FROM waypoint_data WHERE id = ? AND point = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_UPD_WAYPOINT_DATA_POINT, "UPDATE waypoint_data SET point = point - 1 WHERE id = ? AND point > ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_UPD_WAYPOINT_DATA_POSITION, "UPDATE waypoint_data SET position_x = ?, position_y = ?, position_z = ? where id = ? AND point = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_UPD_WAYPOINT_DATA_WPGUID, "UPDATE waypoint_data SET wpguid = ? WHERE id = ? and point = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_SEL_WAYPOINT_DATA_MAX_ID, "SELECT MAX(id) FROM waypoint_data", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_WAYPOINT_DATA_MAX_POINT, "SELECT MAX(point) FROM waypoint_data WHERE id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_WAYPOINT_DATA_BY_ID, "SELECT point, position_x, position_y, position_z, orientation, move_flag, speed, delay, action, action_chance, delay_chance FROM waypoint_data WHERE id = ? ORDER BY point", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_WAYPOINT_DATA_SCRIPT_BY_ID, "SELECT point, position_x, position_y, position_z, orientation, move_flag, speed, delay, action, action_chance FROM waypoint_data_script WHERE id = ? ORDER BY point", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_WAYPOINT_DATA_POS_BY_ID, "SELECT point, position_x, position_y, position_z FROM waypoint_data WHERE id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_WAYPOINT_DATA_POS_FIRST_BY_ID, "SELECT position_x, position_y, position_z FROM waypoint_data WHERE point = 1 AND id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_WAYPOINT_DATA_POS_LAST_BY_ID, "SELECT position_x, position_y, position_z, orientation FROM waypoint_data WHERE id = ? ORDER BY point DESC LIMIT 1", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_WAYPOINT_DATA_BY_WPGUID, "SELECT id, point FROM waypoint_data WHERE wpguid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_WAYPOINT_DATA_ALL_BY_WPGUID, "SELECT id, point, delay, move_flag, action, action_chance FROM waypoint_data WHERE wpguid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_UPD_WAYPOINT_DATA_ALL_WPGUID, "UPDATE waypoint_data SET wpguid = 0", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_SEL_WAYPOINT_DATA_BY_POS, "SELECT id, point FROM waypoint_data WHERE (abs(position_x - ?) <= ?) and (abs(position_y - ?) <= ?) and (abs(position_z - ?) <= ?)", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_WAYPOINT_DATA_WPGUID_BY_ID, "SELECT wpguid FROM waypoint_data WHERE id = ? and wpguid <> 0", CONNECTION_SYNCH);
|
||||
PrepareStatement(WOLRD_SEL_WAYPOINT_DATA_ACTION, "SELECT DISTINCT action FROM waypoint_data", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPTS_MAX_ID, "SELECT MAX(guid) FROM waypoint_scripts", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_INS_CREATURE_ADDON, "INSERT INTO creature_addon(guid, path_id) VALUES (?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_UPD_CREATURE_ADDON_PATH, "UPDATE creature_addon SET path_id = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_DEL_CREATURE_ADDON, "DELETE FROM creature_addon WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_SEL_CREATURE_ADDON_BY_GUID, "SELECT guid FROM creature_addon WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_INS_WAYPOINT_SCRIPT, "INSERT INTO waypoint_scripts (guid) VALUES (?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_DEL_WAYPOINT_SCRIPT, "DELETE FROM waypoint_scripts WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_UPD_WAYPOINT_SCRIPT_ID, "UPDATE waypoint_scripts SET id = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_UPD_WAYPOINT_SCRIPT_X, "UPDATE waypoint_scripts SET x = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_UPD_WAYPOINT_SCRIPT_Y, "UPDATE waypoint_scripts SET y = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_UPD_WAYPOINT_SCRIPT_Z, "UPDATE waypoint_scripts SET z = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_UPD_WAYPOINT_SCRIPT_O, "UPDATE waypoint_scripts SET o = ? WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID, "SELECT id FROM waypoint_scripts WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_DEL_CREATURE, "DELETE FROM creature WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_SEL_COMMANDS, "SELECT name, security, help FROM command", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT gossip_menu_id, minlevel, maxlevel, faction, npcflag, speed_walk, speed_run, scale, dmgschool, dmg_multiplier, baseattacktime, rangeattacktime, unit_class, unit_flags, unit_flags2, dynamicflags, trainer_type, trainer_spell, trainer_class, trainer_race, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, Mana_mod_extra, Armor_mod, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, "SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_IP2NATION_COUNTRY, "SELECT c.country FROM ip2nationcountries c, ip2nation i WHERE i.ip < ? AND c.code = i.country ORDER BY i.ip DESC LIMIT 0,1", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_ITEM_TEMPLATE_BY_NAME, "SELECT entry FROM item_template WHERE name = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_CREATURE_BY_ID, "SELECT guid FROM creature WHERE id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_GAMEOBJECT_NEAREST, "SELECT guid, id, position_x, position_y, position_z, map, (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) AS order_ FROM gameobject WHERE map = ? AND (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) <= ? ORDER BY order_", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_CREATURE_NEAREST, "SELECT guid, id, position_x, position_y, position_z, map, (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) AS order_ FROM creature WHERE map = ? AND (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) <= ? ORDER BY order_", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_INS_CREATURE, "INSERT INTO creature (guid, id , map, zoneId, areaId, spawnMask, phaseMask, modelid, equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, spawndist, currentwaypoint, curhealth, curmana, MovementType, npcflag, unit_flags, unit_flags3, dynamicflags, isActive, personal_size) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_DEL_GAME_EVENT_CREATURE, "DELETE FROM game_event_creature WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_DEL_GAME_EVENT_MODEL_EQUIP, "DELETE FROM game_event_model_equip WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_INS_GAMEOBJECT, "INSERT INTO gameobject (guid, id, map, zoneId, areaId, spawnMask, phaseMask, position_x, position_y, position_z, orientation, rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, isActive, personal_size) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_INS_DISABLES, "INSERT INTO disables (entry, sourceType, flags, comment) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_SEL_DISABLES, "SELECT entry FROM disables WHERE entry = ? AND sourceType = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_DEL_DISABLES, "DELETE FROM disables WHERE entry = ? AND sourceType = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_SEL_BLACKMARKET_TEMPLATE, "SELECT marketId, sellerNpc, itemEntry, quantity, minBid, duration, chance, bonusListIDs FROM blackmarket_template", CONNECTION_SYNCH);
|
||||
|
||||
PrepareStatement(WORLD_DEL_EVENTOBJECT, "DELETE FROM eventobject WHERE guid = ?", CONNECTION_ASYNC);;
|
||||
PrepareStatement(WORLD_INS_EVENTOBJECT, "INSERT INTO eventobject (guid, id , map, zoneId, areaId, spawnMask, phaseMask, position_x, position_y, position_z, orientation) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_SEL_EVENTOBJECT_NEAREST, "SELECT guid, id, position_x, position_y, position_z, map, (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) AS order_ FROM eventobject WHERE map = ? AND (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) <= ? ORDER BY order_", CONNECTION_SYNCH);
|
||||
|
||||
PrepareStatement(WORLD_SEL_CHARACTER_TEMPLATES, "SELECT ID, Name, Description, level, ilevel, fromID FROM character_template", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_CHARACTER_TEMPLATE_CLASSES, "SELECT FactionGroup, Class, X, Y, Z, O, MapID, Money, RaceMask FROM character_template_class WHERE TemplateID = ?", CONNECTION_SYNCH);
|
||||
|
||||
PrepareStatement(WORLD_UPD_QUEST_OBJECTIVE_BUGGED_STATE, "UPDATE quest_objectives SET Bugged = ? WHERE ID = ?", CONNECTION_ASYNC);
|
||||
}
|
||||
128
src/common/Database/Implementation/WorldDatabase.h
Normal file
128
src/common/Database/Implementation/WorldDatabase.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _WORLDDATABASE_H
|
||||
#define _WORLDDATABASE_H
|
||||
|
||||
#include "DatabaseWorkerPool.h"
|
||||
#include "MySQLConnection.h"
|
||||
|
||||
class WorldDatabaseConnection : public MySQLConnection
|
||||
{
|
||||
public:
|
||||
//- Constructors for sync and async connections
|
||||
WorldDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) { }
|
||||
WorldDatabaseConnection(ProducerConsumerQueue<SQLOperation*>* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) { }
|
||||
|
||||
//- Loads database type specific prepared statements
|
||||
void DoPrepareStatements();
|
||||
};
|
||||
|
||||
typedef DatabaseWorkerPool<WorldDatabaseConnection> WorldDatabaseWorkerPool;
|
||||
|
||||
enum WorldDatabaseStatements
|
||||
{
|
||||
/* Naming standard for defines:
|
||||
{DB}_{SEL/INS/UPD/DEL/REP}_{Summary of data changed}
|
||||
When updating more than one field, consider looking at the calling function
|
||||
name for a suiting suffix.
|
||||
*/
|
||||
|
||||
WORLD_SEL_QUEST_POOLS,
|
||||
WORLD_DEL_CRELINKED_RESPAWN,
|
||||
WORLD_REP_CREATURE_LINKED_RESPAWN,
|
||||
WORLD_SEL_SMART_SCRIPTS,
|
||||
WORLD_SEL_SMARTAI_WP,
|
||||
WORLD_DEL_GAMEOBJECT,
|
||||
WORLD_DEL_EVENT_GAMEOBJECT,
|
||||
WORLD_INS_GRAVEYARD_ZONE,
|
||||
WORLD_DEL_GRAVEYARD_ZONE,
|
||||
WORLD_INS_GAME_TELE,
|
||||
WORLD_DEL_GAME_TELE,
|
||||
WORLD_INS_NPC_VENDOR,
|
||||
WORLD_DEL_NPC_VENDOR,
|
||||
WORLD_SEL_NPC_VENDOR_REF,
|
||||
WORLD_UPD_CREATURE_MOVEMENT_TYPE,
|
||||
WORLD_UPD_CREATURE_FACTION,
|
||||
WORLD_UPD_CREATURE_NPCFLAG,
|
||||
WORLD_UPD_CREATURE_POSITION,
|
||||
WORLD_UPD_CREATURE_SPAWN_DISTANCE,
|
||||
WORLD_UPD_CREATURE_SPAWN_TIME_SECS,
|
||||
WORLD_INS_CREATURE_FORMATION,
|
||||
WORLD_INS_WAYPOINT_DATA,
|
||||
WORLD_DEL_WAYPOINT_DATA,
|
||||
WORLD_UPD_WAYPOINT_DATA_POINT,
|
||||
WORLD_UPD_WAYPOINT_DATA_POSITION,
|
||||
WORLD_UPD_WAYPOINT_DATA_WPGUID,
|
||||
WORLD_UPD_WAYPOINT_DATA_ALL_WPGUID,
|
||||
WORLD_SEL_WAYPOINT_DATA_MAX_ID,
|
||||
WORLD_SEL_WAYPOINT_DATA_BY_ID,
|
||||
WORLD_SEL_WAYPOINT_DATA_SCRIPT_BY_ID,
|
||||
WORLD_SEL_WAYPOINT_DATA_POS_BY_ID,
|
||||
WORLD_SEL_WAYPOINT_DATA_POS_FIRST_BY_ID,
|
||||
WORLD_SEL_WAYPOINT_DATA_POS_LAST_BY_ID,
|
||||
WORLD_SEL_WAYPOINT_DATA_BY_WPGUID,
|
||||
WORLD_SEL_WAYPOINT_DATA_ALL_BY_WPGUID,
|
||||
WORLD_SEL_WAYPOINT_DATA_MAX_POINT,
|
||||
WORLD_SEL_WAYPOINT_DATA_BY_POS,
|
||||
WORLD_SEL_WAYPOINT_DATA_WPGUID_BY_ID,
|
||||
WOLRD_SEL_WAYPOINT_DATA_ACTION,
|
||||
WORLD_SEL_WAYPOINT_SCRIPTS_MAX_ID,
|
||||
WORLD_UPD_CREATURE_ADDON_PATH,
|
||||
WORLD_INS_CREATURE_ADDON,
|
||||
WORLD_DEL_CREATURE_ADDON,
|
||||
WORLD_SEL_CREATURE_ADDON_BY_GUID,
|
||||
WORLD_INS_WAYPOINT_SCRIPT,
|
||||
WORLD_DEL_WAYPOINT_SCRIPT,
|
||||
WORLD_UPD_WAYPOINT_SCRIPT_ID,
|
||||
WORLD_UPD_WAYPOINT_SCRIPT_X,
|
||||
WORLD_UPD_WAYPOINT_SCRIPT_Y,
|
||||
WORLD_UPD_WAYPOINT_SCRIPT_Z,
|
||||
WORLD_UPD_WAYPOINT_SCRIPT_O,
|
||||
WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID,
|
||||
WORLD_DEL_CREATURE,
|
||||
WORLD_SEL_COMMANDS,
|
||||
WORLD_SEL_CREATURE_TEMPLATE,
|
||||
WORLD_SEL_WAYPOINT_SCRIPT_BY_ID,
|
||||
WORLD_SEL_IP2NATION_COUNTRY,
|
||||
WORLD_SEL_ITEM_TEMPLATE_BY_NAME,
|
||||
WORLD_SEL_CREATURE_BY_ID,
|
||||
WORLD_SEL_GAMEOBJECT_NEAREST,
|
||||
WORLD_SEL_GAMEOBJECT_TARGET,
|
||||
WORLD_SEL_CREATURE_NEAREST,
|
||||
WORLD_INS_CREATURE,
|
||||
WORLD_DEL_GAME_EVENT_CREATURE,
|
||||
WORLD_DEL_GAME_EVENT_MODEL_EQUIP,
|
||||
WORLD_INS_GAMEOBJECT,
|
||||
WORLD_SEL_DISABLES,
|
||||
WORLD_INS_DISABLES,
|
||||
WORLD_DEL_DISABLES,
|
||||
WORLD_SEL_BLACKMARKET_TEMPLATE,
|
||||
|
||||
WORLD_SEL_CHARACTER_TEMPLATES,
|
||||
WORLD_SEL_CHARACTER_TEMPLATE_CLASSES,
|
||||
|
||||
WORLD_DEL_EVENTOBJECT,
|
||||
WORLD_INS_EVENTOBJECT,
|
||||
WORLD_SEL_EVENTOBJECT_NEAREST,
|
||||
|
||||
WORLD_UPD_QUEST_OBJECTIVE_BUGGED_STATE,
|
||||
|
||||
MAX_WORLDDATABASE_STATEMENTS,
|
||||
};
|
||||
|
||||
#endif
|
||||
572
src/common/Database/MySQLConnection.cpp
Normal file
572
src/common/Database/MySQLConnection.cpp
Normal file
@@ -0,0 +1,572 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
#include <mysql.h>
|
||||
#include <mysqld_error.h>
|
||||
#include <errmsg.h>
|
||||
|
||||
#include "MySQLConnection.h"
|
||||
#include "MySQLThreading.h"
|
||||
#include "QueryResult.h"
|
||||
#include "SQLOperation.h"
|
||||
#include "PreparedStatement.h"
|
||||
#include "DatabaseWorker.h"
|
||||
#include "Timer.h"
|
||||
#include "Log.h"
|
||||
#include "ProducerConsumerQueue.h"
|
||||
|
||||
MySQLConnection::MySQLConnection(MySQLConnectionInfo& connInfo) :
|
||||
m_reconnecting(false),
|
||||
m_prepareError(false),
|
||||
m_queue(NULL),
|
||||
m_worker(NULL),
|
||||
m_Mysql(NULL),
|
||||
m_connectionInfo(connInfo),
|
||||
m_connectionFlags(CONNECTION_SYNCH)
|
||||
{
|
||||
}
|
||||
|
||||
MySQLConnection::MySQLConnection(ProducerConsumerQueue<SQLOperation*>* queue, MySQLConnectionInfo& connInfo) :
|
||||
m_reconnecting(false),
|
||||
m_prepareError(false),
|
||||
m_queue(queue),
|
||||
m_Mysql(NULL),
|
||||
m_connectionInfo(connInfo),
|
||||
m_connectionFlags(CONNECTION_ASYNC)
|
||||
{
|
||||
m_worker = new DatabaseWorker(m_queue, this);
|
||||
}
|
||||
|
||||
MySQLConnection::~MySQLConnection()
|
||||
{
|
||||
for (size_t i = 0; i < m_stmts.size(); ++i)
|
||||
delete m_stmts[i];
|
||||
|
||||
if (m_Mysql)
|
||||
mysql_close(m_Mysql);
|
||||
|
||||
if (m_worker)
|
||||
delete m_worker;
|
||||
}
|
||||
|
||||
void MySQLConnection::Close()
|
||||
{
|
||||
/// Only close us if we're not operating
|
||||
delete this;
|
||||
}
|
||||
|
||||
bool MySQLConnection::Open()
|
||||
{
|
||||
MYSQL *mysqlInit;
|
||||
mysqlInit = mysql_init(NULL);
|
||||
if (!mysqlInit)
|
||||
{
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "Could not initialize Mysql connection to database `%s`", m_connectionInfo.database.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
int port;
|
||||
char const* unix_socket;
|
||||
|
||||
mysql_options(mysqlInit, MYSQL_SET_CHARSET_NAME, "utf8");
|
||||
#ifdef _WIN32
|
||||
if (m_connectionInfo.host == ".") // named pipe use option (Windows)
|
||||
{
|
||||
unsigned int opt = MYSQL_PROTOCOL_PIPE;
|
||||
mysql_options(mysqlInit, MYSQL_OPT_PROTOCOL, (char const*)&opt);
|
||||
port = 0;
|
||||
unix_socket = 0;
|
||||
}
|
||||
else // generic case
|
||||
{
|
||||
port = atoi(m_connectionInfo.port_or_socket.c_str());
|
||||
unix_socket = 0;
|
||||
}
|
||||
#else
|
||||
if (m_connectionInfo.host == ".") // socket use option (Unix/Linux)
|
||||
{
|
||||
unsigned int opt = MYSQL_PROTOCOL_SOCKET;
|
||||
mysql_options(mysqlInit, MYSQL_OPT_PROTOCOL, (char const*)&opt);
|
||||
m_connectionInfo.host = "localhost";
|
||||
port = 0;
|
||||
unix_socket = m_connectionInfo.port_or_socket.c_str();
|
||||
}
|
||||
else // generic case
|
||||
{
|
||||
port = atoi(m_connectionInfo.port_or_socket.c_str());
|
||||
unix_socket = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_Mysql = mysql_real_connect(mysqlInit, m_connectionInfo.host.c_str(), m_connectionInfo.user.c_str(),
|
||||
m_connectionInfo.password.c_str(), m_connectionInfo.database.c_str(), port, unix_socket, 0);
|
||||
|
||||
if (m_Mysql)
|
||||
{
|
||||
if (!m_reconnecting)
|
||||
{
|
||||
TC_LOG_INFO(LOG_FILTER_SQL, "MySQL client library: %s", mysql_get_client_info());
|
||||
TC_LOG_INFO(LOG_FILTER_SQL, "MySQL server ver: %s ", mysql_get_server_info(m_Mysql));
|
||||
if (mysql_get_server_version(m_Mysql) != mysql_get_client_version())
|
||||
TC_LOG_INFO(LOG_FILTER_SQL, "[WARNING] MySQL client/server version mismatch; may conflict with behaviour of prepared statements.");
|
||||
}
|
||||
|
||||
TC_LOG_INFO(LOG_FILTER_SQL, "Connected to MySQL database at %s", m_connectionInfo.host.c_str());
|
||||
mysql_autocommit(m_Mysql, 1);
|
||||
|
||||
// set connection properties to UTF8 to properly handle locales for different
|
||||
// server configs - core sends data in UTF8, so MySQL must expect UTF8 too
|
||||
mysql_set_character_set(m_Mysql, "utf8");
|
||||
return PrepareStatements();
|
||||
}
|
||||
else
|
||||
{
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "Could not connect to MySQL database at %s: %s\n", m_connectionInfo.host.c_str(), mysql_error(mysqlInit));
|
||||
mysql_close(mysqlInit);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MySQLConnection::PrepareStatements()
|
||||
{
|
||||
DoPrepareStatements();
|
||||
return !m_prepareError;
|
||||
}
|
||||
|
||||
bool MySQLConnection::Execute(const char* sql)
|
||||
{
|
||||
if (!m_Mysql)
|
||||
return false;
|
||||
|
||||
{
|
||||
uint32 _s = getMSTime();
|
||||
|
||||
if (mysql_query(m_Mysql, sql))
|
||||
{
|
||||
uint32 lErrno = mysql_errno(m_Mysql);
|
||||
|
||||
TC_LOG_INFO(LOG_FILTER_SQL, "SQL: %s", sql);
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "[%u] %s", lErrno, mysql_error(m_Mysql));
|
||||
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return Execute(sql); // Try again
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef WIN32
|
||||
uint32 _ms = getMSTimeDiff(_s, getMSTime());
|
||||
//if (_ms > 3)
|
||||
TC_LOG_DEBUG(LOG_FILTER_SQL, "[%u ms] SQL: %s", _ms, sql);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MySQLConnection::Execute(PreparedStatement* stmt)
|
||||
{
|
||||
if (!m_Mysql)
|
||||
return false;
|
||||
|
||||
uint32 index = stmt->m_index;
|
||||
volatile std::string query = m_queries[index].query;
|
||||
{
|
||||
MySQLPreparedStatement* m_mStmt = GetPreparedStatement(index);
|
||||
if(!m_mStmt)
|
||||
{
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "[%u] %s index %i", mysql_errno(m_Mysql), mysql_error(m_Mysql), index);
|
||||
return false;
|
||||
}
|
||||
//ASSERT(m_mStmt); // Can only be null if preparation failed, server side error or bad query
|
||||
m_mStmt->m_stmt = stmt; // Cross reference them for debug output
|
||||
|
||||
stmt->BindParameters(m_mStmt);
|
||||
|
||||
MYSQL_STMT* msql_STMT = m_mStmt->GetSTMT();
|
||||
MYSQL_BIND* msql_BIND = m_mStmt->GetBind();
|
||||
|
||||
uint32 _s = getMSTime();
|
||||
|
||||
if (mysql_stmt_bind_param(msql_STMT, msql_BIND))
|
||||
{
|
||||
uint32 lErrno = mysql_errno(m_Mysql);
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString(m_queries[index].query).c_str(), lErrno, mysql_stmt_error(msql_STMT));
|
||||
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return Execute(stmt); // Try again
|
||||
|
||||
m_mStmt->ClearParameters();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mysql_stmt_execute(msql_STMT))
|
||||
{
|
||||
uint32 lErrno = mysql_errno(m_Mysql);
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString(m_queries[index].query).c_str(), lErrno, mysql_stmt_error(msql_STMT));
|
||||
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return Execute(stmt); // Try again
|
||||
|
||||
m_mStmt->ClearParameters();
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
uint32 _ms = getMSTimeDiff(_s, getMSTime());
|
||||
//if (_ms > 3)
|
||||
TC_LOG_DEBUG(LOG_FILTER_SQL, "[%u ms] SQL(p): %s", _ms, m_mStmt->getQueryString(m_queries[index].query).c_str());
|
||||
#endif
|
||||
m_mStmt->ClearParameters();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
QResult MySQLConnection::_Query(PreparedStatement* stmt, MYSQL_RES **pResult, uint64* pRowCount, uint32* pFieldCount)
|
||||
{
|
||||
if (!m_Mysql)
|
||||
return QResult(false, NULL);
|
||||
|
||||
uint32 index = stmt->m_index;
|
||||
volatile std::string query = m_queries[index].query;
|
||||
{
|
||||
MySQLPreparedStatement* m_mStmt = GetPreparedStatement(index);
|
||||
ASSERT(m_mStmt); // Can only be null if preparation failed, server side error or bad query
|
||||
m_mStmt->m_stmt = stmt; // Cross reference them for debug output
|
||||
|
||||
stmt->BindParameters(m_mStmt);
|
||||
|
||||
MYSQL_STMT* msql_STMT = m_mStmt->GetSTMT();
|
||||
MYSQL_BIND* msql_BIND = m_mStmt->GetBind();
|
||||
|
||||
uint32 _s = getMSTime();
|
||||
|
||||
if (mysql_stmt_bind_param(msql_STMT, msql_BIND))
|
||||
{
|
||||
uint32 lErrno = mysql_errno(m_Mysql);
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString(m_queries[index].query).c_str(), lErrno, mysql_stmt_error(msql_STMT));
|
||||
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return _Query(stmt, pResult, pRowCount, pFieldCount); // Try again
|
||||
|
||||
m_mStmt->ClearParameters();
|
||||
return QResult(false, NULL);
|
||||
}
|
||||
|
||||
if (mysql_stmt_execute(msql_STMT))
|
||||
{
|
||||
uint32 lErrno = mysql_errno(m_Mysql);
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "SQL(p): %s\n [ERROR]: [%u] %s",
|
||||
m_mStmt->getQueryString(m_queries[index].query).c_str(), lErrno, mysql_stmt_error(msql_STMT));
|
||||
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return _Query(stmt, pResult, pRowCount, pFieldCount); // Try again
|
||||
|
||||
m_mStmt->ClearParameters();
|
||||
return QResult(false, NULL);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
uint32 _ms = getMSTimeDiff(_s, getMSTime());
|
||||
//if (_ms > 3)
|
||||
TC_LOG_DEBUG(LOG_FILTER_SQL, "[%u ms] SQL(p): %s", _ms, m_mStmt->getQueryString(m_queries[index].query).c_str());
|
||||
#endif
|
||||
m_mStmt->ClearParameters();
|
||||
|
||||
*pResult = mysql_stmt_result_metadata(msql_STMT);
|
||||
*pRowCount = mysql_stmt_num_rows(msql_STMT);
|
||||
*pFieldCount = mysql_stmt_field_count(msql_STMT);
|
||||
|
||||
return QResult(true, m_mStmt);;
|
||||
}
|
||||
}
|
||||
|
||||
ResultSet* MySQLConnection::Query(const char* sql)
|
||||
{
|
||||
if (!sql)
|
||||
return NULL;
|
||||
|
||||
MYSQL_RES *result = NULL;
|
||||
MYSQL_FIELD *fields = NULL;
|
||||
uint64 rowCount = 0;
|
||||
uint32 fieldCount = 0;
|
||||
|
||||
if (!_Query(sql, &result, &fields, &rowCount, &fieldCount))
|
||||
return NULL;
|
||||
|
||||
return new ResultSet(result, fields, rowCount, fieldCount);
|
||||
}
|
||||
|
||||
bool MySQLConnection::_Query(const char *sql, MYSQL_RES **pResult, MYSQL_FIELD **pFields, uint64* pRowCount, uint32* pFieldCount)
|
||||
{
|
||||
if (!m_Mysql)
|
||||
return false;
|
||||
|
||||
{
|
||||
uint32 _s = getMSTime();
|
||||
|
||||
if (mysql_query(m_Mysql, sql))
|
||||
{
|
||||
uint32 lErrno = mysql_errno(m_Mysql);
|
||||
TC_LOG_INFO(LOG_FILTER_SQL, "SQL: %s", sql);
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "[%u] %s", lErrno, mysql_error(m_Mysql));
|
||||
|
||||
if (lErrno == ER_BAD_FIELD_ERROR || lErrno == ER_NO_SUCH_TABLE || lErrno == ER_PARSE_ERROR)
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "TRANSFERT ERROR %u : query : %s", lErrno, sql);
|
||||
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return _Query(sql, pResult, pFields, pRowCount, pFieldCount); // We try again
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef WIN32
|
||||
uint32 _ms = getMSTimeDiff(_s, getMSTime());
|
||||
//if (_ms > 3)
|
||||
TC_LOG_DEBUG(LOG_FILTER_SQL, "[%u ms] SQL: %s", _ms, sql);
|
||||
#endif
|
||||
}
|
||||
|
||||
*pResult = mysql_store_result(m_Mysql);
|
||||
*pRowCount = mysql_affected_rows(m_Mysql);
|
||||
*pFieldCount = mysql_field_count(m_Mysql);
|
||||
}
|
||||
|
||||
if (!*pResult )
|
||||
return false;
|
||||
|
||||
if (!*pRowCount)
|
||||
{
|
||||
mysql_free_result(*pResult);
|
||||
return false;
|
||||
}
|
||||
|
||||
*pFields = mysql_fetch_fields(*pResult);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MySQLConnection::BeginTransaction()
|
||||
{
|
||||
Execute("START TRANSACTION");
|
||||
}
|
||||
|
||||
void MySQLConnection::RollbackTransaction()
|
||||
{
|
||||
Execute("ROLLBACK");
|
||||
}
|
||||
|
||||
void MySQLConnection::CommitTransaction()
|
||||
{
|
||||
Execute("COMMIT");
|
||||
}
|
||||
|
||||
int MySQLConnection::ExecuteTransaction(SQLTransaction& transaction)
|
||||
{
|
||||
std::list<SQLElementData> const& queries = transaction->m_queries;
|
||||
if (queries.empty())
|
||||
return -1;
|
||||
|
||||
BeginTransaction();
|
||||
|
||||
std::list<SQLElementData>::const_iterator itr;
|
||||
for (itr = queries.begin(); itr != queries.end(); ++itr)
|
||||
{
|
||||
SQLElementData const& data = *itr;
|
||||
switch (itr->type)
|
||||
{
|
||||
case SQL_ELEMENT_PREPARED:
|
||||
{
|
||||
PreparedStatement* stmt = data.element.stmt;
|
||||
ASSERT(stmt);
|
||||
if (!Execute(stmt))
|
||||
{
|
||||
TC_LOG_WARN(LOG_FILTER_SQL, "Transaction aborted. %u queries not executed.", (uint32)queries.size());
|
||||
int errorCode = GetLastError();
|
||||
RollbackTransaction();
|
||||
return errorCode;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SQL_ELEMENT_RAW:
|
||||
{
|
||||
const char* sql = data.element.query;
|
||||
ASSERT(sql);
|
||||
if (!Execute(sql))
|
||||
{
|
||||
TC_LOG_WARN(LOG_FILTER_SQL, "Transaction aborted. %u queries not executed.", (uint32)queries.size());
|
||||
int errorCode = GetLastError();
|
||||
RollbackTransaction();
|
||||
return errorCode;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// we might encounter errors during certain queries, and depending on the kind of error
|
||||
// we might want to restart the transaction. So to prevent data loss, we only clean up when it's all done.
|
||||
// This is done in calling functions DatabaseWorkerPool<T>::DirectCommitTransaction and TransactionTask::Execute,
|
||||
// and not while iterating over every element.
|
||||
|
||||
CommitTransaction();
|
||||
return 0;
|
||||
}
|
||||
|
||||
MySQLPreparedStatement* MySQLConnection::GetPreparedStatement(uint32 index)
|
||||
{
|
||||
ASSERT(index < m_stmts.size());
|
||||
MySQLPreparedStatement* ret = m_stmts[index];
|
||||
if (!ret)
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "Could not fetch prepared statement %u on database `%s`, connection type: %s.",
|
||||
index, m_connectionInfo.database.c_str(), (m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void MySQLConnection::PrepareStatement(uint32 index, std::string const& sql, ConnectionFlags flags)
|
||||
{
|
||||
if (!m_reconnecting)
|
||||
{
|
||||
// Pre-calculate the size of the prepared statements
|
||||
size_t const m_argument_count = std::count(sql.begin(), sql.end(), '?');
|
||||
|
||||
// TC only supports uint8 indices.
|
||||
ASSERT(m_argument_count < std::numeric_limits<uint8>::max());
|
||||
|
||||
m_queries.insert(std::make_pair(index, PreparedStatementInfo(sql, static_cast<uint8>(m_argument_count), flags)));
|
||||
}
|
||||
// For reconnection case
|
||||
else
|
||||
delete m_stmts[index];
|
||||
|
||||
// Check if specified query should be prepared on this connection
|
||||
// i.e. don't prepare async statements on synchronous connections
|
||||
// to save memory that will not be used.
|
||||
if (!(m_connectionFlags & flags))
|
||||
{
|
||||
m_stmts[index] = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
MYSQL_STMT* stmt = mysql_stmt_init(m_Mysql);
|
||||
if (!stmt)
|
||||
{
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "In mysql_stmt_init() id: %u, sql: \"%s\"", index, sql.c_str());
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "%s", mysql_error(m_Mysql));
|
||||
m_prepareError = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mysql_stmt_prepare(stmt, sql.c_str(), static_cast<unsigned long>(sql.length())))
|
||||
{
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "In mysql_stmt_prepare() id: %u, sql: \"%s\"", index, sql.c_str());
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "%s", mysql_stmt_error(stmt));
|
||||
mysql_stmt_close(stmt);
|
||||
m_prepareError = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
MySQLPreparedStatement* mStmt = new MySQLPreparedStatement(stmt);
|
||||
m_stmts[index] = mStmt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PreparedResultSet* MySQLConnection::Query(PreparedStatement* stmt)
|
||||
{
|
||||
MYSQL_RES *result = NULL;
|
||||
uint64 rowCount = 0;
|
||||
uint32 fieldCount = 0;
|
||||
|
||||
QResult res = _Query(stmt, &result, &rowCount, &fieldCount);
|
||||
if (!res.res)
|
||||
return NULL;
|
||||
|
||||
if (mysql_more_results(m_Mysql))
|
||||
{
|
||||
mysql_next_result(m_Mysql);
|
||||
}
|
||||
|
||||
return new PreparedResultSet(res.m_stmt->GetSTMT(), result, rowCount, fieldCount);
|
||||
}
|
||||
|
||||
bool MySQLConnection::_HandleMySQLErrno(uint32 errNo)
|
||||
{
|
||||
switch (errNo)
|
||||
{
|
||||
case CR_SERVER_GONE_ERROR:
|
||||
case CR_SERVER_LOST:
|
||||
// for compatibility with newer versions of MariaDB
|
||||
#ifdef CR_INVALID_CONN_HANDLE
|
||||
case CR_INVALID_CONN_HANDLE:
|
||||
#endif
|
||||
case CR_SERVER_LOST_EXTENDED:
|
||||
{
|
||||
m_reconnecting = true;
|
||||
uint64 oldThreadId = mysql_thread_id(GetHandle());
|
||||
mysql_close(GetHandle());
|
||||
if (this->Open()) // Don't remove 'this' pointer unless you want to skip loading all prepared statements....
|
||||
{
|
||||
TC_LOG_INFO(LOG_FILTER_SQL, "Connection to the MySQL server is active.");
|
||||
if (oldThreadId != mysql_thread_id(GetHandle()))
|
||||
TC_LOG_INFO(LOG_FILTER_SQL, "Successfully reconnected to %s @%s:%s (%s).",
|
||||
m_connectionInfo.database.c_str(), m_connectionInfo.host.c_str(), m_connectionInfo.port_or_socket.c_str(),
|
||||
(m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous");
|
||||
|
||||
m_reconnecting = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 lErrno = mysql_errno(GetHandle()); // It's possible this attempted reconnect throws 2006 at us. To prevent crazy recursive calls, sleep here.
|
||||
std::this_thread::sleep_for(std::chrono::seconds(3)); // Sleep 3 seconds
|
||||
return _HandleMySQLErrno(lErrno); // Call self (recursive)
|
||||
}
|
||||
|
||||
case ER_LOCK_DEADLOCK:
|
||||
return false; // Implemented in TransactionTask::Execute and DatabaseWorkerPool<T>::DirectCommitTransaction
|
||||
// Query related errors - skip query
|
||||
case ER_WRONG_VALUE_COUNT:
|
||||
case ER_DUP_ENTRY:
|
||||
return false;
|
||||
|
||||
// Outdated table or database structure - terminate core
|
||||
case ER_BAD_FIELD_ERROR:
|
||||
case ER_NO_SUCH_TABLE:
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "Your database structure is not up to date. Please make sure you've executed all queries in the sql/updates folders.");
|
||||
std::this_thread::sleep_for(Seconds(10));
|
||||
std::abort();
|
||||
return false;
|
||||
case ER_PARSE_ERROR:
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "Error while parsing SQL. Core fix required.");
|
||||
std::this_thread::sleep_for(Seconds(10));
|
||||
std::abort();
|
||||
return false;
|
||||
default:
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "Unhandled MySQL errno %u. Unexpected behaviour possible.", errNo);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
161
src/common/Database/MySQLConnection.h
Normal file
161
src/common/Database/MySQLConnection.h
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "DatabaseWorkerPool.h"
|
||||
#include "Transaction.h"
|
||||
#include "Util.h"
|
||||
#include "ProducerConsumerQueue.h"
|
||||
|
||||
#ifndef _MYSQLCONNECTION_H
|
||||
#define _MYSQLCONNECTION_H
|
||||
|
||||
class DatabaseWorker;
|
||||
class PreparedStatement;
|
||||
class MySQLPreparedStatement;
|
||||
class PingOperation;
|
||||
|
||||
enum ConnectionFlags
|
||||
{
|
||||
CONNECTION_ASYNC = 0x1,
|
||||
CONNECTION_SYNCH = 0x2,
|
||||
CONNECTION_BOTH = CONNECTION_ASYNC | CONNECTION_SYNCH,
|
||||
};
|
||||
|
||||
struct MySQLConnectionInfo
|
||||
{
|
||||
MySQLConnectionInfo() {}
|
||||
MySQLConnectionInfo(const std::string& infoString)
|
||||
{
|
||||
Tokenizer tokens(infoString, ';');
|
||||
|
||||
if (tokens.size() != 5)
|
||||
return;
|
||||
|
||||
uint8 i = 0;
|
||||
|
||||
host.assign(tokens[i++]);
|
||||
port_or_socket.assign(tokens[i++]);
|
||||
user.assign(tokens[i++]);
|
||||
password.assign(tokens[i++]);
|
||||
database.assign(tokens[i++]);
|
||||
}
|
||||
|
||||
std::string user;
|
||||
std::string password;
|
||||
std::string database;
|
||||
std::string host;
|
||||
std::string port_or_socket;
|
||||
};
|
||||
|
||||
struct PreparedStatementInfo
|
||||
{
|
||||
PreparedStatementInfo(std::string const& query_, uint8 const capacity_, ConnectionFlags const flags_) :
|
||||
query(query_), capacity(capacity_), flags(flags_) { }
|
||||
|
||||
PreparedStatementInfo() : capacity(0), flags(CONNECTION_BOTH) { /*ASSERT(false);*/ }
|
||||
|
||||
std::string const query;
|
||||
|
||||
uint8 const capacity; // argument count
|
||||
|
||||
ConnectionFlags const flags; // sync/async
|
||||
};
|
||||
|
||||
typedef std::map<uint32 /*index*/, PreparedStatementInfo > PreparedStatementMap;
|
||||
|
||||
struct QResult
|
||||
{
|
||||
QResult(bool r, MySQLPreparedStatement*d) : res(r), m_stmt(d) {}
|
||||
|
||||
bool res;
|
||||
MySQLPreparedStatement* m_stmt;
|
||||
};
|
||||
|
||||
class MySQLConnection
|
||||
{
|
||||
template <class T> friend class DatabaseWorkerPool;
|
||||
friend class PingOperation;
|
||||
|
||||
public:
|
||||
MySQLConnection(MySQLConnectionInfo& connInfo); //! Constructor for synchronous connections.
|
||||
MySQLConnection(ProducerConsumerQueue<SQLOperation*>* queue, MySQLConnectionInfo& connInfo); //! Constructor for asynchronous connections.
|
||||
virtual ~MySQLConnection();
|
||||
|
||||
virtual bool Open();
|
||||
void Close();
|
||||
|
||||
public:
|
||||
bool Execute(const char* sql);
|
||||
bool Execute(PreparedStatement* stmt);
|
||||
ResultSet* Query(const char* sql);
|
||||
PreparedResultSet* Query(PreparedStatement* stmt);
|
||||
bool _Query(const char *sql, MYSQL_RES **pResult, MYSQL_FIELD **pFields, uint64* pRowCount, uint32* pFieldCount);
|
||||
QResult _Query(PreparedStatement* stmt, MYSQL_RES **pResult, uint64* pRowCount, uint32* pFieldCount);
|
||||
|
||||
void BeginTransaction();
|
||||
void RollbackTransaction();
|
||||
void CommitTransaction();
|
||||
int ExecuteTransaction(SQLTransaction& transaction);
|
||||
|
||||
operator bool () const { return m_Mysql != NULL; }
|
||||
void Ping() { mysql_ping(m_Mysql); }
|
||||
|
||||
uint32 GetLastError() { return mysql_errno(m_Mysql); }
|
||||
|
||||
protected:
|
||||
bool LockIfReady()
|
||||
{
|
||||
/// Tries to acquire lock. If lock is acquired by another thread
|
||||
/// the calling parent will just try another connection
|
||||
return m_Mutex.try_lock();
|
||||
}
|
||||
|
||||
void Unlock()
|
||||
{
|
||||
/// Called by parent databasepool. Will let other threads access this connection
|
||||
m_Mutex.unlock();
|
||||
}
|
||||
|
||||
MYSQL* GetHandle() { return m_Mysql; }
|
||||
MySQLPreparedStatement* GetPreparedStatement(uint32 index);
|
||||
void PrepareStatement(uint32 index, std::string const& sql, ConnectionFlags flags);
|
||||
|
||||
bool PrepareStatements();
|
||||
virtual void DoPrepareStatements() = 0;
|
||||
|
||||
protected:
|
||||
std::vector<MySQLPreparedStatement*> m_stmts; //! PreparedStatements storage
|
||||
PreparedStatementMap m_queries; //! Query storage
|
||||
bool m_reconnecting; //! Are we reconnecting?
|
||||
bool m_prepareError; //! Was there any error while preparing statements?
|
||||
|
||||
private:
|
||||
bool _HandleMySQLErrno(uint32 errNo);
|
||||
|
||||
private:
|
||||
ProducerConsumerQueue<SQLOperation*>* m_queue; //! Queue shared with other asynchronous connections.
|
||||
DatabaseWorker* m_worker; //! Core worker task.
|
||||
MYSQL * m_Mysql; //! MySQL Handle.
|
||||
MySQLConnectionInfo& m_connectionInfo; //! Connection info (used for logging)
|
||||
ConnectionFlags m_connectionFlags; //! Connection flags (for preparing relevant statements)
|
||||
std::mutex m_Mutex;
|
||||
|
||||
MySQLConnection(MySQLConnection const& right) = delete;
|
||||
MySQLConnection& operator=(MySQLConnection const& right) = delete;
|
||||
};
|
||||
|
||||
#endif
|
||||
29
src/common/Database/MySQLThreading.cpp
Normal file
29
src/common/Database/MySQLThreading.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "MySQLThreading.h"
|
||||
#include "mysql.h"
|
||||
|
||||
void MySQL::Library_Init()
|
||||
{
|
||||
mysql_library_init(-1, NULL, NULL);
|
||||
}
|
||||
|
||||
void MySQL::Library_End()
|
||||
{
|
||||
mysql_library_end();
|
||||
}
|
||||
31
src/common/Database/MySQLThreading.h
Normal file
31
src/common/Database/MySQLThreading.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _MYSQLTHREADING_H
|
||||
#define _MYSQLTHREADING_H
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
class MySQL
|
||||
{
|
||||
public:
|
||||
static void Library_Init();
|
||||
|
||||
static void Library_End();
|
||||
};
|
||||
|
||||
#endif
|
||||
484
src/common/Database/PreparedStatement.cpp
Normal file
484
src/common/Database/PreparedStatement.cpp
Normal file
@@ -0,0 +1,484 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PreparedStatement.h"
|
||||
#include "MySQLConnection.h"
|
||||
#include "Log.h"
|
||||
|
||||
PreparedStatement::PreparedStatement(uint32 index, uint8 capacity) :
|
||||
m_index(index), statement_data(capacity)
|
||||
{
|
||||
}
|
||||
|
||||
PreparedStatement::~PreparedStatement()
|
||||
{
|
||||
}
|
||||
|
||||
void PreparedStatement::BindParameters(MySQLPreparedStatement* m_stmt) const
|
||||
{
|
||||
ASSERT (m_stmt);
|
||||
|
||||
uint32 i = 0;
|
||||
for (; i < statement_data.size(); i++)
|
||||
{
|
||||
switch (statement_data[i].type)
|
||||
{
|
||||
case TYPE_BOOL:
|
||||
m_stmt->setBool(i, statement_data[i].data.boolean);
|
||||
break;
|
||||
case TYPE_UI8:
|
||||
m_stmt->setUInt8(i, statement_data[i].data.ui8);
|
||||
break;
|
||||
case TYPE_UI16:
|
||||
m_stmt->setUInt16(i, statement_data[i].data.ui16);
|
||||
break;
|
||||
case TYPE_UI32:
|
||||
m_stmt->setUInt32(i, statement_data[i].data.ui32);
|
||||
break;
|
||||
case TYPE_I8:
|
||||
m_stmt->setInt8(i, statement_data[i].data.i8);
|
||||
break;
|
||||
case TYPE_I16:
|
||||
m_stmt->setInt16(i, statement_data[i].data.i16);
|
||||
break;
|
||||
case TYPE_I32:
|
||||
m_stmt->setInt32(i, statement_data[i].data.i32);
|
||||
break;
|
||||
case TYPE_UI64:
|
||||
m_stmt->setUInt64(i, statement_data[i].data.ui64);
|
||||
break;
|
||||
case TYPE_I64:
|
||||
m_stmt->setInt64(i, statement_data[i].data.i64);
|
||||
break;
|
||||
case TYPE_FLOAT:
|
||||
m_stmt->setFloat(i, statement_data[i].data.f);
|
||||
break;
|
||||
case TYPE_DOUBLE:
|
||||
m_stmt->setDouble(i, statement_data[i].data.d);
|
||||
break;
|
||||
case TYPE_STRING:
|
||||
m_stmt->setBinary(i, statement_data[i].binary, true);
|
||||
break;
|
||||
case TYPE_BINARY:
|
||||
m_stmt->setBinary(i, statement_data[i].binary, false);
|
||||
break;
|
||||
case TYPE_NULL:
|
||||
m_stmt->setNull(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
if (i < m_stmt->m_paramCount)
|
||||
TC_LOG_WARN(LOG_FILTER_SQL, "[WARNING]: BindParameters() for statement %u did not bind all allocated parameters", m_index);
|
||||
#endif
|
||||
}
|
||||
|
||||
//- Bind to buffer
|
||||
void PreparedStatement::setBool(const uint8 index, const bool value)
|
||||
{
|
||||
ASSERT(index < statement_data.size());
|
||||
statement_data[index].data.boolean = value;
|
||||
statement_data[index].type = TYPE_BOOL;
|
||||
}
|
||||
|
||||
void PreparedStatement::setUInt8(const uint8 index, const uint8 value)
|
||||
{
|
||||
ASSERT(index < statement_data.size());
|
||||
statement_data[index].data.ui8 = value;
|
||||
statement_data[index].type = TYPE_UI8;
|
||||
}
|
||||
|
||||
void PreparedStatement::setUInt16(const uint8 index, const uint16 value)
|
||||
{
|
||||
ASSERT(index < statement_data.size());
|
||||
statement_data[index].data.ui16 = value;
|
||||
statement_data[index].type = TYPE_UI16;
|
||||
}
|
||||
|
||||
void PreparedStatement::setUInt32(const uint8 index, const uint32 value)
|
||||
{
|
||||
ASSERT(index < statement_data.size());
|
||||
statement_data[index].data.ui32 = value;
|
||||
statement_data[index].type = TYPE_UI32;
|
||||
}
|
||||
|
||||
void PreparedStatement::setUInt64(const uint8 index, const uint64 value)
|
||||
{
|
||||
ASSERT(index < statement_data.size());
|
||||
statement_data[index].data.ui64 = value;
|
||||
statement_data[index].type = TYPE_UI64;
|
||||
}
|
||||
|
||||
void PreparedStatement::setInt8(const uint8 index, const int8 value)
|
||||
{
|
||||
ASSERT(index < statement_data.size());
|
||||
statement_data[index].data.i8 = value;
|
||||
statement_data[index].type = TYPE_I8;
|
||||
}
|
||||
|
||||
void PreparedStatement::setInt16(const uint8 index, const int16 value)
|
||||
{
|
||||
ASSERT(index < statement_data.size());
|
||||
statement_data[index].data.i16 = value;
|
||||
statement_data[index].type = TYPE_I16;
|
||||
}
|
||||
|
||||
void PreparedStatement::setInt32(const uint8 index, const int32 value)
|
||||
{
|
||||
ASSERT(index < statement_data.size());
|
||||
statement_data[index].data.i32 = value;
|
||||
statement_data[index].type = TYPE_I32;
|
||||
}
|
||||
|
||||
void PreparedStatement::setInt64(const uint8 index, const int64 value)
|
||||
{
|
||||
ASSERT(index < statement_data.size());
|
||||
statement_data[index].data.i64 = value;
|
||||
statement_data[index].type = TYPE_I64;
|
||||
}
|
||||
|
||||
void PreparedStatement::setFloat(const uint8 index, const float value)
|
||||
{
|
||||
ASSERT(index < statement_data.size());
|
||||
statement_data[index].data.f = value;
|
||||
statement_data[index].type = TYPE_FLOAT;
|
||||
}
|
||||
|
||||
void PreparedStatement::setDouble(const uint8 index, const double value)
|
||||
{
|
||||
ASSERT(index < statement_data.size());
|
||||
statement_data[index].data.d = value;
|
||||
statement_data[index].type = TYPE_DOUBLE;
|
||||
}
|
||||
|
||||
void PreparedStatement::setString(const uint8 index, const std::string& value)
|
||||
{
|
||||
ASSERT(index < statement_data.size());
|
||||
statement_data[index].binary.resize(value.length() + 1);
|
||||
memcpy(statement_data[index].binary.data(), value.c_str(), value.length() + 1);
|
||||
statement_data[index].type = TYPE_STRING;
|
||||
}
|
||||
|
||||
void PreparedStatement::setBinary(const uint8 index, const std::vector<uint8>& value)
|
||||
{
|
||||
ASSERT(index < statement_data.size());
|
||||
statement_data[index].binary = value;
|
||||
statement_data[index].type = TYPE_BINARY;
|
||||
}
|
||||
|
||||
void PreparedStatement::setNull(const uint8 index)
|
||||
{
|
||||
ASSERT(index < statement_data.size());
|
||||
statement_data[index].type = TYPE_NULL;
|
||||
}
|
||||
|
||||
MySQLPreparedStatement::MySQLPreparedStatement(MYSQL_STMT* stmt) :
|
||||
m_Mstmt(stmt),
|
||||
m_bind(NULL)
|
||||
{
|
||||
/// Initialize variable parameters
|
||||
m_paramCount = mysql_stmt_param_count(stmt);
|
||||
m_paramsSet.assign(m_paramCount, false);
|
||||
m_bind = new MYSQL_BIND[m_paramCount];
|
||||
memset(m_bind, 0, sizeof(MYSQL_BIND)*m_paramCount);
|
||||
|
||||
/// "If set to 1, causes mysql_stmt_store_result() to update the metadata MYSQL_FIELD->max_length value."
|
||||
my_bool bool_tmp = 1;
|
||||
mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &bool_tmp);
|
||||
}
|
||||
|
||||
MySQLPreparedStatement::~MySQLPreparedStatement()
|
||||
{
|
||||
ClearParameters();
|
||||
if (m_Mstmt->bind_result_done)
|
||||
{
|
||||
delete[] m_Mstmt->bind->length;
|
||||
delete[] m_Mstmt->bind->is_null;
|
||||
}
|
||||
mysql_stmt_close(m_Mstmt);
|
||||
delete[] m_bind;
|
||||
}
|
||||
|
||||
void MySQLPreparedStatement::ClearParameters()
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> guard(i_data_lock);
|
||||
for (uint32 i=0; i < m_paramCount; ++i)
|
||||
{
|
||||
delete m_bind[i].length;
|
||||
m_bind[i].length = NULL;
|
||||
delete[] (char*) m_bind[i].buffer;
|
||||
m_bind[i].buffer = NULL;
|
||||
m_paramsSet[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ParementerIndexAssertFail(uint32 stmtIndex, uint8 index, uint32 paramCount)
|
||||
{
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "Attempted to bind parameter %u%s on a PreparedStatement %u (statement has only %u parameters)", uint32(index) + 1, (index == 1 ? "st" : (index == 2 ? "nd" : (index == 3 ? "rd" : "nd"))), stmtIndex, paramCount);
|
||||
return false;
|
||||
}
|
||||
|
||||
//- Bind on mysql level
|
||||
void MySQLPreparedStatement::AssertValidIndex(uint8 index)
|
||||
{
|
||||
ASSERT(index < m_paramCount || ParementerIndexAssertFail(m_stmt->m_index, index, m_paramCount));
|
||||
|
||||
if (m_paramsSet[index])
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "[ERROR] Prepared Statement (id: %u) trying to bind value on already bound index (%u).", m_stmt->m_index, index);
|
||||
}
|
||||
|
||||
void MySQLPreparedStatement::setBool(const uint8 index, const bool value)
|
||||
{
|
||||
setUInt8(index, value ? 1 : 0);
|
||||
}
|
||||
|
||||
void MySQLPreparedStatement::setUInt8(const uint8 index, const uint8 value)
|
||||
{
|
||||
AssertValidIndex(index);
|
||||
m_paramsSet[index] = true;
|
||||
MYSQL_BIND* param = &m_bind[index];
|
||||
setValue(param, MYSQL_TYPE_TINY, &value, sizeof(uint8), true);
|
||||
}
|
||||
|
||||
void MySQLPreparedStatement::setUInt16(const uint8 index, const uint16 value)
|
||||
{
|
||||
AssertValidIndex(index);
|
||||
m_paramsSet[index] = true;
|
||||
MYSQL_BIND* param = &m_bind[index];
|
||||
setValue(param, MYSQL_TYPE_SHORT, &value, sizeof(uint16), true);
|
||||
}
|
||||
|
||||
void MySQLPreparedStatement::setUInt32(const uint8 index, const uint32 value)
|
||||
{
|
||||
AssertValidIndex(index);
|
||||
m_paramsSet[index] = true;
|
||||
MYSQL_BIND* param = &m_bind[index];
|
||||
setValue(param, MYSQL_TYPE_LONG, &value, sizeof(uint32), true);
|
||||
}
|
||||
|
||||
void MySQLPreparedStatement::setUInt64(const uint8 index, const uint64 value)
|
||||
{
|
||||
AssertValidIndex(index);
|
||||
m_paramsSet[index] = true;
|
||||
MYSQL_BIND* param = &m_bind[index];
|
||||
setValue(param, MYSQL_TYPE_LONGLONG, &value, sizeof(uint64), true);
|
||||
}
|
||||
|
||||
void MySQLPreparedStatement::setInt8(const uint8 index, const int8 value)
|
||||
{
|
||||
AssertValidIndex(index);
|
||||
m_paramsSet[index] = true;
|
||||
MYSQL_BIND* param = &m_bind[index];
|
||||
setValue(param, MYSQL_TYPE_TINY, &value, sizeof(int8), false);
|
||||
}
|
||||
|
||||
void MySQLPreparedStatement::setInt16(const uint8 index, const int16 value)
|
||||
{
|
||||
AssertValidIndex(index);
|
||||
m_paramsSet[index] = true;
|
||||
MYSQL_BIND* param = &m_bind[index];
|
||||
setValue(param, MYSQL_TYPE_SHORT, &value, sizeof(int16), false);
|
||||
}
|
||||
|
||||
void MySQLPreparedStatement::setInt32(const uint8 index, const int32 value)
|
||||
{
|
||||
AssertValidIndex(index);
|
||||
m_paramsSet[index] = true;
|
||||
MYSQL_BIND* param = &m_bind[index];
|
||||
setValue(param, MYSQL_TYPE_LONG, &value, sizeof(int32), false);
|
||||
}
|
||||
|
||||
void MySQLPreparedStatement::setInt64(const uint8 index, const int64 value)
|
||||
{
|
||||
AssertValidIndex(index);
|
||||
m_paramsSet[index] = true;
|
||||
MYSQL_BIND* param = &m_bind[index];
|
||||
setValue(param, MYSQL_TYPE_LONGLONG, &value, sizeof(int64), false);
|
||||
}
|
||||
|
||||
void MySQLPreparedStatement::setFloat(const uint8 index, const float value)
|
||||
{
|
||||
AssertValidIndex(index);
|
||||
m_paramsSet[index] = true;
|
||||
MYSQL_BIND* param = &m_bind[index];
|
||||
setValue(param, MYSQL_TYPE_FLOAT, &value, sizeof(float), (value > 0.0f));
|
||||
}
|
||||
|
||||
void MySQLPreparedStatement::setDouble(const uint8 index, const double value)
|
||||
{
|
||||
AssertValidIndex(index);
|
||||
m_paramsSet[index] = true;
|
||||
MYSQL_BIND* param = &m_bind[index];
|
||||
setValue(param, MYSQL_TYPE_DOUBLE, &value, sizeof(double), (value > 0.0f));
|
||||
}
|
||||
|
||||
void MySQLPreparedStatement::setBinary(const uint8 index, const std::vector<uint8>& value, bool isString)
|
||||
{
|
||||
AssertValidIndex(index);
|
||||
m_paramsSet[index] = true;
|
||||
MYSQL_BIND* param = &m_bind[index];
|
||||
size_t len = value.size();
|
||||
param->buffer_type = MYSQL_TYPE_BLOB;
|
||||
delete [] static_cast<char *>(param->buffer);
|
||||
param->buffer = new char[len];
|
||||
param->buffer_length = len;
|
||||
param->is_null_value = 0;
|
||||
delete param->length;
|
||||
param->length = new unsigned long(len);
|
||||
if (isString)
|
||||
{
|
||||
*param->length -= 1;
|
||||
param->buffer_type = MYSQL_TYPE_VAR_STRING;
|
||||
}
|
||||
|
||||
memcpy(param->buffer, value.data(), len);
|
||||
}
|
||||
|
||||
void MySQLPreparedStatement::setNull(const uint8 index)
|
||||
{
|
||||
AssertValidIndex(index);
|
||||
m_paramsSet[index] = true;
|
||||
MYSQL_BIND* param = &m_bind[index];
|
||||
param->buffer_type = MYSQL_TYPE_NULL;
|
||||
delete [] static_cast<char *>(param->buffer);
|
||||
param->buffer = NULL;
|
||||
param->buffer_length = 0;
|
||||
param->is_null_value = 1;
|
||||
delete param->length;
|
||||
param->length = NULL;
|
||||
}
|
||||
|
||||
void MySQLPreparedStatement::setValue(MYSQL_BIND* param, enum_field_types type, const void* value, uint32 len, bool isUnsigned)
|
||||
{
|
||||
param->buffer_type = type;
|
||||
delete [] static_cast<char *>(param->buffer);
|
||||
param->buffer = new char[len];
|
||||
param->buffer_length = 0;
|
||||
param->is_null_value = 0;
|
||||
param->length = NULL; // Only != NULL for strings
|
||||
param->is_unsigned = isUnsigned;
|
||||
|
||||
memcpy(param->buffer, value, len);
|
||||
}
|
||||
|
||||
std::string MySQLPreparedStatement::getQueryString(std::string const &sqlPattern) const
|
||||
{
|
||||
std::string queryString = sqlPattern;
|
||||
|
||||
size_t pos = 0;
|
||||
for (uint32 i = 0; i < m_stmt->statement_data.size(); i++)
|
||||
{
|
||||
pos = queryString.find('?', pos);
|
||||
std::stringstream ss;
|
||||
|
||||
switch (m_stmt->statement_data[i].type)
|
||||
{
|
||||
case TYPE_BOOL:
|
||||
ss << uint16(m_stmt->statement_data[i].data.boolean);
|
||||
break;
|
||||
case TYPE_UI8:
|
||||
ss << uint16(m_stmt->statement_data[i].data.ui8); // stringstream will append a character with that code instead of numeric representation
|
||||
break;
|
||||
case TYPE_UI16:
|
||||
ss << m_stmt->statement_data[i].data.ui16;
|
||||
break;
|
||||
case TYPE_UI32:
|
||||
ss << m_stmt->statement_data[i].data.ui32;
|
||||
break;
|
||||
case TYPE_I8:
|
||||
ss << int16(m_stmt->statement_data[i].data.i8); // stringstream will append a character with that code instead of numeric representation
|
||||
break;
|
||||
case TYPE_I16:
|
||||
ss << m_stmt->statement_data[i].data.i16;
|
||||
break;
|
||||
case TYPE_I32:
|
||||
ss << m_stmt->statement_data[i].data.i32;
|
||||
break;
|
||||
case TYPE_UI64:
|
||||
ss << m_stmt->statement_data[i].data.ui64;
|
||||
break;
|
||||
case TYPE_I64:
|
||||
ss << m_stmt->statement_data[i].data.i64;
|
||||
break;
|
||||
case TYPE_FLOAT:
|
||||
ss << m_stmt->statement_data[i].data.f;
|
||||
break;
|
||||
case TYPE_DOUBLE:
|
||||
ss << m_stmt->statement_data[i].data.d;
|
||||
break;
|
||||
case TYPE_STRING:
|
||||
ss << (char const*)m_stmt->statement_data[i].binary.data();
|
||||
break;
|
||||
case TYPE_BINARY:
|
||||
ss << "BINARY";
|
||||
break;
|
||||
case TYPE_NULL:
|
||||
ss << "NULL";
|
||||
break;
|
||||
}
|
||||
|
||||
std::string replaceStr = ss.str();
|
||||
queryString.replace(pos, 1, replaceStr);
|
||||
pos += replaceStr.length();
|
||||
}
|
||||
|
||||
return queryString;
|
||||
}
|
||||
|
||||
//- Execution
|
||||
PreparedStatementTask::PreparedStatementTask(PreparedStatement* stmt, bool async, bool iscallback, std::function<void(PreparedQueryResult)> && callback) :
|
||||
m_stmt(stmt), m_Callback(std::move(callback))
|
||||
{
|
||||
m_has_result = async; // If it's async, then there's a result
|
||||
m_has_callback = iscallback;
|
||||
if (async)
|
||||
m_result = new PreparedQueryResultPromise();
|
||||
}
|
||||
|
||||
PreparedStatementTask::~PreparedStatementTask()
|
||||
{
|
||||
delete m_stmt;
|
||||
if (m_has_result && m_result != nullptr)
|
||||
delete m_result;
|
||||
}
|
||||
|
||||
bool PreparedStatementTask::Execute()
|
||||
{
|
||||
if (m_has_result)
|
||||
{
|
||||
PreparedResultSet* result = m_conn->Query(m_stmt);
|
||||
if (!result || !result->GetRowCount())
|
||||
{
|
||||
delete result;
|
||||
if (m_has_callback)
|
||||
m_Callback(PreparedQueryResult(NULL));
|
||||
else
|
||||
m_result->set_value(PreparedQueryResult(NULL));
|
||||
return false;
|
||||
}
|
||||
if (m_has_callback)
|
||||
m_Callback(PreparedQueryResult(result));
|
||||
else
|
||||
m_result->set_value(PreparedQueryResult(result));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _executed = m_conn->Execute(m_stmt);
|
||||
if (_executed && m_has_callback)
|
||||
m_Callback(PreparedQueryResult(NULL));
|
||||
return _executed;
|
||||
}
|
||||
168
src/common/Database/PreparedStatement.h
Normal file
168
src/common/Database/PreparedStatement.h
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _PREPAREDSTATEMENT_H
|
||||
#define _PREPAREDSTATEMENT_H
|
||||
|
||||
#include "SQLOperation.h"
|
||||
#include "DatabaseEnvFwd.h"
|
||||
|
||||
//- Union for data buffer (upper-level bind -> queue -> lower-level bind)
|
||||
union PreparedStatementDataUnion
|
||||
{
|
||||
bool boolean;
|
||||
uint8 ui8;
|
||||
int8 i8;
|
||||
uint16 ui16;
|
||||
int16 i16;
|
||||
uint32 ui32;
|
||||
int32 i32;
|
||||
uint64 ui64;
|
||||
int64 i64;
|
||||
float f;
|
||||
double d;
|
||||
};
|
||||
|
||||
//- This enum helps us differ data held in above union
|
||||
enum PreparedStatementValueType
|
||||
{
|
||||
TYPE_BOOL,
|
||||
TYPE_UI8,
|
||||
TYPE_UI16,
|
||||
TYPE_UI32,
|
||||
TYPE_UI64,
|
||||
TYPE_I8,
|
||||
TYPE_I16,
|
||||
TYPE_I32,
|
||||
TYPE_I64,
|
||||
TYPE_FLOAT,
|
||||
TYPE_DOUBLE,
|
||||
TYPE_STRING,
|
||||
TYPE_BINARY,
|
||||
TYPE_NULL
|
||||
};
|
||||
|
||||
struct PreparedStatementData
|
||||
{
|
||||
PreparedStatementDataUnion data;
|
||||
PreparedStatementValueType type;
|
||||
std::vector<uint8> binary;
|
||||
};
|
||||
|
||||
//- Forward declare
|
||||
class MySQLPreparedStatement;
|
||||
|
||||
//- Upper-level class that is used in code
|
||||
class PreparedStatement
|
||||
{
|
||||
friend class PreparedStatementTask;
|
||||
friend class MySQLPreparedStatement;
|
||||
friend class MySQLConnection;
|
||||
|
||||
public:
|
||||
explicit PreparedStatement(uint32 index, uint8 capacity);
|
||||
~PreparedStatement();
|
||||
|
||||
void setBool(uint8 index, bool value);
|
||||
void setUInt8(uint8 index, uint8 value);
|
||||
void setUInt16(uint8 index, uint16 value);
|
||||
void setUInt32(uint8 index, uint32 value);
|
||||
void setUInt64(uint8 index, uint64 value);
|
||||
void setInt8(uint8 index, int8 value);
|
||||
void setInt16(uint8 index, int16 value);
|
||||
void setInt32(uint8 index, int32 value);
|
||||
void setInt64(uint8 index, int64 value);
|
||||
void setFloat(uint8 index, float value);
|
||||
void setDouble(uint8 index, double value);
|
||||
void setString(uint8 index, const std::string& value);
|
||||
void setBinary(uint8 index, const std::vector<uint8>& value);
|
||||
void setNull(uint8 index);
|
||||
|
||||
protected:
|
||||
//- Copy the parameters to a real MySQLPreparedStatement
|
||||
void BindParameters(MySQLPreparedStatement* m_stmt) const;
|
||||
|
||||
uint32 m_index;
|
||||
//- Buffer of parameters, not tied to MySQL in any way yet
|
||||
std::vector<PreparedStatementData> statement_data;
|
||||
};
|
||||
|
||||
//- Class of which the instances are unique per MySQLConnection
|
||||
//- access to these class objects is only done when a prepared statement task
|
||||
//- is executed.
|
||||
class MySQLPreparedStatement
|
||||
{
|
||||
friend class MySQLConnection;
|
||||
friend class PreparedStatement;
|
||||
|
||||
public:
|
||||
MySQLPreparedStatement(MYSQL_STMT* stmt);
|
||||
~MySQLPreparedStatement();
|
||||
|
||||
void setBool(uint8 index, bool value);
|
||||
void setUInt8(uint8 index, uint8 value);
|
||||
void setUInt16(uint8 index, uint16 value);
|
||||
void setUInt32(uint8 index, uint32 value);
|
||||
void setUInt64(uint8 index, uint64 value);
|
||||
void setInt8(uint8 index, int8 value);
|
||||
void setInt16(uint8 index, int16 value);
|
||||
void setInt32(uint8 index, int32 value);
|
||||
void setInt64(uint8 index, int64 value);
|
||||
void setFloat(uint8 index, float value);
|
||||
void setDouble(uint8 index, double value);
|
||||
void setBinary(uint8 index, const std::vector<uint8>& value, bool isString);
|
||||
void setNull(uint8 index);
|
||||
|
||||
protected:
|
||||
MYSQL_STMT* GetSTMT() { return m_Mstmt; }
|
||||
MYSQL_BIND* GetBind() { return m_bind; }
|
||||
PreparedStatement* m_stmt;
|
||||
void ClearParameters();
|
||||
void AssertValidIndex(uint8 index);
|
||||
std::string getQueryString(std::string const &sqlPattern) const;
|
||||
|
||||
private:
|
||||
void setValue(MYSQL_BIND* param, enum_field_types type, const void* value, uint32 len, bool isUnsigned);
|
||||
|
||||
MYSQL_STMT* m_Mstmt;
|
||||
uint32 m_paramCount;
|
||||
std::vector<bool> m_paramsSet;
|
||||
MYSQL_BIND* m_bind;
|
||||
std::recursive_mutex i_data_lock;
|
||||
|
||||
MySQLPreparedStatement(MySQLPreparedStatement const& right) = delete;
|
||||
MySQLPreparedStatement& operator=(MySQLPreparedStatement const& right) = delete;
|
||||
};
|
||||
|
||||
//- Lower-level class, enqueuable operation
|
||||
class PreparedStatementTask : public SQLOperation
|
||||
{
|
||||
public:
|
||||
PreparedStatementTask(PreparedStatement* stmt, bool async = false, bool iscallback = false, std::function<void(PreparedQueryResult)> && callback = [](PreparedQueryResult) -> void {});
|
||||
~PreparedStatementTask();
|
||||
|
||||
bool Execute() override;
|
||||
PreparedQueryResultFuture GetFuture() { return m_result->get_future(); }
|
||||
|
||||
protected:
|
||||
PreparedStatement* m_stmt;
|
||||
bool m_has_result;
|
||||
bool m_has_callback;
|
||||
PreparedQueryResultPromise* m_result;
|
||||
std::function<void(PreparedQueryResult)> m_Callback;
|
||||
};
|
||||
#endif
|
||||
221
src/common/Database/QueryCallback.cpp
Normal file
221
src/common/Database/QueryCallback.cpp
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "QueryCallback.h"
|
||||
#include "Errors.h"
|
||||
|
||||
template<typename T, typename... Args>
|
||||
void Construct(T& t, Args&&... args)
|
||||
{
|
||||
new (&t) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Destroy(T& t)
|
||||
{
|
||||
t.~T();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ConstructActiveMember(T* obj)
|
||||
{
|
||||
if (!obj->_isPrepared)
|
||||
Construct(obj->_string);
|
||||
else
|
||||
Construct(obj->_prepared);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DestroyActiveMember(T* obj)
|
||||
{
|
||||
if (!obj->_isPrepared)
|
||||
Destroy(obj->_string);
|
||||
else
|
||||
Destroy(obj->_prepared);
|
||||
}
|
||||
|
||||
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 QueryCallback;
|
||||
|
||||
QueryCallbackData(std::function<void(QueryCallback&, QueryResult)>&& callback) : _string(std::move(callback)), _isPrepared(false) { }
|
||||
QueryCallbackData(std::function<void(QueryCallback&, PreparedQueryResult)>&& callback) : _prepared(std::move(callback)), _isPrepared(true) { }
|
||||
QueryCallbackData(QueryCallbackData&& right) noexcept
|
||||
{
|
||||
_isPrepared = right._isPrepared;
|
||||
ConstructActiveMember(this);
|
||||
MoveFrom(this, std::move(right));
|
||||
}
|
||||
QueryCallbackData& operator=(QueryCallbackData&& right) noexcept
|
||||
{
|
||||
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 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(QueryCallback&, QueryResult)> _string;
|
||||
std::function<void(QueryCallback&, PreparedQueryResult)> _prepared;
|
||||
};
|
||||
bool _isPrepared;
|
||||
};
|
||||
|
||||
// Not using initialization lists to work around segmentation faults when compiling with clang without precompiled headers
|
||||
QueryCallback::QueryCallback(std::future<QueryResult>&& result)
|
||||
{
|
||||
_isPrepared = false;
|
||||
Construct(_string, std::move(result));
|
||||
}
|
||||
|
||||
QueryCallback::QueryCallback(std::future<PreparedQueryResult>&& result)
|
||||
{
|
||||
_isPrepared = true;
|
||||
Construct(_prepared, std::move(result));
|
||||
}
|
||||
|
||||
QueryCallback::QueryCallback(QueryCallback&& right) noexcept
|
||||
{
|
||||
_isPrepared = right._isPrepared;
|
||||
ConstructActiveMember(this);
|
||||
MoveFrom(this, std::move(right));
|
||||
_callbacks = std::move(right._callbacks);
|
||||
}
|
||||
|
||||
QueryCallback& QueryCallback::operator=(QueryCallback&& right) noexcept
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
QueryCallback::~QueryCallback()
|
||||
{
|
||||
DestroyActiveMember(this);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
QueryResultFuture f(std::move(_string));
|
||||
std::function<void(QueryCallback&, QueryResult)> cb(std::move(callback._string));
|
||||
cb(*this, f.get());
|
||||
return checkStateAndReturnCompletion();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_prepared.valid() && _prepared.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
|
||||
{
|
||||
PreparedQueryResultFuture f(std::move(_prepared));
|
||||
std::function<void(QueryCallback&, PreparedQueryResult)> cb(std::move(callback._prepared));
|
||||
cb(*this, f.get());
|
||||
return checkStateAndReturnCompletion();
|
||||
}
|
||||
}
|
||||
|
||||
return NotReady;
|
||||
}
|
||||
75
src/common/Database/QueryCallback.h
Normal file
75
src/common/Database/QueryCallback.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _QUERY_CALLBACK_H
|
||||
#define _QUERY_CALLBACK_H
|
||||
|
||||
#include "Define.h"
|
||||
#include "DatabaseEnvFwd.h"
|
||||
#include <functional>
|
||||
#include <future>
|
||||
#include <list>
|
||||
#include <queue>
|
||||
#include <utility>
|
||||
|
||||
class QueryCallback
|
||||
{
|
||||
public:
|
||||
explicit QueryCallback(QueryResultFuture&& result);
|
||||
explicit QueryCallback(PreparedQueryResultFuture&& result);
|
||||
QueryCallback(QueryCallback&& right) noexcept;
|
||||
QueryCallback& operator=(QueryCallback&& right) noexcept;
|
||||
~QueryCallback();
|
||||
|
||||
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
|
||||
{
|
||||
NotReady,
|
||||
NextStep,
|
||||
Completed
|
||||
};
|
||||
|
||||
Status InvokeIfReady();
|
||||
|
||||
private:
|
||||
QueryCallback(QueryCallback const& right) = delete;
|
||||
QueryCallback& operator=(QueryCallback const& right) = delete;
|
||||
|
||||
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
|
||||
{
|
||||
QueryResultFuture _string;
|
||||
PreparedQueryResultFuture _prepared;
|
||||
};
|
||||
bool _isPrepared;
|
||||
|
||||
struct QueryCallbackData;
|
||||
std::queue<QueryCallbackData, std::list<QueryCallbackData>> _callbacks;
|
||||
};
|
||||
|
||||
#endif // _QUERY_CALLBACK_H
|
||||
48
src/common/Database/QueryCallbackProcessor.cpp
Normal file
48
src/common/Database/QueryCallbackProcessor.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "QueryCallbackProcessor.h"
|
||||
#include "QueryCallback.h"
|
||||
#include <algorithm>
|
||||
|
||||
QueryCallbackProcessor::QueryCallbackProcessor()
|
||||
{
|
||||
}
|
||||
|
||||
QueryCallbackProcessor::~QueryCallbackProcessor()
|
||||
{
|
||||
}
|
||||
|
||||
void QueryCallbackProcessor::AddQuery(QueryCallback&& query)
|
||||
{
|
||||
_callbacks.emplace_back(std::move(query));
|
||||
}
|
||||
|
||||
void QueryCallbackProcessor::ProcessReadyQueries()
|
||||
{
|
||||
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() == QueryCallback::Completed;
|
||||
}), updateCallbacks.end());
|
||||
|
||||
_callbacks.insert(_callbacks.end(), std::make_move_iterator(updateCallbacks.begin()), std::make_move_iterator(updateCallbacks.end()));
|
||||
}
|
||||
42
src/common/Database/QueryCallbackProcessor.h
Normal file
42
src/common/Database/QueryCallbackProcessor.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef QueryCallbackProcessor_h__
|
||||
#define QueryCallbackProcessor_h__
|
||||
|
||||
#include "Define.h"
|
||||
#include <vector>
|
||||
|
||||
class QueryCallback;
|
||||
|
||||
class QueryCallbackProcessor
|
||||
{
|
||||
public:
|
||||
QueryCallbackProcessor();
|
||||
~QueryCallbackProcessor();
|
||||
|
||||
void AddQuery(QueryCallback&& query);
|
||||
void ProcessReadyQueries();
|
||||
|
||||
private:
|
||||
QueryCallbackProcessor(QueryCallbackProcessor const&) = delete;
|
||||
QueryCallbackProcessor& operator=(QueryCallbackProcessor const&) = delete;
|
||||
|
||||
std::vector<QueryCallback> _callbacks;
|
||||
};
|
||||
|
||||
#endif // QueryCallbackProcessor_h__
|
||||
197
src/common/Database/QueryHolder.cpp
Normal file
197
src/common/Database/QueryHolder.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "MySQLConnection.h"
|
||||
#include "QueryHolder.h"
|
||||
#include "PreparedStatement.h"
|
||||
#include "Log.h"
|
||||
|
||||
bool SQLQueryHolder::SetQuery(size_t index, const char *sql)
|
||||
{
|
||||
if (m_queries.size() <= index)
|
||||
{
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "Query index (%u) out of range (size: %u) for query: %s", uint32(index), static_cast<uint32>(m_queries.size()), sql);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// not executed yet, just stored (it's not called a holder for nothing)
|
||||
SQLElementData element;
|
||||
element.type = SQL_ELEMENT_RAW;
|
||||
element.element.query = strdup(sql);
|
||||
|
||||
SQLResultSetUnion result;
|
||||
result.qresult = NULL;
|
||||
|
||||
m_queries[index] = SQLResultPair(element, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SQLQueryHolder::SetPreparedQuery(size_t index, PreparedStatement* stmt)
|
||||
{
|
||||
if (m_queries.size() <= index)
|
||||
{
|
||||
TC_LOG_ERROR(LOG_FILTER_SQL, "Query index (%u) out of range (size: %u) for prepared statement", index, static_cast<uint32>(m_queries.size()));
|
||||
return false;
|
||||
}
|
||||
|
||||
/// not executed yet, just stored (it's not called a holder for nothing)
|
||||
SQLElementData element;
|
||||
element.type = SQL_ELEMENT_PREPARED;
|
||||
element.element.stmt = stmt;
|
||||
|
||||
SQLResultSetUnion result;
|
||||
result.presult = NULL;
|
||||
|
||||
m_queries[index] = SQLResultPair(element, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
QueryResult SQLQueryHolder::GetResult(size_t index)
|
||||
{
|
||||
// Don't call to this function if the index is of an ad-hoc statement
|
||||
if (index < m_queries.size())
|
||||
{
|
||||
ResultSet* result = m_queries[index].second.qresult;
|
||||
if (!result || !result->GetRowCount())
|
||||
return QueryResult(NULL);
|
||||
|
||||
result->NextRow();
|
||||
return QueryResult(result);
|
||||
}
|
||||
else
|
||||
return QueryResult(NULL);
|
||||
}
|
||||
|
||||
PreparedQueryResult SQLQueryHolder::GetPreparedResult(size_t index)
|
||||
{
|
||||
// Don't call to this function if the index is of a prepared statement
|
||||
if (index < m_queries.size())
|
||||
{
|
||||
PreparedResultSet* result = m_queries[index].second.presult;
|
||||
if (!result || !result->GetRowCount())
|
||||
return PreparedQueryResult(NULL);
|
||||
|
||||
return PreparedQueryResult(result);
|
||||
}
|
||||
else
|
||||
return PreparedQueryResult(NULL);
|
||||
}
|
||||
|
||||
void SQLQueryHolder::SetResult(size_t index, ResultSet* result)
|
||||
{
|
||||
if (result && !result->GetRowCount())
|
||||
{
|
||||
delete result;
|
||||
result = NULL;
|
||||
}
|
||||
/// store the result in the holder
|
||||
if (index < m_queries.size())
|
||||
m_queries[index].second.qresult = result;
|
||||
}
|
||||
|
||||
void SQLQueryHolder::SetPreparedResult(size_t index, PreparedResultSet* result)
|
||||
{
|
||||
if (result && !result->GetRowCount())
|
||||
{
|
||||
delete result;
|
||||
result = NULL;
|
||||
}
|
||||
/// store the result in the holder
|
||||
if (index < m_queries.size())
|
||||
m_queries[index].second.presult = result;
|
||||
}
|
||||
|
||||
SQLQueryHolder::~SQLQueryHolder()
|
||||
{
|
||||
for (size_t i = 0; i < m_queries.size(); i++)
|
||||
{
|
||||
/// if the result was never used, free the resources
|
||||
/// results used already (getresult called) are expected to be deleted
|
||||
if (SQLElementData* data = &m_queries[i].first)
|
||||
{
|
||||
switch (data->type)
|
||||
{
|
||||
case SQL_ELEMENT_RAW:
|
||||
free((void*)(const_cast<char*>(data->element.query)));
|
||||
break;
|
||||
case SQL_ELEMENT_PREPARED:
|
||||
delete data->element.stmt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SQLQueryHolder::SetSize(size_t size)
|
||||
{
|
||||
/// to optimize push_back, reserve the number of queries about to be executed
|
||||
m_queries.resize(size);
|
||||
}
|
||||
|
||||
SQLQueryHolderTask::SQLQueryHolderTask(SQLQueryHolder* holder) : m_holder(holder), m_executed(false)
|
||||
{
|
||||
}
|
||||
|
||||
SQLQueryHolderTask::~SQLQueryHolderTask()
|
||||
{
|
||||
if (!m_executed)
|
||||
delete m_holder;
|
||||
}
|
||||
|
||||
bool SQLQueryHolderTask::Execute()
|
||||
{
|
||||
m_executed = true;
|
||||
|
||||
if (!m_holder)
|
||||
return false;
|
||||
|
||||
/// we can do this, we are friends
|
||||
std::vector<SQLQueryHolder::SQLResultPair> &queries = m_holder->m_queries;
|
||||
|
||||
for (size_t i = 0; i < queries.size(); i++)
|
||||
{
|
||||
/// execute all queries in the holder and pass the results
|
||||
if (SQLElementData* data = &queries[i].first)
|
||||
{
|
||||
switch (data->type)
|
||||
{
|
||||
case SQL_ELEMENT_RAW:
|
||||
{
|
||||
char const* sql = data->element.query;
|
||||
if (sql)
|
||||
m_holder->SetResult(i, m_conn->Query(sql));
|
||||
break;
|
||||
}
|
||||
case SQL_ELEMENT_PREPARED:
|
||||
{
|
||||
PreparedStatement* stmt = data->element.stmt;
|
||||
if (stmt)
|
||||
m_holder->SetPreparedResult(i, m_conn->Query(stmt));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_result.set_value(m_holder);
|
||||
return true;
|
||||
}
|
||||
|
||||
QueryResultHolderFuture SQLQueryHolderTask::GetFuture()
|
||||
{
|
||||
return m_result.get_future();
|
||||
}
|
||||
55
src/common/Database/QueryHolder.h
Normal file
55
src/common/Database/QueryHolder.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _QUERYHOLDER_H
|
||||
#define _QUERYHOLDER_H
|
||||
|
||||
#include "DatabaseEnvFwd.h"
|
||||
|
||||
class SQLQueryHolder
|
||||
{
|
||||
friend class SQLQueryHolderTask;
|
||||
typedef std::pair<SQLElementData, SQLResultSetUnion> SQLResultPair;
|
||||
std::vector<SQLResultPair> m_queries;
|
||||
public:
|
||||
SQLQueryHolder() {}
|
||||
~SQLQueryHolder();
|
||||
bool SetQuery(size_t index, const char *sql);
|
||||
bool SetPreparedQuery(size_t index, PreparedStatement* stmt);
|
||||
void SetSize(size_t size);
|
||||
QueryResult GetResult(size_t index);
|
||||
PreparedQueryResult GetPreparedResult(size_t index);
|
||||
void SetResult(size_t index, ResultSet* result);
|
||||
void SetPreparedResult(size_t index, PreparedResultSet* result);
|
||||
};
|
||||
|
||||
class SQLQueryHolderTask : public SQLOperation
|
||||
{
|
||||
SQLQueryHolder* m_holder;
|
||||
QueryResultHolderPromise m_result;
|
||||
bool m_executed;
|
||||
|
||||
public:
|
||||
SQLQueryHolderTask(SQLQueryHolder* holder);
|
||||
|
||||
~SQLQueryHolderTask();
|
||||
|
||||
bool Execute() override;
|
||||
QueryResultHolderFuture GetFuture();
|
||||
};
|
||||
|
||||
#endif
|
||||
271
src/common/Database/QueryResult.cpp
Normal file
271
src/common/Database/QueryResult.cpp
Normal file
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "DatabaseEnv.h"
|
||||
#include "Log.h"
|
||||
|
||||
ResultSet::ResultSet(MYSQL_RES *result, MYSQL_FIELD *fields, uint64 rowCount, uint32 fieldCount) :
|
||||
_rowCount(rowCount),
|
||||
_fieldCount(fieldCount),
|
||||
_result(result),
|
||||
_fields(fields)
|
||||
{
|
||||
_currentRow = new Field[_fieldCount];
|
||||
ASSERT(_currentRow);
|
||||
}
|
||||
|
||||
PreparedResultSet::PreparedResultSet(MYSQL_STMT* stmt, MYSQL_RES *result, uint64 rowCount, uint32 fieldCount) :
|
||||
m_rowCount(rowCount),
|
||||
m_rowPosition(0),
|
||||
m_fieldCount(fieldCount),
|
||||
m_rBind(NULL),
|
||||
m_stmt(stmt),
|
||||
m_res(result),
|
||||
m_isNull(NULL),
|
||||
m_length(NULL)
|
||||
{
|
||||
if (!m_res)
|
||||
return;
|
||||
|
||||
if (m_stmt->bind_result_done)
|
||||
{
|
||||
delete[] m_stmt->bind->length;
|
||||
delete[] m_stmt->bind->is_null;
|
||||
}
|
||||
|
||||
m_rBind = new MYSQL_BIND[m_fieldCount];
|
||||
m_isNull = new my_bool[m_fieldCount];
|
||||
m_length = new unsigned long[m_fieldCount];
|
||||
|
||||
memset(m_isNull, 0, sizeof(my_bool) * m_fieldCount);
|
||||
memset(m_rBind, 0, sizeof(MYSQL_BIND) * m_fieldCount);
|
||||
memset(m_length, 0, sizeof(unsigned long) * m_fieldCount);
|
||||
|
||||
//- This is where we store the (entire) resultset
|
||||
if (mysql_stmt_store_result(m_stmt))
|
||||
{
|
||||
TC_LOG_WARN(LOG_FILTER_SQL, "%s:mysql_stmt_store_result, cannot bind result from MySQL server. Error: %s", __FUNCTION__, mysql_stmt_error(m_stmt));
|
||||
return;
|
||||
}
|
||||
|
||||
//- This is where we prepare the buffer based on metadata
|
||||
uint32 i = 0;
|
||||
MYSQL_FIELD* field = mysql_fetch_field(m_res);
|
||||
while (field)
|
||||
{
|
||||
size_t size = Field::SizeForType(field);
|
||||
|
||||
m_rBind[i].buffer_type = field->type;
|
||||
m_rBind[i].buffer = malloc(size);
|
||||
memset(m_rBind[i].buffer, 0, size);
|
||||
m_rBind[i].buffer_length = size;
|
||||
m_rBind[i].length = &m_length[i];
|
||||
m_rBind[i].is_null = &m_isNull[i];
|
||||
m_rBind[i].error = NULL;
|
||||
m_rBind[i].is_unsigned = field->flags & UNSIGNED_FLAG;
|
||||
|
||||
++i;
|
||||
field = mysql_fetch_field(m_res);
|
||||
}
|
||||
|
||||
//- This is where we bind the bind the buffer to the statement
|
||||
if (mysql_stmt_bind_result(m_stmt, m_rBind))
|
||||
{
|
||||
TC_LOG_WARN(LOG_FILTER_SQL, "%s:mysql_stmt_bind_result, cannot bind result from MySQL server. Error: %s", __FUNCTION__, mysql_stmt_error(m_stmt));
|
||||
delete[] m_rBind;
|
||||
delete[] m_isNull;
|
||||
delete[] m_length;
|
||||
return;
|
||||
}
|
||||
|
||||
m_rowCount = mysql_stmt_num_rows(m_stmt);
|
||||
|
||||
m_rows.resize(uint32(m_rowCount));
|
||||
while (_NextRow())
|
||||
{
|
||||
m_rows[uint32(m_rowPosition)] = new Field[m_fieldCount];
|
||||
for (uint64 fIndex = 0; fIndex < m_fieldCount; ++fIndex)
|
||||
{
|
||||
if (!*m_rBind[fIndex].is_null)
|
||||
m_rows[uint32(m_rowPosition)][fIndex].SetByteValue(m_rBind[fIndex].buffer,
|
||||
m_rBind[fIndex].buffer_length,
|
||||
m_rBind[fIndex].buffer_type,
|
||||
*m_rBind[fIndex].length);
|
||||
else
|
||||
switch (m_rBind[fIndex].buffer_type)
|
||||
{
|
||||
case MYSQL_TYPE_TINY_BLOB:
|
||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
case MYSQL_TYPE_BLOB:
|
||||
case MYSQL_TYPE_STRING:
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
m_rows[uint32(m_rowPosition)][fIndex].SetByteValue("",
|
||||
m_rBind[fIndex].buffer_length,
|
||||
m_rBind[fIndex].buffer_type,
|
||||
*m_rBind[fIndex].length);
|
||||
break;
|
||||
default:
|
||||
m_rows[uint32(m_rowPosition)][fIndex].SetByteValue(0,
|
||||
m_rBind[fIndex].buffer_length,
|
||||
m_rBind[fIndex].buffer_type,
|
||||
*m_rBind[fIndex].length);
|
||||
}
|
||||
}
|
||||
m_rowPosition++;
|
||||
}
|
||||
m_rowPosition = 0;
|
||||
|
||||
/// All data is buffered, let go of mysql c api structures
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
ResultSet::~ResultSet()
|
||||
{
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
PreparedResultSet::~PreparedResultSet()
|
||||
{
|
||||
for (uint32 i = 0; i < uint32(m_rowCount); ++i)
|
||||
delete[] m_rows[i];
|
||||
}
|
||||
|
||||
bool ResultSet::NextRow()
|
||||
{
|
||||
if (!_result)
|
||||
return false;
|
||||
|
||||
MYSQL_ROW row = mysql_fetch_row(_result);
|
||||
if (!row)
|
||||
{
|
||||
CleanUp();
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned long* lengths = mysql_fetch_lengths(_result);
|
||||
if (!lengths)
|
||||
{
|
||||
TC_LOG_WARN(LOG_FILTER_SQL, "%s:mysql_fetch_lengths, cannot retrieve value lengths. Error %s.", __FUNCTION__, mysql_error(_result->handle));
|
||||
CleanUp();
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < _fieldCount; i++)
|
||||
_currentRow[i].SetStructuredValue(row[i], _fields[i].type, lengths[i]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64 ResultSet::GetRowCount() const
|
||||
{
|
||||
return _rowCount;
|
||||
}
|
||||
|
||||
uint32 ResultSet::GetFieldCount() const
|
||||
{
|
||||
return _fieldCount;
|
||||
}
|
||||
|
||||
Field* ResultSet::Fetch() const
|
||||
{
|
||||
return _currentRow;
|
||||
}
|
||||
|
||||
const Field& ResultSet::operator[](uint32 index) const
|
||||
{
|
||||
ASSERT(index < _fieldCount);
|
||||
return _currentRow[index];
|
||||
}
|
||||
|
||||
bool PreparedResultSet::NextRow()
|
||||
{
|
||||
/// Only updates the m_rowPosition so upper level code knows in which element
|
||||
/// of the rows vector to look
|
||||
if (++m_rowPosition >= m_rowCount)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64 PreparedResultSet::GetRowCount() const
|
||||
{
|
||||
return m_rowCount;
|
||||
}
|
||||
|
||||
uint32 PreparedResultSet::GetFieldCount() const
|
||||
{
|
||||
return m_fieldCount;
|
||||
}
|
||||
|
||||
Field* PreparedResultSet::Fetch() const
|
||||
{
|
||||
ASSERT(m_rowPosition < m_rowCount);
|
||||
return m_rows[uint32(m_rowPosition)];
|
||||
}
|
||||
|
||||
const Field& PreparedResultSet::operator[](uint32 index) const
|
||||
{
|
||||
ASSERT(m_rowPosition < m_rowCount);
|
||||
ASSERT(index < m_fieldCount);
|
||||
return m_rows[uint32(m_rowPosition)][index];
|
||||
}
|
||||
|
||||
bool PreparedResultSet::_NextRow()
|
||||
{
|
||||
/// Only called in low-level code, namely the constructor
|
||||
/// Will iterate over every row of data and buffer it
|
||||
if (m_rowPosition >= m_rowCount)
|
||||
return false;
|
||||
|
||||
int retval = mysql_stmt_fetch(m_stmt);
|
||||
return retval == 0 || retval == MYSQL_DATA_TRUNCATED;
|
||||
}
|
||||
|
||||
void ResultSet::CleanUp()
|
||||
{
|
||||
if (_currentRow)
|
||||
{
|
||||
delete[] _currentRow;
|
||||
_currentRow = NULL;
|
||||
}
|
||||
|
||||
if (_result)
|
||||
{
|
||||
mysql_free_result(_result);
|
||||
_result = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void PreparedResultSet::CleanUp()
|
||||
{
|
||||
/// More of the in our code allocated sources are deallocated by the poorly documented mysql c api
|
||||
if (m_res)
|
||||
mysql_free_result(m_res);
|
||||
|
||||
FreeBindBuffer();
|
||||
mysql_stmt_free_result(m_stmt);
|
||||
|
||||
delete[] m_rBind;
|
||||
}
|
||||
|
||||
void PreparedResultSet::FreeBindBuffer()
|
||||
{
|
||||
for (uint32 i = 0; i < m_fieldCount; ++i)
|
||||
free(m_rBind[i].buffer);
|
||||
}
|
||||
93
src/common/Database/QueryResult.h
Normal file
93
src/common/Database/QueryResult.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef QUERYRESULT_H
|
||||
#define QUERYRESULT_H
|
||||
|
||||
#include "Field.h"
|
||||
#include "DatabaseEnvFwd.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
#include <mysql.h>
|
||||
|
||||
class ResultSet
|
||||
{
|
||||
public:
|
||||
ResultSet(MYSQL_RES* result, MYSQL_FIELD* fields, uint64 rowCount, uint32 fieldCount);
|
||||
~ResultSet();
|
||||
|
||||
bool NextRow();
|
||||
uint64 GetRowCount() const;
|
||||
uint32 GetFieldCount() const;
|
||||
|
||||
Field* Fetch() const;
|
||||
|
||||
const Field& operator [](uint32 index) const;
|
||||
|
||||
protected:
|
||||
uint64 _rowCount;
|
||||
Field* _currentRow;
|
||||
uint32 _fieldCount;
|
||||
|
||||
private:
|
||||
void CleanUp();
|
||||
MYSQL_RES* _result;
|
||||
MYSQL_FIELD* _fields;
|
||||
|
||||
ResultSet(ResultSet const& right) = delete;
|
||||
ResultSet& operator=(ResultSet const& right) = delete;
|
||||
};
|
||||
|
||||
class PreparedResultSet
|
||||
{
|
||||
public:
|
||||
PreparedResultSet(MYSQL_STMT* stmt, MYSQL_RES* result, uint64 rowCount, uint32 fieldCount);
|
||||
~PreparedResultSet();
|
||||
|
||||
bool NextRow();
|
||||
uint64 GetRowCount() const;
|
||||
uint32 GetFieldCount() const;
|
||||
Field* Fetch() const;
|
||||
const Field& operator [](uint32 index) const;
|
||||
|
||||
protected:
|
||||
std::vector<Field*> m_rows;
|
||||
uint64 m_rowCount;
|
||||
uint64 m_rowPosition;
|
||||
uint32 m_fieldCount;
|
||||
|
||||
private:
|
||||
MYSQL_BIND* m_rBind;
|
||||
MYSQL_STMT* m_stmt;
|
||||
MYSQL_RES* m_res;
|
||||
|
||||
my_bool* m_isNull;
|
||||
unsigned long* m_length;
|
||||
|
||||
void FreeBindBuffer();
|
||||
void CleanUp();
|
||||
bool _NextRow();
|
||||
|
||||
PreparedResultSet(PreparedResultSet const& right) = delete;
|
||||
PreparedResultSet& operator=(PreparedResultSet const& right) = delete;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
77
src/common/Database/SQLOperation.h
Normal file
77
src/common/Database/SQLOperation.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SQLOPERATION_H
|
||||
#define _SQLOPERATION_H
|
||||
|
||||
#include "QueryResult.h"
|
||||
|
||||
//- Forward declare (don't include header to prevent circular includes)
|
||||
class PreparedStatement;
|
||||
|
||||
//- Union that holds element data
|
||||
union SQLElementUnion
|
||||
{
|
||||
PreparedStatement* stmt;
|
||||
const char* query;
|
||||
};
|
||||
|
||||
//- Type specifier of our element data
|
||||
enum SQLElementDataType
|
||||
{
|
||||
SQL_ELEMENT_RAW,
|
||||
SQL_ELEMENT_PREPARED,
|
||||
};
|
||||
|
||||
//- The element
|
||||
struct SQLElementData
|
||||
{
|
||||
SQLElementUnion element;
|
||||
SQLElementDataType type;
|
||||
};
|
||||
|
||||
//- For ambigious resultsets
|
||||
union SQLResultSetUnion
|
||||
{
|
||||
PreparedResultSet* presult;
|
||||
ResultSet* qresult;
|
||||
};
|
||||
|
||||
class MySQLConnection;
|
||||
|
||||
class SQLOperation
|
||||
{
|
||||
public:
|
||||
SQLOperation(): m_conn(NULL) { }
|
||||
virtual ~SQLOperation() { }
|
||||
|
||||
virtual int call()
|
||||
{
|
||||
Execute();
|
||||
return 0;
|
||||
}
|
||||
virtual bool Execute() = 0;
|
||||
virtual void SetConnection(MySQLConnection* con) { m_conn = con; }
|
||||
|
||||
MySQLConnection* m_conn;
|
||||
|
||||
private:
|
||||
SQLOperation(SQLOperation const& right) = delete;
|
||||
SQLOperation& operator=(SQLOperation const& right) = delete;
|
||||
};
|
||||
|
||||
#endif
|
||||
114
src/common/Database/Transaction.cpp
Normal file
114
src/common/Database/Transaction.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "DatabaseEnv.h"
|
||||
#include "Transaction.h"
|
||||
#include <mysqld_error.h>
|
||||
|
||||
//- Append a raw ad-hoc query to the transaction
|
||||
void Transaction::Append(const char* sql)
|
||||
{
|
||||
SQLElementData data;
|
||||
data.type = SQL_ELEMENT_RAW;
|
||||
data.element.query = strdup(sql);
|
||||
m_queries.push_back(data);
|
||||
}
|
||||
|
||||
size_t Transaction::GetSize() const
|
||||
{
|
||||
return m_queries.size();
|
||||
}
|
||||
|
||||
Transaction::Transaction(): _cleanedUp(false)
|
||||
{
|
||||
}
|
||||
|
||||
//- Append a prepared statement to the transaction
|
||||
Transaction::~Transaction()
|
||||
{
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void Transaction::Append(PreparedStatement* stmt)
|
||||
{
|
||||
SQLElementData data;
|
||||
data.type = SQL_ELEMENT_PREPARED;
|
||||
data.element.stmt = stmt;
|
||||
m_queries.push_back(data);
|
||||
}
|
||||
|
||||
void Transaction::Cleanup()
|
||||
{
|
||||
// This might be called by explicit calls to Cleanup or by the auto-destructor
|
||||
if (_cleanedUp)
|
||||
return;
|
||||
|
||||
while (!m_queries.empty())
|
||||
{
|
||||
SQLElementData const &data = m_queries.front();
|
||||
switch (data.type)
|
||||
{
|
||||
case SQL_ELEMENT_PREPARED:
|
||||
delete data.element.stmt;
|
||||
break;
|
||||
case SQL_ELEMENT_RAW:
|
||||
free((void*)(data.element.query));
|
||||
break;
|
||||
}
|
||||
|
||||
m_queries.pop_front();
|
||||
}
|
||||
|
||||
_cleanedUp = true;
|
||||
}
|
||||
|
||||
TransactionTask::TransactionTask(SQLTransaction trans, std::function<void()>&& callback): m_trans(trans), m_Callback(std::move(callback))
|
||||
{
|
||||
}
|
||||
|
||||
bool TransactionTask::Execute()
|
||||
{
|
||||
int errorCode = m_conn->ExecuteTransaction(m_trans);
|
||||
if (!errorCode)
|
||||
{
|
||||
m_Callback(); // Run lambda
|
||||
return true;
|
||||
}
|
||||
else if (errorCode == -1)
|
||||
{
|
||||
m_Callback(); // Run lambda again
|
||||
return true;
|
||||
}
|
||||
|
||||
if (errorCode == ER_LOCK_DEADLOCK)
|
||||
{
|
||||
uint8 loopBreaker = 5; // Handle MySQL Errno 1213 without extending deadlock to the core itself
|
||||
for (uint8 i = 0; i < loopBreaker; ++i)
|
||||
{
|
||||
if (!m_conn->ExecuteTransaction(m_trans))
|
||||
{
|
||||
m_Callback(); // Run lambda
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up now.
|
||||
m_trans->Cleanup();
|
||||
|
||||
return false;
|
||||
}
|
||||
74
src/common/Database/Transaction.h
Normal file
74
src/common/Database/Transaction.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _TRANSACTION_H
|
||||
#define _TRANSACTION_H
|
||||
|
||||
#include "SQLOperation.h"
|
||||
#include "DatabaseEnvFwd.h"
|
||||
#include "StringFormat.h"
|
||||
|
||||
class PreparedStatement;
|
||||
|
||||
class Transaction
|
||||
{
|
||||
friend class TransactionTask;
|
||||
friend class MySQLConnection;
|
||||
friend class DatabaseWokerPool;
|
||||
|
||||
template <typename T>
|
||||
friend class DatabaseWorkerPool;
|
||||
|
||||
public:
|
||||
Transaction();
|
||||
~Transaction();
|
||||
|
||||
void Append(PreparedStatement* statement);
|
||||
void Append(const char* sql);
|
||||
template<typename Format, typename... Args>
|
||||
void PAppend(Format&& sql, Args&&... args)
|
||||
{
|
||||
Append(Trinity::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str());
|
||||
}
|
||||
|
||||
size_t GetSize() const;
|
||||
|
||||
protected:
|
||||
void Cleanup();
|
||||
std::list<SQLElementData> m_queries;
|
||||
|
||||
private:
|
||||
bool _cleanedUp;
|
||||
};
|
||||
|
||||
class TransactionTask : public SQLOperation
|
||||
{
|
||||
template <class T> friend class DatabaseWorkerPool;
|
||||
friend class DatabaseWorker;
|
||||
|
||||
public:
|
||||
TransactionTask(SQLTransaction trans, std::function<void()>&& callback = []() -> void {});
|
||||
~TransactionTask() = default;
|
||||
|
||||
protected:
|
||||
bool Execute() override;
|
||||
|
||||
SQLTransaction m_trans;
|
||||
std::function<void()> m_Callback;
|
||||
};
|
||||
|
||||
#endif
|
||||
128
src/common/Debugging/Errors.cpp
Normal file
128
src/common/Debugging/Errors.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Errors.h"
|
||||
#include "Util.h"
|
||||
#include "Duration.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <thread>
|
||||
#include <cstdarg>
|
||||
|
||||
namespace Trinity {
|
||||
|
||||
void Assert(char const* file, int line, char const* function, char const* message)
|
||||
{
|
||||
fprintf(stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s\n",
|
||||
file, line, function, message);
|
||||
*((volatile int*)NULL) = 0;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void Assert(char const* file, int line, char const* function, char const* message, char const* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
fprintf(stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s ", file, line, function, message);
|
||||
vfprintf(stderr, format, args);
|
||||
fprintf(stderr, "\n");
|
||||
fflush(stderr);
|
||||
|
||||
va_end(args);
|
||||
*((volatile int*)NULL) = 0;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void Fatal(char const* file, int line, char const* function, char const* message, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, message);
|
||||
|
||||
fprintf(stderr, "\n%s:%i in %s FATAL ERROR:\n ", file, line, function);
|
||||
vfprintf(stderr, message, args);
|
||||
fprintf(stderr, "\n");
|
||||
fflush(stderr);
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::seconds(10));
|
||||
*((volatile int*)NULL) = 0;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void Error(char const* file, int line, char const* function, char const* message)
|
||||
{
|
||||
fprintf(stderr, "\n%s:%i in %s ERROR:\n %s\n",
|
||||
file, line, function, message);
|
||||
*((volatile int*)NULL) = 0;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void Warning(char const* file, int line, char const* function, char const* message)
|
||||
{
|
||||
fprintf(stderr, "\n%s:%i in %s WARNING:\n %s\n",
|
||||
file, line, function, message);
|
||||
}
|
||||
|
||||
void Abort(char const* file, int line, char const* function)
|
||||
{
|
||||
fprintf(stderr, "\n%s:%i in %s ABORTED.\n",
|
||||
file, line, function);
|
||||
*((volatile int*)NULL) = 0;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void AbortHandler(int signum)
|
||||
{
|
||||
if (m_worldCrashChecker) // Prevent double dump if crash already run
|
||||
{
|
||||
std::this_thread::sleep_for(Milliseconds(5000)); // Waiting when gdb is dump this thread
|
||||
signal(signum, SIG_DFL);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_worldCrashChecker = true;
|
||||
TC_LOG_ERROR(LOG_FILTER_WORLDSERVER, "AbortHandler m_worldCrashChecker %u", m_worldCrashChecker);
|
||||
|
||||
std::this_thread::sleep_for(Milliseconds(5000)); // Waiting for save and exit from work thread
|
||||
|
||||
signal(signum, SIG_DFL);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void DumpHandler(int signum)
|
||||
{
|
||||
if (m_worldCrashChecker) // Prevent double dump if crash already run
|
||||
{
|
||||
std::this_thread::sleep_for(Milliseconds(5000)); // Waiting when gdb is dump this thread
|
||||
signal(signum, SIG_DFL);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_worldCrashChecker = true;
|
||||
TC_LOG_ERROR(LOG_FILTER_WORLDSERVER, "DumpHandler m_worldCrashChecker %u", m_worldCrashChecker);
|
||||
|
||||
std::this_thread::sleep_for(Milliseconds(5000)); // Waiting for save and exit from work thread
|
||||
|
||||
signal(signum, SIG_DFL);
|
||||
exit(3);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Trinity
|
||||
68
src/common/Debugging/Errors.h
Normal file
68
src/common/Debugging/Errors.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TRINITYCORE_ERRORS_H
|
||||
#define TRINITYCORE_ERRORS_H
|
||||
|
||||
#include "Define.h"
|
||||
#include <atomic>
|
||||
|
||||
namespace Trinity
|
||||
{
|
||||
DECLSPEC_NORETURN void Assert(char const* file, int line, char const* function, char const* message) ATTR_NORETURN;
|
||||
DECLSPEC_NORETURN void Assert(char const* file, int line, char const* function, char const* message, char const* format, ...) ATTR_NORETURN ATTR_PRINTF(5, 6);
|
||||
|
||||
DECLSPEC_NORETURN void Fatal(char const* file, int line, char const* function, char const* message, ...) ATTR_NORETURN ATTR_PRINTF(4, 5);
|
||||
|
||||
DECLSPEC_NORETURN void Error(char const* file, int line, char const* function, char const* message) ATTR_NORETURN;
|
||||
|
||||
DECLSPEC_NORETURN void Abort(char const* file, int line, char const* function) ATTR_NORETURN;
|
||||
|
||||
void Warning(char const* file, int line, char const* function, char const* message);
|
||||
|
||||
DECLSPEC_NORETURN void AbortHandler(int sigval) ATTR_NORETURN;
|
||||
|
||||
DECLSPEC_NORETURN void DumpHandler(int signum) ATTR_NORETURN;
|
||||
|
||||
} // namespace Trinity
|
||||
|
||||
#if COMPILER == COMPILER_MICROSOFT
|
||||
#define ASSERT_BEGIN __pragma(warning(push)) __pragma(warning(disable: 4127))
|
||||
#define ASSERT_END __pragma(warning(pop))
|
||||
#else
|
||||
#define ASSERT_BEGIN
|
||||
#define ASSERT_END
|
||||
#endif
|
||||
|
||||
#define WPAssert(cond, ...) ASSERT_BEGIN do { if (!(cond)) Trinity::Assert(__FILE__, __LINE__, __FUNCTION__, #cond, ##__VA_ARGS__); } while(0) ASSERT_END
|
||||
#define WPFatal(cond, ...) ASSERT_BEGIN do { if (!(cond)) Trinity::Fatal(__FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); } while(0) ASSERT_END
|
||||
#define WPError(cond, msg) ASSERT_BEGIN do { if (!(cond)) Trinity::Error(__FILE__, __LINE__, __FUNCTION__, (msg)); } while(0) ASSERT_END
|
||||
#define WPWarning(cond, msg) ASSERT_BEGIN do { if (!(cond)) Trinity::Warning(__FILE__, __LINE__, __FUNCTION__, (msg)); } while(0) ASSERT_END
|
||||
#define WPAbort() ASSERT_BEGIN do { Trinity::Abort(__FILE__, __LINE__, __FUNCTION__); } while(0) ASSERT_END
|
||||
|
||||
#define ASSERT WPAssert
|
||||
#define ABORT WPAbort
|
||||
|
||||
template <typename T>
|
||||
T* ASSERT_NOTNULL(T* pointer)
|
||||
{
|
||||
ASSERT(pointer);
|
||||
return pointer;
|
||||
}
|
||||
|
||||
#endif
|
||||
1480
src/common/Debugging/WheatyExceptionReport.cpp
Normal file
1480
src/common/Debugging/WheatyExceptionReport.cpp
Normal file
File diff suppressed because it is too large
Load Diff
216
src/common/Debugging/WheatyExceptionReport.h
Normal file
216
src/common/Debugging/WheatyExceptionReport.h
Normal file
@@ -0,0 +1,216 @@
|
||||
#ifndef _WHEATYEXCEPTIONREPORT_
|
||||
#define _WHEATYEXCEPTIONREPORT_
|
||||
|
||||
#if PLATFORM == TC_PLATFORM_WINDOWS && !defined(__MINGW32__)
|
||||
|
||||
#include <winnt.h>
|
||||
#include <winternl.h>
|
||||
#include <dbghelp.h>
|
||||
#include <set>
|
||||
#include <stdlib.h>
|
||||
#include <stack>
|
||||
#include <mutex>
|
||||
#define countof _countof
|
||||
|
||||
#define WER_MAX_ARRAY_ELEMENTS_COUNT 10
|
||||
#define WER_MAX_NESTING_LEVEL 4
|
||||
#define WER_LARGE_BUFFER_SIZE 1024 * 128
|
||||
|
||||
enum BasicType // Stolen from CVCONST.H in the DIA 2.0 SDK
|
||||
{
|
||||
btNoType = 0,
|
||||
btVoid = 1,
|
||||
btChar = 2,
|
||||
btWChar = 3,
|
||||
btInt = 6,
|
||||
btUInt = 7,
|
||||
btFloat = 8,
|
||||
btBCD = 9,
|
||||
btBool = 10,
|
||||
btLong = 13,
|
||||
btULong = 14,
|
||||
btCurrency = 25,
|
||||
btDate = 26,
|
||||
btVariant = 27,
|
||||
btComplex = 28,
|
||||
btBit = 29,
|
||||
btBSTR = 30,
|
||||
btHresult = 31,
|
||||
|
||||
// Custom types
|
||||
btStdString = 101
|
||||
};
|
||||
|
||||
enum DataKind // Stolen from CVCONST.H in the DIA 2.0 SDK
|
||||
{
|
||||
DataIsUnknown,
|
||||
DataIsLocal,
|
||||
DataIsStaticLocal,
|
||||
DataIsParam,
|
||||
DataIsObjectPtr,
|
||||
DataIsFileStatic,
|
||||
DataIsGlobal,
|
||||
DataIsMember,
|
||||
DataIsStaticMember,
|
||||
DataIsConstant
|
||||
};
|
||||
|
||||
const char* const rgBaseType[] =
|
||||
{
|
||||
"<user defined>", // btNoType = 0,
|
||||
"void", // btVoid = 1,
|
||||
"char",//char* // btChar = 2,
|
||||
"wchar_t*", // btWChar = 3,
|
||||
"signed char",
|
||||
"unsigned char",
|
||||
"int", // btInt = 6,
|
||||
"unsigned int", // btUInt = 7,
|
||||
"float", // btFloat = 8,
|
||||
"<BCD>", // btBCD = 9,
|
||||
"bool", // btBool = 10,
|
||||
"short",
|
||||
"unsigned short",
|
||||
"long", // btLong = 13,
|
||||
"unsigned long", // btULong = 14,
|
||||
"int8",
|
||||
"int16",
|
||||
"int32",
|
||||
"int64",
|
||||
"int128",
|
||||
"uint8",
|
||||
"uint16",
|
||||
"uint32",
|
||||
"uint64",
|
||||
"uint128",
|
||||
"<currency>", // btCurrency = 25,
|
||||
"<date>", // btDate = 26,
|
||||
"VARIANT", // btVariant = 27,
|
||||
"<complex>", // btComplex = 28,
|
||||
"<bit>", // btBit = 29,
|
||||
"BSTR", // btBSTR = 30,
|
||||
"HRESULT" // btHresult = 31
|
||||
};
|
||||
|
||||
struct SymbolPair
|
||||
{
|
||||
SymbolPair(DWORD type, DWORD_PTR offset)
|
||||
{
|
||||
_type = type;
|
||||
_offset = offset;
|
||||
}
|
||||
|
||||
bool operator<(const SymbolPair& other) const
|
||||
{
|
||||
return _offset < other._offset ||
|
||||
(_offset == other._offset && _type < other._type);
|
||||
}
|
||||
|
||||
DWORD _type;
|
||||
DWORD_PTR _offset;
|
||||
};
|
||||
typedef std::set<SymbolPair> SymbolPairs;
|
||||
|
||||
struct SymbolDetail
|
||||
{
|
||||
SymbolDetail() : Prefix(), Type(), Suffix(), Name(), Value(), Logged(false), HasChildren(false) {}
|
||||
|
||||
std::string ToString()
|
||||
{
|
||||
Logged = true;
|
||||
std::string formatted = Prefix + Type + Suffix;
|
||||
if (!Name.empty())
|
||||
{
|
||||
if (!formatted.empty())
|
||||
formatted += " ";
|
||||
formatted += Name;
|
||||
}
|
||||
if (!Value.empty())
|
||||
formatted += " = " + Value;
|
||||
return formatted;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return Value.empty() && !HasChildren;
|
||||
}
|
||||
|
||||
std::string Prefix;
|
||||
std::string Type;
|
||||
std::string Suffix;
|
||||
std::string Name;
|
||||
std::string Value;
|
||||
bool Logged;
|
||||
bool HasChildren;
|
||||
};
|
||||
|
||||
class WheatyExceptionReport
|
||||
{
|
||||
public:
|
||||
|
||||
WheatyExceptionReport();
|
||||
~WheatyExceptionReport();
|
||||
|
||||
// entry point where control comes on an unhandled exception
|
||||
static LONG WINAPI WheatyUnhandledExceptionFilter(
|
||||
PEXCEPTION_POINTERS pExceptionInfo);
|
||||
|
||||
static void __cdecl WheatyCrtHandler(wchar_t const* expression, wchar_t const* function, wchar_t const* file, unsigned int line, uintptr_t pReserved);
|
||||
|
||||
static void printTracesForAllThreads(bool);
|
||||
private:
|
||||
// where report info is extracted and generated
|
||||
static void GenerateExceptionReport(PEXCEPTION_POINTERS pExceptionInfo);
|
||||
static void PrintSystemInfo();
|
||||
static BOOL _GetWindowsVersion(TCHAR* szVersion, DWORD cntMax);
|
||||
static BOOL _GetProcessorName(TCHAR* sProcessorName, DWORD maxcount);
|
||||
|
||||
// Helper functions
|
||||
static LPTSTR GetExceptionString(DWORD dwCode);
|
||||
static BOOL GetLogicalAddress(PVOID addr, PTSTR szModule, DWORD len,
|
||||
DWORD& section, DWORD_PTR& offset);
|
||||
|
||||
static void WriteStackDetails(PCONTEXT pContext, bool bWriteVariables, HANDLE pThreadHandle);
|
||||
|
||||
static BOOL CALLBACK EnumerateSymbolsCallback(PSYMBOL_INFO, ULONG, PVOID);
|
||||
|
||||
static bool FormatSymbolValue(PSYMBOL_INFO, STACKFRAME64 *, char * pszBuffer, unsigned cbBuffer);
|
||||
|
||||
static char * DumpTypeIndex(char *, DWORD64, DWORD, DWORD_PTR, bool &, const char*, char*, bool, bool);
|
||||
|
||||
static void FormatOutputValue(char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress, size_t bufferSize, size_t countOverride = 0);
|
||||
|
||||
static BasicType GetBasicType(DWORD typeIndex, DWORD64 modBase);
|
||||
static DWORD_PTR DereferenceUnsafePointer(DWORD_PTR address);
|
||||
|
||||
static int __cdecl _tprintf(const TCHAR * format, ...);
|
||||
static int __cdecl stackprintf(const TCHAR * format, va_list argptr);
|
||||
static int __cdecl heapprintf(const TCHAR * format, va_list argptr);
|
||||
|
||||
static bool StoreSymbol(DWORD type , DWORD_PTR offset);
|
||||
static void ClearSymbols();
|
||||
|
||||
// Variables used by the class
|
||||
static TCHAR m_szLogFileName[MAX_PATH];
|
||||
static TCHAR m_szDumpFileName[MAX_PATH];
|
||||
static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter;
|
||||
static _invalid_parameter_handler m_previousCrtHandler;
|
||||
static HANDLE m_hReportFile;
|
||||
static HANDLE m_hDumpFile;
|
||||
static HANDLE m_hProcess;
|
||||
static SymbolPairs symbols;
|
||||
static std::stack<SymbolDetail> symbolDetails;
|
||||
static bool stackOverflowException;
|
||||
static bool alreadyCrashed;
|
||||
static std::mutex alreadyCrashedLock;
|
||||
typedef NTSTATUS(NTAPI* pRtlGetVersion)(PRTL_OSVERSIONINFOW lpVersionInformation);
|
||||
static pRtlGetVersion RtlGetVersion;
|
||||
|
||||
static char* PushSymbolDetail(char* pszCurrBuffer);
|
||||
static char* PopSymbolDetail(char* pszCurrBuffer);
|
||||
static char* PrintSymbolDetail(char* pszCurrBuffer);
|
||||
|
||||
};
|
||||
|
||||
extern WheatyExceptionReport g_WheatyExceptionReport; // global instance of class
|
||||
#endif // _WIN32
|
||||
#endif // _WHEATYEXCEPTIONREPORT_
|
||||
107
src/common/Define.h
Normal file
107
src/common/Define.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TRINITY_DEFINE_H
|
||||
#define TRINITY_DEFINE_H
|
||||
|
||||
#include "CompilerDefs.h"
|
||||
|
||||
#if COMPILER == COMPILER_GNU
|
||||
# if !defined(__STDC_FORMAT_MACROS)
|
||||
# define __STDC_FORMAT_MACROS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
#include <cinttypes>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <mutex>
|
||||
|
||||
#define TRINITY_LITTLEENDIAN 0
|
||||
#define TRINITY_BIGENDIAN 1
|
||||
|
||||
#if !defined(TRINITY_ENDIAN)
|
||||
# if defined (BOOST_BIG_ENDIAN)
|
||||
# define TRINITY_ENDIAN TRINITY_BIGENDIAN
|
||||
# else
|
||||
# define TRINITY_ENDIAN TRINITY_LITTLEENDIAN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if PLATFORM == TC_PLATFORM_WINDOWS
|
||||
# ifndef DECLSPEC_NORETURN
|
||||
# define DECLSPEC_NORETURN __declspec(noreturn)
|
||||
# endif //DECLSPEC_NORETURN
|
||||
# ifndef DECLSPEC_DEPRECATED
|
||||
# define DECLSPEC_DEPRECATED __declspec(deprecated)
|
||||
# endif //DECLSPEC_DEPRECATED
|
||||
#else //PLATFORM != TC_PLATFORM_WINDOWS
|
||||
# define DECLSPEC_NORETURN
|
||||
# define DECLSPEC_DEPRECATED
|
||||
#endif //PLATFORM
|
||||
|
||||
#if !defined(COREDEBUG)
|
||||
# define TRINITY_INLINE inline
|
||||
#else //COREDEBUG
|
||||
# if !defined(TRINITY_DEBUG)
|
||||
# define TRINITY_DEBUG
|
||||
# endif //TRINITY_DEBUG
|
||||
# define TRINITY_INLINE
|
||||
#endif //!COREDEBUG
|
||||
|
||||
#if COMPILER == COMPILER_GNU
|
||||
# define ATTR_NORETURN __attribute__((noreturn))
|
||||
# define ATTR_PRINTF(F, V) __attribute__ ((format (printf, F, V)))
|
||||
# define ATTR_DEPRECATED __attribute__((deprecated))
|
||||
#else //COMPILER != COMPILER_GNU
|
||||
# define ATTR_NORETURN
|
||||
# define ATTR_PRINTF(F, V)
|
||||
# define ATTR_DEPRECATED
|
||||
#endif //COMPILER == COMPILER_GNU
|
||||
|
||||
#define UI64FMTD "%" PRIu64
|
||||
#define UI64FMTDX "%" PRIx64
|
||||
#define UI64LIT(N) UINT64_C(N)
|
||||
|
||||
#define SI64FMTD "%" PRId64
|
||||
#define SZFMTD "%" PRIuPTR
|
||||
|
||||
#define SI64LIT(N) INT64_C(N)
|
||||
|
||||
typedef int64_t int64;
|
||||
typedef int32_t int32;
|
||||
typedef int16_t int16;
|
||||
typedef int8_t int8;
|
||||
typedef uint64_t uint64;
|
||||
typedef uint32_t uint32;
|
||||
typedef uint16_t uint16;
|
||||
typedef uint8_t uint8;
|
||||
|
||||
enum DBCFormer
|
||||
{
|
||||
FT_STRING = 's', // LocalizedString*
|
||||
FT_STRING_NOT_LOCALIZED = 'S', // char*
|
||||
FT_FLOAT = 'f', // float
|
||||
FT_INT = 'i', // uint32
|
||||
FT_BYTE = 'b', // uint8
|
||||
FT_SHORT = 'h', // uint16
|
||||
FT_LONG = 'l' // uint64
|
||||
};
|
||||
|
||||
#endif //TRINITY_DEFINE_H
|
||||
82
src/common/GitRevision.cpp
Normal file
82
src/common/GitRevision.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
#include "GitRevision.h"
|
||||
#include "revision_data.h"
|
||||
|
||||
char const* GitRevision::GetHash()
|
||||
{
|
||||
return _HASH;
|
||||
}
|
||||
|
||||
char const* GitRevision::GetDate()
|
||||
{
|
||||
return _DATE;
|
||||
}
|
||||
|
||||
char const* GitRevision::GetBranch()
|
||||
{
|
||||
return _BRANCH;
|
||||
}
|
||||
|
||||
char const* GitRevision::GetCMakeCommand()
|
||||
{
|
||||
return _CMAKE_COMMAND;
|
||||
}
|
||||
|
||||
char const* GitRevision::GetBuildDirectory()
|
||||
{
|
||||
return _BUILD_DIRECTORY;
|
||||
}
|
||||
|
||||
char const* GitRevision::GetSourceDirectory()
|
||||
{
|
||||
return _SOURCE_DIRECTORY;
|
||||
}
|
||||
|
||||
char const* GitRevision::GetMySQLExecutable()
|
||||
{
|
||||
return _MYSQL_EXECUTABLE;
|
||||
}
|
||||
|
||||
char const* GitRevision::GetFullDatabase()
|
||||
{
|
||||
return _FULL_DATABASE;
|
||||
}
|
||||
|
||||
char const* GitRevision::GetHotfixesDatabase()
|
||||
{
|
||||
return _HOTFIXES_DATABASE;
|
||||
}
|
||||
|
||||
#define _PACKAGENAME "TrinityCore"
|
||||
|
||||
char const* GitRevision::GetFullVersion()
|
||||
{
|
||||
#if PLATFORM == TC_PLATFORM_WINDOWS
|
||||
# ifdef _WIN64
|
||||
return VER_PRODUCTVERSION_STR " (Win64, " _BUILD_DIRECTIVE ")";
|
||||
# else
|
||||
return VER_PRODUCTVERSION_STR " (Win32, " _BUILD_DIRECTIVE ")";
|
||||
# endif
|
||||
#else
|
||||
return VER_PRODUCTVERSION_STR " (Unix, " _BUILD_DIRECTIVE ")";
|
||||
#endif
|
||||
}
|
||||
|
||||
char const* GitRevision::GetCompanyNameStr()
|
||||
{
|
||||
return VER_COMPANYNAME_STR;
|
||||
}
|
||||
|
||||
char const* GitRevision::GetLegalCopyrightStr()
|
||||
{
|
||||
return VER_LEGALCOPYRIGHT_STR;
|
||||
}
|
||||
|
||||
char const* GitRevision::GetFileVersionStr()
|
||||
{
|
||||
return VER_FILEVERSION_STR;
|
||||
}
|
||||
|
||||
char const* GitRevision::GetProductVersionStr()
|
||||
{
|
||||
return VER_PRODUCTVERSION_STR;
|
||||
}
|
||||
42
src/common/GitRevision.h
Normal file
42
src/common/GitRevision.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GITREVISION_H__
|
||||
#define __GITREVISION_H__
|
||||
|
||||
#include <string>
|
||||
#include "Define.h"
|
||||
|
||||
namespace GitRevision
|
||||
{
|
||||
char const* GetHash();
|
||||
char const* GetDate();
|
||||
char const* GetBranch();
|
||||
char const* GetCMakeCommand();
|
||||
char const* GetBuildDirectory();
|
||||
char const* GetSourceDirectory();
|
||||
char const* GetMySQLExecutable();
|
||||
char const* GetFullDatabase();
|
||||
char const* GetHotfixesDatabase();
|
||||
char const* GetFullVersion();
|
||||
char const* GetCompanyNameStr();
|
||||
char const* GetLegalCopyrightStr();
|
||||
char const* GetFileVersionStr();
|
||||
char const* GetProductVersionStr();
|
||||
}
|
||||
|
||||
#endif
|
||||
238
src/common/Logging/Appender.cpp
Normal file
238
src/common/Logging/Appender.cpp
Normal file
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Appender.h"
|
||||
#include <utility>
|
||||
#include "Common.h"
|
||||
#include "Util.h"
|
||||
|
||||
LogMessage::LogMessage(LogLevel _level, LogFilterType _type, std::string&& _text) : level(_level), type(_type), text(std::forward<std::string>(_text))
|
||||
{
|
||||
mtime = time(nullptr);
|
||||
}
|
||||
|
||||
std::string LogMessage::getTimeStr(time_t time)
|
||||
{
|
||||
tm aTm;
|
||||
localtime_r(&time, &aTm);
|
||||
char buf[20];
|
||||
snprintf(buf, 20, "%04d-%02d-%02d_%02d:%02d:%02d", aTm.tm_year + 1900, aTm.tm_mon + 1, aTm.tm_mday, aTm.tm_hour, aTm.tm_min, aTm.tm_sec);
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
std::string LogMessage::getTimeStr()
|
||||
{
|
||||
return getTimeStr(mtime);
|
||||
}
|
||||
|
||||
Appender::Appender(uint8 _id, std::string _name, AppenderType _type /* = APPENDER_NONE*/, LogLevel _level /* = LOG_LEVEL_DISABLED */, AppenderFlags _flags /* = APPENDER_FLAGS_NONE */) :
|
||||
id(_id), name(std::move(_name)), type(_type), level(_level), flags(_flags)
|
||||
{
|
||||
}
|
||||
|
||||
Appender::~Appender() = default;
|
||||
|
||||
uint8 Appender::getId() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
std::string const& Appender::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
AppenderType Appender::getType() const
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
LogLevel Appender::getLogLevel() const
|
||||
{
|
||||
return level;
|
||||
}
|
||||
|
||||
AppenderFlags Appender::getFlags() const
|
||||
{
|
||||
return flags;
|
||||
}
|
||||
|
||||
void Appender::setLogLevel(LogLevel _level)
|
||||
{
|
||||
level = _level;
|
||||
}
|
||||
|
||||
void Appender::write(LogMessage* message)
|
||||
{
|
||||
if (!level || level > message->level)
|
||||
{
|
||||
//fprintf(stderr, "Appender::write: Appender %s, Level %s. Msg %s Level %s Type %s WRONG LEVEL MASK\n", getName().c_str(), getLogLevelString(level), message->text.c_str(), getLogLevelString(message->level), getLogFilterTypeString(message->type)); // DEBUG - RemoveMe
|
||||
return;
|
||||
}
|
||||
|
||||
message->prefix.clear();
|
||||
if (flags & APPENDER_FLAGS_PREFIX_TIMESTAMP)
|
||||
message->prefix.append(message->getTimeStr());
|
||||
|
||||
if (flags & APPENDER_FLAGS_PREFIX_LOGLEVEL)
|
||||
{
|
||||
if (!message->prefix.empty())
|
||||
message->prefix.push_back(' ');
|
||||
|
||||
char text[MAX_QUERY_LEN];
|
||||
snprintf(text, MAX_QUERY_LEN, "%-5s", getLogLevelString(message->level));
|
||||
message->prefix.append(text);
|
||||
}
|
||||
|
||||
if (flags & APPENDER_FLAGS_PREFIX_LOGFILTERTYPE)
|
||||
{
|
||||
if (!message->prefix.empty())
|
||||
message->prefix.push_back(' ');
|
||||
|
||||
char text[MAX_QUERY_LEN];
|
||||
snprintf(text, MAX_QUERY_LEN, "[%s]", getLogFilterTypeString(message->type));
|
||||
message->prefix.append(text);
|
||||
}
|
||||
|
||||
if (!message->prefix.empty())
|
||||
message->prefix.push_back(' ');
|
||||
|
||||
_write(message);
|
||||
}
|
||||
|
||||
const char* Appender::getLogLevelString(LogLevel level)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case LOG_LEVEL_FATAL:
|
||||
return "FATAL";
|
||||
case LOG_LEVEL_ERROR:
|
||||
return "ERROR";
|
||||
case LOG_LEVEL_WARN:
|
||||
return "WARN";
|
||||
case LOG_LEVEL_INFO:
|
||||
return "INFO";
|
||||
case LOG_LEVEL_DEBUG:
|
||||
return "DEBUG";
|
||||
case LOG_LEVEL_TRACE:
|
||||
return "TRACE";
|
||||
default:
|
||||
return "DISABLED";
|
||||
}
|
||||
}
|
||||
|
||||
char const* Appender::getLogFilterTypeString(LogFilterType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case LOG_FILTER_GENERAL:
|
||||
return "GENERAL";
|
||||
case LOG_FILTER_UNITS:
|
||||
return "UNITS";
|
||||
case LOG_FILTER_PETS:
|
||||
return "PETS";
|
||||
case LOG_FILTER_VEHICLES:
|
||||
return "VEHICLES";
|
||||
case LOG_FILTER_TSCR:
|
||||
return "TSCR";
|
||||
case LOG_FILTER_DATABASE_AI:
|
||||
return "DATABASE_AI";
|
||||
case LOG_FILTER_MAPSCRIPTS:
|
||||
return "MAPSCRIPTS";
|
||||
case LOG_FILTER_NETWORKIO:
|
||||
return "NETWORKIO";
|
||||
case LOG_FILTER_SPELLS_AURAS:
|
||||
return "SPELLS_AURAS";
|
||||
case LOG_FILTER_ACHIEVEMENTSYS:
|
||||
return "ACHIEVEMENTSYS";
|
||||
case LOG_FILTER_CONDITIONSYS:
|
||||
return "CONDITIONSYS";
|
||||
case LOG_FILTER_POOLSYS:
|
||||
return "POOLSYS";
|
||||
case LOG_FILTER_AUCTIONHOUSE:
|
||||
return "AUCTIONHOUSE";
|
||||
case LOG_FILTER_BATTLEGROUND:
|
||||
return "BATTLEGROUND";
|
||||
case LOG_FILTER_OUTDOORPVP:
|
||||
return "OUTDOORPVP";
|
||||
case LOG_FILTER_CHATSYS:
|
||||
return "CHATSYS";
|
||||
case LOG_FILTER_LFG:
|
||||
return "LFG";
|
||||
case LOG_FILTER_MAPS:
|
||||
return "MAPS";
|
||||
case LOG_FILTER_PLAYER:
|
||||
return "PLAYER";
|
||||
case LOG_FILTER_PLAYER_LOADING:
|
||||
return "PLAYER LOADING";
|
||||
case LOG_FILTER_PLAYER_ITEMS:
|
||||
return "PLAYER ITEMS";
|
||||
case LOG_FILTER_PLAYER_SKILLS:
|
||||
return "PLAYER SKILLS";
|
||||
case LOG_FILTER_PLAYER_CHATLOG:
|
||||
return "PLAYER CHATLOG";
|
||||
case LOG_FILTER_LOOT:
|
||||
return "LOOT";
|
||||
case LOG_FILTER_GUILD:
|
||||
return "GUILD";
|
||||
case LOG_FILTER_TRANSPORTS:
|
||||
return "TRANSPORTS";
|
||||
case LOG_FILTER_SQL:
|
||||
return "SQL";
|
||||
case LOG_FILTER_GMCOMMAND:
|
||||
return "GMCOMMAND";
|
||||
case LOG_FILTER_REMOTECOMMAND:
|
||||
return "REMOTECOMMAND";
|
||||
case LOG_FILTER_WARDEN:
|
||||
return "WARDEN";
|
||||
case LOG_FILTER_WORLDSERVER:
|
||||
return "WORLDSERVER";
|
||||
case LOG_FILTER_GAMEEVENTS:
|
||||
return "GAMEEVENTS";
|
||||
case LOG_FILTER_CALENDAR:
|
||||
return "CALENDAR";
|
||||
case LOG_FILTER_CHARACTER:
|
||||
return "CHARACTER";
|
||||
case LOG_FILTER_SQL_DRIVER:
|
||||
return "SQL DRIVER";
|
||||
case LOG_FILTER_SQL_DEV:
|
||||
return "SQL DEV";
|
||||
case LOG_FILTER_PLAYER_DUMP:
|
||||
return "PLAYER DUMP";
|
||||
case LOG_FILTER_BATTLEFIELD:
|
||||
return "BATTLEFIELD";
|
||||
case LOG_FILTER_SERVER_LOADING:
|
||||
return "SERVER LOADING";
|
||||
case LOG_FILTER_OPCODES:
|
||||
return "OPCODE";
|
||||
case LOG_FILTER_BATTLENET:
|
||||
return "BATTLENET";
|
||||
case LOG_FILTER_BNET_SESSION:
|
||||
return "BNET_SESSION";
|
||||
case LOG_FILTER_AREATRIGGER:
|
||||
return "AREATRIGGER";
|
||||
case LOG_FILTER_GOLD:
|
||||
return "GOLD";
|
||||
case LOG_FILTER_WORLD_QUEST:
|
||||
return "WORLD_QUEST";
|
||||
case LOG_FILTER_CHALLENGE:
|
||||
return "CHALLENGE";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "???";
|
||||
}
|
||||
132
src/common/Logging/Appender.h
Normal file
132
src/common/Logging/Appender.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef APPENDER_H
|
||||
#define APPENDER_H
|
||||
|
||||
#include "Define.h"
|
||||
#include "LogCommon.h"
|
||||
#include <time.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
enum LogFilterType
|
||||
{
|
||||
LOG_FILTER_GENERAL = 0, //bnet world // This one should only be used inside Log.cpp
|
||||
LOG_FILTER_UNITS = 1, //world // Anything related to units that doesn't fit in other categories. ie. creature formations
|
||||
LOG_FILTER_PETS = 2, //world
|
||||
LOG_FILTER_VEHICLES = 3, //world
|
||||
LOG_FILTER_TSCR = 4, //world // C++ AI, instance scripts, etc.
|
||||
LOG_FILTER_DATABASE_AI = 5, //world // SmartAI, Creature* * AI
|
||||
LOG_FILTER_MAPSCRIPTS = 6, //world
|
||||
LOG_FILTER_NETWORKIO = 7, //bnet world
|
||||
LOG_FILTER_SPELLS_AURAS = 8, //world
|
||||
LOG_FILTER_ACHIEVEMENTSYS = 9, //world
|
||||
LOG_FILTER_CONDITIONSYS = 10, //world
|
||||
LOG_FILTER_POOLSYS = 11, //world
|
||||
LOG_FILTER_AUCTIONHOUSE = 12, //world
|
||||
LOG_FILTER_BATTLEGROUND = 13, //world
|
||||
LOG_FILTER_OUTDOORPVP = 14, //world
|
||||
LOG_FILTER_CHATSYS = 15, //world
|
||||
LOG_FILTER_LFG = 16, //world
|
||||
LOG_FILTER_MAPS = 17, //world
|
||||
LOG_FILTER_PLAYER = 18, //world // Any player log that does not fit in other player filters
|
||||
LOG_FILTER_PLAYER_LOADING = 19, //world // Debug output from Player::_Load functions
|
||||
LOG_FILTER_PLAYER_ITEMS = 20, //world
|
||||
LOG_FILTER_PLAYER_SKILLS = 21, //world
|
||||
LOG_FILTER_PLAYER_CHATLOG = 22, //world
|
||||
LOG_FILTER_LOOT = 23, //world
|
||||
LOG_FILTER_GUILD = 24, //world
|
||||
LOG_FILTER_TRANSPORTS = 25, //world
|
||||
LOG_FILTER_SQL = 26, //bnet world
|
||||
LOG_FILTER_GMCOMMAND = 27, //world
|
||||
LOG_FILTER_REMOTECOMMAND = 28, //world
|
||||
LOG_FILTER_WARDEN = 29, //world
|
||||
LOG_FILTER_WORLDSERVER = 31, //world
|
||||
LOG_FILTER_GAMEEVENTS = 32, //world
|
||||
LOG_FILTER_CALENDAR = 33, //world
|
||||
LOG_FILTER_CHARACTER = 34, //world
|
||||
LOG_FILTER_SQL_DRIVER = 36, //bnet world
|
||||
LOG_FILTER_SQL_DEV = 37, //bnet world
|
||||
LOG_FILTER_PLAYER_DUMP = 38, //world
|
||||
LOG_FILTER_BATTLEFIELD = 39, //world
|
||||
LOG_FILTER_SERVER_LOADING = 40, //world
|
||||
LOG_FILTER_OPCODES = 41, //world
|
||||
LOG_FILTER_REALMLIST = 44, //bnet
|
||||
LOG_FILTER_BATTLENET = 45, //bnet
|
||||
LOG_FILTER_BNET_SESSION = 47, //bnet
|
||||
LOG_FILTER_PROC = 48, //world
|
||||
LOG_FILTER_DONATE = 50, //world
|
||||
LOG_FILTER_BATTLEPET = 51, //world
|
||||
LOG_FILTER_PROTOBUF = 52, //world
|
||||
LOG_FILTER_AREATRIGGER = 53, //world
|
||||
LOG_FILTER_GOLD = 54, //world
|
||||
LOG_FILTER_WORLD_QUEST = 55, //world
|
||||
LOG_FILTER_CHALLENGE = 56, //world
|
||||
LOG_FILTER_PATH_GENERATOR = 58, //world
|
||||
LOG_FILTER_MMAPS = 59, //world
|
||||
LOG_FILTER_VMAPS = 60, //world
|
||||
|
||||
LOG_FILTER_MAX
|
||||
};
|
||||
|
||||
struct LogMessage
|
||||
{
|
||||
LogMessage(LogLevel _level, LogFilterType _type, std::string&& _text);
|
||||
|
||||
LogMessage(LogMessage const& /*other*/) = delete;
|
||||
LogMessage& operator=(LogMessage const& /*other*/) = delete;
|
||||
|
||||
static std::string getTimeStr(time_t time);
|
||||
std::string getTimeStr();
|
||||
|
||||
LogLevel level;
|
||||
LogFilterType type;
|
||||
std::string text;
|
||||
std::string prefix;
|
||||
std::string param1;
|
||||
time_t mtime;
|
||||
};
|
||||
|
||||
class Appender
|
||||
{
|
||||
public:
|
||||
Appender(uint8 _id, std::string name, AppenderType type = APPENDER_NONE, LogLevel level = LOG_LEVEL_DISABLED, AppenderFlags flags = APPENDER_FLAGS_NONE);
|
||||
virtual ~Appender();
|
||||
|
||||
uint8 getId() const;
|
||||
std::string const& getName() const;
|
||||
AppenderType getType() const;
|
||||
LogLevel getLogLevel() const;
|
||||
AppenderFlags getFlags() const;
|
||||
|
||||
void setLogLevel(LogLevel);
|
||||
void write(LogMessage* message);
|
||||
static const char* getLogLevelString(LogLevel level);
|
||||
static const char* getLogFilterTypeString(LogFilterType type);
|
||||
|
||||
private:
|
||||
virtual void _write(LogMessage const* /*message*/) = 0;
|
||||
|
||||
uint8 id;
|
||||
std::string name;
|
||||
AppenderType type;
|
||||
LogLevel level;
|
||||
AppenderFlags flags;
|
||||
};
|
||||
|
||||
#endif
|
||||
196
src/common/Logging/AppenderConsole.cpp
Normal file
196
src/common/Logging/AppenderConsole.cpp
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <sstream>
|
||||
#if PLATFORM == TC_PLATFORM_WINDOWS
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "AppenderConsole.h"
|
||||
#include "Config.h"
|
||||
#include "Util.h"
|
||||
|
||||
|
||||
AppenderConsole::AppenderConsole(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags) :
|
||||
Appender(id, name, APPENDER_CONSOLE, level, flags), _colored(false)
|
||||
{
|
||||
for (auto & _color : _colors)
|
||||
_color = ColorTypes(MaxColors);
|
||||
}
|
||||
|
||||
void AppenderConsole::InitColors(std::string const& str)
|
||||
{
|
||||
if (str.empty())
|
||||
{
|
||||
_colored = false;
|
||||
return;
|
||||
}
|
||||
|
||||
int color[NUM_ENABLED_LOG_LEVELS];
|
||||
|
||||
std::istringstream ss(str);
|
||||
|
||||
for (auto& i : color)
|
||||
{
|
||||
ss >> i;
|
||||
|
||||
if (!ss)
|
||||
return;
|
||||
|
||||
if (i < 0 || i >= MaxColors)
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i)
|
||||
_colors[i] = ColorTypes(color[i]);
|
||||
|
||||
_colored = true;
|
||||
}
|
||||
|
||||
void AppenderConsole::SetColor(bool stdout_stream, ColorTypes color)
|
||||
{
|
||||
#if PLATFORM == TC_PLATFORM_WINDOWS
|
||||
static WORD WinColorFG[MaxColors] =
|
||||
{
|
||||
0, // BLACK
|
||||
FOREGROUND_RED, // RED
|
||||
FOREGROUND_GREEN, // GREEN
|
||||
FOREGROUND_RED | FOREGROUND_GREEN, // BROWN
|
||||
FOREGROUND_BLUE, // BLUE
|
||||
FOREGROUND_RED | FOREGROUND_BLUE, // MAGENTA
|
||||
FOREGROUND_GREEN | FOREGROUND_BLUE, // CYAN
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, // WHITE
|
||||
// YELLOW
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
|
||||
// RED_BOLD
|
||||
FOREGROUND_RED | FOREGROUND_INTENSITY,
|
||||
// GREEN_BOLD
|
||||
FOREGROUND_GREEN | FOREGROUND_INTENSITY,
|
||||
FOREGROUND_BLUE | FOREGROUND_INTENSITY, // BLUE_BOLD
|
||||
// MAGENTA_BOLD
|
||||
FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||
// CYAN_BOLD
|
||||
FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||
// WHITE_BOLD
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
|
||||
};
|
||||
|
||||
HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
|
||||
SetConsoleTextAttribute(hConsole, WinColorFG[color]);
|
||||
#else
|
||||
enum ANSITextAttr
|
||||
{
|
||||
TA_BOLD = 1,
|
||||
TA_BLINK = 5,
|
||||
TA_REVERSE = 7
|
||||
};
|
||||
|
||||
enum ANSIFgTextAttr
|
||||
{
|
||||
FG_BLACK = 30,
|
||||
FG_RED,
|
||||
FG_GREEN,
|
||||
FG_BROWN,
|
||||
FG_BLUE,
|
||||
FG_MAGENTA,
|
||||
FG_CYAN,
|
||||
FG_WHITE,
|
||||
FG_YELLOW
|
||||
};
|
||||
|
||||
enum ANSIBgTextAttr
|
||||
{
|
||||
BG_BLACK = 40,
|
||||
BG_RED,
|
||||
BG_GREEN,
|
||||
BG_BROWN,
|
||||
BG_BLUE,
|
||||
BG_MAGENTA,
|
||||
BG_CYAN,
|
||||
BG_WHITE
|
||||
};
|
||||
|
||||
static uint8 UnixColorFG[MaxColors] =
|
||||
{
|
||||
FG_BLACK, // BLACK
|
||||
FG_RED, // RED
|
||||
FG_GREEN, // GREEN
|
||||
FG_BROWN, // BROWN
|
||||
FG_BLUE, // BLUE
|
||||
FG_MAGENTA, // MAGENTA
|
||||
FG_CYAN, // CYAN
|
||||
FG_WHITE, // WHITE
|
||||
FG_YELLOW, // YELLOW
|
||||
FG_RED, // LRED
|
||||
FG_GREEN, // LGREEN
|
||||
FG_BLUE, // LBLUE
|
||||
FG_MAGENTA, // LMAGENTA
|
||||
FG_CYAN, // LCYAN
|
||||
FG_WHITE // LWHITE
|
||||
};
|
||||
|
||||
fprintf((stdout_stream ? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < MaxColors ? ";1" : ""));
|
||||
#endif
|
||||
}
|
||||
|
||||
void AppenderConsole::ResetColor(bool stdout_stream)
|
||||
{
|
||||
#if PLATFORM == TC_PLATFORM_WINDOWS
|
||||
auto hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
|
||||
SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
|
||||
#else
|
||||
fprintf((stdout_stream ? stdout : stderr), "\x1b[0m");
|
||||
#endif
|
||||
}
|
||||
|
||||
void AppenderConsole::_write(LogMessage const* message)
|
||||
{
|
||||
bool stdout_stream = !(message->level == LOG_LEVEL_ERROR || message->level == LOG_LEVEL_FATAL);
|
||||
|
||||
if (_colored)
|
||||
{
|
||||
uint8 index;
|
||||
switch (message->level)
|
||||
{
|
||||
case LOG_LEVEL_TRACE:
|
||||
index = 5;
|
||||
break;
|
||||
case LOG_LEVEL_DEBUG:
|
||||
index = 4;
|
||||
break;
|
||||
case LOG_LEVEL_INFO:
|
||||
index = 3;
|
||||
break;
|
||||
case LOG_LEVEL_WARN:
|
||||
index = 2;
|
||||
break;
|
||||
case LOG_LEVEL_FATAL:
|
||||
index = 0;
|
||||
break;
|
||||
case LOG_LEVEL_ERROR: // No break on purpose
|
||||
default:
|
||||
index = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
SetColor(stdout_stream, _colors[index]);
|
||||
utf8printf(stdout_stream ? stdout : stderr, "%s%s", message->prefix.c_str(), message->text.c_str());
|
||||
ResetColor(stdout_stream);
|
||||
}
|
||||
else
|
||||
utf8printf(stdout_stream ? stdout : stderr, "%s%s", message->prefix.c_str(), message->text.c_str());
|
||||
}
|
||||
60
src/common/Logging/AppenderConsole.h
Normal file
60
src/common/Logging/AppenderConsole.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef APPENDERCONSOLE_H
|
||||
#define APPENDERCONSOLE_H
|
||||
|
||||
#include <string>
|
||||
#include "Appender.h"
|
||||
#include "LogCommon.h"
|
||||
|
||||
enum ColorTypes : uint8
|
||||
{
|
||||
BLACK,
|
||||
RED,
|
||||
GREEN,
|
||||
BROWN,
|
||||
BLUE,
|
||||
MAGENTA,
|
||||
CYAN,
|
||||
GREY,
|
||||
YELLOW,
|
||||
LRED,
|
||||
LGREEN,
|
||||
LBLUE,
|
||||
LMAGENTA,
|
||||
LCYAN,
|
||||
WHITE,
|
||||
|
||||
MaxColors
|
||||
};
|
||||
|
||||
class AppenderConsole : public Appender
|
||||
{
|
||||
public:
|
||||
AppenderConsole(uint8 _id, std::string const& name, LogLevel level, AppenderFlags flags);
|
||||
void InitColors(const std::string& init_str);
|
||||
|
||||
private:
|
||||
void SetColor(bool stdout_stream, ColorTypes color);
|
||||
void ResetColor(bool stdout_stream);
|
||||
void _write(LogMessage const* message) override;
|
||||
bool _colored;
|
||||
ColorTypes _colors[NUM_ENABLED_LOG_LEVELS];
|
||||
};
|
||||
|
||||
#endif
|
||||
54
src/common/Logging/AppenderDB.cpp
Normal file
54
src/common/Logging/AppenderDB.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "AppenderDB.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
|
||||
AppenderDB::AppenderDB(uint8 id, std::string const& name, LogLevel level, uint8 realmId):
|
||||
Appender(id, name, APPENDER_DB, level), realm(realmId), enable(false)
|
||||
{
|
||||
}
|
||||
|
||||
AppenderDB::~AppenderDB() = default;
|
||||
|
||||
void AppenderDB::_write(LogMessage const* message)
|
||||
{
|
||||
if (!enable)
|
||||
return;
|
||||
|
||||
switch (message->type)
|
||||
{
|
||||
case LOG_FILTER_SQL:
|
||||
case LOG_FILTER_SQL_DRIVER:
|
||||
case LOG_FILTER_SQL_DEV:
|
||||
break; // Avoid infinite loop, PExecute triggers Logging with LOG_FILTER_SQL type
|
||||
default:
|
||||
auto stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_LOG);
|
||||
stmt->setUInt64(0, message->mtime);
|
||||
stmt->setUInt32(1, realm);
|
||||
stmt->setUInt8(2, message->type);
|
||||
stmt->setUInt8(3, message->level);
|
||||
stmt->setString(4, message->text);
|
||||
LoginDatabase.Execute(stmt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AppenderDB::setEnable(bool _enable)
|
||||
{
|
||||
enable = _enable;
|
||||
}
|
||||
36
src/common/Logging/AppenderDB.h
Normal file
36
src/common/Logging/AppenderDB.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef APPENDERDB_H
|
||||
#define APPENDERDB_H
|
||||
|
||||
#include "Appender.h"
|
||||
|
||||
class AppenderDB : public Appender
|
||||
{
|
||||
public:
|
||||
AppenderDB(uint8 _id, std::string const& _name, LogLevel level, uint8 realmId);
|
||||
~AppenderDB();
|
||||
void setEnable(bool enable);
|
||||
|
||||
private:
|
||||
uint8 realm;
|
||||
bool enable;
|
||||
void _write(LogMessage const* message) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
72
src/common/Logging/AppenderFile.cpp
Normal file
72
src/common/Logging/AppenderFile.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "AppenderFile.h"
|
||||
#include "Common.h"
|
||||
|
||||
AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, const char* _filename, const char* _logDir, const char* _mode, AppenderFlags _flags)
|
||||
: Appender(id, name, APPENDER_FILE, level, _flags), filename(_filename), logDir(_logDir), mode(_mode)
|
||||
{
|
||||
dynamicName = std::string::npos != filename.find("%s");
|
||||
backup = (_flags & APPENDER_FLAGS_MAKE_FILE_BACKUP) != 0;
|
||||
|
||||
logfile = !dynamicName ? OpenFile(_filename, _mode, backup) : nullptr;
|
||||
}
|
||||
|
||||
AppenderFile::~AppenderFile()
|
||||
{
|
||||
if (logfile)
|
||||
{
|
||||
fclose(logfile);
|
||||
logfile = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void AppenderFile::_write(LogMessage const* message)
|
||||
{
|
||||
if (dynamicName)
|
||||
{
|
||||
char namebuf[260/*MAX_PATH*/];
|
||||
snprintf(namebuf, 260/*MAX_PATH*/, filename.c_str(), message->param1.c_str());
|
||||
logfile = OpenFile(namebuf, mode, backup);
|
||||
}
|
||||
|
||||
if (logfile)
|
||||
{
|
||||
fprintf(logfile, "%s%s", message->prefix.c_str(), message->text.c_str());
|
||||
fflush(logfile);
|
||||
|
||||
if (dynamicName)
|
||||
{
|
||||
fclose(logfile);
|
||||
logfile = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FILE* AppenderFile::OpenFile(std::string const &filename, std::string const &mode, bool backup)
|
||||
{
|
||||
if (mode == "w" && backup)
|
||||
{
|
||||
auto newName(filename);
|
||||
newName.push_back('.');
|
||||
newName.append(LogMessage::getTimeStr(time(nullptr)));
|
||||
rename(filename.c_str(), newName.c_str()); // no error handling... if we couldn't make a backup, just ignore
|
||||
}
|
||||
|
||||
return fopen((logDir + filename).c_str(), mode.c_str());
|
||||
}
|
||||
40
src/common/Logging/AppenderFile.h
Normal file
40
src/common/Logging/AppenderFile.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef APPENDERFILE_H
|
||||
#define APPENDERFILE_H
|
||||
|
||||
#include "Appender.h"
|
||||
|
||||
class AppenderFile : public Appender
|
||||
{
|
||||
public:
|
||||
AppenderFile(uint8 _id, std::string const& _name, LogLevel level, const char* filename, const char* logDir, const char* mode, AppenderFlags flags);
|
||||
~AppenderFile();
|
||||
FILE* OpenFile(std::string const& _name, std::string const& _mode, bool _backup);
|
||||
|
||||
private:
|
||||
void _write(LogMessage const* message) override;
|
||||
FILE* logfile;
|
||||
std::string filename;
|
||||
std::string logDir;
|
||||
std::string mode;
|
||||
bool dynamicName;
|
||||
bool backup;
|
||||
};
|
||||
|
||||
#endif
|
||||
725
src/common/Logging/Log.cpp
Normal file
725
src/common/Logging/Log.cpp
Normal file
@@ -0,0 +1,725 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Log.h"
|
||||
#include "Common.h"
|
||||
#include "Config.h"
|
||||
#include "Util.h"
|
||||
#include "AppenderConsole.h"
|
||||
#include "AppenderFile.h"
|
||||
#include "AppenderDB.h"
|
||||
#include "LogOperation.h"
|
||||
#include "Logger.h"
|
||||
#include "Duration.h"
|
||||
|
||||
#include <cstdarg>
|
||||
#include <sstream>
|
||||
#include "StringFormat.h"
|
||||
|
||||
Log::Log() : _ioService(nullptr), _strand(nullptr)
|
||||
{
|
||||
arenaLogFile2v2 = nullptr;
|
||||
arenaLogFile3v3 = nullptr;
|
||||
diffLogFile = nullptr;
|
||||
spammLogFile = nullptr;
|
||||
wardenLogFile = nullptr;
|
||||
mapInfoFile = nullptr;
|
||||
freezeFile = nullptr;
|
||||
acLogFile = nullptr;
|
||||
arenaSeasonLogFile = nullptr;
|
||||
tryCatchLogFile = nullptr;
|
||||
SetRealmID(0);
|
||||
m_logsTimestamp = "_" + GetTimestampStr();
|
||||
loggerList.resize(LOG_FILTER_MAX);
|
||||
LoadFromConfig();
|
||||
_checkLock = false;
|
||||
}
|
||||
|
||||
Log::~Log()
|
||||
{
|
||||
delete _strand;
|
||||
Close();
|
||||
}
|
||||
|
||||
Log* Log::instance(boost::asio::io_service* ioService)
|
||||
{
|
||||
static Log instance;
|
||||
|
||||
if (ioService != nullptr)
|
||||
{
|
||||
instance._ioService = ioService;
|
||||
instance._strand = new boost::asio::strand(*ioService);
|
||||
}
|
||||
|
||||
return &instance;
|
||||
}
|
||||
|
||||
uint8 Log::NextAppenderId()
|
||||
{
|
||||
return AppenderId++;
|
||||
}
|
||||
|
||||
int32 GetConfigIntDefault(std::string base, const char* name, int32 value)
|
||||
{
|
||||
base.append(name);
|
||||
return sConfigMgr->GetIntDefault(base, value);
|
||||
}
|
||||
|
||||
std::string GetConfigStringDefault(std::string base, const char* name, const char* value)
|
||||
{
|
||||
base.append(name);
|
||||
return sConfigMgr->GetStringDefault(base, value);
|
||||
}
|
||||
|
||||
// Returns default logger if the requested logger is not found
|
||||
Logger* Log::GetLoggerByType(LogFilterType filter)
|
||||
{
|
||||
if (loggerList.size() <= filter)
|
||||
return nullptr;
|
||||
return loggerList[filter];
|
||||
}
|
||||
|
||||
Appender* Log::GetAppenderByName(std::string const& name)
|
||||
{
|
||||
auto it = appenders.begin();
|
||||
while (it != appenders.end() && it->second && it->second->getName() != name)
|
||||
++it;
|
||||
|
||||
return it == appenders.end() ? nullptr : it->second.get();
|
||||
}
|
||||
|
||||
void Log::CreateAppenderFromConfig(const char* name)
|
||||
{
|
||||
if (!name || *name == '\0')
|
||||
return;
|
||||
|
||||
// Format=type,level,flags,optional1,optional2
|
||||
// if type = File. optional1 = file and option2 = mode
|
||||
// if type = Console. optional1 = Color
|
||||
std::string options = "Appender.";
|
||||
options.append(name);
|
||||
options = sConfigMgr->GetStringDefault(options, "");
|
||||
Tokenizer tokens(options, ',');
|
||||
auto iter = tokens.begin();
|
||||
|
||||
if (tokens.size() < 2)
|
||||
{
|
||||
fprintf(stderr, "Log::CreateAppenderFromConfig: Wrong configuration for appender %s. Config line: %s\n", name, options.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
AppenderFlags flags = APPENDER_FLAGS_NONE;
|
||||
auto type = AppenderType(atoi(*iter));
|
||||
++iter;
|
||||
auto level = LogLevel(atoi(*iter));
|
||||
if (level > LOG_LEVEL_FATAL)
|
||||
{
|
||||
fprintf(stderr, "Log::CreateAppenderFromConfig: Wrong Log Level %u for appender %s\n", level, name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (++iter != tokens.end())
|
||||
flags = AppenderFlags(atoi(*iter));
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case APPENDER_CONSOLE:
|
||||
{
|
||||
auto appender = new AppenderConsole(NextAppenderId(), name, level, flags);
|
||||
appenders[appender->getId()].reset(appender);
|
||||
if (++iter != tokens.end())
|
||||
appender->InitColors(*iter);
|
||||
break;
|
||||
}
|
||||
case APPENDER_FILE:
|
||||
{
|
||||
std::string mode = "a";
|
||||
|
||||
if (++iter == tokens.end())
|
||||
{
|
||||
fprintf(stderr, "Log::CreateAppenderFromConfig: Missing file name for appender %s\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string filename = *iter;
|
||||
|
||||
if (++iter != tokens.end())
|
||||
mode = *iter;
|
||||
|
||||
if (flags & APPENDER_FLAGS_USE_TIMESTAMP)
|
||||
{
|
||||
auto dot_pos = filename.find_last_of('.');
|
||||
if (dot_pos != std::string::npos)
|
||||
filename.insert(dot_pos, m_logsTimestamp);
|
||||
else
|
||||
filename += m_logsTimestamp;
|
||||
}
|
||||
|
||||
auto id = NextAppenderId();
|
||||
appenders[id].reset(new AppenderFile(id, name, level, filename.c_str(), m_logsDir.c_str(), mode.c_str(), flags));
|
||||
break;
|
||||
}
|
||||
case APPENDER_DB:
|
||||
{
|
||||
auto id = NextAppenderId();
|
||||
appenders[id].reset(new AppenderDB(id, name, level, realm));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fprintf(stderr, "Log::CreateAppenderFromConfig: Unknown type %u for appender %s\n", type, name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Log::CreateLoggerFromConfig(const char* name)
|
||||
{
|
||||
if (!name || *name == '\0')
|
||||
return;
|
||||
|
||||
std::string options = "Logger.";
|
||||
options.append(name);
|
||||
options = sConfigMgr->GetStringDefault(options, "");
|
||||
if (options.empty())
|
||||
{
|
||||
fprintf(stderr, "Log::CreateLoggerFromConfig: Missing config option Logger.%s\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
Tokenizer tokens(options, ',');
|
||||
auto iter = tokens.begin();
|
||||
|
||||
if (tokens.size() != 3)
|
||||
{
|
||||
fprintf(stderr, "Log::CreateLoggerFromConfig: Wrong config option Logger.%s=%s\n", name, options.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 type = atoi(*iter);
|
||||
if (type > LOG_FILTER_MAX)
|
||||
{
|
||||
fprintf(stderr, "Log::CreateLoggerFromConfig: Wrong type %u for logger %s\n", type, name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (loggerList.size() <= type)
|
||||
return;
|
||||
|
||||
Logger& logger = loggers[type];
|
||||
if (!logger.getName().empty())
|
||||
{
|
||||
fprintf(stderr, "Error while configuring Logger %s. Already defined\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
++iter;
|
||||
|
||||
auto level = LogLevel(atoi(*iter));
|
||||
if (level > LOG_LEVEL_FATAL)
|
||||
{
|
||||
fprintf(stderr, "Log::CreateLoggerFromConfig: Wrong Log Level %u for logger %s\n", type, name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (level < lowestLogLevel)
|
||||
lowestLogLevel = level;
|
||||
|
||||
loggerList[type] = &logger;
|
||||
logger.Create(name, LogFilterType(type), level);
|
||||
|
||||
++iter;
|
||||
std::istringstream ss(*iter);
|
||||
std::string str;
|
||||
|
||||
ss >> str;
|
||||
while (ss)
|
||||
{
|
||||
if (auto appender = GetAppenderByName(str))
|
||||
logger.addAppender(appender->getId(), appender);
|
||||
else
|
||||
fprintf(stderr, "Error while configuring Appender %s in Logger %s. Appender does not exist", str.c_str(), name);
|
||||
ss >> str;
|
||||
}
|
||||
}
|
||||
|
||||
void Log::ReadAppendersFromConfig()
|
||||
{
|
||||
std::istringstream ss(sConfigMgr->GetStringDefault("Appenders", ""));
|
||||
std::string name;
|
||||
|
||||
do
|
||||
{
|
||||
ss >> name;
|
||||
CreateAppenderFromConfig(name.c_str());
|
||||
name = "";
|
||||
} while (ss);
|
||||
}
|
||||
|
||||
void Log::ReadLoggersFromConfig()
|
||||
{
|
||||
std::istringstream ss(sConfigMgr->GetStringDefault("Loggers", ""));
|
||||
std::string name;
|
||||
|
||||
do
|
||||
{
|
||||
ss >> name;
|
||||
CreateLoggerFromConfig(name.c_str());
|
||||
name = "";
|
||||
} while (ss);
|
||||
|
||||
auto it = loggers.cbegin();
|
||||
while (it != loggers.end() && it->first)
|
||||
++it;
|
||||
|
||||
// root logger must exist. Marking as disabled as its not configured
|
||||
if (it == loggers.end())
|
||||
loggers[0].Create("root", LOG_FILTER_GENERAL, LOG_LEVEL_DISABLED);
|
||||
}
|
||||
|
||||
void Log::EnableDBAppenders()
|
||||
{
|
||||
for (auto& appender : appenders)
|
||||
if (appender.second && appender.second->getType() == APPENDER_DB)
|
||||
static_cast<AppenderDB*>(appender.second.get())->setEnable(true);
|
||||
}
|
||||
|
||||
void Log::vlog(LogFilterType filter, LogLevel level, char const* str, va_list argptr)
|
||||
{
|
||||
char text[MAX_QUERY_LEN];
|
||||
vsnprintf(text, MAX_QUERY_LEN, str, argptr);
|
||||
|
||||
std::unique_ptr<LogMessage> msg(new LogMessage(level, filter, text));
|
||||
write(std::move(msg));
|
||||
}
|
||||
|
||||
void Log::write(std::unique_ptr<LogMessage>&& msg)
|
||||
{
|
||||
auto logger = GetLoggerByType(msg->type);
|
||||
msg->text.append("\n");
|
||||
|
||||
if (_ioService)
|
||||
{
|
||||
auto logOperation = std::make_shared<LogOperation>(logger, std::move(msg));
|
||||
_ioService->post(_strand->wrap([logOperation]() { logOperation->call(); }));
|
||||
}
|
||||
else
|
||||
logger->write(msg.get());
|
||||
|
||||
// initialize stderr and stdout, without this launcher wont have realtime output
|
||||
std::cout << "";
|
||||
std::cerr << "";
|
||||
}
|
||||
|
||||
std::string Log::GetTimestampStr()
|
||||
{
|
||||
auto tt = SystemClock::to_time_t(SystemClock::now());
|
||||
|
||||
std::tm aTm{};
|
||||
localtime_r(&tt, &aTm);
|
||||
|
||||
// YYYY year
|
||||
// MM month (2 digits 01-12)
|
||||
// DD day (2 digits 01-31)
|
||||
|
||||
try
|
||||
{
|
||||
return Trinity::StringFormat("%04d-%02d-%02d", aTm.tm_year + 1900, aTm.tm_mon + 1, aTm.tm_mday);
|
||||
}
|
||||
catch (std::exception const& ex)
|
||||
{
|
||||
fprintf(stderr, "Failed to initialize timestamp part of log filename! %s", ex.what());
|
||||
fflush(stderr);
|
||||
ABORT();
|
||||
}
|
||||
}
|
||||
|
||||
bool Log::SetLogLevel(std::string const& name, const char* newLevelc, bool isLogger /* = true */)
|
||||
{
|
||||
auto newLevel = LogLevel(atoi(newLevelc));
|
||||
if (newLevel < 0)
|
||||
return false;
|
||||
|
||||
if (isLogger)
|
||||
{
|
||||
auto it = loggers.begin();
|
||||
while (it != loggers.end() && it->second.getName() != name)
|
||||
++it;
|
||||
|
||||
if (it == loggers.end())
|
||||
return false;
|
||||
|
||||
if (newLevel != LOG_LEVEL_DISABLED && newLevel < lowestLogLevel)
|
||||
lowestLogLevel = newLevel;
|
||||
|
||||
it->second.setLogLevel(newLevel);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto appender = GetAppenderByName(name);
|
||||
if (!appender)
|
||||
return false;
|
||||
|
||||
appender->setLogLevel(newLevel);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Log::ShouldLog(LogFilterType type, LogLevel level) const
|
||||
{
|
||||
// Don't even look for a logger if the LogLevel is lower than lowest log levels across all loggers
|
||||
if (level < lowestLogLevel)
|
||||
return false;
|
||||
|
||||
if (_checkLock)
|
||||
return false;
|
||||
|
||||
if (loggerList.size() <= type)
|
||||
return false;
|
||||
|
||||
auto logger = loggerList[type];
|
||||
if (!logger)
|
||||
return false;
|
||||
|
||||
auto loggerLevel = logger->getLogLevel();
|
||||
return loggerLevel && loggerLevel <= level;
|
||||
}
|
||||
void Log::outCharDump(char const* str, uint32 accountId, uint64 guid, char const* name)
|
||||
{
|
||||
if (!str || !ShouldLog(LOG_FILTER_PLAYER_DUMP, LOG_LEVEL_INFO))
|
||||
return;
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << "== START DUMP == (account: " << accountId << " guid: " << guid << " name: " << name
|
||||
<< ")\n" << str << "\n== END DUMP ==\n";
|
||||
|
||||
std::unique_ptr<LogMessage> msg(new LogMessage(LOG_LEVEL_INFO, LOG_FILTER_PLAYER_DUMP, ss.str()));
|
||||
std::ostringstream param;
|
||||
param << guid << '_' << name;
|
||||
|
||||
msg->param1 = param.str();
|
||||
|
||||
write(std::move(msg));
|
||||
}
|
||||
|
||||
void Log::outCommand(uint32 account, const char * str, ...)
|
||||
{
|
||||
if (!str || !ShouldLog(LOG_FILTER_GMCOMMAND, LOG_LEVEL_INFO))
|
||||
return;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, str);
|
||||
char text[MAX_QUERY_LEN];
|
||||
vsnprintf(text, MAX_QUERY_LEN, str, ap);
|
||||
va_end(ap);
|
||||
|
||||
std::unique_ptr<LogMessage> msg(new LogMessage(LOG_LEVEL_INFO, LOG_FILTER_GMCOMMAND, text));
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << account;
|
||||
msg->param1 = ss.str();
|
||||
|
||||
write(std::move(msg));
|
||||
}
|
||||
|
||||
void Log::SetRealmID(uint32 id)
|
||||
{
|
||||
realm = id;
|
||||
}
|
||||
|
||||
void Log::Close()
|
||||
{
|
||||
if (arenaLogFile2v2 != nullptr)
|
||||
fclose(arenaLogFile2v2);
|
||||
arenaLogFile2v2 = nullptr;
|
||||
if (arenaLogFile3v3 != nullptr)
|
||||
fclose(arenaLogFile3v3);
|
||||
arenaLogFile3v3 = nullptr;
|
||||
if (spammLogFile != nullptr)
|
||||
fclose(spammLogFile);
|
||||
spammLogFile = nullptr;
|
||||
if (diffLogFile != nullptr)
|
||||
fclose(diffLogFile);
|
||||
diffLogFile = nullptr;
|
||||
if (wardenLogFile != nullptr)
|
||||
fclose(wardenLogFile);
|
||||
wardenLogFile = nullptr;
|
||||
|
||||
if (mapInfoFile != nullptr)
|
||||
fclose(mapInfoFile);
|
||||
mapInfoFile = nullptr;
|
||||
|
||||
if (freezeFile != nullptr)
|
||||
fclose(freezeFile);
|
||||
freezeFile = nullptr;
|
||||
|
||||
if (acLogFile != nullptr)
|
||||
fclose(acLogFile);
|
||||
acLogFile = nullptr;
|
||||
|
||||
if (arenaSeasonLogFile != nullptr)
|
||||
fclose(arenaSeasonLogFile);
|
||||
arenaSeasonLogFile = nullptr;
|
||||
|
||||
if (tryCatchLogFile != nullptr)
|
||||
fclose(tryCatchLogFile);
|
||||
tryCatchLogFile = nullptr;
|
||||
|
||||
loggers.clear();
|
||||
appenders.clear();
|
||||
}
|
||||
|
||||
void Log::LoadFromConfig()
|
||||
{
|
||||
Close();
|
||||
AppenderId = 0;
|
||||
lowestLogLevel = LOG_LEVEL_FATAL;
|
||||
|
||||
m_logsDir = sConfigMgr->GetStringDefault("LogsDir", "");
|
||||
if (!m_logsDir.empty() && (m_logsDir.at(m_logsDir.length() - 1) != '/') && (m_logsDir.at(m_logsDir.length() - 1) != '\\'))
|
||||
m_logsDir.push_back('/');
|
||||
|
||||
ReadAppendersFromConfig();
|
||||
ReadLoggersFromConfig();
|
||||
|
||||
arenaLogFile2v2 = openLogFile("ArenaLogFile2v2", nullptr, "a");
|
||||
arenaLogFile3v3 = openLogFile("ArenaLogFile3v3", nullptr, "a");
|
||||
spammLogFile = openLogFile("SpammLogFile", nullptr, "a");
|
||||
diffLogFile = openLogFile("diffLogFile", nullptr, "a");
|
||||
wardenLogFile = openLogFile("Warden.LogFile", nullptr, "a");
|
||||
mapInfoFile = openLogFile("MapInfo.LogFile", nullptr, "a");
|
||||
_pveEncounterLogFile = openLogFile("PveEncounters", nullptr, "a");
|
||||
freezeFile = openLogFile("freezeFile", nullptr, "a");
|
||||
acLogFile = openLogFile("AnticheatLogFile", nullptr, "a");
|
||||
arenaSeasonLogFile = openLogFile("ArenaSeasonLogFile", nullptr, "a");
|
||||
tryCatchLogFile = openLogFile("TryCatchLogFile", nullptr, "a");
|
||||
}
|
||||
|
||||
void Log::outArena(uint8 jointype, const char * str, ...)
|
||||
{
|
||||
if (!str)
|
||||
return;
|
||||
|
||||
if (jointype != 2 && jointype != 3) // 2 -2v2, 3 - 3v3, 0 - both
|
||||
jointype = 3;
|
||||
else
|
||||
jointype -= 1;
|
||||
|
||||
// on the output we have flags -> jointype & 1 - 2v2, jointype & 2 - 3v3
|
||||
|
||||
if (jointype & 1 && arenaLogFile2v2)
|
||||
{
|
||||
va_list ap;
|
||||
outTimestamp(arenaLogFile2v2);
|
||||
va_start(ap, str);
|
||||
vfprintf(arenaLogFile2v2, str, ap);
|
||||
fprintf(arenaLogFile2v2, "\n");
|
||||
va_end(ap);
|
||||
fflush(arenaLogFile2v2);
|
||||
}
|
||||
|
||||
if (jointype & 2 && arenaLogFile3v3)
|
||||
{
|
||||
va_list ap;
|
||||
outTimestamp(arenaLogFile3v3);
|
||||
va_start(ap, str);
|
||||
vfprintf(arenaLogFile3v3, str, ap);
|
||||
fprintf(arenaLogFile3v3, "\n");
|
||||
va_end(ap);
|
||||
fflush(arenaLogFile3v3);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::OutPveEncounter(char const* str, ...)
|
||||
{
|
||||
if (!str || !_pveEncounterLogFile)
|
||||
return;
|
||||
|
||||
va_list ap;
|
||||
outTimestamp(_pveEncounterLogFile);
|
||||
va_start(ap, str);
|
||||
vfprintf(_pveEncounterLogFile, str, ap);
|
||||
fprintf(_pveEncounterLogFile, "\n");
|
||||
va_end(ap);
|
||||
fflush(_pveEncounterLogFile);
|
||||
}
|
||||
|
||||
void Log::outTimestamp(FILE* file)
|
||||
{
|
||||
auto t = time(nullptr);
|
||||
auto aTm = localtime(&t);
|
||||
// YYYY year
|
||||
// MM month (2 digits 01-12)
|
||||
// DD day (2 digits 01-31)
|
||||
// HH hour (2 digits 00-23)
|
||||
// MM minutes (2 digits 00-59)
|
||||
// SS seconds (2 digits 00-59)
|
||||
fprintf(file, "%-4d-%02d-%02d %02d:%02d:%02d ", aTm->tm_year + 1900, aTm->tm_mon + 1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec);
|
||||
}
|
||||
|
||||
FILE* Log::openLogFile(char const* configFileName, char const* configTimeStampFlag, char const* mode)
|
||||
{
|
||||
auto logfn = sConfigMgr->GetStringDefault(configFileName, "");
|
||||
if (logfn.empty())
|
||||
return nullptr;
|
||||
|
||||
if (configTimeStampFlag && sConfigMgr->GetBoolDefault(configTimeStampFlag, false))
|
||||
{
|
||||
auto dot_pos = logfn.find_last_of('.');
|
||||
if (dot_pos != std::string::npos)
|
||||
logfn.insert(dot_pos, m_logsTimestamp);
|
||||
else
|
||||
logfn += m_logsTimestamp;
|
||||
}
|
||||
|
||||
return fopen((m_logsDir + logfn).c_str(), mode);
|
||||
}
|
||||
|
||||
void Log::outSpamm(const char * str, ...)
|
||||
{
|
||||
if (!str)
|
||||
return;
|
||||
|
||||
if (spammLogFile)
|
||||
{
|
||||
va_list ap;
|
||||
outTimestamp(spammLogFile);
|
||||
va_start(ap, str);
|
||||
vfprintf(spammLogFile, str, ap);
|
||||
fprintf(spammLogFile, "\n");
|
||||
va_end(ap);
|
||||
fflush(spammLogFile);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::outDiff(const char * str, ...)
|
||||
{
|
||||
if (!str)
|
||||
return;
|
||||
|
||||
if (diffLogFile)
|
||||
{
|
||||
va_list ap;
|
||||
outTimestamp(diffLogFile);
|
||||
va_start(ap, str);
|
||||
vfprintf(diffLogFile, str, ap);
|
||||
fprintf(diffLogFile, "\n");
|
||||
va_end(ap);
|
||||
fflush(diffLogFile);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::outFreeze(const char * str, ...)
|
||||
{
|
||||
if (!str)
|
||||
return;
|
||||
|
||||
if (freezeFile)
|
||||
{
|
||||
va_list ap;
|
||||
outTimestamp(freezeFile);
|
||||
va_start(ap, str);
|
||||
vfprintf(freezeFile, str, ap);
|
||||
fprintf(freezeFile, "\n");
|
||||
va_end(ap);
|
||||
fflush(freezeFile);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::outAnticheat(const char * str, ...)
|
||||
{
|
||||
if (!str)
|
||||
return;
|
||||
|
||||
if (acLogFile)
|
||||
{
|
||||
va_list ap;
|
||||
outTimestamp(acLogFile);
|
||||
va_start(ap, str);
|
||||
vfprintf(acLogFile, str, ap);
|
||||
fprintf(acLogFile, "\n");
|
||||
va_end(ap);
|
||||
fflush(acLogFile);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::outMapInfo(const char * str, ...)
|
||||
{
|
||||
if (!str)
|
||||
return;
|
||||
|
||||
if (mapInfoFile)
|
||||
{
|
||||
va_list ap;
|
||||
outTimestamp(mapInfoFile);
|
||||
va_start(ap, str);
|
||||
vfprintf(mapInfoFile, str, ap);
|
||||
fprintf(mapInfoFile, "\n");
|
||||
va_end(ap);
|
||||
fflush(mapInfoFile);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::outWarden(const char * str, ...)
|
||||
{
|
||||
if (!str)
|
||||
return;
|
||||
|
||||
if (wardenLogFile)
|
||||
{
|
||||
va_list ap;
|
||||
outTimestamp(wardenLogFile);
|
||||
va_start(ap, str);
|
||||
vfprintf(wardenLogFile, str, ap);
|
||||
fprintf(wardenLogFile, "\n");
|
||||
va_end(ap);
|
||||
fflush(wardenLogFile);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::outArenaSeason(const char * str, ...)
|
||||
{
|
||||
if (!str)
|
||||
return;
|
||||
|
||||
if (arenaSeasonLogFile)
|
||||
{
|
||||
va_list ap;
|
||||
outTimestamp(arenaSeasonLogFile);
|
||||
va_start(ap, str);
|
||||
vfprintf(arenaSeasonLogFile, str, ap);
|
||||
fprintf(arenaSeasonLogFile, "\n");
|
||||
va_end(ap);
|
||||
fflush(arenaSeasonLogFile);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::outTryCatch(const char * str, ...)
|
||||
{
|
||||
if (!str)
|
||||
return;
|
||||
|
||||
if (tryCatchLogFile)
|
||||
{
|
||||
va_list ap;
|
||||
outTimestamp(tryCatchLogFile);
|
||||
va_start(ap, str);
|
||||
vfprintf(tryCatchLogFile, str, ap);
|
||||
fprintf(tryCatchLogFile, "\n");
|
||||
va_end(ap);
|
||||
fflush(tryCatchLogFile);
|
||||
}
|
||||
}
|
||||
166
src/common/Logging/Log.h
Normal file
166
src/common/Logging/Log.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOG_H
|
||||
#define LOG_H
|
||||
|
||||
#include "Define.h"
|
||||
#include "LogCommon.h"
|
||||
#include "Appender.h"
|
||||
#include "Logger.h"
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <stdarg.h>
|
||||
#include <safe_ptr.h>
|
||||
#include "StringFormat.h"
|
||||
#include "Common.h"
|
||||
|
||||
typedef std::unordered_map<uint8, Logger> LoggerMap;
|
||||
typedef std::vector<Logger*> LoggerList;
|
||||
|
||||
class Log
|
||||
{
|
||||
Log();
|
||||
~Log();
|
||||
|
||||
public:
|
||||
Log(Log const&) = delete;
|
||||
Log(Log&&) = delete;
|
||||
Log& operator=(Log const&) = delete;
|
||||
Log& operator=(Log&&) = delete;
|
||||
|
||||
static Log* instance(boost::asio::io_service* ioService = nullptr);
|
||||
|
||||
void LoadFromConfig();
|
||||
void Close();
|
||||
bool ShouldLog(LogFilterType type, LogLevel level) const;
|
||||
bool SetLogLevel(std::string const& name, char const* newLevelc, bool isLogger = true);
|
||||
|
||||
void outMessage(LogFilterType filter, LogLevel level, std::string&& message)
|
||||
{
|
||||
std::unique_ptr<LogMessage> msg(new LogMessage(level, filter, std::move(message)));
|
||||
write(std::move(msg));
|
||||
}
|
||||
|
||||
template<typename Format, typename... Args>
|
||||
void outMessage(LogFilterType filter, LogLevel level, Format&& fmt, Args&&... args)
|
||||
{
|
||||
outMessage(filter, level, Trinity::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
void outArena(uint8 jointype, const char * str, ...); // ATTR_PRINTF(3, 4);
|
||||
void OutPveEncounter(char const* str, ...);
|
||||
void outSpamm(const char * str, ...) ATTR_PRINTF(2, 3);
|
||||
void outDiff(const char * str, ...) ATTR_PRINTF(2, 3);
|
||||
void outWarden(const char * str, ...) ATTR_PRINTF(2, 3);
|
||||
void outCommand(uint32 account, const char * str, ...) ATTR_PRINTF(3, 4);
|
||||
void outCharDump(char const* str, uint32 accountId, uint64 guid, char const* name);
|
||||
void outMapInfo(const char * str, ...) ATTR_PRINTF(2, 3);
|
||||
void outFreeze(const char * str, ...) ATTR_PRINTF(2, 3);
|
||||
void outAnticheat(const char * str, ...) ATTR_PRINTF(2, 3);
|
||||
void outArenaSeason(const char * str, ...) ATTR_PRINTF(2, 3);
|
||||
void outTryCatch(const char * str, ...) ATTR_PRINTF(2, 3);
|
||||
|
||||
void EnableDBAppenders();
|
||||
static std::string GetTimestampStr();
|
||||
|
||||
void SetRealmID(uint32 id);
|
||||
static void outTimestamp(FILE* file);
|
||||
uint32 GetRealmID() const { return realm; }
|
||||
|
||||
|
||||
std::atomic<bool> _checkLock{};
|
||||
|
||||
private:
|
||||
void vlog(LogFilterType f, LogLevel level, char const* str, va_list argptr);
|
||||
void write(std::unique_ptr<LogMessage>&& msg);
|
||||
|
||||
Logger* GetLoggerByType(LogFilterType filter);
|
||||
Appender* GetAppenderByName(std::string const& name);
|
||||
uint8 NextAppenderId();
|
||||
void CreateAppenderFromConfig(const char* name);
|
||||
void CreateLoggerFromConfig(const char* name);
|
||||
void ReadAppendersFromConfig();
|
||||
void ReadLoggersFromConfig();
|
||||
|
||||
std::unordered_map<uint8, std::unique_ptr<Appender>> appenders;
|
||||
LoggerMap loggers;
|
||||
LoggerList loggerList;
|
||||
uint8 AppenderId{};
|
||||
LogLevel lowestLogLevel = LOG_LEVEL_DISABLED;
|
||||
FILE* openLogFile(char const* configFileName, char const* configTimeStampFlag, char const* mode);
|
||||
FILE* arenaLogFile2v2;
|
||||
FILE* arenaLogFile3v3;
|
||||
FILE* spammLogFile;
|
||||
FILE* diffLogFile;
|
||||
FILE* wardenLogFile;
|
||||
FILE* mapInfoFile;
|
||||
FILE* _pveEncounterLogFile{};
|
||||
FILE* freezeFile;
|
||||
FILE* acLogFile;
|
||||
FILE* arenaSeasonLogFile;
|
||||
FILE* tryCatchLogFile;
|
||||
|
||||
std::string m_logsDir;
|
||||
std::string m_logsTimestamp;
|
||||
|
||||
uint32 realm{};
|
||||
boost::asio::io_service* _ioService;
|
||||
boost::asio::strand* _strand;
|
||||
};
|
||||
|
||||
#define sLog Log::instance()
|
||||
|
||||
#define TC_LOG_MESSAGE_BODY(filterType__, level__, ...) \
|
||||
if (sLog->ShouldLog(filterType__, level__)) \
|
||||
sLog->outMessage(filterType__, level__, __VA_ARGS__);
|
||||
|
||||
#define TC_LOG_TRACE(filterType__, ...) \
|
||||
do { \
|
||||
TC_LOG_MESSAGE_BODY(filterType__, LOG_LEVEL_TRACE, __VA_ARGS__) \
|
||||
} while(0)
|
||||
|
||||
#define TC_LOG_DEBUG(filterType__, ...) \
|
||||
do { \
|
||||
TC_LOG_MESSAGE_BODY(filterType__, LOG_LEVEL_DEBUG, __VA_ARGS__) \
|
||||
} while(0)
|
||||
|
||||
#define TC_LOG_INFO(filterType__, ...) \
|
||||
do { \
|
||||
TC_LOG_MESSAGE_BODY(filterType__, LOG_LEVEL_INFO, __VA_ARGS__) \
|
||||
} while(0)
|
||||
|
||||
#define TC_LOG_WARN(filterType__, ...) \
|
||||
do { \
|
||||
TC_LOG_MESSAGE_BODY(filterType__, LOG_LEVEL_WARN, __VA_ARGS__) \
|
||||
} while(0)
|
||||
|
||||
#define TC_LOG_ERROR(filterType__, ...) \
|
||||
do { \
|
||||
TC_LOG_MESSAGE_BODY(filterType__, LOG_LEVEL_ERROR, __VA_ARGS__) \
|
||||
} while(0)
|
||||
|
||||
#define TC_LOG_FATAL(filterType__, ...) \
|
||||
do { \
|
||||
TC_LOG_MESSAGE_BODY(filterType__, LOG_LEVEL_FATAL, __VA_ARGS__) \
|
||||
} while(0)
|
||||
|
||||
#endif
|
||||
52
src/common/Logging/LogCommon.h
Normal file
52
src/common/Logging/LogCommon.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LogCommon_h__
|
||||
#define LogCommon_h__
|
||||
|
||||
enum LogLevel
|
||||
{
|
||||
LOG_LEVEL_DISABLED = 0,
|
||||
LOG_LEVEL_TRACE = 1,
|
||||
LOG_LEVEL_DEBUG = 2,
|
||||
LOG_LEVEL_INFO = 3,
|
||||
LOG_LEVEL_WARN = 4,
|
||||
LOG_LEVEL_ERROR = 5,
|
||||
LOG_LEVEL_FATAL = 6,
|
||||
|
||||
NUM_ENABLED_LOG_LEVELS = 6
|
||||
};
|
||||
|
||||
enum AppenderType : uint8
|
||||
{
|
||||
APPENDER_NONE,
|
||||
APPENDER_CONSOLE,
|
||||
APPENDER_FILE,
|
||||
APPENDER_DB
|
||||
};
|
||||
|
||||
enum AppenderFlags
|
||||
{
|
||||
APPENDER_FLAGS_NONE = 0x00,
|
||||
APPENDER_FLAGS_PREFIX_TIMESTAMP = 0x01,
|
||||
APPENDER_FLAGS_PREFIX_LOGLEVEL = 0x02,
|
||||
APPENDER_FLAGS_PREFIX_LOGFILTERTYPE = 0x04,
|
||||
APPENDER_FLAGS_USE_TIMESTAMP = 0x08, // only used by FileAppender
|
||||
APPENDER_FLAGS_MAKE_FILE_BACKUP = 0x10 // only used by FileAppender
|
||||
};
|
||||
|
||||
#endif // LogCommon_h__
|
||||
32
src/common/Logging/LogOperation.cpp
Normal file
32
src/common/Logging/LogOperation.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Appender.h"
|
||||
#include "LogOperation.h"
|
||||
#include "Logger.h"
|
||||
|
||||
LogOperation::LogOperation(Logger * _logger, std::unique_ptr<LogMessage>&& _msg) : logger(_logger), msg(std::forward<std::unique_ptr<LogMessage>>(_msg))
|
||||
{
|
||||
}
|
||||
|
||||
LogOperation::~LogOperation() = default;
|
||||
|
||||
int LogOperation::call()
|
||||
{
|
||||
logger->write(msg.get());
|
||||
return 0;
|
||||
}
|
||||
40
src/common/Logging/LogOperation.h
Normal file
40
src/common/Logging/LogOperation.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOGOPERATION_H
|
||||
#define LOGOPERATION_H
|
||||
|
||||
#include "Define.h"
|
||||
#include <memory>
|
||||
|
||||
class Logger;
|
||||
struct LogMessage;
|
||||
|
||||
class LogOperation
|
||||
{
|
||||
public:
|
||||
LogOperation(Logger * _logger, std::unique_ptr<LogMessage>&& _msg);
|
||||
~LogOperation();
|
||||
|
||||
int call();
|
||||
|
||||
protected:
|
||||
Logger * logger;
|
||||
std::unique_ptr<LogMessage> msg;
|
||||
};
|
||||
|
||||
#endif
|
||||
77
src/common/Logging/Logger.cpp
Normal file
77
src/common/Logging/Logger.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Logger.h"
|
||||
|
||||
Logger::Logger() : name(""), type(LOG_FILTER_GENERAL), level(LOG_LEVEL_DISABLED)
|
||||
{
|
||||
}
|
||||
|
||||
void Logger::Create(std::string const& _name, LogFilterType _type, LogLevel _level)
|
||||
{
|
||||
name = _name;
|
||||
type = _type;
|
||||
level = _level;
|
||||
}
|
||||
|
||||
Logger::~Logger()
|
||||
{
|
||||
appenders.clear();
|
||||
}
|
||||
|
||||
std::string const& Logger::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
LogFilterType Logger::getType() const
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
LogLevel Logger::getLogLevel() const
|
||||
{
|
||||
return level;
|
||||
}
|
||||
|
||||
void Logger::addAppender(uint8 id, Appender* appender)
|
||||
{
|
||||
appenders[id] = appender;
|
||||
}
|
||||
|
||||
void Logger::delAppender(uint8 id)
|
||||
{
|
||||
appenders.erase(id);
|
||||
}
|
||||
|
||||
void Logger::setLogLevel(LogLevel _level)
|
||||
{
|
||||
level = _level;
|
||||
}
|
||||
|
||||
void Logger::write(LogMessage* message)
|
||||
{
|
||||
if (!level || level > message->level || message->text.empty())
|
||||
{
|
||||
//fprintf(stderr, "Logger::write: Logger %s, Level %u. Msg %s Level %u WRONG LEVEL MASK OR EMPTY MSG\n", getName().c_str(), messge.level, message.text.c_str(), .message.level); // DEBUG - RemoveMe
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& appender : appenders)
|
||||
if (appender.second)
|
||||
appender.second->write(message);
|
||||
}
|
||||
51
src/common/Logging/Logger.h
Normal file
51
src/common/Logging/Logger.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOGGER_H
|
||||
#define LOGGER_H
|
||||
|
||||
#include "Appender.h"
|
||||
#include "Define.h"
|
||||
#include "LogCommon.h"
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
class Logger
|
||||
{
|
||||
public:
|
||||
Logger();
|
||||
~Logger();
|
||||
|
||||
void Create(std::string const& name, LogFilterType type, LogLevel level);
|
||||
void addAppender(uint8 type, Appender *);
|
||||
void delAppender(uint8 type);
|
||||
|
||||
std::string const& getName() const;
|
||||
LogFilterType getType() const;
|
||||
LogLevel getLogLevel() const;
|
||||
void setLogLevel(LogLevel level);
|
||||
void write(LogMessage* message);
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
LogFilterType type;
|
||||
LogLevel level;
|
||||
std::unordered_map<uint8, Appender*> appenders;
|
||||
};
|
||||
|
||||
#endif
|
||||
19
src/common/Memory.h
Normal file
19
src/common/Memory.h
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
|
||||
#ifndef _MEMORY_H
|
||||
#define _MEMORY_H
|
||||
|
||||
#include "DetourAlloc.h"
|
||||
|
||||
// memory management
|
||||
inline void* dtCustomAlloc(int size, dtAllocHint /*hint*/)
|
||||
{
|
||||
return (void*)new unsigned char[size];
|
||||
}
|
||||
|
||||
inline void dtCustomFree(void* ptr)
|
||||
{
|
||||
delete [] (unsigned char*)ptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
265
src/common/Platform/ServiceWin32.cpp
Normal file
265
src/common/Platform/ServiceWin32.cpp
Normal file
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "Common.h"
|
||||
#include "Log.h"
|
||||
#include <cstring>
|
||||
#include <windows.h>
|
||||
#include <winsvc.h>
|
||||
|
||||
#if !defined(WINADVAPI)
|
||||
#if !defined(_ADVAPI32_)
|
||||
#define WINADVAPI DECLSPEC_IMPORT
|
||||
#else
|
||||
#define WINADVAPI
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern int main(int argc, char ** argv);
|
||||
extern char serviceLongName[];
|
||||
extern char serviceName[];
|
||||
extern char serviceDescription[];
|
||||
|
||||
extern int m_ServiceStatus;
|
||||
|
||||
SERVICE_STATUS serviceStatus;
|
||||
|
||||
SERVICE_STATUS_HANDLE serviceStatusHandle = 0;
|
||||
|
||||
typedef WINADVAPI BOOL (WINAPI *CSD_T)(SC_HANDLE, DWORD, LPCVOID);
|
||||
|
||||
bool WinServiceInstall()
|
||||
{
|
||||
CSD_T ChangeService_Config2;
|
||||
HMODULE advapi32;
|
||||
SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
|
||||
|
||||
if (serviceControlManager)
|
||||
{
|
||||
char path[_MAX_PATH + 10];
|
||||
if (GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0)
|
||||
{
|
||||
SC_HANDLE service;
|
||||
std::strcat(path, " --service run");
|
||||
service = CreateService(serviceControlManager,
|
||||
serviceName, // name of service
|
||||
serviceLongName, // service name to display
|
||||
SERVICE_ALL_ACCESS, // desired access
|
||||
// service type
|
||||
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
|
||||
SERVICE_AUTO_START, // start type
|
||||
SERVICE_ERROR_IGNORE, // error control type
|
||||
path, // service's binary
|
||||
0, // no load ordering group
|
||||
0, // no tag identifier
|
||||
0, // no dependencies
|
||||
0, // LocalSystem account
|
||||
0); // no password
|
||||
if (service)
|
||||
{
|
||||
advapi32 = GetModuleHandle("ADVAPI32.DLL");
|
||||
if (!advapi32)
|
||||
{
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(serviceControlManager);
|
||||
return false;
|
||||
}
|
||||
|
||||
ChangeService_Config2 = (CSD_T) GetProcAddress(advapi32, "ChangeServiceConfig2A");
|
||||
if (!ChangeService_Config2)
|
||||
{
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(serviceControlManager);
|
||||
return false;
|
||||
}
|
||||
|
||||
SERVICE_DESCRIPTION sdBuf;
|
||||
sdBuf.lpDescription = serviceDescription;
|
||||
ChangeService_Config2(
|
||||
service, // handle to service
|
||||
SERVICE_CONFIG_DESCRIPTION, // change: description
|
||||
&sdBuf); // new data
|
||||
|
||||
SC_ACTION _action[1];
|
||||
_action[0].Type = SC_ACTION_RESTART;
|
||||
_action[0].Delay = 10000;
|
||||
SERVICE_FAILURE_ACTIONS sfa;
|
||||
ZeroMemory(&sfa, sizeof(SERVICE_FAILURE_ACTIONS));
|
||||
sfa.lpsaActions = _action;
|
||||
sfa.cActions = 1;
|
||||
sfa.dwResetPeriod =INFINITE;
|
||||
ChangeService_Config2(
|
||||
service, // handle to service
|
||||
SERVICE_CONFIG_FAILURE_ACTIONS, // information level
|
||||
&sfa); // new data
|
||||
|
||||
CloseServiceHandle(service);
|
||||
|
||||
}
|
||||
}
|
||||
CloseServiceHandle(serviceControlManager);
|
||||
}
|
||||
|
||||
printf("Service installed\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WinServiceUninstall()
|
||||
{
|
||||
SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
|
||||
|
||||
if (serviceControlManager)
|
||||
{
|
||||
SC_HANDLE service = OpenService(serviceControlManager,
|
||||
serviceName, SERVICE_QUERY_STATUS | DELETE);
|
||||
if (service)
|
||||
{
|
||||
SERVICE_STATUS serviceStatus2;
|
||||
if (QueryServiceStatus(service, &serviceStatus2))
|
||||
{
|
||||
if (serviceStatus2.dwCurrentState == SERVICE_STOPPED)
|
||||
DeleteService(service);
|
||||
}
|
||||
CloseServiceHandle(service);
|
||||
}
|
||||
|
||||
CloseServiceHandle(serviceControlManager);
|
||||
}
|
||||
|
||||
printf("Service uninstalled\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
void WINAPI ServiceControlHandler(DWORD controlCode)
|
||||
{
|
||||
switch (controlCode)
|
||||
{
|
||||
case SERVICE_CONTROL_INTERROGATE:
|
||||
break;
|
||||
|
||||
case SERVICE_CONTROL_SHUTDOWN:
|
||||
case SERVICE_CONTROL_STOP:
|
||||
serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
|
||||
SetServiceStatus(serviceStatusHandle, &serviceStatus);
|
||||
|
||||
m_ServiceStatus = 0;
|
||||
return;
|
||||
|
||||
case SERVICE_CONTROL_PAUSE:
|
||||
m_ServiceStatus = 2;
|
||||
serviceStatus.dwCurrentState = SERVICE_PAUSED;
|
||||
SetServiceStatus(serviceStatusHandle, &serviceStatus);
|
||||
break;
|
||||
|
||||
case SERVICE_CONTROL_CONTINUE:
|
||||
serviceStatus.dwCurrentState = SERVICE_RUNNING;
|
||||
SetServiceStatus(serviceStatusHandle, &serviceStatus);
|
||||
m_ServiceStatus = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( controlCode >= 128 && controlCode <= 255 )
|
||||
// user defined control code
|
||||
break;
|
||||
else
|
||||
// unrecognized control code
|
||||
break;
|
||||
}
|
||||
|
||||
SetServiceStatus(serviceStatusHandle, &serviceStatus);
|
||||
}
|
||||
|
||||
void WINAPI ServiceMain(DWORD argc, char *argv[])
|
||||
{
|
||||
// initialise service status
|
||||
serviceStatus.dwServiceType = SERVICE_WIN32;
|
||||
serviceStatus.dwCurrentState = SERVICE_START_PENDING;
|
||||
serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
|
||||
serviceStatus.dwWin32ExitCode = NO_ERROR;
|
||||
serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
|
||||
serviceStatus.dwCheckPoint = 0;
|
||||
serviceStatus.dwWaitHint = 0;
|
||||
|
||||
serviceStatusHandle = RegisterServiceCtrlHandler(serviceName, ServiceControlHandler);
|
||||
|
||||
if ( serviceStatusHandle )
|
||||
{
|
||||
char path[_MAX_PATH + 1];
|
||||
unsigned int i, last_slash = 0;
|
||||
|
||||
GetModuleFileName(0, path, sizeof(path)/sizeof(path[0]));
|
||||
|
||||
for (i = 0; i < std::strlen(path); i++)
|
||||
{
|
||||
if (path[i] == '\\') last_slash = i;
|
||||
}
|
||||
|
||||
path[last_slash] = 0;
|
||||
|
||||
// service is starting
|
||||
serviceStatus.dwCurrentState = SERVICE_START_PENDING;
|
||||
SetServiceStatus(serviceStatusHandle, &serviceStatus);
|
||||
|
||||
// do initialisation here
|
||||
SetCurrentDirectory(path);
|
||||
|
||||
// running
|
||||
serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
|
||||
serviceStatus.dwCurrentState = SERVICE_RUNNING;
|
||||
SetServiceStatus( serviceStatusHandle, &serviceStatus );
|
||||
|
||||
////////////////////////
|
||||
// service main cycle //
|
||||
////////////////////////
|
||||
|
||||
m_ServiceStatus = 1;
|
||||
argc = 1;
|
||||
main(argc, argv);
|
||||
|
||||
// service was stopped
|
||||
serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
|
||||
SetServiceStatus(serviceStatusHandle, &serviceStatus);
|
||||
|
||||
// do cleanup here
|
||||
|
||||
// service is now stopped
|
||||
serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
|
||||
serviceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||
SetServiceStatus(serviceStatusHandle, &serviceStatus);
|
||||
}
|
||||
}
|
||||
|
||||
bool WinServiceRun()
|
||||
{
|
||||
SERVICE_TABLE_ENTRY serviceTable[] =
|
||||
{
|
||||
{ serviceName, ServiceMain },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
if (!StartServiceCtrlDispatcher(serviceTable))
|
||||
{
|
||||
TC_LOG_ERROR(LOG_FILTER_GENERAL, "StartService Failed. Error [%u]", ::GetLastError());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
29
src/common/Platform/ServiceWin32.h
Normal file
29
src/common/Platform/ServiceWin32.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef _WIN32_SERVICE_
|
||||
#define _WIN32_SERVICE_
|
||||
|
||||
bool WinServiceInstall();
|
||||
bool WinServiceUninstall();
|
||||
bool WinServiceRun();
|
||||
|
||||
#endif // _WIN32_SERVICE_
|
||||
#endif // _WIN32
|
||||
|
||||
1
src/common/PrecompiledHeaders/commonPCH.cpp
Normal file
1
src/common/PrecompiledHeaders/commonPCH.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "commonPCH.h"
|
||||
23
src/common/PrecompiledHeaders/commonPCH.h
Normal file
23
src/common/PrecompiledHeaders/commonPCH.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "BoundingIntervalHierarchy.h"
|
||||
#include "Common.h"
|
||||
#include "Config.h"
|
||||
#include "Define.h"
|
||||
#include "Errors.h"
|
||||
#include "GitRevision.h"
|
||||
#include "Log.h"
|
||||
#include "MapTree.h"
|
||||
#include "ModelInstance.h"
|
||||
#include "Util.h"
|
||||
#include "VMapDefinitions.h"
|
||||
#include "WorldModel.h"
|
||||
#include <G3D/Ray.h>
|
||||
#include <G3D/Vector3.h>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
44
src/common/Threading/AchievPoolMgr.cpp
Normal file
44
src/common/Threading/AchievPoolMgr.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "AchievPoolMgr.hpp"
|
||||
|
||||
namespace Trinity {
|
||||
|
||||
AchievPoolMgr::AchievPoolMgr()
|
||||
: requestCount_(0)
|
||||
{ }
|
||||
|
||||
void AchievPoolMgr::start(std::size_t numThreads)
|
||||
{
|
||||
threads_.reserve(numThreads);
|
||||
for (std::size_t i = 0; i < numThreads; ++i)
|
||||
threads_.emplace_back(&AchievPoolMgr::threadFunc, this);
|
||||
}
|
||||
|
||||
void AchievPoolMgr::stop()
|
||||
{
|
||||
if (!queue_.frozen()) {
|
||||
queue_.freeze();
|
||||
for (auto &t : threads_)
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
|
||||
void AchievPoolMgr::wait()
|
||||
{
|
||||
GuardType guard(lock_);
|
||||
waitCond_.wait(guard, [this] { return requestCount_ == 0; });
|
||||
}
|
||||
|
||||
void AchievPoolMgr::threadFunc()
|
||||
{
|
||||
cds::threading::Manager::attachThread();
|
||||
FunctorType f;
|
||||
while (queue_.pop(f)) {
|
||||
f();
|
||||
GuardType g(lock_);
|
||||
if (--requestCount_ == 0)
|
||||
waitCond_.notify_all();
|
||||
}
|
||||
cds::threading::Manager::detachThread();
|
||||
}
|
||||
|
||||
} // namespace Trinity
|
||||
71
src/common/Threading/AchievPoolMgr.hpp
Normal file
71
src/common/Threading/AchievPoolMgr.hpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#ifndef TRINITY_SHARED_ACHIEV_POOL_MGR_HPP
|
||||
#define TRINITY_SHARED_ACHIEV_POOL_MGR_HPP
|
||||
|
||||
#include "SynchronizedQueue.hpp"
|
||||
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <cds/init.h>
|
||||
#include <cds/gc/hp.h>
|
||||
|
||||
namespace Trinity {
|
||||
|
||||
class AchievPoolMgr final
|
||||
{
|
||||
typedef std::mutex LockType;
|
||||
|
||||
typedef std::unique_lock<LockType> GuardType;
|
||||
|
||||
typedef std::function<void()> FunctorType;
|
||||
|
||||
typedef Trinity::SynchronizedQueue<FunctorType> QueueType;
|
||||
|
||||
private:
|
||||
AchievPoolMgr();
|
||||
|
||||
public:
|
||||
static AchievPoolMgr * instance()
|
||||
{
|
||||
static AchievPoolMgr mgr;
|
||||
return &mgr;
|
||||
}
|
||||
|
||||
void start(std::size_t numThreads);
|
||||
|
||||
void stop();
|
||||
|
||||
template <typename RequestType>
|
||||
void schedule(RequestType request)
|
||||
{
|
||||
GuardType g(lock_);
|
||||
if (queue_.push(std::move(request)))
|
||||
++requestCount_;
|
||||
}
|
||||
|
||||
void wait();
|
||||
|
||||
private:
|
||||
void threadFunc();
|
||||
|
||||
QueueType queue_;
|
||||
|
||||
std::vector<std::thread> threads_;
|
||||
|
||||
int requestCount_;
|
||||
|
||||
LockType lock_;
|
||||
|
||||
std::condition_variable waitCond_;
|
||||
};
|
||||
|
||||
} // namespace Trinity
|
||||
|
||||
#define sAchievPoolMgr Trinity::AchievPoolMgr::instance()
|
||||
|
||||
#endif // TRINITY_SHARED_THREAD_POOL_MGR_HPP
|
||||
556
src/common/Threading/LockedMap.h
Normal file
556
src/common/Threading/LockedMap.h
Normal file
@@ -0,0 +1,556 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 /dev/rsa for MangosR2 <http://github.com/MangosR2>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/* written for use instead not locked std::map */
|
||||
|
||||
#ifndef LOCKEDMAP_H
|
||||
#define LOCKEDMAP_H
|
||||
|
||||
#include "Common.h"
|
||||
#include <map>
|
||||
#include <assert.h>
|
||||
|
||||
namespace Trinity
|
||||
{
|
||||
template <class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator<std::pair<const Key,T> > >
|
||||
class LockedMap
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::mutex LockType;
|
||||
typedef std::lock_guard<LockType> LockGuard;
|
||||
typedef LockGuard ReadGuard;
|
||||
typedef LockGuard WriteGuard;
|
||||
|
||||
typedef typename std::map<Key, T, Compare, Allocator>::iterator iterator;
|
||||
typedef typename std::map<Key, T, Compare, Allocator>::const_iterator const_iterator;
|
||||
typedef typename std::map<Key, T, Compare, Allocator>::reverse_iterator reverse_iterator;
|
||||
typedef typename std::map<Key, T, Compare, Allocator>::const_reverse_iterator const_reverse_iterator;
|
||||
typedef typename std::map<Key, T, Compare, Allocator>::allocator_type allocator_type;
|
||||
typedef typename std::map<Key, T, Compare, Allocator>::value_type value_type;
|
||||
typedef typename std::map<Key, T, Compare, Allocator>::size_type size_type;
|
||||
typedef typename std::map<Key, T, Compare, Allocator>::key_compare key_compare;
|
||||
typedef typename std::map<Key, T, Compare, Allocator>::value_compare value_compare;
|
||||
|
||||
// Constructors
|
||||
explicit LockedMap(const Compare& comp = Compare(), const Allocator& alloc = Allocator()) : m_storage(comp, alloc)
|
||||
{}
|
||||
|
||||
template <class InputIterator> LockedMap(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& alloc = Allocator())
|
||||
: m_storage(first, last, comp, alloc)
|
||||
{}
|
||||
|
||||
LockedMap(const LockedMap<Key, T, Compare, Allocator> & x) : m_storage(x.m_storage)
|
||||
{}
|
||||
|
||||
// Destructor
|
||||
virtual ~LockedMap(void)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
}
|
||||
|
||||
// Copy
|
||||
LockedMap<Key, Compare, Allocator>& operator= (const LockedMap<Key, Compare, Allocator>& x)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
ReadGuard GuardX(x.GetLock());
|
||||
m_storage = x.m_storage;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Iterators
|
||||
iterator begin()
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.begin();
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.end();
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.begin();
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.end();
|
||||
}
|
||||
|
||||
reverse_iterator rbegin()
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.rbegin();
|
||||
}
|
||||
|
||||
reverse_iterator rend()
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.rend();
|
||||
}
|
||||
|
||||
const_reverse_iterator rbegin() const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.rbegin();
|
||||
}
|
||||
|
||||
const_reverse_iterator rend() const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.rend();
|
||||
}
|
||||
|
||||
// Capacity
|
||||
size_type size(void) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.size();
|
||||
}
|
||||
|
||||
size_type max_size(void) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.max_size();
|
||||
}
|
||||
|
||||
bool empty(void) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.empty();
|
||||
}
|
||||
|
||||
// Access
|
||||
T& operator[](const Key& x)
|
||||
{
|
||||
if (find(x) == end())
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
return m_storage[x];
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage[x];
|
||||
}
|
||||
}
|
||||
|
||||
const T& operator[](const Key& x) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage[x];
|
||||
}
|
||||
|
||||
// Modifiers
|
||||
std::pair<iterator, bool> insert(const value_type& x)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
return m_storage.insert(x);
|
||||
}
|
||||
|
||||
iterator insert(iterator position, const value_type& x)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
return m_storage.insert(position, x);
|
||||
}
|
||||
|
||||
template <class InputIterator> void insert(InputIterator first, InputIterator last)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
m_storage.insert(first, last);
|
||||
}
|
||||
|
||||
void erase(iterator pos)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
m_storage.erase(pos);
|
||||
}
|
||||
|
||||
size_type erase(const Key& x)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
return m_storage.erase(x);
|
||||
}
|
||||
|
||||
void erase(iterator begin, iterator end)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
m_storage.erase(begin, end);
|
||||
}
|
||||
|
||||
void swap(LockedMap<Key, T, Compare, Allocator>& x) noexcept
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
WriteGuard GuardX(x.GetLock());
|
||||
m_storage.swap(x.storage);
|
||||
}
|
||||
|
||||
void clear(void)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
m_storage.clear();
|
||||
}
|
||||
|
||||
// Observers
|
||||
key_compare key_comp(void) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.key_comp();
|
||||
}
|
||||
|
||||
value_compare value_comp(void) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.value_comp();
|
||||
}
|
||||
|
||||
// Operations
|
||||
const_iterator find(const Key& x) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.find(x);
|
||||
}
|
||||
|
||||
iterator find(const Key& x)
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.find(x);
|
||||
}
|
||||
|
||||
size_type count(const Key& x) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.count(x);
|
||||
}
|
||||
|
||||
const_iterator lower_bound(const Key& x) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.lower_bound(x);
|
||||
}
|
||||
|
||||
iterator lower_bound(const Key& x)
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.lower_bound(x);
|
||||
}
|
||||
|
||||
const_iterator upper_bound(const Key& x) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.upper_bound(x);
|
||||
}
|
||||
|
||||
iterator upper_bound(const Key& x)
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.upper_bound(x);
|
||||
}
|
||||
|
||||
std::pair<const_iterator, const_iterator> equal_range(const Key& x) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.equal_range(x);
|
||||
}
|
||||
|
||||
std::pair<iterator, iterator> equal_range(const Key& x)
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.equal_range(x);
|
||||
}
|
||||
|
||||
// Allocator
|
||||
allocator_type get_allocator(void) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.get_allocator();
|
||||
}
|
||||
|
||||
LockType& GetLock() { return i_lock; }
|
||||
LockType& GetLock() const { return i_lock; }
|
||||
|
||||
// may be used _ONLY_ with external locking!
|
||||
std::map<Key, T>& getSource()
|
||||
{
|
||||
return m_storage;
|
||||
}
|
||||
|
||||
protected:
|
||||
mutable LockType i_lock;
|
||||
std::map<Key, T, Compare, Allocator> m_storage;
|
||||
};
|
||||
|
||||
template <class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator<std::pair<const Key,T> > >
|
||||
class LockedMultiMap
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::mutex LockType;
|
||||
typedef std::lock_guard<LockType> LockGuard;
|
||||
typedef LockGuard ReadGuard;
|
||||
typedef LockGuard WriteGuard;
|
||||
|
||||
typedef typename std::multimap<Key, T, Compare, Allocator>::iterator iterator;
|
||||
typedef typename std::multimap<Key, T, Compare, Allocator>::const_iterator const_iterator;
|
||||
typedef typename std::multimap<Key, T, Compare, Allocator>::reverse_iterator reverse_iterator;
|
||||
typedef typename std::multimap<Key, T, Compare, Allocator>::const_reverse_iterator const_reverse_iterator;
|
||||
typedef typename std::multimap<Key, T, Compare, Allocator>::allocator_type allocator_type;
|
||||
typedef typename std::multimap<Key, T, Compare, Allocator>::value_type value_type;
|
||||
typedef typename std::multimap<Key, T, Compare, Allocator>::size_type size_type;
|
||||
typedef typename std::multimap<Key, T, Compare, Allocator>::key_compare key_compare;
|
||||
typedef typename std::multimap<Key, T, Compare, Allocator>::value_compare value_compare;
|
||||
|
||||
// Constructors
|
||||
explicit LockedMultiMap(const Compare& comp = Compare(), const Allocator& alloc = Allocator()) : m_storage(comp, alloc)
|
||||
{}
|
||||
|
||||
template <class InputIterator> LockedMultiMap(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& alloc = Allocator())
|
||||
: m_storage(first, last, comp, alloc)
|
||||
{}
|
||||
|
||||
LockedMultiMap(const LockedMap<Key, T, Compare, Allocator> & x) : m_storage(x.m_storage)
|
||||
{}
|
||||
|
||||
// Destructor
|
||||
virtual ~LockedMultiMap(void)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
}
|
||||
|
||||
// Copy
|
||||
LockedMultiMap<Key, Compare, Allocator>& operator= (const LockedMultiMap<Key, Compare, Allocator>& x)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
ReadGuard GuardX(x.GetLock());
|
||||
m_storage = x.m_storage;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Iterators
|
||||
iterator begin()
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.begin();
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.end();
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.begin();
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.end();
|
||||
}
|
||||
|
||||
reverse_iterator rbegin()
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.rbegin();
|
||||
}
|
||||
|
||||
reverse_iterator rend()
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.rend();
|
||||
}
|
||||
|
||||
const_reverse_iterator rbegin() const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.rbegin();
|
||||
}
|
||||
|
||||
const_reverse_iterator rend() const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.rend();
|
||||
}
|
||||
|
||||
// Capacity
|
||||
size_type size(void) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.size();
|
||||
}
|
||||
|
||||
size_type max_size(void) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.max_size();
|
||||
}
|
||||
|
||||
bool empty(void) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.empty();
|
||||
}
|
||||
|
||||
// Modifiers
|
||||
std::pair<iterator, bool> insert(const value_type& x)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
return m_storage.insert(x);
|
||||
}
|
||||
|
||||
iterator insert(iterator position, const value_type& x)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
return m_storage.insert(position, x);
|
||||
}
|
||||
|
||||
template <class InputIterator> void insert(InputIterator first, InputIterator last)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
m_storage.insert(first, last);
|
||||
}
|
||||
|
||||
void erase(iterator pos)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
m_storage.erase(pos);
|
||||
}
|
||||
|
||||
size_type erase(const Key& x)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
return m_storage.erase(x);
|
||||
}
|
||||
|
||||
void erase(iterator begin, iterator end)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
m_storage.erase(begin, end);
|
||||
}
|
||||
|
||||
void swap(LockedMap<Key, T, Compare, Allocator>& x)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
WriteGuard GuardX(x.GetLock());
|
||||
m_storage.swap(x.storage);
|
||||
}
|
||||
|
||||
void clear(void)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
m_storage.clear();
|
||||
}
|
||||
|
||||
// Observers
|
||||
key_compare key_comp(void) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.key_comp();
|
||||
}
|
||||
|
||||
value_compare value_comp(void) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.value_comp();
|
||||
}
|
||||
|
||||
// Operations
|
||||
const_iterator find(const Key& x) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.find(x);
|
||||
}
|
||||
|
||||
iterator find(const Key& x)
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.find(x);
|
||||
}
|
||||
|
||||
size_type count(const Key& x) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.count(x);
|
||||
}
|
||||
|
||||
const_iterator lower_bound(const Key& x) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.lower_bound(x);
|
||||
}
|
||||
|
||||
iterator lower_bound(const Key& x)
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.lower_bound(x);
|
||||
}
|
||||
|
||||
const_iterator upper_bound(const Key& x) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.upper_bound(x);
|
||||
}
|
||||
|
||||
iterator upper_bound(const Key& x)
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.upper_bound(x);
|
||||
}
|
||||
|
||||
std::pair<const_iterator, const_iterator> equal_range(const Key& x) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.equal_range(x);
|
||||
}
|
||||
|
||||
std::pair<iterator, iterator> equal_range(const Key& x)
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.equal_range(x);
|
||||
}
|
||||
|
||||
// Allocator
|
||||
allocator_type get_allocator(void) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.get_allocator();
|
||||
}
|
||||
|
||||
LockType& GetLock() { return i_lock; }
|
||||
LockType& GetLock() const { return i_lock; }
|
||||
|
||||
// may be used _ONLY_ with external locking!
|
||||
std::multimap<Key, T>& getSource()
|
||||
{
|
||||
return m_storage;
|
||||
}
|
||||
|
||||
protected:
|
||||
mutable LockType i_lock;
|
||||
std::multimap<Key, T, Compare, Allocator> m_storage;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
158
src/common/Threading/LockedQueue.h
Normal file
158
src/common/Threading/LockedQueue.h
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOCKEDQUEUE_H
|
||||
#define LOCKEDQUEUE_H
|
||||
|
||||
#include <deque>
|
||||
#include <mutex>
|
||||
|
||||
template <class T, typename StorageType = std::deque<T> >
|
||||
class LockedQueue
|
||||
{
|
||||
//! Lock access to the queue.
|
||||
std::mutex _lock;
|
||||
|
||||
//! Storage backing the queue.
|
||||
StorageType _queue;
|
||||
|
||||
//! Cancellation flag.
|
||||
volatile bool _canceled;
|
||||
|
||||
public:
|
||||
|
||||
//! Create a LockedQueue.
|
||||
LockedQueue()
|
||||
: _canceled(false)
|
||||
{
|
||||
}
|
||||
|
||||
//! Destroy a LockedQueue.
|
||||
virtual ~LockedQueue()
|
||||
{
|
||||
}
|
||||
|
||||
//! Adds an item to the queue.
|
||||
void add(const T& item)
|
||||
{
|
||||
lock();
|
||||
|
||||
_queue.push_back(item);
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
//! Adds items back to front of the queue
|
||||
template<class Iterator>
|
||||
void readd(Iterator begin, Iterator end)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
_queue.insert(_queue.begin(), begin, end);
|
||||
}
|
||||
|
||||
//! Gets the next result in the queue, if any.
|
||||
bool next(T& result)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
|
||||
if (_queue.empty())
|
||||
return false;
|
||||
|
||||
result = _queue.front();
|
||||
_queue.pop_front();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Checker>
|
||||
bool next(T& result, Checker& check)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
|
||||
if (_queue.empty())
|
||||
return false;
|
||||
|
||||
result = _queue.front();
|
||||
if (!check.Process(result))
|
||||
return false;
|
||||
|
||||
_queue.pop_front();
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Peeks at the top of the queue. Check if the queue is empty before calling! Remember to unlock after use if autoUnlock == false.
|
||||
T& peek(bool autoUnlock = false)
|
||||
{
|
||||
lock();
|
||||
|
||||
T& result = _queue.front();
|
||||
|
||||
if (autoUnlock)
|
||||
unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//! Cancels the queue.
|
||||
void cancel()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
|
||||
_canceled = true;
|
||||
}
|
||||
|
||||
//! Checks if the queue is cancelled.
|
||||
bool cancelled()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
return _canceled;
|
||||
}
|
||||
|
||||
//! Locks the queue for access.
|
||||
void lock()
|
||||
{
|
||||
this->_lock.lock();
|
||||
}
|
||||
|
||||
//! Unlocks the queue.
|
||||
void unlock()
|
||||
{
|
||||
this->_lock.unlock();
|
||||
}
|
||||
|
||||
///! Calls pop_front of the queue
|
||||
void pop_front()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
_queue.pop_front();
|
||||
}
|
||||
|
||||
///! Checks if we're empty or not with locks held
|
||||
bool empty()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
return _queue.empty();
|
||||
}
|
||||
|
||||
uint32 size()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
return _queue.size();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
354
src/common/Threading/LockedVector.h
Normal file
354
src/common/Threading/LockedVector.h
Normal file
@@ -0,0 +1,354 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 /dev/rsa for MangosR2 <http://github.com/MangosR2>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* based on LockedQueue class from MaNGOS */
|
||||
/* written for use instead not locked std::list && std::vector */
|
||||
|
||||
#ifndef LOCKEDVECTOR_H
|
||||
#define LOCKEDVECTOR_H
|
||||
|
||||
#include "Common.h"
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <assert.h>
|
||||
|
||||
namespace Trinity
|
||||
{
|
||||
template <class T, class Allocator = std::allocator<T> >
|
||||
class LockedVector
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::mutex LockType;
|
||||
typedef std::lock_guard<LockType> LockGuard;
|
||||
typedef LockGuard ReadGuard;
|
||||
typedef LockGuard WriteGuard;
|
||||
|
||||
typedef typename std::vector<T, Allocator>::iterator iterator;
|
||||
typedef typename std::vector<T, Allocator>::const_iterator const_iterator;
|
||||
typedef typename std::vector<T, Allocator>::reverse_iterator reverse_iterator;
|
||||
typedef typename std::vector<T, Allocator>::const_reverse_iterator const_reverse_iterator;
|
||||
typedef typename std::vector<T, Allocator>::allocator_type allocator_type;
|
||||
typedef typename std::vector<T, Allocator>::value_type value_type;
|
||||
typedef typename std::vector<T, Allocator>::size_type size_type;
|
||||
typedef typename std::vector<T, Allocator>::difference_type difference_type;
|
||||
|
||||
//Constructors
|
||||
explicit LockedVector(const Allocator& alloc = Allocator()) : m_storage(alloc)
|
||||
{}
|
||||
|
||||
explicit LockedVector(size_type n, const T& value = T(), const Allocator& alloc = Allocator())
|
||||
: m_storage(n, value, alloc)
|
||||
{}
|
||||
|
||||
virtual ~LockedVector(void)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
}
|
||||
|
||||
void reserve(size_type idx)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
m_storage.reserve(idx);
|
||||
}
|
||||
|
||||
// Methods
|
||||
void push_back(const T& item)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
m_storage.push_back(item);
|
||||
}
|
||||
|
||||
void insert(iterator pos, size_type n, const T& u)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
m_storage.insert(pos, n, u);
|
||||
}
|
||||
|
||||
template <class InputIterator>
|
||||
void insert(iterator pos, InputIterator begin, InputIterator end)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
m_storage.insert(pos, begin, end);
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
m_storage.pop_back();
|
||||
}
|
||||
|
||||
void erase(size_type pos)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
m_storage.erase(m_storage.begin() + pos);
|
||||
}
|
||||
|
||||
iterator erase(iterator itr)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
return m_storage.erase(itr);
|
||||
}
|
||||
|
||||
void remove(const T& item)
|
||||
{
|
||||
erase(item);
|
||||
}
|
||||
|
||||
void erase(const T& item)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
for (size_type i = 0; i < m_storage.size();)
|
||||
{
|
||||
if (item == m_storage[i])
|
||||
m_storage.erase(m_storage.begin() + i);
|
||||
else
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
T* find(const T& item)
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
for (size_type i = 0; i < m_storage.size(); ++i)
|
||||
{
|
||||
if (item == m_storage[i])
|
||||
return &m_storage[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const T* find(const T& item) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
for (size_type i = 0; i < m_storage.size(); ++i)
|
||||
{
|
||||
if (item == m_storage[i])
|
||||
return &m_storage[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
m_storage.clear();
|
||||
}
|
||||
|
||||
T& operator[](size_type idx)
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage[idx];
|
||||
}
|
||||
|
||||
const T& operator[](size_type idx) const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage[idx];
|
||||
}
|
||||
|
||||
T& at(size_type idx)
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.at(idx);
|
||||
}
|
||||
|
||||
T& front()
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.front();
|
||||
}
|
||||
|
||||
T& back()
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.back();
|
||||
}
|
||||
|
||||
const T& front() const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.front();
|
||||
}
|
||||
|
||||
const T& back() const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.back();
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.begin();
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.end();
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.begin();
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.end();
|
||||
}
|
||||
|
||||
reverse_iterator rbegin()
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.rbegin();
|
||||
}
|
||||
|
||||
reverse_iterator rend()
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.rend();
|
||||
}
|
||||
|
||||
const_reverse_iterator rbegin() const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.rbegin();
|
||||
}
|
||||
|
||||
const_reverse_iterator rend() const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.rend();
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.empty();
|
||||
}
|
||||
|
||||
size_type size() const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.size();
|
||||
}
|
||||
|
||||
LockedVector& operator=(const std::vector<T> &v)
|
||||
{
|
||||
clear();
|
||||
WriteGuard Guard(GetLock());
|
||||
for (typename std::vector<T>::const_iterator i = v.begin(); i != v.end(); ++i)
|
||||
{
|
||||
this->push_back(*i);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
LockedVector(const std::vector<T> &v)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
for (typename std::vector<T>::const_iterator i = v.begin(); i != v.end(); ++i)
|
||||
{
|
||||
this->push_back(*i);
|
||||
}
|
||||
}
|
||||
|
||||
LockedVector& operator=(const std::list<T> &v)
|
||||
{
|
||||
clear();
|
||||
WriteGuard Guard(GetLock());
|
||||
for (typename std::list<T>::const_iterator i = v.begin(); i != v.end(); ++i)
|
||||
{
|
||||
this->push_back(*i);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
LockedVector(const std::list<T> &v)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
for (typename std::list<T>::const_iterator i = v.begin(); i != v.end(); ++i)
|
||||
{
|
||||
this->push_back(*i);
|
||||
}
|
||||
}
|
||||
|
||||
LockedVector& operator=(const LockedVector<T> &v)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
ReadGuard GuardX(v.GetLock());
|
||||
m_storage = v.m_storage;
|
||||
return *this;
|
||||
}
|
||||
|
||||
LockedVector(const LockedVector<T> &v)
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
ReadGuard GuardX(v.GetLock());
|
||||
m_storage = v.m_storage;
|
||||
}
|
||||
|
||||
void swap(LockedVector<T, Allocator>& x) noexcept
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
WriteGuard GuardX(x.GetLock());
|
||||
m_storage.swap(x.m_storage);
|
||||
}
|
||||
|
||||
void resize(size_type num, T def = T())
|
||||
{
|
||||
WriteGuard Guard(GetLock());
|
||||
m_storage.resize(num, def);
|
||||
}
|
||||
|
||||
//Allocator
|
||||
allocator_type get_allocator() const
|
||||
{
|
||||
ReadGuard Guard(GetLock());
|
||||
return m_storage.get_allocator();
|
||||
}
|
||||
|
||||
// Sort template
|
||||
template <typename C>
|
||||
void sort(C& compare)
|
||||
{
|
||||
iterator _begin = begin();
|
||||
iterator _end = end();
|
||||
WriteGuard Guard(GetLock());
|
||||
std::stable_sort(_begin, _end, compare);
|
||||
}
|
||||
|
||||
LockType& GetLock() { return i_lock; }
|
||||
LockType& GetLock() const { return i_lock; }
|
||||
|
||||
// may be used _ONLY_ with external locking!
|
||||
std::vector<T>& getSource()
|
||||
{
|
||||
return m_storage;
|
||||
}
|
||||
|
||||
protected:
|
||||
mutable LockType i_lock;
|
||||
std::vector<T, Allocator> m_storage;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
100
src/common/Threading/ProcessPriority.h
Normal file
100
src/common/Threading/ProcessPriority.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _PROCESSPRIO_H
|
||||
#define _PROCESSPRIO_H
|
||||
|
||||
#include "Configuration/Config.h"
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sched.h>
|
||||
#include <sys/resource.h>
|
||||
#define PROCESS_HIGH_PRIORITY -15 // [-20, 19], default is 0
|
||||
#endif
|
||||
|
||||
void SetProcessPriority(const std::string /*logChannel*/)
|
||||
{
|
||||
#if defined(_WIN32) || defined(__linux__)
|
||||
|
||||
///- Handle affinity for multiple processors and process priority
|
||||
uint32 affinity = sConfigMgr->GetIntDefault("UseProcessors", 0);
|
||||
bool highPriority = sConfigMgr->GetBoolDefault("ProcessPriority", false);
|
||||
|
||||
#ifdef _WIN32 // Windows
|
||||
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
if (affinity > 0)
|
||||
{
|
||||
ULONG_PTR appAff;
|
||||
ULONG_PTR sysAff;
|
||||
|
||||
if (GetProcessAffinityMask(hProcess, &appAff, &sysAff))
|
||||
{
|
||||
// remove non accessible processors
|
||||
ULONG_PTR currentAffinity = affinity & appAff;
|
||||
|
||||
if (!currentAffinity)
|
||||
TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Processors marked in UseProcessors bitmask (hex) %x are not accessible. Accessible processors bitmask (hex): %x", affinity, appAff);
|
||||
else if (SetProcessAffinityMask(hProcess, currentAffinity))
|
||||
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Using processors (bitmask, hex): %x", currentAffinity);
|
||||
else
|
||||
TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Can't set used processors (hex): %x", currentAffinity);
|
||||
}
|
||||
}
|
||||
|
||||
if (highPriority)
|
||||
{
|
||||
if (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS))
|
||||
TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Process priority class set to HIGH");
|
||||
else
|
||||
TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Can't set process priority class.");
|
||||
}
|
||||
|
||||
#else // Linux
|
||||
|
||||
if (affinity > 0)
|
||||
{
|
||||
cpu_set_t mask;
|
||||
CPU_ZERO(&mask);
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(affinity) * 8; ++i)
|
||||
if (affinity & (1 << i))
|
||||
CPU_SET(i, &mask);
|
||||
|
||||
if (sched_setaffinity(0, sizeof(mask), &mask))
|
||||
TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Can't set used processors (hex): %x, error: %s", affinity, strerror(errno));
|
||||
else
|
||||
{
|
||||
CPU_ZERO(&mask);
|
||||
sched_getaffinity(0, sizeof(mask), &mask);
|
||||
TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Using processors (bitmask, hex): %lx", *(__cpu_mask*)(&mask));
|
||||
}
|
||||
}
|
||||
|
||||
if (highPriority)
|
||||
{
|
||||
if (setpriority(PRIO_PROCESS, 0, PROCESS_HIGH_PRIORITY))
|
||||
TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Can't set process priority class, error: %s", strerror(errno));
|
||||
else
|
||||
TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, "Process priority class set to %i", getpriority(PRIO_PROCESS, 0));
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
109
src/common/Threading/ProducerConsumerQueue.h
Normal file
109
src/common/Threading/ProducerConsumerQueue.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _PCQ_H
|
||||
#define _PCQ_H
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <atomic>
|
||||
#include <type_traits>
|
||||
|
||||
template <typename T>
|
||||
class ProducerConsumerQueue
|
||||
{
|
||||
std::mutex _queueLock;
|
||||
std::queue<T> _queue;
|
||||
std::condition_variable _condition;
|
||||
std::atomic<bool> _shutdown;
|
||||
|
||||
public:
|
||||
|
||||
ProducerConsumerQueue<T>() : _shutdown(false) { }
|
||||
|
||||
void Push(const T& value)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_queueLock);
|
||||
_queue.push(std::move(value));
|
||||
|
||||
_condition.notify_one();
|
||||
}
|
||||
|
||||
bool Empty()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_queueLock);
|
||||
|
||||
return _queue.empty();
|
||||
}
|
||||
|
||||
bool Pop(T& value)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_queueLock);
|
||||
|
||||
if (_queue.empty() || _shutdown)
|
||||
return false;
|
||||
|
||||
value = _queue.front();
|
||||
|
||||
_queue.pop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WaitAndPop(T& value)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_queueLock);
|
||||
|
||||
while (_queue.empty() && !_shutdown)
|
||||
_condition.wait(lock);
|
||||
|
||||
if (_queue.empty() || _shutdown)
|
||||
return;
|
||||
|
||||
value = _queue.front();
|
||||
|
||||
_queue.pop();
|
||||
}
|
||||
|
||||
void Cancel()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(_queueLock);
|
||||
|
||||
while (!_queue.empty())
|
||||
{
|
||||
T& value = _queue.front();
|
||||
|
||||
DeleteQueuedObject(value);
|
||||
|
||||
_queue.pop();
|
||||
}
|
||||
|
||||
_shutdown = true;
|
||||
|
||||
_condition.notify_all();
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename E = T>
|
||||
typename std::enable_if<std::is_pointer<E>::value>::type DeleteQueuedObject(E& obj) { delete obj; }
|
||||
|
||||
template<typename E = T>
|
||||
typename std::enable_if<!std::is_pointer<E>::value>::type DeleteQueuedObject(E const& /*packet*/) { }
|
||||
};
|
||||
|
||||
#endif
|
||||
84
src/common/Threading/SynchronizedQueue.hpp
Normal file
84
src/common/Threading/SynchronizedQueue.hpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#ifndef TRINITY_SHARED_SYNCHRONIZED_QUEUE_HPP
|
||||
#define TRINITY_SHARED_SYNCHRONIZED_QUEUE_HPP
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <deque>
|
||||
#include <mutex>
|
||||
|
||||
namespace Trinity {
|
||||
|
||||
template <typename T>
|
||||
class SynchronizedQueue
|
||||
{
|
||||
typedef std::deque<T> QueueType;
|
||||
|
||||
public:
|
||||
SynchronizedQueue()
|
||||
: frozen_(false)
|
||||
{ }
|
||||
|
||||
bool frozen() const
|
||||
{
|
||||
return frozen_.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
void freeze()
|
||||
{
|
||||
frozen_.store(true, std::memory_order_release);
|
||||
waitCond_.notify_all();
|
||||
}
|
||||
|
||||
bool push(T data)
|
||||
{
|
||||
if (frozen())
|
||||
return false;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
queue_.push_back(std::move(data));
|
||||
}
|
||||
|
||||
waitCond_.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pop(T &data)
|
||||
{
|
||||
if (frozen())
|
||||
return false;
|
||||
|
||||
std::unique_lock<std::mutex> guard(mutex_);
|
||||
waitCond_.wait(guard, [this] { return frozen() || !queue_.empty(); });
|
||||
|
||||
if (frozen())
|
||||
return false;
|
||||
|
||||
data = std::move(queue_.front());
|
||||
queue_.pop_front();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool try_pop(T &data)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
|
||||
if (queue_.empty())
|
||||
return false;
|
||||
|
||||
data = queue_.front();
|
||||
queue_.pop_front();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
QueueType queue_;
|
||||
std::atomic<bool> frozen_;
|
||||
std::mutex mutex_;
|
||||
std::condition_variable waitCond_;
|
||||
};
|
||||
|
||||
} // namespace Trinity
|
||||
|
||||
#endif // TRINITY_SHARED_SYNCHRONIZED_QUEUE_HPP
|
||||
44
src/common/Threading/ThreadPoolMgr.cpp
Normal file
44
src/common/Threading/ThreadPoolMgr.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "ThreadPoolMgr.hpp"
|
||||
|
||||
namespace Trinity {
|
||||
|
||||
ThreadPoolMgr::ThreadPoolMgr()
|
||||
: requestCount_(0)
|
||||
{ }
|
||||
|
||||
void ThreadPoolMgr::start(std::size_t numThreads)
|
||||
{
|
||||
threads_.reserve(numThreads);
|
||||
for (std::size_t i = 0; i < numThreads; ++i)
|
||||
threads_.emplace_back(&ThreadPoolMgr::threadFunc, this);
|
||||
}
|
||||
|
||||
void ThreadPoolMgr::stop()
|
||||
{
|
||||
if (!queue_.frozen()) {
|
||||
queue_.freeze();
|
||||
for (auto &t : threads_)
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadPoolMgr::wait()
|
||||
{
|
||||
GuardType guard(lock_);
|
||||
waitCond_.wait(guard, [this] { return requestCount_ == 0; });
|
||||
}
|
||||
|
||||
void ThreadPoolMgr::threadFunc()
|
||||
{
|
||||
cds::threading::Manager::attachThread();
|
||||
FunctorType f;
|
||||
while (queue_.pop(f)) {
|
||||
f();
|
||||
GuardType g(lock_);
|
||||
if (--requestCount_ == 0)
|
||||
waitCond_.notify_all();
|
||||
}
|
||||
cds::threading::Manager::detachThread();
|
||||
}
|
||||
|
||||
} // namespace Trinity
|
||||
71
src/common/Threading/ThreadPoolMgr.hpp
Normal file
71
src/common/Threading/ThreadPoolMgr.hpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#ifndef TRINITY_SHARED_THREAD_POOL_MGR_HPP
|
||||
#define TRINITY_SHARED_THREAD_POOL_MGR_HPP
|
||||
|
||||
#include "SynchronizedQueue.hpp"
|
||||
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <cds/init.h>
|
||||
#include <cds/gc/hp.h>
|
||||
|
||||
namespace Trinity {
|
||||
|
||||
class ThreadPoolMgr final
|
||||
{
|
||||
typedef std::mutex LockType;
|
||||
|
||||
typedef std::unique_lock<LockType> GuardType;
|
||||
|
||||
typedef std::function<void()> FunctorType;
|
||||
|
||||
typedef Trinity::SynchronizedQueue<FunctorType> QueueType;
|
||||
|
||||
private:
|
||||
ThreadPoolMgr();
|
||||
|
||||
public:
|
||||
static ThreadPoolMgr * instance()
|
||||
{
|
||||
static ThreadPoolMgr mgr;
|
||||
return &mgr;
|
||||
}
|
||||
|
||||
void start(std::size_t numThreads);
|
||||
|
||||
void stop();
|
||||
|
||||
template <typename RequestType>
|
||||
void schedule(RequestType request)
|
||||
{
|
||||
GuardType g(lock_);
|
||||
if (queue_.push(std::move(request)))
|
||||
++requestCount_;
|
||||
}
|
||||
|
||||
void wait();
|
||||
|
||||
private:
|
||||
void threadFunc();
|
||||
|
||||
QueueType queue_;
|
||||
|
||||
std::vector<std::thread> threads_;
|
||||
|
||||
int requestCount_;
|
||||
|
||||
LockType lock_;
|
||||
|
||||
std::condition_variable waitCond_;
|
||||
};
|
||||
|
||||
} // namespace Trinity
|
||||
|
||||
#define sThreadPoolMgr Trinity::ThreadPoolMgr::instance()
|
||||
|
||||
#endif // TRINITY_SHARED_THREAD_POOL_MGR_HPP
|
||||
68
src/common/Utilities/AsioHacksFwd.h
Normal file
68
src/common/Utilities/AsioHacksFwd.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef AsioHacksFwd_h__
|
||||
#define AsioHacksFwd_h__
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace posix_time
|
||||
{
|
||||
class ptime;
|
||||
}
|
||||
|
||||
namespace asio
|
||||
{
|
||||
namespace ip
|
||||
{
|
||||
class address;
|
||||
|
||||
class tcp;
|
||||
|
||||
template <typename InternetProtocol>
|
||||
class basic_endpoint;
|
||||
|
||||
typedef basic_endpoint<tcp> tcp_endpoint;
|
||||
|
||||
template <typename InternetProtocol>
|
||||
class resolver_service;
|
||||
|
||||
template <typename InternetProtocol, typename ResolverService>
|
||||
class basic_resolver;
|
||||
|
||||
typedef basic_resolver<tcp, resolver_service<tcp>> tcp_resolver;
|
||||
}
|
||||
|
||||
template <typename Time>
|
||||
struct time_traits;
|
||||
|
||||
template <typename TimeType, typename TimeTraits>
|
||||
class deadline_timer_service;
|
||||
|
||||
template <typename Time, typename TimeTraits, typename TimerService>
|
||||
class basic_deadline_timer;
|
||||
|
||||
typedef basic_deadline_timer<posix_time::ptime, time_traits<posix_time::ptime>, deadline_timer_service<posix_time::ptime, time_traits<posix_time::ptime>>> deadline_timer;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Trinity
|
||||
{
|
||||
class AsioStrand;
|
||||
}
|
||||
|
||||
#endif // AsioHacksFwd_h__
|
||||
32
src/common/Utilities/AsioHacksImpl.h
Normal file
32
src/common/Utilities/AsioHacksImpl.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef AsioHacksImpl_h__
|
||||
#define AsioHacksImpl_h__
|
||||
|
||||
#include <boost/asio/strand.hpp>
|
||||
|
||||
namespace Trinity
|
||||
{
|
||||
class AsioStrand : public boost::asio::io_service::strand
|
||||
{
|
||||
public:
|
||||
explicit AsioStrand(boost::asio::io_service& io_service) : boost::asio::io_service::strand(io_service) { }
|
||||
};
|
||||
}
|
||||
|
||||
#endif // AsioHacksImpl_h__
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user