mxoemu/Reality/Source/Master.cpp
2010-02-15 12:52:58 +00:00

230 lines
5.3 KiB
C++

// *************************************************************************************************
// --------------------------------------
// Copyright (C) 2006-2010 Rajko Stojadinovic
//
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
// *************************************************************************************************
#define THIS_IS_SPARTA
#include "Common.h"
#include "Master.h"
#include "Log.h"
#include "Config.h"
#include "MersenneTwister.h"
#include "Threading/Threading.h"
#include "Database/Database.h"
#include "AuthRunnable.h"
#include "MarginRunnable.h"
#include "GameRunnable.h"
#include "ConsoleThread.h"
createFileSingleton( Master );
volatile bool Master::m_stopEvent = false;
void Master::_OnSignal(int s)
{
switch (s)
{
case SIGINT:
Master::m_stopEvent = true;
break;
case SIGTERM:
Master::m_stopEvent = true;
break;
case SIGABRT:
Master::m_stopEvent = true;
break;
#if PLATFORM == PLATFORM_WIN32
case SIGBREAK:
Master::m_stopEvent = true;
break;
#endif
}
signal(s, _OnSignal);
}
Master::Master()
{
}
Master::~Master()
{
}
#define REALITY_CONFIG "Reality.conf"
bool Master::Run()
{
if (!sConfig.SetSource(REALITY_CONFIG))
{
CRITICAL_LOG(format("Could not find configuration file %1%.") % REALITY_CONFIG);
exit(0);
}
INFO_LOG(format("Reality v0.01 Alpha %1% bit version started") % (sizeof(int*) * 8));
if( !_StartDB() )
{
CRITICAL_LOG("Error starting database!");
Database::CleanupLibs();
return false;
}
DEBUG_LOG("Initializing random number generators...");
uint32 seed = time(NULL);
new MTRand(seed);
srand(seed);
_HookSignals();
//init thread manager
ThreadPool.Startup();
//start server threads
AuthRunnable *authRun = new AuthRunnable();
ThreadPool.ExecuteTask(authRun);
MarginRunnable *marginRun = new MarginRunnable();
ThreadPool.ExecuteTask(marginRun);
GameRunnable *gameRun = new GameRunnable();
ThreadPool.ExecuteTask(gameRun);
//spawn console thread
ConsoleThread *consoleRun = new ConsoleThread();
ThreadPool.ExecuteTask(consoleRun);
while (!Master::m_stopEvent)
{
Sleep(100);
}
authRun->Terminate();
marginRun->Terminate();
gameRun->Terminate();
consoleRun->Terminate();
DEBUG_LOG("Exiting...");
ThreadPool.ShowStats();
_UnhookSignals();
_StopDB();
return 0;
}
// Database defines.
Database* Database_Main;
bool Master::_StartDB()
{
Database_Main = Database::Create();
std::string hostname, username, password, database;
int port = 0;
bool result = sConfig.GetString("Database.Username", &username);
sConfig.GetString("Database.Password", &password);
result = !result ? result : sConfig.GetString("Database.Hostname", &hostname);
result = !result ? result : sConfig.GetString("Database.Name", &database);
result = !result ? result : sConfig.GetInt("Database.Port", &port);
if(result == false)
{
CRITICAL_LOG("sql: One or more parameters were missing from Database directive.");
return false;
}
// Initialize it
if(!sDatabase.Initialize(hostname.c_str(), (unsigned int)port, username.c_str(),
password.c_str(), database.c_str(), sConfig.GetIntDefault("Database.ConnectionCount", 5),
16384))
{
CRITICAL_LOG("sql: Main database initialization failed. Exiting.");
return false;
}
return true;
}
void Master::_StopDB()
{
sDatabase.EndThreads();
sDatabase.Shutdown();
}
void Master::_HookSignals()
{
signal(SIGINT, _OnSignal);
signal(SIGTERM, _OnSignal);
signal(SIGABRT, _OnSignal);
#if PLATFORM == PLATFORM_WIN32
signal(SIGBREAK, _OnSignal);
#endif
}
void Master::_UnhookSignals()
{
signal(SIGINT, 0);
signal(SIGTERM, 0);
signal(SIGABRT, 0);
#if PLATFORM == PLATFORM_WIN32
signal(SIGBREAK, 0);
#endif
}
#ifdef WIN32
NativeMutex m_crashedMutex;
// Crash Handler
void OnCrash( bool Terminate )
{
ERROR_LOG( "Advanced crash handler initialized." );
if( !m_crashedMutex.AttemptAcquire() )
TerminateThread( GetCurrentThread(), 0 );
try
{
ERROR_LOG( "Waiting for all database queries to finish..." );
sDatabase.EndThreads();
}
catch(...)
{
ERROR_LOG( "Threw an exception while attempting to save all data." );
}
ERROR_LOG( "Closing." );
// Terminate Entire Application
if( Terminate )
{
HANDLE pH = OpenProcess( PROCESS_TERMINATE, TRUE, GetCurrentProcessId() );
TerminateProcess( pH, 1 );
CloseHandle( pH );
}
}
#endif