diff options
Diffstat (limited to 'src/common')
51 files changed, 876 insertions, 750 deletions
diff --git a/src/common/Collision/Management/MMapManager.cpp b/src/common/Collision/Management/MMapManager.cpp index 3e57c095eb1..6065763aa60 100644 --- a/src/common/Collision/Management/MMapManager.cpp +++ b/src/common/Collision/Management/MMapManager.cpp @@ -17,6 +17,7 @@ */ #include "MMapManager.h" +#include "Errors.h" #include "Log.h" #include "Config.h" #include "MMapFactory.h" diff --git a/src/common/Collision/VMapTools.h b/src/common/Collision/VMapTools.h deleted file mode 100644 index 41ce1039744..00000000000 --- a/src/common/Collision/VMapTools.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 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 _VMAPTOOLS_H -#define _VMAPTOOLS_H - -#include <G3D/CollisionDetection.h> -#include <G3D/AABox.h> - -#include "Define.h" - -#include "NodeValueAccess.h" - -/** -The Class is mainly taken from G3D/AABSPTree.h but modified to be able to use our internal data structure. -This is an iterator that helps us analysing the BSP-Trees. -The collision detection is modified to return true, if we are inside an object. -*/ - -namespace VMAP -{ - template<class TValue> - class IntersectionCallBack { - public: - TValue* closestEntity; - G3D::Vector3 hitLocation; - G3D::Vector3 hitNormal; - - void operator()(const G3D::Ray& ray, const TValue* entity, bool pStopAtFirstHit, float& distance) { - entity->intersect(ray, distance, pStopAtFirstHit, hitLocation, hitNormal); - } - }; - - //============================================================== - //============================================================== - //============================================================== - - class TC_COMMON_API MyCollisionDetection - { - private: - public: - - static bool collisionLocationForMovingPointFixedAABox( - const G3D::Vector3& origin, - const G3D::Vector3& dir, - const G3D::AABox& box, - G3D::Vector3& location, - bool& Inside) - { - - // Integer representation of a floating-point value. -#define IR(x) (reinterpret_cast<G3D::uint32 const&>(x)) - - Inside = true; - const G3D::Vector3& MinB = box.low(); - const G3D::Vector3& MaxB = box.high(); - G3D::Vector3 MaxT(-1.0f, -1.0f, -1.0f); - - // Find candidate planes. - for (int i = 0; i < 3; ++i) - { - if (origin[i] < MinB[i]) - { - location[i] = MinB[i]; - Inside = false; - - // Calculate T distances to candidate planes - if (IR(dir[i])) - { - MaxT[i] = (MinB[i] - origin[i]) / dir[i]; - } - } - else if (origin[i] > MaxB[i]) - { - location[i] = MaxB[i]; - Inside = false; - - // Calculate T distances to candidate planes - if (IR(dir[i])) - { - MaxT[i] = (MaxB[i] - origin[i]) / dir[i]; - } - } - } - - if (Inside) - { - // definite hit - location = origin; - return true; - } - - // Get largest of the maxT's for final choice of intersection - int WhichPlane = 0; - if (MaxT[1] > MaxT[WhichPlane]) - { - WhichPlane = 1; - } - - if (MaxT[2] > MaxT[WhichPlane]) - { - WhichPlane = 2; - } - - // Check final candidate actually inside box - if (IR(MaxT[WhichPlane]) & 0x80000000) - { - // Miss the box - return false; - } - - for (int i = 0; i < 3; ++i) - { - if (i != WhichPlane) - { - location[i] = origin[i] + MaxT[WhichPlane] * dir[i]; - if ((location[i] < MinB[i]) || - (location[i] > MaxB[i])) - { - // On this plane we're outside the box extents, so - // we miss the box - return false; - } - } - } - /* - // Choose the normal to be the plane normal facing into the ray - normal = G3D::Vector3::zero(); - normal[WhichPlane] = (dir[WhichPlane] > 0) ? -1.0 : 1.0; - */ - return true; - -#undef IR - } - }; -} -#endif diff --git a/src/common/Common.h b/src/common/Common.h index a37111fcaf9..8b681af3054 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -20,42 +20,11 @@ #define TRINITYCORE_COMMON_H #include "Define.h" - -#include <algorithm> -#include <array> -#include <exception> -#include <list> -#include <map> #include <memory> -#include <queue> -#include <set> -#include <sstream> #include <string> -#include <type_traits> -#include <unordered_map> -#include <unordered_set> -#include <vector> -#include <numeric> - -#include <cmath> -#include <cstdio> -#include <cstdlib> -#include <cstring> -#include <ctime> -#include <cerrno> -#include <csignal> - -#include <boost/optional.hpp> -#include <boost/utility/in_place_factory.hpp> -#include <boost/functional/hash.hpp> - -#include "Debugging/Errors.h" - -#include "Threading/LockedQueue.h" +#include <utility> #if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS -# include <ws2tcpip.h> - # if TRINITY_COMPILER == TRINITY_COMPILER_INTEL # if !defined(BOOST_ASIO_HAS_MOVE) # define BOOST_ASIO_HAS_MOVE @@ -73,8 +42,6 @@ #if TRINITY_COMPILER == TRINITY_COMPILER_MICROSOFT -#include <float.h> - #define snprintf _snprintf #define atoll _atoi64 #define vsnprintf _vsnprintf @@ -87,8 +54,6 @@ #endif -inline float finiteAlways(float f) { return std::isfinite(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); } @@ -139,9 +104,7 @@ const uint8 OLD_TOTAL_LOCALES = 9; /// @todo convert in simple system TC_COMMON_API extern char const* localeNames[TOTAL_LOCALES]; -TC_COMMON_API LocaleConstant GetLocaleByName(const std::string& name); - -typedef std::vector<std::string> StringVector; +TC_COMMON_API LocaleConstant GetLocaleByName(std::string const& name); #pragma pack(push, 1) @@ -152,7 +115,7 @@ struct TC_COMMON_API LocalizedString #pragma pack(pop) -// we always use stdlibc++ std::max/std::min, undefine some not C++ standard defines (Win API and some other platforms) +// we always use stdlib std::max/std::min, undefine some not C++ standard defines (Win API and some other platforms) #ifdef max #undef max #endif @@ -167,10 +130,6 @@ struct TC_COMMON_API LocalizedString #define MAX_QUERY_LEN 32*1024 -//! Optional helper class to wrap optional values within. -template <typename T> -using Optional = boost::optional<T>; - namespace Trinity { //! std::make_unique implementation (TODO: remove this once C++14 is supported) @@ -181,19 +140,4 @@ namespace Trinity } } -//! Hash implementation for std::pair to allow using pairs in unordered_set or as key for unordered_map -//! Individual types used in pair must be hashable by boost::hash -namespace std -{ - template<class K, class V> - struct hash<std::pair<K, V>> - { - public: - size_t operator()(std::pair<K, V> const& key) const - { - return boost::hash_value(key); - } - }; -} - #endif diff --git a/src/common/Configuration/BuiltInConfig.h b/src/common/Configuration/BuiltInConfig.h index cc21555f4bf..a818407fb74 100644 --- a/src/common/Configuration/BuiltInConfig.h +++ b/src/common/Configuration/BuiltInConfig.h @@ -18,8 +18,8 @@ #ifndef BUILT_IN_CONFIG_H #define BUILT_IN_CONFIG_H -#include <string> #include "Define.h" +#include <string> /// Provides helper functions to access built-in values /// which can be overwritten in config diff --git a/src/common/Configuration/Config.cpp b/src/common/Configuration/Config.cpp index be05916e805..d4e56716501 100644 --- a/src/common/Configuration/Config.cpp +++ b/src/common/Configuration/Config.cpp @@ -16,14 +16,23 @@ * 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" #include "Log.h" +#include "Util.h" +#include <boost/property_tree/ini_parser.hpp> +#include <algorithm> +#include <memory> +#include <mutex> -using namespace boost::property_tree; +namespace bpt = boost::property_tree; + +namespace +{ + std::string _filename; + std::vector<std::string> _args; + bpt::ptree _config; + std::mutex _configLock; +} bool ConfigMgr::LoadInitial(std::string const& file, std::vector<std::string> args, std::string& error) @@ -35,8 +44,8 @@ bool ConfigMgr::LoadInitial(std::string const& file, std::vector<std::string> ar try { - ptree fullTree; - ini_parser::read_ini(file, fullTree); + bpt::ptree fullTree; + bpt::ini_parser::read_ini(file, fullTree); if (fullTree.empty()) { @@ -47,7 +56,7 @@ bool ConfigMgr::LoadInitial(std::string const& file, std::vector<std::string> ar // Since we're using only one section per config file, we skip the section and have direct property access _config = fullTree.begin()->second; } - catch (ini_parser::ini_parser_error const& e) + catch (bpt::ini_parser::ini_parser_error const& e) { if (e.line() == 0) error = e.message() + " (" + e.filename() + ")"; @@ -75,14 +84,14 @@ T ConfigMgr::GetValueDefault(std::string const& name, T def) const { try { - return _config.get<T>(ptree::path_type(name, '/')); + return _config.get<T>(bpt::ptree::path_type(name, '/')); } - catch (boost::property_tree::ptree_bad_path) + catch (bpt::ptree_bad_path) { TC_LOG_WARN("server.loading", "Missing name %s in config file %s, add \"%s = %s\" to this file", name.c_str(), _filename.c_str(), name.c_str(), std::to_string(def).c_str()); } - catch (boost::property_tree::ptree_bad_data) + catch (bpt::ptree_bad_data) { TC_LOG_ERROR("server.loading", "Bad value defined for name %s in config file %s, going to use %s instead", name.c_str(), _filename.c_str(), std::to_string(def).c_str()); @@ -96,14 +105,14 @@ std::string ConfigMgr::GetValueDefault<std::string>(std::string const& name, std { try { - return _config.get<std::string>(ptree::path_type(name, '/')); + return _config.get<std::string>(bpt::ptree::path_type(name, '/')); } - catch (boost::property_tree::ptree_bad_path) + catch (bpt::ptree_bad_path) { TC_LOG_WARN("server.loading", "Missing name %s in config file %s, add \"%s = %s\" to this file", name.c_str(), _filename.c_str(), name.c_str(), def.c_str()); } - catch (boost::property_tree::ptree_bad_data) + catch (bpt::ptree_bad_data) { TC_LOG_ERROR("server.loading", "Bad value defined for name %s in config file %s, going to use %s instead", name.c_str(), _filename.c_str(), def.c_str()); @@ -123,7 +132,7 @@ bool ConfigMgr::GetBoolDefault(std::string const& name, bool def) const { std::string val = GetValueDefault(name, std::string(def ? "1" : "0")); val.erase(std::remove(val.begin(), val.end(), '"'), val.end()); - return (val == "1" || val == "true" || val == "TRUE" || val == "yes" || val == "YES"); + return StringToBool(val); } int ConfigMgr::GetIntDefault(std::string const& name, int def) const @@ -142,13 +151,18 @@ std::string const& ConfigMgr::GetFilename() return _filename; } -std::list<std::string> ConfigMgr::GetKeysByString(std::string const& name) +std::vector<std::string> const& ConfigMgr::GetArguments() const +{ + return _args; +} + +std::vector<std::string> ConfigMgr::GetKeysByString(std::string const& name) { std::lock_guard<std::mutex> lock(_configLock); - std::list<std::string> keys; + std::vector<std::string> keys; - for (const ptree::value_type& child : _config) + for (bpt::ptree::value_type const& child : _config) if (child.first.compare(0, name.length(), name) == 0) keys.push_back(child.first); diff --git a/src/common/Configuration/Config.h b/src/common/Configuration/Config.h index 46b9bf73697..a503e419657 100644 --- a/src/common/Configuration/Config.h +++ b/src/common/Configuration/Config.h @@ -20,12 +20,8 @@ #define CONFIG_H #include "Define.h" - #include <string> -#include <list> #include <vector> -#include <mutex> -#include <boost/property_tree/ptree.hpp> class TC_COMMON_API ConfigMgr { @@ -36,8 +32,7 @@ class TC_COMMON_API ConfigMgr public: /// Method used only for loading main configuration files (bnetserver.conf and worldserver.conf) - bool LoadInitial(std::string const& file, std::vector<std::string> args, - std::string& error); + bool LoadInitial(std::string const& file, std::vector<std::string> args, std::string& error); static ConfigMgr* instance(); @@ -49,15 +44,10 @@ public: float GetFloatDefault(std::string const& name, float def) const; std::string const& GetFilename(); - std::vector<std::string> const& GetArguments() const { return _args; } - std::list<std::string> GetKeysByString(std::string const& name); + std::vector<std::string> const& GetArguments() const; + std::vector<std::string> GetKeysByString(std::string const& name); private: - std::string _filename; - std::vector<std::string> _args; - boost::property_tree::ptree _config; - std::mutex _configLock; - template<class T> T GetValueDefault(std::string const& name, T def) const; }; diff --git a/src/common/Cryptography/BigNumber.h b/src/common/Cryptography/BigNumber.h index c8ca5860933..8936ffffe53 100644 --- a/src/common/Cryptography/BigNumber.h +++ b/src/common/Cryptography/BigNumber.h @@ -19,8 +19,8 @@ #ifndef _AUTH_BIGNUMBER_H #define _AUTH_BIGNUMBER_H -#include <memory> #include "Define.h" +#include <memory> #include <string> struct bignum_st; diff --git a/src/common/Cryptography/HmacHash.cpp b/src/common/Cryptography/HmacHash.cpp index 8432ce3a322..1c38a7e0117 100644 --- a/src/common/Cryptography/HmacHash.cpp +++ b/src/common/Cryptography/HmacHash.cpp @@ -18,7 +18,8 @@ #include "HmacHash.h" #include "BigNumber.h" -#include "Common.h" +#include "Errors.h" +#include <cstring> template<HashCreateFn HashCreator, uint32 DigestLength> HmacHash<HashCreator, DigestLength>::HmacHash(uint32 len, uint8 const* seed) diff --git a/src/common/Cryptography/SessionKeyGeneration.h b/src/common/Cryptography/SessionKeyGeneration.h index 4507ae1aa0a..fdf468701bb 100644 --- a/src/common/Cryptography/SessionKeyGeneration.h +++ b/src/common/Cryptography/SessionKeyGeneration.h @@ -19,7 +19,8 @@ #ifndef SessionKeyGeneration_h__ #define SessionKeyGeneration_h__ -#include "Common.h" +#include "Define.h" +#include <cstring> template<class Hash> class SessionKeyGenerator diff --git a/src/common/DataStores/DB2FileLoader.cpp b/src/common/DataStores/DB2FileLoader.cpp index 4d12e2f67e1..0dc9edb19f0 100644 --- a/src/common/DataStores/DB2FileLoader.cpp +++ b/src/common/DataStores/DB2FileLoader.cpp @@ -21,6 +21,7 @@ #include "DB2Meta.h" #include "Errors.h" #include "Log.h" +#include <sstream> DB2FileLoadInfo::DB2FileLoadInfo() : Fields(nullptr), FieldCount(0), Meta(nullptr) { diff --git a/src/common/Debugging/WheatyExceptionReport.cpp b/src/common/Debugging/WheatyExceptionReport.cpp index 25d768654f6..46192f33d34 100644 --- a/src/common/Debugging/WheatyExceptionReport.cpp +++ b/src/common/Debugging/WheatyExceptionReport.cpp @@ -6,7 +6,9 @@ #include "CompilerDefs.h" #if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS && !defined(__MINGW32__) +#ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN +#endif #pragma warning(disable:4996) #pragma warning(disable:4312) #pragma warning(disable:4311) @@ -21,6 +23,7 @@ #include "Common.h" #include "GitRevision.h" +#include <algorithm> #define CrashFolder _T("Crashes") #pragma comment(linker, "/DEFAULTLIB:dbghelp.lib") diff --git a/src/common/Define.h b/src/common/Define.h index 4e7cf03956e..56a5068e528 100644 --- a/src/common/Define.h +++ b/src/common/Define.h @@ -56,7 +56,7 @@ #endif #if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS -# define TRINITY_PATH_MAX MAX_PATH +# define TRINITY_PATH_MAX 260 # define _USE_MATH_DEFINES # ifndef DECLSPEC_NORETURN # define DECLSPEC_NORETURN __declspec(noreturn) diff --git a/src/common/GitRevision.cpp b/src/common/GitRevision.cpp index e0626a7df1d..96e31e5e6e5 100644 --- a/src/common/GitRevision.cpp +++ b/src/common/GitRevision.cpp @@ -1,3 +1,20 @@ +/* + * 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 "GitRevision.h" #include "revision_data.h" diff --git a/src/common/GitRevision.h b/src/common/GitRevision.h index e69fcd6c812..a0a0fb85867 100644 --- a/src/common/GitRevision.h +++ b/src/common/GitRevision.h @@ -18,7 +18,6 @@ #ifndef __GITREVISION_H__ #define __GITREVISION_H__ -#include <string> #include "Define.h" namespace GitRevision diff --git a/src/common/Logging/Appender.cpp b/src/common/Logging/Appender.cpp index ec88d5fd4c1..4a995e5ab69 100644 --- a/src/common/Logging/Appender.cpp +++ b/src/common/Logging/Appender.cpp @@ -16,27 +16,10 @@ */ #include "Appender.h" -#include "Common.h" -#include "Util.h" +#include "LogMessage.h" #include "StringFormat.h" - -#include <utility> #include <sstream> -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 const& _name, LogLevel _level /* = LOG_LEVEL_DISABLED */, AppenderFlags _flags /* = APPENDER_FLAGS_NONE */): id(_id), name(_name), level(_level), flags(_flags) { } diff --git a/src/common/Logging/Appender.h b/src/common/Logging/Appender.h index 6a9932b7935..ff9d11f4713 100644 --- a/src/common/Logging/Appender.h +++ b/src/common/Logging/Appender.h @@ -18,72 +18,13 @@ #ifndef APPENDER_H #define APPENDER_H -#include <unordered_map> +#include "Define.h" +#include "LogCommon.h" #include <stdexcept> #include <string> -#include <time.h> -#include <type_traits> #include <vector> -#include <utility> -#include "Define.h" - -// Values assigned have their equivalent in enum ACE_Log_Priority -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 -}; - -const uint8 MaxLogLevels = 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 -}; - -struct TC_COMMON_API LogMessage -{ - LogMessage(LogLevel _level, std::string const& _type, std::string&& _text) - : level(_level), type(_type), text(std::forward<std::string>(_text)), mtime(time(NULL)) - { } - LogMessage(LogMessage const& /*other*/) = delete; - LogMessage& operator=(LogMessage const& /*other*/) = delete; - - static std::string getTimeStr(time_t time); - std::string getTimeStr(); - - LogLevel const level; - std::string const type; - std::string const text; - std::string prefix; - std::string param1; - time_t mtime; - - ///@ Returns size of the log message content in bytes - uint32 Size() const - { - return static_cast<uint32>(prefix.size() + text.size()); - } -}; +struct LogMessage; class TC_COMMON_API Appender { @@ -111,18 +52,6 @@ class TC_COMMON_API Appender AppenderFlags flags; }; -typedef std::unordered_map<uint8, Appender*> AppenderMap; - -typedef std::vector<char const*> ExtraAppenderArgs; -typedef Appender*(*AppenderCreatorFn)(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs); -typedef std::unordered_map<uint8, AppenderCreatorFn> AppenderCreatorMap; - -template<class AppenderImpl> -Appender* CreateAppender(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs) -{ - return new AppenderImpl(id, name, level, flags, std::forward<ExtraAppenderArgs>(extraArgs)); -} - class TC_COMMON_API InvalidAppenderArgsException : public std::length_error { public: diff --git a/src/common/Logging/AppenderConsole.cpp b/src/common/Logging/AppenderConsole.cpp index 3378c185cc5..7ae1987162e 100644 --- a/src/common/Logging/AppenderConsole.cpp +++ b/src/common/Logging/AppenderConsole.cpp @@ -15,20 +15,19 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <sstream> - #include "AppenderConsole.h" -#include "Config.h" +#include "LogMessage.h" #include "Util.h" +#include <sstream> #if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS #include <Windows.h> #endif -AppenderConsole::AppenderConsole(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs) +AppenderConsole::AppenderConsole(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*> extraArgs) : Appender(id, name, level, flags), _colored(false) { - for (uint8 i = 0; i < MaxLogLevels; ++i) + for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i) _colors[i] = ColorTypes(MaxColors); if (!extraArgs.empty()) @@ -43,11 +42,11 @@ void AppenderConsole::InitColors(std::string const& str) return; } - int color[MaxLogLevels]; + int color[NUM_ENABLED_LOG_LEVELS]; std::istringstream ss(str); - for (uint8 i = 0; i < MaxLogLevels; ++i) + for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i) { ss >> color[i]; @@ -58,7 +57,7 @@ void AppenderConsole::InitColors(std::string const& str) return; } - for (uint8 i = 0; i < MaxLogLevels; ++i) + for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i) _colors[i] = ColorTypes(color[i]); _colored = true; diff --git a/src/common/Logging/AppenderConsole.h b/src/common/Logging/AppenderConsole.h index c56a745bfba..9fd57c99f8a 100644 --- a/src/common/Logging/AppenderConsole.h +++ b/src/common/Logging/AppenderConsole.h @@ -18,7 +18,6 @@ #ifndef APPENDERCONSOLE_H #define APPENDERCONSOLE_H -#include <string> #include "Appender.h" enum ColorTypes @@ -47,7 +46,7 @@ class TC_COMMON_API AppenderConsole : public Appender public: typedef std::integral_constant<AppenderType, APPENDER_CONSOLE>::type TypeIndex; - AppenderConsole(uint8 _id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs); + AppenderConsole(uint8 _id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*> extraArgs); void InitColors(const std::string& init_str); AppenderType getType() const override { return TypeIndex::value; } @@ -56,7 +55,7 @@ class TC_COMMON_API AppenderConsole : public Appender void ResetColor(bool stdout_stream); void _write(LogMessage const* message) override; bool _colored; - ColorTypes _colors[MaxLogLevels]; + ColorTypes _colors[NUM_ENABLED_LOG_LEVELS]; }; #endif diff --git a/src/common/Logging/AppenderFile.cpp b/src/common/Logging/AppenderFile.cpp index a1595594a36..94a586649f4 100644 --- a/src/common/Logging/AppenderFile.cpp +++ b/src/common/Logging/AppenderFile.cpp @@ -16,15 +16,11 @@ */ #include "AppenderFile.h" -#include "Common.h" -#include "StringFormat.h" #include "Log.h" +#include "LogMessage.h" +#include <algorithm> -#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS -# include <Windows.h> -#endif - -AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs) : +AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*> extraArgs) : Appender(id, name, level, flags), logfile(NULL), _logDir(sLog->GetLogsDir()), diff --git a/src/common/Logging/AppenderFile.h b/src/common/Logging/AppenderFile.h index aeb1c2d8001..8e728cbdf4d 100644 --- a/src/common/Logging/AppenderFile.h +++ b/src/common/Logging/AppenderFile.h @@ -18,15 +18,15 @@ #ifndef APPENDERFILE_H #define APPENDERFILE_H -#include <atomic> #include "Appender.h" +#include <atomic> class TC_COMMON_API AppenderFile : public Appender { public: typedef std::integral_constant<AppenderType, APPENDER_FILE>::type TypeIndex; - AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs); + AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*> extraArgs); ~AppenderFile(); FILE* OpenFile(std::string const& name, std::string const& mode, bool backup); AppenderType getType() const override { return TypeIndex::value; } diff --git a/src/common/Logging/Log.cpp b/src/common/Logging/Log.cpp index 691352aacbe..3bb9edaa9a1 100644 --- a/src/common/Logging/Log.cpp +++ b/src/common/Logging/Log.cpp @@ -17,14 +17,17 @@ */ #include "Log.h" -#include "Common.h" -#include "Config.h" -#include "Util.h" #include "AppenderConsole.h" #include "AppenderFile.h" +#include "AsioHacksImpl.h" +#include "Common.h" +#include "Config.h" +#include "Errors.h" +#include "Logger.h" +#include "LogMessage.h" #include "LogOperation.h" - -#include <cstdio> +#include "Util.h" +#include <chrono> #include <sstream> Log::Log() : AppenderId(0), lowestLogLevel(LOG_LEVEL_FATAL), _ioService(nullptr), _strand(nullptr) @@ -45,25 +48,13 @@ uint8 Log::NextAppenderId() return AppenderId++; } -int32 GetConfigIntDefault(std::string base, const char* name, int32 value) -{ - base.append(name); - return sConfigMgr->GetIntDefault(base.c_str(), value); -} - -std::string GetConfigStringDefault(std::string base, const char* name, const char* value) -{ - base.append(name); - return sConfigMgr->GetStringDefault(base.c_str(), value); -} - Appender* Log::GetAppenderByName(std::string const& name) { - AppenderMap::iterator it = appenders.begin(); + auto it = appenders.begin(); while (it != appenders.end() && it->second && it->second->getName() != name) ++it; - return it == appenders.end() ? NULL : it->second; + return it == appenders.end() ? nullptr : it->second.get(); } void Log::CreateAppenderFromConfig(std::string const& appenderName) @@ -77,7 +68,7 @@ void Log::CreateAppenderFromConfig(std::string const& appenderName) std::string options = sConfigMgr->GetStringDefault(appenderName.c_str(), ""); Tokenizer tokens(options, ','); - Tokenizer::const_iterator iter = tokens.begin(); + auto iter = tokens.begin(); size_t size = tokens.size(); std::string name = appenderName.substr(9); @@ -110,8 +101,8 @@ void Log::CreateAppenderFromConfig(std::string const& appenderName) try { - Appender* appender = factoryFunction->second(NextAppenderId(), name, level, flags, ExtraAppenderArgs(iter, tokens.end())); - appenders[appender->getId()] = appender; + Appender* appender = factoryFunction->second(NextAppenderId(), name, level, flags, std::vector<char const*>(iter, tokens.end())); + appenders[appender->getId()].reset(appender); } catch (InvalidAppenderArgsException const& iaae) { @@ -145,8 +136,8 @@ void Log::CreateLoggerFromConfig(std::string const& appenderName) return; } - Logger& logger = loggers[name]; - if (!logger.getName().empty()) + std::unique_ptr<Logger>& logger = loggers[name]; + if (logger) { fprintf(stderr, "Error while configuring Logger %s. Already defined\n", name.c_str()); return; @@ -162,7 +153,7 @@ void Log::CreateLoggerFromConfig(std::string const& appenderName) if (level < lowestLogLevel) lowestLogLevel = level; - logger.Create(name, level); + logger = Trinity::make_unique<Logger>(name, level); //fprintf(stdout, "Log::CreateLoggerFromConfig: Created Logger %s, Level %u\n", name.c_str(), level); std::istringstream ss(*iter); @@ -173,7 +164,7 @@ void Log::CreateLoggerFromConfig(std::string const& appenderName) { if (Appender* appender = GetAppenderByName(str)) { - logger.addAppender(appender->getId(), appender); + logger->addAppender(appender->getId(), appender); //fprintf(stdout, "Log::CreateLoggerFromConfig: Added Appender %s to Logger %s\n", appender->getName().c_str(), name.c_str()); } else @@ -184,24 +175,16 @@ void Log::CreateLoggerFromConfig(std::string const& appenderName) void Log::ReadAppendersFromConfig() { - std::list<std::string> keys = sConfigMgr->GetKeysByString("Appender."); - - while (!keys.empty()) - { - CreateAppenderFromConfig(keys.front()); - keys.pop_front(); - } + std::vector<std::string> keys = sConfigMgr->GetKeysByString("Appender."); + for (std::string const& appenderName : keys) + CreateAppenderFromConfig(appenderName); } void Log::ReadLoggersFromConfig() { - std::list<std::string> keys = sConfigMgr->GetKeysByString("Logger."); - - while (!keys.empty()) - { - CreateLoggerFromConfig(keys.front()); - keys.pop_front(); - } + std::vector<std::string> keys = sConfigMgr->GetKeysByString("Logger."); + for (std::string const& loggerName : keys) + CreateLoggerFromConfig(loggerName); // Bad config configuration, creating default config if (loggers.find(LOGGER_ROOT) == loggers.end()) @@ -211,26 +194,43 @@ void Log::ReadLoggersFromConfig() Close(); // Clean any Logger or Appender created - AppenderConsole* appender = new AppenderConsole(NextAppenderId(), "Console", LOG_LEVEL_DEBUG, APPENDER_FLAGS_NONE, ExtraAppenderArgs()); - appenders[appender->getId()] = appender; + AppenderConsole* appender = new AppenderConsole(NextAppenderId(), "Console", LOG_LEVEL_DEBUG, APPENDER_FLAGS_NONE, std::vector<char const*>()); + appenders[appender->getId()].reset(appender); - Logger& rootLogger = loggers[LOGGER_ROOT]; - rootLogger.Create(LOGGER_ROOT, LOG_LEVEL_ERROR); - rootLogger.addAppender(appender->getId(), appender); + Logger* rootLogger = new Logger(LOGGER_ROOT, LOG_LEVEL_ERROR); + rootLogger->addAppender(appender->getId(), appender); + loggers[LOGGER_ROOT].reset(rootLogger); - Logger& serverLogger = loggers["server"]; - serverLogger.Create("server", LOG_LEVEL_INFO); - serverLogger.addAppender(appender->getId(), appender); + Logger* serverLogger = new Logger("server", LOG_LEVEL_INFO); + serverLogger->addAppender(appender->getId(), appender); + loggers["server"].reset(serverLogger); } } +void Log::RegisterAppender(uint8 index, AppenderCreatorFn appenderCreateFn) +{ + auto itr = appenderFactory.find(index); + ASSERT(itr == appenderFactory.end()); + appenderFactory[index] = appenderCreateFn; +} + +void Log::outMessage(std::string const& filter, LogLevel const level, std::string&& message) +{ + write(Trinity::make_unique<LogMessage>(level, filter, std::move(message))); +} + +void Log::outCommand(std::string&& message, std::string&& param1) +{ + write(Trinity::make_unique<LogMessage>(LOG_LEVEL_INFO, "commands.gm", std::move(message), std::move(param1))); +} + void Log::write(std::unique_ptr<LogMessage>&& msg) const { Logger const* logger = GetLoggerByType(msg->type); if (_ioService) { - auto logOperation = std::shared_ptr<LogOperation>(new LogOperation(logger, std::move(msg))); + auto logOperation = std::make_shared<LogOperation>(logger, std::move(msg)); _ioService->post(_strand->wrap([logOperation](){ logOperation->call(); })); } @@ -238,6 +238,23 @@ void Log::write(std::unique_ptr<LogMessage>&& msg) const logger->write(msg.get()); } +Logger const* Log::GetLoggerByType(std::string const& type) const +{ + auto it = loggers.find(type); + if (it != loggers.end()) + return it->second.get(); + + if (type == LOGGER_ROOT) + return NULL; + + std::string parentLogger = LOGGER_ROOT; + size_t found = type.find_last_of("."); + if (found != std::string::npos) + parentLogger = type.substr(0, found); + + return GetLoggerByType(parentLogger); +} + std::string Log::GetTimestampStr() { time_t tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); @@ -272,14 +289,14 @@ bool Log::SetLogLevel(std::string const& name, const char* newLevelc, bool isLog if (isLogger) { - LoggerMap::iterator it = loggers.begin(); - while (it != loggers.end() && it->second.getName() != name) + auto it = loggers.begin(); + while (it != loggers.end() && it->second->getName() != name) ++it; if (it == loggers.end()) return false; - it->second.setLogLevel(newLevel); + it->second->setLogLevel(newLevel); if (newLevel != LOG_LEVEL_DISABLED && newLevel < lowestLogLevel) lowestLogLevel = newLevel; @@ -316,19 +333,34 @@ void Log::outCharDump(char const* str, uint32 accountId, uint64 guid, char const void Log::SetRealmId(uint32 id) { - for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it) + for (auto it = appenders.begin(); it != appenders.end(); ++it) it->second->setRealmId(id); } void Log::Close() { loggers.clear(); - for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it) - delete it->second; - appenders.clear(); } +bool Log::ShouldLog(std::string const& type, LogLevel level) const +{ + // TODO: Use cache to store "Type.sub1.sub2": "Type" equivalence, should + // Speed up in cases where requesting "Type.sub1.sub2" but only configured + // Logger "Type" + + // Don't even look for a logger if the LogLevel is lower than lowest log levels across all loggers + if (level < lowestLogLevel) + return false; + + Logger const* logger = GetLoggerByType(type); + if (!logger) + return false; + + LogLevel logLevel = logger->getLogLevel(); + return logLevel != LOG_LEVEL_DISABLED && logLevel <= level; +} + Log* Log::instance() { static Log instance; @@ -340,7 +372,7 @@ void Log::Initialize(boost::asio::io_service* ioService) if (ioService) { _ioService = ioService; - _strand = new boost::asio::strand(*ioService); + _strand = new Trinity::AsioStrand(*ioService); } LoadFromConfig(); diff --git a/src/common/Logging/Log.h b/src/common/Logging/Log.h index 218d03f804d..f5970fc045a 100644 --- a/src/common/Logging/Log.h +++ b/src/common/Logging/Log.h @@ -20,30 +20,46 @@ #define TRINITYCORE_LOG_H #include "Define.h" -#include "Appender.h" -#include "Logger.h" +#include "AsioHacksFwd.h" +#include "LogCommon.h" #include "StringFormat.h" -#include "Common.h" -#include <boost/asio/io_service.hpp> -#include <boost/asio/strand.hpp> - -#include <stdarg.h> -#include <unordered_map> -#include <string> #include <memory> +#include <unordered_map> +#include <vector> + +class Appender; +class Logger; +struct LogMessage; + +namespace boost +{ + namespace asio + { + class io_service; + } +} #define LOGGER_ROOT "root" -class TC_COMMON_API Log +typedef Appender*(*AppenderCreatorFn)(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*>&& extraArgs); + +template<class AppenderImpl> +Appender* CreateAppender(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*>&& extraArgs) { - typedef std::unordered_map<std::string, Logger> LoggerMap; + return new AppenderImpl(id, name, level, flags, std::forward<std::vector<char const*>>(extraArgs)); +} +class TC_COMMON_API Log +{ private: Log(); ~Log(); + Log(Log const&) = delete; + Log(Log&&) = delete; + Log& operator=(Log const&) = delete; + Log& operator=(Log&&) = delete; public: - static Log* instance(); void Initialize(boost::asio::io_service* ioService); @@ -56,8 +72,7 @@ class TC_COMMON_API Log template<typename Format, typename... Args> inline void outMessage(std::string const& filter, LogLevel const level, Format&& fmt, Args&&... args) { - write(Trinity::make_unique<LogMessage>(level, filter, - Trinity::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...))); + outMessage(filter, level, Trinity::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...)); } template<typename Format, typename... Args> @@ -66,13 +81,7 @@ class TC_COMMON_API Log if (!ShouldLog("commands.gm", LOG_LEVEL_INFO)) return; - std::unique_ptr<LogMessage> msg = - Trinity::make_unique<LogMessage>(LOG_LEVEL_INFO, "commands.gm", - Trinity::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...)); - - msg->param1 = std::to_string(account); - - write(std::move(msg)); + outCommand(Trinity::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...), std::to_string(account)); } void outCharDump(char const* str, uint32 account_id, uint64 guid, char const* name); @@ -83,9 +92,7 @@ class TC_COMMON_API Log void RegisterAppender() { using Index = typename AppenderImpl::TypeIndex; - auto itr = appenderFactory.find(Index::value); - ASSERT(itr == appenderFactory.end()); - appenderFactory[Index::value] = &CreateAppender<AppenderImpl>; + RegisterAppender(Index::value, &CreateAppender<AppenderImpl>); } std::string const& GetLogsDir() const { return m_logsDir; } @@ -102,10 +109,13 @@ class TC_COMMON_API Log void CreateLoggerFromConfig(std::string const& name); void ReadAppendersFromConfig(); void ReadLoggersFromConfig(); + void RegisterAppender(uint8 index, AppenderCreatorFn appenderCreateFn); + void outMessage(std::string const& filter, LogLevel const level, std::string&& message); + void outCommand(std::string&& message, std::string&& param1); - AppenderCreatorMap appenderFactory; - AppenderMap appenders; - LoggerMap loggers; + std::unordered_map<uint8, AppenderCreatorFn> appenderFactory; + std::unordered_map<uint8, std::unique_ptr<Appender>> appenders; + std::unordered_map<std::string, std::unique_ptr<Logger>> loggers; uint8 AppenderId; LogLevel lowestLogLevel; @@ -113,44 +123,9 @@ class TC_COMMON_API Log std::string m_logsTimestamp; boost::asio::io_service* _ioService; - boost::asio::strand* _strand; + Trinity::AsioStrand* _strand; }; -inline Logger const* Log::GetLoggerByType(std::string const& type) const -{ - LoggerMap::const_iterator it = loggers.find(type); - if (it != loggers.end()) - return &(it->second); - - if (type == LOGGER_ROOT) - return NULL; - - std::string parentLogger = LOGGER_ROOT; - size_t found = type.find_last_of("."); - if (found != std::string::npos) - parentLogger = type.substr(0,found); - - return GetLoggerByType(parentLogger); -} - -inline bool Log::ShouldLog(std::string const& type, LogLevel level) const -{ - // TODO: Use cache to store "Type.sub1.sub2": "Type" equivalence, should - // Speed up in cases where requesting "Type.sub1.sub2" but only configured - // Logger "Type" - - // Don't even look for a logger if the LogLevel is lower than lowest log levels across all loggers - if (level < lowestLogLevel) - return false; - - Logger const* logger = GetLoggerByType(type); - if (!logger) - return false; - - LogLevel logLevel = logger->getLogLevel(); - return logLevel != LOG_LEVEL_DISABLED && logLevel <= level; -} - #define sLog Log::instance() #define LOG_EXCEPTION_FREE(filterType__, level__, ...) \ diff --git a/src/common/Logging/LogCommon.h b/src/common/Logging/LogCommon.h new file mode 100644 index 00000000000..7579884bbb1 --- /dev/null +++ b/src/common/Logging/LogCommon.h @@ -0,0 +1,52 @@ +/* + * 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 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__ diff --git a/src/common/Logging/LogMessage.cpp b/src/common/Logging/LogMessage.cpp new file mode 100644 index 00000000000..85a5d14135e --- /dev/null +++ b/src/common/Logging/LogMessage.cpp @@ -0,0 +1,43 @@ +/* + * 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 "LogMessage.h" +#include "Util.h" + +LogMessage::LogMessage(LogLevel _level, std::string const& _type, std::string&& _text) + : level(_level), type(_type), text(std::forward<std::string>(_text)), mtime(time(nullptr)) +{ +} + +LogMessage::LogMessage(LogLevel _level, std::string const& _type, std::string&& _text, std::string&& _param1) + : level(_level), type(_type), text(std::forward<std::string>(_text)), param1(std::forward<std::string>(_param1)), 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); +} diff --git a/src/common/Logging/LogMessage.h b/src/common/Logging/LogMessage.h new file mode 100644 index 00000000000..84f2a0579fa --- /dev/null +++ b/src/common/Logging/LogMessage.h @@ -0,0 +1,51 @@ +/* + * 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 LogMessage_h__ +#define LogMessage_h__ + +#include "Define.h" +#include "LogCommon.h" +#include <string> +#include <ctime> + +struct TC_COMMON_API LogMessage +{ + LogMessage(LogLevel _level, std::string const& _type, std::string&& _text); + LogMessage(LogLevel _level, std::string const& _type, std::string&& _text, std::string&& _param1); + + LogMessage(LogMessage const& /*other*/) = delete; + LogMessage& operator=(LogMessage const& /*other*/) = delete; + + static std::string getTimeStr(time_t time); + std::string getTimeStr(); + + LogLevel const level; + std::string const type; + std::string const text; + std::string prefix; + std::string param1; + time_t mtime; + + ///@ Returns size of the log message content in bytes + uint32 Size() const + { + return static_cast<uint32>(prefix.size() + text.size()); + } +}; + +#endif // LogMessage_h__ diff --git a/src/common/Logging/LogOperation.cpp b/src/common/Logging/LogOperation.cpp index 81bb98b9cce..c3a3711cc49 100644 --- a/src/common/Logging/LogOperation.cpp +++ b/src/common/Logging/LogOperation.cpp @@ -17,6 +17,15 @@ #include "LogOperation.h" #include "Logger.h" +#include "LogMessage.h" + +LogOperation::LogOperation(Logger const* _logger, std::unique_ptr<LogMessage>&& _msg) : logger(_logger), msg(std::forward<std::unique_ptr<LogMessage>>(_msg)) +{ +} + +LogOperation::~LogOperation() +{ +} int LogOperation::call() { diff --git a/src/common/Logging/LogOperation.h b/src/common/Logging/LogOperation.h index a7230d1749d..ddf5ef1debc 100644 --- a/src/common/Logging/LogOperation.h +++ b/src/common/Logging/LogOperation.h @@ -18,8 +18,8 @@ #ifndef LOGOPERATION_H #define LOGOPERATION_H -#include <memory> #include "Define.h" +#include <memory> class Logger; struct LogMessage; @@ -27,11 +27,9 @@ struct LogMessage; class TC_COMMON_API LogOperation { public: - LogOperation(Logger const* _logger, std::unique_ptr<LogMessage>&& _msg) - : logger(_logger), msg(std::forward<std::unique_ptr<LogMessage>>(_msg)) - { } + LogOperation(Logger const* _logger, std::unique_ptr<LogMessage>&& _msg); - ~LogOperation() { } + ~LogOperation(); int call(); diff --git a/src/common/Logging/Logger.cpp b/src/common/Logging/Logger.cpp index 8e1f9c7ef9d..a3a72f15642 100644 --- a/src/common/Logging/Logger.cpp +++ b/src/common/Logging/Logger.cpp @@ -16,14 +16,10 @@ */ #include "Logger.h" +#include "Appender.h" +#include "LogMessage.h" -Logger::Logger(): name(""), level(LOG_LEVEL_DISABLED) { } - -void Logger::Create(std::string const& _name, LogLevel _level) -{ - name = _name; - level = _level; -} +Logger::Logger(std::string const& _name, LogLevel _level): name(_name), level(_level) { } std::string const& Logger::getName() const { @@ -58,7 +54,7 @@ void Logger::write(LogMessage* message) const return; } - for (AppenderMap::const_iterator it = appenders.begin(); it != appenders.end(); ++it) + for (auto it = appenders.begin(); it != appenders.end(); ++it) if (it->second) it->second->write(message); } diff --git a/src/common/Logging/Logger.h b/src/common/Logging/Logger.h index 1446062c22b..dabeb8ced3a 100644 --- a/src/common/Logging/Logger.h +++ b/src/common/Logging/Logger.h @@ -18,15 +18,19 @@ #ifndef LOGGER_H #define LOGGER_H -#include "Appender.h" +#include "Define.h" +#include "LogCommon.h" +#include <unordered_map> + +class Appender; +struct LogMessage; class TC_COMMON_API Logger { public: - Logger(); + Logger(std::string const& name, LogLevel level); - void Create(std::string const& name, LogLevel level); - void addAppender(uint8 type, Appender *); + void addAppender(uint8 type, Appender* appender); void delAppender(uint8 type); std::string const& getName() const; @@ -37,7 +41,7 @@ class TC_COMMON_API Logger private: std::string name; LogLevel level; - AppenderMap appenders; + std::unordered_map<uint8, Appender*> appenders; }; #endif diff --git a/src/common/Metric/Metric.cpp b/src/common/Metric/Metric.cpp index 7091dd0d376..963528c0627 100644 --- a/src/common/Metric/Metric.cpp +++ b/src/common/Metric/Metric.cpp @@ -1,27 +1,33 @@ /* -* 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/>. -*/ + * 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 "Metric.h" -#include "Log.h" +#include "AsioHacksImpl.h" +#include "Common.h" #include "Config.h" +#include "Log.h" #include "Util.h" +#include <boost/algorithm/string/replace.hpp> +#include <boost/asio/deadline_timer.hpp> +#include <boost/asio/ip/tcp.hpp> void Metric::Initialize(std::string const& realmName, boost::asio::io_service& ioService, std::function<void()> overallStatusLogger) { + _dataStream = Trinity::make_unique<boost::asio::ip::tcp::iostream>(); _realmName = FormatInfluxDBTagValue(realmName); _batchTimer = Trinity::make_unique<boost::asio::deadline_timer>(ioService); _overallStatusTimer = Trinity::make_unique<boost::asio::deadline_timer>(ioService); @@ -31,8 +37,9 @@ void Metric::Initialize(std::string const& realmName, boost::asio::io_service& i bool Metric::Connect() { - _dataStream.connect(_hostname, _port); - auto error = _dataStream.error(); + auto& stream = static_cast<boost::asio::ip::tcp::iostream&>(GetDataStream()); + stream.connect(_hostname, _port); + auto error = stream.error(); if (error) { TC_LOG_ERROR("metric", "Error connecting to '%s:%s', disabling Metric. Error message : %s", @@ -40,7 +47,7 @@ bool Metric::Connect() _enabled = false; return false; } - _dataStream.clear(); + stream.clear(); return true; } @@ -156,22 +163,22 @@ void Metric::SendBatch() return; } - if (!_dataStream.good() && !Connect()) + if (!GetDataStream().good() && !Connect()) return; - _dataStream << "POST " << "/write?db=" << _databaseName << " HTTP/1.1\r\n"; - _dataStream << "Host: " << _hostname << ":" << _port << "\r\n"; - _dataStream << "Accept: */*\r\n"; - _dataStream << "Content-Type: application/octet-stream\r\n"; - _dataStream << "Content-Transfer-Encoding: binary\r\n"; + GetDataStream() << "POST " << "/write?db=" << _databaseName << " HTTP/1.1\r\n"; + GetDataStream() << "Host: " << _hostname << ":" << _port << "\r\n"; + GetDataStream() << "Accept: */*\r\n"; + GetDataStream() << "Content-Type: application/octet-stream\r\n"; + GetDataStream() << "Content-Transfer-Encoding: binary\r\n"; - _dataStream << "Content-Length: " << std::to_string(batchedData.tellp()) << "\r\n\r\n"; - _dataStream << batchedData.rdbuf(); + GetDataStream() << "Content-Length: " << std::to_string(batchedData.tellp()) << "\r\n\r\n"; + GetDataStream() << batchedData.rdbuf(); std::string http_version; - _dataStream >> http_version; + GetDataStream() >> http_version; unsigned int status_code = 0; - _dataStream >> status_code; + GetDataStream() >> status_code; if (status_code != 204) { TC_LOG_ERROR("metric", "Error sending data, returned HTTP code: %u", status_code); @@ -179,14 +186,12 @@ void Metric::SendBatch() // Read and ignore the status description std::string status_description; - std::getline(_dataStream, status_description); + std::getline(GetDataStream(), status_description); // Read headers std::string header; - while (std::getline(_dataStream, header) && header != "\r") - { + while (std::getline(GetDataStream(), header) && header != "\r") if (header == "Connection: close\r") - _dataStream.close(); - } + static_cast<boost::asio::ip::tcp::iostream&>(GetDataStream()).close(); ScheduleSend(); } @@ -200,7 +205,7 @@ void Metric::ScheduleSend() } else { - _dataStream.close(); + static_cast<boost::asio::ip::tcp::iostream&>(GetDataStream()).close(); MetricData* data; // Clear the queue while (_queuedData.Dequeue(data)) @@ -228,8 +233,62 @@ void Metric::ScheduleOverallStatusLog() } } +std::string Metric::FormatInfluxDBValue(bool value) +{ + return value ? "t" : "f"; +} + +template<class T> +std::string Metric::FormatInfluxDBValue(T value) +{ + return std::to_string(value) + 'i'; +} + +std::string Metric::FormatInfluxDBValue(std::string const& value) +{ + return '"' + boost::replace_all_copy(value, "\"", "\\\"") + '"'; +} + +std::string Metric::FormatInfluxDBValue(const char* value) +{ + return FormatInfluxDBValue(std::string(value)); +} + +std::string Metric::FormatInfluxDBValue(double value) +{ + return std::to_string(value); +} + +std::string Metric::FormatInfluxDBValue(float value) +{ + return FormatInfluxDBValue(double(value)); +} + +std::string Metric::FormatInfluxDBTagValue(std::string const& value) +{ + // ToDo: should handle '=' and ',' characters too + return boost::replace_all_copy(value, " ", "\\ "); +} + +Metric::Metric() +{ +} + +Metric::~Metric() +{ +} + Metric* Metric::instance() { static Metric instance; return &instance; } + +template TC_COMMON_API std::string Metric::FormatInfluxDBValue(int8); +template TC_COMMON_API std::string Metric::FormatInfluxDBValue(uint8); +template TC_COMMON_API std::string Metric::FormatInfluxDBValue(int16); +template TC_COMMON_API std::string Metric::FormatInfluxDBValue(uint16); +template TC_COMMON_API std::string Metric::FormatInfluxDBValue(int32); +template TC_COMMON_API std::string Metric::FormatInfluxDBValue(uint32); +template TC_COMMON_API std::string Metric::FormatInfluxDBValue(int64); +template TC_COMMON_API std::string Metric::FormatInfluxDBValue(uint64); diff --git a/src/common/Metric/Metric.h b/src/common/Metric/Metric.h index 8e4d1292519..b54d1b758ef 100644 --- a/src/common/Metric/Metric.h +++ b/src/common/Metric/Metric.h @@ -1,28 +1,39 @@ /* -* 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/>. -*/ + * 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 METRIC_H__ #define METRIC_H__ -#include "Common.h" -#include "Threading/MPSCQueue.h" -#include <boost/asio/ip/tcp.hpp> -#include <boost/algorithm/string.hpp> -#include <type_traits> +#include "Define.h" +#include "AsioHacksFwd.h" +#include "MPSCQueue.h" +#include <chrono> +#include <functional> +#include <iosfwd> +#include <memory> +#include <string> + +namespace boost +{ + namespace asio + { + class io_service; + } +} enum MetricDataType { @@ -33,7 +44,7 @@ enum MetricDataType struct MetricData { std::string Category; - std::chrono::time_point<std::chrono::system_clock> Timestamp; + std::chrono::system_clock::time_point Timestamp; MetricDataType Type; // LogValue-specific fields @@ -47,7 +58,8 @@ struct MetricData class TC_COMMON_API Metric { private: - boost::asio::ip::tcp::iostream _dataStream; + std::iostream& GetDataStream() { return *_dataStream; } + std::unique_ptr<std::iostream> _dataStream; MPSCQueue<MetricData> _queuedData; std::unique_ptr<boost::asio::deadline_timer> _batchTimer; std::unique_ptr<boost::asio::deadline_timer> _overallStatusTimer; @@ -66,31 +78,24 @@ private: void ScheduleSend(); void ScheduleOverallStatusLog(); - template<class T, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> - static std::string FormatInfluxDBValue(T value) { return std::to_string(value) + 'i'; } - - static std::string FormatInfluxDBValue(std::string const& value) - { - return '"' + boost::replace_all_copy(value, "\"", "\\\"") + '"'; - } - - static std::string FormatInfluxDBValue(bool value) { return value ? "t" : "f"; } - static std::string FormatInfluxDBValue(const char* value) { return FormatInfluxDBValue(std::string(value)); } - static std::string FormatInfluxDBValue(double value) { return std::to_string(value); } - static std::string FormatInfluxDBValue(float value) { return FormatInfluxDBValue(double(value)); } + static std::string FormatInfluxDBValue(bool value); + template<class T> + static std::string FormatInfluxDBValue(T value); + static std::string FormatInfluxDBValue(std::string const& value); + static std::string FormatInfluxDBValue(const char* value); + static std::string FormatInfluxDBValue(double value); + static std::string FormatInfluxDBValue(float value); - static std::string FormatInfluxDBTagValue(std::string const& value) - { - // ToDo: should handle '=' and ',' characters too - return boost::replace_all_copy(value, " ", "\\ "); - } + static std::string FormatInfluxDBTagValue(std::string const& value); // ToDo: should format TagKey and FieldKey too in the same way as TagValue public: + Metric(); + ~Metric(); static Metric* instance(); - void Initialize(std::string const& realmName, boost::asio::io_service& ioService, std::function<void()> overallStatusLogger = [](){}); + void Initialize(std::string const& realmName, boost::asio::io_service& ioService, std::function<void()> overallStatusLogger); void LoadFromConfigs(); void Update(); diff --git a/src/common/PrecompiledHeaders/commonPCH.h b/src/common/PrecompiledHeaders/commonPCH.h index 1d3f8928e82..fc9d8a0f6a7 100644 --- a/src/common/PrecompiledHeaders/commonPCH.h +++ b/src/common/PrecompiledHeaders/commonPCH.h @@ -1,10 +1,24 @@ +#include "BoundingIntervalHierarchy.h" +#include "Common.h" +#include "Config.h" #include "Define.h" -#include "VMapDefinitions.h" +#include "Errors.h" +#include "GitRevision.h" +#include "Log.h" +#include "LogMessage.h" #include "MapTree.h" -#include "WorldModel.h" #include "ModelInstance.h" -#include "BoundingIntervalHierarchy.h" -#include "RegularGrid.h" -#include "BoundingIntervalHierarchyWrapper.h" -#include "GameObjectModel.h" -#include "GitRevision.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> diff --git a/src/common/Threading/ProcessPriority.cpp b/src/common/Threading/ProcessPriority.cpp new file mode 100644 index 00000000000..da3cc83a544 --- /dev/null +++ b/src/common/Threading/ProcessPriority.cpp @@ -0,0 +1,95 @@ +/* + * 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 "ProcessPriority.h" +#include "Log.h" + +#ifdef _WIN32 // Windows +#include <Windows.h> +#elif defined(__linux__) +#include <sched.h> +#include <sys/resource.h> +#define PROCESS_HIGH_PRIORITY -15 // [-20, 19], default is 0 +#endif + +void SetProcessPriority(std::string const& logChannel, uint32 affinity, bool highPriority) +{ + ///- Handle affinity for multiple processors and process priority +#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(logChannel, "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(logChannel, "Using processors (bitmask, hex): %x", currentAffinity); + else + TC_LOG_ERROR(logChannel, "Can't set used processors (hex): %x", currentAffinity); + } + } + + if (highPriority) + { + if (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS)) + TC_LOG_INFO(logChannel, "Process priority class set to HIGH"); + else + TC_LOG_ERROR(logChannel, "Can't set process priority class."); + } + +#elif defined(__linux__) // 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(logChannel, "Can't set used processors (hex): %x, error: %s", affinity, strerror(errno)); + else + { + CPU_ZERO(&mask); + sched_getaffinity(0, sizeof(mask), &mask); + TC_LOG_INFO(logChannel, "Using processors (bitmask, hex): %lx", *(__cpu_mask*)(&mask)); + } + } + + if (highPriority) + { + if (setpriority(PRIO_PROCESS, 0, PROCESS_HIGH_PRIORITY)) + TC_LOG_ERROR(logChannel, "Can't set process priority class, error: %s", strerror(errno)); + else + TC_LOG_INFO(logChannel, "Process priority class set to %i", getpriority(PRIO_PROCESS, 0)); + } +#else + (void)logChannel; + (void)affinity; + (void)highPriority; +#endif +} diff --git a/src/common/Threading/ProcessPriority.h b/src/common/Threading/ProcessPriority.h index b4ff3f5ecf6..3cb866c7de1 100644 --- a/src/common/Threading/ProcessPriority.h +++ b/src/common/Threading/ProcessPriority.h @@ -18,86 +18,12 @@ #ifndef _PROCESSPRIO_H #define _PROCESSPRIO_H -#include "Configuration/Config.h" +#include "Define.h" +#include <string> -#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(logChannel, "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(logChannel, "Using processors (bitmask, hex): %x", currentAffinity); - else - TC_LOG_ERROR(logChannel, "Can't set used processors (hex): %x", currentAffinity); - } - } - - if (highPriority) - { - if (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS)) - TC_LOG_INFO(logChannel, "Process priority class set to HIGH"); - else - TC_LOG_ERROR(logChannel, "Can't set process priority class."); - } +#define CONFIG_PROCESSOR_AFFINITY "UseProcessors" +#define CONFIG_HIGH_PRIORITY "ProcessPriority" -#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(logChannel, "Can't set used processors (hex): %x, error: %s", affinity, strerror(errno)); - else - { - CPU_ZERO(&mask); - sched_getaffinity(0, sizeof(mask), &mask); - TC_LOG_INFO(logChannel, "Using processors (bitmask, hex): %lx", *(__cpu_mask*)(&mask)); - } - } - - if (highPriority) - { - if (setpriority(PRIO_PROCESS, 0, PROCESS_HIGH_PRIORITY)) - TC_LOG_ERROR(logChannel, "Can't set process priority class, error: %s", strerror(errno)); - else - TC_LOG_INFO(logChannel, "Process priority class set to %i", getpriority(PRIO_PROCESS, 0)); - } - -#endif -#else - // Suppresses unused argument warning for all other platforms - (void)logChannel; -#endif -} +void TC_COMMON_API SetProcessPriority(std::string const& logChannel, uint32 affinity, bool highPriority); #endif diff --git a/src/common/Utilities/AsioHacksFwd.h b/src/common/Utilities/AsioHacksFwd.h new file mode 100644 index 00000000000..6d4c9f5a3ed --- /dev/null +++ b/src/common/Utilities/AsioHacksFwd.h @@ -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/>. + */ + +#ifndef AsioHacksFwd_h__ +#define AsioHacksFwd_h__ + +namespace boost +{ + namespace posix_time + { + class ptime; + } + + namespace asio + { + 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__ diff --git a/src/common/Utilities/AsioHacksImpl.h b/src/common/Utilities/AsioHacksImpl.h new file mode 100644 index 00000000000..86888927a72 --- /dev/null +++ b/src/common/Utilities/AsioHacksImpl.h @@ -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: + AsioStrand(boost::asio::io_service& io_service) : boost::asio::io_service::strand(io_service) { } + }; +} + +#endif // AsioHacksImpl_h__ diff --git a/src/common/Utilities/EventMap.cpp b/src/common/Utilities/EventMap.cpp index d4ea70174c4..e1c46d0ae65 100644 --- a/src/common/Utilities/EventMap.cpp +++ b/src/common/Utilities/EventMap.cpp @@ -16,6 +16,7 @@ */ #include "EventMap.h" +#include "Random.h" void EventMap::Reset() { @@ -32,6 +33,11 @@ void EventMap::SetPhase(uint8 phase) _phase = uint8(1 << (phase - 1)); } +void EventMap::ScheduleEvent(uint32 eventId, Milliseconds const& minTime, Milliseconds const& maxTime, uint32 group /*= 0*/, uint32 phase /*= 0*/) +{ + ScheduleEvent(eventId, urand(uint32(minTime.count()), uint32(maxTime.count())), group, phase); +} + void EventMap::ScheduleEvent(uint32 eventId, uint32 time, uint32 group /*= 0*/, uint8 phase /*= 0*/) { if (group && group <= 8) @@ -43,6 +49,16 @@ void EventMap::ScheduleEvent(uint32 eventId, uint32 time, uint32 group /*= 0*/, _eventMap.insert(EventStore::value_type(_time + time, eventId)); } +void EventMap::RescheduleEvent(uint32 eventId, Milliseconds const& minTime, Milliseconds const& maxTime, uint32 group /*= 0*/, uint32 phase /*= 0*/) +{ + RescheduleEvent(eventId, urand(uint32(minTime.count()), uint32(maxTime.count())), group, phase); +} + +void EventMap::Repeat(uint32 minTime, uint32 maxTime) +{ + Repeat(urand(minTime, maxTime)); +} + uint32 EventMap::ExecuteEvent() { while (!Empty()) diff --git a/src/common/Utilities/EventMap.h b/src/common/Utilities/EventMap.h index edcc7a64455..22899ea6b60 100644 --- a/src/common/Utilities/EventMap.h +++ b/src/common/Utilities/EventMap.h @@ -18,9 +18,9 @@ #ifndef _EVENT_MAP_H_ #define _EVENT_MAP_H_ -#include "Common.h" +#include "Define.h" #include "Duration.h" -#include "Util.h" +#include <map> class TC_COMMON_API EventMap { @@ -134,10 +134,7 @@ public: * @param group The group which the event is associated to. Has to be between 1 and 8. 0 means it has no group. * @param phase The phase in which the event can occur. Has to be between 1 and 8. 0 means it can occur in all phases. */ - void ScheduleEvent(uint32 eventId, Milliseconds const& minTime, Milliseconds const& maxTime, uint32 group = 0, uint32 phase = 0) - { - ScheduleEvent(eventId, urand(uint32(minTime.count()), uint32(maxTime.count())), group, phase); - } + void ScheduleEvent(uint32 eventId, Milliseconds const& minTime, Milliseconds const& maxTime, uint32 group = 0, uint32 phase = 0); /** * @name ScheduleEvent @@ -171,10 +168,7 @@ public: * @param group The group which the event is associated to. Has to be between 1 and 8. 0 means it has no group. * @param phase The phase in which the event can occur. Has to be between 1 and 8. 0 means it can occur in all phases. */ - void RescheduleEvent(uint32 eventId, Milliseconds const& minTime, Milliseconds const& maxTime, uint32 group = 0, uint32 phase = 0) - { - RescheduleEvent(eventId, urand(uint32(minTime.count()), uint32(maxTime.count())), group, phase); - } + void RescheduleEvent(uint32 eventId, Milliseconds const& minTime, Milliseconds const& maxTime, uint32 group = 0, uint32 phase = 0); /** * @name RescheduleEvent @@ -227,10 +221,7 @@ public: * @param minTime Minimum time until the event occurs. * @param maxTime Maximum time until the event occurs. */ - void Repeat(uint32 minTime, uint32 maxTime) - { - Repeat(urand(minTime, maxTime)); - } + void Repeat(uint32 minTime, uint32 maxTime); /** * @name ExecuteEvent diff --git a/src/common/Utilities/EventProcessor.cpp b/src/common/Utilities/EventProcessor.cpp index 07fce187ad3..76517abf007 100644 --- a/src/common/Utilities/EventProcessor.cpp +++ b/src/common/Utilities/EventProcessor.cpp @@ -44,7 +44,7 @@ void EventProcessor::Update(uint32 p_time) m_time += p_time; // main event loop - EventList::iterator i; + std::multimap<uint64, BasicEvent*>::iterator i; while (((i = m_events.begin()) != m_events.end()) && i->first <= m_time) { // get and remove event from queue diff --git a/src/common/Utilities/EventProcessor.h b/src/common/Utilities/EventProcessor.h index 3b924dbb3e5..081c9e82884 100644 --- a/src/common/Utilities/EventProcessor.h +++ b/src/common/Utilities/EventProcessor.h @@ -68,8 +68,6 @@ class TC_COMMON_API BasicEvent uint64 m_execTime; // planned time of next execution, filled by event handler }; -typedef std::multimap<uint64, BasicEvent*> EventList; - class TC_COMMON_API EventProcessor { public: @@ -83,7 +81,7 @@ class TC_COMMON_API EventProcessor protected: uint64 m_time; - EventList m_events; + std::multimap<uint64, BasicEvent*> m_events; }; #endif diff --git a/src/common/Utilities/Hash.h b/src/common/Utilities/Hash.h new file mode 100644 index 00000000000..fe2047f7024 --- /dev/null +++ b/src/common/Utilities/Hash.h @@ -0,0 +1,51 @@ +/* + * 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 TrinityCore_Hash_h__ +#define TrinityCore_Hash_h__ + +#include <functional> +#include <utility> + +namespace Trinity +{ + template<typename T> + inline void hash_combine(std::size_t& seed, T const& val) + { + seed ^= std::hash<T>()(val) + 0x9E3779B9 + (seed << 6) + (seed >> 2); + } +} + + //! Hash implementation for std::pair to allow using pairs in unordered_set or as key for unordered_map + //! Individual types used in pair must be hashable by std::hash +namespace std +{ + template<class K, class V> + struct hash<std::pair<K, V>> + { + public: + size_t operator()(std::pair<K, V> const& p) const + { + size_t hashVal = 0; + Trinity::hash_combine(hashVal, p.first); + Trinity::hash_combine(hashVal, p.second); + return hashVal; + } + }; +} + +#endif // TrinityCore_Hash_h__ diff --git a/src/common/Utilities/Optional.h b/src/common/Utilities/Optional.h new file mode 100644 index 00000000000..c13a3a6a298 --- /dev/null +++ b/src/common/Utilities/Optional.h @@ -0,0 +1,28 @@ +/* + * 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 TrinityCore_Optional_h__ +#define TrinityCore_Optional_h__ + +#include <boost/optional.hpp> +#include <boost/utility/in_place_factory.hpp> + + //! Optional helper class to wrap optional values within. +template <typename T> +using Optional = boost::optional<T>; + +#endif // TrinityCore_Optional_h__ diff --git a/src/common/Utilities/Random.cpp b/src/common/Utilities/Random.cpp index 3a0cdedcf4b..890ba1b8fce 100644 --- a/src/common/Utilities/Random.cpp +++ b/src/common/Utilities/Random.cpp @@ -16,7 +16,6 @@ */ #include "Random.h" -#include "Common.h" #include "Errors.h" #include "SFMT.h" #include <boost/thread/tss.hpp> @@ -53,8 +52,8 @@ uint32 urand(uint32 min, uint32 max) uint32 urandms(uint32 min, uint32 max) { ASSERT(max >= min); - ASSERT(INT_MAX / IN_MILLISECONDS >= max); - return GetRng()->URandom(min * IN_MILLISECONDS, max * IN_MILLISECONDS); + ASSERT(std::numeric_limits<uint32>::max() / Milliseconds::period::den >= max); + return GetRng()->URandom(min * Milliseconds::period::den, max * Milliseconds::period::den); } float frand(float min, float max) diff --git a/src/common/Utilities/Random.h b/src/common/Utilities/Random.h index ded0a6c6e5c..d200282093a 100644 --- a/src/common/Utilities/Random.h +++ b/src/common/Utilities/Random.h @@ -21,7 +21,6 @@ #include "Define.h" #include "Duration.h" #include <limits> -#include <random> /* Return a random number in the range min..max. */ TC_COMMON_API int32 irand(int32 min, int32 max); diff --git a/src/common/Utilities/StartProcess.cpp b/src/common/Utilities/StartProcess.cpp index 6f4676232ca..32182f67761 100644 --- a/src/common/Utilities/StartProcess.cpp +++ b/src/common/Utilities/StartProcess.cpp @@ -16,27 +16,20 @@ */ #include "StartProcess.h" - -#include <atomic> -#include <thread> -#include <functional> +#include "Errors.h" +#include "Log.h" +#include "Optional.h" #include <boost/algorithm/string/join.hpp> -#include <boost/iostreams/stream.hpp> #include <boost/iostreams/copy.hpp> -#include <boost/iostreams/concepts.hpp> -#include <boost/iostreams/device/file_descriptor.hpp> #include <boost/process.hpp> -#include <boost/system/system_error.hpp> - -#include "Common.h" -#include "Log.h" using namespace boost::process; using namespace boost::process::initializers; using namespace boost::iostreams; -namespace Trinity { +namespace Trinity +{ template<typename T> class TCLogSink @@ -250,19 +243,15 @@ std::shared_ptr<AsyncProcessResult> return handle; } -Optional<std::string> SearchExecutableInPath(std::string const& filename) +std::string SearchExecutableInPath(std::string const& filename) { try { - auto result = search_path(filename); - if (result.empty()) - return boost::none; - else - return result; + return search_path(filename); } catch (...) { - return boost::none; + return ""; } } diff --git a/src/common/Utilities/StartProcess.h b/src/common/Utilities/StartProcess.h index 120c4f26ea6..249d4ebd47e 100644 --- a/src/common/Utilities/StartProcess.h +++ b/src/common/Utilities/StartProcess.h @@ -18,11 +18,13 @@ #ifndef Process_h__ #define Process_h__ +#include "Define.h" #include <future> #include <memory> -#include "Common.h" +#include <vector> -namespace Trinity { +namespace Trinity +{ /// Starts a process with the given arguments and parameters and will block /// until the process is finished. @@ -60,7 +62,7 @@ TC_COMMON_API std::shared_ptr<AsyncProcessResult> /// Searches for the given executable in the PATH variable /// and returns a present optional when it was found. -TC_COMMON_API Optional<std::string> SearchExecutableInPath(std::string const& filename); +TC_COMMON_API std::string SearchExecutableInPath(std::string const& filename); } // namespace Trinity diff --git a/src/common/Utilities/TaskScheduler.cpp b/src/common/Utilities/TaskScheduler.cpp index 730ef8d4b89..a9dcf5dc09b 100644 --- a/src/common/Utilities/TaskScheduler.cpp +++ b/src/common/Utilities/TaskScheduler.cpp @@ -16,6 +16,7 @@ */ #include "TaskScheduler.h" +#include "Errors.h" TaskScheduler& TaskScheduler::ClearValidator() { diff --git a/src/common/Utilities/TaskScheduler.h b/src/common/Utilities/TaskScheduler.h index d6c399639bc..0213fb90f9b 100644 --- a/src/common/Utilities/TaskScheduler.h +++ b/src/common/Utilities/TaskScheduler.h @@ -18,6 +18,9 @@ #ifndef _TASK_SCHEDULER_H_ #define _TASK_SCHEDULER_H_ +#include "Duration.h" +#include "Optional.h" +#include "Random.h" #include <algorithm> #include <chrono> #include <vector> @@ -26,11 +29,6 @@ #include <utility> #include <set> -#include <boost/optional.hpp> - -#include "Util.h" -#include "Duration.h" - class TaskContext; /// The TaskScheduler class provides the ability to schedule std::function's in the near future. @@ -73,13 +71,13 @@ class TC_COMMON_API TaskScheduler timepoint_t _end; duration_t _duration; - boost::optional<group_t> _group; + Optional<group_t> _group; repeated_t _repeated; task_handler_t _task; public: // All Argument construct - Task(timepoint_t const& end, duration_t const& duration, boost::optional<group_t> const& group, + Task(timepoint_t const& end, duration_t const& duration, Optional<group_t> const& group, repeated_t const repeated, task_handler_t const& task) : _end(end), _duration(duration), _group(group), _repeated(repeated), _task(task) { } diff --git a/src/common/Utilities/Timer.h b/src/common/Utilities/Timer.h index e774808bcb0..30a8873102c 100644 --- a/src/common/Utilities/Timer.h +++ b/src/common/Utilities/Timer.h @@ -19,6 +19,7 @@ #ifndef TRINITY_TIMER_H #define TRINITY_TIMER_H +#include "Define.h" #include <chrono> inline uint32 getMSTime() diff --git a/src/common/Utilities/Util.cpp b/src/common/Utilities/Util.cpp index ae08d3ba5a6..05dfee273d8 100644 --- a/src/common/Utilities/Util.cpp +++ b/src/common/Utilities/Util.cpp @@ -18,11 +18,12 @@ #include "Util.h" #include "Common.h" -#include "CompilerDefs.h" -#include "utf8.h" -#include "Errors.h" // for ASSERT -#include <stdarg.h> -#include <boost/algorithm/string/case_conv.hpp> +#include <boost/asio/ip/address.hpp> +#include <utf8.h> +#include <algorithm> +#include <sstream> +#include <cstdarg> +#include <ctime> #if TRINITY_COMPILER == TRINITY_COMPILER_GNU #include <sys/socket.h> @@ -149,7 +150,7 @@ int64 MoneyStringToMoney(const std::string& moneyString) if (gCount + sCount + cCount != 1) return 0; - uint64 amount = atoull(*itr); + uint64 amount = strtoull(*itr, nullptr, 10); if (gCount == 1) money += amount * 100 * 100; else if (sCount == 1) @@ -171,8 +172,8 @@ uint32 TimeStringToSecs(const std::string& timestring) { if (isdigit(*itr)) { - buffer*=10; - buffer+= (*itr)-'0'; + buffer *= 10; + buffer += *itr - '0'; } else { @@ -184,9 +185,9 @@ uint32 TimeStringToSecs(const std::string& timestring) case 's': multiplier = 1; break; default : return 0; //bad format } - buffer*=multiplier; - secs+=buffer; - buffer=0; + buffer *= multiplier; + secs += buffer; + buffer = 0; } } @@ -214,9 +215,9 @@ bool IsIPAddress(char const* ipaddress) if (!ipaddress) return false; - // Let the big boys do it. - // Drawback: all valid ip address formats are recognized e.g.: 12.23, 121234, 0xABCD) - return inet_addr(ipaddress) != INADDR_NONE; + boost::system::error_code error; + boost::asio::ip::address::from_string(ipaddress, error); + return !error; } /// create PID file @@ -374,6 +375,16 @@ bool WStrToUtf8(std::wstring const& wstr, std::string& utf8str) typedef wchar_t const* const* wstrlist; +void wstrToUpper(std::wstring& str) +{ + std::transform(str.begin(), str.end(), str.begin(), wcharToUpper); +} + +void wstrToLower(std::wstring& str) +{ + std::transform(str.begin(), str.end(), str.begin(), wcharToLower); +} + std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension) { // supported only Cyrillic cases @@ -558,6 +569,7 @@ void HexStrToByteArray(std::string const& str, uint8* out, bool reverse /*= fals bool StringToBool(std::string const& str) { - std::string lowerStr = boost::algorithm::to_lower_copy(str); + std::string lowerStr = str; + std::transform(str.begin(), str.end(), lowerStr.begin(), ::tolower); return lowerStr == "1" || lowerStr == "true" || lowerStr == "yes"; } diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h index c7a8289cb74..cd17946a40b 100644 --- a/src/common/Utilities/Util.h +++ b/src/common/Utilities/Util.h @@ -21,25 +21,9 @@ #include "Define.h" #include "Errors.h" -#include "Random.h" - -#include <algorithm> #include <string> #include <sstream> #include <vector> -#include <list> -#include <map> -#include <ctime> - -// Searcher for map of structs -template<typename T, class S> struct Finder -{ - T val_; - T S::* idMember_; - - Finder(T val, T S::* idMember) : val_(val), idMember_(idMember) {} - bool operator()(const std::pair<int, S> &obj) { return obj.second.*idMember_ == val_; } -}; class TC_COMMON_API Tokenizer { @@ -297,15 +281,8 @@ inline wchar_t wcharToLower(wchar_t wchar) return wchar; } -inline void wstrToUpper(std::wstring& str) -{ - std::transform( str.begin(), str.end(), str.begin(), wcharToUpper ); -} - -inline void wstrToLower(std::wstring& str) -{ - std::transform( str.begin(), str.end(), str.begin(), wcharToLower ); -} +TC_COMMON_API void wstrToUpper(std::wstring& str); +TC_COMMON_API void wstrToLower(std::wstring& str); TC_COMMON_API std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension); |