From 1b539d55226b6d904bf89cd2ac0851aa35f8e949 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 15 Jan 2014 01:32:18 -0700 Subject: [PATCH] Added serverUtility library --- engine/server/library/CMakeLists.txt | 1 + .../library/serverUtility/CMakeLists.txt | 11 + .../serverUtility/AdminAccountManager.h | 1 + .../public/serverUtility/ChatLogManager.h | 1 + .../serverUtility/ClusterWideDataManager.h | 1 + .../ClusterWideDataManagerList.h | 1 + .../serverUtility/ConfigServerUtility.h | 1 + .../public/serverUtility/FirstServerUtility.h | 1 + .../public/serverUtility/FreeCtsDataTable.h | 1 + .../public/serverUtility/LocationData.h | 1 + .../public/serverUtility/MissionLocation.h | 1 + .../public/serverUtility/PopulationList.h | 1 + .../include/public/serverUtility/PvpEnemy.h | 2 + .../serverUtility/RecentMaxSyncedValue.h | 2 + .../serverUtility/ResourceFractalData.h | 1 + .../public/serverUtility/ServerClock.h | 1 + .../public/serverUtility/ServerConnection.h | 1 + .../serverUtility/ServerServiceHandler.h | 1 + .../public/serverUtility/SetupServerUtility.h | 1 + .../library/serverUtility/src/CMakeLists.txt | 74 +++ .../serverUtility/src/linux/stlhack.cpp | 22 + .../src/shared/AdminAccountManager.cpp | 139 +++++ .../src/shared/AdminAccountManager.h | 40 ++ .../src/shared/ChatLogManager.cpp | 489 +++++++++++++++ .../serverUtility/src/shared/ChatLogManager.h | 41 ++ .../src/shared/ClusterWideDataManager.cpp | 316 ++++++++++ .../src/shared/ClusterWideDataManager.h | 80 +++ .../src/shared/ClusterWideDataManagerList.cpp | 574 ++++++++++++++++++ .../src/shared/ClusterWideDataManagerList.h | 40 ++ .../src/shared/ConfigServerUtility.cpp | 94 +++ .../src/shared/ConfigServerUtility.h | 33 + .../src/shared/FirstServerUtility.h | 8 + .../src/shared/FreeCtsDataTable.cpp | 433 +++++++++++++ .../src/shared/FreeCtsDataTable.h | 47 ++ .../serverUtility/src/shared/LocationData.cpp | 39 ++ .../serverUtility/src/shared/LocationData.h | 51 ++ .../src/shared/MissionLocation.cpp | 38 ++ .../src/shared/MissionLocation.h | 72 +++ .../src/shared/PopulationList.cpp | 147 +++++ .../serverUtility/src/shared/PopulationList.h | 100 +++ .../serverUtility/src/shared/PvpEnemy.cpp | 43 ++ .../serverUtility/src/shared/PvpEnemy.h | 62 ++ .../src/shared/RecentMaxSyncedValue.cpp | 110 ++++ .../src/shared/RecentMaxSyncedValue.h | 35 ++ .../src/shared/ResourceFractalData.cpp | 27 + .../src/shared/ResourceFractalData.h | 32 + .../serverUtility/src/shared/ServerClock.cpp | 112 ++++ .../serverUtility/src/shared/ServerClock.h | 54 ++ .../src/shared/ServerConnection.cpp | 297 +++++++++ .../src/shared/ServerConnection.h | 91 +++ .../src/shared/ServerServiceHandler.h | 38 ++ .../src/shared/SetupServerUtility.cpp | 25 + .../src/shared/SetupServerUtility.h | 27 + .../src/shared/SystemAssignedProcessId.cpp | 43 ++ .../src/shared/SystemAssignedProcessId.h | 32 + .../src/win32/FirstServerUtility.cpp | 2 + 56 files changed, 3938 insertions(+) create mode 100644 engine/server/library/serverUtility/CMakeLists.txt create mode 100644 engine/server/library/serverUtility/include/public/serverUtility/AdminAccountManager.h create mode 100644 engine/server/library/serverUtility/include/public/serverUtility/ChatLogManager.h create mode 100644 engine/server/library/serverUtility/include/public/serverUtility/ClusterWideDataManager.h create mode 100644 engine/server/library/serverUtility/include/public/serverUtility/ClusterWideDataManagerList.h create mode 100644 engine/server/library/serverUtility/include/public/serverUtility/ConfigServerUtility.h create mode 100644 engine/server/library/serverUtility/include/public/serverUtility/FirstServerUtility.h create mode 100644 engine/server/library/serverUtility/include/public/serverUtility/FreeCtsDataTable.h create mode 100644 engine/server/library/serverUtility/include/public/serverUtility/LocationData.h create mode 100644 engine/server/library/serverUtility/include/public/serverUtility/MissionLocation.h create mode 100644 engine/server/library/serverUtility/include/public/serverUtility/PopulationList.h create mode 100644 engine/server/library/serverUtility/include/public/serverUtility/PvpEnemy.h create mode 100644 engine/server/library/serverUtility/include/public/serverUtility/RecentMaxSyncedValue.h create mode 100644 engine/server/library/serverUtility/include/public/serverUtility/ResourceFractalData.h create mode 100644 engine/server/library/serverUtility/include/public/serverUtility/ServerClock.h create mode 100644 engine/server/library/serverUtility/include/public/serverUtility/ServerConnection.h create mode 100644 engine/server/library/serverUtility/include/public/serverUtility/ServerServiceHandler.h create mode 100644 engine/server/library/serverUtility/include/public/serverUtility/SetupServerUtility.h create mode 100644 engine/server/library/serverUtility/src/CMakeLists.txt create mode 100644 engine/server/library/serverUtility/src/linux/stlhack.cpp create mode 100644 engine/server/library/serverUtility/src/shared/AdminAccountManager.cpp create mode 100644 engine/server/library/serverUtility/src/shared/AdminAccountManager.h create mode 100644 engine/server/library/serverUtility/src/shared/ChatLogManager.cpp create mode 100644 engine/server/library/serverUtility/src/shared/ChatLogManager.h create mode 100644 engine/server/library/serverUtility/src/shared/ClusterWideDataManager.cpp create mode 100644 engine/server/library/serverUtility/src/shared/ClusterWideDataManager.h create mode 100644 engine/server/library/serverUtility/src/shared/ClusterWideDataManagerList.cpp create mode 100644 engine/server/library/serverUtility/src/shared/ClusterWideDataManagerList.h create mode 100644 engine/server/library/serverUtility/src/shared/ConfigServerUtility.cpp create mode 100644 engine/server/library/serverUtility/src/shared/ConfigServerUtility.h create mode 100644 engine/server/library/serverUtility/src/shared/FirstServerUtility.h create mode 100644 engine/server/library/serverUtility/src/shared/FreeCtsDataTable.cpp create mode 100644 engine/server/library/serverUtility/src/shared/FreeCtsDataTable.h create mode 100644 engine/server/library/serverUtility/src/shared/LocationData.cpp create mode 100644 engine/server/library/serverUtility/src/shared/LocationData.h create mode 100644 engine/server/library/serverUtility/src/shared/MissionLocation.cpp create mode 100644 engine/server/library/serverUtility/src/shared/MissionLocation.h create mode 100644 engine/server/library/serverUtility/src/shared/PopulationList.cpp create mode 100644 engine/server/library/serverUtility/src/shared/PopulationList.h create mode 100644 engine/server/library/serverUtility/src/shared/PvpEnemy.cpp create mode 100644 engine/server/library/serverUtility/src/shared/PvpEnemy.h create mode 100644 engine/server/library/serverUtility/src/shared/RecentMaxSyncedValue.cpp create mode 100644 engine/server/library/serverUtility/src/shared/RecentMaxSyncedValue.h create mode 100644 engine/server/library/serverUtility/src/shared/ResourceFractalData.cpp create mode 100644 engine/server/library/serverUtility/src/shared/ResourceFractalData.h create mode 100644 engine/server/library/serverUtility/src/shared/ServerClock.cpp create mode 100644 engine/server/library/serverUtility/src/shared/ServerClock.h create mode 100644 engine/server/library/serverUtility/src/shared/ServerConnection.cpp create mode 100644 engine/server/library/serverUtility/src/shared/ServerConnection.h create mode 100644 engine/server/library/serverUtility/src/shared/ServerServiceHandler.h create mode 100644 engine/server/library/serverUtility/src/shared/SetupServerUtility.cpp create mode 100644 engine/server/library/serverUtility/src/shared/SetupServerUtility.h create mode 100644 engine/server/library/serverUtility/src/shared/SystemAssignedProcessId.cpp create mode 100644 engine/server/library/serverUtility/src/shared/SystemAssignedProcessId.h create mode 100644 engine/server/library/serverUtility/src/win32/FirstServerUtility.cpp diff --git a/engine/server/library/CMakeLists.txt b/engine/server/library/CMakeLists.txt index 1e7013f0..6609f072 100644 --- a/engine/server/library/CMakeLists.txt +++ b/engine/server/library/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(serverKeyShare) add_subdirectory(serverMetrics) +add_subdirectory(serverUtility) diff --git a/engine/server/library/serverUtility/CMakeLists.txt b/engine/server/library/serverUtility/CMakeLists.txt new file mode 100644 index 00000000..458d6cf6 --- /dev/null +++ b/engine/server/library/serverUtility/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 2.8) + +project(serverUtility) + +if(WIN32) + add_definitions(/D_CRT_SECURE_NO_WARNINGS) +endif() + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/public) + +add_subdirectory(src) diff --git a/engine/server/library/serverUtility/include/public/serverUtility/AdminAccountManager.h b/engine/server/library/serverUtility/include/public/serverUtility/AdminAccountManager.h new file mode 100644 index 00000000..6fbcca2e --- /dev/null +++ b/engine/server/library/serverUtility/include/public/serverUtility/AdminAccountManager.h @@ -0,0 +1 @@ +#include "../../src/shared/AdminAccountManager.h" diff --git a/engine/server/library/serverUtility/include/public/serverUtility/ChatLogManager.h b/engine/server/library/serverUtility/include/public/serverUtility/ChatLogManager.h new file mode 100644 index 00000000..558ef272 --- /dev/null +++ b/engine/server/library/serverUtility/include/public/serverUtility/ChatLogManager.h @@ -0,0 +1 @@ +#include "../../src/shared/ChatLogManager.h" diff --git a/engine/server/library/serverUtility/include/public/serverUtility/ClusterWideDataManager.h b/engine/server/library/serverUtility/include/public/serverUtility/ClusterWideDataManager.h new file mode 100644 index 00000000..d5cbc8f7 --- /dev/null +++ b/engine/server/library/serverUtility/include/public/serverUtility/ClusterWideDataManager.h @@ -0,0 +1 @@ +#include "../../src/shared/ClusterWideDataManager.h" diff --git a/engine/server/library/serverUtility/include/public/serverUtility/ClusterWideDataManagerList.h b/engine/server/library/serverUtility/include/public/serverUtility/ClusterWideDataManagerList.h new file mode 100644 index 00000000..ce58844d --- /dev/null +++ b/engine/server/library/serverUtility/include/public/serverUtility/ClusterWideDataManagerList.h @@ -0,0 +1 @@ +#include "../../src/shared/ClusterWideDataManagerList.h" diff --git a/engine/server/library/serverUtility/include/public/serverUtility/ConfigServerUtility.h b/engine/server/library/serverUtility/include/public/serverUtility/ConfigServerUtility.h new file mode 100644 index 00000000..e486f037 --- /dev/null +++ b/engine/server/library/serverUtility/include/public/serverUtility/ConfigServerUtility.h @@ -0,0 +1 @@ +#include "../../src/shared/ConfigServerUtility.h" diff --git a/engine/server/library/serverUtility/include/public/serverUtility/FirstServerUtility.h b/engine/server/library/serverUtility/include/public/serverUtility/FirstServerUtility.h new file mode 100644 index 00000000..a16e52f5 --- /dev/null +++ b/engine/server/library/serverUtility/include/public/serverUtility/FirstServerUtility.h @@ -0,0 +1 @@ +#include "../../src/shared/FirstServerUtility.h" diff --git a/engine/server/library/serverUtility/include/public/serverUtility/FreeCtsDataTable.h b/engine/server/library/serverUtility/include/public/serverUtility/FreeCtsDataTable.h new file mode 100644 index 00000000..4564b137 --- /dev/null +++ b/engine/server/library/serverUtility/include/public/serverUtility/FreeCtsDataTable.h @@ -0,0 +1 @@ +#include "../../src/shared/FreeCtsDataTable.h" diff --git a/engine/server/library/serverUtility/include/public/serverUtility/LocationData.h b/engine/server/library/serverUtility/include/public/serverUtility/LocationData.h new file mode 100644 index 00000000..0533936c --- /dev/null +++ b/engine/server/library/serverUtility/include/public/serverUtility/LocationData.h @@ -0,0 +1 @@ +#include "../../src/shared/LocationData.h" diff --git a/engine/server/library/serverUtility/include/public/serverUtility/MissionLocation.h b/engine/server/library/serverUtility/include/public/serverUtility/MissionLocation.h new file mode 100644 index 00000000..5a792a8d --- /dev/null +++ b/engine/server/library/serverUtility/include/public/serverUtility/MissionLocation.h @@ -0,0 +1 @@ +#include "../../src/shared/MissionLocation.h" diff --git a/engine/server/library/serverUtility/include/public/serverUtility/PopulationList.h b/engine/server/library/serverUtility/include/public/serverUtility/PopulationList.h new file mode 100644 index 00000000..c6c0e905 --- /dev/null +++ b/engine/server/library/serverUtility/include/public/serverUtility/PopulationList.h @@ -0,0 +1 @@ +#include "../../src/shared/PopulationList.h" diff --git a/engine/server/library/serverUtility/include/public/serverUtility/PvpEnemy.h b/engine/server/library/serverUtility/include/public/serverUtility/PvpEnemy.h new file mode 100644 index 00000000..9fc102f9 --- /dev/null +++ b/engine/server/library/serverUtility/include/public/serverUtility/PvpEnemy.h @@ -0,0 +1,2 @@ +#include "../../src/shared/PvpEnemy.h" + diff --git a/engine/server/library/serverUtility/include/public/serverUtility/RecentMaxSyncedValue.h b/engine/server/library/serverUtility/include/public/serverUtility/RecentMaxSyncedValue.h new file mode 100644 index 00000000..da9a9b31 --- /dev/null +++ b/engine/server/library/serverUtility/include/public/serverUtility/RecentMaxSyncedValue.h @@ -0,0 +1,2 @@ +#include "../../src/shared/RecentMaxSyncedValue.h" + diff --git a/engine/server/library/serverUtility/include/public/serverUtility/ResourceFractalData.h b/engine/server/library/serverUtility/include/public/serverUtility/ResourceFractalData.h new file mode 100644 index 00000000..e7b21790 --- /dev/null +++ b/engine/server/library/serverUtility/include/public/serverUtility/ResourceFractalData.h @@ -0,0 +1 @@ +#include "../../src/shared/ResourceFractalData.h" diff --git a/engine/server/library/serverUtility/include/public/serverUtility/ServerClock.h b/engine/server/library/serverUtility/include/public/serverUtility/ServerClock.h new file mode 100644 index 00000000..912b0fcf --- /dev/null +++ b/engine/server/library/serverUtility/include/public/serverUtility/ServerClock.h @@ -0,0 +1 @@ +#include "../../src/shared/ServerClock.h" diff --git a/engine/server/library/serverUtility/include/public/serverUtility/ServerConnection.h b/engine/server/library/serverUtility/include/public/serverUtility/ServerConnection.h new file mode 100644 index 00000000..416e6936 --- /dev/null +++ b/engine/server/library/serverUtility/include/public/serverUtility/ServerConnection.h @@ -0,0 +1 @@ +#include "../../src/shared/ServerConnection.h" diff --git a/engine/server/library/serverUtility/include/public/serverUtility/ServerServiceHandler.h b/engine/server/library/serverUtility/include/public/serverUtility/ServerServiceHandler.h new file mode 100644 index 00000000..1bf73e92 --- /dev/null +++ b/engine/server/library/serverUtility/include/public/serverUtility/ServerServiceHandler.h @@ -0,0 +1 @@ +#include "../../src/shared/ServerServiceHandler.h" diff --git a/engine/server/library/serverUtility/include/public/serverUtility/SetupServerUtility.h b/engine/server/library/serverUtility/include/public/serverUtility/SetupServerUtility.h new file mode 100644 index 00000000..af79341e --- /dev/null +++ b/engine/server/library/serverUtility/include/public/serverUtility/SetupServerUtility.h @@ -0,0 +1 @@ +#include "../../src/shared/SetupServerUtility.h" diff --git a/engine/server/library/serverUtility/src/CMakeLists.txt b/engine/server/library/serverUtility/src/CMakeLists.txt new file mode 100644 index 00000000..a18e9691 --- /dev/null +++ b/engine/server/library/serverUtility/src/CMakeLists.txt @@ -0,0 +1,74 @@ + +set(SHARED_SOURCES + shared/AdminAccountManager.cpp + shared/AdminAccountManager.h + shared/ChatLogManager.cpp + shared/ConfigServerUtility.cpp + shared/ConfigServerUtility.h + shared/ClusterWideDataManager.cpp + shared/ClusterWideDataManager.h + shared/ClusterWideDataManagerList.cpp + shared/ClusterWideDataManagerList.h + shared/FirstServerUtility.h + shared/FreeCtsDataTable.cpp + shared/FreeCtsDataTable.h + shared/LocationData.cpp + shared/LocationData.h + shared/MissionLocation.cpp + shared/MissionLocation.h + shared/PopulationList.cpp + shared/PopulationList.h + shared/PvpEnemy.cpp + shared/PvpEnemy.h + shared/ResourceFractalData.cpp + shared/ResourceFractalData.h + shared/RecentMaxSyncedValue.cpp + shared/RecentMaxSyncedValue.h + shared/ServerClock.cpp + shared/ServerClock.h + shared/ServerConnection.cpp + shared/ServerConnection.h + shared/ServerServiceHandler.h + shared/SetupServerUtility.cpp + shared/SetupServerUtility.h + shared/SystemAssignedProcessId.cpp + shared/SystemAssignedProcessId.h +) + +if(WIN32) + set(PLATFORM_SOURCES + win32/FirstServerUtility.cpp + ) +else() + set(PLATFORM_SOURCES + linux/stlhack.cpp + ) +endif() + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/shared + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedDebug/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundation/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundationTypes/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedLog/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMath/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMathArchive/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMemoryManager/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMessageDispatch/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedNetwork/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedNetworkMessages/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedUtility/include/public + ${SWG_ENGINE_SOURCE_DIR}/shared/library/serverNetworkMessages/include/public + #${SWG_ENGINE_SOURCE_DIR}/shared/library/serverUtility/include/public + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/archive/include + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/localization/include + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/localizationArchive/include/public + #${SWG_EXTERNALS_SOURCE_DIR}/ours/library/singleton/include + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicode/include + ${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicodeArchive/include/public +) + +add_library(serverUtility STATIC + ${SHARED_SOURCES} + ${PLATFORM_SOURCES} +) diff --git a/engine/server/library/serverUtility/src/linux/stlhack.cpp b/engine/server/library/serverUtility/src/linux/stlhack.cpp new file mode 100644 index 00000000..3053178a --- /dev/null +++ b/engine/server/library/serverUtility/src/linux/stlhack.cpp @@ -0,0 +1,22 @@ +//#include "FirstGame.h" +#include //without this we get an internal compiler error + +// This resolves a problem with stlport compiling under gcc 2.91 that ships with RedHat 6.2. +// Basically, the compiler has trouble instantiating an instance of _Stl_prime without it +// being explicitly defined. So we have to instantiate one. +// We should try removing this file when either we a) upgrade the compiler or b) upgrate the OS. + +#define __stl_num_primes 28 +#define __PRIME_LIST_BODY { \ + 53ul, 97ul, 193ul, 389ul, 769ul, \ + 1543ul, 3079ul, 6151ul, 12289ul, 24593ul, \ + 49157ul, 98317ul, 196613ul, 393241ul, 786433ul, \ + 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul, \ + 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,\ + 1610612741ul, 3221225473ul, 4294967291ul \ +} + +template <> const size_t std::_Stl_prime::_M_list[__stl_num_primes] = __PRIME_LIST_BODY; + +#undef __stl_num_primes +#undef __PRIME_LIST_BODY diff --git a/engine/server/library/serverUtility/src/shared/AdminAccountManager.cpp b/engine/server/library/serverUtility/src/shared/AdminAccountManager.cpp new file mode 100644 index 00000000..85656cb2 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/AdminAccountManager.cpp @@ -0,0 +1,139 @@ +// AdminAccountManager.cpp +// copyright 2002 Sony Online Entertainment + +//----------------------------------------------------------------------- + +#include "serverUtility/FirstServerUtility.h" +#include "serverUtility/AdminAccountManager.h" + +#include "sharedFoundation/ExitChain.h" +#include "sharedUtility/DataTable.h" +#include "sharedUtility/DataTableManager.h" + +#include + +//----------------------------------------------------------------------- + +DataTable * AdminAccountManager::ms_adminTable = 0; +bool AdminAccountManager::ms_installed = false; +std::string *AdminAccountManager::ms_dataTableName = NULL; + +//----------------------------------------------------------------------- + +void AdminAccountManager::install(const std::string &dataTableName) +{ + DEBUG_FATAL(ms_installed, ("AdminAccountManager already installed")); + + ms_adminTable = DataTableManager::getTable (dataTableName, true); + DEBUG_FATAL(!ms_adminTable, ("Could not open admin file %s!", dataTableName.c_str())); + ms_installed = true; + + ms_dataTableName = new std::string(dataTableName); + + ExitChain::add(AdminAccountManager::remove, "DataTableManager::remove"); +} + +//----------------------------------------------------------------------- + +void AdminAccountManager::remove() +{ + DEBUG_FATAL(!ms_installed, ("AdminAccountManager not installed")); + NOT_NULL(ms_dataTableName); + DataTableManager::close(*ms_dataTableName); + ms_installed = false; + delete ms_dataTableName; + ms_dataTableName = NULL; +} + +//----------------------------------------------------------------------- + +const char *AdminAccountManager::getAdminCommandName() +{ + DEBUG_FATAL(!ms_installed, ("AdminAccountManager not installed")); + return ms_adminTable->getStringValue("AdminSkill", 0); +} + +//----------------------------------------------------------------------- + +const std::string & AdminAccountManager::getAdminTagName() +{ + static const std::string s = "*admin*"; + DEBUG_FATAL(!ms_installed, ("AdminAccountManager not installed")); + return s; +} + +//----------------------------------------------------------------------- + +bool AdminAccountManager::isAdminAccount(const std::string & account, int& level) +{ + level = 0; + DEBUG_FATAL(!ms_installed, ("AdminAccountManager not installed")); + + int columnNumber = ms_adminTable->findColumnNumber("AdminAccounts"); + DEBUG_FATAL(columnNumber == -1, ("Error loading admin table...no account column")); + int row = ms_adminTable->searchColumnString( columnNumber, account); + if (row == -1) + return false; + + level = ms_adminTable->getIntValue("AdminLevel", row); + return true; +} + +//----------------------------------------------------------------------- + +bool AdminAccountManager::isInternalIp(const std::string & addr) +{ + DEBUG_FATAL(!ms_installed, ("AdminAccountManager not installed")); + + std::vector ipAddrs; + ms_adminTable->getStringColumn("AdminIpBlocks", ipAddrs); + + bool retval = false; + + for (std::vector::iterator i = ipAddrs.begin(); i != ipAddrs.end(); ++i) + { + const std::string ipAddr(*i); + + //Check IP block + //Look for X in the IP block signifying a wild card. + size_t xpos = ipAddr.find ('x'); + + //if no X is found, do a straight compare + if ( (xpos == 0 || xpos == std::string::npos) + && ipAddr.compare(addr) == 0 + ) + { + retval = true; + } + + //we only want to compare up to the X, but if that is bigger that our addr + //we cannot compare the two, so return false. + else if (xpos - 1 > addr.size()) + retval = false; + + //compare substring + else if (ipAddr.compare(0, xpos - 1, addr, 0, xpos - 1) == 0) + { + retval = true; + } + + if (retval == true) + { + return true; + } + } + + + return retval; +} + +//----------------------------------------------------------------------- + +void AdminAccountManager::reload() +{ + DEBUG_FATAL(!ms_installed, ("AdminAccountManager not installed")); + NOT_NULL(ms_dataTableName); + DataTableManager::reload(*ms_dataTableName); +} + +//----------------------------------------------------------------------- diff --git a/engine/server/library/serverUtility/src/shared/AdminAccountManager.h b/engine/server/library/serverUtility/src/shared/AdminAccountManager.h new file mode 100644 index 00000000..d099b790 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/AdminAccountManager.h @@ -0,0 +1,40 @@ +// AdminAccountManager.h +// copyright 2002 Sony Online Entertainment +// Author: Justin Randall + +#ifndef _AdminAccountManager_H +#define _AdminAccountManager_H + +//----------------------------------------------------------------------- + +class DataTable; + +class AdminAccountManager +{ + +public: + static void install(const std::string &dataTableName); + static void remove(); + + static const char *getAdminCommandName(); + static const std::string & getAdminTagName(); + + static bool isAdminAccount(const std::string & account, int& level); + static bool isInternalIp(const std::string & addr); + static void reload(); + + +private: + AdminAccountManager(); + ~AdminAccountManager(); + + static DataTable * ms_adminTable; + static bool ms_installed; + static std::string * ms_dataTableName; + +}; + +//----------------------------------------------------------------------- + + +#endif diff --git a/engine/server/library/serverUtility/src/shared/ChatLogManager.cpp b/engine/server/library/serverUtility/src/shared/ChatLogManager.cpp new file mode 100644 index 00000000..5f3cd77c --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/ChatLogManager.cpp @@ -0,0 +1,489 @@ +// ============================================================================ +// +// ChatLogManager.cpp +// Copyright Sony Online Entertainment, Inc. +// +// ============================================================================ + +#include "serverUtility/FirstServerUtility.h" +#include "serverUtility/ChatLogManager.h" + +#include "serverUtility/ConfigServerUtility.h" +#include "sharedFoundation/LessPointerComparator.h" +#include "sharedFoundation/ExitChain.h" +#include "sharedFoundation/FormattedString.h" +#include "sharedFoundation/Os.h" +#include "sharedLog/Log.h" +#include "sharedNetworkMessages/ChatAvatarId.h" +#include "sharedNetworkMessages/MessageQueueSpatialChat.h" +#include "UnicodeUtils.h" + +#include +#include + +// ============================================================================ +// +// ChatLogManagerNamespace +// +// ============================================================================ + +namespace ChatLogManagerNamespace +{ + class ChatLogEntry + { + public: + + ChatLogEntry(Unicode::String const &fromPlayer, Unicode::String const &toPlayer, Unicode::String const *text, Unicode::String const &channel, time_t const time) + : m_fromPlayer(Unicode::toLower(fromPlayer)) + , m_toPlayer(Unicode::toLower(toPlayer)) + , m_text(text) + , m_channel(channel) + , m_time(time) + { + } + + Unicode::String const &getFromPlayer() const + { + return m_fromPlayer; + } + + Unicode::String const &getToPlayer() const + { + return m_toPlayer; + } + + Unicode::String const &getText() const + { + return *m_text; + } + + Unicode::String const &getChannel() const + { + return m_channel; + } + + time_t getTime() const + { + return m_time; + } + + private: + + Unicode::String m_fromPlayer; + Unicode::String m_toPlayer; + Unicode::String const *m_text; + Unicode::String m_channel; + time_t m_time; + + // Disabled + + ChatLogEntry(); + }; + + typedef std::list > TimeLog; + typedef std::map ChatLog; + typedef std::map PlayerLog; + typedef std::map MessageList; // Second parameter is the reference count + + TimeLog s_timeLog; + ChatLog s_chatLog; + PlayerLog s_playerLog; + MessageList s_chatMessageList; + time_t s_purgeTime = 0; + int s_currentIndex = 0; + time_t s_chatLogMemoryTimer = 0; + time_t const s_chatLogMemoryTime = 30; + int s_cacheHits = 0; + int s_cacheMisses = 0; + + void printPlayerLog(); + void addChatLogEntry(Unicode::String const &fromPlayer, Unicode::String const &toPlayer, Unicode::String const &message, Unicode::String const &channel, int const messageIndex, time_t const time); + bool removeChatLogEntry(int const messageIndex); + void purgeChatLog(); + std::string getTimeString(time_t const time); + std::string getTimeStringShort(time_t const time); +}; + +using namespace ChatLogManagerNamespace; + +//----------------------------------------------------------------------------- +void ChatLogManagerNamespace::printPlayerLog() +{ + LOGC(ConfigServerUtility::isChatLogManagerLoggingEnabled(), "ChatLogManager", ("-- ChatLogManagerNamespace::printPlayerLog() BEGIN -------------\n")); + PlayerLog::const_iterator iterPlayerLog = s_playerLog.begin(); + + for (; iterPlayerLog != s_playerLog.end(); ++iterPlayerLog) + { + LOGC(ConfigServerUtility::isChatLogManagerLoggingEnabled(), "ChatLogManager", ("player(%s) messages(%d)\n", Unicode::wideToNarrow(iterPlayerLog->first).c_str(), iterPlayerLog->second)); + } + + LOGC(ConfigServerUtility::isChatLogManagerLoggingEnabled(), "ChatLogManager", ("-- ChatLogManagerNamespace::printPlayerLog() END -------------\n")); +} + +//----------------------------------------------------------------------------- +void ChatLogManagerNamespace::addChatLogEntry(Unicode::String const &fromPlayer, Unicode::String const &toPlayer, Unicode::String const &message, Unicode::String const &channel, int const messageIndex, time_t const time) +{ + ChatLog::const_iterator iterChatLog = s_chatLog.find(messageIndex); + + if (iterChatLog != s_chatLog.end()) + { + // This string has already been added + + ++s_cacheHits; + + LOGC(ConfigServerUtility::isChatLogManagerLoggingEnabled(), "ChatLogManager", ("INSERT-HIT s_chatLog.size(%u) messageIndex(%d) time(%u) fromPlayer(%s) toPlayer(%s) channel(%s) text(%s)\n", s_chatLog.size(), messageIndex, iterChatLog->second.getTime(), Unicode::wideToNarrow(fromPlayer).c_str(), Unicode::wideToNarrow(toPlayer).c_str(), Unicode::wideToNarrow(channel).c_str(), Unicode::wideToNarrow(message).c_str())); + } + else + { + Unicode::String const *finalMessage = NULL; + + // Add the new string to the master message list, or if it already exists, just increase the reference count + + MessageList::iterator iterChatMessageList = s_chatMessageList.find(&message); + + if (iterChatMessageList != s_chatMessageList.end()) + { + // Increase the reference count + + ++iterChatMessageList->second; + + finalMessage = iterChatMessageList->first; + } + else + { + // Add the new message to the list + + finalMessage = new Unicode::String(message); + + s_chatMessageList.insert(std::make_pair(finalMessage, 1)); + } + + ++s_cacheMisses; + + s_timeLog.push_back(std::make_pair(time, messageIndex)); + s_chatLog.insert(std::make_pair(messageIndex, ChatLogEntry(fromPlayer, toPlayer, finalMessage, channel, time))); + + // Track the player's who are in the logs, and how many time they have messages in the logs + + Unicode::String const lowerFromPlayer(Unicode::toLower(fromPlayer)); + PlayerLog::iterator iterPlayerLog = s_playerLog.find(lowerFromPlayer); + + if (iterPlayerLog != s_playerLog.end()) + { + ++(iterPlayerLog->second); + } + else + { + s_playerLog.insert(std::make_pair(lowerFromPlayer, 1)); + } + + LOGC(ConfigServerUtility::isChatLogManagerLoggingEnabled(), "ChatLogManager", ("INSERT-MISS s_chatLog.size(%u) messageIndex(%d) time(%u) fromPlayer(%s) toPlayer(%s) channel(%s) text(%s)\n", s_chatLog.size(), messageIndex, time, Unicode::wideToNarrow(lowerFromPlayer).c_str(), Unicode::wideToNarrow(toPlayer).c_str(), Unicode::wideToNarrow(channel).c_str(), Unicode::wideToNarrow(message).c_str())); + } +} + +//----------------------------------------------------------------------------- +bool ChatLogManagerNamespace::removeChatLogEntry(int const messageIndex) +{ + bool result = false; + ChatLog::iterator iterChatLog = s_chatLog.find(messageIndex); + + if (iterChatLog != s_chatLog.end()) + { + result = true; + + // Remove the chat message + + Unicode::String const &message = iterChatLog->second.getText(); + MessageList::iterator iterChatMessageList = s_chatMessageList.find(&message); + + if (iterChatMessageList != s_chatMessageList.end()) + { + if (--iterChatMessageList->second <= 0) + { + // No more chat logs are referencing this message, we can remove it + + delete iterChatMessageList->first; + + s_chatMessageList.erase(iterChatMessageList); + } + } + else + { + DEBUG_WARNING(true, ("Master chat list does not contain message index(%d). This is a bug.", messageIndex)); + } + + // Remove the player log + + PlayerLog::iterator iterPlayerLog = s_playerLog.find(iterChatLog->second.getFromPlayer()); + + if (iterPlayerLog != s_playerLog.end()) + { + if (--iterPlayerLog->second <= 0) + { + s_playerLog.erase(iterPlayerLog); + } + } + else + { + DEBUG_WARNING(true, ("A player log was unable to be removed for %s", Unicode::wideToNarrow(iterChatLog->second.getFromPlayer()).c_str())); + } + + s_chatLog.erase(iterChatLog); + } + + return result; +} + +//----------------------------------------------------------------------------- +void ChatLogManagerNamespace::purgeChatLog() +{ + // This purges the list of old data once a second + + time_t const systemTime = Os::getRealSystemTime(); + + if (s_purgeTime != systemTime) + { + s_purgeTime = systemTime; + + time_t const chatLogPurgeTime = static_cast(ConfigServerUtility::getChatLogMinutes() * 60); + TimeLog::iterator iterTimeLog = s_timeLog.begin(); + int chatLogCount = static_cast(s_timeLog.size()); + int purgedMessages = 0; + + for (; iterTimeLog != s_timeLog.end(); ++iterTimeLog) + { + time_t const time = iterTimeLog->first; + + if ( (time < (systemTime - chatLogPurgeTime)) + || (static_cast(s_chatMessageList.size()) > ConfigServerUtility::getServerMaxChatLogLines())) + { + int const messageIndex = iterTimeLog->second; + + if (removeChatLogEntry(messageIndex)) + { + --chatLogCount; + ++purgedMessages; + + LOGC(ConfigServerUtility::isChatLogManagerLoggingEnabled(), "ChatLogManager", ("REMOVE index(%d) s_chatLog.size(%u) s_chatMessageList.size(%u)\n", messageIndex, s_chatLog.size(), s_chatMessageList.size())); + } + else + { + LOGC(ConfigServerUtility::isChatLogManagerLoggingEnabled(), "ChatLogManager", ("ERROR: REMOVE index(%d) Unable to resolve the message index in the chat log.\n", messageIndex)); + } + } + else + { + break; + } + } + + if (purgedMessages > 0) + { + // Remove the items from the time log + + s_timeLog.erase(s_timeLog.begin(), iterTimeLog); + } + + // Make sure the time log and chat log are equal in size, if not, then something is seriously wrong + + DEBUG_WARNING((s_timeLog.size() != s_chatLog.size()), ("ERROR: Time log and chat log are not the same size. This is a bug.")); + } +} + +//----------------------------------------------------------------------------- +std::string ChatLogManagerNamespace::getTimeString(time_t const time) +{ + std::string result(ctime(&time)); + + if (!result.empty()) + { + result.erase(result.size() - 1); + } + + return result; +} + +//----------------------------------------------------------------------------- +std::string ChatLogManagerNamespace::getTimeStringShort(time_t const time) +{ + std::string result(ctime(&time)); + + if (!result.empty()) + { + result = result.substr(11, 8); + } + + return result; +} + +// ============================================================================ +// +// ChatLogManager +// +// ============================================================================ + +//----------------------------------------------------------------------------- +void ChatLogManager::install() +{ + LOG("ChatLogManager", ("chatLogMinutes(%d)", ConfigServerUtility::getChatLogMinutes())); + LOG("ChatLogManager", ("serverMaxChatLogLines(%d)", ConfigServerUtility::getServerMaxChatLogLines())); + LOG("ChatLogManager", ("playerMaxChatLogLines(%d)", ConfigServerUtility::getPlayerMaxChatLogLines())); + LOG("ChatLogManager", ("chatLogManagerLoggingEnabled(%s)", ConfigServerUtility::isChatLogManagerLoggingEnabled() ? "yes" : "no")); + + ExitChain::add(&remove, "ChatLogManager::remove"); +} + +//----------------------------------------------------------------------------- +void ChatLogManager::remove() +{ + while (!s_chatMessageList.empty()) + { + MessageList::iterator iterMessageList = s_chatMessageList.begin(); + + delete iterMessageList->first; + + s_chatMessageList.erase(iterMessageList); + } +} + +//----------------------------------------------------------------------------- +void ChatLogManager::logChat(Unicode::String const & fromPlayer, Unicode::String const & toPlayer, Unicode::String const & message, Unicode::String const & channel, int const messageIndex, time_t const time) +{ + addChatLogEntry(fromPlayer, toPlayer, message, channel, messageIndex, time); + purgeChatLog(); + + if (ConfigServerUtility::isChatLogManagerLoggingEnabled()) + { + printPlayerLog(); + } +} + +//----------------------------------------------------------------------------- +int ChatLogManager::getNextMessageIndex() +{ + return s_currentIndex++; +} + +//----------------------------------------------------------------------------- +bool ChatLogManager::getChatMessage(int const messageIndex, Unicode::String &chatMessage) +{ + bool result = false; + ChatLog::const_iterator iterChatLog = s_chatLog.find(messageIndex); + + if (iterChatLog != s_chatLog.end()) + { + result = true; + chatMessage.clear(); + ChatLogEntry const &chatLogEntry = iterChatLog->second; + + buildLogEntry(chatMessage, chatLogEntry.getFromPlayer(), chatLogEntry.getToPlayer(), chatLogEntry.getText(), chatLogEntry.getChannel(), chatLogEntry.getTime()); + } + else + { + LOGC(ConfigServerUtility::isChatLogManagerLoggingEnabled(), "ChatLogManager", ("Unable to find chat log message(%d)\n", messageIndex)); + } + + return result; +} + +//----------------------------------------------------------------------------- +bool ChatLogManager::getChatMessage(int const messageIndex, Unicode::String &fromPlayer, Unicode::String &toPlayer, Unicode::String &text, Unicode::String &channel, time_t &time) +{ + bool result = false; + + ChatLog::const_iterator iterChatLog = s_chatLog.find(messageIndex); + + if (iterChatLog != s_chatLog.end()) + { + result = true; + ChatLogEntry const &chatLogEntry = iterChatLog->second; + + fromPlayer = chatLogEntry.getFromPlayer(); + toPlayer = chatLogEntry.getToPlayer(); + text = chatLogEntry.getText(); + channel = chatLogEntry.getChannel(); + time = chatLogEntry.getTime(); + } + else + { + DEBUG_WARNING(true, ("Unable to find chat log message(%d)\n", messageIndex)); + } + + return result; +} + +//----------------------------------------------------------------------------- +void ChatLogManager::buildLogEntry(Unicode::String &result, Unicode::String const &fromPlayer, Unicode::String const &toPlayer, Unicode::String const &message, Unicode::String const &channel, time_t const time) +{ + result.clear(); + result.append(Unicode::narrowToWide(getTimeStringShort(time))); + result.append(Unicode::narrowToWide(" [")); + result.append(channel); + result.append(Unicode::narrowToWide("] ")); + result.append(fromPlayer); + + if (!toPlayer.empty()) + { + result.append(Unicode::narrowToWide(" -> ")); + result.append(toPlayer); + } + + result.append(Unicode::narrowToWide(": ")); + result.append(message); + result.append(Unicode::narrowToWide("\n")); +} + +//----------------------------------------------------------------------------- +bool ChatLogManager::isPlayerInLogs(Unicode::String const &player) +{ + return (s_playerLog.find(Unicode::toLower(player)) != s_playerLog.end()); +} + +//----------------------------------------------------------------------------- +void ChatLogManager::getReportHeader(Unicode::String & header, std::string const &reportingPlayer, NetworkId const &reportingPlayerNetworkId, std::string const &reportingPlayerStationName, uint32 reportingPlayerStationId, std::string const &harassingPlayer, NetworkId const &harassingPlayerNetworkId, std::string const &harassingPlayerStationName, uint32 harassingPlayerStationId) +{ + header.clear(); + header.append(Unicode::narrowToWide("\n\n//--------------------------------------------------------\n")); + + FormattedString<512> fs; + + // Reporting + + header.append(Unicode::narrowToWide(fs.sprintf("Reporting: %s (%s)", reportingPlayer.c_str(), reportingPlayerNetworkId.getValueString().c_str()))); + + if (!reportingPlayerStationName.empty() || (reportingPlayerStationId > 0)) + { + header.append(Unicode::narrowToWide(" Station ID:")); + if (!reportingPlayerStationName.empty()) + header.append(Unicode::narrowToWide(fs.sprintf(" %s", reportingPlayerStationName.c_str()))); + if (reportingPlayerStationId > 0) + header.append(Unicode::narrowToWide(fs.sprintf(" (%lu)", reportingPlayerStationId))); + } + + header.append(Unicode::narrowToWide("\n")); + + // Harassing + + header.append(Unicode::narrowToWide(fs.sprintf("Harassing: %s (%s)", harassingPlayer.c_str(), harassingPlayerNetworkId.getValueString().c_str()))); + + if (!harassingPlayerStationName.empty() || (harassingPlayerStationId > 0)) + { + header.append(Unicode::narrowToWide(" Station ID:")); + if (!harassingPlayerStationName.empty()) + header.append(Unicode::narrowToWide(fs.sprintf(" %s", harassingPlayerStationName.c_str()))); + if (harassingPlayerStationId > 0) + header.append(Unicode::narrowToWide(fs.sprintf(" (%lu)", harassingPlayerStationId))); + } + + header.append(Unicode::narrowToWide("\n")); + + // Creation time + + header.append(Unicode::narrowToWide(fs.sprintf("Log Creation Time: %s\n", getTimeString(Os::getRealSystemTime()).c_str()))); + + // Time length + + header.append(Unicode::narrowToWide(fs.sprintf("Log Time Length: %d minutes\n", ConfigServerUtility::getChatLogMinutes()))); +} + +// ============================================================================ diff --git a/engine/server/library/serverUtility/src/shared/ChatLogManager.h b/engine/server/library/serverUtility/src/shared/ChatLogManager.h new file mode 100644 index 00000000..62ab60ad --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/ChatLogManager.h @@ -0,0 +1,41 @@ +// ============================================================================ +// +// ChatLogManager.h +// Copyright Sony Online Entertainment, Inc. +// +// ============================================================================ + +#ifndef INCLUDED_ChatLogManager_H +#define INCLUDED_ChatLogManager_H + +class NetworkId; + +//----------------------------------------------------------------------------- +class ChatLogManager +{ +public: + + static void install(); + static void remove(); + + static void logChat(Unicode::String const &fromPlayer, Unicode::String const &toPlayer, Unicode::String const &message, Unicode::String const &channel, int const messageIndex, time_t const time); + static bool getChatMessage(int const messageIndex, Unicode::String &fromPlayer, Unicode::String &toPlayer, Unicode::String &text, Unicode::String &channel, time_t &time); + static bool getChatMessage(int const messageIndex, Unicode::String &chatMessage); + static int getNextMessageIndex(); + static void buildLogEntry(Unicode::String &result, Unicode::String const &fromPlayer, Unicode::String const &toPlayer, Unicode::String const &message, Unicode::String const &channel, time_t const time); + static bool isPlayerInLogs(Unicode::String const &player); + static void getReportHeader(Unicode::String & header, std::string const &reportingPlayer, NetworkId const &reportingPlayerNetworkId, std::string const &reportingPlayerStationName, uint32 reportingPlayerStationId, std::string const &harassingPlayer, NetworkId const &harassingPlayerNetworkId, std::string const &harassingPlayerStationName, uint32 harassingPlayerStationId); + +private: + + // Disable + + ChatLogManager(); + ~ChatLogManager(); + ChatLogManager(ChatLogManager const &); + ChatLogManager &operator =(ChatLogManager const &); +}; + +// ============================================================================ + +#endif // INCLUDED_ChatLogManager_H diff --git a/engine/server/library/serverUtility/src/shared/ClusterWideDataManager.cpp b/engine/server/library/serverUtility/src/shared/ClusterWideDataManager.cpp new file mode 100644 index 00000000..a0abea38 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/ClusterWideDataManager.cpp @@ -0,0 +1,316 @@ +// ====================================================================== +// +// ClusterWideDataManager.cpp +// Copyright 2004 Sony Online Entertainment, Inc. +// All Rights Reserved. +// +// ====================================================================== + +#include "serverUtility/FirstServerUtility.h" +#include "serverUtility/ClusterWideDataManager.h" + +// ====================================================================== + +unsigned long ClusterWideDataManager::ms_lockKeyCounter = 0; + +// ====================================================================== + +ClusterWideDataManager::ClusterWideDataManager(std::string const & managerName) : + m_managerName(managerName), + m_dictionaryMap() +{ +} + +// ---------------------------------------------------------------------- + +ClusterWideDataManager::~ClusterWideDataManager() +{ +} + +// ---------------------------------------------------------------------- + +bool ClusterWideDataManager::getElement(std::string const & elementNameRegex, + bool const lockElements, + std::vector & elementNameList, + std::vector & elementDictionaryList, + unsigned long & lockKey) +{ + bool success = true; + + // allocate a new lock key; if we end up not actually + // using the new lock key, we will "put it back" + if (lockElements) + { + ++ms_lockKeyCounter; + + // handle wraparound + if (ms_lockKeyCounter == 0) + ms_lockKeyCounter = 1; + } + + elementNameList.clear(); + elementDictionaryList.clear(); + lockKey = 0; + + bool useRegexCompare = isElementNameRegex(elementNameRegex); + std::vector tempElementDictionaryList; + + for (ElementDataMap::iterator iter = m_dictionaryMap.begin(); iter != m_dictionaryMap.end(); ++iter) + { + if (isMatchElementName(elementNameRegex, iter->first, useRegexCompare)) + { + // if element is locked and request wanted to lock + // returned elements, don't need to look any further + if ((lockElements) && ((iter->second).lockKey > 0)) + { + success = false; + break; + } + + // found a match, add the element name to return list + elementNameList.push_back(iter->first); + + // if request wanted to lock returned elements, don't + // put the dictionary on the return list yet, because + // if it's a regular expression search, the request + // may still fail if a matching element after this + // is locked, and we will have wasted time putting + // the dictionary on the returned list, which makes + // a copy of the dictionary, which could be expensive; + // so we will put a reference to the dictionary into + // a temporary list, and at the end, copy them over + // into the return dictionary list + if (lockElements) + tempElementDictionaryList.push_back(&(iter->second)); + else + elementDictionaryList.push_back((iter->second).dictionary); + + // if not using regular expression, we already found + // the one match, so don't need to look any further + if (!useRegexCompare) + break; + } + } + + // if successful, copy matching dictionary from temp list to return list + if ((success) && (lockElements)) + { + for (std::vector::iterator iter2 = tempElementDictionaryList.begin(); iter2 != tempElementDictionaryList.end(); ++iter2) + { + // lock the elements in the return list + (*iter2)->lockKey = ms_lockKeyCounter; + + elementDictionaryList.push_back((*iter2)->dictionary); + } + + // return the lock key to the caller that can be used + // later to unlock the elements in the return list + if (!elementDictionaryList.empty()) + lockKey = ms_lockKeyCounter; + } + + // if new lock key was not used, "put it back" + if (lockElements) + { + if ((!success) || (elementDictionaryList.empty())) + --ms_lockKeyCounter; + } + + // if failure, make sure all return lists are empty + if (!success) + { + elementNameList.clear(); + elementDictionaryList.clear(); + } + + return success; +} + +// ---------------------------------------------------------------------- + +int ClusterWideDataManager::releaseLock(unsigned long const lockKey) +{ + // if no lock specified, no elements will be unlocked + if (lockKey == 0) + return 0; + + int numberElementsUnlocked = 0; + + for (ElementDataMap::iterator iter = m_dictionaryMap.begin(); iter != m_dictionaryMap.end(); ++iter) + { + if (((iter->second).lockKey > 0) && ((iter->second).lockKey == lockKey)) + { + (iter->second).lockKey = 0; + ++numberElementsUnlocked; + } + } + + return numberElementsUnlocked; +} + +// ---------------------------------------------------------------------- + +int ClusterWideDataManager::removeElement(std::string const & elementNameRegex, unsigned long const lockKey) +{ + // if no lock specified, no elements will be removed + if (lockKey == 0) + return 0; + + int numberElementsRemoved = 0; + bool useRegexCompare = isElementNameRegex(elementNameRegex); + + for (ElementDataMap::iterator iter = m_dictionaryMap.begin(); iter != m_dictionaryMap.end();) + { + if (isMatchElementName(elementNameRegex, iter->first, useRegexCompare)) + { + if (((iter->second).lockKey > 0) && ((iter->second).lockKey == lockKey)) + { + m_dictionaryMap.erase(iter++); + ++numberElementsRemoved; + } + else + { + ++iter; + } + + // if not using regular expression, we already found + // the one match, so don't need to look any further + if (!useRegexCompare) + break; + } + else + { + ++iter; + } + } + + return numberElementsRemoved; +} + +// ---------------------------------------------------------------------- + +int ClusterWideDataManager::removeElementByOwnerId(unsigned long const ownerId) +{ + // if no ownerId specified, no elements will be removed + if (ownerId == 0) + return 0; + + // remove elements regardless of whether they are locked or not + int numberElementsRemoved = 0; + + for (ElementDataMap::iterator iter = m_dictionaryMap.begin(); iter != m_dictionaryMap.end();) + { + if ((iter->second).ownerId == ownerId) + { + m_dictionaryMap.erase(iter++); + ++numberElementsRemoved; + } + else + { + ++iter; + } + } + + return numberElementsRemoved; +} + +// ---------------------------------------------------------------------- + +int ClusterWideDataManager::updateDictionary(std::string const & elementNameRegex, ValueDictionary const & dictionary, unsigned long const lockKey) +{ + return updateDictionaryHelper(elementNameRegex, dictionary, false, 0, lockKey); +} + +// ---------------------------------------------------------------------- + +int ClusterWideDataManager::replaceDictionary(std::string const & elementNameRegex, ValueDictionary const & dictionary, unsigned long const ownerId, unsigned long const lockKey) +{ + return updateDictionaryHelper(elementNameRegex, dictionary, true, ownerId, lockKey); +} + +// ---------------------------------------------------------------------- + +int ClusterWideDataManager::updateDictionaryHelper(std::string const & elementNameRegex, ValueDictionary const & dictionary, bool const overwriteDictionary, unsigned long const ownerId, unsigned long const lockKey) +{ + int numberElementsUpdated = 0; + bool foundMatch = false; + bool useRegexCompare = isElementNameRegex(elementNameRegex); + + for (ElementDataMap::iterator iter = m_dictionaryMap.begin(); iter != m_dictionaryMap.end(); ++iter) + { + if (isMatchElementName(elementNameRegex, iter->first, useRegexCompare)) + { + foundMatch = true; + + if (((iter->second).lockKey > 0) && ((iter->second).lockKey == lockKey)) + { + if (overwriteDictionary) + { + (iter->second).ownerId = ownerId; + (iter->second).dictionary = dictionary; + } + else + { + (iter->second).dictionary.insert(dictionary); + } + + ++numberElementsUpdated; + } + + // if not using regular expression, we already found + // the one match, so don't need to look any further + if (!useRegexCompare) + break; + } + } + + // if no match was found, and a single element was specified, + // and overwrite was specified, insert it + if ((!useRegexCompare) && (!foundMatch) && (overwriteDictionary)) + { + ElementData element; + element.lockKey = 0; + element.ownerId = ownerId; + element.dictionary = dictionary; + + m_dictionaryMap[elementNameRegex] = element; + + ++numberElementsUpdated; + } + + return numberElementsUpdated; +} + +// ---------------------------------------------------------------------- + +bool ClusterWideDataManager::isElementNameRegex(std::string const & elementNameRegex) +{ + // check for regular expression; currently we + // only support a single * at the end of the string + return ((elementNameRegex.length() > 0) && (elementNameRegex.rfind('*') == (elementNameRegex.length() - 1))); +} + +// ---------------------------------------------------------------------- + +bool ClusterWideDataManager::isMatchElementName(std::string const & elementNameRegex, std::string const & elementName, bool const useRegexCompare) +{ + if (useRegexCompare) + { + if (elementNameRegex.length() == 1) + { + return true; + } + else + { + // currently, the only regular expression we support + // is a single * at the end of the string + return (strncmp(elementNameRegex.c_str(), elementName.c_str(), elementNameRegex.length() - 1) == 0); + } + } + else + { + return (elementNameRegex == elementName); + } +} + +// ====================================================================== diff --git a/engine/server/library/serverUtility/src/shared/ClusterWideDataManager.h b/engine/server/library/serverUtility/src/shared/ClusterWideDataManager.h new file mode 100644 index 00000000..cc5e5e8b --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/ClusterWideDataManager.h @@ -0,0 +1,80 @@ +// ====================================================================== +// +// ClusterWideDataManager.h +// Copyright 2004 Sony Online Entertainment, Inc. +// All Rights Reserved. +// +// ====================================================================== + +#ifndef INCLUDED_ClusterWideDataManager_H +#define INCLUDED_ClusterWideDataManager_H + +// ====================================================================== + +#include "sharedUtility/ValueDictionary.h" + +#include +#include +#include + +// ====================================================================== + +class ClusterWideDataManager +{ +public: //ctor/dtor + ClusterWideDataManager(std::string const & managerName); + ~ClusterWideDataManager(); + +public: // methods + std::string const & getManagerName() const; + bool getElement(std::string const & elementNameRegex, + bool lockElements, + std::vector & elementNameList, + std::vector & elementDictionaryList, + unsigned long & lockKey); + int releaseLock(unsigned long lockKey); + int removeElement(std::string const & elementNameRegex, unsigned long lockKey); + int removeElementByOwnerId(unsigned long ownerId); + int updateDictionary(std::string const & elementNameRegex, ValueDictionary const & dictionary, unsigned long lockKey); + int replaceDictionary(std::string const & elementNameRegex, ValueDictionary const & dictionary, unsigned long ownerId, unsigned long lockKey); + +private: // helper function + int updateDictionaryHelper(std::string const & elementNameRegex, ValueDictionary const & dictionary, bool overwriteDictionary, unsigned long ownerId, unsigned long lockKey); + static bool isElementNameRegex(std::string const & elementNameRegex); + static bool isMatchElementName(std::string const & elementNameRegex, std::string const & elementName, bool useRegexCompare); + +private: // data structures + struct ElementData + { + ElementData() : lockKey(0), ownerId(0) {}; + + unsigned long lockKey; + unsigned long ownerId; + ValueDictionary dictionary; + }; + + typedef std::map ElementDataMap; + +private: + std::string const m_managerName; + ElementDataMap m_dictionaryMap; + + // for assigning lock keys + static unsigned long ms_lockKeyCounter; + + // Disabled. + ClusterWideDataManager(); + ClusterWideDataManager(ClusterWideDataManager const &); + ClusterWideDataManager &operator =(ClusterWideDataManager const &); +}; + +//----------------------------------------------------------------------- + +inline std::string const & ClusterWideDataManager::getManagerName() const +{ + return m_managerName; +} + +// ====================================================================== + +#endif diff --git a/engine/server/library/serverUtility/src/shared/ClusterWideDataManagerList.cpp b/engine/server/library/serverUtility/src/shared/ClusterWideDataManagerList.cpp new file mode 100644 index 00000000..659f1c61 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/ClusterWideDataManagerList.cpp @@ -0,0 +1,574 @@ +// ====================================================================== +// +// ClusterWideDataManagerList.cpp +// Copyright 2004 Sony Online Entertainment, Inc. +// All Rights Reserved. +// +// ====================================================================== + +#include "serverUtility/FirstServerUtility.h" +#include "serverUtility/ClusterWideDataManagerList.h" + +#include "serverUtility/ClusterWideDataManager.h" +#include "serverUtility/ServerConnection.h" +#include "sharedFoundation/ExitChain.h" +#include "sharedLog/Log.h" +#include "sharedMessageDispatch/Receiver.h" +#include "sharedNetworkMessages/ClusterWideDataGetElementMessage.h" +#include "sharedNetworkMessages/ClusterWideDataGetElementResponseMessage.h" +#include "sharedNetworkMessages/ClusterWideDataReleaseLockMessage.h" +#include "sharedNetworkMessages/ClusterWideDataRemoveElementMessage.h" +#include "sharedNetworkMessages/ClusterWideDataUpdateDictionaryMessage.h" +#include "sharedUtility/ValueDictionaryArchive.h" + +// ====================================================================== + +namespace ClusterWideDataManagerListNamespace +{ + struct LockInfo + { + LockInfo() : lockKey(0), lockTime(0.0), managerName() {}; + + unsigned long lockKey; + float lockTime; + std::string managerName; + }; + + struct QueuedRequestInfo + { + QueuedRequestInfo() : processId(0), requestTime(0.0), request(NULL), server(NULL) {}; + + unsigned long processId; + float requestTime; + ClusterWideDataGetElementMessage * request; + ServerConnection * server; + }; + + typedef std::map QueuedRequestList; + + typedef std::multimap ServerLockList; + typedef std::pair ServerLockListConstRange; + typedef std::pair ServerLockListRange; + + typedef std::map ManagerList; + + typedef std::map LockTimeList; + + // tracks requests which are queued because elements are locked + unsigned long s_queuedRequestNumber = 0; + QueuedRequestList s_queuedRequestList; + + // tracks servers and the locks they own + ServerLockList s_serverLockList; + + // tracks the different Cluster wide data managers + ManagerList s_managerList; + + // tracks when locks are assigned so they can be automatically released + // after a certain amount of time and the owner hasn't release them yet + float s_oldestLockAge = 0.0; + int s_lockTimeoutValue = 0; + LockTimeList s_lockTimeList; + + // accumulate game time to be used in detecting expired locks + float s_totalGameTime = 0.0; + + ClusterWideDataManager * getClusterWideDataManager(std::string const & managerName, bool const createIfNotExist); + void processQueuedRequests(); + bool handleClusterWideDataGetElementMessage(ClusterWideDataGetElementMessage const & msg, ServerConnection & server); + void handleClusterWideDataReleaseLockMessage(ClusterWideDataReleaseLockMessage const & msg, ServerConnection const & server); + void handleClusterWideDataRemoveElementMessage(ClusterWideDataRemoveElementMessage const & msg, ServerConnection const & server); + void handleClusterWideDataUpdateDictionaryMessage(ClusterWideDataUpdateDictionaryMessage const & msg, ServerConnection const & server); + void removeFromLockTimeList(unsigned long const lockKey); + void removeExpiredLocks(); +} + +// ---------------------------------------------------------------------- + +void ClusterWideDataManagerList::install() +{ + ExitChain::add(remove, "ClusterWideDataManagerList"); +} + +// ---------------------------------------------------------------------- + +void ClusterWideDataManagerList::remove() +{ + // clear up queued requests + for (ClusterWideDataManagerListNamespace::QueuedRequestList::iterator iter = ClusterWideDataManagerListNamespace::s_queuedRequestList.begin(); iter != ClusterWideDataManagerListNamespace::s_queuedRequestList.end(); ++iter) + delete iter->second.request; + + ClusterWideDataManagerListNamespace::s_queuedRequestList.clear(); + + // clear up cluster wide data managers + for (ClusterWideDataManagerListNamespace::ManagerList::iterator iter2 = ClusterWideDataManagerListNamespace::s_managerList.begin(); iter2 != ClusterWideDataManagerListNamespace::s_managerList.end(); ++iter2) + delete iter2->second; + + ClusterWideDataManagerListNamespace::s_managerList.clear(); + + // clear up lock lists + ClusterWideDataManagerListNamespace::s_serverLockList.clear(); + ClusterWideDataManagerListNamespace::s_lockTimeList.clear(); +} + +// ---------------------------------------------------------------------- + +void ClusterWideDataManagerList::update(float time) +{ + // accumulate game time + ClusterWideDataManagerListNamespace::s_totalGameTime += time; + + // handle and locks that have expired + ClusterWideDataManagerListNamespace::removeExpiredLocks(); +} + +// ---------------------------------------------------------------------- + +void ClusterWideDataManagerList::registerMessage(MessageDispatch::Receiver & messageReceiver) +{ + messageReceiver.connectToMessage(ClusterWideDataGetElementMessage::ms_messageName.c_str()); + messageReceiver.connectToMessage(ClusterWideDataReleaseLockMessage::ms_messageName.c_str()); + messageReceiver.connectToMessage(ClusterWideDataRemoveElementMessage::ms_messageName.c_str()); + messageReceiver.connectToMessage(ClusterWideDataUpdateDictionaryMessage::ms_messageName.c_str()); +} + +// ---------------------------------------------------------------------- + +bool ClusterWideDataManagerList::handleMessage(const MessageDispatch::Emitter & source, const MessageDispatch::MessageBase & message) +{ + bool handledMessage = false; + + if (message.isType(ClusterWideDataGetElementMessage::ms_messageName.c_str())) + { + handledMessage = true; + + Archive::ReadIterator ri = safe_cast(&message)->getByteStream().begin(); + + // dynamic allocation because if the request needs to be queued, + // we will store the message off for later processing + ClusterWideDataGetElementMessage * msg = new ClusterWideDataGetElementMessage(ri); + + // need to cast away const here because we need to send response + // back to source and ServerConnection::send() is non-const + ServerConnection * server = const_cast(dynamic_cast(&source)); + if (server) + { + if (ClusterWideDataManagerListNamespace::handleClusterWideDataGetElementMessage(*msg, *server)) + { + delete msg; + } + else + { + // some elements were locked, queue the request for later processing + LOG("ClusterWideDataManagerList", ("Queuing request from server (%lu), manager name (%s), element name regex (%s), lock elements (%s), request Id (%lu)", server->getProcessId(), msg->getManagerName().c_str(), msg->getElementNameRegex().c_str(), (msg->getLockElements() ? "true" : "false"), msg->getRequestId())); + + ClusterWideDataManagerListNamespace::QueuedRequestInfo info; + info.processId = server->getProcessId(); + info.requestTime = ClusterWideDataManagerListNamespace::s_totalGameTime; + info.request = msg; + info.server = server; + + ClusterWideDataManagerListNamespace::s_queuedRequestList[++ClusterWideDataManagerListNamespace::s_queuedRequestNumber] = info; + } + } + else + { + WARNING(true, ("Received ClusterWideDataGetElementMessage but not from a game server - manager name (%s), element name regex (%s), lock elements (%s), request Id (%lu)", msg->getManagerName().c_str(), msg->getElementNameRegex().c_str(), (msg->getLockElements() ? "true" : "false"), msg->getRequestId())); + delete msg; + } + } + else if (message.isType(ClusterWideDataReleaseLockMessage::ms_messageName.c_str())) + { + handledMessage = true; + + Archive::ReadIterator ri = safe_cast(&message)->getByteStream().begin(); + ClusterWideDataReleaseLockMessage msg(ri); + + ServerConnection const * server = dynamic_cast(&source); + if (server) + { + ClusterWideDataManagerListNamespace::handleClusterWideDataReleaseLockMessage(msg, *server); + } + else + { + WARNING(true, ("Received ClusterWideDataReleaseLockMessage but not from a game server - manager name (%s), lock key (%lu)", msg.getManagerName().c_str(), msg.getLockKey())); + } + } + else if (message.isType(ClusterWideDataRemoveElementMessage::ms_messageName.c_str())) + { + handledMessage = true; + + Archive::ReadIterator ri = safe_cast(&message)->getByteStream().begin(); + ClusterWideDataRemoveElementMessage msg(ri); + + ServerConnection const * server = dynamic_cast(&source); + if (server) + { + ClusterWideDataManagerListNamespace::handleClusterWideDataRemoveElementMessage(msg, *server); + } + else + { + WARNING(true, ("Received ClusterWideDataRemoveElementMessage but not from a game server - manager name (%s), element name regex (%s)", msg.getManagerName().c_str(), msg.getElementNameRegex().c_str())); + } + } + else if (message.isType(ClusterWideDataUpdateDictionaryMessage::ms_messageName.c_str())) + { + handledMessage = true; + + Archive::ReadIterator ri = safe_cast(&message)->getByteStream().begin(); + ClusterWideDataUpdateDictionaryMessage msg(ri); + + ServerConnection const * server = dynamic_cast(&source); + if (server) + { + ClusterWideDataManagerListNamespace::handleClusterWideDataUpdateDictionaryMessage(msg, *server); + } + else + { + WARNING(true, ("Received ClusterWideDataUpdateDictionaryMessage but not from a game server - manager name (%s), element name regex (%s), replace dictionary (%s)", msg.getManagerName().c_str(), msg.getElementNameRegex().c_str(), (msg.getReplaceDictionary() ? "yes" : "no"))); + } + } + + return handledMessage; +} + +// ---------------------------------------------------------------------- + +void ClusterWideDataManagerList::onGameServerDisconnect(unsigned long const processId) +{ + // remove any queued messages for the disconnected server + int requestsDeleted = 0; + + for (ClusterWideDataManagerListNamespace::QueuedRequestList::iterator iter = ClusterWideDataManagerListNamespace::s_queuedRequestList.begin(); iter != ClusterWideDataManagerListNamespace::s_queuedRequestList.end();) + { + if (iter->second.processId == processId) + { + delete iter->second.request; + ClusterWideDataManagerListNamespace::s_queuedRequestList.erase(iter++); + ++requestsDeleted; + } + else + { + ++iter; + } + } + + if (requestsDeleted > 0) + LOG("ClusterWideDataManagerList", ("Removed (%d) pending requests for disconnected server (%lu)", requestsDeleted, processId)); + + // remove any "auto remove" elements owned by the server + int elementsRemoved = 0; + + for (ClusterWideDataManagerListNamespace::ManagerList::const_iterator iter3 = ClusterWideDataManagerListNamespace::s_managerList.begin(); iter3 != ClusterWideDataManagerListNamespace::s_managerList.end(); ++iter3) + { + elementsRemoved += iter3->second->removeElementByOwnerId(processId); + } + + if (elementsRemoved > 0) + LOG("ClusterWideDataManagerList", ("Removed (%d) elements for disconnected server (%lu)", elementsRemoved, processId)); + + // if server has any outstanding locks, unlock those elements + int elementsUnlocked = 0; + + ClusterWideDataManagerListNamespace::ServerLockListConstRange range = ClusterWideDataManagerListNamespace::s_serverLockList.equal_range(processId); + + ClusterWideDataManager * manager = NULL; + for (ClusterWideDataManagerListNamespace::ServerLockList::const_iterator iter2 = range.first; iter2 != range.second; ++iter2) + { + manager = ClusterWideDataManagerListNamespace::getClusterWideDataManager((iter2->second).managerName, false); + if (manager) + elementsUnlocked += manager->releaseLock((iter2->second).lockKey); + else + WARNING(true, ("ClusterWideDataManager (%s) not found for lock (%lu) owned by disconnected server (%lu)", (iter2->second).managerName.c_str(), (iter2->second).lockKey, processId)); + + ClusterWideDataManagerListNamespace::removeFromLockTimeList((iter2->second).lockKey); + } + + unsigned int locksDeleted = ClusterWideDataManagerListNamespace::s_serverLockList.erase(processId); + + if (locksDeleted > 0) + LOG("ClusterWideDataManagerList", ("Removed (%d) locks and unlocked (%d) elements for disconnected server (%lu)", locksDeleted, elementsUnlocked, processId)); + + // if any locks were released or any elements were removed, + // then some elements may now be unlocked, so go through + // the queued requests and process them + if ((elementsUnlocked > 0) || (elementsRemoved > 0)) + ClusterWideDataManagerListNamespace::processQueuedRequests(); +} + +// ---------------------------------------------------------------------- + +void ClusterWideDataManagerList::setLockTimeoutValue(int const timeout) +{ + LOG("ClusterWideDataManagerList", ("Setting lock timeout value to (%d) seconds", timeout)); + + ClusterWideDataManagerListNamespace::s_lockTimeoutValue = timeout; +} + +// ---------------------------------------------------------------------- + +int ClusterWideDataManagerList::getNumberOfQueuedRequests() +{ + return ClusterWideDataManagerListNamespace::s_queuedRequestList.size(); +} + +// ---------------------------------------------------------------------- + +ClusterWideDataManager * ClusterWideDataManagerListNamespace::getClusterWideDataManager(std::string const & managerName, bool const createIfNotExist) +{ + ManagerList::iterator iter = s_managerList.find(managerName); + if (iter != s_managerList.end()) + return iter->second; + + if (createIfNotExist) + { + ClusterWideDataManager * manager = new ClusterWideDataManager(managerName); + s_managerList[managerName] = manager; + return manager; + } + + return NULL; +} + +// ---------------------------------------------------------------------- + +void ClusterWideDataManagerListNamespace::processQueuedRequests() +{ + for (QueuedRequestList::iterator iter = s_queuedRequestList.begin(); iter != s_queuedRequestList.end();) + { + if (handleClusterWideDataGetElementMessage(*(iter->second.request), *(iter->second.server))) + { + delete iter->second.request; + s_queuedRequestList.erase(iter++); + } + else + { + ++iter; + } + } +} + +// ---------------------------------------------------------------------- + +bool ClusterWideDataManagerListNamespace::handleClusterWideDataGetElementMessage(ClusterWideDataGetElementMessage const & msg, ServerConnection & server) +{ + bool success = true; + + std::vector elementNameList; + std::vector elementDictionaryList; + unsigned long lockKey = 0; + + ClusterWideDataManager * manager = getClusterWideDataManager(msg.getManagerName(), false); + if (manager) + { + success = manager->getElement(msg.getElementNameRegex(), msg.getLockElements(), elementNameList, elementDictionaryList, lockKey); + } + + if (success) + { + // cut down on the log spam; don't log "browse" requests + if (lockKey > 0) + LOG("ClusterWideDataManagerList", ("Returned (%d) elements to server (%lu), manager name (%s), element name regex (%s), lock elements (%s), request Id (%lu), lock key (%lu)", elementNameList.size(), server.getProcessId(), msg.getManagerName().c_str(), msg.getElementNameRegex().c_str(), (msg.getLockElements() ? "true" : "false"), msg.getRequestId(), lockKey)); + + // send response + ClusterWideDataGetElementResponseMessage resp(msg.getManagerName(), msg.getElementNameRegex(), elementNameList, elementDictionaryList, msg.getRequestId(), lockKey); + server.send(resp, true); + + // if a lock was acquired, add it to the lock list so if + // the server goes down, we can unlock the locked elements + if (lockKey > 0) + { + LockInfo info; + info.lockKey = lockKey; + info.lockTime = s_totalGameTime; + info.managerName = msg.getManagerName(); + + IGNORE_RETURN(s_serverLockList.insert(ServerLockList::value_type(server.getProcessId(), info))); + + s_lockTimeList[lockKey] = info.lockTime; + + if (s_lockTimeList.size() == 1) + s_oldestLockAge = info.lockTime; + } + } + + return success; +} + +// ---------------------------------------------------------------------- + +void ClusterWideDataManagerListNamespace::handleClusterWideDataReleaseLockMessage(ClusterWideDataReleaseLockMessage const & msg, ServerConnection const & server) +{ + // remove the lock from the lock list + bool foundLockToRemove = false; + ServerLockListRange range = s_serverLockList.equal_range(server.getProcessId()); + ServerLockList::iterator iter; + for (iter = range.first; iter != range.second; ++iter) + { + if ((iter->second).lockKey == msg.getLockKey()) + { + if ((iter->second).managerName == msg.getManagerName()) + foundLockToRemove = true; + else + WARNING(true, ("ClusterWideDataManagerList received request to unlock lock (%lu) with incorrect manager (%s) where correct manager is (%s)", msg.getLockKey(), (msg.getManagerName()).c_str(), ((iter->second).managerName).c_str())); + break; + } + } + + if (foundLockToRemove) + { + // if we found a lock to remove in the ServerLockList, we remove it from the manager and the list + ClusterWideDataManager * manager = getClusterWideDataManager(msg.getManagerName(), false); + if (manager) + { + s_serverLockList.erase(iter); + ClusterWideDataManagerListNamespace::removeFromLockTimeList(msg.getLockKey()); + + int numberElementsUnlocked = manager->releaseLock(msg.getLockKey()); + + LOG("ClusterWideDataManagerList", ("Unlocked (%d) elements for server (%lu), manager name (%s), lock key (%lu)", numberElementsUnlocked, server.getProcessId(), msg.getManagerName().c_str(), msg.getLockKey())); + + // if any elements were unlocked, so go through the queued requests and process them + if (numberElementsUnlocked > 0) + processQueuedRequests(); + } + else + LOG("ClusterWideDataManagerList", ("ClusterWideDataManagerList received request to unlock lock but could not get a ClusterWideDataManager for manager name (%s), lock key (%lu)", msg.getManagerName().c_str(), msg.getLockKey())); + } + else if (iter == range.second) + LOG("ClusterWideDataManagerList", ("ClusterWideDataManagerList received request to unlock lock but could not find any locks with matching lock key: manager name (%s), lock key (%lu)", msg.getManagerName().c_str(), msg.getLockKey())); +} + +// ---------------------------------------------------------------------- + +void ClusterWideDataManagerListNamespace::handleClusterWideDataRemoveElementMessage(ClusterWideDataRemoveElementMessage const & msg, ServerConnection const & server) +{ + ClusterWideDataManager * manager = getClusterWideDataManager(msg.getManagerName(), false); + if (manager) + { + int numberElementsRemoved = manager->removeElement(msg.getElementNameRegex(), msg.getLockKey()); + + LOG("ClusterWideDataManagerList", ("Removed (%d) elements for server (%lu), manager name (%s), element name regex (%s), lock key (%lu)", numberElementsRemoved, server.getProcessId(), msg.getManagerName().c_str(), msg.getElementNameRegex().c_str(), msg.getLockKey())); + + // if any elements were removed, so go through the queued requests and process them + if (numberElementsRemoved > 0) + processQueuedRequests(); + } +} + +// ---------------------------------------------------------------------- + +void ClusterWideDataManagerListNamespace::handleClusterWideDataUpdateDictionaryMessage(ClusterWideDataUpdateDictionaryMessage const & msg, ServerConnection const & server) +{ + ClusterWideDataManager * manager = getClusterWideDataManager(msg.getManagerName(), true); + if (manager) + { + if (msg.getReplaceDictionary()) + { + int numberElementsReplaced = manager->replaceDictionary(msg.getElementNameRegex(), msg.getDictionary(), (msg.getAutoRemove() ? server.getProcessId() : 0) , msg.getLockKey()); + + LOG("ClusterWideDataManagerList", ("Replaced (%d) elements for server (%lu), manager name (%s), element name regex (%s), auto remove (%s), lock key (%lu)", numberElementsReplaced, server.getProcessId(), msg.getManagerName().c_str(), msg.getElementNameRegex().c_str(), (msg.getAutoRemove() ? "yes" : "no"), msg.getLockKey())); + } + else + { + int numberElementsUpdated = manager->updateDictionary(msg.getElementNameRegex(), msg.getDictionary(), msg.getLockKey()); + + LOG("ClusterWideDataManagerList", ("Updated (%d) elements for server (%lu), manager name (%s), element name regex (%s), lock key (%lu)", numberElementsUpdated, server.getProcessId(), msg.getManagerName().c_str(), msg.getElementNameRegex().c_str(), msg.getLockKey())); + } + } +} + +// ---------------------------------------------------------------------- + +void ClusterWideDataManagerListNamespace::removeFromLockTimeList(unsigned long const lockKey) +{ + IGNORE_RETURN(s_lockTimeList.erase(lockKey)); + + if (!ClusterWideDataManagerListNamespace::s_lockTimeList.empty()) + ClusterWideDataManagerListNamespace::s_oldestLockAge = ClusterWideDataManagerListNamespace::s_lockTimeList.begin()->second; + else + ClusterWideDataManagerListNamespace::s_oldestLockAge = 0.0; +} + +// ---------------------------------------------------------------------- + +void ClusterWideDataManagerListNamespace::removeExpiredLocks() +{ + if (s_lockTimeoutValue <= 0) + return; + + if (s_oldestLockAge == 0.0) + return; + + if ((s_totalGameTime - s_oldestLockAge) < static_cast(s_lockTimeoutValue)) + return; + + if (s_lockTimeList.empty()) + { + WARNING(true, ("ClusterWideDataManagerList mismatch - age of the oldest lock is (%.2f seconds), but there are no locks in the lock time list", (s_totalGameTime - s_oldestLockAge))); + + s_oldestLockAge = 0.0; + + return; + } + + // get the lock key that has expired + unsigned long oldestLockKey = 0; + + // limit the scope of iter + { + LockTimeList::iterator iter = s_lockTimeList.begin(); + if (iter->second != s_oldestLockAge) //lint !e777 // we compare these two float values because we expect them to be bitwise identical + { + WARNING(true, ("ClusterWideDataManagerList mismatch between perceived age of the oldest lock (%.2f seconds), and the actual age of the oldest lock (%.2f seconds), lock key (%lu)", (s_totalGameTime - s_oldestLockAge), (s_totalGameTime - iter->second), iter->first)); + + s_oldestLockAge = iter->second; + + return; + } + + // remove the lock from the lock time list + oldestLockKey = iter->first; + + // ***iter is invalid after this call; also the call will change s_oldestLockAge + // to be the age of the next oldest lock, or 0 if there are no more locks*** + removeFromLockTimeList(oldestLockKey); + } + + // find the lock info for the expired lock key + ServerLockList::iterator iter2 = s_serverLockList.begin(); + for (; iter2 != s_serverLockList.end(); ++iter2) + { + if ((iter2->second).lockKey == oldestLockKey) + break; + } + + if (iter2 == s_serverLockList.end()) + { + WARNING(true, ("ClusterWideDataManagerList could not locate lock info for expired lock key (%lu)", oldestLockKey)); + return; + } + + // release the locked elements + int numberElementsUnlocked = 0; + ClusterWideDataManager * manager = getClusterWideDataManager((iter2->second).managerName, false); + if (manager) + { + numberElementsUnlocked = manager->releaseLock((iter2->second).lockKey); + + LOG("ClusterWideDataManagerList", ("Unlocked (%d) elements for expired lock key (%lu) owned by server (%lu)", numberElementsUnlocked, (iter2->second).lockKey, iter2->first)); + } + else + { + WARNING(true, ("ClusterWideDataManager (%s) not found for expired lock key (%lu) owned by server (%lu)", (iter2->second).managerName.c_str(), (iter2->second).lockKey, iter2->first)); + } + + // remove the lock from the lock list + s_serverLockList.erase(iter2); + + // if any elements were unlocked, so go through the queued requests and process them + if (numberElementsUnlocked > 0) + processQueuedRequests(); +} + +// ====================================================================== diff --git a/engine/server/library/serverUtility/src/shared/ClusterWideDataManagerList.h b/engine/server/library/serverUtility/src/shared/ClusterWideDataManagerList.h new file mode 100644 index 00000000..1b14a9a4 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/ClusterWideDataManagerList.h @@ -0,0 +1,40 @@ +// ====================================================================== +// +// ClusterWideDataManagerList.h +// Copyright 2004 Sony Online Entertainment, Inc. +// All Rights Reserved. +// +// ====================================================================== + +#ifndef INCLUDED_ClusterWideDataManagerList_H +#define INCLUDED_ClusterWideDataManagerList_H + +// ====================================================================== + +namespace MessageDispatch +{ + class Emitter; + class MessageBase; + class Receiver; +} + +// ====================================================================== + +class ClusterWideDataManagerList +{ +public: + + static void install(); + static void remove(); + static void update(float time); + + static void registerMessage(MessageDispatch::Receiver & messageReceiver); + static bool handleMessage(MessageDispatch::Emitter const & source, MessageDispatch::MessageBase const & message); + static void onGameServerDisconnect(unsigned long processId); + static void setLockTimeoutValue(int timeout); + static int getNumberOfQueuedRequests(); +}; + +// ====================================================================== + +#endif diff --git a/engine/server/library/serverUtility/src/shared/ConfigServerUtility.cpp b/engine/server/library/serverUtility/src/shared/ConfigServerUtility.cpp new file mode 100644 index 00000000..83d3230c --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/ConfigServerUtility.cpp @@ -0,0 +1,94 @@ +// ConfigServerUtility.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +//----------------------------------------------------------------------- + +#include "serverUtility/FirstServerUtility.h" +#include "serverUtility/ConfigServerUtility.h" +#include "sharedFoundation/ConfigFile.h" + +//----------------------------------------------------------------------- + +namespace ConfigServerUtilityNamespace +{ + int spawnCookie; + int chatLogMinutes; + int serverMaxChatLogLines; + int playerMaxChatLogLines; + bool chatLogManagerLoggingEnabled; +} + +using namespace ConfigServerUtilityNamespace; + +#define KEY_INT(a,b) (a = ConfigFile::getKeyInt("ServerUtility", #a, b)) +#define KEY_BOOL(a,b) (a = ConfigFile::getKeyBool("ServerUtility", #a, b)) +#define KEY_FLOAT(a,b) (a = ConfigFile::getKeyFloat("ServerUtility", #a, b)) +#define KEY_STRING(a,b) (a = ConfigFile::getKeyString("ServerUtility", #a, b)) + +//----------------------------------------------------------------------- + +ConfigServerUtility::ConfigServerUtility() +{ +} + +//----------------------------------------------------------------------- + +ConfigServerUtility::~ConfigServerUtility() +{ +} + +//----------------------------------------------------------------------- + +int ConfigServerUtility::getSpawnCookie() +{ + return spawnCookie; +} + +//----------------------------------------------------------------------- + +int ConfigServerUtility::getChatLogMinutes() +{ + return chatLogMinutes; +} + +//----------------------------------------------------------------------- + +int ConfigServerUtility::getServerMaxChatLogLines() +{ + return serverMaxChatLogLines; +} + +//----------------------------------------------------------------------- + +int ConfigServerUtility::getPlayerMaxChatLogLines() +{ + return playerMaxChatLogLines; +} + +//----------------------------------------------------------------------- + +bool ConfigServerUtility::isChatLogManagerLoggingEnabled() +{ + return chatLogManagerLoggingEnabled; +} + +//----------------------------------------------------------------------- + +void ConfigServerUtility::install() +{ + KEY_INT(spawnCookie, 0); + KEY_INT(chatLogMinutes, 10); + KEY_INT(serverMaxChatLogLines, 5000); + KEY_INT(playerMaxChatLogLines, 200); + KEY_BOOL(chatLogManagerLoggingEnabled, false); +} + +//----------------------------------------------------------------------- + +void ConfigServerUtility::remove() +{ +} + +//----------------------------------------------------------------------- + diff --git a/engine/server/library/serverUtility/src/shared/ConfigServerUtility.h b/engine/server/library/serverUtility/src/shared/ConfigServerUtility.h new file mode 100644 index 00000000..33f0db04 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/ConfigServerUtility.h @@ -0,0 +1,33 @@ +// ConfigServerUtility.h +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +#ifndef _INCLUDED_ConfigServerUtility_H +#define _INCLUDED_ConfigServerUtility_H + +//----------------------------------------------------------------------- + +class ConfigServerUtility +{ +public: + ~ConfigServerUtility(); + + static int getSpawnCookie (); + static int getChatLogMinutes(); + static int getServerMaxChatLogLines(); + static int getPlayerMaxChatLogLines(); + static bool isChatLogManagerLoggingEnabled(); + + static void install(); + static void remove(); + +private: + ConfigServerUtility(); + ConfigServerUtility & operator = (const ConfigServerUtility & rhs); + ConfigServerUtility(const ConfigServerUtility & source); + +}; + +//----------------------------------------------------------------------- + +#endif // _INCLUDED_ConfigServerUtility_H diff --git a/engine/server/library/serverUtility/src/shared/FirstServerUtility.h b/engine/server/library/serverUtility/src/shared/FirstServerUtility.h new file mode 100644 index 00000000..ff451891 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/FirstServerUtility.h @@ -0,0 +1,8 @@ +#ifndef INCLUDED_FirstServerUtility_H +#define INCLUDED_FirstServerUtility_H + +#include "sharedFoundation/FirstSharedFoundation.h" +#include "sharedDebug/FirstSharedDebug.h" +#include "sharedMemoryManager/FirstSharedMemoryManager.h" + +#endif diff --git a/engine/server/library/serverUtility/src/shared/FreeCtsDataTable.cpp b/engine/server/library/serverUtility/src/shared/FreeCtsDataTable.cpp new file mode 100644 index 00000000..3be9fe88 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/FreeCtsDataTable.cpp @@ -0,0 +1,433 @@ +// ====================================================================== +// +// FreeCtsDataTable.cpp +// Copyright 2008 Sony Online Entertainment LLC (SOE) +// All rights reserved. +// +// ====================================================================== + +#include "serverUtility/FirstServerUtility.h" +#include "serverUtility/FreeCtsDataTable.h" + +#include "sharedFoundation/CalendarTime.h" +#include "sharedFoundation/ConfigFile.h" +#include "sharedUtility/DataTable.h" +#include "sharedUtility/DataTableManager.h" +#include "UnicodeUtils.h" + +// ====================================================================== + +namespace FreeCtsDataTableNamespace +{ + std::multimap s_freeCtsList; + + bool s_dataLoaded = false; + std::string s_freeCtsFileName; + void loadData(); + + time_t convertToEpoch(int year, int month, int day, int hour, int minute, int second); +} + +using namespace FreeCtsDataTableNamespace; + +// ====================================================================== + +void FreeCtsDataTableNamespace::loadData() +{ + if (s_dataLoaded) + return; + + s_dataLoaded = true; + + // set up data to determine free CTS + s_freeCtsFileName = ConfigFile::getKeyString("FreeCts", "freeCtsFilename", ""); + if (!s_freeCtsFileName.empty()) + { + DataTable * table = DataTableManager::getTable(s_freeCtsFileName, true); + if (table) + { + int const columnRuleName = table->findColumnNumber("ruleName"); + int const columnRuleDescription = table->findColumnNumber("ruleDescription"); + + int const columnSourceClusterList = table->findColumnNumber("sourceClusterList"); + int const columnTargetClusterList = table->findColumnNumber("targetClusterList"); + + int const columnStartDateYr = table->findColumnNumber("startDateYr"); + int const columnStartDateMo = table->findColumnNumber("startDateMo"); + int const columnStartDateDy = table->findColumnNumber("startDateDy"); + int const columnStartDateHr = table->findColumnNumber("startDateHr"); + int const columnStartDateMin = table->findColumnNumber("startDateMin"); + int const columnStartDateSec = table->findColumnNumber("startDateSec"); + + int const columnEndDateYr = table->findColumnNumber("endDateYr"); + int const columnEndDateMo = table->findColumnNumber("endDateMo"); + int const columnEndDateDy = table->findColumnNumber("endDateDy"); + int const columnEndDateHr = table->findColumnNumber("endDateHr"); + int const columnEndDateMin = table->findColumnNumber("endDateMin"); + int const columnEndDateSec = table->findColumnNumber("endDateSec"); + + int const columnCharacterCreateDateRangeLowerYr = table->findColumnNumber("characterCreateDateRangeLowerYr"); + int const columnCharacterCreateDateRangeLowerMo = table->findColumnNumber("characterCreateDateRangeLowerMo"); + int const columnCharacterCreateDateRangeLowerDy = table->findColumnNumber("characterCreateDateRangeLowerDy"); + int const columnCharacterCreateDateRangeLowerHr = table->findColumnNumber("characterCreateDateRangeLowerHr"); + int const columnCharacterCreateDateRangeLowerMin = table->findColumnNumber("characterCreateDateRangeLowerMin"); + int const columnCharacterCreateDateRangeLowerSec = table->findColumnNumber("characterCreateDateRangeLowerSec"); + + int const columnCharacterCreateDateRangeUpperYr = table->findColumnNumber("characterCreateDateRangeUpperYr"); + int const columnCharacterCreateDateRangeUpperMo = table->findColumnNumber("characterCreateDateRangeUpperMo"); + int const columnCharacterCreateDateRangeUpperDy = table->findColumnNumber("characterCreateDateRangeUpperDy"); + int const columnCharacterCreateDateRangeUpperHr = table->findColumnNumber("characterCreateDateRangeUpperHr"); + int const columnCharacterCreateDateRangeUpperMin = table->findColumnNumber("characterCreateDateRangeUpperMin"); + int const columnCharacterCreateDateRangeUpperSec = table->findColumnNumber("characterCreateDateRangeUpperSec"); + + FATAL((columnRuleName < 0), ("column \"ruleName\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnRuleDescription < 0), ("column \"ruleDescription\" not found in %s", s_freeCtsFileName.c_str())); + + FATAL((columnSourceClusterList < 0), ("column \"sourceClusterList\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnTargetClusterList < 0), ("column \"targetClusterList\" not found in %s", s_freeCtsFileName.c_str())); + + FATAL((columnStartDateYr < 0), ("column \"startDateYr\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnStartDateMo < 0), ("column \"startDateMo\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnStartDateDy < 0), ("column \"startDateDy\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnStartDateHr < 0), ("column \"startDateHr\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnStartDateMin < 0), ("column \"startDateMin\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnStartDateSec < 0), ("column \"startDateSec\" not found in %s", s_freeCtsFileName.c_str())); + + FATAL((columnEndDateYr < 0), ("column \"endDateYr\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnEndDateMo < 0), ("column \"endDateMo\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnEndDateDy < 0), ("column \"endDateDy\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnEndDateHr < 0), ("column \"endDateHr\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnEndDateMin < 0), ("column \"endDateMin\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnEndDateSec < 0), ("column \"endDateSec\" not found in %s", s_freeCtsFileName.c_str())); + + FATAL((columnCharacterCreateDateRangeLowerYr < 0), ("column \"characterCreateDateRangeLowerYr\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnCharacterCreateDateRangeLowerMo < 0), ("column \"characterCreateDateRangeLowerMo\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnCharacterCreateDateRangeLowerDy < 0), ("column \"characterCreateDateRangeLowerDy\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnCharacterCreateDateRangeLowerHr < 0), ("column \"characterCreateDateRangeLowerHr\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnCharacterCreateDateRangeLowerMin < 0), ("column \"characterCreateDateRangeLowerMin\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnCharacterCreateDateRangeLowerSec < 0), ("column \"characterCreateDateRangeLowerSec\" not found in %s", s_freeCtsFileName.c_str())); + + FATAL((columnCharacterCreateDateRangeUpperYr < 0), ("column \"characterCreateDateRangeUpperYr\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnCharacterCreateDateRangeUpperMo < 0), ("column \"characterCreateDateRangeUpperMo\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnCharacterCreateDateRangeUpperDy < 0), ("column \"characterCreateDateRangeUpperDy\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnCharacterCreateDateRangeUpperHr < 0), ("column \"characterCreateDateRangeUpperHr\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnCharacterCreateDateRangeUpperMin < 0), ("column \"characterCreateDateRangeUpperMin\" not found in %s", s_freeCtsFileName.c_str())); + FATAL((columnCharacterCreateDateRangeUpperSec < 0), ("column \"characterCreateDateRangeUpperSec\" not found in %s", s_freeCtsFileName.c_str())); + + std::string sourceClusterList, targetClusterList; + int startDateYr, startDateMo, startDateDy, startDateHr, startDateMin, startDateSec; + int endDateYr, endDateMo, endDateDy, endDateHr, endDateMin, endDateSec; + int characterCreateDateRangeLowerYr, characterCreateDateRangeLowerMo, characterCreateDateRangeLowerDy, characterCreateDateRangeLowerHr, characterCreateDateRangeLowerMin, characterCreateDateRangeLowerSec; + int characterCreateDateRangeUpperYr, characterCreateDateRangeUpperMo, characterCreateDateRangeUpperDy, characterCreateDateRangeUpperHr, characterCreateDateRangeUpperMin, characterCreateDateRangeUpperSec; + + FreeCtsDataTable::FreeCtsInfo freeCtsInfo; + + Unicode::UnicodeStringVector tokensSourceClusterList, tokensTargetClusterList; + Unicode::UnicodeStringVector::const_iterator tokensIter; + static Unicode::String const clusterListDelimiters(Unicode::narrowToWide(", ")); + + int const numRows = table->getNumRows(); + for (int i = 0; i < numRows; ++i) + { + freeCtsInfo.ruleName = table->getStringValue(columnRuleName, i); + freeCtsInfo.ruleDescription = table->getStringValue(columnRuleDescription, i); + + sourceClusterList = table->getStringValue(columnSourceClusterList, i); + targetClusterList = table->getStringValue(columnTargetClusterList, i); + + startDateYr = table->getIntValue(columnStartDateYr, i); + startDateMo = table->getIntValue(columnStartDateMo, i); + startDateDy = table->getIntValue(columnStartDateDy, i); + startDateHr = table->getIntValue(columnStartDateHr, i); + startDateMin = table->getIntValue(columnStartDateMin, i); + startDateSec = table->getIntValue(columnStartDateSec, i); + + endDateYr = table->getIntValue(columnEndDateYr, i); + endDateMo = table->getIntValue(columnEndDateMo, i); + endDateDy = table->getIntValue(columnEndDateDy, i); + endDateHr = table->getIntValue(columnEndDateHr, i); + endDateMin = table->getIntValue(columnEndDateMin, i); + endDateSec = table->getIntValue(columnEndDateSec, i); + + characterCreateDateRangeLowerYr = table->getIntValue(columnCharacterCreateDateRangeLowerYr, i); + characterCreateDateRangeLowerMo = table->getIntValue(columnCharacterCreateDateRangeLowerMo, i); + characterCreateDateRangeLowerDy = table->getIntValue(columnCharacterCreateDateRangeLowerDy, i); + characterCreateDateRangeLowerHr = table->getIntValue(columnCharacterCreateDateRangeLowerHr, i); + characterCreateDateRangeLowerMin = table->getIntValue(columnCharacterCreateDateRangeLowerMin, i); + characterCreateDateRangeLowerSec = table->getIntValue(columnCharacterCreateDateRangeLowerSec, i); + + characterCreateDateRangeUpperYr = table->getIntValue(columnCharacterCreateDateRangeUpperYr, i); + characterCreateDateRangeUpperMo = table->getIntValue(columnCharacterCreateDateRangeUpperMo, i); + characterCreateDateRangeUpperDy = table->getIntValue(columnCharacterCreateDateRangeUpperDy, i); + characterCreateDateRangeUpperHr = table->getIntValue(columnCharacterCreateDateRangeUpperHr, i); + characterCreateDateRangeUpperMin = table->getIntValue(columnCharacterCreateDateRangeUpperMin, i); + characterCreateDateRangeUpperSec = table->getIntValue(columnCharacterCreateDateRangeUpperSec, i); + + freeCtsInfo.targetCluster.clear(); + freeCtsInfo.startTime = -1; + freeCtsInfo.endTime = -1; + freeCtsInfo.sourceCharacterCreateTimeLower = -1; + freeCtsInfo.sourceCharacterCreateTimeUpper = -1; + + if ((startDateYr > 0) && (startDateMo > 0) && (startDateDy > 0)) + { + freeCtsInfo.startTime = convertToEpoch(startDateYr, startDateMo, startDateDy, startDateHr, startDateMin, startDateSec); + FATAL((freeCtsInfo.startTime <= 0), ("date %d/%d/%d %d:%d:%d on row %d is invalid", startDateMo, startDateDy, startDateYr, startDateHr, startDateMin, startDateSec, (i+3))); + } + + if ((endDateYr > 0) && (endDateMo > 0) && (endDateDy > 0)) + { + freeCtsInfo.endTime = convertToEpoch(endDateYr, endDateMo, endDateDy, endDateHr, endDateMin, endDateSec); + FATAL((freeCtsInfo.endTime <= 0), ("date %d/%d/%d %d:%d:%d on row %d is invalid", endDateMo, endDateDy, endDateYr, endDateHr, endDateMin, endDateSec, (i+3))); + } + + if ((freeCtsInfo.startTime > 0) && (freeCtsInfo.endTime > 0)) + { + FATAL((freeCtsInfo.startTime >= freeCtsInfo.endTime), ("start date (%s) must be before end date (%s) on row %d", CalendarTime::convertEpochToTimeStringLocal(freeCtsInfo.startTime).c_str(), CalendarTime::convertEpochToTimeStringLocal(freeCtsInfo.endTime).c_str(), (i+3))); + } + + if ((characterCreateDateRangeLowerYr > 0) && (characterCreateDateRangeLowerMo > 0) && (characterCreateDateRangeLowerDy > 0)) + { + freeCtsInfo.sourceCharacterCreateTimeLower = convertToEpoch(characterCreateDateRangeLowerYr, characterCreateDateRangeLowerMo, characterCreateDateRangeLowerDy, characterCreateDateRangeLowerHr, characterCreateDateRangeLowerMin, characterCreateDateRangeLowerSec); + FATAL((freeCtsInfo.sourceCharacterCreateTimeLower <= 0), ("date %d/%d/%d %d:%d:%d on row %d is invalid", characterCreateDateRangeLowerMo, characterCreateDateRangeLowerDy, characterCreateDateRangeLowerYr, characterCreateDateRangeLowerHr, characterCreateDateRangeLowerMin, characterCreateDateRangeLowerSec, (i+3))); + } + + if ((characterCreateDateRangeUpperYr > 0) && (characterCreateDateRangeUpperMo > 0) && (characterCreateDateRangeUpperDy > 0)) + { + freeCtsInfo.sourceCharacterCreateTimeUpper = convertToEpoch(characterCreateDateRangeUpperYr, characterCreateDateRangeUpperMo, characterCreateDateRangeUpperDy, characterCreateDateRangeUpperHr, characterCreateDateRangeUpperMin, characterCreateDateRangeUpperSec); + FATAL((freeCtsInfo.sourceCharacterCreateTimeUpper <= 0), ("date %d/%d/%d %d:%d:%d on row %d is invalid", characterCreateDateRangeUpperMo, characterCreateDateRangeUpperDy, characterCreateDateRangeUpperYr, characterCreateDateRangeUpperHr, characterCreateDateRangeUpperMin, characterCreateDateRangeUpperSec, (i+3))); + } + + if ((freeCtsInfo.sourceCharacterCreateTimeLower > 0) && (freeCtsInfo.sourceCharacterCreateTimeUpper > 0)) + { + FATAL((freeCtsInfo.sourceCharacterCreateTimeLower >= freeCtsInfo.sourceCharacterCreateTimeUpper), ("lower date (%s) must be before upper date (%s) on row %d", CalendarTime::convertEpochToTimeStringLocal(freeCtsInfo.sourceCharacterCreateTimeLower).c_str(), CalendarTime::convertEpochToTimeStringLocal(freeCtsInfo.sourceCharacterCreateTimeUpper).c_str(), (i+3))); + } + + tokensSourceClusterList.clear(); + tokensTargetClusterList.clear(); + if (Unicode::tokenize(Unicode::narrowToWide(sourceClusterList), tokensSourceClusterList, &clusterListDelimiters, NULL) && (tokensSourceClusterList.size() > 0) && Unicode::tokenize(Unicode::narrowToWide(targetClusterList), tokensTargetClusterList, &clusterListDelimiters, NULL) && (tokensTargetClusterList.size() > 0)) + { + for (tokensIter = tokensTargetClusterList.begin(); tokensIter != tokensTargetClusterList.end(); ++tokensIter) + freeCtsInfo.targetCluster[Unicode::wideToNarrow(Unicode::toLower(*tokensIter))] = Unicode::wideToNarrow(*tokensIter); + + for (tokensIter = tokensSourceClusterList.begin(); tokensIter != tokensSourceClusterList.end(); ++tokensIter) + IGNORE_RETURN(s_freeCtsList.insert(std::make_pair(Unicode::wideToNarrow(Unicode::toLower(*tokensIter)), freeCtsInfo))); + } + } + + DataTableManager::close(s_freeCtsFileName); + +#ifdef _DEBUG + for (std::multimap::const_iterator iter = s_freeCtsList.begin(); iter != s_freeCtsList.end(); ++iter) + { + std::string targetClusters; + for (std::map::const_iterator iter2 = iter->second.targetCluster.begin(); iter2 != iter->second.targetCluster.end(); ++iter2) + { + if (!targetClusters.empty()) + targetClusters += ", "; + + targetClusters += iter2->first; + } + + std::string startDate("NA"); + std::string endDate("NA"); + + if (iter->second.startTime > 0) + startDate = CalendarTime::convertEpochToTimeStringLocal(iter->second.startTime); + + if (iter->second.endTime > 0) + endDate = CalendarTime::convertEpochToTimeStringLocal(iter->second.endTime); + + std::string characterCreateDateLower("NA"); + std::string characterCreateDateUpper("NA"); + + if (iter->second.sourceCharacterCreateTimeLower > 0) + characterCreateDateLower = CalendarTime::convertEpochToTimeStringLocal(iter->second.sourceCharacterCreateTimeLower); + + if (iter->second.sourceCharacterCreateTimeUpper > 0) + characterCreateDateUpper = CalendarTime::convertEpochToTimeStringLocal(iter->second.sourceCharacterCreateTimeUpper); + + DEBUG_REPORT_LOG(true, ("FreeCtsInfo rule=(%s, %s), source cluster=(%s) target clusters=(%s) start/end=(%ld, %s) -> (%ld, %s) character create date=(%ld, %s) -> (%ld, %s)\n", iter->second.ruleName.c_str(), iter->second.ruleDescription.c_str(), iter->first.c_str(), targetClusters.c_str(), iter->second.startTime, startDate.c_str(), iter->second.endTime, endDate.c_str(), iter->second.sourceCharacterCreateTimeLower, characterCreateDateLower.c_str(), iter->second.sourceCharacterCreateTimeUpper, characterCreateDateUpper.c_str())); + } +#endif + } + } +} + +// ---------------------------------------------------------------------- + +time_t FreeCtsDataTableNamespace::convertToEpoch(int const year, int const month, int const day, int const hour, int const minute, int const second) +{ + time_t const timeNow = ::time(NULL); + struct tm * timeinfo = ::localtime(&timeNow); + FATAL(!timeinfo, ("::localtime() returns NULL")); + + // greater than zero if Daylight Saving Time is in effect, + // zero if Daylight Saving Time is not in effect, + // and less than zero if the information is not available. + int const currentTimeIsDst = timeinfo->tm_isdst; + + timeinfo->tm_year = year - 1900; + timeinfo->tm_mon = month - 1; + timeinfo->tm_mday = day; + timeinfo->tm_hour = hour; + timeinfo->tm_min = minute; + timeinfo->tm_sec = second; + + time_t convertedTime = ::mktime(timeinfo); + + if (convertedTime <= 0) + { + return convertedTime; + } + + // if the converted time converted back to y/m/d h:m:s doesn't + // match the y/m/d h:m:s that is passed in, it probably means + // the passed in time is in a different standard/daylight period + // than the current time, so try the conversion again with the + // "opposite" standard/daylight period than the current time, + // and it should be OK + timeinfo = ::localtime(&convertedTime); + FATAL(!timeinfo, ("::localtime() returns NULL")); + + if ((timeinfo->tm_year != (year - 1900)) || + (timeinfo->tm_mon != (month - 1)) || + (timeinfo->tm_mday != day) || + (timeinfo->tm_hour != hour) || + (timeinfo->tm_min != minute) || + (timeinfo->tm_sec != second)) + { + if (currentTimeIsDst >= 0) + { + timeinfo->tm_year = year - 1900; + timeinfo->tm_mon = month - 1; + timeinfo->tm_mday = day; + timeinfo->tm_hour = hour; + timeinfo->tm_min = minute; + timeinfo->tm_sec = second; + timeinfo->tm_isdst = ((currentTimeIsDst == 0) ? 1 : 0); + + convertedTime = ::mktime(timeinfo); + } + } + + return convertedTime; +} + +// ---------------------------------------------------------------------- + +std::string const & FreeCtsDataTable::getFreeCtsFileName() +{ + if (!s_dataLoaded) + loadData(); + + return s_freeCtsFileName; +} + +// ---------------------------------------------------------------------- + +std::multimap const & FreeCtsDataTable::getFreeCtsInfo() +{ + if (!s_dataLoaded) + loadData(); + + return s_freeCtsList; +} + +// ---------------------------------------------------------------------- + +FreeCtsDataTable::FreeCtsInfo const * FreeCtsDataTable::isFreeCtsSourceCluster(std::string const & sourceCluster) +{ + if (!s_dataLoaded) + loadData(); + + if (s_freeCtsList.empty()) + return NULL; + + time_t const timeNow = ::time(NULL); + std::pair::const_iterator, std::multimap::const_iterator> range = s_freeCtsList.equal_range(Unicode::toLower(sourceCluster)); + for (std::multimap::const_iterator iter = range.first; iter != range.second; ++iter) + { + bool const satisfyStartTime = ((iter->second.startTime <= 0) || (timeNow >= iter->second.startTime)); + bool const satisfyEndTime = ((iter->second.endTime <= 0) || (timeNow <= iter->second.endTime)); + + if (satisfyStartTime && satisfyEndTime) + return &(iter->second); + } + + return NULL; +} + +// ---------------------------------------------------------------------- + +FreeCtsDataTable::FreeCtsInfo const * FreeCtsDataTable::wouldCharacterTransferBeFree(time_t const sourceCharacterCreateTime, uint32 const sourceStationId, std::string const & sourceCluster, uint32 const targetStationId, std::string const & targetCluster, bool ignoreTimeRestriction) +{ + if (!s_dataLoaded) + loadData(); + + if (s_freeCtsList.empty()) + return NULL; + + if ((sourceCharacterCreateTime <= 0) && !ignoreTimeRestriction) + return NULL; + + if (sourceStationId != targetStationId) + return NULL; + + time_t const timeNow = ::time(NULL); + + std::string const lowerTargetCluster(Unicode::toLower(targetCluster)); + std::pair::const_iterator, std::multimap::const_iterator> range = s_freeCtsList.equal_range(Unicode::toLower(sourceCluster)); + for (std::multimap::const_iterator iter = range.first; iter != range.second; ++iter) + { + if (iter->second.targetCluster.count(lowerTargetCluster) > 0) + { + if (ignoreTimeRestriction) + return &(iter->second); + + bool const satisfyStartTime = ((iter->second.startTime <= 0) || (timeNow >= iter->second.startTime)); + bool const satisfyEndTime = ((iter->second.endTime <= 0) || (timeNow <= iter->second.endTime)); + + bool const satisfyCreateTimeLowerBound = ((iter->second.sourceCharacterCreateTimeLower <= 0) || (sourceCharacterCreateTime >= iter->second.sourceCharacterCreateTimeLower)); + bool const satisfyCreateTimeUpperBound = ((iter->second.sourceCharacterCreateTimeUpper <= 0) || (sourceCharacterCreateTime <= iter->second.sourceCharacterCreateTimeUpper)); + + if (satisfyStartTime && satisfyEndTime && satisfyCreateTimeLowerBound && satisfyCreateTimeUpperBound) + return &(iter->second); + } + } + + return NULL; +} + +// ---------------------------------------------------------------------- + +FreeCtsDataTable::FreeCtsInfo const * FreeCtsDataTable::getFreeCtsInfoForCharacter(time_t const sourceCharacterCreateTime, std::string const & sourceCluster, bool ignoreTimeRestriction) +{ + if (!s_dataLoaded) + loadData(); + + if (s_freeCtsList.empty()) + return NULL; + + if ((sourceCharacterCreateTime <= 0) && !ignoreTimeRestriction) + return NULL; + + time_t const timeNow = ::time(NULL); + std::pair::const_iterator, std::multimap::const_iterator> range = s_freeCtsList.equal_range(Unicode::toLower(sourceCluster)); + for (std::multimap::const_iterator iter = range.first; iter != range.second; ++iter) + { + if (ignoreTimeRestriction) + return &(iter->second); + + bool const satisfyStartTime = ((iter->second.startTime <= 0) || (timeNow >= iter->second.startTime)); + bool const satisfyEndTime = ((iter->second.endTime <= 0) || (timeNow <= iter->second.endTime)); + + bool const satisfyCreateTimeLowerBound = ((iter->second.sourceCharacterCreateTimeLower <= 0) || (sourceCharacterCreateTime >= iter->second.sourceCharacterCreateTimeLower)); + bool const satisfyCreateTimeUpperBound = ((iter->second.sourceCharacterCreateTimeUpper <= 0) || (sourceCharacterCreateTime <= iter->second.sourceCharacterCreateTimeUpper)); + + if (satisfyStartTime && satisfyEndTime && satisfyCreateTimeLowerBound && satisfyCreateTimeUpperBound) + return &(iter->second); + } + + return NULL; +} diff --git a/engine/server/library/serverUtility/src/shared/FreeCtsDataTable.h b/engine/server/library/serverUtility/src/shared/FreeCtsDataTable.h new file mode 100644 index 00000000..9f47c461 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/FreeCtsDataTable.h @@ -0,0 +1,47 @@ +// ====================================================================== +// +// FreeCtsDataTable.h +// Copyright 2006 Sony Online Entertainment LLC (SOE) +// All rights reserved. +// +// ====================================================================== + +#ifndef INCLUDED_FreeCtsDataTable_H +#define INCLUDED_FreeCtsDataTable_H + +#include +#include + +// ====================================================================== + +class FreeCtsDataTable // static class +{ +public: + + struct FreeCtsInfo + { + std::string ruleName; + std::string ruleDescription; + std::map targetCluster; + time_t startTime; + time_t endTime; + time_t sourceCharacterCreateTimeLower; + time_t sourceCharacterCreateTimeUpper; + }; + + static std::string const & getFreeCtsFileName(); + static stdmultimap::fwd const & getFreeCtsInfo(); + static FreeCtsDataTable::FreeCtsInfo const * isFreeCtsSourceCluster(std::string const & sourceCluster); + static FreeCtsDataTable::FreeCtsInfo const * wouldCharacterTransferBeFree(time_t sourceCharacterCreateTime, uint32 sourceStationId, std::string const & sourceCluster, uint32 targetStationId, std::string const & targetCluster, bool ignoreTimeRestriction); + static FreeCtsDataTable::FreeCtsInfo const * getFreeCtsInfoForCharacter(time_t sourceCharacterCreateTime, std::string const & sourceCluster, bool ignoreTimeRestriction); + +private: // disabled + + FreeCtsDataTable(); + FreeCtsDataTable(FreeCtsDataTable const &); + FreeCtsDataTable &operator =(FreeCtsDataTable const &); +}; + +// ====================================================================== + +#endif // INCLUDED_FreeCtsDataTable_H diff --git a/engine/server/library/serverUtility/src/shared/LocationData.cpp b/engine/server/library/serverUtility/src/shared/LocationData.cpp new file mode 100644 index 00000000..80c670ad --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/LocationData.cpp @@ -0,0 +1,39 @@ +// ====================================================================== +// +// LocationData.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "serverUtility/FirstServerUtility.h" +#include "serverUtility/LocationData.h" + +#include "sharedMathArchive/VectorArchive.h" +#include "unicodeArchive/UnicodeArchive.h" + +// ====================================================================== + +namespace Archive +{ + void get(ReadIterator & source, LocationData & target) + { + get(source, target.scene); + Vector center; + float radius; + get(source, center); + get(source, radius); + target.location.setCenter(center); + target.location.setRadius(radius); + get(source, target.name); + } + + void put(ByteStream & target, const LocationData & source) + { + put(target, source.scene); + put(target, source.location.getCenter()); + put(target, source.location.getRadius()); + put(target, source.name); + } +} + +// ====================================================================== diff --git a/engine/server/library/serverUtility/src/shared/LocationData.h b/engine/server/library/serverUtility/src/shared/LocationData.h new file mode 100644 index 00000000..20580d5c --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/LocationData.h @@ -0,0 +1,51 @@ +// ====================================================================== +// +// LocationData.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_LocationData_H +#define INCLUDED_LocationData_H + +// ====================================================================== + +#include "Archive/AutoByteStream.h" +#include "sharedMath/Sphere.h" +#include "Unicode.h" +//#include "sharedFoundation/NetworkId.h" +//#include "sharedMath/Vector.h" + +// ====================================================================== + +/* namespace DB */ +/* { */ +/* class BindableDouble; */ +/* template */ +/* class BindableString; */ +/* } */ + +// ====================================================================== + +class LocationData +{ + public: + Sphere location; + Unicode::String name; + std::string scene; + + inline bool operator==(const LocationData & rhs) const + { + return this == &rhs || (scene == rhs.scene && location == rhs.location && name == rhs.name); + } +}; + +namespace Archive +{ + void get(ReadIterator & source, LocationData & target); + void put(ByteStream & target, const LocationData & source); +} + +// ====================================================================== + +#endif diff --git a/engine/server/library/serverUtility/src/shared/MissionLocation.cpp b/engine/server/library/serverUtility/src/shared/MissionLocation.cpp new file mode 100644 index 00000000..1d1274c0 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/MissionLocation.cpp @@ -0,0 +1,38 @@ +// ====================================================================== +// +// MissionLocation.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "serverUtility/FirstServerUtility.h" +#include "serverUtility/MissionLocation.h" + +#include "localizationArchive/StringIdArchive.h" +#include "sharedMathArchive/VectorArchive.h" +#include "sharedFoundation/NetworkIdArchive.h" +#include "unicodeArchive/UnicodeArchive.h" + +// ====================================================================== + +namespace Archive +{ + + void get(ReadIterator & source, MissionLocation & target) + { + get(source, target.coordinates); + get(source, target.planetName); + get(source, target.regionName); + get(source, target.cell); + } + + void put(ByteStream & target, const MissionLocation & source) + { + put(target, source.coordinates); + put(target, source.planetName); + put(target, source.regionName); + put(target, source.cell); + } +} + +// ====================================================================== diff --git a/engine/server/library/serverUtility/src/shared/MissionLocation.h b/engine/server/library/serverUtility/src/shared/MissionLocation.h new file mode 100644 index 00000000..c2a792ae --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/MissionLocation.h @@ -0,0 +1,72 @@ +// ====================================================================== +// +// MissionLocation.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_MissionLocation_H +#define INCLUDED_MissionLocation_H + +// ====================================================================== + +#include "Archive/AutoByteStream.h" +#include "sharedFoundation/NetworkId.h" +#include "sharedMath/Vector.h" +#include "StringId.h" + +// ====================================================================== + +namespace DB +{ + class BindableDouble; + template + class BindableString; +} + +// ====================================================================== + +//Todo: Generalize this into an all-purpose Location class +class MissionLocation +{ + public: + Vector coordinates; + std::string planetName; + Unicode::String regionName; + NetworkId cell; + + public: + bool operator== (const MissionLocation &rhs) const; + bool operator!= (const MissionLocation &rhs) const; + + public: + //@todo: (un)pack cell + void unpackFromDatabase(const DB::BindableDouble &x,const DB::BindableDouble &y, const DB::BindableDouble &z, const DB::BindableString<500> &planet, const DB::BindableString<500> ®ion_name, const DB::BindableNetworkId &cell); + void packToDatabase(DB::BindableDouble &x,DB::BindableDouble &y, DB::BindableDouble &z, DB::BindableString<500> &planet, DB::BindableString<500> ®ion_name, DB::BindableNetworkId &cell) const; +}; + +// ====================================================================== + +inline bool MissionLocation::operator== (const MissionLocation &rhs) const +{ + return ((coordinates == rhs.coordinates) && (planetName == rhs.planetName) && (regionName == rhs.regionName) && (cell == rhs.cell)); +} + +// ---------------------------------------------------------------------- + +inline bool MissionLocation::operator!= (const MissionLocation &rhs) const +{ + return !(MissionLocation::operator==(rhs)); +} + +// ====================================================================== + +namespace Archive +{ + void get(ReadIterator & source, MissionLocation & target); + void put(ByteStream & target, const MissionLocation & source); +} + +// ====================================================================== + +#endif diff --git a/engine/server/library/serverUtility/src/shared/PopulationList.cpp b/engine/server/library/serverUtility/src/shared/PopulationList.cpp new file mode 100644 index 00000000..9b5346d9 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/PopulationList.cpp @@ -0,0 +1,147 @@ +// ====================================================================== +// +// PopulationList.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "serverUtility/FirstServerUtility.h" +#include "serverUtility/PopulationList.h" + +#include "Archive/AutoByteStream.h" + +// ====================================================================== + +PopulationList::PopulationList() +{ +} + +// ---------------------------------------------------------------------- + +PopulationList::~PopulationList() +{ +} + +// ---------------------------------------------------------------------- + +void PopulationList::setPopulation(const std::string &scene, int x, int z, int population) +{ + m_populationMap[Location(scene,x,z)]=population; + m_populationCache.clear(); +} + +// ---------------------------------------------------------------------- + +int PopulationList::getNearestPopulation(const std::string &scene, int x, int z) const +{ + Location where(scene,x,z); + PopulationMapType::const_iterator i=m_populationMap.find(where); + if (i!=m_populationMap.end()) + return i->second; + else + { + i=m_populationCache.find(where); + if (i!=m_populationCache.end()) + return i->second; + else + { + int closestSoFar=-1; + int population=0; + for (i=m_populationMap.begin(); i!=m_populationMap.end(); ++i) + { + if (i->first.getScene()==scene) + { + int distX=x - i->first.getX(); + int distZ=z - i->first.getZ(); + int distSquared = (distX*distX)+(distZ*distZ); + if (closestSoFar==-1 || distSquared < closestSoFar) + { + closestSoFar = distSquared; + population = i->second; + } + } + } + m_populationCache.insert(std::make_pair(where,population)); + return population; + } + } +} + +// ---------------------------------------------------------------------- + +void PopulationList::update(const PopulationList &newData) +{ + for (PopulationMapType::const_iterator i=newData.m_populationMap.begin(); i!=newData.m_populationMap.end(); ++i) + { + setPopulation(i->first.getScene(), i->first.getX(), i->first.getZ(), i->second); + } +} + +// ====================================================================== + +PopulationList::Location::Location(const std::string &scene, int x, int z) : + m_scene(scene), + m_x(x), + m_z(z) +{ +} + +// ---------------------------------------------------------------------- + +bool PopulationList::Location::operator<(const Location &rhs) const +{ + if (m_z < rhs.m_z) + return true; + else + { + if (m_z == rhs.m_z) + { + if (m_x < rhs.m_x) + return true; + else + { + if (m_x == rhs.m_x) + return (m_scene < rhs.m_scene); + } + } + } + + return false; +} + +// ====================================================================== + +namespace Archive +{ + void get(ReadIterator & source, PopulationList & target) + { + size_t numEntries; + get(source,numEntries); + for (size_t count=0; count < numEntries; ++count) + { + std::string scene; + int x; + int z; + int population; + get(source,scene); + get(source,x); + get(source,z); + get(source,population); + target.setPopulation(scene,x,z,population); + } + } + + void put(ByteStream & target, const PopulationList & source) + { + put(target,source.m_populationMap.size()); + for (PopulationList::PopulationMapType::const_iterator i=source.m_populationMap.begin(); i!=source.m_populationMap.end(); ++i) + { + put(target,i->first.getScene()); + put(target,i->first.getX()); + put(target,i->first.getZ()); + put(target,i->second); + } + } +} + +// ====================================================================== diff --git a/engine/server/library/serverUtility/src/shared/PopulationList.h b/engine/server/library/serverUtility/src/shared/PopulationList.h new file mode 100644 index 00000000..9f4a2115 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/PopulationList.h @@ -0,0 +1,100 @@ +// ====================================================================== +// +// PopulationList.h +// copyright (c) 2003 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_PopulationList_H +#define INCLUDED_PopulationList_H + +// ====================================================================== + +#include +#include + +// ====================================================================== + +class PopulationList; +namespace Archive +{ + class ReadIterator; + class ByteStream; +} + +// ====================================================================== + +namespace Archive +{ + void get(ReadIterator & source, PopulationList & target); + void put(ByteStream & target, const PopulationList & source); +} + +// ====================================================================== + +/** + * A class that manages a list of locations and the number of players + * in each location. + */ + +class PopulationList +{ + public: + PopulationList(); + ~PopulationList(); + + public: + void setPopulation(const std::string &scene, int x, int z, int population); + int getNearestPopulation(const std::string &scene, int x, int z) const; + void update(const PopulationList &newData); + + private: + class Location + { + public: + Location(const std::string &scene, int x, int z); + bool operator< (const Location &rhs) const; + + public: + const std::string &getScene() const; + int getX() const; + int getZ() const; + + private: + std::string m_scene; + int m_x; + int m_z; + }; + + typedef std::map PopulationMapType; + PopulationMapType m_populationMap; + mutable PopulationMapType m_populationCache; + + friend void Archive::get(ReadIterator & source, PopulationList & target); + friend void Archive::put(ByteStream & target, const PopulationList & source); +}; + +// ====================================================================== + +inline const std::string &PopulationList::Location::getScene() const +{ + return m_scene; +} + +// ---------------------------------------------------------------------- + +inline int PopulationList::Location::getX() const +{ + return m_x; +} + +// ---------------------------------------------------------------------- + +inline int PopulationList::Location::getZ() const +{ + return m_z; +} + +// ====================================================================== + +#endif diff --git a/engine/server/library/serverUtility/src/shared/PvpEnemy.cpp b/engine/server/library/serverUtility/src/shared/PvpEnemy.cpp new file mode 100644 index 00000000..95faa593 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/PvpEnemy.cpp @@ -0,0 +1,43 @@ +// ====================================================================== +// +// PvpEnemy.cpp +// +// Copyright 2003 Sony Online Entertainment +// +// ====================================================================== + +#include "serverUtility/FirstServerUtility.h" +#include "serverUtility/PvpEnemy.h" +#include "Archive/Archive.h" +#include "Archive/ByteStream.h" +#include "sharedFoundation/NetworkIdArchive.h" + +// ====================================================================== + +namespace Archive +{ + +// ====================================================================== + +void put(Archive::ByteStream &target, PvpEnemy const &source) +{ + put(target, source.enemyId); + put(target, source.enemyFaction); + put(target, source.expireTime); +} + +// ---------------------------------------------------------------------- + +void get(Archive::ReadIterator &source, PvpEnemy &target) +{ + get(source, target.enemyId); + get(source, target.enemyFaction); + get(source, target.expireTime); +} + +// ====================================================================== + +} + +// ====================================================================== + diff --git a/engine/server/library/serverUtility/src/shared/PvpEnemy.h b/engine/server/library/serverUtility/src/shared/PvpEnemy.h new file mode 100644 index 00000000..4659ae81 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/PvpEnemy.h @@ -0,0 +1,62 @@ +// ====================================================================== +// +// PvpEnemy.h +// +// Copyright 2003 Sony Online Entertainment +// +// ====================================================================== + +#ifndef _PvpEnemy_H +#define _PvpEnemy_H + +// ====================================================================== + +#include "sharedFoundation/NetworkId.h" + +// ====================================================================== + +struct PvpEnemy +{ + PvpEnemy() : + enemyId(NetworkId::cms_invalid), + enemyFaction(0), + expireTime(0) + { + } + + PvpEnemy(NetworkId const &id, uint32 faction, int time) : + enemyId(id), + enemyFaction(faction), + expireTime(time) + { + } + + NetworkId enemyId; + uint32 enemyFaction; + int expireTime; +}; + +// ---------------------------------------------------------------------- + +inline bool operator==(PvpEnemy const &lhs, PvpEnemy const &rhs) +{ + return lhs.expireTime == rhs.expireTime + && lhs.enemyId == rhs.enemyId + && lhs.enemyFaction == rhs.enemyFaction; +} + +// ---------------------------------------------------------------------- + +namespace Archive +{ + class ByteStream; + class ReadIterator; + + void put(Archive::ByteStream &target, PvpEnemy const &source); + void get(Archive::ReadIterator &source, PvpEnemy &target); +} + +// ====================================================================== + +#endif // _PvpEnemy_H + diff --git a/engine/server/library/serverUtility/src/shared/RecentMaxSyncedValue.cpp b/engine/server/library/serverUtility/src/shared/RecentMaxSyncedValue.cpp new file mode 100644 index 00000000..c40768f7 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/RecentMaxSyncedValue.cpp @@ -0,0 +1,110 @@ +// ====================================================================== +// +// RecentMaxSyncedValue.cpp +// +// Copyright 2004 Sony Online Entertainment +// +// ====================================================================== + +#include "serverUtility/FirstServerUtility.h" +#include "serverUtility/RecentMaxSyncedValue.h" + +// ====================================================================== + +namespace RecentMaxSyncedValueNamespace +{ + + // ---------------------------------------------------------------------- + + int syncStampLongDeltaTime(uint32 stamp1, uint32 stamp2) + { + uint32 const delta = stamp1 - stamp2; + if (delta > 0x7fffffff) + return static_cast(0xffffffff-delta); + return static_cast(delta); + } + + // ---------------------------------------------------------------------- + +} + +using namespace RecentMaxSyncedValueNamespace; + +// ====================================================================== + +RecentMaxSyncedValue::RecentMaxSyncedValue(float value, int checkIntervalMs, int fudgeIntervalMs) : + m_maximum(value), + m_oldMaximum(value), + m_changeSyncStamp(0), + m_checkIntervalMs(checkIntervalMs), + m_fudgeIntervalMs(fudgeIntervalMs) +{ +} + +// ---------------------------------------------------------------------- + +float RecentMaxSyncedValue::getLastSetValue() const +{ + return m_maximum; +} + +// ---------------------------------------------------------------------- + +float RecentMaxSyncedValue::getRecentMaximum(uint32 curSyncStamp) +{ + // If we have reduced the maximum recently, see if we're still in the + // interval we allow for keeping old maximums around, and if so, + // use the faster max speed. If we have passed the end of the + // interval, clear the stamp so we don't have to check it anymore. + if (m_changeSyncStamp) + { + int const fudgeTime = m_checkIntervalMs + m_fudgeIntervalMs; + if (syncStampLongDeltaTime(m_changeSyncStamp, curSyncStamp) < fudgeTime) + return m_oldMaximum; + m_changeSyncStamp = 0; + } + return m_maximum; +} + +// ---------------------------------------------------------------------- + +void RecentMaxSyncedValue::setValue(float value, uint32 curSyncStamp) +{ + if (value >= getRecentMaximum(curSyncStamp)) + { + // If we are setting a maximum higher than our current effective maximum, + // just clear the sync stamp. + m_changeSyncStamp = 0; + } + else + { + // We're reducing our maximum, so we need to preserve our old maximum to + // deal with usage in the time following the change. We also need to + // deal with reducing the maximum multiple times in a short interval. + + // m_maximum is our previous maximum. We know that the new maximum being + // set is less than this value from the previous check, so the maximum + // is being reduced. + + // m_oldMaximum was our previous old maximum, being kept around to make + // sure we're being liberal when determining what the maximum possible + // value over a given time interval should be. + + // 1) If our previous maximum is greater than our previous old maximum, + // or we don't have a previous old maximum, we push the previous + // maximum into the old maximum for future use. + // 2) Otherwise, we have an old maximum greater than our previous + // maximum, so we want to lower the old maximum iff more time has + // elapsed than we allow for keeping old maximums around. Not doing + // this could allow us to lower the maximum too quickly. + if ( m_maximum >= m_oldMaximum + || !m_changeSyncStamp + || syncStampLongDeltaTime(m_changeSyncStamp, curSyncStamp) >= m_fudgeIntervalMs) + m_oldMaximum = m_maximum; + m_changeSyncStamp = curSyncStamp; + } + m_maximum = value; +} + +// ====================================================================== + diff --git a/engine/server/library/serverUtility/src/shared/RecentMaxSyncedValue.h b/engine/server/library/serverUtility/src/shared/RecentMaxSyncedValue.h new file mode 100644 index 00000000..6127bb9d --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/RecentMaxSyncedValue.h @@ -0,0 +1,35 @@ +// ====================================================================== +// +// RecentMaxSyncedValue.h +// +// Copyright 2004 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_RecentMaxSyncedValue_H +#define INCLUDED_RecentMaxSyncedValue_H + +class RecentMaxSyncedValue +{ +public: + RecentMaxSyncedValue(float value, int checkIntervalMs, int fudgeIntervalMs); + float getLastSetValue() const; + float getRecentMaximum(uint32 curSyncStamp); + void setValue(float value, uint32 curSyncStamp); + +private: + RecentMaxSyncedValue(); + RecentMaxSyncedValue(RecentMaxSyncedValue const &); + RecentMaxSyncedValue &operator=(RecentMaxSyncedValue const &); + + float m_maximum; + float m_oldMaximum; + uint32 m_changeSyncStamp; + int const m_checkIntervalMs; + int const m_fudgeIntervalMs; +}; + +// ====================================================================== + +#endif // INCLUDED_RecentMaxSyncedValue_H + diff --git a/engine/server/library/serverUtility/src/shared/ResourceFractalData.cpp b/engine/server/library/serverUtility/src/shared/ResourceFractalData.cpp new file mode 100644 index 00000000..45e03b16 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/ResourceFractalData.cpp @@ -0,0 +1,27 @@ +// ====================================================================== +// +// ResourceFractalData.cpp +// copyright (c) 2004 Sony Online Entertainment +// +// ====================================================================== + +#include "serverUtility/FirstServerUtility.h" +#include "serverUtility/ResourceFractalData.h" + +#include "Archive/AutoByteStream.h" + +// ====================================================================== + +ResourceFractalData::ResourceFractalData() : + m_scaleX(0.0f), + m_scaleY(0.0f), + m_bias(0.0f), + m_gain(0.0f), + m_combinationRule(0), + m_frequency(0.0f), + m_amplitude(0.0f), + m_octaves(0) +{ +} + +// ====================================================================== diff --git a/engine/server/library/serverUtility/src/shared/ResourceFractalData.h b/engine/server/library/serverUtility/src/shared/ResourceFractalData.h new file mode 100644 index 00000000..4e13e489 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/ResourceFractalData.h @@ -0,0 +1,32 @@ +// ====================================================================== +// +// ResourceFractalData.h +// copyright (c) 2004 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_ResourceFractalData_H +#define INCLUDED_ResourceFractalData_H + +// ====================================================================== + +/** + * Fractal parameters for resource pools + */ +struct ResourceFractalData +{ + float m_scaleX; + float m_scaleY; + float m_bias; + float m_gain; + int m_combinationRule; + float m_frequency; + float m_amplitude; + int m_octaves; + + ResourceFractalData(); +}; + +// ====================================================================== + +#endif diff --git a/engine/server/library/serverUtility/src/shared/ServerClock.cpp b/engine/server/library/serverUtility/src/shared/ServerClock.cpp new file mode 100644 index 00000000..a5a13a8a --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/ServerClock.cpp @@ -0,0 +1,112 @@ +// ServerClock.cpp +// copyright 2001 Verant Interactive +// Author: Justin Randall + +//----------------------------------------------------------------------- + +#include "serverUtility/FirstServerUtility.h" +#include "serverUtility/ServerClock.h" +#include "sharedLog/Log.h" +#include +#include + +// ---------------------------------------------------------------------- + +const unsigned long ServerClock::cms_endOfTime = static_cast(-1); + +//----------------------------------------------------------------------- + +ServerClock::ServerClock() : +serverFrame(0), +subtractInterval(0), +lastTime(time(0)) +{ +} + +//----------------------------------------------------------------------- + +ServerClock::~ServerClock() +{ +} + +//----------------------------------------------------------------------- + +const unsigned long ServerClock::getGameTimeSeconds() const +{ + FATAL(!isSet(), ("ServerClock::getGameTimeSeconds: Clock was not set.")); + return int(lastTime - subtractInterval); +} + +//----------------------------------------------------------------------- + +void ServerClock::incrementServerFrame() +{ + const time_t currentTime = time(0); + + if (currentTime < lastTime-120 || currentTime > lastTime+120) + LOG("ServerClock", ("Clock changed by more than 120 seconds in a frame (%lu to %lu)!", lastTime, currentTime)); + lastTime = currentTime; + + serverFrame++; +} + +//----------------------------------------------------------------------- + +void ServerClock::setSubtractInterval(const unsigned long newSubtractInterval) +{ + subtractInterval = newSubtractInterval; +} + +//----------------------------------------------------------------------- + +void ServerClock::setGameTimeSeconds(const unsigned long newGameTime) +{ + subtractInterval = int(time(0) - newGameTime); + LOG("ServerClock", ("Game time set to %lu (subtract interval %lu)", newGameTime, subtractInterval)); +} + +//----------------------------------------------------------------------- + +ServerClock &ServerClock::getInstance() +{ + static ServerClock theInstance; + return theInstance; +} + +// ---------------------------------------------------------------------- + +/** + * Given a time in seconds, make a string that expresses how long it is. + * For debug output only. In English, not localized. Not thread-safe. + */ +std::string ServerClock::getDebugPrintableTimeframe(unsigned long const timeInSeconds) +{ + unsigned long const dayInSeconds = 60 * 60 * 24; + unsigned long const hourInSeconds = 60 * 60; + unsigned long const minuteInSeconds = 60; + + static char buffer[256]; + + if (timeInSeconds > dayInSeconds) + { + snprintf(buffer, 256, "~ %lu days", timeInSeconds / dayInSeconds); + } + else if (timeInSeconds > hourInSeconds) + { + snprintf(buffer, 256, "~ %lu hours", timeInSeconds / hourInSeconds); + } + else if (timeInSeconds > minuteInSeconds) + { + snprintf(buffer, 256, "~ %lu minutes", timeInSeconds / minuteInSeconds); + } + else + { + snprintf(buffer, 256, "%lu seconds", timeInSeconds); + } + + buffer[255]='\0'; + return std::string(buffer); +} + +// ====================================================================== + diff --git a/engine/server/library/serverUtility/src/shared/ServerClock.h b/engine/server/library/serverUtility/src/shared/ServerClock.h new file mode 100644 index 00000000..36ee93b9 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/ServerClock.h @@ -0,0 +1,54 @@ +// ServerClock.h +// copyright 2001 Verant Interactive +// Author: Justin Randall + +//----------------------------------------------------------------------- + +class ServerClock +{ +public: + static ServerClock &getInstance(); + + ~ServerClock(); + const unsigned long getGameTimeSeconds () const; + const unsigned long getServerFrame() const; + const unsigned long getSubtractInterval() const; + void incrementServerFrame(); + void setSubtractInterval(const unsigned long newSubtractInterval); + void setGameTimeSeconds (unsigned long newGameTime); + bool isSet () const; + std::string getDebugPrintableTimeframe (const unsigned long timeInSeconds); + + static const unsigned long cms_endOfTime; + +protected: + ServerClock(); + +private: + unsigned long serverFrame; + unsigned long subtractInterval; + mutable time_t lastTime; +}; + +//----------------------------------------------------------------------- + +inline const unsigned long ServerClock::getServerFrame() const +{ + return serverFrame; +} + +//----------------------------------------------------------------------- + +inline const unsigned long ServerClock::getSubtractInterval() const +{ + return subtractInterval; +} + +// ---------------------------------------------------------------------- + +inline bool ServerClock::isSet() const +{ + return subtractInterval!=0; +} + +//----------------------------------------------------------------------- diff --git a/engine/server/library/serverUtility/src/shared/ServerConnection.cpp b/engine/server/library/serverUtility/src/shared/ServerConnection.cpp new file mode 100644 index 00000000..c3cfdb1d --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/ServerConnection.cpp @@ -0,0 +1,297 @@ +// ====================================================================== +// +// ServerConnection.cpp +// copyright 2000 Verant Interactive +// Author: Justin Randall +// ====================================================================== + +#include "serverUtility/FirstServerUtility.h" +#include "serverUtility/ServerConnection.h" + +#include "Archive/ByteStream.h" +#include "serverNetworkMessages/CentralGameServerMessages.h" +#include "serverNetworkMessages/GameGameServerMessages.h" +#include "serverNetworkMessages/ReloadDatatableMessage.h" +#include "sharedLog/Log.h" +#include "sharedNetworkMessages/GameNetworkMessage.h" +#include "sharedNetworkMessages/GenericValueTypeMessage.h" +#include "sharedFoundation/NetworkIdArchive.h" +#include "sharedFoundation/Crc.h" +#include "sharedFoundation/Os.h" +#include "SystemAssignedProcessId.h" +#include "unicodeArchive/UnicodeArchive.h" +#include + +// ====================================================================== + +namespace ServerConnectionNamespace +{ + std::vector s_forwardableMessages; +} +using namespace ServerConnectionNamespace; + +// ====================================================================== + +void ServerConnection::install() // static +{ + s_forwardableMessages.push_back(Crc::calculate("AddGameServer")); // startup + s_forwardableMessages.push_back(Crc::calculate("DeltasMessage")); // deltas + s_forwardableMessages.push_back(Crc::calculate("SynchronizeScriptVarDeltasMessage"));// deltas + s_forwardableMessages.push_back(Crc::calculate("CreateObjectByCrcMessage")); // baselines + s_forwardableMessages.push_back(Crc::calculate("UpdateObjectPositionMessage")); // baselines + s_forwardableMessages.push_back(Crc::calculate("BaselinesMessage")); // baselines + s_forwardableMessages.push_back(Crc::calculate("SynchronizeScriptVarsMessage")); // baselines + s_forwardableMessages.push_back(Crc::calculate("setDecayTime")); // baselines + s_forwardableMessages.push_back(Crc::calculate("AiCreatureStateMessage")); // baselines + s_forwardableMessages.push_back(Crc::calculate("AiMovementMessage")); // baselines + s_forwardableMessages.push_back(Crc::calculate("EndBaselinesMessage")); // baselines + s_forwardableMessages.push_back(Crc::calculate("SlowDownEffectMessage")); // baselines + s_forwardableMessages.push_back(Crc::calculate("AuthTransferClientMessage")); // auth transfer + s_forwardableMessages.push_back(Crc::calculate("SetAuthoritativeMessage")); // auth transfer + s_forwardableMessages.push_back(Crc::calculate("CreateSyncUiMessage")); // auth transfer + s_forwardableMessages.push_back(Crc::calculate("PageChangeAuthority")); // auth transfer + s_forwardableMessages.push_back(Crc::calculate("AuthTransferConfirmMessage")); // auth transfer + s_forwardableMessages.push_back(Crc::calculate("PlayedTimeAccumMessage")); // auth transfer + s_forwardableMessages.push_back(Crc::calculate("UnloadObjectMessage")); // container transfer + s_forwardableMessages.push_back(Crc::calculate("UpdateContainmentMessage")); // container transfer + s_forwardableMessages.push_back(Crc::calculate("ObjControllerMessage")); // controller messages + s_forwardableMessages.push_back(Crc::calculate("TeleportMessage")); // teleport + s_forwardableMessages.push_back(Crc::calculate("PlayerSanityCheck")); // player sanity checker + s_forwardableMessages.push_back(Crc::calculate("PlayerSanityCheckProxy")); // player sanity checker + s_forwardableMessages.push_back(Crc::calculate("PlayerSanityCheckSuccess")); // player sanity checker + s_forwardableMessages.push_back(Crc::calculate("PlayerSanityCheckProxyFail")); // player sanity checker + s_forwardableMessages.push_back(Crc::calculate("UnloadPersistedCharacter")); // player sanity checker + s_forwardableMessages.push_back(Crc::calculate("AddResourceTypeMessage")); // universe data + s_forwardableMessages.push_back(Crc::calculate("AddImportedResourceType")); // universe data + s_forwardableMessages.push_back(Crc::calculate("UniverseCompleteMessage")); // universe data + s_forwardableMessages.push_back(Crc::calculate("SetTheaterMessage")); // universe data + s_forwardableMessages.push_back(Crc::calculate("ClearTheaterMessage")); // universe data + s_forwardableMessages.push_back(Crc::calculate("ManualDepleteResourceMessage")); // universe data + s_forwardableMessages.push_back(Crc::calculate("AddAttribModName")); // universe data + s_forwardableMessages.push_back(Crc::calculate("AddAttribModNamesList")); // universe data + s_forwardableMessages.push_back(Crc::calculate("CharacterNamesMessage")); // universe data + s_forwardableMessages.push_back(Crc::calculate("MessageToMessage")); // messageTos + s_forwardableMessages.push_back(Crc::calculate("WhoHasMessage")); // messageTos + s_forwardableMessages.push_back(Crc::calculate("ObjectNotOnServerMessage")); // messageTos + s_forwardableMessages.push_back(Crc::calculate("ObjectOnServerMessage")); // messageTos + s_forwardableMessages.push_back(Crc::calculate("EnableNewJediTrackingMessage")); // console commands + s_forwardableMessages.push_back(Crc::calculate("EnablePlayerSanityCheckerMessage")); // console commands + s_forwardableMessages.push_back(Crc::calculate("ReloadAdminTableMessage")); // console commands + s_forwardableMessages.push_back(Crc::calculate("ReloadCommandTableMessage")); // console commands + s_forwardableMessages.push_back(Crc::calculate(ReloadDatatableMessage::ms_messageName)); // console commands + s_forwardableMessages.push_back(Crc::calculate("ReloadScriptMessage")); // console commands + s_forwardableMessages.push_back(Crc::calculate("ReloadTemplateMessage")); // console commands + s_forwardableMessages.push_back(Crc::calculate("SetOverrideAccountAgeMessage")); // console commands + s_forwardableMessages.push_back(Crc::calculate("ClaimRewardsReplyMessage")); // veteran reward system + s_forwardableMessages.push_back(Crc::calculate("UnloadProxyMessage")); // object load + s_forwardableMessages.push_back(Crc::calculate("CSRSLReq")); // city (ClusterStartupResidenceStructureListRequest) + s_forwardableMessages.push_back(Crc::calculate("CSRSLRsp")); // city (ClusterStartupResidenceStructureListResponse) + + std::sort(s_forwardableMessages.begin(), s_forwardableMessages.end()); +} + +// ---------------------------------------------------------------------- + +const unsigned long ServerConnection::makeProcessId() // static +{ + static unsigned long pid = 0; + return ++pid; +} + +// ---------------------------------------------------------------------- + +bool ServerConnection::isMessageForwardable(unsigned long int type) // static +{ + return std::binary_search(s_forwardableMessages.begin(), s_forwardableMessages.end(), type); +} + +// ---------------------------------------------------------------------- + +ServerConnection::MessageConnectionCallback::MessageConnectionCallback(const char * const messageName) : +MessageDispatch::MessageBase(messageName) +{ +} + +// ---------------------------------------------------------------------- + +ServerConnection::MessageConnectionCallback::~MessageConnectionCallback() +{ +} + +// ---------------------------------------------------------------------- + +ServerConnection::MessageConnectionOverflowing::MessageConnectionOverflowing(const unsigned int newBytesPending) : +MessageDispatch::MessageBase("ConnectionOverflowing"), +bytesPending(newBytesPending) +{ +} + +// ---------------------------------------------------------------------- + +ServerConnection::MessageConnectionOverflowing::~MessageConnectionOverflowing() +{ +} + +// ---------------------------------------------------------------------- + +const unsigned int ServerConnection::MessageConnectionOverflowing::getBytesPending() const +{ + return bytesPending; +} + +// ---------------------------------------------------------------------- + +ServerConnection::ServerConnection(const std::string & a, const unsigned short p, const NetworkSetupData & setup) : +Connection(a, p, setup), +MessageDispatch::Emitter(), +processId(0), +osProcessId(0) +{ + char desc[1024] = {"\0"}; + snprintf(desc, sizeof(desc), "%s:%d", Os::getProgramName(), Os::getProcessId()); + GenericValueTypeMessage d("DescribeConnection", desc); + send(d, true); + SystemAssignedProcessId id(Os::getProcessId()); + send(id, true); +} + +// ---------------------------------------------------------------------- + +ServerConnection::ServerConnection(UdpConnectionMT * u, TcpClient * t) : +Connection(u, t), +MessageDispatch::Emitter(), +processId(0), +osProcessId(0) +{ + char desc[1024] = {"\0"}; + snprintf(desc, sizeof(desc), "%s:%d", Os::getProgramName(), Os::getProcessId()); + GenericValueTypeMessage d("DescribeConnection", desc); + send(d, true); + SystemAssignedProcessId id(Os::getProcessId()); + send(id, true); +} + +// ---------------------------------------------------------------------- + +ServerConnection::~ServerConnection() +{ +} + +// ---------------------------------------------------------------------- + +void ServerConnection::onConnectionClosed() +{ + static MessageConnectionCallback m("ConnectionClosed"); + emitMessage(m); +} + +// ---------------------------------------------------------------------- + +void ServerConnection::onConnectionOpened() +{ + processId = makeProcessId(); + static MessageConnectionCallback m("ConnectionOpened"); + emitMessage(m); +} + +// ---------------------------------------------------------------------- + +void ServerConnection::onConnectionOverflowing(const unsigned int bytesPending) +{ + // not static -- bytesPending is different each time this is invoked + MessageConnectionOverflowing m(bytesPending); + emitMessage(m); +} + +// ---------------------------------------------------------------------- + +void ServerConnection::onReceive(const Archive::ByteStream & message) +{ + try + { + Archive::ReadIterator r = message.begin(); + GameNetworkMessage m(r); + r = message.begin(); + if(m.isType("CentralGameServerSetProcessId")) + { + CentralGameServerSetProcessId p(r); + r = message.begin(); + processId = p.getProcessId(); + } + else if(m.isType("GameGameServerConnect")) + { + GameGameServerConnect p(r); + r = message.begin(); + processId = p.getProcessId(); + } + else if(m.isType("SystemAssignedProcessId")) + { + SystemAssignedProcessId id(r); + osProcessId = id.getId(); + } + else if(m.isType("DescribeConnection")) + { + GenericValueTypeMessage d(r); + describeConnection(d.getValue()); + } + + emitMessage(m); + } + catch(const Archive::ReadException & readException) + { + WARNING(true, ("Archive::ReadException : %s\n\tDisconnecting from remote server...", readException.what())); + disconnect(); + + } +} + +// ---------------------------------------------------------------------- + +void ServerConnection::reportReceive(const Archive::ByteStream & bs) +{ + Connection::reportReceive(bs); + static Archive::ReadIterator ri; + ri = bs.begin(); + GameNetworkMessage whatIsIt(ri); + NetworkHandler::reportMessage("recv." + whatIsIt.getCmdName(), bs.getSize()); +} + +// ---------------------------------------------------------------------- + +void ServerConnection::reportSend(const Archive::ByteStream & bs) +{ + Connection::reportReceive(bs); + static Archive::ReadIterator ri; + ri = bs.begin(); + GameNetworkMessage whatIsIt(ri); + NetworkHandler::reportMessage("send." + whatIsIt.getCmdName(), bs.getSize()); + + m_pendingPackets.push_back(std::make_pair(whatIsIt.getCmdName(), bs.getSize())); +} + +// ---------------------------------------------------------------------- + +void ServerConnection::send(const GameNetworkMessage & message, const bool reliable) +{ + static Archive::ByteStream a; + a.clear(); + message.pack(a); + Connection::send(a, reliable); +} + +// ---------------------------------------------------------------------- + +void ServerConnection::onConnectionStalled(const unsigned long stallTimeMs) +{ + LOG("Network", ("Connection to %s, pid %d stalled with %d bytes pending for %d milliseconds", getRemoteAddress().c_str(), getOsProcessId(), getPendingBytes(), stallTimeMs)); +} + +// ---------------------------------------------------------------------- + +void ServerConnection::setProcessId(const uint32 newProcessId) +{ + processId = newProcessId; +} + +// ====================================================================== + diff --git a/engine/server/library/serverUtility/src/shared/ServerConnection.h b/engine/server/library/serverUtility/src/shared/ServerConnection.h new file mode 100644 index 00000000..d7fd6519 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/ServerConnection.h @@ -0,0 +1,91 @@ +// ====================================================================== +// +// ServerConnection.h +// copyright 2000 Verant Interactive +// Author: Justin Randall +// ====================================================================== + +#ifndef _ServerConnection_H +#define _ServerConnection_H + +// ====================================================================== + +#include "sharedMessageDispatch/Emitter.h" +#include "sharedMessageDispatch/Message.h" +#include "sharedNetwork/Connection.h" + +// ====================================================================== + +class GameNetworkMessage; + +// ====================================================================== + +class ServerConnection: public Connection, public MessageDispatch::Emitter +{ +public: + ServerConnection (const std::string & address, const unsigned short port, const NetworkSetupData &); + ServerConnection (UdpConnectionMT *, TcpClient * t); + virtual ~ServerConnection (); + + static void install (); + static const unsigned long makeProcessId (); + static bool isMessageForwardable (unsigned long int type); + + const unsigned long getProcessId () const; + const unsigned long getOsProcessId () const; + virtual void onConnectionClosed (); + virtual void onConnectionOpened (); + virtual void onConnectionOverflowing (const unsigned int bytesPending); + virtual void onConnectionStalled (const unsigned long stallTimeMs); + virtual void onReceive (const Archive::ByteStream & message); + virtual void reportReceive (const Archive::ByteStream & bs); + virtual void reportSend (const Archive::ByteStream & bs); + virtual void send (const GameNetworkMessage & message, const bool reliable); + virtual void setProcessId (const unsigned long newProcessId); + +public: + class MessageConnectionCallback: public MessageDispatch::MessageBase + { + public: + MessageConnectionCallback(const char * const messageName); + ~MessageConnectionCallback(); + }; + + class MessageConnectionOverflowing : public MessageDispatch::MessageBase + { + public: + MessageConnectionOverflowing(const unsigned int bytesPending); + ~MessageConnectionOverflowing(); + + const unsigned int getBytesPending() const; + private: + unsigned int bytesPending; + }; + +private: + ServerConnection(const ServerConnection&); //disable + ServerConnection &operator=(const ServerConnection&); //disable + +private: + unsigned long processId; + unsigned long osProcessId; // remote's operating system assigned PID +}; + +//----------------------------------------------------------------------- + +inline const unsigned long ServerConnection::getProcessId(void) const +{ + return processId; +} + +//----------------------------------------------------------------------- + +inline const unsigned long ServerConnection::getOsProcessId() const +{ + return osProcessId; +} + +// ====================================================================== + +#endif // _ServerConnection_H + diff --git a/engine/server/library/serverUtility/src/shared/ServerServiceHandler.h b/engine/server/library/serverUtility/src/shared/ServerServiceHandler.h new file mode 100644 index 00000000..ecc698cc --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/ServerServiceHandler.h @@ -0,0 +1,38 @@ +#ifndef _SERVER_SERVICE_HANDLER_H +#define _SERVER_SERVICE_HANDLER_H + +#include "Network/ConnectionHandler.h" + +#include +#include "ServiceHandler.h" + +class ServerServiceHandler : +public ServiceHandler +{ +public: + virtual ~ServerServiceHandler(); + virtual void onConnectionClose(NetConnection * closingConnection, ConnectionHandler * connectionHandler, uint32 causeCode); +protected: + std::list _connections; +}; + +inline ServerServiceHandler::~ServerServiceHandler() +{ + std::list::iterator i; + ConnectionHandler * c; + + for(i = _connections.begin(); i != _connections.end(); ++i) + { + c = *i; + delete c; + } + _connections.clear(); +} + +inline void ServerServiceHandler::onConnectionClose(NetConnection * closingConnection, ConnectionHandler * connectionHandler, uint32 causeCode) +{ + _connections.remove(connectionHandler); + delete connectionHandler; +} + +#endif _SERVER_SERVICE_HANDLER_H \ No newline at end of file diff --git a/engine/server/library/serverUtility/src/shared/SetupServerUtility.cpp b/engine/server/library/serverUtility/src/shared/SetupServerUtility.cpp new file mode 100644 index 00000000..6e3c7424 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/SetupServerUtility.cpp @@ -0,0 +1,25 @@ +// ====================================================================== +// +// SetupServerUtility.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "serverUtility/FirstServerUtility.h" +#include "serverUtility/SetupServerUtility.h" + +#include "serverUtility/ChatLogManager.h" +#include "serverUtility/ConfigServerUtility.h" +#include "serverUtility/ServerConnection.h" + +// ====================================================================== + +void SetupServerUtility::install() +{ + ConfigServerUtility::install(); + ChatLogManager::install(); + ServerConnection::install(); +} + + +// ====================================================================== diff --git a/engine/server/library/serverUtility/src/shared/SetupServerUtility.h b/engine/server/library/serverUtility/src/shared/SetupServerUtility.h new file mode 100644 index 00000000..e2bc416f --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/SetupServerUtility.h @@ -0,0 +1,27 @@ +// ====================================================================== +// +// SetupServerUtility.h +// copyright (c) 2004 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_SetupServerUtility_H +#define INCLUDED_SetupServerUtility_H + +// ====================================================================== + +class SetupServerUtility +{ +public: + + static void install(); + +private: + SetupServerUtility(); + SetupServerUtility(const SetupServerUtility &); + SetupServerUtility &operator =(const SetupServerUtility &); +}; + +// ====================================================================== + +#endif diff --git a/engine/server/library/serverUtility/src/shared/SystemAssignedProcessId.cpp b/engine/server/library/serverUtility/src/shared/SystemAssignedProcessId.cpp new file mode 100644 index 00000000..3ad1949b --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/SystemAssignedProcessId.cpp @@ -0,0 +1,43 @@ +// SystemAssignedProcessId.cpp +// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +//----------------------------------------------------------------------- + +#include "serverUtility/FirstServerUtility.h" +#include "SystemAssignedProcessId.h" + +//----------------------------------------------------------------------- + +SystemAssignedProcessId::SystemAssignedProcessId(const unsigned long id) : +GameNetworkMessage("SystemAssignedProcessId"), +m_id(id) +{ + addVariable(m_id); +} + +//----------------------------------------------------------------------- + +SystemAssignedProcessId::SystemAssignedProcessId(Archive::ReadIterator & source) : +GameNetworkMessage("SystemAssignedProcessId"), +m_id() +{ + addVariable(m_id); + unpack(source); +} + +//----------------------------------------------------------------------- + +SystemAssignedProcessId::~SystemAssignedProcessId() +{ +} + +//----------------------------------------------------------------------- + +const unsigned long SystemAssignedProcessId::getId() const +{ + return m_id.get(); +} + +//----------------------------------------------------------------------- + diff --git a/engine/server/library/serverUtility/src/shared/SystemAssignedProcessId.h b/engine/server/library/serverUtility/src/shared/SystemAssignedProcessId.h new file mode 100644 index 00000000..2ecbf8b0 --- /dev/null +++ b/engine/server/library/serverUtility/src/shared/SystemAssignedProcessId.h @@ -0,0 +1,32 @@ +// SystemAssignedProcessId.h +// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +#ifndef _INCLUDED_SystemAssignedProcessId_H +#define _INCLUDED_SystemAssignedProcessId_H + +//----------------------------------------------------------------------- + +#include "sharedNetworkMessages/GameNetworkMessage.h" + +//----------------------------------------------------------------------- + +class SystemAssignedProcessId : public GameNetworkMessage +{ +public: + explicit SystemAssignedProcessId(const unsigned long id); + explicit SystemAssignedProcessId(Archive::ReadIterator & source); + ~SystemAssignedProcessId(); + + const unsigned long getId () const; + +private: + SystemAssignedProcessId & operator = (const SystemAssignedProcessId & rhs); + SystemAssignedProcessId(const SystemAssignedProcessId & source); + + Archive::AutoVariable m_id; +}; + +//----------------------------------------------------------------------- + +#endif // _INCLUDED_SystemAssignedProcessId_H diff --git a/engine/server/library/serverUtility/src/win32/FirstServerUtility.cpp b/engine/server/library/serverUtility/src/win32/FirstServerUtility.cpp new file mode 100644 index 00000000..73488cc4 --- /dev/null +++ b/engine/server/library/serverUtility/src/win32/FirstServerUtility.cpp @@ -0,0 +1,2 @@ + +#include "serverUtility/FirstServerUtility.h" \ No newline at end of file