00001
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "stdnet.h"
00029
00030 #ifdef NL_OS_WINDOWS
00031
00032
00033
00034
00035
00036
00037
00038 # define _WIN32_WINDOWS 0x0410
00039 # define WINVER 0x0400
00040 # include <windows.h>
00041 # include <direct.h>
00042
00043 #elif defined NL_OS_UNIX
00044
00045 # include <unistd.h>
00046
00047 #endif
00048
00049 #include <stdlib.h>
00050 #include <signal.h>
00051
00052 #include "nel/misc/config_file.h"
00053 #include "nel/misc/displayer.h"
00054 #include "nel/misc/mutex.h"
00055 #include "nel/misc/window_displayer.h"
00056 #include "nel/misc/gtk_displayer.h"
00057 #include "nel/misc/win_displayer.h"
00058 #include "nel/misc/path.h"
00059 #include "nel/misc/hierarchical_timer.h"
00060 #include "nel/misc/report.h"
00061
00062 #include "nel/net/naming_client.h"
00063 #include "nel/net/service.h"
00064 #include "nel/net/unified_network.h"
00065 #include "nel/net/net_manager.h"
00066 #include "nel/net/net_displayer.h"
00067 #include "nel/net/email.h"
00068 #include "nel/net/varpath.h"
00069
00070 #include "nel/misc/hierarchical_timer.h"
00071
00072
00073
00074
00075
00076
00077 using namespace std;
00078 using namespace NLMISC;
00079
00080
00081 namespace NLNET
00082 {
00083
00084
00085
00086
00087
00088
00089 static const sint Signal[] = {
00090 SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM
00091 };
00092
00093 static const char *SignalName[]=
00094 {
00095 "SIGABRT", "SIGFPE", "SIGILL", "SIGINT", "SIGSEGV", "SIGTERM"
00096 };
00097
00098
00099
00100
00101
00102
00103
00104
00105 IService *IService::_Instance = NULL;
00106
00107 static sint ExitSignalAsked = 0;
00108
00109
00110 static sint32 NetSpeedLoop, UserSpeedLoop;
00111
00112
00113
00114 static uint SignalisedThread;
00115
00116 static CFileDisplayer fd;
00117 static CNetDisplayer commandDisplayer(false);
00118 static CLog commandLog;
00119
00120
00121
00122
00123
00124
00125 void serviceGetView (uint32 rid, const string &rawvarpath, vector<string> &vara, vector<string> &vala)
00126 {
00127 string str;
00128 CLog logDisplayVars;
00129 CMemDisplayer mdDisplayVars;
00130 logDisplayVars.addDisplayer (&mdDisplayVars);
00131
00132 CVarPath varpath(rawvarpath);
00133
00134
00135 vara.push_back ("service");
00136
00137 vala.push_back (IService::getInstance ()->getServiceUnifiedName());
00138
00139 for (uint j = 0; j < varpath.Destination.size (); j++)
00140 {
00141 string cmd = varpath.Destination[j].first;
00142
00143
00144 uint pos = cmd.find("=");
00145 if (pos != string::npos)
00146 cmd[pos] = ' ';
00147
00148 mdDisplayVars.clear ();
00149 ICommand::execute(cmd, logDisplayVars, true);
00150 const std::deque<std::string> &strs = mdDisplayVars.lockStrings();
00151 if (strs.size()>0)
00152 {
00153 string s_ = strs[0];
00154
00155 uint32 pos = strs[0].find("=");
00156 if(pos != string::npos && pos + 2 < strs[0].size())
00157 {
00158 uint32 pos2 = string::npos;
00159 if(strs[0][strs[0].size()-1] == '\n')
00160 pos2 = strs[0].size() - pos - 2 - 1;
00161
00162 str = strs[0].substr (pos+2, pos2);
00163 }
00164 else
00165 {
00166 str = "???";
00167 }
00168 }
00169 else
00170 {
00171 str = "???";
00172 }
00173 mdDisplayVars.unlockStrings();
00174
00175 if (pos != string::npos)
00176 vara.push_back(cmd.substr(0, pos));
00177 else
00178 vara.push_back(cmd);
00179
00180 vala.push_back (str);
00181 nlinfo ("Add to result view '%s' = '%s'", varpath.Destination[j].first.c_str(), str.c_str());
00182 }
00183
00184 }
00185
00186 void servcbGetView (CMessage &msgin, const std::string &serviceName, uint16 sid)
00187 {
00188 uint32 rid;
00189 string rawvarpath;
00190
00191 msgin.serial (rid);
00192 msgin.serial (rawvarpath);
00193
00194 vector<string> vara;
00195 vector<string> vala;
00196
00197 serviceGetView (rid, rawvarpath, vara, vala);
00198
00199 CMessage msgout("VIEW");
00200 msgout.serial(rid);
00201
00202 msgout.serialCont (vara);
00203 msgout.serialCont (vala);
00204
00205 CUnifiedNetwork::getInstance ()->send (sid, msgout);
00206 nlinfo ("Sent result view to service '%s-%hu'", serviceName.c_str(), sid);
00207 }
00208
00209 void AESConnection (const string &serviceName, uint16 sid, void *arg)
00210 {
00211
00212
00213
00214
00215
00216
00217 CMessage msgout ("SID");
00218 uint32 pid = getpid ();
00219 msgout.serial (IService::getInstance()->_AliasName, IService::getInstance()->_LongName, pid);
00220 ICommand::serialCommands (msgout);
00221 CUnifiedNetwork::getInstance()->send("AES", msgout);
00222
00223 if (IService::getInstance()->_Initialized)
00224 {
00225 CMessage msgout2 ("SR");
00226 CUnifiedNetwork::getInstance()->send("AES", msgout2);
00227 }
00228
00229
00230
00231
00232
00233
00234 }
00235
00236
00237 static void AESDisconnection (const std::string &serviceName, uint16 sid, void *arg)
00238 {
00239
00240 }
00241
00242
00243 static void cbExecCommand (CMessage &msgin, const std::string &serviceName, uint16 sid)
00244 {
00245 nlwarning ("AES: Deprecated function call cbExecCommand");
00246
00247
00248
00249
00250
00251 }
00252
00253
00254 static void cbStopService (CMessage &msgin, const std::string &serviceName, uint16 sid)
00255 {
00256 nlinfo ("Receive a stop from service %s-%d, need to quit", serviceName.c_str(), sid);
00257 ExitSignalAsked = 0xFFFF;
00258 }
00259
00260
00261
00262
00263 static TUnifiedCallbackItem AESCallbackArray[] =
00264 {
00265 { "STOPS", cbStopService },
00266 { "EXEC_COMMAND", cbExecCommand },
00267 { "GET_VIEW", servcbGetView },
00268 };
00269
00270
00271
00272
00273
00274
00275 static void sigHandler(int Sig)
00276 {
00277
00278 signal(Sig, sigHandler);
00279
00280
00281 for (int i = 0; i < (int)(sizeof(Signal)/sizeof(Signal[0])); i++)
00282 {
00283 if (Sig == Signal[i])
00284 {
00285 if (getThreadId () != SignalisedThread)
00286 {
00287 nldebug ("Not the main thread received the signal (%s, %d), ignore it", SignalName[i],Sig);
00288 return;
00289 }
00290 else
00291 {
00292 nlinfo ("Signal %s (%d) received", SignalName[i], Sig);
00293 switch (Sig)
00294 {
00295 case SIGABRT :
00296 case SIGILL :
00297 case SIGINT :
00298 case SIGSEGV :
00299 case SIGTERM :
00300
00301
00302 if (ExitSignalAsked == 0)
00303 {
00304 nlinfo ("Receive a signal that said that i must exit");
00305 ExitSignalAsked = Sig;
00306 return;
00307 }
00308 else
00309 {
00310 nlinfo ("Signal already received, launch the brutal exit");
00311 exit (EXIT_FAILURE);
00312 }
00313 break;
00314 }
00315 }
00316 }
00317 }
00318 nlinfo ("Unknown signal received (%d)", Sig);
00319 }
00320
00321
00322 static void initSignal()
00323 {
00324 SignalisedThread = getThreadId ();
00325 #ifdef NL_DEBUG
00326
00327 signal(Signal[3], sigHandler);
00328
00329 #else
00330
00331
00332
00333
00334
00335
00336
00337
00338 #endif
00339 }
00340
00341
00342
00343
00344
00345
00346 IService::IService() :
00347 WindowDisplayer(NULL),
00348 _Port(0),
00349 _RecordingState(CCallbackNetBase::Off),
00350 _UpdateTimeout(100),
00351 _SId(0),
00352 _Status(0),
00353 _Initialized(false),
00354 _ResetMeasures(false)
00355 {
00356
00357 nlassert( _Instance == NULL );
00358
00359 _Instance = this;
00360 }
00361
00362
00363
00364 bool IService::haveArg (char argName)
00365 {
00366 for (uint32 i = 0; i < _Args.size(); i++)
00367 {
00368 if (_Args[i].size() >= 2 && _Args[i][0] == '-')
00369 {
00370 if (_Args[i][1] == argName)
00371 {
00372 return true;
00373 }
00374 }
00375 }
00376 return false;
00377 }
00378
00379 string IService::getArg (char argName)
00380 {
00381 for (uint32 i = 0; i < _Args.size(); i++)
00382 {
00383 if (_Args[i].size() >= 2 && _Args[i][0] == '-')
00384 {
00385 if (_Args[i][1] == argName)
00386 {
00387 return _Args[i].substr(2);
00388 }
00389 }
00390 }
00391 throw Exception ("Parameter '-%c' is not found in command line", argName);
00392 }
00393
00394
00395 void IService::setArgs (const char *args)
00396 {
00397 _Args.push_back ("<ProgramName>");
00398
00399 string sargs (args);
00400 uint32 pos1 = 0, pos2 = 0;
00401
00402 do
00403 {
00404 pos1 = sargs.find_first_not_of (" ", pos2);
00405 if (pos1 == string::npos) break;
00406 pos2 = sargs.find_first_of (" ", pos1);
00407 _Args.push_back (sargs.substr (pos1, pos2-pos1));
00408 }
00409 while (pos2 != string::npos);
00410 }
00411
00412 void IService::setArgs (int argc, const char **argv)
00413 {
00414 for (sint i = 0; i < argc; i++)
00415 {
00416 _Args.push_back (argv[i]);
00417 }
00418 }
00419
00420
00421
00422
00423 CCallbackServer *IService::getServer()
00424 {
00425 return NULL;
00426 }
00427
00428
00429
00430 void cbLogFilter (CConfigFile::CVar &var)
00431 {
00432 CLog *log = NULL;
00433 if (var.Name == "NegFiltersDebug")
00434 {
00435 log = DebugLog;
00436 nlinfo ("Updating negative filter on debug from config file");
00437 }
00438 else if (var.Name == "NegFiltersInfo")
00439 {
00440 log = InfoLog;
00441 nlinfo ("Updating negative filter on info from config file");
00442 }
00443 else
00444 {
00445 nlstop;
00446 }
00447
00448
00449 CConfigFile::CVar &oldvar = IService::getInstance()->ConfigFile.getVar (var.Name);
00450 for (sint j = 0; j < oldvar.size(); j++)
00451 {
00452 log->removeFilter (oldvar.asString(j).c_str());
00453 }
00454
00455
00456 for (sint i = 0; i < var.size(); i++)
00457 {
00458 log->addNegativeFilter (var.asString(i).c_str());
00459 }
00460 }
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473 sint IService::main (const char *serviceShortName, const char *serviceLongName, uint16 servicePort, const char *configDir, const char *logDir)
00474 {
00475 bool userInitCalled = false;
00476 bool resyncEvenly = false;
00477 CConfigFile::CVar *var = NULL;
00478
00479
00480 nlassert (atoi(serviceShortName) == 0);
00481
00482 try
00483 {
00484
00485
00486
00487
00488 _ConfigDir = CPath::standardizePath(configDir);
00489 _LogDir = CPath::standardizePath(logDir);
00490 _ShortName = serviceShortName;
00491 _LongName = serviceLongName;
00492
00493
00494 CLog::setProcessName (_ShortName);
00495
00496 setReportEmailFunction ((void*)sendEmail);
00497 setDefaultEmailParams ("gw.nevrax.com", "", "lecroart@nevrax.com");
00498
00499
00500 if (haveArg('A'))
00501 {
00502 _RunningPath = CPath::standardizePath(getArg('A'));
00503 #ifdef NL_OS_WINDOWS
00504 _chdir (_RunningPath.c_str());
00505 #else
00506 chdir (_RunningPath.c_str());
00507 #endif
00508 }
00509
00510
00511
00512
00513
00514
00515 if (haveArg('L'))
00516 _LogDir = CPath::standardizePath(getArg('L'));
00517
00518
00519 if (haveArg('C'))
00520 _ConfigDir = CPath::standardizePath(getArg('C'));
00521
00522 createDebug (_LogDir.c_str(), false);
00523
00524
00525
00526
00527 fd.setParam (_LogDir + _LongName + ".log", false);
00528
00529 DebugLog->addDisplayer (&fd);
00530 InfoLog->addDisplayer (&fd);
00531 WarningLog->addDisplayer (&fd);
00532 AssertLog->addDisplayer (&fd);
00533 ErrorLog->addDisplayer (&fd);
00534
00535
00536
00537
00538
00539
00540 CHTimer::startBench(false, true);
00541
00542
00543
00544
00545
00546
00547 ConfigFile.load (_ConfigDir + _LongName + ".cfg");
00548
00549
00550
00551
00552
00553
00554 if ((var = ConfigFile.getVarPtr ("NegFiltersDebug")) != NULL)
00555 {
00556 ConfigFile.setCallback ("NegFiltersDebug", cbLogFilter);
00557 for (sint i = 0; i < var->size(); i++)
00558 {
00559 DebugLog->addNegativeFilter (var->asString(i).c_str());
00560 }
00561 }
00562
00563 if ((var = ConfigFile.getVarPtr ("NegFiltersInfo")) != NULL)
00564 {
00565 ConfigFile.setCallback ("NegFiltersInfo", cbLogFilter);
00566 for (sint i = 0; i < var->size(); i++)
00567 {
00568 InfoLog->addNegativeFilter (var->asString(i).c_str());
00569 }
00570 }
00571
00572
00573
00574
00575
00576
00577 if ((var = ConfigFile.getVarPtr ("WindowStyle")) != NULL)
00578 {
00579 string disp = var->asString ();
00580 #ifdef NL_USE_GTK
00581 if (disp == "GTK")
00582 {
00583 WindowDisplayer = new CGtkDisplayer ("DEFAULT_WD");
00584 }
00585 #endif // NL_USE_GTK
00586
00587 #ifdef NL_OS_WINDOWS
00588 if (disp == "WIN")
00589 {
00590 WindowDisplayer = new CWinDisplayer ("DEFAULT_WD");
00591 }
00592 #endif // NL_OS_WINDOWS
00593
00594 if (WindowDisplayer == NULL && disp != "NONE")
00595 {
00596 nlwarning ("Unknown value for the WindowStyle (should be GTK, WIN or NONE), use no window displayer");
00597 }
00598 }
00599
00600 vector <pair<string,uint> > displayedVariables;
00601
00602 if (WindowDisplayer != NULL)
00603 {
00604
00605
00606
00607
00608 sint x=-1, y=-1, w=-1, h=-1, fs=10;
00609 bool iconified = false, ww = false;
00610 string fn;
00611
00612 if ((var = ConfigFile.getVarPtr("XWinParam")) != NULL) x = var->asInt();
00613 if ((var = ConfigFile.getVarPtr("YWinParam")) != NULL) y = var->asInt();
00614 if ((var = ConfigFile.getVarPtr("WWinParam")) != NULL) w = var->asInt();
00615 if ((var = ConfigFile.getVarPtr("HWinParam")) != NULL) h = var->asInt();
00616 if ((var = ConfigFile.getVarPtr("HWinParam")) != NULL) iconified = var->asInt() == 1;
00617 if ((var = ConfigFile.getVarPtr("FontSize")) != NULL) fs = var->asInt();
00618 if ((var = ConfigFile.getVarPtr("FontName")) != NULL) fn = var->asString();
00619 if ((var = ConfigFile.getVarPtr("WordWrap")) != NULL) ww = var->asInt() == 1;
00620
00621 if (haveArg('I')) iconified = true;
00622
00623 WindowDisplayer->create (string("*INIT* ") + _ShortName + " " + _LongName, iconified, x, y, w, h, -1, fs, fn, ww);
00624
00625 DebugLog->addDisplayer (WindowDisplayer);
00626 InfoLog->addDisplayer (WindowDisplayer);
00627 WarningLog->addDisplayer (WindowDisplayer);
00628 ErrorLog->addDisplayer (WindowDisplayer);
00629 AssertLog->addDisplayer (WindowDisplayer);
00630
00631
00632 displayedVariables.push_back(make_pair(string("NetLop|NetSpeedLoop"), WindowDisplayer->createLabel ("NetLop")));
00633 displayedVariables.push_back(make_pair(string("UsrLop|UserSpeedLoop"), WindowDisplayer->createLabel ("UsrLop")));
00634
00635
00636
00637
00638 displayedVariables.push_back(make_pair(string("|Scroller"), WindowDisplayer->createLabel ("NeL Rulez")));
00639
00640 CConfigFile::CVar *v = ConfigFile.getVarPtr("DisplayedVariables");
00641 if (v != NULL)
00642 {
00643 for (sint i = 0; i < v->size(); i++)
00644 {
00645 displayedVariables.push_back(make_pair(v->asString(i), WindowDisplayer->createLabel (v->asString(i).c_str())));
00646 }
00647 }
00648 }
00649
00650 nlinfo ("Starting Service '%s' using NeL ("__DATE__" "__TIME__")", _ShortName.c_str());
00651
00652 setStatus (EXIT_SUCCESS);
00653
00654
00655
00656
00657
00658 #ifdef NL_OS_WINDOWS
00659 #ifdef NL_RELEASE
00660 initSignal();
00661 #else
00662
00663 if (IsDebuggerPresent ())
00664 {
00665
00666 initSignal();
00667 }
00668 else
00669 {
00670
00671 initSignal();
00672 }
00673 #endif
00674 #else // NL_OS_UNIX
00675 initSignal();
00676 #endif
00677
00678
00679
00680
00681
00682
00683 #ifdef NL_OS_UNIX
00684
00685 sigset_t SigList;
00686 bool IgnoredPipe = true;
00687 if (sigemptyset (&SigList) == -1)
00688 {
00689 perror("sigemptyset()");
00690 IgnoredPipe = false;
00691 }
00692
00693 if (sigaddset (&SigList, SIGPIPE) == -1)
00694 {
00695 perror("sigaddset()");
00696 IgnoredPipe = false;
00697 }
00698
00699 if (sigprocmask (SIG_BLOCK, &SigList, NULL) == -1)
00700 {
00701 perror("sigprocmask()");
00702 IgnoredPipe = false;
00703 }
00704 nldebug ("SIGPIPE %s", IgnoredPipe?"Ignored":"Not Ignored");
00705 #endif // NL_OS_UNIX
00706
00707
00708
00709
00710
00711
00712 string localhost;
00713 try
00714 {
00715
00716 CSock::initNetwork();
00717
00718
00719 localhost = CInetAddress::localHost().hostName();
00720 }
00721 catch (NLNET::ESocket &)
00722 {
00723 localhost = "<UnknownHost>";
00724 }
00725
00726
00727 CLog::setProcessName (localhost+"/"+_ShortName);
00728
00729
00730
00731
00732
00733
00734 if ((var = ConfigFile.getVarPtr("Port")) != NULL)
00735 {
00736
00737 _Port = var->asInt();
00738 }
00739 else
00740 {
00741
00742 _Port = servicePort;
00743 }
00744
00745
00746 if (haveArg('P'))
00747 {
00748 _Port = atoi(getArg('P').c_str());
00749 }
00750
00751
00752 if (haveArg('N'))
00753 {
00754 _AliasName = getArg('N');
00755 }
00756
00757
00758 if ((var = ConfigFile.getVarPtr ("Rec")) != NULL)
00759 {
00760 string srecstate = var->asString();
00761 strupr( srecstate );
00762 if ( srecstate == "RECORD" )
00763 {
00764 _RecordingState = CCallbackNetBase::Record;
00765 nlinfo( "Service recording messages" );
00766 }
00767 else if ( srecstate == "REPLAY" )
00768 {
00769 _RecordingState = CCallbackNetBase::Replay;
00770 nlinfo( "Service replaying messages" );
00771 }
00772 else
00773 {
00774 _RecordingState = CCallbackNetBase::Off;
00775 }
00776 }
00777 else
00778 {
00779
00780 _RecordingState = CCallbackNetBase::Off;
00781 }
00782
00783
00784 if ((var = ConfigFile.getVarPtr ("StringMsgFormat")) != NULL)
00785 {
00786 CMessage::setDefaultStringMode( var->asInt() == 1 );
00787 }
00788 else
00789 {
00790
00791 CMessage::setDefaultStringMode( false );
00792 }
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00827
00828
00829 if ((var = ConfigFile.getVarPtr ("SId")) != NULL)
00830 {
00831 sint32 sid = var->asInt();
00832 if (sid<=0 || sid>255)
00833 {
00834 nlwarning("Bad SId value in the config file, %d is not in [0;255] range", sid);
00835 _SId = 0;
00836 }
00837 else
00838 {
00839 _SId = (uint8) sid;
00840 }
00841 }
00842 else
00843 {
00844
00845 _SId = 0;
00846 }
00847
00848
00849
00850 if ((var = ConfigFile.getVarPtr ("DontUseNS")) != NULL)
00851 {
00852
00853 _DontUseNS = (var->asInt() == 1);
00854 }
00855 else
00856 {
00857
00858 _DontUseNS = false;
00859 }
00860
00861
00862
00863
00864
00865 if ((var = ConfigFile.getVarPtr ("Networks")) != NULL)
00866 {
00867 for (uint8 i = 0; i < var->size (); i++)
00868 CUnifiedNetwork::getInstance()->addNetworkAssociation (var->asString(i), i);
00869 }
00870
00871 if ((var = ConfigFile.getVarPtr ("DefaultNetworks")) != NULL)
00872 {
00873 for (uint8 i = 0; i < var->size (); i++)
00874 CUnifiedNetwork::getInstance()->addDefaultNetwork(var->asString(i));
00875 }
00876
00877
00878 if (!_DontUseNS)
00879 {
00880 bool ok = false;
00881 while (!ok)
00882 {
00883
00884 string LSAddr = ConfigFile.getVar ("NSHost").asString();
00885
00886
00887 if (LSAddr.find(":") == string::npos)
00888 LSAddr += ":50000";
00889
00890 CInetAddress loc(LSAddr);
00891 try
00892 {
00893 CUnifiedNetwork::getInstance()->init (&loc, _RecordingState, _ShortName, _Port, _SId);
00894
00895 ok = true;
00896 }
00897 catch (ESocketConnectionFailed &)
00898 {
00899 nlwarning ("Could not connect to the Naming Service (%s). Retrying in a few seconds...", loc.asString().c_str());
00900 nlSleep (5000);
00901 }
00902 }
00903 }
00904 else
00905 {
00906 CUnifiedNetwork::getInstance()->init(NULL, _RecordingState, _ShortName, _Port, _SId);
00907 }
00908
00909
00910
00911
00912 if(!_DontUseNS)
00913 {
00914 nlassert (_SId != 0);
00915 }
00916
00917
00918
00919
00920
00921
00922 if ((var = ConfigFile.getVarPtr ("DontUseAES")) != NULL)
00923 {
00924
00925 _DontUseAES = var->asInt() == 1;
00926 }
00927 else
00928 {
00929
00930 _DontUseAES = false;
00931 }
00932
00933 if (!_DontUseAES)
00934 {
00935 CUnifiedNetwork::getInstance()->setServiceUpCallback ("AES", AESConnection, NULL);
00936 CUnifiedNetwork::getInstance()->setServiceDownCallback ("AES", AESDisconnection, NULL);
00937 CUnifiedNetwork::getInstance()->addCallbackArray (AESCallbackArray, sizeof(AESCallbackArray)/sizeof(AESCallbackArray[0]));
00938 CUnifiedNetwork::getInstance()->addService ("AES", CInetAddress("localhost:49997"));
00939 }
00940
00941
00942
00943
00944
00945
00946
00947 NLNET::CUnifiedNetwork::getInstance()->addCallbackArray(_CallbackArray, _CallbackArraySize);
00948
00949
00950
00951
00952
00953 _NextEntityId.setServiceId(_SId);
00954
00955
00956 CLog::setProcessName (localhost+"/"+_ShortName+"-"+toString((uint16)_SId));
00957
00958
00959
00960
00961
00962
00963 if ((var = ConfigFile.getVarPtr ("Paths")) != NULL)
00964 {
00965 for (sint i = 0; i < var->size(); i++)
00966 {
00967 CPath::addSearchPath (var->asString(i), true, false);
00968 }
00969 }
00970
00971 if ((var = ConfigFile.getVarPtr ("PathsNoRecurse")) != NULL)
00972 {
00973 for (sint i = 0; i < var->size(); i++)
00974 {
00975 CPath::addSearchPath (var->asString(i), false, false);
00976 }
00977 }
00978
00979
00980
00981 if ((var = ConfigFile.getVarPtr ("WriteFilesDirectory")) != NULL)
00982 {
00983 WriteFilesDirectory = CPath::standardizePath(var->asString());
00984 }
00985
00986
00987
00988
00989
00990
00991 userInitCalled = true;
00992 init ();
00993
00994
00995
00996
00997
00998
00999
01000
01001 CUnifiedNetwork::getInstance()->connect();
01002
01003
01004
01005
01006
01007
01008 if (!_DontUseAES)
01009 {
01010
01011 CMessage msgout ("SR");
01012 CUnifiedNetwork::getInstance()->send("AES", msgout);
01013 }
01014
01015
01016 _Initialized = true;
01017
01018 nlinfo ("Service initialised, executing StartCommands");
01019
01020
01021
01022
01023
01024 if ((var = ConfigFile.getVarPtr ("StartCommands")) != NULL)
01025 {
01026 for (sint i = 0; i < var->size(); i++)
01027 {
01028 ICommand::execute (var->asString(i), *InfoLog);
01029 }
01030 }
01031
01032 string str;
01033 CLog logDisplayVars;
01034 CMemDisplayer mdDisplayVars;
01035 logDisplayVars.addDisplayer (&mdDisplayVars);
01036
01037 nlinfo ("Service ready");
01038
01039 if (WindowDisplayer != NULL)
01040 WindowDisplayer->setTitleBar (_ShortName + " " + _LongName + " " + _Version);
01041
01042
01043
01044
01045
01046 do
01047 {
01048
01049
01050 TTime bbefore = CTime::getLocalTime ();
01051
01052
01053
01054 if (!update ())
01055 {
01056
01057
01058 break;
01059 }
01060
01061
01062
01063 TTime before = CTime::getLocalTime ();
01064
01065 if (WindowDisplayer != NULL)
01066 {
01067
01068 if (!WindowDisplayer->update ())
01069 {
01070 nlinfo ("The window displayer was closed by user, need to quit");
01071 ExitSignalAsked = 1;
01072 }
01073 }
01074
01075
01076 if (ExitSignalAsked > 0)
01077 {
01078
01079 break;
01080 }
01081
01082 CConfigFile::checkConfigFiles ();
01083
01084 CFile::checkFileChange();
01085
01086
01087
01088 CUnifiedNetwork::getInstance()->update (_UpdateTimeout);
01089
01090
01091
01092 if (resyncEvenly)
01093 {
01094 static TTime LastSyncTime = CTime::getLocalTime ();
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110 }
01111
01112 NetSpeedLoop = (sint32) (CTime::getLocalTime () - before);
01113 UserSpeedLoop = (sint32) (before - bbefore);
01114
01115 if (WindowDisplayer != NULL)
01116 {
01117 uint64 rcv, snd, rcvq, sndq;
01118 rcv = CUnifiedNetwork::getInstance()->getBytesReceived ();
01119 snd = CUnifiedNetwork::getInstance()->getBytesSent ();
01120 rcvq = CUnifiedNetwork::getInstance()->getReceiveQueueSize ();
01121 sndq = CUnifiedNetwork::getInstance()->getSendQueueSize ();
01122
01123 for (uint i = 0; i < displayedVariables.size(); i++)
01124 {
01125
01126 if (displayedVariables[i].first.empty())
01127 continue;
01128
01129
01130 if (displayedVariables[i].first[0] == '@')
01131 continue;
01132
01133 string dispName = displayedVariables[i].first;
01134 string varName = dispName;
01135 uint32 pos = dispName.find("|");
01136 if (pos != string::npos)
01137 {
01138 varName = displayedVariables[i].first.substr(pos+1);
01139 dispName = displayedVariables[i].first.substr(0, pos);
01140 }
01141
01142 if (dispName.empty())
01143 str = "";
01144 else
01145 str = dispName + ": ";
01146
01147 mdDisplayVars.clear ();
01148 ICommand::execute(varName, logDisplayVars, true);
01149 const std::deque<std::string> &strs = mdDisplayVars.lockStrings();
01150 if (strs.size()>0)
01151 {
01152
01153 string s_ = strs[0];
01154
01155 uint32 pos = strs[0].find("=");
01156 if(pos != string::npos && pos + 2 < strs[0].size())
01157 {
01158 uint32 pos2 = string::npos;
01159 if(strs[0][strs[0].size()-1] == '\n')
01160 pos2 = strs[0].size() - pos - 2 - 1;
01161
01162 str += strs[0].substr (pos+2, pos2);
01163 }
01164 else
01165 {
01166 str += "???";
01167 }
01168 }
01169 else
01170 {
01171 str += "???";
01172 }
01173 mdDisplayVars.unlockStrings();
01174 WindowDisplayer->setLabel (displayedVariables[i].second, str);
01175 }
01176
01177 }
01178
01179
01180
01181
01182
01183 if ( _ResetMeasures )
01184 {
01185 CHTimer::clear();
01186 _ResetMeasures = false;
01187 }
01188
01189 }
01190 while (true);
01191 }
01192
01193
01194
01195
01196
01197 catch (EFatalError &)
01198 {
01199
01200
01201 setStatus (EXIT_FAILURE);
01202 }
01203 catch ( uint )
01204 {
01205 ErrorLog->displayNL( "System exception" );
01206 }
01207
01208 #ifdef NL_RELEASE
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223 #endif
01224
01225 try
01226 {
01227 nlinfo ("Service starts releasing");
01228
01229
01230
01231
01232
01233 if (userInitCalled)
01234 release ();
01235
01236
01237
01238
01239
01240 CUnifiedNetwork::getInstance()->release ();
01241
01242 CSock::releaseNetwork ();
01243
01244
01245
01246
01247
01248 if (WindowDisplayer != NULL)
01249 {
01250 DebugLog->removeDisplayer (WindowDisplayer);
01251 InfoLog->removeDisplayer (WindowDisplayer);
01252 WarningLog->removeDisplayer (WindowDisplayer);
01253 ErrorLog->removeDisplayer (WindowDisplayer);
01254 AssertLog->removeDisplayer (WindowDisplayer);
01255
01256 delete WindowDisplayer;
01257 WindowDisplayer = NULL;
01258 }
01259
01260 nlinfo ("Service released succesfuly");
01261 }
01262
01263
01264
01265
01266
01267 catch (EFatalError &)
01268 {
01269
01270
01271 setStatus (EXIT_FAILURE);
01272 }
01273
01274 #ifdef NL_RELEASE
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288 #endif
01289
01290 CHTimer::endBench();
01291 CHTimer::display();
01292 CHTimer::displayByExecutionPath ();
01293 CHTimer::displayHierarchical(InfoLog, true, 64);
01294 CHTimer::displayHierarchicalByExecutionPathSorted (InfoLog, CHTimer::TotalTime, true, 64);
01295
01296 nlinfo ("Service ends");
01297
01298 return ExitSignalAsked?100+ExitSignalAsked:getStatus ();
01299 }
01300
01301 void IService::exit (sint code)
01302 {
01303 nlinfo ("somebody called IService::exit(), I have to quit");
01304 ExitSignalAsked = code;
01305 }
01306
01307
01308
01309
01310 void IService::requireResetMeasures()
01311 {
01312 _ResetMeasures = true;
01313 }
01314
01315
01316 std::string IService::getServiceUnifiedName () const
01317 {
01318 nlassert (!_ShortName.empty())
01319 string res;
01320 if (!_AliasName.empty())
01321 {
01322 res = _AliasName+"/";
01323 }
01324 res += _ShortName;
01325 if (_SId != 0)
01326 {
01327 res += "-";
01328 res += toString (_SId);
01329 }
01330 return res;
01331 }
01332
01333
01334
01335
01336
01337
01338
01339 NLMISC_VARIABLE(sint32, NetSpeedLoop, "duration of the last network loop (in ms)");
01340 NLMISC_VARIABLE(sint32, UserSpeedLoop, "duration of the last user loop (in ms)");
01341
01342 NLMISC_DYNVARIABLE(uint64, ReceivedBytes, "total of bytes received by this service")
01343 {
01344
01345 if (get)
01346 *pointer = CUnifiedNetwork::getInstance()->getBytesReceived ();
01347 }
01348
01349 NLMISC_DYNVARIABLE(uint64, SentBytes, "total of bytes sent by this service")
01350 {
01351
01352 if (get)
01353 *pointer = CUnifiedNetwork::getInstance()->getBytesSent ();
01354 }
01355
01356 NLMISC_DYNVARIABLE(uint64, ReceivedQueueSize, "current size in bytes of the received queue size")
01357 {
01358
01359 if (get)
01360 *pointer = CUnifiedNetwork::getInstance()->getReceiveQueueSize ();
01361 }
01362
01363 NLMISC_DYNVARIABLE(uint64, SentQueueSize, "current size in bytes of the sent queue size")
01364 {
01365
01366 if (get)
01367 *pointer = CUnifiedNetwork::getInstance()->getSendQueueSize ();
01368 }
01369
01370 NLMISC_DYNVARIABLE(string, Scroller, "current size in bytes of the sent queue size")
01371 {
01372 if (get)
01373 {
01374
01375 static string foo = "Welcome to NeL Service! This scroll is used to see the update frequency of the main function and to see if the service is frozen or not. Have a nice day and hope you'll like NeL!!! "
01376 "Welcome to NeL Service! This scroll is used to see the update frequency of the main function and to see if the service is frozen or not. Have a nice day and hope you'll like NeL!!! ";
01377 static int pos = 0;
01378 *pointer = foo.substr ((pos++)%(foo.size()/2), 10);
01379 }
01380 }
01381
01382 NLMISC_COMMAND (quit, "exit the service", "")
01383 {
01384 if(args.size() != 0) return false;
01385
01386 nlinfo ("User ask me with a command to quit");
01387 ExitSignalAsked = 0xFFFF;
01388
01389 return true;
01390 }
01391
01392 NLMISC_COMMAND (brutalQuit, "exit the service brutally", "")
01393 {
01394 if(args.size() != 0) return false;
01395
01396 ::exit (0xFFFFFFFF);
01397
01398 return true;
01399 }
01400
01401
01402 #ifdef MUTEX_DEBUG
01403 NLMISC_COMMAND (mutex, "display mutex values", "")
01404 {
01405 if(args.size() != 0) return false;
01406
01407 map<CFairMutex*,TMutexLocks> acquiretimes = getNewAcquireTimes();
01408
01409 map<CFairMutex*,TMutexLocks>::iterator im;
01410 for ( im=acquiretimes.begin(); im!=acquiretimes.end(); ++im )
01411 {
01412 nlinfo( "%d %p %s: %.0f %.0f, called %u times th(%d, %d wait)%s", (*im).second.MutexNum, (*im).first, (*im).second.MutexName.c_str(),
01413 CTime::cpuCycleToSecond((*im).second.TimeToEnter)*1000.0, CTime::cpuCycleToSecond((*im).second.TimeInMutex)*1000.0,
01414 (*im).second.Nb, (*im).second.ThreadHavingTheMutex, (*im).second.WaitingMutex,
01415 (*im).second.Dead?" DEAD":"");
01416 }
01417
01418 return true;
01419 }
01420 #endif // MUTEX_DEBUG
01421
01422 NLMISC_COMMAND (serviceInfo, "display information about this service", "")
01423 {
01424 if(args.size() != 0) return false;
01425
01426 log.displayNL ("Service %s '%s' using NeL ("__DATE__" "__TIME__")", IService::getInstance()->getServiceLongName().c_str(), IService::getInstance()->getServiceUnifiedName().c_str());
01427 log.displayNL ("Service listening port: %d", IService::getInstance()->_Port);
01428 log.displayNL ("Service running directory: '%s'", IService::getInstance()->_RunningPath.c_str());
01429 log.displayNL ("Service log directory: '%s'", IService::getInstance()->_LogDir.c_str());
01430 log.displayNL ("Service config directory: '%s' config filename: '%s.cfg'", IService::getInstance()->_ConfigDir.c_str(), IService::getInstance()->_LongName.c_str());
01431 log.displayNL ("Service id: %d", IService::getInstance()->_SId);
01432 log.displayNL ("Service update timeout: %dms", IService::getInstance()->_UpdateTimeout);
01433 log.displayNL ("Service %suse naming service", IService::getInstance()->_DontUseNS?"don't ":"");
01434 log.displayNL ("Service %suse admin executor service", IService::getInstance()->_DontUseAES?"don't ":"");
01435 #ifdef NL_RELEASE_DEBUG
01436 string mode = "NL_RELEASE_DEBUG";
01437 #elif defined(NL_DEBUG_FAST)
01438 string mode = "NL_DEBUG_FAST";
01439 #elif defined(NL_DEBUG)
01440 string mode = "NL_DEBUG";
01441 #elif defined(NL_RELEASE)
01442 string mode = "NL_RELEASE";
01443 #else
01444 string mode = "???";
01445 #endif
01446 log.displayNL ("NeL is compiled in %s mode", mode.c_str());
01447
01448 nlinfo ("Services arguments: %d args", IService::getInstance()->_Args.size ());
01449 for (uint i = 0; i < IService::getInstance()->_Args.size (); i++)
01450 {
01451 nlinfo (" argv[%d] = '%s'", i, IService::getInstance()->_Args[i].c_str ());
01452 }
01453
01454 log.displayNL ("Naming service info: %s", CNamingClient::info().c_str());
01455
01456 ICommand::execute ("services", log);
01457
01458 return true;
01459 }
01460
01461 NLMISC_COMMAND(resetMeasures, "reset hierarchical timer", "")
01462 {
01463 IService::getInstance()->requireResetMeasures();
01464 return true;
01465 }
01466
01467 NLMISC_COMMAND(displayMeasures, "display hierarchical timer", "")
01468 {
01469 CHTimer::display();
01470 CHTimer::displayHierarchicalByExecutionPathSorted (InfoLog, CHTimer::TotalTime, true, 64);
01471 return true;
01472 }
01473
01474 NLMISC_COMMAND(getWinDisplayerInfo, "display the info about the pos and size of the window displayer", "")
01475 {
01476 uint32 x,y,w,h;
01477 IService::getInstance()->WindowDisplayer->getWindowPos (x,y,w,h);
01478 log.displayNL ("Window Displayer : XWinParam = %d; YWinParam = %d; WWinParam = %d; HWinParam = %d;", x, y, w, h);
01479 return true;
01480 }
01481
01482 NLMISC_COMMAND(printConfigFile, "display the variables of the default configfile", "")
01483 {
01484 IService::getInstance()->ConfigFile.print(&log);
01485 return true;
01486 }
01487
01488 NLMISC_COMMAND(getUnknownConfigFileVariables, "display the variables from config file that are called but not present", "")
01489 {
01490 log.displayNL ("%d Variables not found in the configfile '%s'", IService::getInstance()->ConfigFile.UnknownVariables.size(), IService::getInstance()->ConfigFile.getFilename().c_str() );
01491 for (uint i = 0; i < IService::getInstance()->ConfigFile.UnknownVariables.size(); i++)
01492 {
01493 log.displayNL (" %s", IService::getInstance()->ConfigFile.UnknownVariables[i].c_str());
01494 }
01495 return true;
01496 }
01497
01498 NLMISC_COMMAND (freeze, "Freeze the service for N seconds (for debug purpose)", "<N>")
01499 {
01500 if(args.size() != 1) return false;
01501
01502 sint32 n = atoi (args[0].c_str());
01503
01504 log.displayNL ("Freezing %d seconds", n);
01505
01506 nlSleep(n * 1000);
01507 return true;
01508 }
01509
01510 uint32 foo = 7777, bar = 6666;
01511
01512 NLMISC_VARIABLE(uint32, foo, "test the get view system");
01513 NLMISC_VARIABLE(uint32, bar, "test the get view system");
01514
01515
01516
01517
01518
01519
01520
01521
01522 NLMISC_DYNVARIABLE(string, State, "Set this value to 0 to shutdown the service and 1 to start the service")
01523 {
01524 static string running = "Online";
01525
01526
01527 if (get)
01528 {
01529 *pointer = running;
01530 }
01531 else
01532 {
01533 if (IService::getInstance()->getServiceShortName() == "AES" || IService::getInstance()->getServiceShortName() == "AS")
01534 {
01535 nlinfo ("I can't set State=0 because I'm the admin and I should never quit");
01536 }
01537 else if (*pointer == "0")
01538 {
01539
01540 nlinfo ("User ask me with a command to quit using the State variable");
01541 ExitSignalAsked = 0xFFFE;
01542 running = "Quitting";
01543 }
01544 else
01545 {
01546 nlwarning ("Unknown value for State '%s'", (*pointer).c_str());
01547 }
01548 }
01549 }
01550
01551
01552 }