root/trunk/src/trinityrealm/Main.cpp @ 34

Revision 2, 9.8 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

Line 
1/*
2 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18
19/// \addtogroup realmd Realm Daemon
20/// @{
21/// \file
22
23#include "Common.h"
24#include "Database/DatabaseEnv.h"
25#include "RealmList.h"
26
27#include "Config/ConfigEnv.h"
28#include "Log.h"
29#include "sockets/ListenSocket.h"
30#include "AuthSocket.h"
31#include "SystemConfig.h"
32#include "Util.h"
33
34// Format is YYYYMMDDRR where RR is the change in the conf file
35// for that day.
36#ifndef _REALMDCONFVERSION
37# define _REALMDCONFVERSION 2007062001
38#endif
39
40#ifndef _TRINITY_REALM_CONFIG
41# define _TRINITY_REALM_CONFIG  "trinityrealm.conf"
42#endif //_TRINITY_REALM_CONFIG
43
44#ifdef WIN32
45#include "ServiceWin32.h"
46char serviceName[] = "realmd";
47char serviceLongName[] = "MaNGOS realmd service";
48char serviceDescription[] = "Massive Network Game Object Server";
49/*
50 * -1 - not in service mode
51 *  0 - stopped
52 *  1 - running
53 *  2 - paused
54 */
55int m_ServiceStatus = -1;
56#endif
57
58bool StartDB(std::string &dbstring);
59void UnhookSignals();
60void HookSignals();
61
62bool stopEvent = false;                                     ///< Setting it to true stops the server
63RealmList m_realmList;                                      ///< Holds the list of realms for this server
64
65DatabaseType dbRealmServer;                                 ///< Accessor to the realm server database
66
67/// Print out the usage string for this program on the console.
68void usage(const char *prog)
69{
70    sLog.outString("Usage: \n %s [<options>]\n"
71        "    -c config_file           use config_file as configuration file\n\r"
72        #ifdef WIN32
73        "    Running as service functions:\n\r"
74        "    --service                run as service\n\r"
75        "    -s install               install service\n\r"
76        "    -s uninstall             uninstall service\n\r"
77        #endif
78        ,prog);
79}
80
81/// Launch the realm server
82extern int main(int argc, char **argv)
83{
84    ///- Command line parsing to get the configuration file name
85    char const* cfg_file = _TRINITY_REALM_CONFIG;
86    int c=1;
87    while( c < argc )
88    {
89        if( strcmp(argv[c],"-c") == 0)
90        {
91            if( ++c >= argc )
92            {
93                sLog.outError("Runtime-Error: -c option requires an input argument");
94                usage(argv[0]);
95                return 1;
96            }
97            else
98                cfg_file = argv[c];
99        }
100
101        #ifdef WIN32
102        ////////////
103        //Services//
104        ////////////
105        if( strcmp(argv[c],"-s") == 0)
106        {
107            if( ++c >= argc )
108            {
109                sLog.outError("Runtime-Error: -s option requires an input argument");
110                usage(argv[0]);
111                return 1;
112            }
113            if( strcmp(argv[c],"install") == 0)
114            {
115                if (WinServiceInstall())
116                    sLog.outString("Installing service");
117                return 1;
118            }
119            else if( strcmp(argv[c],"uninstall") == 0)
120            {
121                if(WinServiceUninstall())
122                    sLog.outString("Uninstalling service");
123                return 1;
124            }
125            else
126            {
127                sLog.outError("Runtime-Error: unsupported option %s",argv[c]);
128                usage(argv[0]);
129                return 1;
130            }
131        }
132        if( strcmp(argv[c],"--service") == 0)
133        {
134            WinServiceRun();
135        }
136        ////
137        #endif
138        ++c;
139    }
140
141    if (!sConfig.SetSource(cfg_file))
142    {
143        sLog.outError("Could not find configuration file %s.", cfg_file);
144        return 1;
145    }
146    sLog.outString("Using configuration file %s.", cfg_file);
147
148    ///- Check the version of the configuration file
149    uint32 confVersion = sConfig.GetIntDefault("ConfVersion", 0);
150    if (confVersion < _REALMDCONFVERSION)
151    {
152        sLog.outError("*****************************************************************************");
153        sLog.outError(" WARNING: Your trinityrealm.conf version indicates your conf file is out of date!");
154        sLog.outError("          Please check for updates, as your current default values may cause");
155        sLog.outError("          strange behavior.");
156        sLog.outError("*****************************************************************************");
157        clock_t pause = 3000 + clock();
158
159        while (pause > clock()) {}
160    }
161
162    sLog.outString( "%s (realm-daemon)", _FULLVERSION );
163    sLog.outString( "<Ctrl-C> to stop.\n" );
164
165    /// realmd PID file creation
166    std::string pidfile = sConfig.GetStringDefault("PidFile", "");
167    if(!pidfile.empty())
168    {
169        uint32 pid = CreatePIDFile(pidfile);
170        if( !pid )
171        {
172            sLog.outError( "Cannot create PID file %s.\n", pidfile.c_str() );
173            return 1;
174        }
175
176        sLog.outString( "Daemon PID: %u\n", pid );
177    }
178
179    ///- Initialize the database connection
180    std::string dbstring;
181    if(!StartDB(dbstring))
182        return 1;
183
184    ///- Get the list of realms for the server
185    m_realmList.Initialize(sConfig.GetIntDefault("RealmsStateUpdateDelay", 20));
186    if (m_realmList.size() == 0)
187    {
188        sLog.outError("No valid realms specified.");
189        return 1;
190    }
191
192    ///- Launch the listening network socket
193    port_t rmport = sConfig.GetIntDefault( "RealmServerPort", DEFAULT_REALMSERVER_PORT );
194    std::string bind_ip = sConfig.GetStringDefault("BindIP", "0.0.0.0");
195
196    SocketHandler h;
197    ListenSocket<AuthSocket> authListenSocket(h);
198    if ( authListenSocket.Bind(bind_ip.c_str(),rmport))
199    {
200        sLog.outError( "MaNGOS realmd can not bind to %s:%d",bind_ip.c_str(), rmport );
201        return 1;
202    }
203
204    h.Add(&authListenSocket);
205
206    ///- Catch termination signals
207    HookSignals();
208
209    ///- Handle affinity for multiple processors and process priority on Windows
210    #ifdef WIN32
211    {
212        HANDLE hProcess = GetCurrentProcess();
213
214        uint32 Aff = sConfig.GetIntDefault("UseProcessors", 0);
215        if(Aff > 0)
216        {
217            ULONG_PTR appAff;
218            ULONG_PTR sysAff;
219
220            if(GetProcessAffinityMask(hProcess,&appAff,&sysAff))
221            {
222                ULONG_PTR curAff = Aff & appAff;            // remove non accessible processors
223
224                if(!curAff )
225                {
226                    sLog.outError("Processors marked in UseProcessors bitmask (hex) %x not accessible for realmd. Accessible processors bitmask (hex): %x",Aff,appAff);
227                }
228                else
229                {
230                    if(SetProcessAffinityMask(hProcess,curAff))
231                        sLog.outString("Using processors (bitmask, hex): %x", curAff);
232                    else
233                        sLog.outError("Can't set used processors (hex): %x", curAff);
234                }
235            }
236            sLog.outString();
237        }
238
239        bool Prio = sConfig.GetBoolDefault("ProcessPriority", false);
240
241        if(Prio)
242        {
243            if(SetPriorityClass(hProcess,HIGH_PRIORITY_CLASS))
244                sLog.outString("TrinityRealm process priority class set to HIGH");
245            else
246                sLog.outError("ERROR: Can't set realmd process priority class.");
247            sLog.outString();
248        }
249    }
250    #endif
251
252    // maximum counter for next ping
253    uint32 numLoops = (sConfig.GetIntDefault( "MaxPingTime", 30 ) * (MINUTE * 1000000 / 100000));
254    uint32 loopCounter = 0;
255
256    ///- Wait for termination signal
257    while (!stopEvent)
258    {
259
260        h.Select(0, 100000);
261
262        if( (++loopCounter) == numLoops )
263        {
264            loopCounter = 0;
265            sLog.outDetail("Ping MySQL to keep connection alive");
266            delete dbRealmServer.Query("SELECT 1 FROM realmlist LIMIT 1");
267        }
268#ifdef WIN32
269        if (m_ServiceStatus == 0) stopEvent = true;
270        while (m_ServiceStatus == 2) Sleep(1000);
271#endif
272    }
273
274    ///- Wait for the delay thread to exit
275    dbRealmServer.HaltDelayThread();
276
277    ///- Remove signal handling before leaving
278    UnhookSignals();
279
280    sLog.outString( "Halting process..." );
281    return 0;
282}
283
284/// Handle termination signals
285/** Put the global variable stopEvent to 'true' if a termination signal is caught **/
286void OnSignal(int s)
287{
288    switch (s)
289    {
290        case SIGINT:
291        case SIGTERM:
292            stopEvent = true;
293            break;
294        #ifdef _WIN32
295        case SIGBREAK:
296            stopEvent = true;
297            break;
298        #endif
299    }
300
301    signal(s, OnSignal);
302}
303
304/// Initialize connection to the database
305bool StartDB(std::string &dbstring)
306{
307    if(!sConfig.GetString("LoginDatabaseInfo", &dbstring))
308    {
309        sLog.outError("Database not specified");
310        return false;
311    }
312
313    sLog.outString("Database: %s", dbstring.c_str() );
314    if(!dbRealmServer.Initialize(dbstring.c_str()))
315    {
316        sLog.outError("Cannot connect to database");
317        return false;
318    }
319
320    return true;
321}
322
323/// Define hook 'OnSignal' for all termination signals
324void HookSignals()
325{
326    signal(SIGINT, OnSignal);
327    signal(SIGTERM, OnSignal);
328    #ifdef _WIN32
329    signal(SIGBREAK, OnSignal);
330    #endif
331}
332
333/// Unhook the signals before leaving
334void UnhookSignals()
335{
336    signal(SIGINT, 0);
337    signal(SIGTERM, 0);
338    #ifdef _WIN32
339    signal(SIGBREAK, 0);
340    #endif
341
342}
343
344/// @}
Note: See TracBrowser for help on using the browser.