2009-04-06 21:14:51 +02:00
/*
2009-02-04 12:42:26 +01:00
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
2008-10-14 11:57:03 -05:00
*
2010-01-16 20:19:18 +03:00
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
2008-10-02 16:23:55 -05:00
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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
2008-11-15 11:56:59 -06:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2008-10-02 16:23:55 -05:00
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
2008-11-15 11:56:59 -06:00
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2008-10-02 16:23:55 -05:00
*/
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/** \file
2008-10-14 11:57:03 -05:00
\ingroup Trinityd
2008-10-02 16:23:55 -05:00
*/
2009-10-17 15:51:44 -07:00
2010-05-19 21:16:59 +02:00
#include <ace/Sig_Handler.h>
2009-10-17 15:51:44 -07:00
2008-10-04 06:17:19 -05:00
#include "Common.h"
2008-10-02 16:23:55 -05:00
#include "SystemConfig.h"
2010-05-19 21:16:59 +02:00
#include "SignalHandler.h"
2009-06-04 21:41:07 +02:00
#include "World.h"
#include "WorldRunnable.h"
#include "WorldSocket.h"
#include "WorldSocketMgr.h"
2010-06-08 01:34:51 +02:00
#include "Configuration/ConfigEnv.h"
2008-10-02 16:23:55 -05:00
#include "Database/DatabaseEnv.h"
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#include "CliRunnable.h"
2009-06-04 21:41:07 +02:00
#include "Log.h"
#include "Master.h"
2008-10-02 16:23:55 -05:00
#include "RASocket.h"
2010-07-23 09:26:23 +02:00
#include "TCSoap.h"
2009-12-24 10:20:15 +01:00
#include "Timer.h"
2008-10-02 16:23:55 -05:00
#include "Util.h"
2009-10-17 15:51:44 -07:00
2010-06-08 01:34:51 +02:00
#include "TcpSocket.h"
#include "Utility.h"
#include "Parse.h"
#include "Socket.h"
#include "SocketHandler.h"
#include "ListenSocket.h"
#include "BigNumber.h"
2009-10-17 15:51:44 -07:00
2010-06-23 01:47:41 +02:00
#ifdef _WIN32
2008-10-02 16:23:55 -05:00
#include "ServiceWin32.h"
extern int m_ServiceStatus ;
#endif
2009-10-17 15:51:44 -07:00
2010-05-19 21:16:59 +02:00
/// Handle cored's termination signals
class CoredSignalHandler : public Trinity :: SignalHandler
{
public :
virtual void HandleSignal ( int SigNum )
{
switch ( SigNum )
{
case SIGINT :
World :: StopNow ( RESTART_EXIT_CODE );
break ;
case SIGTERM :
#ifdef _WIN32
case SIGBREAK :
if ( m_ServiceStatus != 1 )
#endif /* _WIN32 */
World :: StopNow ( SHUTDOWN_EXIT_CODE );
break ;
}
}
};
2009-05-13 18:22:21 -05:00
class FreezeDetectorRunnable : public ACE_Based :: Runnable
2008-10-02 16:23:55 -05:00
{
public :
FreezeDetectorRunnable () { _delaytime = 0 ; }
uint32 m_loops , m_lastchange ;
uint32 w_loops , w_lastchange ;
uint32 _delaytime ;
void SetDelayTime ( uint32 t ) { _delaytime = t ; }
void run ( void )
{
2010-06-25 01:30:06 +02:00
if ( ! _delaytime )
2008-10-02 16:23:55 -05:00
return ;
sLog . outString ( "Starting up anti-freeze thread (%u seconds max stuck time)..." , _delaytime / 1000 );
m_loops = 0 ;
w_loops = 0 ;
m_lastchange = 0 ;
w_lastchange = 0 ;
2010-06-25 01:30:06 +02:00
while ( ! World :: IsStopped ())
2008-10-02 16:23:55 -05:00
{
2009-05-13 18:22:21 -05:00
ACE_Based :: Thread :: Sleep ( 1000 );
2008-10-02 16:23:55 -05:00
uint32 curtime = getMSTime ();
// normal work
2010-06-25 01:30:06 +02:00
if ( w_loops != World :: m_worldLoopCounter )
2008-10-02 16:23:55 -05:00
{
w_lastchange = curtime ;
w_loops = World :: m_worldLoopCounter ;
}
2008-11-15 11:56:59 -06:00
// possible freeze
2010-06-25 01:30:06 +02:00
else if ( getMSTimeDiff ( w_lastchange , curtime ) > _delaytime )
2008-10-02 16:23:55 -05:00
{
sLog . outError ( "World Thread hangs, kicking out server!" );
* (( uint32 volatile * ) NULL ) = 0 ; // bang crash
}
}
sLog . outString ( "Anti-freeze thread exiting without problems." );
}
};
2009-10-17 15:51:44 -07:00
2009-05-13 18:22:21 -05:00
class RARunnable : public ACE_Based :: Runnable
2008-10-04 06:17:19 -05:00
{
public :
2009-03-20 22:17:39 +01:00
uint32 numLoops , loopCounter ;
2009-10-17 15:51:44 -07:00
2009-03-20 22:17:39 +01:00
RARunnable ()
{
uint32 socketSelecttime = sWorld . getConfig ( CONFIG_SOCKET_SELECTTIME );
numLoops = ( sConfig . GetIntDefault ( "MaxPingTime" , 30 ) * ( MINUTE * 1000000 / socketSelecttime ));
2008-10-04 06:17:19 -05:00
loopCounter = 0 ;
2009-03-20 22:17:39 +01:00
}
2009-10-17 15:51:44 -07:00
2009-03-20 22:17:39 +01:00
void checkping ()
{
// ping if need
if (( ++ loopCounter ) == numLoops )
{
loopCounter = 0 ;
sLog . outDetail ( "Ping MySQL to keep connection alive" );
2010-01-23 14:45:58 +01:00
WorldDatabase . Query ( "SELECT 1 FROM command LIMIT 1" );
2010-05-08 05:03:32 +02:00
LoginDatabase . Query ( "SELECT 1 FROM realmlist LIMIT 1" );
2010-01-23 14:45:58 +01:00
CharacterDatabase . Query ( "SELECT 1 FROM bugreport LIMIT 1" );
2009-03-20 22:17:39 +01:00
}
}
2009-10-17 15:51:44 -07:00
2009-03-20 22:17:39 +01:00
void run ()
{
SocketHandler h ;
2009-10-17 15:51:44 -07:00
2009-03-20 22:17:39 +01:00
// Launch the RA listener socket
ListenSocket < RASocket > RAListenSocket ( h );
bool usera = sConfig . GetBoolDefault ( "Ra.Enable" , false );
2009-10-17 15:51:44 -07:00
2009-03-20 22:17:39 +01:00
if ( usera )
{
port_t raport = sConfig . GetIntDefault ( "Ra.Port" , 3443 );
std :: string stringip = sConfig . GetStringDefault ( "Ra.IP" , "0.0.0.0" );
ipaddr_t raip ;
if ( ! Utility :: u2ip ( stringip , raip ))
2010-02-05 00:31:28 +01:00
sLog . outError ( "Trinity RA can not bind to ip %s" , stringip . c_str ());
2009-03-20 22:17:39 +01:00
else if ( RAListenSocket . Bind ( raip , raport ))
2010-02-05 00:31:28 +01:00
sLog . outError ( "Trinity RA can not bind to port %d on %s" , raport , stringip . c_str ());
2009-03-20 22:17:39 +01:00
else
{
h . Add ( & RAListenSocket );
2009-10-17 15:51:44 -07:00
2009-03-20 22:17:39 +01:00
sLog . outString ( "Starting Remote access listner on port %d on %s" , raport , stringip . c_str ());
}
}
2009-10-17 15:51:44 -07:00
2009-03-20 22:17:39 +01:00
// Socket Selet time is in microseconds , not miliseconds!!
uint32 socketSelecttime = sWorld . getConfig ( CONFIG_SOCKET_SELECTTIME );
2009-10-17 15:51:44 -07:00
2009-03-20 22:17:39 +01:00
// if use ra spend time waiting for io, if not use ra ,just sleep
if ( usera )
2008-10-04 06:17:19 -05:00
{
2009-03-20 22:17:39 +01:00
while ( ! World :: IsStopped ())
{
h . Select ( 0 , socketSelecttime );
checkping ();
}
2008-10-04 06:17:19 -05:00
}
2009-03-20 22:17:39 +01:00
else
2008-10-04 06:17:19 -05:00
{
2009-03-20 22:17:39 +01:00
while ( ! World :: IsStopped ())
{
2009-06-27 17:10:17 -05:00
ACE_Based :: Thread :: Sleep ( static_cast < unsigned long > ( socketSelecttime / 1000 ));
2009-03-20 22:17:39 +01:00
checkping ();
}
2008-10-04 06:17:19 -05:00
}
2009-03-20 22:17:39 +01:00
}
2008-10-04 06:17:19 -05:00
};
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
Master :: Master ()
{
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
Master ::~ Master ()
{
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/// Main function
int Master :: Run ()
{
2010-05-29 17:26:43 +02:00
BigNumber seed1 ;
seed1 . SetRand ( 16 * 8 );
2008-10-02 16:23:55 -05:00
sLog . outString ( "%s (core-daemon)" , _FULLVERSION );
sLog . outString ( "<Ctrl-C> to stop. \n " );
2009-10-17 15:51:44 -07:00
2009-03-20 22:17:39 +01:00
sLog . outString ( " ______ __" );
sLog . outString ( "/ \\ __ _ \\ __ __/ \\ \\ __" );
sLog . outString ( " \\ /_/ \\ \\ / _ __ / \\ _ \\ ___ / \\ _ \\ \\ ,_ \\ __ __" );
sLog . outString ( " \\ \\ \\ / \\ `'__ \\ / \\ \\ /' _ ` \\ / \\ \\ \\ \\ / / \\ \\ / \\ \\ " );
sLog . outString ( " \\ \\ \\ \\ \\ / \\ \\ \\ / \\ \\ / \\ \\ \\ \\ \\ \\ _ \\ \\ \\ _ \\ \\ " );
sLog . outString ( " \\ \\ _ \\ \\ _ \\ \\ \\ _ \\ \\ _ \\ \\ _ \\ \\ _ \\ \\ __ \\\\ /`____ \\ " );
sLog . outString ( " \\ /_/ \\ /_/ \\ /_/ \\ /_/ \\ /_/ \\ /_/ \\ /__/ `/___/> \\ " );
sLog . outString ( " C O R E / \\ ___/" );
sLog . outString ( "http://TrinityCore.org \\ /__/ \n " );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/// worldd PID file creation
std :: string pidfile = sConfig . GetStringDefault ( "PidFile" , "" );
if ( ! pidfile . empty ())
{
uint32 pid = CreatePIDFile ( pidfile );
if ( ! pid )
{
sLog . outError ( "Cannot create PID file %s. \n " , pidfile . c_str () );
return 1 ;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
sLog . outString ( "Daemon PID: %u \n " , pid );
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
///- Start the databases
if ( ! _StartDB ())
return 1 ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
///- Initialize the World
sWorld . SetInitialWorldSettings ();
2009-10-17 15:51:44 -07:00
2010-05-19 21:16:59 +02:00
// Initialise the signal handlers
CoredSignalHandler SignalINT , SignalTERM ;
#ifdef _WIN32
CoredSignalHandler SignalBREAK ;
#endif /* _WIN32 */
// Register realmd's signal handlers
ACE_Sig_Handler Handler ;
Handler . register_handler ( SIGINT , & SignalINT );
Handler . register_handler ( SIGTERM , & SignalTERM );
#ifdef _WIN32
Handler . register_handler ( SIGBREAK , & SignalBREAK );
#endif /* _WIN32 */
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
///- Launch WorldRunnable thread
2009-08-08 12:37:33 -05:00
ACE_Based :: Thread world_thread ( new WorldRunnable );
world_thread . setPriority ( ACE_Based :: Highest );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// set server online
2010-05-08 05:03:32 +02:00
LoginDatabase . PExecute ( "UPDATE realmlist SET color = 0, population = 0 WHERE id = '%d'" , realmID );
2009-10-17 15:51:44 -07:00
2009-08-08 12:12:56 -05:00
ACE_Based :: Thread * cliThread = NULL ;
2009-10-17 15:51:44 -07:00
2010-06-23 01:47:41 +02:00
#ifdef _WIN32
2008-10-02 16:23:55 -05:00
if ( sConfig . GetBoolDefault ( "Console.Enable" , true ) && ( m_ServiceStatus == - 1 ) /* need disable console in service mode*/ )
#else
if ( sConfig . GetBoolDefault ( "Console.Enable" , true ))
#endif
{
///- Launch CliRunnable thread
2009-08-08 12:12:56 -05:00
cliThread = new ACE_Based :: Thread ( new CliRunnable );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2009-08-08 12:37:33 -05:00
ACE_Based :: Thread rar_thread ( new RARunnable );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
///- Handle affinity for multiple processors and process priority on Windows
2010-06-23 01:47:41 +02:00
#ifdef _WIN32
2008-10-02 16:23:55 -05:00
{
HANDLE hProcess = GetCurrentProcess ();
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
uint32 Aff = sConfig . GetIntDefault ( "UseProcessors" , 0 );
if ( Aff > 0 )
{
ULONG_PTR appAff ;
ULONG_PTR sysAff ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
if ( GetProcessAffinityMask ( hProcess , & appAff , & sysAff ))
{
ULONG_PTR curAff = Aff & appAff ; // remove non accessible processors
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
if ( ! curAff )
{
2008-10-14 11:57:03 -05:00
sLog . outError ( "Processors marked in UseProcessors bitmask (hex) %x not accessible for Trinityd. Accessible processors bitmask (hex): %x" , Aff , appAff );
2008-10-02 16:23:55 -05:00
}
else
{
if ( SetProcessAffinityMask ( hProcess , curAff ))
sLog . outString ( "Using processors (bitmask, hex): %x" , curAff );
else
sLog . outError ( "Can't set used processors (hex): %x" , curAff );
}
}
2009-03-20 22:17:39 +01:00
sLog . outString ( "" );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
bool Prio = sConfig . GetBoolDefault ( "ProcessPriority" , false );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// if(Prio && (m_ServiceStatus == -1)/* need set to default process priority class in service mode*/)
if ( Prio )
{
if ( SetPriorityClass ( hProcess , HIGH_PRIORITY_CLASS ))
sLog . outString ( "TrinityCore process priority class set to HIGH" );
else
2008-10-14 11:57:03 -05:00
sLog . outError ( "ERROR: Can't set Trinityd process priority class." );
2009-03-20 22:17:39 +01:00
sLog . outString ( "" );
2008-10-02 16:23:55 -05:00
}
}
#endif
2010-07-23 09:26:23 +02:00
//Start soap serving thread
ACE_Based :: Thread * soap_thread = NULL ;
if ( sConfig . GetBoolDefault ( "SOAP.Enabled" , false ))
{
TCSoapRunnable * runnable = new TCSoapRunnable ();
runnable -> setListenArguments ( sConfig . GetStringDefault ( "SOAP.IP" , "127.0.0.1" ), sConfig . GetIntDefault ( "SOAP.Port" , 7878 ));
soap_thread = new ACE_Based :: Thread ( runnable );
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
uint32 realCurrTime , realPrevTime ;
realCurrTime = realPrevTime = getMSTime ();
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
///- Start up freeze catcher thread
2009-08-08 12:37:33 -05:00
if ( uint32 freeze_delay = sConfig . GetIntDefault ( "MaxCoreStuckTime" , 0 ))
2008-10-02 16:23:55 -05:00
{
FreezeDetectorRunnable * fdr = new FreezeDetectorRunnable ();
fdr -> SetDelayTime ( freeze_delay * 1000 );
2009-08-08 12:37:33 -05:00
ACE_Based :: Thread freeze_thread ( fdr );
freeze_thread . setPriority ( ACE_Based :: Highest );
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-04 06:17:19 -05:00
///- Launch the world listener socket
2009-03-20 22:17:39 +01:00
port_t wsport = sWorld . getConfig ( CONFIG_PORT_WORLD );
std :: string bind_ip = sConfig . GetStringDefault ( "BindIP" , "0.0.0.0" );
2009-10-17 15:51:44 -07:00
2009-03-20 22:17:39 +01:00
if ( sWorldSocketMgr -> StartNetwork ( wsport , bind_ip . c_str ()) == - 1 )
2008-10-04 06:17:19 -05:00
{
2009-03-20 22:17:39 +01:00
sLog . outError ( "Failed to start network" );
World :: StopNow ( ERROR_EXIT_CODE );
// go down and shutdown the server
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-04 06:17:19 -05:00
sWorldSocketMgr -> Wait ();
2009-10-17 15:51:44 -07:00
2010-07-23 09:26:23 +02:00
if ( soap_thread )
{
soap_thread -> wait ();
soap_thread -> destroy ();
delete soap_thread ;
}
2008-10-02 16:23:55 -05:00
// set server offline
2010-05-08 05:03:32 +02:00
LoginDatabase . PExecute ( "UPDATE realmlist SET color = 2 WHERE id = '%d'" , realmID );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// when the main thread closes the singletons get unloaded
// since worldrunnable uses them, it will crash if unloaded after master
2009-08-08 12:37:33 -05:00
world_thread . wait ();
rar_thread . wait ();
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
///- Clean database before leaving
clearOnlineAccounts ();
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
///- Wait for delay threads to end
CharacterDatabase . HaltDelayThread ();
WorldDatabase . HaltDelayThread ();
2010-05-08 05:03:32 +02:00
LoginDatabase . HaltDelayThread ();
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
sLog . outString ( "Halting process..." );
2009-10-17 15:51:44 -07:00
2009-08-08 12:37:33 -05:00
if ( cliThread )
2008-10-02 16:23:55 -05:00
{
2010-06-23 01:47:41 +02:00
#ifdef _WIN32
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// this only way to terminate CLI thread exist at Win32 (alt. way exist only in Windows Vista API)
//_exit(1);
// send keyboard input to safely unblock the CLI thread
INPUT_RECORD b [ 5 ];
HANDLE hStdIn = GetStdHandle ( STD_INPUT_HANDLE );
b [ 0 ]. EventType = KEY_EVENT ;
b [ 0 ]. Event . KeyEvent . bKeyDown = TRUE ;
b [ 0 ]. Event . KeyEvent . uChar . AsciiChar = 'X' ;
b [ 0 ]. Event . KeyEvent . wVirtualKeyCode = 'X' ;
b [ 0 ]. Event . KeyEvent . wRepeatCount = 1 ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
b [ 1 ]. EventType = KEY_EVENT ;
b [ 1 ]. Event . KeyEvent . bKeyDown = FALSE ;
b [ 1 ]. Event . KeyEvent . uChar . AsciiChar = 'X' ;
b [ 1 ]. Event . KeyEvent . wVirtualKeyCode = 'X' ;
b [ 1 ]. Event . KeyEvent . wRepeatCount = 1 ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
b [ 2 ]. EventType = KEY_EVENT ;
b [ 2 ]. Event . KeyEvent . bKeyDown = TRUE ;
b [ 2 ]. Event . KeyEvent . dwControlKeyState = 0 ;
b [ 2 ]. Event . KeyEvent . uChar . AsciiChar = '\r' ;
b [ 2 ]. Event . KeyEvent . wVirtualKeyCode = VK_RETURN ;
b [ 2 ]. Event . KeyEvent . wRepeatCount = 1 ;
b [ 2 ]. Event . KeyEvent . wVirtualScanCode = 0x1c ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
b [ 3 ]. EventType = KEY_EVENT ;
b [ 3 ]. Event . KeyEvent . bKeyDown = FALSE ;
b [ 3 ]. Event . KeyEvent . dwControlKeyState = 0 ;
b [ 3 ]. Event . KeyEvent . uChar . AsciiChar = '\r' ;
b [ 3 ]. Event . KeyEvent . wVirtualKeyCode = VK_RETURN ;
b [ 3 ]. Event . KeyEvent . wVirtualScanCode = 0x1c ;
b [ 3 ]. Event . KeyEvent . wRepeatCount = 1 ;
DWORD numb ;
2010-05-13 00:15:21 +02:00
WriteConsoleInput ( hStdIn , b , 4 , & numb );
2009-10-17 15:51:44 -07:00
2009-08-08 12:12:56 -05:00
cliThread -> wait ();
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
#else
2009-10-17 15:51:44 -07:00
2009-08-08 12:12:56 -05:00
cliThread -> destroy ();
2009-10-17 15:51:44 -07:00
2009-08-08 12:12:56 -05:00
#endif
2009-10-17 15:51:44 -07:00
2009-08-08 12:12:56 -05:00
delete cliThread ;
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// for some unknown reason, unloading scripts here and not in worldrunnable
// fixes a memory leak related to detaching threads from the module
2010-01-19 11:36:05 +01:00
//UnloadScriptingModule();
2009-10-17 15:51:44 -07:00
2008-11-20 16:16:57 -06:00
// Exit the process with specified return value
return World :: GetExitCode ();
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/// Initialize connection to the databases
bool Master :: _StartDB ()
{
2009-05-04 11:39:43 -04:00
sLog . SetLogDB ( false );
2008-10-02 16:23:55 -05:00
std :: string dbstring ;
2009-10-17 15:51:44 -07:00
2009-03-20 22:17:39 +01:00
///- Get world database info from configuration file
dbstring = sConfig . GetStringDefault ( "WorldDatabaseInfo" , "" );
2010-06-21 23:58:27 +02:00
if ( dbstring . empty ())
2008-10-02 16:23:55 -05:00
{
2010-06-21 23:58:27 +02:00
sLog . outError ( "World database not specified in configuration file" );
2008-10-02 16:23:55 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
///- Initialise the world database
2010-06-21 23:58:27 +02:00
if ( ! WorldDatabase . Initialize ( dbstring . c_str ()))
2008-10-02 16:23:55 -05:00
{
sLog . outError ( "Cannot connect to world database %s" , dbstring . c_str ());
return false ;
}
2009-10-17 15:51:44 -07:00
2009-03-20 22:17:39 +01:00
///- Get character database info from configuration file
dbstring = sConfig . GetStringDefault ( "CharacterDatabaseInfo" , "" );
2010-06-21 23:58:27 +02:00
if ( dbstring . empty ())
2008-10-02 16:23:55 -05:00
{
2010-06-21 23:58:27 +02:00
sLog . outError ( "Character database not specified in configuration file" );
2008-10-02 16:23:55 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
///- Initialise the Character database
2010-06-21 23:58:27 +02:00
if ( ! CharacterDatabase . Initialize ( dbstring . c_str ()))
2008-10-02 16:23:55 -05:00
{
sLog . outError ( "Cannot connect to Character database %s" , dbstring . c_str ());
return false ;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
///- Get login database info from configuration file
2010-05-08 05:03:32 +02:00
dbstring = sConfig . GetStringDefault ( "LoginDatabaseInfo" , "" );
2010-06-21 23:58:27 +02:00
if ( dbstring . empty ())
2008-10-02 16:23:55 -05:00
{
sLog . outError ( "Login database not specified in configuration file" );
return false ;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
///- Initialise the login database
2010-06-21 23:58:27 +02:00
if ( ! LoginDatabase . Initialize ( dbstring . c_str ()))
2008-10-02 16:23:55 -05:00
{
sLog . outError ( "Cannot connect to login database %s" , dbstring . c_str ());
return false ;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
///- Get the realm Id from the configuration file
realmID = sConfig . GetIntDefault ( "RealmID" , 0 );
2010-06-21 23:58:27 +02:00
if ( ! realmID )
2008-10-02 16:23:55 -05:00
{
sLog . outError ( "Realm ID not defined in configuration file" );
return false ;
}
sLog . outString ( "Realm running as realm ID %d" , realmID );
2009-10-17 15:51:44 -07:00
2009-05-04 11:39:43 -04:00
///- Initialize the DB logging system
2010-05-29 03:16:39 +02:00
sLog . SetLogDBLater ( sConfig . GetBoolDefault ( "EnableLogDB" , false )); // set var to enable DB logging once startup finished.
sLog . SetLogDB ( false );
sLog . SetRealmID ( realmID );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
///- Clean the database before starting
clearOnlineAccounts ();
2009-10-17 15:51:44 -07:00
2009-03-25 15:52:28 +01:00
///- Insert version info into DB
2009-09-10 22:40:40 +02:00
WorldDatabase . PExecute ( "UPDATE version SET core_version = '%s', core_revision = '%s'" , _FULLVERSION , _REVISION );
2009-10-17 15:51:44 -07:00
2008-11-02 16:53:46 -06:00
sWorld . LoadDBVersion ();
2009-10-17 15:51:44 -07:00
2009-04-09 17:57:57 -05:00
sLog . outString ( "Using World DB: %s" , sWorld . GetDBVersion ());
sLog . outString ( "Using creature EventAI: %s" , sWorld . GetCreatureEventAIVersion ());
2008-10-02 16:23:55 -05:00
return true ;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
/// Clear 'online' status for all accounts with characters in this realm
void Master :: clearOnlineAccounts ()
{
// Cleanup online status for characters hosted at current realm
/// \todo Only accounts with characters logged on *this* realm should have online status reset. Move the online column from 'account' to 'realmcharacters'?
2010-05-08 05:03:32 +02:00
LoginDatabase . PExecute (
2008-10-02 16:23:55 -05:00
"UPDATE account SET online = 0 WHERE online > 0 "
"AND id IN (SELECT acctid FROM realmcharacters WHERE realmid = '%d')" , realmID );
2009-10-17 15:51:44 -07:00
2008-12-19 16:05:13 -06:00
CharacterDatabase . Execute ( "UPDATE characters SET online = 0 WHERE online<>0" );
2009-10-17 15:51:44 -07:00
2009-03-20 22:17:39 +01:00
// Battleground instance ids reset at server restart
2009-08-13 04:42:19 -04:00
CharacterDatabase . Execute ( "UPDATE character_battleground_data SET instance_id = 0" );
2008-10-02 16:23:55 -05:00
}