diff options
author | Kitzunu <24550914+Kitzunu@users.noreply.github.com> | 2021-05-30 21:12:01 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-30 21:12:01 +0200 |
commit | ae665f7ec32c5da3877b4acb0d0dd2534e9cdd06 (patch) | |
tree | 4354987c0cf316e701cedbd83e805d1c773c3dd6 | |
parent | e93159b408f2ce2162b98c9a631fa7b932a97593 (diff) |
feat(Core/Command): server debug (#6007)
* initial work
* fix query
* load
* clean up
* remove from startup
* ACE
* remove static
* Update MySQLThreading.cpp
* not used
* Update MySQLThreading.cpp
* unit testing
* Update WorldMock.h
* show Boost ver
* Update WorldMock.h
* include
* Now we have boost::filesystem woo
* fix build
* fix typo
-rw-r--r-- | data/sql/updates/pending_db_world/rev_1621718778456057300.sql | 5 | ||||
-rw-r--r-- | src/cmake/revision.h.in.cmake | 2 | ||||
-rw-r--r-- | src/common/GitRevision.cpp | 18 | ||||
-rw-r--r-- | src/common/GitRevision.h | 2 | ||||
-rw-r--r-- | src/server/database/Database/MySQLThreading.cpp | 23 | ||||
-rw-r--r-- | src/server/database/Database/MySQLThreading.h | 38 | ||||
-rw-r--r-- | src/server/game/World/IWorld.h | 4 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 39 | ||||
-rw-r--r-- | src/server/game/World/World.h | 7 | ||||
-rw-r--r-- | src/server/scripts/Commands/cs_server.cpp | 117 | ||||
-rw-r--r-- | src/server/worldserver/Master.cpp | 1 | ||||
-rw-r--r-- | src/test/mocks/WorldMock.h | 4 |
12 files changed, 226 insertions, 34 deletions
diff --git a/data/sql/updates/pending_db_world/rev_1621718778456057300.sql b/data/sql/updates/pending_db_world/rev_1621718778456057300.sql new file mode 100644 index 0000000000..0e10c13ba8 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1621718778456057300.sql @@ -0,0 +1,5 @@ +INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1621718778456057300'); + +DELETE FROM `command` WHERE `name` = 'server debug'; +INSERT INTO `command` (`name`, `security`, `help`) VALUES +('server debug', 3, 'Syntax: .server debug\r\nShows detailed information about the server setup, useful when reporting a bug.'); diff --git a/src/cmake/revision.h.in.cmake b/src/cmake/revision.h.in.cmake index 9888ddd90b..0b977bc68f 100644 --- a/src/cmake/revision.h.in.cmake +++ b/src/cmake/revision.h.in.cmake @@ -4,6 +4,8 @@ #define _HASH "@rev_hash@" #define _DATE "@rev_date@" #define _BRANCH "@rev_branch@" + #define _CMAKE_VERSION R"(@CMAKE_VERSION@)" + #define _CMAKE_HOST_SYSTEM R"(@CMAKE_HOST_SYSTEM_NAME@ @CMAKE_HOST_SYSTEM_VERSION@)" #define VER_COMPANYNAME_STR "AzerothCore" #define VER_LEGALCOPYRIGHT_STR "AzerothCore" #define VER_FILEVERSION 0,0,0 diff --git a/src/common/GitRevision.cpp b/src/common/GitRevision.cpp index bf7fd4a428..a8a53665f7 100644 --- a/src/common/GitRevision.cpp +++ b/src/common/GitRevision.cpp @@ -21,6 +21,16 @@ char const* GitRevision::GetBranch() return _BRANCH; } +char const* GitRevision::GetCMakeVersion() +{ + return _CMAKE_VERSION; +} + +char const* GitRevision::GetHostOSVersion() +{ + return _CMAKE_HOST_SYSTEM; +} + #if AC_PLATFORM == AC_PLATFORM_WINDOWS # ifdef _WIN64 # define AZEROTH_PLATFORM_STR "Win64" @@ -31,9 +41,15 @@ char const* GitRevision::GetBranch() # define AZEROTH_PLATFORM_STR "Unix" #endif +#ifndef ACORE_API_USE_DYNAMIC_LINKING +# define ACORE_LINKAGE_TYPE_STR "Static" +#else +# define ACORE_LINKAGE_TYPE_STR "Dynamic" +#endif + char const* GitRevision::GetFullVersion() { - return VER_COMPANYNAME_STR " rev. " VER_PRODUCTVERSION_STR " (" AZEROTH_PLATFORM_STR ", " _BUILD_DIRECTIVE ")"; + return VER_COMPANYNAME_STR " rev. " VER_PRODUCTVERSION_STR " (" AZEROTH_PLATFORM_STR ", " _BUILD_DIRECTIVE ", " ACORE_LINKAGE_TYPE_STR ")"; } char const* GitRevision::GetCompanyNameStr() diff --git a/src/common/GitRevision.h b/src/common/GitRevision.h index 762c3512da..f46520b057 100644 --- a/src/common/GitRevision.h +++ b/src/common/GitRevision.h @@ -13,6 +13,8 @@ namespace GitRevision char const* GetHash(); char const* GetDate(); char const* GetBranch(); + char const* GetCMakeVersion(); + char const* GetHostOSVersion(); char const* GetFullVersion(); char const* GetCompanyNameStr(); char const* GetLegalCopyrightStr(); diff --git a/src/server/database/Database/MySQLThreading.cpp b/src/server/database/Database/MySQLThreading.cpp new file mode 100644 index 0000000000..5d70ee4f8d --- /dev/null +++ b/src/server/database/Database/MySQLThreading.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2016+ AzerothCore <www.azerothcore.org> + * Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/> + */ + +#include "MySQLThreading.h" +#include "Log.h" +#include <mysql.h> + +void MySQL::Library_Init() +{ + mysql_library_init(-1, nullptr, nullptr); +} + +void MySQL::Library_End() +{ + mysql_library_end(); +} + +uint32 MySQL::GetLibraryVersion() +{ + return MYSQL_VERSION_ID; +} diff --git a/src/server/database/Database/MySQLThreading.h b/src/server/database/Database/MySQLThreading.h index 29f1a07405..8a26ba375b 100644 --- a/src/server/database/Database/MySQLThreading.h +++ b/src/server/database/Database/MySQLThreading.h @@ -9,39 +9,11 @@ #include "Log.h" -class MySQL +namespace MySQL { -public: - /*! Create a thread on the MySQL server to mirrior the calling thread, - initializes thread-specific variables and allows thread-specific - operations without concurrence from other threads. - This should only be called if multiple core threads are running - on the same MySQL connection. Seperate MySQL connections implicitly - create a mirror thread. - */ - static void Thread_Init() - { - mysql_thread_init(); - } - - /*! Shuts down MySQL thread and frees resources, should only be called - when we terminate. MySQL threads and connections are not configurable - during runtime. - */ - static void Thread_End() - { - mysql_thread_end(); - } - - static void Library_Init() - { - mysql_library_init(-1, nullptr, nullptr); - } - - static void Library_End() - { - mysql_library_end(); - } -}; + void Library_Init(); + void Library_End(); + uint32 GetLibraryVersion(); +} #endif diff --git a/src/server/game/World/IWorld.h b/src/server/game/World/IWorld.h index 383d17e9e0..5f40a9f524 100644 --- a/src/server/game/World/IWorld.h +++ b/src/server/game/World/IWorld.h @@ -581,7 +581,11 @@ public: virtual void UpdateRealmCharCount(uint32 accid) = 0; virtual LocaleConstant GetAvailableDbcLocale(LocaleConstant locale) const = 0; virtual void LoadDBVersion() = 0; + virtual void LoadDBRevision() = 0; virtual char const* GetDBVersion() const = 0; + virtual char const* GetWorldDBRevision() const = 0; + virtual char const* GetCharacterDBRevision() const = 0; + virtual char const* GetAuthDBRevision() const = 0; virtual void LoadAutobroadcasts() = 0; virtual void UpdateAreaDependentAuras() = 0; virtual uint32 GetCleaningFlags() const = 0; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 20186e06f2..69392bc299 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -3109,6 +3109,45 @@ void World::LoadDBVersion() m_DBVersion = "Unknown world database."; } +void World::LoadDBRevision() +{ + QueryResult resultWorld = WorldDatabase.Query("SELECT date FROM version_db_world ORDER BY date DESC LIMIT 1"); + QueryResult resultCharacter = CharacterDatabase.Query("SELECT date FROM version_db_characters ORDER BY date DESC LIMIT 1"); + QueryResult resultAuth = LoginDatabase.Query("SELECT date FROM version_db_auth ORDER BY date DESC LIMIT 1"); + + if (resultWorld) + { + Field* fields = resultWorld->Fetch(); + + m_WorldDBRevision = fields[0].GetString(); + } + if (resultCharacter) + { + Field* fields = resultCharacter->Fetch(); + + m_CharacterDBRevision = fields[0].GetString(); + } + if (resultAuth) + { + Field* fields = resultAuth->Fetch(); + + m_AuthDBRevision = fields[0].GetString(); + } + + if (m_WorldDBRevision.empty()) + { + m_WorldDBRevision = "Unkown World Database Revision"; + } + if (m_CharacterDBRevision.empty()) + { + m_CharacterDBRevision = "Unkown Character Database Revision"; + } + if (m_AuthDBRevision.empty()) + { + m_AuthDBRevision = "Unkown Auth Database Revision"; + } +} + void World::UpdateAreaDependentAuras() { SessionMap::const_iterator itr; diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index b2005d2073..edbfd8dfde 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -370,7 +370,11 @@ public: // used World DB version void LoadDBVersion(); + void LoadDBRevision(); char const* GetDBVersion() const { return m_DBVersion.c_str(); } + char const* GetWorldDBRevision() const { return m_WorldDBRevision.c_str(); } + char const* GetCharacterDBRevision() const { return m_CharacterDBRevision.c_str(); } + char const* GetAuthDBRevision() const { return m_AuthDBRevision.c_str(); } void LoadAutobroadcasts(); @@ -478,6 +482,9 @@ private: // used versions std::string m_DBVersion; + std::string m_WorldDBRevision; + std::string m_CharacterDBRevision; + std::string m_AuthDBRevision; typedef std::map<uint8, std::string> AutobroadcastsMap; AutobroadcastsMap m_Autobroadcasts; diff --git a/src/server/scripts/Commands/cs_server.cpp b/src/server/scripts/Commands/cs_server.cpp index 068988f754..d02b7b6605 100644 --- a/src/server/scripts/Commands/cs_server.cpp +++ b/src/server/scripts/Commands/cs_server.cpp @@ -15,12 +15,20 @@ EndScriptData */ #include "Chat.h" #include "Config.h" #include "GitRevision.h" +#include "VMapManager2.h" +#include "VMapFactory.h" #include "Language.h" #include "ObjectAccessor.h" #include "Player.h" +#include "Realm.h" #include "ScriptMgr.h" #include "ServerMotd.h" #include "StringConvert.h" +#include <boost/filesystem/operations.hpp> +#include <boost/version.hpp> +#include <openssl/crypto.h> +#include <openssl/opensslv.h> +#include <numeric> class server_commandscript : public CommandScript { @@ -64,6 +72,7 @@ public: static std::vector<ChatCommand> serverCommandTable = { { "corpses", SEC_GAMEMASTER, true, &HandleServerCorpsesCommand, "" }, + { "debug", SEC_ADMINISTRATOR, true, &HandleServerDebugCommand, "" }, { "exit", SEC_CONSOLE, true, &HandleServerExitCommand, "" }, { "idlerestart", SEC_CONSOLE, true, nullptr, "", serverIdleRestartCommandTable }, { "idleshutdown", SEC_CONSOLE, true, nullptr, "", serverIdleShutdownCommandTable }, @@ -89,6 +98,114 @@ public: return true; } + static bool HandleServerDebugCommand(ChatHandler* handler, char const* /*args*/) + { + uint16 worldPort = uint16(sWorld->getIntConfig(CONFIG_PORT_WORLD)); + std::string dbPortOutput; + + { + uint16 dbPort = 0; + if (QueryResult res = LoginDatabase.PQuery("SELECT port FROM realmlist WHERE id = %u", realm.Id.Realm)) + dbPort = (*res)[0].GetUInt16(); + + if (dbPort) + dbPortOutput = acore::StringFormat("Realmlist (Realm Id: %u) configured in port %" PRIu16, realm.Id.Realm, dbPort); + else + dbPortOutput = acore::StringFormat("Realm Id: %u not found in `realmlist` table. Please check your setup", realm.Id.Realm); + } + + handler->PSendSysMessage("%s", GitRevision::GetFullVersion()); + handler->PSendSysMessage("Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION)); + handler->PSendSysMessage("Using ACE version: %s", ACE_VERSION); + handler->PSendSysMessage("Using Boost version: %i.%i.%i", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100); + handler->PSendSysMessage("Using MySQL version: %u", MySQL::GetLibraryVersion()); + handler->PSendSysMessage("Using CMake version: %s", GitRevision::GetCMakeVersion()); + + handler->PSendSysMessage("Compiled on: %s", GitRevision::GetHostOSVersion()); + + handler->PSendSysMessage("Worldserver listening connections on port %" PRIu16, worldPort); + handler->PSendSysMessage("%s", dbPortOutput.c_str()); + + bool vmapIndoorCheck = sWorld->getBoolConfig(CONFIG_VMAP_INDOOR_CHECK); + bool vmapLOSCheck = VMAP::VMapFactory::createOrGetVMapManager()->isLineOfSightCalcEnabled(); + bool vmapHeightCheck = VMAP::VMapFactory::createOrGetVMapManager()->isHeightCalcEnabled(); + + bool mmapEnabled = sWorld->getBoolConfig(CONFIG_ENABLE_MMAPS); + + std::string dataDir = sWorld->GetDataPath(); + std::vector<std::string> subDirs; + subDirs.emplace_back("maps"); + if (vmapIndoorCheck || vmapLOSCheck || vmapHeightCheck) + { + handler->PSendSysMessage("VMAPs status: Enabled. LineOfSight: %i, getHeight: %i, indoorCheck: %i", vmapLOSCheck, vmapHeightCheck, vmapIndoorCheck); + subDirs.emplace_back("vmaps"); + } + else + handler->SendSysMessage("VMAPs status: Disabled"); + + if (mmapEnabled) + { + handler->SendSysMessage("MMAPs status: Enabled"); + subDirs.emplace_back("mmaps"); + } + else + handler->SendSysMessage("MMAPs status: Disabled"); + + for (std::string const& subDir : subDirs) + { + boost::filesystem::path mapPath(dataDir); + mapPath /= subDir; + + if (!boost::filesystem::exists(mapPath)) + { + handler->PSendSysMessage("%s directory doesn't exist!. Using path: %s", subDir.c_str(), mapPath.generic_string().c_str()); + continue; + } + + auto end = boost::filesystem::directory_iterator(); + std::size_t folderSize = std::accumulate(boost::filesystem::directory_iterator(mapPath), end, std::size_t(0), [](std::size_t val, boost::filesystem::path const& mapFile) + { + if (boost::filesystem::is_regular_file(mapFile)) + val += boost::filesystem::file_size(mapFile); + return val; + }); + + handler->PSendSysMessage("%s directory located in %s. Total size: " SZFMTD " bytes", subDir.c_str(), mapPath.generic_string().c_str(), folderSize); + } + + LocaleConstant defaultLocale = sWorld->GetDefaultDbcLocale(); + uint32 availableLocalesMask = (1 << defaultLocale); + + for (uint8 i = 0; i < TOTAL_LOCALES; ++i) + { + LocaleConstant locale = static_cast<LocaleConstant>(i); + if (locale == defaultLocale) + continue; + + if (sWorld->GetAvailableDbcLocale(locale) != defaultLocale) + availableLocalesMask |= (1 << locale); + } + + std::string availableLocales; + for (uint8 i = 0; i < TOTAL_LOCALES; ++i) + { + if (!(availableLocalesMask & (1 << i))) + continue; + + availableLocales += localeNames[i]; + if (i != TOTAL_LOCALES - 1) + availableLocales += " "; + } + + handler->PSendSysMessage("Using %s DBC Locale as default. All available DBC locales: %s", localeNames[defaultLocale], availableLocales.c_str()); + + handler->PSendSysMessage("Using World DB: %s", sWorld->GetDBVersion()); + handler->PSendSysMessage("Using World DB Revision: %s", sWorld->GetWorldDBRevision()); + handler->PSendSysMessage("Using Character DB Revision: %s", sWorld->GetCharacterDBRevision()); + handler->PSendSysMessage("Using Auth DB Revision: %s", sWorld->GetAuthDBRevision()); + return true; + } + static bool HandleServerInfoCommand(ChatHandler* handler, char const* /*args*/) { std::string realmName = sWorld->GetRealmName(); diff --git a/src/server/worldserver/Master.cpp b/src/server/worldserver/Master.cpp index dce780f814..fd2a7e2e33 100644 --- a/src/server/worldserver/Master.cpp +++ b/src/server/worldserver/Master.cpp @@ -406,6 +406,7 @@ bool Master::_StartDB() WorldDatabase.PExecute("UPDATE version SET core_version = '%s', core_revision = '%s'", GitRevision::GetFullVersion(), GitRevision::GetHash()); // One-time query sWorld->LoadDBVersion(); + sWorld->LoadDBRevision(); LOG_INFO("server", "Using World DB: %s", sWorld->GetDBVersion()); return true; diff --git a/src/test/mocks/WorldMock.h b/src/test/mocks/WorldMock.h index f58be22e22..15c2c8cd1b 100644 --- a/src/test/mocks/WorldMock.h +++ b/src/test/mocks/WorldMock.h @@ -112,7 +112,11 @@ public: MOCK_METHOD(void, UpdateRealmCharCount, (uint32 accid), ()); MOCK_METHOD(LocaleConstant, GetAvailableDbcLocale, (LocaleConstant locale), (const)); MOCK_METHOD(void, LoadDBVersion, ()); + MOCK_METHOD(void, LoadDBRevision, ()); MOCK_METHOD(char const *, GetDBVersion, (), (const)); + MOCK_METHOD(char const *, GetWorldDBRevision, (), (const)); + MOCK_METHOD(char const *, GetCharacterDBRevision, (), (const)); + MOCK_METHOD(char const *, GetAuthDBRevision, (), (const)); MOCK_METHOD(void, LoadAutobroadcasts, ()); MOCK_METHOD(void, UpdateAreaDependentAuras, ()); MOCK_METHOD(uint32, GetCleaningFlags, (), (const)); |