Added serverUtility library

This commit is contained in:
Anonymous
2014-01-15 01:33:26 -07:00
parent ed496d5653
commit 222d858a18
56 changed files with 3936 additions and 0 deletions
+1
View File
@@ -1,3 +1,4 @@
add_subdirectory(serverKeyShare)
add_subdirectory(serverMetrics)
add_subdirectory(serverUtility)
@@ -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)
@@ -0,0 +1 @@
#include "../../src/shared/AdminAccountManager.h"
@@ -0,0 +1 @@
#include "../../src/shared/ChatLogManager.h"
@@ -0,0 +1 @@
#include "../../src/shared/ClusterWideDataManager.h"
@@ -0,0 +1 @@
#include "../../src/shared/ClusterWideDataManagerList.h"
@@ -0,0 +1 @@
#include "../../src/shared/ConfigServerUtility.h"
@@ -0,0 +1 @@
#include "../../src/shared/FirstServerUtility.h"
@@ -0,0 +1 @@
#include "../../src/shared/FreeCtsDataTable.h"
@@ -0,0 +1 @@
#include "../../src/shared/LocationData.h"
@@ -0,0 +1 @@
#include "../../src/shared/MissionLocation.h"
@@ -0,0 +1 @@
#include "../../src/shared/PopulationList.h"
@@ -0,0 +1,2 @@
#include "../../src/shared/PvpEnemy.h"
@@ -0,0 +1,2 @@
#include "../../src/shared/RecentMaxSyncedValue.h"
@@ -0,0 +1 @@
#include "../../src/shared/ResourceFractalData.h"
@@ -0,0 +1 @@
#include "../../src/shared/ServerClock.h"
@@ -0,0 +1 @@
#include "../../src/shared/ServerConnection.h"
@@ -0,0 +1 @@
#include "../../src/shared/ServerServiceHandler.h"
@@ -0,0 +1 @@
#include "../../src/shared/SetupServerUtility.h"
@@ -0,0 +1,72 @@
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_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/unicode/include
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicodeArchive/include/public
)
add_library(serverUtility STATIC
${SHARED_SOURCES}
${PLATFORM_SOURCES}
)
@@ -0,0 +1,22 @@
//#include "FirstGame.h"
#include <hash_map> //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<bool> 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<bool>::_M_list[__stl_num_primes] = __PRIME_LIST_BODY;
#undef __stl_num_primes
#undef __PRIME_LIST_BODY
@@ -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 <string>
//-----------------------------------------------------------------------
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<const char *> ipAddrs;
ms_adminTable->getStringColumn("AdminIpBlocks", ipAddrs);
bool retval = false;
for (std::vector<const char *>::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);
}
//-----------------------------------------------------------------------
@@ -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
@@ -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 <list>
#include <map>
// ============================================================================
//
// 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<std::pair<time_t, int> > TimeLog;
typedef std::map<int, ChatLogEntry> ChatLog;
typedef std::map<Unicode::String, int> PlayerLog;
typedef std::map<Unicode::String const *, int, LessPointerComparator> 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<time_t>(ConfigServerUtility::getChatLogMinutes() * 60);
TimeLog::iterator iterTimeLog = s_timeLog.begin();
int chatLogCount = static_cast<int>(s_timeLog.size());
int purgedMessages = 0;
for (; iterTimeLog != s_timeLog.end(); ++iterTimeLog)
{
time_t const time = iterTimeLog->first;
if ( (time < (systemTime - chatLogPurgeTime))
|| (static_cast<int>(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())));
}
// ============================================================================
@@ -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
@@ -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<std::string> & elementNameList,
std::vector<ValueDictionary> & 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<ElementData *> 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<ElementData *>::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);
}
}
// ======================================================================
@@ -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 <map>
#include <string>
#include <vector>
// ======================================================================
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<std::string> & elementNameList,
std::vector<ValueDictionary> & 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<std::string, ElementData> 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
@@ -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<unsigned long, QueuedRequestInfo> QueuedRequestList;
typedef std::multimap<unsigned long, LockInfo> ServerLockList;
typedef std::pair<ServerLockList::const_iterator, ServerLockList::const_iterator> ServerLockListConstRange;
typedef std::pair<ServerLockList::iterator, ServerLockList::iterator> ServerLockListRange;
typedef std::map<std::string, ClusterWideDataManager *> ManagerList;
typedef std::map<unsigned long, float> 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<const GameNetworkMessage *>(&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<ServerConnection *>(dynamic_cast<ServerConnection const *>(&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<const GameNetworkMessage *>(&message)->getByteStream().begin();
ClusterWideDataReleaseLockMessage msg(ri);
ServerConnection const * server = dynamic_cast<ServerConnection const *>(&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<const GameNetworkMessage *>(&message)->getByteStream().begin();
ClusterWideDataRemoveElementMessage msg(ri);
ServerConnection const * server = dynamic_cast<ServerConnection const *>(&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<const GameNetworkMessage *>(&message)->getByteStream().begin();
ClusterWideDataUpdateDictionaryMessage msg(ri);
ServerConnection const * server = dynamic_cast<ServerConnection const *>(&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<std::string> elementNameList;
std::vector<ValueDictionary> 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<float>(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();
}
// ======================================================================
@@ -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
@@ -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()
{
}
//-----------------------------------------------------------------------
@@ -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
@@ -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
@@ -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<std::string, FreeCtsDataTable::FreeCtsInfo> 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<std::string, FreeCtsDataTable::FreeCtsInfo>::const_iterator iter = s_freeCtsList.begin(); iter != s_freeCtsList.end(); ++iter)
{
std::string targetClusters;
for (std::map<std::string, std::string>::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<std::string, FreeCtsDataTable::FreeCtsInfo> 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<std::multimap<std::string, FreeCtsInfo>::const_iterator, std::multimap<std::string, FreeCtsInfo>::const_iterator> range = s_freeCtsList.equal_range(Unicode::toLower(sourceCluster));
for (std::multimap<std::string, FreeCtsInfo>::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<std::multimap<std::string, FreeCtsInfo>::const_iterator, std::multimap<std::string, FreeCtsInfo>::const_iterator> range = s_freeCtsList.equal_range(Unicode::toLower(sourceCluster));
for (std::multimap<std::string, FreeCtsInfo>::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<std::multimap<std::string, FreeCtsInfo>::const_iterator, std::multimap<std::string, FreeCtsInfo>::const_iterator> range = s_freeCtsList.equal_range(Unicode::toLower(sourceCluster));
for (std::multimap<std::string, FreeCtsInfo>::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;
}
@@ -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 <map>
#include <string>
// ======================================================================
class FreeCtsDataTable // static class
{
public:
struct FreeCtsInfo
{
std::string ruleName;
std::string ruleDescription;
std::map<std::string, std::string> targetCluster;
time_t startTime;
time_t endTime;
time_t sourceCharacterCreateTimeLower;
time_t sourceCharacterCreateTimeUpper;
};
static std::string const & getFreeCtsFileName();
static stdmultimap<std::string, FreeCtsDataTable::FreeCtsInfo>::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
@@ -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);
}
}
// ======================================================================
@@ -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 <int S> */
/* 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
@@ -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);
}
}
// ======================================================================
@@ -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 <int S>
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> &region_name, const DB::BindableNetworkId &cell);
void packToDatabase(DB::BindableDouble &x,DB::BindableDouble &y, DB::BindableDouble &z, DB::BindableString<500> &planet, DB::BindableString<500> &region_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
@@ -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<Location, int>(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);
}
}
}
// ======================================================================
@@ -0,0 +1,100 @@
// ======================================================================
//
// PopulationList.h
// copyright (c) 2003 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_PopulationList_H
#define INCLUDED_PopulationList_H
// ======================================================================
#include <string>
#include <map>
// ======================================================================
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<Location, int> 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
@@ -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);
}
// ======================================================================
}
// ======================================================================
@@ -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
@@ -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<int>(0xffffffff-delta);
return static_cast<int>(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;
}
// ======================================================================
@@ -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
@@ -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)
{
}
// ======================================================================
@@ -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
@@ -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 <time.h>
#include <string>
// ----------------------------------------------------------------------
const unsigned long ServerClock::cms_endOfTime = static_cast<unsigned long>(-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);
}
// ======================================================================
@@ -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;
}
//-----------------------------------------------------------------------
@@ -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 <algorithm>
// ======================================================================
namespace ServerConnectionNamespace
{
std::vector<unsigned long int> 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<std::string> 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<std::string> 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<std::string> 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;
}
// ======================================================================
@@ -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
@@ -0,0 +1,38 @@
#ifndef _SERVER_SERVICE_HANDLER_H
#define _SERVER_SERVICE_HANDLER_H
#include "Network/ConnectionHandler.h"
#include <list>
#include "ServiceHandler.h"
class ServerServiceHandler :
public ServiceHandler
{
public:
virtual ~ServerServiceHandler();
virtual void onConnectionClose(NetConnection * closingConnection, ConnectionHandler * connectionHandler, uint32 causeCode);
protected:
std::list<ConnectionHandler *> _connections;
};
inline ServerServiceHandler::~ServerServiceHandler()
{
std::list<ConnectionHandler *>::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
@@ -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();
}
// ======================================================================
@@ -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
@@ -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();
}
//-----------------------------------------------------------------------
@@ -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<unsigned long> m_id;
};
//-----------------------------------------------------------------------
#endif // _INCLUDED_SystemAssignedProcessId_H
@@ -0,0 +1,2 @@
#include "serverUtility/FirstServerUtility.h"