Added TaskManager app

This commit is contained in:
Anonymous
2014-01-16 20:06:39 -07:00
parent 39e541c767
commit 2bcd8a262c
46 changed files with 4822 additions and 0 deletions
+1
View File
@@ -1,2 +1,3 @@
add_subdirectory(LoginServer)
add_subdirectory(TaskManager)
@@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 2.8)
project(TaskManager)
add_subdirectory(src)
@@ -0,0 +1,116 @@
set(SHARED_SOURCES
shared/CentralConnection.cpp
shared/CentralConnection.h
shared/ConfigTaskManager.cpp
shared/ConfigTaskManager.h
shared/ConsoleConnection.cpp
shared/ConsoleConnection.h
shared/Console.cpp
shared/Console.h
shared/ConsoleImplementation.cpp
shared/ConsoleImplementation.h
shared/DatabaseConnection.cpp
shared/DatabaseConnection.h
shared/EnvironmentVariable.h
shared/FirstTaskManager.cpp
shared/FirstTaskManager.h
shared/GameConnection.cpp
shared/GameConnection.h
shared/Locator.cpp
shared/Locator.h
shared/ManagerConnection.cpp
shared/ManagerConnection.h
shared/MetricsServerConnection.cpp
shared/MetricsServerConnection.h
shared/PlanetConnection.cpp
shared/PlanetConnection.h
shared/ProcessSpawner.h
shared/TaskConnection.cpp
shared/TaskConnection.h
shared/TaskHandler.cpp
shared/TaskHandler.h
shared/TaskManager.cpp
shared/TaskManager.h
shared/TaskManagerSysInfo.h
)
if(WIN32)
set(PLATFORM_SOURCES
win32/ConsoleInput.cpp
win32/EnvironmentVariable.cpp
win32/ProcessSpawner.cpp
win32/TaskManagerSysInfo.cpp
win32/WinMain.cpp
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/win32)
else()
set(PLATFORM_SOURCES
linux/ConsoleInput.cpp
linux/EnvironmentVariable.cpp
linux/main.cpp
linux/ProcessSpawner.cpp
linux/TaskManagerSysInfo.cpp
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/linux)
endif()
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/shared
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedCompression/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedDebug/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFile/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/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/sharedThread/include/public
${SWG_ENGINE_SOURCE_DIR}/server/library/serverNetworkMessages/include/public
${SWG_ENGINE_SOURCE_DIR}/server/library/serverUtility/include/public
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/archive/include
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/fileInterface/include/public
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/singleton/include
)
link_directories(${STLPORT_LIBDIR})
add_executable(TaskManager
${SHARED_SOURCES}
${PLATFORM_SOURCES}
)
target_link_libraries(TaskManager
sharedCompression
sharedDebug
sharedFile
sharedFoundation
sharedLog
sharedMath
sharedMemoryManager
sharedMessageDispatch
sharedNetwork
sharedNetworkMessages
sharedRandom
sharedSynchronization
sharedThread
sharedUtility
serverNetworkMessages
serverUtility
archive
fileInterface
localization
localizationArchive
unicode
unicodeArchive
udplibrary
${ZLIB_LIBRARY}
)
if(WIN32)
target_link_libraries(TaskManager mswsock ws2_32)
endif()
@@ -0,0 +1,58 @@
// TaskManager.cpp
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTaskManager.h"
#include "Console.h"
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <curses.h>
//-----------------------------------------------------------------------
struct SetBufferMode
{
SetBufferMode();
~SetBufferMode() {};
};
SetBufferMode::SetBufferMode()
{
setvbuf(stdin, NULL, _IONBF, 0);
}
//-----------------------------------------------------------------------
const char Console::getNextChar()
{
static SetBufferMode setBufferMode;
char result = 0;
fd_set rfds;
struct timeval tv;
FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 0;
int ready = select(1, &rfds, 0, 0, &tv);
if(ready)
{
result = static_cast<char>(getchar());
if(result < 1)
result = 0;
}
/*
if(_kbhit())
result = static_cast<char>(_getche());
*/
return result;
}
//-----------------------------------------------------------------------
@@ -0,0 +1,39 @@
#include "FirstTaskManager.h"
#include <stdlib.h>
#include <string>
namespace EnvironmentVariable
{
bool addToEnvironmentVariable(const char* key, const char* value)
{
bool retval = false;
const char* oldValue = getenv(key);
if (oldValue)
{
std::string s(oldValue);
s += ":";
s += value;
//Bad things happen if the first character happens to be : (ie from an empty environment string)
const char* newValue = s.c_str();
if (newValue[0] == ':')
++newValue;
retval = (setenv(key, newValue, 1) == 0);
}
else
{
retval = (setenv(key, value, 0) == 0);
}
return retval;
}
bool setEnvironmentVariable(const char* key, const char* value)
{
return (setenv(key, value, 1) == 0);
}
};
@@ -0,0 +1,167 @@
#include "sharedFoundation/FirstSharedFoundation.h"
#include "ProcessSpawner.h"
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <wait.h>
#include <vector>
uint32 ProcessSpawner::prefix;
//-----------------------------------------------------------------------
bool tokenize (const std::string & str, std::vector<std::string> & result)
{
size_t end_pos = 0;
size_t start_pos = 0;
result.clear ();
for (;;)
{
if (end_pos >= str.size ())
break;
start_pos = str.find_first_not_of (' ', end_pos);
if (start_pos == str.npos) //lint !e1705
break;
//----------------------------------------------------------------------
if (str [start_pos] == '\"')
{
if (++start_pos >= str.size ())
break;
end_pos = str.find_first_of ('\"', start_pos);
}
else
end_pos = str.find_first_of (' ', start_pos);
//----------------------------------------------------------------------
if (start_pos == end_pos)
break;
if (end_pos == str.npos) //lint !e1705
{
result.push_back (str.substr (start_pos));
break;
}
else
{
result.push_back (str.substr (start_pos, end_pos - start_pos));
}
++start_pos;
}
return true;
}
// ----------------------------------------------------------------------
uint32 execute(const char * commandLine, char * const * parameters)
{
DEBUG_REPORT_LOG(true, ("Now Attempting To Spawn %s\n", commandLine));
pid_t p;
// fork
p = fork();
if (p == 0)
{
// i am child
DEBUG_REPORT_LOG(true, ("Now Spawning %s\n", commandLine));
int result = execv(commandLine, parameters); //lint !e10 Expecting a function (huh?)
if (result == -1)
{
IGNORE_RETURN(perror("execv")); //lint !e10
_exit(0);
}
}
return p; //lint !e732 Loss of sign
}
// ----------------------------------------------------------------------
void makeParameters(const std::vector<std::string> & parameters, std::vector<char *> & p)
{
std::vector<std::string>::const_iterator i;
for(i = parameters.begin(); i != parameters.end(); ++i)
{
char * arg = new char[(*i).length() + 1];
strcpy(arg, (*i).c_str()); //lint !e64 !e534
p.push_back(arg);
}
p.push_back(NULL);
}
// ----------------------------------------------------------------------
void freeParameters(std::vector<char *> & p)
{
std::vector<char *>::iterator piter;
for(piter = p.begin(); piter != p.end(); ++piter)
{
char * arg = (*piter);
delete[] arg;
}
}
// ----------------------------------------------------------------------
uint32 ProcessSpawner::execute(const std::string & commandLine, const std::vector<std::string> & parameters)
{
std::vector<char *> p;
makeParameters(parameters, p);
std::string c = "./";
c += commandLine;
uint32 pid = ::execute(c.c_str(), &p[0]);
freeParameters(p);
return pid;
}
// ----------------------------------------------------------------------
uint32 ProcessSpawner::execute(const std::string & commandLine)
{
std::vector<std::string> parameters;
IGNORE_RETURN(tokenize(commandLine, parameters));
std::vector<char *> p;
makeParameters(parameters, p);
uint32 result = ::execute(p[0], &p[0]);
freeParameters(p);
return result;
}
// ----------------------------------------------------------------------
bool ProcessSpawner::isProcessActive(uint32 pid)
{
pid_t result = waitpid(static_cast<pid_t>(pid), 0, WNOHANG|WUNTRACED);
return (result < 1);
}
// ----------------------------------------------------------------------
void ProcessSpawner::kill(uint32 pid)
{
IGNORE_RETURN(::kill(static_cast<int>(pid), SIGKILL));
int status;
IGNORE_RETURN(waitpid(static_cast<int>(pid), &status, 0));
}
// ----------------------------------------------------------------------
void ProcessSpawner::forceCore(const unsigned long pid)
{
IGNORE_RETURN(::kill(static_cast<int>(pid), SIGABRT));
}
// ----------------------------------------------------------------------
@@ -0,0 +1,85 @@
// TaskManagerSysInfo.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTaskManager.h"
#include "TaskManagerSysInfo.h"
#include <sys/sysinfo.h>
#include "TaskManager.h"
//-----------------------------------------------------------------------
TaskManagerSysInfo::TaskManagerSysInfo() :
averageScore()
{
update();
}
//-----------------------------------------------------------------------
TaskManagerSysInfo::TaskManagerSysInfo(const TaskManagerSysInfo &)
{
}
//-----------------------------------------------------------------------
TaskManagerSysInfo::~TaskManagerSysInfo()
{
}
//-----------------------------------------------------------------------
TaskManagerSysInfo & TaskManagerSysInfo::operator = (const TaskManagerSysInfo & rhs)
{
if(this != &rhs)
{
// make assignments if right hand side is not this instance
}
return *this;
}
//-----------------------------------------------------------------------
const float TaskManagerSysInfo::getScore() const
{
#if 0
//Temporariy remove this since it's not giving us good results
FILE * avg = popen("uptime", "r");
float a = 0.0f;
if(avg)
{
std::string output;
while(!feof(avg))
{
char buf[1024] = {"\0"};
fread(buf, sizeof(buf), 1, avg);
output += buf;
}
char formatted[1024] = {"\0"};
std::string load = output.substr(output.find("load average:"));
sscanf(load.c_str(), "load average: %f", &a);
pclose(avg);
}
return a;
#else
float ret = static_cast<float>(TaskManager::getNumGameConnections());
return ret;
#endif
}
//-----------------------------------------------------------------------
void TaskManagerSysInfo::update()
{
}
//-----------------------------------------------------------------------
@@ -0,0 +1,45 @@
#include "sharedFoundation/FirstSharedFoundation.h"
#include "ConfigTaskManager.h"
#include "TaskManager.h"
#include "sharedCompression/SetupSharedCompression.h"
#include "sharedDebug/SetupSharedDebug.h"
#include "sharedFile/SetupSharedFile.h"
#include "sharedFoundation/ConfigFile.h"
#include "sharedFoundation/Os.h"
#include "sharedFoundation/SetupSharedFoundation.h"
#include "sharedNetworkMessages/SetupSharedNetworkMessages.h"
#include "sharedRandom/SetupSharedRandom.h"
#include "sharedThread/SetupSharedThread.h"
// ======================================================================
int main(int argc, char ** argv)
{
SetupSharedThread::install();
SetupSharedDebug::install(1024);
//-- setup foundation
SetupSharedFoundation::Data setupFoundationData(SetupSharedFoundation::Data::D_game);
setupFoundationData.lpCmdLine = ConvertCommandLine(argc,argv);
setupFoundationData.configFile = "taskmanager.cfg";
SetupSharedFoundation::install (setupFoundationData);
SetupSharedCompression::install();
SetupSharedFile::install(false);
SetupSharedNetworkMessages::install();
SetupSharedRandom::install(static_cast<uint32>(time(NULL))); //lint !e1924 !e64 // NULL is a C-Style cast?
Os::setProgramName("TaskManager");
//setup the server
ConfigTaskManager::install();
//-- run game
TaskManager::install();
TaskManager::run();
TaskManager::remove();
SetupSharedFoundation::remove();
return 0;
}
@@ -0,0 +1,115 @@
// CentralConnection.cpp
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTaskManager.h"
#include "CentralConnection.h"
#include "TaskConnection.h"
#include "TaskManager.h"
#include "serverNetworkMessages/PreloadFinishedMessage.h"
#include "serverNetworkMessages/TaskSpawnProcess.h"
#include "sharedNetworkMessages/ConsoleChannelMessages.h"
#include "sharedFoundation/Clock.h"
#include "sharedMessageDispatch/Transceiver.h"
//-----------------------------------------------------------------------
CentralConnection::CentralConnection(TaskConnection * c, const std::string & n) :
TaskHandler(),
callback(),
commandLine(n),
connected(true),
connection(c),
lastSpawnTime(Clock::timeMs())
{
callback.connect(c->getTransceiverClosed(), *this, &CentralConnection::closed); //lint !e1025 !e1703 !e1514 !e64
callback.connect(*this, &CentralConnection::onProcessKilled); //lint !e1025 !e1703 !e1514 !e64 !e1058 !e118
// TaskManager::startServer("ConnectionServer", "");
// TaskManager::startServer("SwgDatabaseServer", "");
}
//-----------------------------------------------------------------------
CentralConnection::~CentralConnection()
{
connection = 0;
}
//-----------------------------------------------------------------------
void CentralConnection::closed(const Closed &)
{
if(connected)
{
ProcessAborted a;
a.commandLine = commandLine;
a.hostName = NetworkHandler::getHostName();
MessageDispatch::Transceiver<const ProcessAborted &> b;
b.emitMessage(a);
unsigned long t = Clock::timeMs();
if(t - lastSpawnTime > 5000) // stop spawning if it bombs immediately
{
lastSpawnTime = t;
// need to restart it!
//IGNORE_RETURN(TaskManager::startServer(commandLine));
}
else
{
// emit the killed message
ProcessKilled k;
k.commandLine = a.commandLine;
k.hostName = a.hostName;
MessageDispatch::Transceiver<const ProcessKilled &> pk;
pk.emitMessage(k);
}
connected = false;
TaskManager::setCentralConnection(0);
}
}
//-----------------------------------------------------------------------
void CentralConnection::onProcessKilled(const ProcessKilled & k)
{
if(k.commandLine == commandLine)
lastSpawnTime = Clock::timeMs(); // force it to stay dead
}
//-----------------------------------------------------------------------
void CentralConnection::receive(const Archive::ByteStream & message)
{
Archive::ReadIterator r(message);
GameNetworkMessage m(r);
r = message.begin();
if(m.isType("TaskSpawnProcess"))
{
TaskSpawnProcess s(r);
IGNORE_RETURN(TaskManager::startServer(s.getProcessName(), s.getOptions(), s.getTargetHostAddress(), s.getSpawnDelay()));
}
else if(m.isType("PreloadFinishedMessage"))
{
PreloadFinishedMessage m(r);
if (m.getFinished())
TaskManager::onPreloadFinished();
}
else if(m.isType("ConGenericMessage"))
{
ConGenericMessage taskConsoleCommand(r);
static std::string command = taskConsoleCommand.getMsg();
while(command.rfind(' ') != command.npos || command.rfind('\n') != command.npos || command.rfind('\r') != command.npos)
{
command = command.substr(0, command.length() - 1);
}
TaskManager::executeCommand(command);
}
}
//-----------------------------------------------------------------------
@@ -0,0 +1,42 @@
// CentralConnection.h
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_CentralConnection_H
#define _INCLUDED_CentralConnection_H
//-----------------------------------------------------------------------
#include "sharedMessageDispatch/Transceiver.h"
#include "TaskHandler.h"
class TaskConnection;
struct Closed;
//-----------------------------------------------------------------------
class CentralConnection : public TaskHandler
{
public:
CentralConnection(TaskConnection * newConnection, const std::string & commandLine);
~CentralConnection();
void closed(const Closed &);
void receive(const Archive::ByteStream & message);
private:
CentralConnection & operator = (const CentralConnection & rhs);
CentralConnection(const CentralConnection & source);
void onProcessKilled(const struct ProcessKilled &);
private:
MessageDispatch::Callback callback;
std::string commandLine;
bool connected;
TaskConnection * connection;
unsigned long lastSpawnTime;
}; //lint !e1712 default constructor not defined for class 'CentralConnection'
//-----------------------------------------------------------------------
#endif // _INCLUDED_CentralConnection_H
@@ -0,0 +1,108 @@
// ConfigTaskManager.cpp
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTaskManager.h"
#include "sharedFoundation/ConfigFile.h"
#include "sharedNetwork/SetupSharedNetwork.h"
#include "ConfigTaskManager.h"
#include <vector>
//-----------------------------------------------------------------------
ConfigTaskManager::Data * ConfigTaskManager::data = 0;
#define KEY_INT(a,b) (data->a = ConfigFile::getKeyInt("TaskManager", #a, b))
#define KEY_BOOL(a,b) (data->a = ConfigFile::getKeyBool("TaskManager", #a, b))
#define KEY_FLOAT(a,b) (data->a = ConfigFile::getKeyFloat("TaskManager", #a, b))
#define KEY_STRING(a,b) (data->a = ConfigFile::getKeyString("TaskManager", #a, b))
//-----------------------------------------------------------------------
namespace ConfigTaskManagerNamespace
{
typedef std::vector<char const *> StringPtrArray;
StringPtrArray ms_environmentVariable; // ConfigFile owns the pointer
}
using namespace ConfigTaskManagerNamespace;
// ======================================================================
int ConfigTaskManager::getNumberOfEnvironmentVariables()
{
return static_cast<int>(ms_environmentVariable.size());
}
// ----------------------------------------------------------------------
char const * ConfigTaskManager::getEnvironmentVariable(int index)
{
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, index, getNumberOfEnvironmentVariables());
return ms_environmentVariable[static_cast<size_t>(index)];
}
// ----------------------------------------------------------------------
void ConfigTaskManager::install(void)
{
SetupSharedNetwork::SetupData networkSetupData;
SetupSharedNetwork::getDefaultServerSetupData(networkSetupData);
SetupSharedNetwork::install(networkSetupData);
data = new ConfigTaskManager::Data;
KEY_BOOL (autoStart, true);
KEY_STRING (clusterName, "devcluster");
KEY_BOOL (verifyClusterName, false);
KEY_INT (gameServerTimeout, 600);
KEY_STRING (gameServiceBindInterface, "");
KEY_INT (gameServicePort, 60001);
KEY_INT (consoleConnectionPort, 60000);
KEY_STRING (consoleServiceBindInterface, "");
KEY_STRING (loginServerAddress, "swo-dev5.station.sony.com");
KEY_INT (loginServerTaskServicePort, 44459);
KEY_FLOAT (maximumLoad, 3.0f);
KEY_FLOAT (loadConnectionServer, 0.5f);
KEY_FLOAT (loadPlanetServer, 0.128f);
KEY_FLOAT (loadGameServer, 1.0f);
KEY_BOOL (publishMode, false);
KEY_STRING (rcFileName, "taskmanager.rc");
KEY_BOOL (restartCentral, false);
KEY_INT (restartDelayCentralServer, 60); // seconds
KEY_INT (restartDelayLogServer, 30);
KEY_INT (restartDelayMetricsServer, 60);
KEY_INT (restartDelayCommoditiesServer, 60);
KEY_INT (restartDelayTransferServer, 30);
KEY_STRING (taskManagerServiceBindInterface, "");
KEY_INT (taskManagerServicePort, 50001);
KEY_INT (maximumClockDriftToleranceSeconds, 10); // seconds
KEY_INT (systemTimeCheckIntervalSeconds, 60); // seconds
KEY_INT (clockDriftFatalIntervalSeconds, 1*60*60); // seconds
int index = 0;
char const * result = 0;
do
{
result = ConfigFile::getKeyString("TaskManager", "environmentVariable", index++, 0);
if (result != 0)
{
ms_environmentVariable.push_back(result);
}
}
while (result);
}
//-----------------------------------------------------------------------
void ConfigTaskManager::remove(void)
{
delete data;
data = 0;
}
//-----------------------------------------------------------------------
@@ -0,0 +1,273 @@
// ConfigTaskManager.h
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _ConfigTaskManager_H
#define _ConfigTaskManager_H
//-----------------------------------------------------------------------
class ConfigTaskManager
{
public:
struct Data
{
bool autoStart;
const char * clusterName;
bool verifyClusterName;
int consoleConnectionPort;
const char * consoleServiceBindInterface;
unsigned long gameServerTimeout;
const char * gameServiceBindInterface;
int gameServicePort;
const char * loginServerAddress;
int loginServerTaskServicePort;
float maximumLoad;
float loadConnectionServer;
float loadPlanetServer;
float loadGameServer;
bool publishMode;
const char * rcFileName;
bool restartCentral;
int restartDelayCentralServer;
int restartDelayLogServer;
int restartDelayMetricsServer;
int restartDelayCommoditiesServer;
int restartDelayTransferServer;
int taskManagerServicePort;
const char * taskManagerServiceBindInterface;
int maximumClockDriftToleranceSeconds;
int systemTimeCheckIntervalSeconds;
int clockDriftFatalIntervalSeconds;
};
static const bool getAutoStart ();
static const char * getClusterName ();
static const bool getVerifyClusterName ();
static const uint16 getConsoleConnectionPort ();
static const char * getConsoleServiceBindInterface ();
static const char * getLoginServerAddress ();
static const uint16 getLoginServerTaskServicePort ();
static const bool getPublishMode();
static const char * getRcFileName ();
static bool getRestartCentral();
static unsigned int getRestartDelayCentralServer ();
static unsigned int getRestartDelayLogServer ();
static unsigned int getRestartDelayMetricsServer ();
static unsigned int getRestartDelayCommoditiesServer ();
static unsigned int getRestartDelayTransferServer ();
static unsigned long getGameServerTimeout ();
static const char * getGameServiceBindInterface ();
static uint16 getGameServicePort();
static float getMaximumLoad ();
static float getLoadConnectionServer ();
static float getLoadPlanetServer ();
static float getLoadGameServer ();
static uint16 getTaskManagerServicePort();
static const char * getTaskManagerServiceBindInterface();
static int getMaximumClockDriftToleranceSeconds();
static int getSystemTimeCheckIntervalSeconds();
static int getClockDriftFatalIntervalSeconds();
static void install ();
static void remove ();
static int getNumberOfEnvironmentVariables();
static char const * getEnvironmentVariable(int index);
private:
static Data * data;
};
//-----------------------------------------------------------------------
inline const bool ConfigTaskManager::getAutoStart()
{
return data->autoStart;
}
//-----------------------------------------------------------------------
inline const char * ConfigTaskManager::getClusterName()
{
return data->clusterName;
}
//-----------------------------------------------------------------------
inline const bool ConfigTaskManager::getVerifyClusterName()
{
return data->verifyClusterName;
}
//-----------------------------------------------------------------------
inline const uint16 ConfigTaskManager::getConsoleConnectionPort()
{
return static_cast<uint16>(data->consoleConnectionPort);
}
//-----------------------------------------------------------------------
inline uint16 ConfigTaskManager::getGameServicePort()
{
return static_cast<uint16>(data->gameServicePort);
}
//-----------------------------------------------------------------------
inline uint16 ConfigTaskManager::getTaskManagerServicePort()
{
return static_cast<uint16>(data->taskManagerServicePort);
}
//-----------------------------------------------------------------------
inline const char * ConfigTaskManager::getLoginServerAddress()
{
return data->loginServerAddress;
}
//-----------------------------------------------------------------------
inline const uint16 ConfigTaskManager::getLoginServerTaskServicePort()
{
return static_cast<uint16>(data->loginServerTaskServicePort);
}
//-----------------------------------------------------------------------
inline const char * ConfigTaskManager::getRcFileName()
{
return data->rcFileName;
}
//-----------------------------------------------------------------------
inline const char * ConfigTaskManager::getConsoleServiceBindInterface()
{
return data->consoleServiceBindInterface;
}
//-----------------------------------------------------------------------
inline const char * ConfigTaskManager::getGameServiceBindInterface()
{
return data->gameServiceBindInterface;
}
//-----------------------------------------------------------------------
inline const char * ConfigTaskManager::getTaskManagerServiceBindInterface()
{
return data->taskManagerServiceBindInterface;
}
//-----------------------------------------------------------------------
inline const bool ConfigTaskManager::getPublishMode()
{
return data->publishMode;
}
//-----------------------------------------------------------------------
inline float ConfigTaskManager::getMaximumLoad()
{
return data->maximumLoad;
}
//-----------------------------------------------------------------------
inline float ConfigTaskManager::getLoadConnectionServer()
{
return data->loadConnectionServer;
}
//-----------------------------------------------------------------------
inline float ConfigTaskManager::getLoadPlanetServer()
{
return data->loadPlanetServer;
}
//-----------------------------------------------------------------------
inline float ConfigTaskManager::getLoadGameServer()
{
return data->loadGameServer;
}
// ----------------------------------------------------------------------
inline unsigned long ConfigTaskManager::getGameServerTimeout()
{
return data->gameServerTimeout;
}
// ----------------------------------------------------------------------
inline bool ConfigTaskManager::getRestartCentral()
{
return data->restartCentral;
}
// ----------------------------------------------------------------------
inline unsigned int ConfigTaskManager::getRestartDelayCentralServer()
{
return static_cast<unsigned int>(data->restartDelayCentralServer);
}
// ----------------------------------------------------------------------
inline unsigned int ConfigTaskManager::getRestartDelayLogServer()
{
return static_cast<unsigned int>(data->restartDelayLogServer);
}
// ----------------------------------------------------------------------
inline unsigned int ConfigTaskManager::getRestartDelayMetricsServer()
{
return static_cast<unsigned int>(data->restartDelayMetricsServer);
}
// ----------------------------------------------------------------------
inline unsigned int ConfigTaskManager::getRestartDelayCommoditiesServer()
{
return static_cast<unsigned int>(data->restartDelayCommoditiesServer);
}
// ----------------------------------------------------------------------
inline unsigned int ConfigTaskManager::getRestartDelayTransferServer()
{
return static_cast<unsigned int>(data->restartDelayTransferServer);
}
// ----------------------------------------------------------------------
inline int ConfigTaskManager::getMaximumClockDriftToleranceSeconds()
{
return data->maximumClockDriftToleranceSeconds;
}
// ----------------------------------------------------------------------
inline int ConfigTaskManager::getSystemTimeCheckIntervalSeconds()
{
return data->systemTimeCheckIntervalSeconds;
}
// ----------------------------------------------------------------------
inline int ConfigTaskManager::getClockDriftFatalIntervalSeconds()
{
return data->clockDriftFatalIntervalSeconds;
}
// ----------------------------------------------------------------------
#endif // _ConfigTaskManager_H
@@ -0,0 +1,73 @@
// Console.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTaskManager.h"
#include "ConfigTaskManager.h"
#include "Console.h"
#include "ConsoleImplementation.h"
#include <cstdio>
//-----------------------------------------------------------------------
Console::Console() :
consoleImplementation(new ConsoleImplementation)
{
}
//-----------------------------------------------------------------------
Console::~Console()
{
delete consoleImplementation;
}
//-----------------------------------------------------------------------
Console & Console::instance()
{
static Console console;
return console;
}
//-----------------------------------------------------------------------
const std::string Console::getNextCommand()
{
return instance().consoleImplementation->popNextCommand();
}
//-----------------------------------------------------------------------
const bool Console::hasPendingCommand()
{
return instance().consoleImplementation->hasPendingCommand();
}
//-----------------------------------------------------------------------
void Console::update()
{
if(ConfigTaskManager::getAutoStart())
return;
static Console & con = instance();
char ch = 0;
while((ch = con.getNextChar()) != 0)
{
if(ch == 10 || ch == 13)
{
con.consoleImplementation->pushCommand(con.currentCommand);
con.currentCommand.clear();
}
else
{
con.currentCommand += ch;
}
}
}
//-----------------------------------------------------------------------
@@ -0,0 +1,41 @@
// Console.h
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_Console_H
#define _INCLUDED_Console_H
//-----------------------------------------------------------------------
#include <string>
//-----------------------------------------------------------------------
class ConsoleImplementation;
//-----------------------------------------------------------------------
class Console
{
public:
~Console();
static const bool hasPendingCommand ();
static const std::string getNextCommand ();
static void update ();
private:
Console();
Console & operator = (const Console & rhs);
Console(const Console & source);
static Console & instance();
const char getNextChar();
private:
ConsoleImplementation * consoleImplementation;
std::string currentCommand;
};
//-----------------------------------------------------------------------
#endif // _INCLUDED_Console_H
@@ -0,0 +1,60 @@
// ConsoleConnection.cpp
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTaskManager.h"
#include "Archive/ByteStream.h"
#include "ConsoleConnection.h"
#include "sharedNetworkMessages/ConsoleChannelMessages.h"
#include "TaskManager.h"
//-----------------------------------------------------------------------
ConsoleConnection::ConsoleConnection(UdpConnectionMT * udpConnection, TcpClient * t) :
ServerConnection(udpConnection, t)
{
}
//-----------------------------------------------------------------------
ConsoleConnection::~ConsoleConnection()
{
}
//-----------------------------------------------------------------------
void ConsoleConnection::onReceive(const Archive::ByteStream & message)
{
static Archive::ReadIterator ri;
ri = message.begin();
GameNetworkMessage msg(ri);
if(msg.isType("ConGenericMessage"))
{
ri = message.begin();
ConGenericMessage taskConsoleCommand(ri);
static std::string command;
command = taskConsoleCommand.getMsg();
while(command.rfind(' ') != command.npos || command.rfind('\n') != command.npos || command.rfind('\r') != command.npos)
command = command.substr(0, command.length() - 1);
ConGenericMessage response(TaskManager::executeCommand(command), taskConsoleCommand.getMsgId());
send(response, true);
GameNetworkMessage dis("RequestDisconnect");
send(dis, true);
REPORT_LOG(true, ("Received remote console command from %s : [%s]\n", getRemoteAddress().c_str(), command.c_str()));
}
else
{
// someone is sending the wrong data!
disconnect();
}
}
//-----------------------------------------------------------------------
@@ -0,0 +1,30 @@
// ConsoleConnection.h
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_ConsoleConnection_H
#define _INCLUDED_ConsoleConnection_H
//-----------------------------------------------------------------------
#include "serverUtility/ServerConnection.h"
//-----------------------------------------------------------------------
class ConsoleConnection : public ServerConnection
{
public:
ConsoleConnection(UdpConnectionMT * udpConnection, TcpClient *);
~ConsoleConnection();
virtual void onReceive (const Archive::ByteStream & message);
private:
ConsoleConnection & operator = (const ConsoleConnection & rhs);
ConsoleConnection(const ConsoleConnection & source);
};
//-----------------------------------------------------------------------
#endif // _INCLUDED_ConsoleConnection_H
@@ -0,0 +1,50 @@
// ConsoleImplementation.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTaskManager.h"
#include "ConsoleImplementation.h"
//-----------------------------------------------------------------------
ConsoleImplementation::ConsoleImplementation()
{
}
//-----------------------------------------------------------------------
ConsoleImplementation::~ConsoleImplementation()
{
}
//-----------------------------------------------------------------------
const bool ConsoleImplementation::hasPendingCommand() const
{
return (!m_pendingCommands.empty());
}
//-----------------------------------------------------------------------
const std::string ConsoleImplementation::popNextCommand()
{
std::string result;
if(hasPendingCommand())
{
result = m_pendingCommands.front();
m_pendingCommands.pop_front();
}
return result;
}
//-----------------------------------------------------------------------
void ConsoleImplementation::pushCommand(const std::string & newCommand)
{
m_pendingCommands.push_back(newCommand);
}
//-----------------------------------------------------------------------
@@ -0,0 +1,34 @@
// ConsoleImplementation.h
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_ConsoleImplementation_H
#define _INCLUDED_ConsoleImplementation_H
//-----------------------------------------------------------------------
#include <list>
#include <string>
//-----------------------------------------------------------------------
class ConsoleImplementation
{
public:
ConsoleImplementation();
~ConsoleImplementation();
const bool hasPendingCommand () const;
const std::string popNextCommand ();
void pushCommand (const std::string & newCommand);
private:
ConsoleImplementation & operator = (const ConsoleImplementation & rhs);
ConsoleImplementation(const ConsoleImplementation & source);
private:
std::list<std::string> m_pendingCommands;
};
//-----------------------------------------------------------------------
#endif // _INCLUDED_ConsoleImplementation_H
@@ -0,0 +1,60 @@
// DatabaseConnection.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTaskManager.h"
#include "DatabaseConnection.h"
#include "TaskManager.h"
#include "serverNetworkMessages/GameTaskManagerMessages.h"
#include "serverNetworkMessages/TaskSpawnProcess.h"
//-----------------------------------------------------------------------
DatabaseConnection::DatabaseConnection() :
TaskHandler()
{
// TaskManager::startServer("PlanetServer", "");
// TaskManager::startServer("SwgGameServer", "");
}
//-----------------------------------------------------------------------
DatabaseConnection::~DatabaseConnection()
{
}
//-----------------------------------------------------------------------
DatabaseConnection & DatabaseConnection::operator = (const DatabaseConnection & rhs)
{
if(this != &rhs)
{
// make assignments if right hand side is not this instance
}
return *this;
}
//-----------------------------------------------------------------------
void DatabaseConnection::receive(const Archive::ByteStream & message)
{
Archive::ReadIterator r(message);
GameNetworkMessage m(r);
r = message.begin();
if(m.isType("TaskSpawnProcess"))
{
TaskSpawnProcess s(r);
IGNORE_RETURN(TaskManager::startServer(s.getProcessName(), s.getOptions(), s.getTargetHostAddress(), s.getSpawnDelay()));
}
else if(m.isType("ServerIdleMessage"))
{
ServerIdleMessage msg(r);
TaskManager::onDatabaseIdle(msg.getIsIdle());
}
}
//-----------------------------------------------------------------------
@@ -0,0 +1,28 @@
// DatabaseConnection.h
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_DatabaseConnection_H
#define _INCLUDED_DatabaseConnection_H
//-----------------------------------------------------------------------
#include "TaskHandler.h"
//-----------------------------------------------------------------------
class DatabaseConnection : public TaskHandler
{
public:
DatabaseConnection();
~DatabaseConnection();
void receive(const Archive::ByteStream & message);
private:
DatabaseConnection & operator = (const DatabaseConnection & rhs);
DatabaseConnection(const DatabaseConnection & source);
};
//-----------------------------------------------------------------------
#endif // _INCLUDED_DatabaseConnection_H
@@ -0,0 +1,10 @@
namespace EnvironmentVariable
{
//This function takes a string in the form key=value. It will add
//value to the environment variable key if key exists. Otherwise it
//will create a new env called key and set it to value.
bool addToEnvironmentVariable(const char* key, const char* value);
bool setEnvironmentVariable(const char* key, const char* value);
};
@@ -0,0 +1,12 @@
// FirstTaskManager.cpp
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTaskManager.h"
void FirstTaskManagerFoo(){} //lint !e714 // enable #pragma warning disable
//-----------------------------------------------------------------------
@@ -0,0 +1,18 @@
// FirstTaskManager.h
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_FirstTaskManager_H
#define _INCLUDED_FirstTaskManager_H
//-----------------------------------------------------------------------
#pragma warning ( disable : 4786 )
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedFoundationTypes/FoundationTypes.h"
#include <string>
#include <map>
//-----------------------------------------------------------------------
#endif // _INCLUDED_FirstTaskManager_H
@@ -0,0 +1,175 @@
// GameConnection.cpp
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTaskManager.h"
#include "GameConnection.h"
#include "ConfigTaskManager.h"
#include "Archive/Archive.h"
#include "TaskManager.h"
#include "sharedFoundation/Clock.h"
#include "sharedLog/Log.h"
#include "sharedNetwork/NetworkHandler.h"
#include "sharedNetworkMessages/GenericValueTypeMessage.h"
#include "ProcessSpawner.h"
//-----------------------------------------------------------------------
namespace GameConnectionNamespace
{
std::vector<GameConnection *> s_gameConnections;
}
using namespace GameConnectionNamespace;
//-----------------------------------------------------------------------
GameConnection::GameConnection(TaskConnection * c) :
TaskHandler(),
connection(c),
m_lastKeepalive(0),
m_pid(0),
m_commandLine(),
m_timeLastKilled(0),
m_loggedKill(false),
m_loggedKillForceCore(false)
{
TaskManager::addToGameConnections(1);
s_gameConnections.push_back(this);
}
//-----------------------------------------------------------------------
GameConnection::~GameConnection()
{
std::vector<GameConnection *>::iterator f = std::find(s_gameConnections.begin(), s_gameConnections.end(), this);
if(f != s_gameConnections.end())
s_gameConnections.erase(f);
connection = 0;
TaskManager::addToGameConnections(-1);
}
//-----------------------------------------------------------------------
void GameConnection::install()
{
}
//-----------------------------------------------------------------------
void GameConnection::remove()
{
s_gameConnections.clear();
}
//-----------------------------------------------------------------------
void GameConnection::receive(const Archive::ByteStream & message)
{
Archive::ReadIterator r(message);
GameNetworkMessage m(r);
r = message.begin();
if(m.isType("GameServerTaskManagerKeepAlive"))
{
if(! m_pid)
{
GenericValueTypeMessage<unsigned long> msg(r);
m_pid = msg.getValue();
#ifndef _WIN32
// get the command line
if (m_pid && m_commandLine.empty())
{
char filename[30];
snprintf(filename, sizeof(filename)-1, "/proc/%lu/cmdline", m_pid);
// format of the cmdline file is a NULL separates every
// parameter, so we'll have to replace the NULLs with spaces
FILE *inFile = fopen(filename,"rb");
if (inFile)
{
char buffer[512];
int bytesRead = fread(buffer, 1, sizeof(buffer)-1, inFile);
if ((bytesRead > 0) && (bytesRead < static_cast<int>(sizeof(buffer))))
{
buffer[bytesRead] = '\0';
for (int i = 0; i < bytesRead; ++i)
{
if (buffer[i] == '\0')
{
buffer[i] = ' ';
}
}
m_commandLine = buffer;
}
fclose(inFile);
}
}
#endif
}
m_lastKeepalive = Clock::timeSeconds();
}
}
//-----------------------------------------------------------------------
void GameConnection::update()
{
std::vector<GameConnection *>::iterator i;
std::vector<GameConnection *> v = s_gameConnections;
const unsigned long currentTime = Clock::timeSeconds();
const unsigned long gameServerTimeout = ConfigTaskManager::getGameServerTimeout();
if (gameServerTimeout > 0)
{
for (i = v.begin(); i != v.end(); ++i)
{
GameConnection * g = (*i);
if (g->m_lastKeepalive && g->m_pid && ((g->m_lastKeepalive + gameServerTimeout) < currentTime))
{
// attempt ProcessSpawner::forceCore() once per minute and if that doesn't
// work after a period of gameServerTimeout, then do a ProcessSpawner::kill()
if ((currentTime - g->m_lastKeepalive) > (2 * gameServerTimeout))
{
g->m_timeLastKilled = currentTime;
LOG("ServerHang", ("killing (kill) GameServer %s,%d (%s) because it has not provided a keepalive message in %d seconds", NetworkHandler::getHumanReadableHostName().c_str(), g->m_pid, g->m_commandLine.c_str(), currentTime - g->m_lastKeepalive));
WARNING(true, ("killing (kill) GameServer %s,%d (%s) because it has not provided a keepalive message in %d seconds", NetworkHandler::getHumanReadableHostName().c_str(), g->m_pid, g->m_commandLine.c_str(), currentTime - g->m_lastKeepalive));
// one time logging to customer service channel
if (!g->m_loggedKill)
{
g->m_loggedKill = true;
LOG("TaskManager", ("ServerHang: killing (kill) GameServer %s,%d (%s) because it has not provided a keepalive message in %d seconds", NetworkHandler::getHumanReadableHostName().c_str(), g->m_pid, g->m_commandLine.c_str(), currentTime - g->m_lastKeepalive));
}
ProcessSpawner::kill(g->m_pid);
}
else if ((g->m_timeLastKilled == 0) || ((currentTime - g->m_timeLastKilled) >= 60))
{
g->m_timeLastKilled = currentTime;
LOG("ServerHang", ("killing (forceCore) GameServer %s,%d (%s) because it has not provided a keepalive message in %d seconds", NetworkHandler::getHumanReadableHostName().c_str(), g->m_pid, g->m_commandLine.c_str(), currentTime - g->m_lastKeepalive));
WARNING(true, ("killing (forceCore) GameServer %s,%d (%s) because it has not provided a keepalive message in %d seconds", NetworkHandler::getHumanReadableHostName().c_str(), g->m_pid, g->m_commandLine.c_str(), currentTime - g->m_lastKeepalive));
// one time logging to customer service channel
if (!g->m_loggedKillForceCore)
{
g->m_loggedKillForceCore = true;
LOG("TaskManager", ("ServerHang: killing (forceCore) GameServer %s,%d (%s) because it has not provided a keepalive message in %d seconds", NetworkHandler::getHumanReadableHostName().c_str(), g->m_pid, g->m_commandLine.c_str(), currentTime - g->m_lastKeepalive));
}
ProcessSpawner::forceCore(g->m_pid);
}
}
}
}
}
//-----------------------------------------------------------------------
@@ -0,0 +1,43 @@
// GameConnection.h
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_GameConnection_H
#define _INCLUDED_GameConnection_H
//-----------------------------------------------------------------------
#include "TaskHandler.h"
#include <string>
class TaskConnection;
//-----------------------------------------------------------------------
class GameConnection : public TaskHandler
{
public:
explicit GameConnection(TaskConnection * connection);
~GameConnection();
static void install();
void receive(const Archive::ByteStream & message);
static void remove();
static void update();
private:
GameConnection & operator = (const GameConnection & rhs);
GameConnection(const GameConnection & source);
TaskConnection * connection;
unsigned long m_lastKeepalive;
unsigned long m_pid;
std::string m_commandLine;
unsigned long m_timeLastKilled;
bool m_loggedKill;
bool m_loggedKillForceCore;
}; //lint !e1712
//-----------------------------------------------------------------------
#endif // _INCLUDED_GameConnection_H
@@ -0,0 +1,445 @@
// ======================================================================
//
// Locator.cpp
//
// Copyright 2000-04 Sony Online Entertainment
//
// ======================================================================
#include "FirstTaskManager.h"
#include "Locator.h"
#include "ConfigTaskManager.h"
#include "ManagerConnection.h"
#include "TaskManager.h"
#include "serverNetworkMessages/TaskUtilization.h"
#include "sharedFoundation/ConfigFile.h"
#include "sharedLog/Log.h"
#include <algorithm>
#include <vector>
// ======================================================================
namespace LocatorNamespace
{
float getConfigSetting(const char *section, const char *key, const float defaultValue)
{
const ConfigFile::Section * sec = ConfigFile::getSection(section);
if (sec == NULL)
return defaultValue;
const ConfigFile::Key * ky = sec->findKey(key);
if (ky == NULL)
return defaultValue;
return ky->getAsFloat(ky->getCount()-1, defaultValue);
}
struct PreferredNode
{
std::string m_nodeLabel;
std::string m_processName;
std::vector<std::string> m_nodeOptions;
bool match(std::string const &processName, std::string const &options) const
{
if (m_processName != processName)
return false;
for (std::vector<std::string>::const_iterator i = m_nodeOptions.begin(); i != m_nodeOptions.end(); ++i)
if (options.find(*i) == std::string::npos)
return false;
return true;
}
};
struct ServerEntry
{
ServerEntry(ManagerConnection *conn, std::string const &label, float load);
bool operator==(std::string const &label) const
{
return m_label == label;
}
bool operator<(ServerEntry const & rhs) const
{
// don't change this; the code requires that the nodes
// list be ordered by the current load on the node
return m_load < rhs.m_load;
}
bool hasAvailableLoad(float cost) const
{
return ((m_load + cost) < m_maximumLoad);
}
ManagerConnection *m_connection;
std::string m_label;
float m_load;
float m_maximumLoad;
};
ServerEntry::ServerEntry(ManagerConnection *conn, std::string const &label, float load) :
m_connection(conn),
m_label(label),
m_load(load),
m_maximumLoad(0.0f)
{
// see if there is a maximum load specified for this particular node
char key[128];
snprintf(key, sizeof(key)-1, "maximumLoad.%s", m_label.c_str());
key[sizeof(key)-1] = '\0';
m_maximumLoad = getConfigSetting("TaskManager", key, ConfigTaskManager::getMaximumLoad());
}
std::vector<ServerEntry> s_serverList;
const char s_masterNodeLabel[] = "node0";
float s_myLoad;
std::vector<PreferredNode> s_preferredNodes;
std::map<std::string, std::string> s_closedConnections; // to keep track of TaskManager that we have lost connection to which has not yet reconnected
ManagerConnection *getPreferredServer(std::string const &processName, std::string const &options, float cost);
ManagerConnection *getUnpreferredServer(float cost);
void addPreferredNode(std::string const &preferredNodeSpec);
}
using namespace LocatorNamespace;
// ======================================================================
void Locator::install()
{
int index = 0;
char const * result = 0;
do
{
result = ConfigFile::getKeyString("TaskManager", "preferredNode", index++, 0);
if (result)
addPreferredNode(result);
}
while (result);
}
// ----------------------------------------------------------------------
void Locator::closed(std::string const &label, ManagerConnection const *oldConnection)
{
if (oldConnection)
{
std::vector<ServerEntry>::iterator i = std::find(s_serverList.begin(), s_serverList.end(), label);
if (i != s_serverList.end())
{
DEBUG_REPORT_LOG(true, ("Removing connection %s on %s from locator map\n", label.c_str(), oldConnection->getRemoteAddress().c_str()));
IGNORE_RETURN(s_serverList.erase(i));
s_closedConnections[label] = oldConnection->getRemoteAddress();
}
}
}
// ----------------------------------------------------------------------
ManagerConnection *LocatorNamespace::getPreferredServer(std::string const &processName, std::string const &options, float cost)
{
// Find a node other than the master node that can afford to run the process
// and is a preferred node for the process and option set.
for (std::vector<ServerEntry>::iterator i = s_serverList.begin(); i != s_serverList.end(); ++i)
{
ServerEntry &e = *i;
if ((e.m_label != s_masterNodeLabel) && (e.hasAvailableLoad(cost)))
{
for (std::vector<PreferredNode>::const_iterator j = s_preferredNodes.begin(); j != s_preferredNodes.end(); ++j)
if ((*j).m_nodeLabel == e.m_label && (*j).match(processName, options))
return e.m_connection;
}
}
return 0;
}
// ----------------------------------------------------------------------
ManagerConnection *LocatorNamespace::getUnpreferredServer(float cost)
{
// Find a node other than the master node that can afford to run the process
// and is a not marked as a preferred node for anything; if more than one
// node qualifies, return the node with the lowest load
for (std::vector<ServerEntry>::iterator i = s_serverList.begin(); i != s_serverList.end(); ++i)
{
ServerEntry &e = *i;
if ((e.m_label != s_masterNodeLabel) && (e.hasAvailableLoad(cost)))
{
bool foundPreferred = false;
for (std::vector<PreferredNode>::const_iterator j = s_preferredNodes.begin(); j != s_preferredNodes.end(); ++j)
{
if ((*j).m_nodeLabel == e.m_label)
{
foundPreferred = true;
break;
}
}
// s_serverList is ordered by load, so this will
// return the available node with the lowest load
if (!foundPreferred)
return e.m_connection;
}
}
return 0;
}
// ----------------------------------------------------------------------
ManagerConnection *Locator::getBestServer(std::string const &processName, std::string const &options, float cost)
{
if (s_serverList.empty())
return 0;
// first, look for a preferred node for this process
{
ManagerConnection * const connection = getPreferredServer(processName, options, cost);
if (connection)
return connection;
}
// there is not a preferred node available, so look for a node which is not preferred in some form
{
ManagerConnection * const connection = getUnpreferredServer(cost);
if (connection)
return connection;
}
// there is not a non-preferred node available, so look for any node other than the command node;
// If more than one node qualifies, we want to choose the one who currently has the lowest load
{
for (std::vector<ServerEntry>::iterator i = s_serverList.begin(); i != s_serverList.end(); ++i)
{
ServerEntry &e = *i;
if ((e.m_label != s_masterNodeLabel) && (e.hasAvailableLoad(cost)))
{
// s_serverList is ordered by load, so this will
// return the available node with the lowest load
return e.m_connection;
}
}
WARNING(true, ("No hosts are available to spawn a process costing %f without exceeding the host's load limit", cost));
}
return 0;
}
// ----------------------------------------------------------------------
ManagerConnection *Locator::getServer(std::string const &label)
{
for (std::vector<ServerEntry>::const_iterator i = s_serverList.begin(); i != s_serverList.end(); ++i)
if (i->m_label == label || i->m_connection->getRemoteAddress() == label)
return i->m_connection;
return 0;
}
// ----------------------------------------------------------------------
float Locator::getServerLoad(std::string const &label)
{
std::vector<ServerEntry>::const_iterator i = std::find(s_serverList.begin(), s_serverList.end(), label);
if (i != s_serverList.end())
return i->m_load;
return 0.f;
}
// ----------------------------------------------------------------------
float Locator::getServerMaximumLoad(std::string const &label)
{
std::vector<ServerEntry>::const_iterator i = std::find(s_serverList.begin(), s_serverList.end(), label);
if (i != s_serverList.end())
return i->m_maximumLoad;
// see if there is a maximum load specified for this particular node
char key[128];
snprintf(key, sizeof(key)-1, "maximumLoad.%s", label.c_str());
key[sizeof(key)-1] = '\0';
return getConfigSetting("TaskManager", key, ConfigTaskManager::getMaximumLoad());
}
// ----------------------------------------------------------------------
void Locator::incrementMyLoad(float amount)
{
s_myLoad += amount;
std::sort(s_serverList.begin(), s_serverList.end());
}
// ----------------------------------------------------------------------
void Locator::decrementMyLoad(float amount)
{
s_myLoad -= amount;
if (s_myLoad < 0.0f)
s_myLoad = 0.0f;
std::sort(s_serverList.begin(), s_serverList.end());
updateAllLoads(-amount);
}
// ----------------------------------------------------------------------
void Locator::incrementServerLoad(std::string const &label, float amount)
{
std::vector<ServerEntry>::iterator i = std::find(s_serverList.begin(), s_serverList.end(), label);
if (i != s_serverList.end())
{
i->m_load += amount;
std::sort(s_serverList.begin(), s_serverList.end());
}
}
// ----------------------------------------------------------------------
void Locator::decrementServerLoad(std::string const &label, float amount)
{
std::vector<ServerEntry>::iterator i = std::find(s_serverList.begin(), s_serverList.end(), label);
if (i != s_serverList.end())
{
i->m_load -= amount;
if (i->m_load < 0.0f)
{
DEBUG_WARNING(true, ("%s dropped less than 0", label.c_str()));
i->m_load = 0.0f;
}
std::sort(s_serverList.begin(), s_serverList.end());
}
}
// ----------------------------------------------------------------------
float Locator::getMyLoad()
{
return s_myLoad;
}
// ----------------------------------------------------------------------
float Locator::getMyMaximumLoad()
{
static float myMaximumLoad = -1.0f;
// get the maximum load for this particular node
if (myMaximumLoad <= 0.0f)
{
// see if there is a maximum load specified for this particular node
char key[128];
snprintf(key, sizeof(key)-1, "maximumLoad.%s", TaskManager::getNodeLabel().c_str());
key[sizeof(key)-1] = '\0';
myMaximumLoad = getConfigSetting("TaskManager", key, ConfigTaskManager::getMaximumLoad());
}
return myMaximumLoad;
}
// ----------------------------------------------------------------------
void Locator::opened(std::string const &label, ManagerConnection *newConnection)
{
if (newConnection)
{
std::vector<ServerEntry>::const_iterator i = std::find(s_serverList.begin(), s_serverList.end(), label);
if (i == s_serverList.end())
{
ServerEntry s(newConnection, label, 0.0f);
s_serverList.push_back(s);
std::sort(s_serverList.begin(), s_serverList.end());
IGNORE_RETURN(s_closedConnections.erase(label));
LOG("TaskManagerConnect", ("Connection with remote task manager %s established with label %s, maximum load %f", newConnection->getRemoteAddress().c_str(), label.c_str(), s.m_maximumLoad));
}
else
{
WARNING_STRICT_FATAL(true, ("Tried to add %s on %s to server list but it already exsists", label.c_str(), newConnection->getRemoteAddress().c_str()));
}
DEBUG_REPORT_LOG(true, ("Connection with remote task manager %s established with label %s\n", newConnection->getRemoteAddress().c_str(), label.c_str()));
TaskManager::runSpawnRequestQueue();
}
else
WARNING_STRICT_FATAL(true, ("Passed null connection to Locator::opened"));
}
// ----------------------------------------------------------------------
void Locator::updateServerLoad(std::string const &label, float load)
{
std::vector<ServerEntry>::iterator i = std::find(s_serverList.begin(), s_serverList.end(), label);
if(i != s_serverList.end())
{
i->m_load += load;
std::sort(s_serverList.begin(), s_serverList.end());
LOG("TaskManager", ("updateServerLoad(%s, %f)", label.c_str(), load));
}
else
{
DEBUG_WARNING(true, ("Told to update load on %s which didn't exist\n", label.c_str()));
}
TaskManager::runSpawnRequestQueue();
}
// ----------------------------------------------------------------------
void Locator::updateAllLoads(float delta)
{
if (!s_serverList.empty())
{
TaskUtilization const util(TaskUtilization::SYSTEM_AVG, delta);
sendToAllTaskManagers(util);
}
}
// ----------------------------------------------------------------------
std::map<std::string, std::string> const & Locator::getClosedConnections()
{
return s_closedConnections;
}
// ----------------------------------------------------------------------
void Locator::sendToAllTaskManagers(GameNetworkMessage const &msg)
{
if (!s_serverList.empty())
for (std::vector<ServerEntry>::const_iterator i = s_serverList.begin(); i != s_serverList.end(); ++i)
i->m_connection->send(msg);
}
// ----------------------------------------------------------------------
void LocatorNamespace::addPreferredNode(std::string const &preferredNodeSpec)
{
// preferredNodeSpec is "nodeLabel:processName:option=value:option=value:..."
PreferredNode n;
std::string::size_type lastPos = 0;
std::string::size_type pos;
pos = preferredNodeSpec.find(':', lastPos);
n.m_nodeLabel = preferredNodeSpec.substr(lastPos, pos-lastPos);
lastPos = pos == std::string::npos ? preferredNodeSpec.size() : pos+1;
pos = preferredNodeSpec.find(':', lastPos);
n.m_processName = preferredNodeSpec.substr(lastPos, pos-lastPos);
lastPos = pos == std::string::npos ? preferredNodeSpec.size() : pos+1;
while (lastPos != std::string::npos)
{
pos = preferredNodeSpec.find(':', lastPos);
n.m_nodeOptions.push_back(preferredNodeSpec.substr(lastPos, pos-lastPos));
lastPos = pos == std::string::npos ? std::string::npos : pos+1;
}
if (!n.m_nodeLabel.empty() && !n.m_processName.empty())
s_preferredNodes.push_back(n);
}
// ======================================================================
@@ -0,0 +1,46 @@
// ======================================================================
//
// Locator.h
//
// Copyright 2000-04 Sony Online Entertainment
//
// ======================================================================
#ifndef _INCLUDED_Locator_H
#define _INCLUDED_Locator_H
// ======================================================================
#include <string>
class GameNetworkMessage;
class ManagerConnection;
// ======================================================================
class Locator
{
public:
static void install();
static void closed(std::string const &label, ManagerConnection const *oldConnection);
static ManagerConnection *getBestServer(std::string const &processName, std::string const &options, float cost);
static float getMyLoad();
static float getMyMaximumLoad();
static float getServerLoad(std::string const &label);
static float getServerMaximumLoad(std::string const &label);
static ManagerConnection *getServer(std::string const &label);
static void incrementMyLoad(float amount);
static void incrementServerLoad(std::string const &label, float amount);
static void decrementMyLoad(float amount);
static void decrementServerLoad(std::string const &label, float amount);
static void opened(std::string const &label, ManagerConnection *newConnection);
static void sendToAllTaskManagers(GameNetworkMessage const &msg);
static void updateServerLoad(std::string const &label, float load);
static void updateAllLoads(float delta);
static stdmap<std::string, std::string>::fwd const & getClosedConnections();
};
// ======================================================================
#endif // _INCLUDED_Locator_H
@@ -0,0 +1,225 @@
// ManagerConnection.cpp
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTaskManager.h"
#include "Locator.h"
#include "ManagerConnection.h"
#include "serverNetworkMessages/TaskProcessDiedMessage.h"
#include "serverNetworkMessages/TaskSpawnProcess.h"
#include "serverNetworkMessages/TaskSpawnProcessAck.h"
#include "serverNetworkMessages/TaskUtilization.h"
#include "serverNetworkMessages/TaskConnectionIdMessage.h"
#include "sharedFoundation/CalendarTime.h"
#include "sharedFoundation/Clock.h"
#include "sharedFoundation/FormattedString.h"
#include "sharedFoundation/Scheduler.h"
#include "sharedLog/Log.h"
#include "sharedMessageDispatch/Transceiver.h"
#include "sharedNetwork/NetworkSetupData.h"
#include "sharedNetworkMessages/GenericValueTypeMessage.h"
#include "ConfigTaskManager.h"
#include "TaskConnection.h"
#include "TaskManager.h"
//-----------------------------------------------------------------------
namespace ManagerConnectionNamespace
{
int s_managerConnectionCount = 0;
}
using namespace ManagerConnectionNamespace;
//-----------------------------------------------------------------------
ManagerConnection::ManagerConnection(const std::string & a, const unsigned short p) :
Connection(a,p, NetworkSetupData()),
m_nodeLabel(0),
m_remoteUtilAvg(100000.0f)
{
}
//-----------------------------------------------------------------------
ManagerConnection::ManagerConnection(UdpConnectionMT * u, TcpClient * t) :
Connection(u, t),
m_nodeLabel(0),
m_remoteUtilAvg(100000.0f)
{
}
//-----------------------------------------------------------------------
ManagerConnection::~ManagerConnection()
{
if (m_nodeLabel)
{
Locator::closed(*m_nodeLabel, this);
delete m_nodeLabel;
m_nodeLabel = 0;
}
}
//-----------------------------------------------------------------------
void ManagerConnection::onConnectionClosed()
{
DEBUG_REPORT_LOG(true, ("Manager connection %s closed\n", getRemoteAddress().c_str()));
TaskManager::retryConnection(this);
if (m_nodeLabel)
{
Locator::closed(*m_nodeLabel, this);
delete m_nodeLabel;
m_nodeLabel = 0;
}
s_managerConnectionCount--;
}
//-----------------------------------------------------------------------
void ManagerConnection::onConnectionOpened()
{
DEBUG_REPORT_LOG(true, ("Manager connection opened\n"));
TaskConnectionIdMessage id(TaskConnectionIdMessage::TaskManager, TaskManager::getNodeLabel(), ConfigTaskManager::getClusterName());
send(id);
s_managerConnectionCount++;
}
//-----------------------------------------------------------------------
void ManagerConnection::onReceive(const Archive::ByteStream & message)
{
Archive::ReadIterator r(message);
GameNetworkMessage m(r);
r = message.begin();
if (m.isType("SystemTimeCheck"))
{
long const currentTime = static_cast<long>(::time(NULL));
GenericValueTypeMessage<std::pair<std::string, long > > msg(r);
if (TaskManager::getNodeLabel() == "node0")
{
if ((std::max(currentTime, msg.getValue().second) - std::min(currentTime, msg.getValue().second)) > ConfigTaskManager::getMaximumClockDriftToleranceSeconds())
{
LOG("CustomerService", ("system_clock_mismatch:System clock mismatch (%d seconds) by more than %d seconds: master TaskManager epoch (%ld), remote TaskManager %s (%s) epoch (%ld)", (std::max(currentTime, msg.getValue().second) - std::min(currentTime, msg.getValue().second)), ConfigTaskManager::getMaximumClockDriftToleranceSeconds(), currentTime, msg.getValue().first.c_str(), getRemoteAddress().c_str(), msg.getValue().second));
// tell CentralServer about the system clock mismatch so it can report an alert to SOEMon
GenericValueTypeMessage<std::string> systemTimeMismatchMessage("SystemTimeMismatchNotification",
FormattedString<1024>().sprintf("%s: %s (%s) is off by %ld seconds", CalendarTime::convertEpochToTimeStringLocal(static_cast<time_t>(currentTime)).c_str(), msg.getValue().first.c_str(), getRemoteAddress().c_str(), (std::max(currentTime, msg.getValue().second) - std::min(currentTime, msg.getValue().second))));
TaskManager::sendToCentralServer(systemTimeMismatchMessage);
}
}
}
else if (m.isType("TaskConnectionIdMessage"))
{
static long const clockDriftFatalTimePeriod = static_cast<long>(TaskManager::getStartTime()) + ConfigTaskManager::getClockDriftFatalIntervalSeconds();
long const currentTime = static_cast<long>(::time(NULL));
TaskConnectionIdMessage t(r);
WARNING_STRICT_FATAL(t.getServerType() != TaskConnectionIdMessage::TaskManager,
("ManagerConnection received wrong type identifier"));
WARNING_STRICT_FATAL(m_nodeLabel, ("Received new taskconnectionIdMessage with an already named connection"));
FATAL((ConfigTaskManager::getVerifyClusterName() && (TaskManager::getNodeLabel() == "node0") && (t.getServerType() == TaskConnectionIdMessage::TaskManager) && (t.getClusterName() != std::string(ConfigTaskManager::getClusterName()))), ("Remote TaskManager %s (%s) reported cluster name (%s) that is different from my cluster name (%s)", t.getCommandLine().c_str(), getRemoteAddress().c_str(), t.getClusterName().c_str(), ConfigTaskManager::getClusterName()));
// don't allow cluster to start if the system clock across the boxes are out of sync
bool remoteSystemClockInSync = true;
if (TaskManager::getNodeLabel() == "node0")
{
if ((std::max(currentTime, t.getCurrentEpochTime()) - std::min(currentTime, t.getCurrentEpochTime())) > ConfigTaskManager::getMaximumClockDriftToleranceSeconds())
{
remoteSystemClockInSync = false;
// don't bring down the cluster if we lost a box and when the box is
// restarted, its system clock is out of sync; just ignore that
// TaskManager, and send it a message to terminate itself
if (currentTime <= clockDriftFatalTimePeriod)
{
FATAL(true, ("System clock mismatch (%d seconds) by more than %d seconds: master TaskManager epoch (%ld), remote TaskManager %s (%s) epoch (%ld)", (std::max(currentTime, t.getCurrentEpochTime()) - std::min(currentTime, t.getCurrentEpochTime())), ConfigTaskManager::getMaximumClockDriftToleranceSeconds(), currentTime, t.getCommandLine().c_str(), getRemoteAddress().c_str(), t.getCurrentEpochTime()));
}
else
{
LOG("CustomerService", ("system_clock_mismatch:System clock mismatch (%d seconds) by more than %d seconds: master TaskManager epoch (%ld), remote TaskManager %s (%s) epoch (%ld). Telling remote TaskManager to terminate.", (std::max(currentTime, t.getCurrentEpochTime()) - std::min(currentTime, t.getCurrentEpochTime())), ConfigTaskManager::getMaximumClockDriftToleranceSeconds(), currentTime, t.getCommandLine().c_str(), getRemoteAddress().c_str(), t.getCurrentEpochTime()));
GenericValueTypeMessage<std::pair<std::string, std::pair<long, long> > > systemTimeMismatchMessage("SystemTimeMismatchMessage", std::make_pair(TaskManager::getNodeLabel(), std::make_pair(static_cast<long>(currentTime), t.getCurrentEpochTime())));
send(systemTimeMismatchMessage);
}
}
}
if (remoteSystemClockInSync)
{
m_nodeLabel = new std::string(t.getCommandLine());
Locator::opened(*m_nodeLabel, this);
TaskManager::resendUnacknowledgedSpawnRequests(this, *m_nodeLabel);
}
}
else if (m.isType("SystemTimeMismatchMessage"))
{
GenericValueTypeMessage<std::pair<std::string, std::pair<long, long> > > msg(r);
FATAL((msg.getValue().first == "node0"), ("System clock mismatch (%d seconds) by more than %d seconds: master TaskManager epoch (%ld), self epoch (%ld)", (std::max(msg.getValue().second.first, msg.getValue().second.second) - std::min(msg.getValue().second.first, msg.getValue().second.second)), ConfigTaskManager::getMaximumClockDriftToleranceSeconds(), msg.getValue().second.first, msg.getValue().second.second));
}
else if(m.isType("TaskSpawnProcess"))
{
TaskSpawnProcess s(r);
if (TaskManager::startServer(s.getProcessName(), s.getOptions(), s.getTargetHostAddress(), s.getSpawnDelay()) == 0)
{
DEBUG_REPORT_LOG(true, ("Failed to spawn %s on this node\n", s.getProcessName().c_str()));
//send fail message back
}
else
{
TaskSpawnProcessAck ack(s.getTransactionId());
send(ack);
}
}
else if(m.isType("TaskUtilization"))
{
TaskUtilization util(r);
switch(util.getUtilType())
{
case TaskUtilization::SYSTEM_AVG:
{
if (m_nodeLabel)
{
m_remoteUtilAvg = util.getUtilAmount();
Locator::updateServerLoad(*m_nodeLabel, m_remoteUtilAvg);
}
}
break;
default:
break;
}
}
else if(m.isType("TaskProcessDiedMessage"))
{
TaskProcessDiedMessage died(r);
TaskManager::sendToCentralServer(died);
}
else if(m.isType("TaskSpawnProcessAck"))
{
TaskSpawnProcessAck ack(r);
TaskManager::removePendingSpawnProcessAck(ack.getTransactionId());
}
}
//-----------------------------------------------------------------------
void ManagerConnection::send(const GameNetworkMessage & message)
{
Archive::ByteStream b;
message.pack(b);
Connection::send(b, true);
}
//-----------------------------------------------------------------------
int ManagerConnection::getConnectionCount()
{
return s_managerConnectionCount;
}
//-----------------------------------------------------------------------
@@ -0,0 +1,51 @@
// ManagerConnection.h
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_ManagerConnection_H
#define _INCLUDED_ManagerConnection_H
//-----------------------------------------------------------------------
#include "sharedMessageDispatch/Transceiver.h"
#include "TaskHandler.h"
#include "sharedNetwork/Connection.h"
class GameNetworkMessage;
class TaskConnection;
//-----------------------------------------------------------------------
class ManagerConnection : public Connection
{
public:
ManagerConnection(const std::string & remoteAddres, const unsigned short remotePort);
ManagerConnection(UdpConnectionMT*, TcpClient *);
~ManagerConnection();
static int getConnectionCount ();
const std::string* getNodeLabel() const;
virtual void onConnectionClosed ();
virtual void onConnectionOpened ();
virtual void onReceive (const Archive::ByteStream & message);
void send(const GameNetworkMessage & message);
private:
ManagerConnection & operator = (const ManagerConnection & rhs);
ManagerConnection(const ManagerConnection & source);
ManagerConnection();
private:
std::string *m_nodeLabel;
float m_remoteUtilAvg;
};
//-----------------------------------------------------------------------
inline const std::string* ManagerConnection::getNodeLabel() const
{
return m_nodeLabel;
}
//-----------------------------------------------------------------------
#endif // _INCLUDED_ManagerConnection_H
@@ -0,0 +1,87 @@
// MetricsServerConnection.cpp
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTaskManager.h"
#include "MetricsServerConnection.h"
#include "sharedFoundation/Clock.h"
#include "sharedMessageDispatch/Transceiver.h"
#include "TaskConnection.h"
#include "TaskManager.h"
//-----------------------------------------------------------------------
MetricsServerConnection::MetricsServerConnection(TaskConnection * c, const std::string & n) :
TaskHandler(),
callback(),
commandLine(n),
connected(true),
connection(c),
lastSpawnTime(Clock::timeMs())
{
callback.connect(c->getTransceiverClosed(), *this, &MetricsServerConnection::closed); //lint !e1025 !e1703 !e1514 !e64
callback.connect(*this, &MetricsServerConnection::onProcessKilled); //lint !e1025 !e1703 !e1514 !e64 !e1058 !e118
}
//-----------------------------------------------------------------------
MetricsServerConnection::~MetricsServerConnection()
{
connection = 0;
}
//-----------------------------------------------------------------------
void MetricsServerConnection::closed(const Closed &)
{
if(connected)
{
ProcessAborted a;
a.commandLine = commandLine;
a.hostName = NetworkHandler::getHostName();
MessageDispatch::Transceiver<const ProcessAborted &> b;
b.emitMessage(a);
unsigned long t = Clock::timeMs();
if(t - lastSpawnTime > 5000) // stop spawning if it bombs immediately
{
lastSpawnTime = t;
// need to restart it!
// IGNORE_RETURN(TaskManager::startServer("MetricsServer", "", "local"));
}
else
{
// emit the killed message
ProcessKilled k;
k.commandLine = a.commandLine;
k.hostName = a.hostName;
MessageDispatch::Transceiver<const ProcessKilled &> pk;
pk.emitMessage(k);
}
connected = false;
}
}
//-----------------------------------------------------------------------
void MetricsServerConnection::onProcessKilled(const ProcessKilled & k)
{
if(k.commandLine == commandLine)
lastSpawnTime = Clock::timeMs(); // force it to stay dead
}
//-----------------------------------------------------------------------
void MetricsServerConnection::receive(const Archive::ByteStream & )
{
#if 0
Archive::ReadIterator r(message);
GameNetworkMessage m(r);
#endif
}
//-----------------------------------------------------------------------
@@ -0,0 +1,42 @@
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_MetricsServerConnection_H
#define _INCLUDED_MetricsServerConnection_H
//-----------------------------------------------------------------------
#include "sharedMessageDispatch/Transceiver.h"
#include "TaskHandler.h"
class TaskConnection;
struct Closed;
//-----------------------------------------------------------------------
class MetricsServerConnection : public TaskHandler
{
public:
MetricsServerConnection(TaskConnection * newConnection, const std::string & commandLine);
~MetricsServerConnection();
void closed(const Closed &);
void receive(const Archive::ByteStream & message);
private:
MetricsServerConnection();
MetricsServerConnection & operator = (const MetricsServerConnection & rhs);
MetricsServerConnection(const MetricsServerConnection & source);
void onProcessKilled(const struct ProcessKilled &);
private:
MessageDispatch::Callback callback;
std::string commandLine;
bool connected;
TaskConnection * connection;
unsigned long lastSpawnTime;
};
//-----------------------------------------------------------------------
#endif // _INCLUDED_MetricsServerConnection_H
@@ -0,0 +1,65 @@
// PlanetConnection.cpp
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
//-----------------------------------------------------------------------
#include "FirstTaskManager.h"
#include "PlanetConnection.h"
#include "serverNetworkMessages/TaskSpawnProcess.h"
#include "sharedMessageDispatch/Transceiver.h"
#include "TaskConnection.h"
#include "TaskManager.h"
//-----------------------------------------------------------------------
PlanetConnection::PlanetConnection(TaskConnection * c) :
TaskHandler(),
connection(c)
{
}
//-----------------------------------------------------------------------
PlanetConnection::PlanetConnection(const PlanetConnection &)
{
connection = 0;
}
//-----------------------------------------------------------------------
PlanetConnection::~PlanetConnection()
{
}
//-----------------------------------------------------------------------
PlanetConnection & PlanetConnection::operator = (const PlanetConnection & rhs)
{
if(this != &rhs)
{
// make assignments if right hand side is not this instance
}
return *this;
}
//-----------------------------------------------------------------------
void PlanetConnection::receive(const Archive::ByteStream & message)
{
static const std::string localName = NetworkHandler::getHostName();
Archive::ReadIterator r(message);
GameNetworkMessage m(r);
r = message.begin();
if(m.isType("TaskSpawnProcess"))
{
TaskSpawnProcess s(r);
TaskManager::startServer(s.getProcessName(), s.getOptions(), s.getTargetHostAddress(), s.getSpawnDelay());
}
}
//-----------------------------------------------------------------------
@@ -0,0 +1,32 @@
// PlanetConnection.h
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
#ifndef _INCLUDED_PlanetConnection_H
#define _INCLUDED_PlanetConnection_H
//-----------------------------------------------------------------------
#include "TaskHandler.h"
class TaskConnection;
//-----------------------------------------------------------------------
class PlanetConnection : public TaskHandler
{
public:
PlanetConnection(TaskConnection * connection);
~PlanetConnection();
void receive(const Archive::ByteStream & message);
private:
PlanetConnection & operator = (const PlanetConnection & rhs);
PlanetConnection(const PlanetConnection & source);
TaskConnection * connection;
};
//-----------------------------------------------------------------------
#endif // _INCLUDED_PlanetConnection_H
@@ -0,0 +1,26 @@
#ifndef _PROCESS_SPAWNER_H
#define _PROCESS_SPAWNER_H
#include <string>
#include <vector>
class ProcessSpawner
{
public:
static uint32 execute(const std::string & commandLine, const std::vector<std::string> & parameters);
static uint32 execute(const std::string & commandLine);
static void forceCore(const unsigned long pid);
static bool isProcessActive(uint32 pid);
static void kill(uint32 pid);
static uint32 postfixCounter;
static uint32 prefix;
private:
ProcessSpawner();
~ProcessSpawner();
ProcessSpawner(const ProcessSpawner&);
ProcessSpawner& operator= (const ProcessSpawner&);
};
//-----------------------------------------------------------------------
#endif // _PROCESS_SPAWNER_H
@@ -0,0 +1,225 @@
// TaskConnection.cpp
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTaskManager.h"
#include "CentralConnection.h"
#include "ConfigTaskManager.h"
#include "DatabaseConnection.h"
#include "Locator.h"
#include "GameConnection.h"
#include "ManagerConnection.h"
#include "MetricsServerConnection.h"
#include "PlanetConnection.h"
#include "TaskConnection.h"
#include "TaskManager.h"
#include "serverNetworkMessages/ExcommunicateGameServerMessage.h"
#include "serverNetworkMessages/TaskConnectionIdMessage.h"
#include "serverNetworkMessages/TaskKillProcess.h"
#include "sharedNetwork/NetworkSetupData.h"
//-----------------------------------------------------------------------
TaskConnection::TaskConnection(const std::string & a, const unsigned short p) :
Connection(a, p, NetworkSetupData()),
closed(),
failed(),
identified(),
opened(),
overflowing(),
receiveMessage(),
reset(),
handler(0)
{
}
//-----------------------------------------------------------------------
TaskConnection::TaskConnection(UdpConnectionMT * u, TcpClient * t) :
Connection(u, t),
closed(),
failed(),
identified(),
opened(),
overflowing(),
receiveMessage(),
reset(),
handler(0)
{
}
//-----------------------------------------------------------------------
TaskConnection::~TaskConnection()
{
delete handler;
}
//-----------------------------------------------------------------------
void TaskConnection::onConnectionClosed()
{
static Closed msg;
closed.emitMessage(msg); //lint !e738 Symbol 'msg' not explicitly initialized
}
//-----------------------------------------------------------------------
void TaskConnection::onConnectionOpened()
{
DEBUG_REPORT_LOG(true, ("Task Connection opened %s\n", getRemoteAddress().c_str()));
static Opened msg;
opened.emitMessage(msg); //lint !e738 Symbol 'msg' not explicitly initialized
}
//-----------------------------------------------------------------------
void TaskConnection::onConnectionOverflowing(const unsigned int bytesPending)
{
static Overflowing msg;
msg.bytesPending = bytesPending;
overflowing.emitMessage(msg);
}
//-----------------------------------------------------------------------
void TaskConnection::onReceive(const Archive::ByteStream & message)
{
static Receive msg;
if(handler)
handler->receive(message);
Archive::ReadIterator r(message);
GameNetworkMessage m(r);
if(m.isType("TaskConnectionIdMessage"))
{
r = message.begin();
TaskConnectionIdMessage t(r);
FATAL((ConfigTaskManager::getVerifyClusterName() && (TaskManager::getNodeLabel() == "node0") && (t.getServerType() == TaskConnectionIdMessage::TaskManager) && (t.getClusterName() != std::string(ConfigTaskManager::getClusterName()))), ("Remote TaskManager %s (%s) reported cluster name (%s) that is different from my cluster name (%s)", t.getCommandLine().c_str(), getRemoteAddress().c_str(), t.getClusterName().c_str(), ConfigTaskManager::getClusterName()));
Identified i = {this, t.getServerType() };
identified.emitMessage(i);
switch(i.id)
{
case TaskConnectionIdMessage::Central:
{
REPORT_LOG(true, ("New Central Server connection active\n"));
handler = new CentralConnection(this, t.getCommandLine());
TaskManager::setCentralConnection(this);
}
break;
case TaskConnectionIdMessage::Game:
{
REPORT_LOG(true, ("New Game Server connection active\n"));
handler = new GameConnection(this);
}
break;
case TaskConnectionIdMessage::Database:
{
REPORT_LOG(true, ("New Database Server connection active\n"));
handler = new DatabaseConnection();
}
break;
case TaskConnectionIdMessage::Metrics:
{
REPORT_LOG(true, ("New Metrics Server connection active\n"));
handler = new MetricsServerConnection(this, t.getCommandLine());
}
break;
case TaskConnectionIdMessage::Planet:
{
REPORT_LOG(true, ("New Planet Server connection active\n"));
handler = new PlanetConnection(this);
}
break;
default:
WARNING_STRICT_FATAL(true, ("Unknown id (%d) received on task connection", i.id));
break;
}
}
else if(m.isType("ExcommunicateGameServerMessage"))
{
r = message.begin();
ExcommunicateGameServerMessage ex(r);
TaskKillProcess k(ex.getHostName(), ex.getProcessId(), true);
TaskManager::killProcess(k);
// broadcast to other task managers
Locator::sendToAllTaskManagers(k);
}
else if(m.isType("TaskKillProcess"))
{
r = message.begin();
TaskKillProcess k(r);
TaskManager::killProcess(k);
}
msg.message = &message;
receiveMessage.emitMessage(msg);
}
//-----------------------------------------------------------------------
void TaskConnection::send(const GameNetworkMessage & message)
{
Archive::ByteStream b;
message.pack(b);
Connection::send(b, true);
}
//-----------------------------------------------------------------------
MessageDispatch::Transceiver<const Closed &> & TaskConnection::getTransceiverClosed()
{
return closed; //lint !e1536 Exposing low access member
}
//-----------------------------------------------------------------------
MessageDispatch::Transceiver<const Failed &> & TaskConnection::getTransceiverFailed()
{
return failed; //lint !e1536 Exposing low access member
}
//-----------------------------------------------------------------------
MessageDispatch::Transceiver<const Identified &> & TaskConnection::getTransceiverIdentified()
{
return identified; //lint !e1536 Exposing low access member
}
//-----------------------------------------------------------------------
MessageDispatch::Transceiver<const Opened &> & TaskConnection::getTransceiverOpened()
{
return opened; //lint !e1536 Exposing low access member
}
//-----------------------------------------------------------------------
MessageDispatch::Transceiver<const Overflowing &> & TaskConnection::getTransceiverOverflowing()
{
return overflowing; //lint !e1536 Exposing low access member
}
//-----------------------------------------------------------------------
MessageDispatch::Transceiver<const Receive &> & TaskConnection::getTransceiverReceive()
{
return receiveMessage; //lint !e1536 Exposing low access member
}
//-----------------------------------------------------------------------
MessageDispatch::Transceiver<const Reset &> & TaskConnection::getTransceiverReset()
{
return reset; //lint !e1536 Exposing low access member
}
//-----------------------------------------------------------------------
@@ -0,0 +1,75 @@
// TaskConnection.h
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_TaskConnection_H
#define _INCLUDED_TaskConnection_H
//-----------------------------------------------------------------------
#include <algorithm>
#include "sharedMessageDispatch/Transceiver.h"
#include "sharedNetwork/Connection.h"
namespace Archive
{
class ByteStream;
}
class GameNetworkMessage;
class TaskConnection;
class TaskHandler;
//-----------------------------------------------------------------------
struct Closed {};
struct Failed {};
struct Identified {TaskConnection * connection; unsigned char id;};
struct Opened {};
struct Overflowing {unsigned int bytesPending;};
struct Receive {const Archive::ByteStream * message;};
struct Reset {};
class TaskConnection : public Connection
{
public:
public:
TaskConnection(const std::string & remoteAddress, const unsigned short remotePort);
TaskConnection(UdpConnectionMT *, TcpClient *);
~TaskConnection();
static int getConnectionCount ();
virtual void onConnectionClosed ();
virtual void onConnectionOpened ();
virtual void onConnectionOverflowing (const unsigned int bytesPending);
virtual void onReceive (const Archive::ByteStream & message);
void send (const GameNetworkMessage & message); //lint !e1411 Member with different signature hides virtual member 'Connection::send(const Archive::ByteStream &, bool) const // jrandall how can it hide the virtual if the signature differs?
MessageDispatch::Transceiver<const Closed &> & getTransceiverClosed ();
MessageDispatch::Transceiver<const Failed &> & getTransceiverFailed ();
MessageDispatch::Transceiver<const Identified &> & getTransceiverIdentified ();
MessageDispatch::Transceiver<const Opened &> & getTransceiverOpened ();
MessageDispatch::Transceiver<const Overflowing &> & getTransceiverOverflowing ();
MessageDispatch::Transceiver<const Receive &> & getTransceiverReceive ();
MessageDispatch::Transceiver<const Reset &> & getTransceiverReset ();
private: // capabilities / emissions
MessageDispatch::Transceiver<const Closed &> closed;
MessageDispatch::Transceiver<const Failed &> failed;
MessageDispatch::Transceiver<const Identified &> identified;
MessageDispatch::Transceiver<const Opened &> opened;
MessageDispatch::Transceiver<const Overflowing &> overflowing;
MessageDispatch::Transceiver<const Receive &> receiveMessage;
MessageDispatch::Transceiver<const Reset &> reset;
private:
TaskConnection & operator = (const TaskConnection & rhs);
TaskConnection(const TaskConnection & source);
private:
TaskHandler * handler;
}; //lint !e1712 default constructor not defined for class 'TaskConnection'
//-----------------------------------------------------------------------
#endif // _INCLUDED_TaskConnection_H
@@ -0,0 +1,41 @@
// TaskHandler.cpp
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTaskManager.h"
#include "TaskHandler.h"
//-----------------------------------------------------------------------
TaskHandler::TaskHandler()
{
}
//-----------------------------------------------------------------------
TaskHandler::TaskHandler(const TaskHandler &)
{
}
//-----------------------------------------------------------------------
TaskHandler::~TaskHandler()
{
}
//-----------------------------------------------------------------------
TaskHandler & TaskHandler::operator = (const TaskHandler & rhs)
{
if(this != &rhs)
{
// make assignments if right hand side is not this instance
}
return *this;
}
//-----------------------------------------------------------------------
@@ -0,0 +1,33 @@
// TaskHandler.h
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_TaskHandler_H
#define _INCLUDED_TaskHandler_H
//-----------------------------------------------------------------------
namespace Archive
{
class ByteStream;
}
//-----------------------------------------------------------------------
class TaskHandler
{
public:
TaskHandler();
virtual ~TaskHandler() = 0;
virtual void receive(const Archive::ByteStream & message) = 0;
private:
TaskHandler & operator = (const TaskHandler & rhs);
TaskHandler(const TaskHandler & source);
};
//-----------------------------------------------------------------------
#endif // _INCLUDED_TaskHandler_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,179 @@
// TaskManager.h
// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_TaskManager_H
#define _INCLUDED_TaskManager_H
#include <map>
#include <string>
#include <set>
#include <vector>
//-----------------------------------------------------------------------
class Connection;
class ConsoleConnection;
class GameNetworkMessage;
class LoginConnection;
class Service;
class ManagerConnection;
class TaskConnection;
class TaskKillProcess;
class TaskManagerSysInfo;
//-----------------------------------------------------------------------
struct ProcessKilled
{
std::string commandLine;
std::string hostName;
};
//-----------------------------------------------------------------------
struct ProcessAborted
{
std::string commandLine;
std::string hostName;
};
//-----------------------------------------------------------------------
struct ProcessStarted
{
unsigned long pid;
std::string commandLine;
std::string hostName;
};
//-----------------------------------------------------------------------
struct RequestProcessKill
{
std::string commandLine;
std::string hostName;
unsigned long pid;
};
//-----------------------------------------------------------------------
struct RequestProcessStart
{
std::string commandLine;
std::string hostName;
};
//-----------------------------------------------------------------------
struct ProcessEntry
{
std::string processName;
std::string targetHost;
std::string executable;
std::string options;
};
//-----------------------------------------------------------------------
class TaskManager
{
public:
typedef unsigned int SpawnDelaySeconds;
TaskManager();
~TaskManager();
static std::string executeCommand (const std::string & command);
static const float getLoadAverage ();
static const std::string & getNodeLabel();
static time_t getStartTime();
static void killProcess (const TaskKillProcess &);
static void retryConnection (ManagerConnection const *connection);
static void sendToCentralServer (const GameNetworkMessage & msg);
static void setCentralConnection (TaskConnection * connection);
static void onDatabaseIdle (bool isIdle);
static void onPreloadFinished ();
static void runSpawnRequestQueue ();
static unsigned long startServer (const std::string & processName, const std::string & options, const std::string& hostName, SpawnDelaySeconds spawnDelay);
static void stopCluster ();
static void resendUnacknowledgedSpawnRequests (Connection * connection, const std::string & nodeLabel);
static void removePendingSpawnProcessAck (int transactionId);
static void install ();
static void remove ();
static void run ();
static void update ();
static const std::set<std::pair< std::string, unsigned long> > & getLocalServers();
static const std::map<std::string, std::pair<std::string, unsigned long> > & getRemoteServers();
static void addToGameConnections(int x);
static int getNumGameConnections();
private:
TaskManager & operator = (const TaskManager & rhs);
TaskManager(const TaskManager & source);
static TaskManager & instance();
void processRcFile();
void processEnvironmentVariables();
void setupNodeList();
static unsigned long startServerLocal(const ProcessEntry & processEntry, const std::string & options);
static void startCluster();
private:
struct NodeEntry
{
NodeEntry(const std::string &, const std::string & , int);
bool operator==(const NodeEntry &) const;
bool operator==(const std::string & address) const;
std::string m_address;
std::string m_nodeLabel;
int m_nodeNumber;
};
std::map<std::string, ProcessEntry> m_processEntries;
std::set<std::pair<std::string, unsigned long> > m_localServers;
std::map<std::string, std::pair<std::string, unsigned long> > m_remoteServers;
std::string m_nodeLabel;
time_t const m_startTime;
std::vector<NodeEntry> m_nodeList;
int m_nodeNumber;
std::vector<NodeEntry> m_nodeToConnectToList;
Service * m_managerService;
Service * m_taskService;
Service * m_consoleService;
TaskManagerSysInfo * m_sysInfoSource;
TaskConnection * m_centralConnection;
};
//-----------------------------------------------------------------------
inline const std::set<std::pair<std::string, unsigned long> > & TaskManager::getLocalServers()
{
return instance().m_localServers;
}
//-----------------------------------------------------------------------
inline const std::string& TaskManager::getNodeLabel()
{
return instance().m_nodeLabel;
}
//-----------------------------------------------------------------------
inline time_t TaskManager::getStartTime()
{
return instance().m_startTime;
}
//-----------------------------------------------------------------------
#endif // _INCLUDED_TaskManager_H
@@ -0,0 +1,28 @@
// TaskManagerSysInfo.h
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
#ifndef _INCLUDED_TaskManagerSysInfo_H
#define _INCLUDED_TaskManagerSysInfo_H
#include <list>
//-----------------------------------------------------------------------
class TaskManagerSysInfo
{
public:
TaskManagerSysInfo();
~TaskManagerSysInfo();
void update();
const float getScore () const;
private:
TaskManagerSysInfo & operator = (const TaskManagerSysInfo & rhs);
TaskManagerSysInfo(const TaskManagerSysInfo & source);
std::list<float> averageScore;
};
//-----------------------------------------------------------------------
#endif // _INCLUDED_TaskManagerSysInfo_H
@@ -0,0 +1,22 @@
// ConsoleInput.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTaskManager.h"
#include "Console.h"
#include <conio.h>
//-----------------------------------------------------------------------
const char Console::getNextChar()
{
char result = 0;
if(_kbhit())
result = static_cast<char>(_getche());
return result;
}
//-----------------------------------------------------------------------
@@ -0,0 +1,33 @@
#include "FirstTaskManager.h"
namespace EnvironmentVariable
{
bool addToEnvironmentVariable(const char* key, const char* value)
{
bool retval = false;
char oldValue[256];
DWORD tmp = GetEnvironmentVariable(key, oldValue, sizeof(oldValue));
if (tmp != 0)
{
std::string s(oldValue);
s += ";";
s += value;
//Bad things happen if the first character happens to be ; (ie from an empty environment string)
const char* newValue = s.c_str();
if (newValue[0] == ';')
++newValue;
retval = (SetEnvironmentVariable(key, newValue) != 0);
}
else
{
retval = (SetEnvironmentVariable(key, value) != 0);
}
return retval;
}
bool setEnvironmentVariable(const char* key, const char* value)
{
return (SetEnvironmentVariable(key, value) != 0);
}
};
@@ -0,0 +1,153 @@
#include "FirstTaskManager.h"
#include "sharedFoundation/FirstSharedFoundation.h"
#include "ProcessSpawner.h"
#include <map>
#include <string>
#include "TaskManager.h"
#include <stdio.h>
uint32 ProcessSpawner::prefix;
std::map<uint32, HANDLE> procById;
//-----------------------------------------------------------------------
bool tokenize (const std::string & str, std::vector<std::string> & result)
{
size_t end_pos = 0;
size_t start_pos = 0;
result.clear ();
for (;;)
{
if (end_pos >= str.size ())
break;
start_pos = str.find_first_not_of (' ', end_pos);
if (start_pos == str.npos)
break;
//----------------------------------------------------------------------
if (str [start_pos] == '\"')
{
if (++start_pos >= str.size ())
break;
end_pos = str.find_first_of ('\"', start_pos);
}
else
end_pos = str.find_first_of (' ', start_pos);
//----------------------------------------------------------------------
if (start_pos == end_pos)
break;
if (end_pos == str.npos)
{
result.push_back (str.substr (start_pos));
break;
}
else
result.push_back (str.substr (start_pos, end_pos - start_pos));
++start_pos;
}
return true;
}
uint32 ProcessSpawner::execute(const std::string & processName, const std::vector<std::string> & parameters)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
char cmd[1024] = {"\0"};
std::string cmdLine;
cmdLine = processName.c_str();
cmdLine += " ";
std::vector<std::string>::const_iterator i;
for(i = parameters.begin(); i != parameters.end(); ++i)
{
cmdLine += (*i).c_str();
cmdLine += " ";
}
_snprintf(cmd, 1024, "%s.exe", processName.c_str());
// _snprintf(cmd, 1024, "%s", processName.c_str());
memset(&si, 0, sizeof(si));
memset(&pi, 0, sizeof(pi));
si.cb = sizeof(si);
const int result = CreateProcess(cmd, const_cast<char *>(cmdLine.c_str()), NULL, NULL, false, 0, 0, 0, &si, &pi);
UNREF (result);
#ifdef _DEBUG
if (!result)
{
DWORD iErr = GetLastError();
char * errStr = strerror(iErr);
DEBUG_REPORT_LOG(true, ("ProcessSpawner: %s - %s\n", cmd, errStr));
}
#endif
procById.insert(std::pair<uint32, HANDLE>(pi.dwProcessId, pi.hProcess));
return pi.dwProcessId;
}
//-----------------------------------------------------------------------
uint32 ProcessSpawner::execute(const std::string & cmd)
{
std::vector<std::string> args;
size_t firstArg = cmd.find_first_of(" ");
std::string processName;
if(firstArg < cmd.size())
{
std::string a = cmd.substr(firstArg + 1);
tokenize(a, args);
processName = cmd.substr(0, firstArg);
}
else
{
processName = cmd;
}
return execute(processName, args);
}
//-----------------------------------------------------------------------
bool ProcessSpawner::isProcessActive(uint32 pid)
{
bool result = false;
std::map<uint32, HANDLE>::const_iterator f = procById.find(pid);
if(f != procById.end())
{
DWORD exitCode;
GetExitCodeProcess((*f).second, &exitCode);
result = (exitCode == STILL_ACTIVE);
}
return result;
}
//-----------------------------------------------------------------------
void ProcessSpawner::kill(uint32 pid)
{
HANDLE p = OpenProcess(PROCESS_TERMINATE, false, (DWORD)pid);
if(p)
TerminateProcess(p, 0);
}
//-----------------------------------------------------------------------
void ProcessSpawner::forceCore(const unsigned long pid)
{
ProcessSpawner::kill(pid);
}
//-----------------------------------------------------------------------
@@ -0,0 +1,147 @@
// TaskManagerSysInfo.cpp
// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved.
// Author: Justin Randall
//-----------------------------------------------------------------------
#include "FirstTaskManager.h"
#include "TaskManagerSysInfo.h"
#pragma warning ( disable : 4201)
#include <windows.h>
#include <tlhelp32.h>
//-----------------------------------------------------------------------
TaskManagerSysInfo::TaskManagerSysInfo() :
averageScore()
{
update();
}
//-----------------------------------------------------------------------
TaskManagerSysInfo::TaskManagerSysInfo(const TaskManagerSysInfo &)
{
}
//-----------------------------------------------------------------------
TaskManagerSysInfo::~TaskManagerSysInfo()
{
}
//-----------------------------------------------------------------------
TaskManagerSysInfo & TaskManagerSysInfo::operator = (const TaskManagerSysInfo & rhs)
{
if(this != &rhs)
{
// make assignments if right hand side is not this instance
}
return *this;
}
//-----------------------------------------------------------------------
const float TaskManagerSysInfo::getScore() const
{
std::list<float>::const_iterator i;
float avg = 0.0f;
for(i = averageScore.begin(); i != averageScore.end(); ++i)
{
avg += (*i);
}
avg = avg / averageScore.size();
return avg;
}
//-----------------------------------------------------------------------
void TaskManagerSysInfo::update()
{
static int64 activeTime[2] = {0};
static int64 currentTime[2] = {0};
float currentScore = 0.0f;
activeTime[0] = activeTime[1];
currentTime[0] = currentTime[1];
activeTime[1] = 0;
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
double procAvg = 0.0f;
MEMORYSTATUS memStat;
GlobalMemoryStatus(&memStat);
currentScore = static_cast<float>(static_cast<float>(memStat.dwMemoryLoad) * 0.005f);
if(hProcessSnap != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 pe32 = {0};
pe32.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hProcessSnap, &pe32))
{
do
{
HANDLE proc = OpenProcess(PROCESS_QUERY_INFORMATION, false, pe32.th32ProcessID);
// some stuf with the enumerated processes
FILETIME createTime = {0};
FILETIME exitTime = {0};
FILETIME kernelTime = {0};
FILETIME userTime = {0};
GetProcessTimes(proc, &createTime, &exitTime, &kernelTime, &userTime);
int64 totals;
// SDK docs say:
// It is not recommended that you add and subtract values
// from the FILETIME structure to obtain relative times. Instead, you should
// Copy the resulting FILETIME structure to a ULARGE_INTEGER structure.
// Use normal 64-bit arithmetic on the ULARGE_INTEGER value.
int64 c;
int64 e;
int64 k;
int64 u;
memcpy(&c, &createTime, sizeof(int64));
memcpy(&e, &exitTime, sizeof(int64));
memcpy(&k, &kernelTime, sizeof(int64));
memcpy(&u, &userTime, sizeof(int64));
totals = k + u;
FILETIME fst;
SYSTEMTIME st;
GetSystemTime(&st);
SystemTimeToFileTime(&st, &fst);
int64 runTime;
memcpy(&runTime, &fst, sizeof(int64));
runTime = runTime - c;
if(c || e || k || u)
{
activeTime[1] += k + e;
}
}
while (Process32Next(hProcessSnap, &pe32));
}
}
FILETIME fst;
SYSTEMTIME st;
GetSystemTime(&st);
SystemTimeToFileTime(&st, &fst);
memcpy(&currentTime[1], &fst, sizeof(int64));
int64 timeSlice = currentTime[1] - currentTime[0];
int64 activeSlice = activeTime[1] - activeTime[0];
procAvg = static_cast<double>(static_cast<double>(activeSlice) / timeSlice);
//REPORT_LOG(true, ("%f\n", procAvg));
currentScore = currentScore + static_cast<float>(procAvg * 0.5);
averageScore.insert(averageScore.end(), currentScore);
if(averageScore.size() > 100)
averageScore.erase(averageScore.begin());
}
//-----------------------------------------------------------------------
@@ -0,0 +1,43 @@
#include "FirstTaskManager.h"
#include "sharedFoundation/FirstSharedFoundation.h"
#include "sharedCompression/SetupSharedCompression.h"
#include "sharedDebug/SetupSharedDebug.h"
#include "sharedFile/SetupSharedFile.h"
#include "sharedFoundation/ConfigFile.h"
#include "sharedFoundation/SetupSharedFoundation.h"
#include "sharedNetworkMessages/SetupSharedNetworkMessages.h"
#include "sharedThread/SetupSharedThread.h"
#include "TaskManager.h"
#include "ConfigTaskManager.h"
//=====================================================================
int main(int argc, char **argv)
{
SetupSharedThread::install();
SetupSharedDebug::install(1024);
//-- setup foundation
SetupSharedFoundation::Data setupFoundationData(SetupSharedFoundation::Data::D_game);
setupFoundationData.argc = argc;
setupFoundationData.argv = argv;
setupFoundationData.createWindow = false;
setupFoundationData.clockUsesSleep = true;
SetupSharedFoundation::install (setupFoundationData);
SetupSharedCompression::install();
SetupSharedNetworkMessages::install();
ConfigTaskManager::install();
//-- run server
SetupSharedFoundation::callbackWithExceptionHandling(TaskManager::run);
SetupSharedFoundation::remove();
SetupSharedThread::remove();
return 0;
}
//=====================================================================