#include <service.h>
service_howto
Temporary command line arguments :
Olivier Cado
Nevrax France
Definition at line 177 of file service.h.
get methods. These methods provide a way to read internal service variables. | |
| std::string | getArg (char argName) |
| const std::vector< std::string > & | getArgs () const |
| Returns arguments of the program pass from the user to the program using parameters (ie: "myprog param1 param2"). | |
| CCallbackNetBase::TRecordingState | getRecordingState () const |
| Returns the recording state (don't needed if you use layer5). | |
| const std::string & | getServiceAliasName () const |
| Returns the current service alias name setted by AES. | |
| TServiceId | getServiceId () const |
| Returns the service identifier. | |
| const std::string & | getServiceLongName () const |
| Returns the current service long name (ie: test_serivce). | |
| const std::string & | getServiceShortName () const |
| Returns the current service short name (ie: TS). | |
| std::string | getServiceUnifiedName () const |
| Returns the current service unified name that is alias/short-id or short-id if alias is empty. | |
| sint | getStatus () const |
| Returns the status. | |
| bool | haveArg (char argName) |
| Returns true if the argument if present in the command line (ie: haveArg('p') will return true if -p is in the command line). | |
| IService * | getInstance () |
| Returns the instance of the service to access to methods/variables class. | |
variables. These variables are used by the internal system. | |
| std::string | _AliasName |
| std::vector< std::string > | _Args |
| Array of arguments pass from the command line. | |
| TUnifiedCallbackItem * | _CallbackArray |
| uint | _CallbackArraySize |
| bool | _DontUseAES |
| true if the service don't use the admin executor service | |
| bool | _DontUseNS |
| true if the service don't use the naming service | |
| bool | _Initialized |
| true if the service initialisation is passed | |
| std::string | _LongName |
| CCallbackNetBase::TRecordingState | _RecordingState |
| Recording state. | |
| bool | _ResetMeasures |
| Require to reset the hierarchical timer. | |
| uint32 | _ShardId |
| Shard Id. | |
| std::string | _ShortName |
| Current service name sets by the actual service when declaring NLNET_SERVICE_MAIN. | |
| TServiceId | _SId |
| the service id of this sevice | |
| sint | _Status |
| the status of this service (the status is give to the at the release time) | |
| NLMISC::TTime | _UpdateTimeout |
| Select timeout value in milliseconds between to call of user update(). | |
| NLMISC::CVariable< std::string > | ConfigDirectory |
| The directory where the configfile is. | |
| NLMISC::CVariable< uint16 > | ListeningPort |
| Listening port of this service. | |
| NLMISC::CVariable< std::string > | LogDirectory |
| The directory where the logfiles are. | |
| NLMISC::CVariable< std::string > | RunningDirectory |
| The directory where the service is running. | |
| NLMISC::CVariable< std::string > | Version |
| IService * | _Instance = NULL |
| Instance of this service (singleton). | |
Public Member Functions | |
| uint16 | getPort () |
| uint32 | getShardId () const |
| void | setVersion (const std::string &version) |
set methods. These methods provide a way to modify internal service variables. | |
| void | exit (sint code=0x10) |
| void | setStatus (sint status) |
| void | setUpdateTimeout (NLMISC::TTime timeout) |
User overload methods. These methods can be overload by the user do handle init, update and release operation. | |
| virtual void | init () |
| Initializes the service (must be called before the first call to update()). | |
| virtual void | release () |
| Finalization. Release the service. For example, this founction free all allocation made in the init() function. | |
| virtual bool | update () |
| This function is called every "frame" (you must call init() before). It returns false if the service is stopped. | |
private methods. These methods are used by internal system but can't be put in private, don't use them. | |
| IService () | |
| Ctor. You must not inherit ctor but overload init() function. | |
| sint | main (const char *serviceShortName, const char *serviceLongName, uint16 servicePort, const char *configDir, const char *logDir, const char *compilationDate) |
| This main is called by the macro (service5 says if we have to use layer5 or not). | |
| void | requireResetMeasures () |
| Require to reset the hierarchical timer. | |
| void | setArgs (const char *args) |
| Sets the command line and init _Args variable. You must call this before calling main(). | |
| void | setArgs (int argc, const char **argv) |
| Sets the command line and init _Args variable. You must call this before calling main(). | |
| void | setCallbackArray (TUnifiedCallbackItem *array, uint nbelem) |
| Sets the default callback array given from the macro. | |
| virtual | ~IService () |
| Dtor. You must not inherit dtor but overload release() function. | |
Data Fields | |
| NLMISC::CVariable< std::string > | SaveFilesDirectory |
| NLMISC::CWindowDisplayer * | WindowDisplayer |
| The window displayer instance. | |
| NLMISC::CVariable< std::string > | WriteFilesDirectory |
variables. These variables can be read/modified by the user. | |
| NLMISC::CLog | CommandLog |
| NLMISC::CConfigFile | ConfigFile |
Private Member Functions | |
methods. These methods are used by internal system. | |
| void | setRecordingState (CCallbackNetBase::TRecordingState rec) |
| Changes the recording state (use if you know what you are doing). | |
Friends | |
| void | cbAESConnection (const std::string &serviceName, uint16 sid, void *arg) |
| void | cbDirectoryChanged (const NLMISC::IVariable &var) |
| void | cbReceiveShardId (NLNET::CMessage &msgin, const std::string &serviceName, uint16 serviceId) |
| struct | getWinDisplayerInfoClass |
| void | serviceGetView (uint32 rid, const std::string &rawvarpath, std::vector< std::string > &vara, std::vector< std::string > &vala) |
| struct | serviceInfoClass |
|
|
Ctor. You must not inherit ctor but overload init() function.
Definition at line 278 of file service.cpp. References NLNET::cbDirectoryChanged().
00278 : 00279 WindowDisplayer(0), 00280 WriteFilesDirectory("WriteFilesDirectory", "directory where to save generic shard information (packed_sheets for example)", ".", 0, true, cbDirectoryChanged), 00281 SaveFilesDirectory("SaveFilesDirectory", "directory where to save specific shard information (shard time for example)", ".", 0, true, cbDirectoryChanged), 00282 ListeningPort("ListeningPort", "listening port for this service", 0, 0, true), 00283 _RecordingState(CCallbackNetBase::Off), 00284 _UpdateTimeout(100), 00285 _SId(0), 00286 _Status(0), 00287 _Initialized(false), 00288 ConfigDirectory("ConfigDirectory", "directory where config files are", ".", 0, true, cbDirectoryChanged), 00289 LogDirectory("LogDirectory", "directory where the service is logging", ".", 0, true, cbDirectoryChanged), 00290 RunningDirectory("RunningDirectory", "directory where the service is running on", ".", 0, true, cbDirectoryChanged), 00291 Version("Version", "Version of the shard", ""), 00292 _CallbackArray (0), 00293 _CallbackArraySize (0), 00294 _DontUseNS(false), 00295 _DontUseAES(false), 00296 _ResetMeasures(false) 00297 { 00298 // Singleton 00299 _Instance = this; 00300 } |
|
|
Dtor. You must not inherit dtor but overload release() function.
Definition at line 300 of file service.h.
00300 {}
|
|
|
Call this function if you want the service quits next loop. The code will be returned outside of the application.
Definition at line 1333 of file service.cpp. References NLNET::ExitSignalAsked, nlinfo, and sint.
01334 {
01335 nlinfo ("SERVICE: Somebody called IService::exit(), I have to quit");
01336 ExitSignalAsked = code;
01337 }
|
|
|
Returns the parameter linked to an option (ie: getArg('p') will return "toto" if -ptoto is in the command line) It'll thrown an Exception if the argName is not found Definition at line 319 of file service.cpp. References uint32. Referenced by main().
00320 {
00321 for (uint32 i = 0; i < _Args.size(); i++)
00322 {
00323 if (_Args[i].size() >= 2 && _Args[i][0] == '-')
00324 {
00325 if (_Args[i][1] == argName)
00326 {
00327 return _Args[i].substr(2);
00328 }
00329 }
00330 }
00331 throw Exception ("Parameter '-%c' is not found in command line", argName);
00332 }
|
|
|
Returns arguments of the program pass from the user to the program using parameters (ie: "myprog param1 param2").
Definition at line 221 of file service.h.
00221 { return _Args; }
|
|
|
Returns the instance of the service to access to methods/variables class.
Definition at line 200 of file service.h. References nlassert. Referenced by NLAILINK::getLocalServerID().
|
|
|
Definition at line 317 of file service.h. References ListeningPort, and uint16.
00317 { return ListeningPort; }
|
|
|
Returns the recording state (don't needed if you use layer5).
Definition at line 238 of file service.h.
00238 { return _RecordingState; }
|
|
|
Returns the current service alias name setted by AES.
Definition at line 209 of file service.h. References _AliasName.
00209 { return _AliasName; };
|
|
|
Returns the service identifier.
Definition at line 215 of file service.h. References _SId, and NLNET::TServiceId.
00215 { return _SId; }
|
|
|
Returns the current service long name (ie: test_serivce).
Definition at line 206 of file service.h. References _LongName. Referenced by main().
00206 { return _LongName; };
|
|
|
Returns the current service short name (ie: TS).
Definition at line 203 of file service.h. References _ShortName.
00203 { return _ShortName; };
|
|
|
Returns the current service unified name that is alias/short-id or short-id if alias is empty.
Definition at line 1348 of file service.cpp. References _AliasName, _ShortName, _SId, nlassert, res, and NLMISC::toString().
01349 {
01350 nlassert (!_ShortName.empty());
01351 string res;
01352 if (!_AliasName.empty())
01353 {
01354 res = _AliasName+"/";
01355 }
01356 res += _ShortName;
01357 if (_SId != 0)
01358 {
01359 res += "-";
01360 res += toString (_SId);
01361 }
01362 return res;
01363 }
|
|
|
Definition at line 319 of file service.h. References _ShardId, and uint32.
00319 { return _ShardId; }
|
|
|
Returns the status.
Definition at line 218 of file service.h. Referenced by main().
00218 { return _Status; }
|
|
|
Returns true if the argument if present in the command line (ie: haveArg('p') will return true if -p is in the command line).
Definition at line 304 of file service.cpp. References uint32. Referenced by main().
|
|
|
Initializes the service (must be called before the first call to update()).
Definition at line 185 of file service.h. Referenced by main().
00185 {}
|
|
||||||||||||||||||||||||||||
|
This main is called by the macro (service5 says if we have to use layer5 or not).
Layer5 Startup Definition at line 419 of file service.cpp. References _AliasName, _CallbackArraySize, _DontUseAES, _DontUseNS, _LongName, _ResetMeasures, _ShardId, _ShortName, _SId, _UpdateTimeout, CTimeoutAssertionThread::activate(), NLNET::CUnifiedNetwork::addCallbackArray(), NLMISC::CLog::addDisplayer(), NLMISC::CConfigFile::CVar::asInt(), NLMISC::AssertLog, NLNET::CInetAddress::asString(), NLMISC::CConfigFile::CVar::asString(), NLMISC::beep(), NLNET::Bench(), NLNET::builtinServiceCallbacks, NLNET::cbExecuteCommands(), NLNET::cbLogFilter(), NLMISC::changeLogDirectory(), NLMISC::CMemDisplayer::clear(), CommandLog, NLNET::CompilationDate, ConfigDirectory, ConfigFile, NLMISC::CWindowDisplayer::create(), NLMISC::CWindowDisplayer::createLabel(), NLMISC::DebugLog, CTimeoutAssertionThread::desactivate(), NLMISC::CLog::displayNL(), NLMISC::ErrorLog, NLMISC::CConfigFile::exists(), NLNET::ExitSignalAsked, getArg(), NLNET::CUnifiedNetwork::getInstance(), getServiceLongName(), getStatus(), NLMISC::CConfigFile::getVar(), NLMISC::CConfigFile::getVarPtr(), H_AUTO, haveArg(), NLMISC::InfoLog, init(), NLMISC::IVariable::init(), NLNET::initAdmin(), NLNET::initSignal(), IsDebuggerPresent, NLNET::LaunchingDate, ListeningPort, NLMISC::CConfigFile::load(), NLMISC::CMemDisplayer::lockStrings(), LogDirectory, NLNET::MyTAT, NLNET::NbUserUpdate, NLNET::NegFiltersNames, NLNET::NetSpeedLoop(), nlassert, nldebug, nlerror, nlinfo, NLMISC::nlSleep(), nlwarning, release(), NLMISC::CLog::removeDisplayer(), RunningDirectory, SaveFilesDirectory, NLNET::sendEmail(), NLMISC::setAssert(), NLMISC::CConfigFile::setCallback(), NLNET::setDefaultEmailParams(), NLMISC::CWindowDisplayer::setLabel(), NLMISC::CLog::setProcessName(), NLMISC::setReportEmailFunction(), NLMISC::CEntityId::setServiceId(), setStatus(), NLMISC::CWindowDisplayer::setTitleBar(), sint, sint32, size, NLMISC::CConfigFile::CVar::size(), NLMISC::strupr(), NLMISC::toString(), NLMISC::TTime, uint, uint16, uint32, uint64, uint8, NLMISC::CMemDisplayer::unlockStrings(), NLMISC::CWindowDisplayer::update(), update(), NLNET::updateAdmin(), NLNET::UserSpeedLoop(), v, w, NLMISC::WarningLog, WindowDisplayer, x, and y.
00420 {
00421 bool userInitCalled = false;
00422 // bool resyncEvenly = false;
00423 CConfigFile::CVar *var = NULL;
00424
00425 // a short name service can't be a number
00426 nlassert (atoi(serviceShortName) == 0);
00427
00428 try
00429 {
00430 //
00431 // Init parameters
00432 //
00433
00434 _ShortName = serviceShortName;
00435 CLog::setProcessName (_ShortName);
00436
00437 // get the path where to run the service if any in the command line
00438 if (haveArg('A'))
00439 RunningDirectory = CPath::standardizePath(getArg('A'));
00440
00441 ConfigDirectory = CPath::standardizePath(configDir);
00442 LogDirectory = CPath::standardizePath(logDir);
00443 _LongName = serviceLongName;
00444
00445 CompilationDate = compilationDate;
00446
00447 LaunchingDate = CTime::getSecondsSince1970();
00448
00449 ListeningPort = servicePort;
00450
00451 setReportEmailFunction ((void*)sendEmail);
00452 setDefaultEmailParams ("gw.nevrax.com", "", "lecroart@nevrax.com");
00453
00454
00455 //
00456 // Load the config file
00457 //
00458
00459 // get the config file dir if any in the command line
00460 if (haveArg('C'))
00461 ConfigDirectory = CPath::standardizePath(getArg('C'));
00462
00463 string cfn = ConfigDirectory.c_str() + _LongName + ".cfg";
00464 if (!CFile::fileExists(ConfigDirectory.c_str() + _LongName + ".cfg"))
00465 {
00466 // check if the default exists
00467 if (!CFile::fileExists(ConfigDirectory.c_str() + _LongName + "_default.cfg"))
00468 {
00469 nlerror ("SERVICE: The config file '%s' is not found, neither the default one, can't launch the service", cfn.c_str());
00470 }
00471 else
00472 {
00473 // create the basic .cfg that link the default one
00474 FILE *fp = fopen (cfn.c_str(), "w");
00475 if (fp == NULL)
00476 {
00477 nlerror ("SERVICE: Can't create config file '%s'", cfn.c_str());
00478 }
00479 fprintf(fp, "// link the default config file for %s\n", _LongName.c_str());
00480 fprintf(fp, "RootConfigFilename = \"%s_default.cfg\";\n", _LongName.c_str());
00481 fclose (fp);
00482 }
00483 }
00484
00485 ConfigFile.load (cfn);
00486
00487 // setup variable with config file variable
00488 IVariable::init (ConfigFile);
00489
00490 // we have to call this again because the config file can changed this variable but the cmd line is more prioritary
00491 if (haveArg('A'))
00492 RunningDirectory = CPath::standardizePath(getArg('A'));
00493
00494
00495 //
00496 // Init debug/log stuffs (must be first things otherwise we can't log if errors)
00497 //
00498
00499 // get the log dir if any in the command line
00500 if (haveArg('L'))
00501 LogDirectory = CPath::standardizePath(getArg('L'));
00502
00503 changeLogDirectory (LogDirectory);
00504
00505 // we create the log with service name filename ("test_service.log" for example)
00506 fd.setParam (LogDirectory.c_str() + _LongName + ".log", false);
00507
00508 DebugLog->addDisplayer (&fd);
00509 InfoLog->addDisplayer (&fd);
00510 WarningLog->addDisplayer (&fd);
00511 AssertLog->addDisplayer (&fd);
00512 ErrorLog->addDisplayer (&fd);
00513 CommandLog.addDisplayer (&fd, true);
00514
00515 //
00516 // Init the hierarchical timer
00517 //
00518
00519 CHTimer::startBench(false, true);
00520 CHTimer::endBench();
00521
00522
00523 //
00524 // Set the assert mode
00525 //
00526
00527 if (ConfigFile.exists ("Assert"))
00528 setAssert (ConfigFile.getVar("Assert").asInt() == 1);
00529
00530 //
00531 // Set the shard Id
00532 //
00533
00534 if ((var = ConfigFile.getVarPtr("NoWSShardId")) != NULL)
00535 {
00536 _ShardId = var->asInt();
00537 }
00538 else
00539 {
00540 // something high enough as default
00541 _ShardId = 666;
00542 }
00543
00544 //
00545 // Set the negative filter from the config file
00546 //
00547
00548 for(const char **name = NegFiltersNames; *name; name++)
00549 {
00550 if ((var = ConfigFile.getVarPtr (*name)) != NULL)
00551 {
00552 ConfigFile.setCallback (*name, cbLogFilter);
00553 cbLogFilter(*var);
00554 }
00555 }
00556
00557 ConfigFile.setCallback ("Commands", cbExecuteCommands);
00558 if ((var = ConfigFile.getVarPtr ("Commands")) != NULL)
00559 {
00560 cbExecuteCommands(*var);
00561 }
00562
00563
00564 //
00565 // Create the window if needed
00566 //
00567
00568 if ((var = ConfigFile.getVarPtr ("WindowStyle")) != NULL)
00569 {
00570 string disp = var->asString ();
00571 #ifdef NL_USE_GTK
00572 if (disp == "GTK")
00573 {
00574 WindowDisplayer = new CGtkDisplayer ("DEFAULT_WD");
00575 }
00576 #endif // NL_USE_GTK
00577
00578 #ifdef NL_OS_WINDOWS
00579 if (disp == "WIN")
00580 {
00581 WindowDisplayer = new CWinDisplayer ("DEFAULT_WD");
00582 }
00583 #endif // NL_OS_WINDOWS
00584
00585 if (WindowDisplayer == NULL && disp != "NONE")
00586 {
00587 nlwarning ("SERVICE: Unknown value for the WindowStyle (should be GTK, WIN or NONE), use no window displayer");
00588 }
00589 }
00590
00591 vector <pair<string,uint> > displayedVariables;
00592 //uint speedNetLabel, speedUsrLabel, rcvLabel, sndLabel, rcvQLabel, sndQLabel, scrollLabel;
00593 if (WindowDisplayer != NULL)
00594 {
00595 //
00596 // Init window param if necessary
00597 //
00598
00599 sint x=-1, y=-1, w=-1, h=-1, fs=10, history=-1;
00600 bool iconified = false, ww = false;
00601 string fn;
00602
00603 if ((var = ConfigFile.getVarPtr("XWinParam")) != NULL) x = var->asInt();
00604 if ((var = ConfigFile.getVarPtr("YWinParam")) != NULL) y = var->asInt();
00605 if ((var = ConfigFile.getVarPtr("WWinParam")) != NULL) w = var->asInt();
00606 if ((var = ConfigFile.getVarPtr("HWinParam")) != NULL) h = var->asInt();
00607 if ((var = ConfigFile.getVarPtr("HistoryWinParam")) != NULL) history = var->asInt();
00608 if ((var = ConfigFile.getVarPtr("IWinParam")) != NULL) iconified = var->asInt() == 1;
00609 if ((var = ConfigFile.getVarPtr("FontSize")) != NULL) fs = var->asInt();
00610 if ((var = ConfigFile.getVarPtr("FontName")) != NULL) fn = var->asString();
00611 if ((var = ConfigFile.getVarPtr("WordWrap")) != NULL) ww = var->asInt() == 1;
00612
00613 if (haveArg('I')) iconified = true;
00614
00615 WindowDisplayer->create (string("*INIT* ") + _ShortName + " " + _LongName, iconified, x, y, w, h, history, fs, fn, ww, &CommandLog);
00616
00617 DebugLog->addDisplayer (WindowDisplayer);
00618 InfoLog->addDisplayer (WindowDisplayer);
00619 WarningLog->addDisplayer (WindowDisplayer);
00620 ErrorLog->addDisplayer (WindowDisplayer);
00621 AssertLog->addDisplayer (WindowDisplayer);
00622 CommandLog.addDisplayer(WindowDisplayer, true);
00623
00624 // adding default displayed variables
00625 displayedVariables.push_back(make_pair(string("NetLop|NetSpeedLoop"), WindowDisplayer->createLabel ("NetLop")));
00626 displayedVariables.push_back(make_pair(string("UsrLop|UserSpeedLoop"), WindowDisplayer->createLabel ("UsrLop")));
00627 // displayedVariables.push_back(make_pair(string("Rcv|ReceivedBytes"), WindowDisplayer->createLabel ("Rcv")));
00628 // displayedVariables.push_back(make_pair(string("Snd|SentBytes"), WindowDisplayer->createLabel ("Snd")));
00629 // displayedVariables.push_back(make_pair(string("RcvQ|ReceivedQueueSize"), WindowDisplayer->createLabel ("RcvQ")));
00630 // displayedVariables.push_back(make_pair(string("SndQ|SentQueueSize"), WindowDisplayer->createLabel ("SndQ")));
00631 displayedVariables.push_back(make_pair(string("|Scroller"), WindowDisplayer->createLabel ("NeL Rulez")));
00632
00633 CConfigFile::CVar *v = ConfigFile.getVarPtr("DisplayedVariables");
00634 if (v != NULL)
00635 {
00636 for (sint i = 0; i < v->size(); i++)
00637 {
00638 displayedVariables.push_back(make_pair(v->asString(i), WindowDisplayer->createLabel (v->asString(i).c_str())));
00639 }
00640 }
00641 }
00642
00643 nlinfo ("SERVICE: Starting Service '%s' using NeL ("__DATE__" "__TIME__") compiled %s", _ShortName.c_str(), CompilationDate.c_str());
00644 nlinfo ("SERVICE: On OS: %s", CSystemInfo::getOS().c_str());
00645
00646 setStatus (EXIT_SUCCESS);
00647
00648 //
00649 // Redirect signal if needed (in release mode only)
00650 //
00651
00652 #ifdef NL_OS_WINDOWS
00653 #ifdef NL_RELEASE
00654 initSignal();
00655 #else
00656 // don't install signal is the application is started in debug mode
00657 if (IsDebuggerPresent ())
00658 {
00659 //nlinfo("Running with the debugger, don't redirect signals");
00660 initSignal();
00661 }
00662 else
00663 {
00664 //nlinfo("Running without the debugger, redirect SIGINT signal");
00665 initSignal();
00666 }
00667 #endif
00668 #else // NL_OS_UNIX
00669 initSignal();
00670 #endif
00671
00672
00673 //
00674 // Ignore SIGPIPE (broken pipe) on unix system
00675 //
00676
00677 #ifdef NL_OS_UNIX
00678 // Ignore the SIGPIPE signal
00679 sigset_t SigList;
00680 bool IgnoredPipe = true;
00681 if (sigemptyset (&SigList) == -1)
00682 {
00683 perror("sigemptyset()");
00684 IgnoredPipe = false;
00685 }
00686
00687 if (sigaddset (&SigList, SIGPIPE) == -1)
00688 {
00689 perror("sigaddset()");
00690 IgnoredPipe = false;
00691 }
00692
00693 if (sigprocmask (SIG_BLOCK, &SigList, NULL) == -1)
00694 {
00695 perror("sigprocmask()");
00696 IgnoredPipe = false;
00697 }
00698 nldebug ("SERVICE: SIGPIPE %s", IgnoredPipe?"Ignored":"Not Ignored");
00699 #endif // NL_OS_UNIX
00700
00701
00702 //
00703 // Initialize the network system
00704 //
00705
00706 string localhost;
00707 try
00708 {
00709 // Initialize WSAStartup and network stuffs
00710 CSock::initNetwork();
00711
00712 // Get the localhost name
00713 localhost = CInetAddress::localHost().hostName();
00714 }
00715 catch (NLNET::ESocket &)
00716 {
00717 localhost = "<UnknownHost>";
00718 }
00719
00720 // Set the localhost name and service name to the logger
00721 CLog::setProcessName (localhost+"/"+_ShortName);
00722 nlinfo ("SERVICE: Host: %s", localhost.c_str());
00723
00724 //
00725 // Initialize server parameters
00726 //
00727
00728 // set the listen port if there are a port arg in the command line
00729 if (haveArg('P'))
00730 {
00731 ListeningPort = atoi(getArg('P').c_str());
00732 }
00733
00734 // set the aliasname if is present in the command line
00735 if (haveArg('N'))
00736 {
00737 _AliasName = getArg('N');
00738 }
00739
00740 // Load the recording state from the config file
00741 if ((var = ConfigFile.getVarPtr ("Rec")) != NULL)
00742 {
00743 string srecstate = var->asString();
00744 strupr( srecstate );
00745 if ( srecstate == "RECORD" )
00746 {
00747 _RecordingState = CCallbackNetBase::Record;
00748 nlinfo( "SERVICE: Service recording messages" );
00749 }
00750 else if ( srecstate == "REPLAY" )
00751 {
00752 _RecordingState = CCallbackNetBase::Replay;
00753 nlinfo( "SERVICE: Service replaying messages" );
00754 }
00755 else
00756 {
00757 _RecordingState = CCallbackNetBase::Off;
00758 }
00759 }
00760 else
00761 {
00762 // Not found
00763 _RecordingState = CCallbackNetBase::Off;
00764 }
00765
00766 // Load the default stream format
00767 if ((var = ConfigFile.getVarPtr ("StringMsgFormat")) != NULL)
00768 {
00769 CMessage::setDefaultStringMode( var->asInt() == 1 );
00770 }
00771 else
00772 {
00773 // Not found => binary
00774 CMessage::setDefaultStringMode( false );
00775 }
00776
00777 /*
00778 //
00779 // Layer4 Startup (Connect to the Naming Service (except for the NS itself and Login Service))
00780 //
00781
00782 if (IService::_ShortName != "NS" && IService::_ShortName != "LS" && IService::_ShortName != "AES" && IService::_ShortName != "AS")
00783 {
00784 bool ok = false;
00785 while (!ok)
00786 {
00787 // read the naming service address from the config file
00788 CInetAddress loc(ConfigFile.getVar("NSHost").asString(), ConfigFile.getVar("NSPort").asInt());
00789 try
00790 {
00791 CNetManager::init( &loc, _RecordingState );
00792 ok = true;
00793 }
00794 catch (ESocketConnectionFailed &)
00795 {
00796 nlwarning ("Could not connect to the Naming Service (%s). Retrying in a few seconds...", loc.asString().c_str());
00797 nlSleep (5000);
00798 }
00799 }
00800 }
00801 else
00802 {
00803 CNetManager::init( NULL, _RecordingState );
00804 }
00805 */
00806
00810
00811 // get the sid
00812 if ((var = ConfigFile.getVarPtr ("SId")) != NULL)
00813 {
00814 sint32 sid = var->asInt();
00815 if (sid<=0 || sid>255)
00816 {
00817 nlwarning("SERVICE: Bad SId value in the config file, %d is not in [0;255] range", sid);
00818 _SId = 0;
00819 }
00820 else
00821 {
00822 _SId = (uint8) sid;
00823 }
00824 }
00825 else
00826 {
00827 // ok, SId not found, use dynamic sid
00828 _SId = 0;
00829 }
00830
00831
00832 // look if we don't want to use NS
00833 if ((var = ConfigFile.getVarPtr ("DontUseNS")) != NULL)
00834 {
00835 // if we set the value in the config file, get it
00836 _DontUseNS = (var->asInt() == 1);
00837 }
00838 else
00839 {
00840 // if not, we use ns only if service is not ns, ls, aes, as
00841 _DontUseNS = false;
00842 }
00843
00844 //
00845 // Register all network associations (must be before the CUnifiedNetwork::getInstance()->init)
00846 //
00847
00848 if ((var = ConfigFile.getVarPtr ("Networks")) != NULL)
00849 {
00850 for (uint8 i = 0; i < var->size (); i++)
00851 CUnifiedNetwork::getInstance()->addNetworkAssociation (var->asString(i), i);
00852 }
00853
00854 if ((var = ConfigFile.getVarPtr ("DefaultNetworks")) != NULL)
00855 {
00856 for (uint8 i = 0; i < var->size (); i++)
00857 CUnifiedNetwork::getInstance()->addDefaultNetwork(var->asString(i));
00858 }
00859
00860 // normal setup for the common services
00861 if (!_DontUseNS)
00862 {
00863 bool ok = false;
00864 while (!ok)
00865 {
00866 string LSAddr;
00867
00868 if (haveArg('B'))
00869 {
00870 // if the naming service address is set on the command line, get it (overwrite the cfg)
00871 LSAddr = getArg('B');
00872 }
00873 else
00874 {
00875 // else read the naming service address from the config file
00876 LSAddr = ConfigFile.getVar ("NSHost").asString();
00877 }
00878
00879 // if there's no port to the NS, use the default one 50000
00880 if (LSAddr.find(":") == string::npos)
00881 LSAddr += ":50000";
00882
00883 CInetAddress loc(LSAddr);
00884 try
00885 {
00886 if ( CUnifiedNetwork::getInstance()->init (&loc, _RecordingState, _ShortName, ListeningPort, _SId) )
00887 {
00888 ok = true;
00889 }
00890 else
00891 {
00892 nlinfo( "SERVICE: Exiting..." );
00893 beep( 880, 400 );
00894 beep( 440, 400 );
00895 beep( 220, 400 );
00896 return 10;
00897 }
00898 }
00899 catch (ESocketConnectionFailed &)
00900 {
00901 nlwarning ("SERVICE: Could not connect to the Naming Service (%s). Retrying in a few seconds...", loc.asString().c_str());
00902 nlSleep (5000);
00903 }
00904 }
00905 }
00906 else
00907 {
00908 CUnifiedNetwork::getInstance()->init(NULL, _RecordingState, _ShortName, ListeningPort, _SId);
00909 }
00910
00911 // At this point, the _SId must be ok if we use the naming service.
00912 // If it's 0, it means that we don't use NS and we left the other side server to find a sid for your connection
00913
00914 if(!_DontUseNS)
00915 {
00916 nlassert (_SId != 0);
00917 }
00918
00919 //
00920 // Connect to the local AES and send identification
00921 //
00922
00923 // look if we don't want to use NS
00924 if ((var = ConfigFile.getVarPtr ("DontUseAES")) != NULL)
00925 {
00926 // if we set the value in the config file, get it
00927 _DontUseAES = var->asInt() == 1;
00928 }
00929 else
00930 {
00931 // if not, we use aes only if service is not aes or as
00932 _DontUseAES = false;
00933 }
00934
00935 initAdmin (_DontUseAES);
00936
00937
00938 //
00939 // Add callback array
00940 //
00941
00942 // add inner service callback array
00943 NLNET::CUnifiedNetwork::getInstance()->addCallbackArray(builtinServiceCallbacks, sizeof(builtinServiceCallbacks)/sizeof(builtinServiceCallbacks[0]));
00944
00945 // add callback set in the NLNET_SERVICE_MAIN macro
00946 NLNET::CUnifiedNetwork::getInstance()->addCallbackArray(_CallbackArray, _CallbackArraySize);
00947
00948 //
00949 // Now we have the service id, we can set the entites id generator
00950 //
00951
00952 NLMISC::CEntityId::setServiceId(_SId);
00953
00954 // Set the localhost name and service name and the sid
00955 CLog::setProcessName (localhost+"/"+_ShortName+"-"+toString((uint16)_SId));
00956
00957
00958 //
00959 // Add default pathes
00960 //
00961
00962 if ((var = ConfigFile.getVarPtr ("IgnoredFiles")) != NULL)
00963 {
00964 for (sint i = 0; i < var->size(); i++)
00965 {
00966 CPath::addIgnoredDoubleFile (var->asString(i));
00967 }
00968 }
00969
00970 if ((var = ConfigFile.getVarPtr ("Paths")) != NULL)
00971 {
00972 for (sint i = 0; i < var->size(); i++)
00973 {
00974 CPath::addSearchPath (var->asString(i), true, false);
00975 }
00976 }
00977
00978 if ((var = ConfigFile.getVarPtr ("PathsNoRecurse")) != NULL)
00979 {
00980 for (sint i = 0; i < var->size(); i++)
00981 {
00982 CPath::addSearchPath (var->asString(i), false, false);
00983 }
00984 }
00985
00986 // if we can, try to setup where to save files
00987 if (IService::getInstance()->haveArg('W'))
00988 {
00989 // use the command line param if set
00990 SaveFilesDirectory = IService::getInstance()->getArg('W');
00991 }
00992
00993
00994 //
00995 // Call the user service init
00996 //
00997
00998 userInitCalled = true; // the bool must be put *before* the call to init()
00999 init ();
01000
01001
01002 //
01003 // Connects to the present services
01004 // WARNING: only after the user init() was called because the
01005 // addService may call up service callbacks.
01006 //
01007
01008 CUnifiedNetwork::getInstance()->connect();
01009
01010 //
01011 // Say to the AES that the service is ready
01012 //
01013
01014 if (!_DontUseAES)
01015 {
01016 // send the ready message (service init finished)
01017 CMessage msgout ("SR");
01018 CUnifiedNetwork::getInstance()->send("AES", msgout);
01019 }
01020
01021
01022 _Initialized = true;
01023
01024 nlinfo ("SERVICE: Service initialised, executing StartCommands");
01025
01026 //
01027 // Call the user command from the config file if any
01028 //
01029
01030 if ((var = ConfigFile.getVarPtr ("StartCommands")) != NULL)
01031 {
01032 for (sint i = 0; i < var->size(); i++)
01033 {
01034 ICommand::execute (var->asString(i), CommandLog);
01035 }
01036 }
01037
01038 string str;
01039 CLog logDisplayVars;
01040 CLightMemDisplayer mdDisplayVars;
01041 logDisplayVars.addDisplayer (&mdDisplayVars);
01042
01043 //
01044 // Activate the timeout assertion thread
01045 //
01046
01047 IThread::create(&MyTAT)->start();
01048
01049 //
01050 // Set service ready
01051 //
01052
01053 nlinfo ("SERVICE: Service ready");
01054
01055 if (WindowDisplayer != NULL)
01056 WindowDisplayer->setTitleBar (_ShortName + " " + _LongName + " " + Version.c_str());
01057
01058 //
01059 // Call the user service update each loop and check files and network activity
01060 //
01061
01062 do
01063 {
01064 MyTAT.activate();
01065
01066 if(Bench) CHTimer::startBench(false, true, false);
01067
01068 // count the amount of time to manage internal system
01069 TTime bbefore = CTime::getLocalTime ();
01070
01071 // call the user update and exit if the user update asks it
01072 {
01073 H_AUTO(NLNETServiceUpdate);
01074 if (!update ())
01075 {
01076 CHTimer::endBench();
01077 break;
01078 }
01079 }
01080
01081 // if the launching mode is 'quit after the first update' we set the exit signal
01082 if (haveArg('Q'))
01083 {
01084 ExitSignalAsked = 1;
01085 }
01086 NbUserUpdate++;
01087
01088 // count the amount of time to manage internal system
01089 TTime before = CTime::getLocalTime ();
01090
01091 if (WindowDisplayer != NULL)
01092 {
01093 // update the window displayer and quit if asked
01094 if (!WindowDisplayer->update ())
01095 {
01096 nlinfo ("SERVICE: The window displayer was closed by user, need to quit");
01097 ExitSignalAsked = 1;
01098 }
01099 }
01100
01101 // stop the loop if the exit signal asked
01102 if (ExitSignalAsked > 0)
01103 {
01104 CHTimer::endBench();
01105 break;
01106 }
01107
01108 CConfigFile::checkConfigFiles ();
01109
01110 updateAdmin ();
01111
01112 CFile::checkFileChange();
01113
01114 // get and manage layer 5 messages
01115 CUnifiedNetwork::getInstance()->update (_UpdateTimeout);
01116
01117 // resync the clock every hours
01118 // if (resyncEvenly)
01119 // {
01120 // static TTime LastSyncTime = CTime::getLocalTime ();
01121
01122 //---------------------------------------
01123 // To simulate Ctrl-C in the debugger... Exit after 1 min !
01124 /*if (CTime::getLocalTime () - LastSyncTime > 60 * 1000 )
01125 {
01126 ExitSignalAsked = 1;
01127 }*/
01128 //---------------------------------------
01129 /*
01130 if (CTime::getLocalTime () - LastSyncTime > 60*60*1000)
01131 {
01132 CUniTime::syncUniTimeFromService ( _RecordingState );
01133 LastSyncTime = CTime::getLocalTime ();
01134 }
01135 */
01136 // }
01137
01138 NetSpeedLoop = (sint32) (CTime::getLocalTime () - before);
01139 UserSpeedLoop = (sint32) (before - bbefore);
01140
01141 if (WindowDisplayer != NULL)
01142 {
01143 uint64 rcv, snd, rcvq, sndq;
01144 rcv = CUnifiedNetwork::getInstance()->getBytesReceived ();
01145 snd = CUnifiedNetwork::getInstance()->getBytesSent ();
01146 rcvq = CUnifiedNetwork::getInstance()->getReceiveQueueSize ();
01147 sndq = CUnifiedNetwork::getInstance()->getSendQueueSize ();
01148
01149 for (uint i = 0; i < displayedVariables.size(); i++)
01150 {
01151 // it s a separator, do nothing
01152 if (displayedVariables[i].first.empty())
01153 continue;
01154
01155 // it s a command, do nothing
01156 if (displayedVariables[i].first[0] == '@')
01157 continue;
01158
01159 string dispName = displayedVariables[i].first;
01160 string varName = dispName;
01161 uint32 pos = dispName.find("|");
01162 if (pos != string::npos)
01163 {
01164 varName = displayedVariables[i].first.substr(pos+1);
01165 dispName = displayedVariables[i].first.substr(0, pos);
01166 }
01167
01168 if (dispName.empty())
01169 str = "";
01170 else
01171 str = dispName + ": ";
01172
01173 mdDisplayVars.clear ();
01174 ICommand::execute(varName, logDisplayVars, true);
01175 const std::deque<std::string> &strs = mdDisplayVars.lockStrings();
01176 if (strs.size()>0)
01177 {
01178 str += strs[0].substr(0,strs[0].size()-1);
01179 /*
01180 string s_ = strs[0];
01181
01182 uint32 pos = strs[0].find("=");
01183 if(pos != string::npos && pos + 2 < strs[0].size())
01184 {
01185 uint32 pos2 = string::npos;
01186 if(strs[0][strs[0].size()-1] == '\n')
01187 pos2 = strs[0].size() - pos - 2 - 1;
01188
01189 str += strs[0].substr (pos+2, pos2);
01190 }
01191 else
01192 {
01193 str += "???";
01194 }*/
01195 }
01196 else
01197 {
01198 str += "???";
01199 }
01200 mdDisplayVars.unlockStrings();
01201 WindowDisplayer->setLabel (displayedVariables[i].second, str);
01202 }
01203
01204 }
01205
01206 // nldebug ("SYNC: updatetimeout must be %d and is %d, sleep the rest of the time", _UpdateTimeout, delta);
01207
01208 CHTimer::endBench();
01209
01210 // Resetting the hierarchical timer must be done outside the top-level timer
01211 if ( _ResetMeasures )
01212 {
01213 CHTimer::clear();
01214 _ResetMeasures = false;
01215 }
01216
01217 MyTAT.desactivate();
01218 }
01219 while (true);
01220 }
01221 /* catch (ETrapDebug &)
01222 {
01223 // we have to do that if we want to trap unhandled exception with the report message box
01224 setStatus (EXIT_FAILURE);
01225 }
01226 */ catch (EFatalError &)
01227 {
01228 // Somebody call nlerror, so we have to quit now, the message already display
01229 // so we don't have to to anything
01230 setStatus (EXIT_FAILURE);
01231 }
01232 catch ( uint ) // SEH exceptions
01233 {
01234 ErrorLog->displayNL( "SERVICE: System exception" );
01235 }
01236
01237 #ifdef NL_RELEASE
01238 /* // in release mode, we catch everything to handle clean release.
01239 catch (Exception &e)
01240 {
01241 // Catch NeL exception to release the system cleanly
01242 setStatus (EXIT_FAILURE);
01243 nlinfo ("ERROR: NeL Exception: Error running the service \"%s\": %s", _ShortName.c_str(), e.what());
01244 }
01245 catch (...)
01246 {
01247 // Catch anything we can to release the system cleanly
01248 setStatus (EXIT_FAILURE);
01249 nlinfo ("ERROR: Unknown external exception");
01250 }
01251 */
01252 #endif
01253
01254 try
01255 {
01256 nlinfo ("SERVICE: Service starts releasing");
01257
01258 //
01259 // Call the user service release() if the init() was called
01260 //
01261
01262 if (userInitCalled)
01263 release ();
01264
01265 //
01266 // Delete all network connection (naming client also)
01267 //
01268
01269 CUnifiedNetwork::getInstance()->release ();
01270
01271 CSock::releaseNetwork ();
01272
01273 //
01274 // Remove the window displayer
01275 //
01276
01277 if (WindowDisplayer != NULL)
01278 {
01279 DebugLog->removeDisplayer (WindowDisplayer);
01280 InfoLog->removeDisplayer (WindowDisplayer);
01281 WarningLog->removeDisplayer (WindowDisplayer);
01282 ErrorLog->removeDisplayer (WindowDisplayer);
01283 AssertLog->removeDisplayer (WindowDisplayer);
01284 CommandLog.removeDisplayer (WindowDisplayer);
01285
01286 delete WindowDisplayer;
01287 WindowDisplayer = NULL;
01288 }
01289
01290 nlinfo ("SERVICE: Service released succesfuly");
01291 }
01292 /* catch (ETrapDebug &)
01293 {
01294 // we have to do that if we want to trap unhandled exception with the report message box
01295 setStatus (EXIT_FAILURE);
01296 }
01297 */ catch (EFatalError &)
01298 {
01299 // Somebody call nlerror, so we have to quit now, the message already display
01300 // so we don't have to to anything
01301 setStatus (EXIT_FAILURE);
01302 }
01303
01304 #ifdef NL_RELEASE
01305 /* // in release mode, we catch everything to handle clean release.
01306 catch (Exception &e)
01307 {
01308 setStatus (EXIT_FAILURE);
01309 nlinfo ("ERROR: NeL Exception: Error releasing the service \"%s\": %s", _ShortName.c_str(), e.what());
01310 }
01311 catch (...)
01312 {
01313 // Catch anything we can to release the system cleanly
01314 setStatus (EXIT_FAILURE);
01315 nlinfo ("ERROR: Unknown external exception");
01316 }
01317 */
01318 #endif
01319
01320 CHTimer::display();
01321 CHTimer::displayByExecutionPath ();
01322 CHTimer::displayHierarchical(&CommandLog, true, 64);
01323 CHTimer::displayHierarchicalByExecutionPathSorted (&CommandLog, CHTimer::TotalTime, true, 64);
01324
01325 nlinfo ("SERVICE: Service ends");
01326
01327 string name = getServiceLongName () + ".memory_report";
01328 NLMEMORY::StatisticsReport (name.c_str(), false);
01329
01330 return ExitSignalAsked?100+ExitSignalAsked:getStatus ();
01331 }
|
|
|
Finalization. Release the service. For example, this founction free all allocation made in the init() function.
Definition at line 191 of file service.h. Referenced by main().
00191 {}
|
|
|
Require to reset the hierarchical timer.
Definition at line 1342 of file service.cpp. References _ResetMeasures.
01343 {
01344 _ResetMeasures = true;
01345 }
|
|
|
Sets the command line and init _Args variable. You must call this before calling main().
Definition at line 335 of file service.cpp. References uint32.
00336 {
00337 _Args.push_back ("<ProgramName>");
00338
00339 string sargs (args);
00340 uint32 pos1 = 0, pos2 = 0;
00341
00342 do
00343 {
00344 pos1 = sargs.find_first_not_of (" ", pos2);
00345 if (pos1 == string::npos) break;
00346 pos2 = sargs.find_first_of (" ", pos1);
00347 _Args.push_back (sargs.substr (pos1, pos2-pos1));
00348 }
00349 while (pos2 != string::npos);
00350 }
|
|
||||||||||||
|
Sets the command line and init _Args variable. You must call this before calling main().
Definition at line 352 of file service.cpp. References sint.
|
|
||||||||||||
|
Sets the default callback array given from the macro.
Definition at line 291 of file service.h. References _CallbackArraySize, and uint.
00291 { _CallbackArray = array; _CallbackArraySize = nbelem; }
|
|
|
Changes the recording state (use if you know what you are doing).
Definition at line 327 of file service.h.
00327 { _RecordingState = rec; }
|
|
|
Sets the status of the service, this status is return to the application. EXIT_SUCCESS is the default status You can set it to EXIT_FAILURE or any value you want. It's useful when you use the service in a script and you want to know the return value of the application to do the appropriate things. Definition at line 251 of file service.h. Referenced by main().
00251 { _Status = status; }
|
|
|
Selects timeout value in seconds for each update. You are absolutely certain that your update() function will not be called before this amount of time you set. If you set the update timeout value higher than 0, all messages in queues will be process until the time greater than the timeout user update(). If you set the update timeout value to 0, all messages in queues will be process one time before calling the user update(). The default value is 100 (100ms) Definition at line 264 of file service.h. References _UpdateTimeout, and NLMISC::TTime.
00264 { /*if (timeout>1.0) nlerror ("IServer::setUpdateTimeout is now a double in SECOND and not ms");*/ _UpdateTimeout = timeout; }
|
|
|
Definition at line 315 of file service.h.
00315 { Version = version; }
|
|
|
This function is called every "frame" (you must call init() before). It returns false if the service is stopped.
Definition at line 188 of file service.h. Referenced by main().
00188 { return true; }
|
|
||||||||||||||||
|
|
|
|
|
|
||||||||||||||||
|
|
|
|
|
|
||||||||||||||||||||
|
|
|
|
|
|
|
Definition at line 347 of file service.h. Referenced by getServiceAliasName(), getServiceUnifiedName(), and main(). |
|
|
Array of arguments pass from the command line.
|
|
|
|
|
|
Definition at line 376 of file service.h. Referenced by main(), and setCallbackArray(). |
|
|
true if the service don't use the admin executor service
Definition at line 381 of file service.h. Referenced by main(). |
|
|
true if the service don't use the naming service
Definition at line 379 of file service.h. Referenced by main(). |
|
|
true if the service initialisation is passed
|
|
|
Instance of this service (singleton).
Definition at line 115 of file service.cpp. |
|
|
Definition at line 346 of file service.h. Referenced by getServiceLongName(), and main(). |
|
|
Recording state.
|
|
|
Require to reset the hierarchical timer.
Definition at line 384 of file service.h. Referenced by main(), and requireResetMeasures(). |
|
|
Shard Id.
Definition at line 387 of file service.h. Referenced by getShardId(), and main(). |
|
|
Current service name sets by the actual service when declaring NLNET_SERVICE_MAIN.
Definition at line 345 of file service.h. Referenced by getServiceShortName(), getServiceUnifiedName(), and main(). |
|
|
the service id of this sevice
Definition at line 356 of file service.h. Referenced by getServiceId(), getServiceUnifiedName(), and main(). |
|
|
the status of this service (the status is give to the at the release time)
Definition at line 359 of file service.h. Referenced by getStatus(), and setStatus(). |
|
|
Select timeout value in milliseconds between to call of user update().
Definition at line 353 of file service.h. Referenced by main(), and setUpdateTimeout(). |
|
|
Definition at line 273 of file service.h. Referenced by main(). |
|
|
The directory where the configfile is.
Definition at line 365 of file service.h. Referenced by main(). |
|
|
Definition at line 270 of file service.h. Referenced by main(). |
|
|
Listening port of this service.
|
|
|
The directory where the logfiles are.
Definition at line 368 of file service.h. Referenced by main(). |
|
|
The directory where the service is running.
Definition at line 371 of file service.h. Referenced by main(). |
|
|
Directory where to store files that the services will write during the exploitation of the game (for example: player backup, string cache) Use .toString() to access to the value Definition at line 313 of file service.h. Referenced by main(). |
|
|
|
|
|
The window displayer instance.
Definition at line 305 of file service.h. Referenced by main(). |
|
|
Directory where to store files that the services will write but are the same for all shard instance (for example: packet_sheets) Use .toString() to access to the value |
1.3.6