00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef NL_SERVICE_H
00026 #define NL_SERVICE_H
00027
00028
00029
00030
00031
00032 #include "nel/misc/types_nl.h"
00033
00034 #if defined(NL_OS_WINDOWS) && defined(_WINDOWS)
00035 # define NOMINMAX
00036 # include <windows.h>
00037 #endif
00038
00039 #include "nel/misc/config_file.h"
00040 #include "nel/misc/entity_id.h"
00041 #include "nel/misc/variable.h"
00042 #include "nel/misc/command.h"
00043 #include "nel/misc/entity_id.h"
00044 #include "nel/misc/cpu_time_stat.h"
00045 #include "nel/misc/sstring.h"
00046
00047 #include "unified_network.h"
00048
00049 #include <string>
00050 #include <vector>
00051
00052 namespace NLMISC
00053 {
00054 class CWindowDisplayer;
00055 }
00056
00057
00058 namespace NLNET
00059 {
00060
00061 class CCallbackServer;
00062 class IServiceUpdatable;
00063
00064
00065
00066
00067
00068
00069
00115 #if defined(NL_OS_WINDOWS) && defined(_WINDOWS)
00116 #define NLNET_SERVICE_MAIN(__ServiceClassName, __ServiceShortName, __ServiceLongName, __ServicePort, __ServiceCallbackArray, __ConfigDir, __LogDir) \
00117 \
00118 int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) \
00119 { \
00120 NLMISC::CApplicationContext serviceContext; \
00121 __ServiceClassName *scn = new __ServiceClassName; \
00122 scn->setArgs (lpCmdLine); \
00123 createDebug(NULL,!scn->haveLongArg("nolog"));\
00124 scn->setCallbackArray (__ServiceCallbackArray, sizeof(__ServiceCallbackArray)/sizeof(__ServiceCallbackArray[0])); \
00125 sint retval = scn->main (__ServiceShortName, __ServiceLongName, __ServicePort, __ConfigDir, __LogDir, __DATE__" "__TIME__); \
00126 delete scn; \
00127 return retval; \
00128 }
00129
00130 #else
00131 #define NLNET_SERVICE_MAIN(__ServiceClassName, __ServiceShortName, __ServiceLongName, __ServicePort, __ServiceCallbackArray, __ConfigDir, __LogDir) \
00132 \
00133 int main(int argc, const char **argv) \
00134 { \
00135 NLMISC::CApplicationContext serviceContext; \
00136 __ServiceClassName *scn = new __ServiceClassName; \
00137 scn->setArgs (argc, argv); \
00138 createDebug(NULL,!scn->haveLongArg("nolog"));\
00139 scn->setCallbackArray (__ServiceCallbackArray, sizeof(__ServiceCallbackArray)/sizeof(__ServiceCallbackArray[0])); \
00140 sint retval = scn->main (__ServiceShortName, __ServiceLongName, __ServicePort, __ConfigDir, __LogDir, __DATE__" "__TIME__); \
00141 delete scn; \
00142 return retval; \
00143 }
00144
00145 #endif
00146
00147 #define DEFAULT_SHARD_ID 666
00148
00149
00150
00151
00152
00153
00154
00155
00157 typedef bool (*TRequestClosureClearanceCallback) ();
00158
00159
00160
00161
00162
00163 extern TUnifiedCallbackItem EmptyCallbackArray[1];
00164
00165
00166
00167
00168
00169
00186 class IService
00187 {
00188 public:
00189
00191
00192
00195 virtual void commandStart () {}
00196
00198 virtual void init () {}
00199
00201 virtual bool update () { return true; }
00202
00204 virtual void release () {}
00205
00207
00208
00210
00211
00213 static IService *getInstance ();
00214
00216 static bool isServiceInitialized() { return _Instance != NULL; }
00217
00219 const std::string &getServiceShortName () const { return _ShortName; };
00220
00222 const std::string &getServiceLongName () const { return _LongName; };
00223
00225 const std::string &getServiceAliasName () const { return _AliasName; };
00226
00228 std::string getServiceUnifiedName () const;
00229
00231 TServiceId getServiceId () const { return _SId; }
00232
00234 const std::string &getHostName() const { return _HostName; }
00235
00237 sint getExitStatus () const { return _ExitStatus; }
00238
00240 uint32 getLaunchingDate () const;
00241
00243 bool getDontUseNS() const { return _DontUseNS; };
00244
00246 bool getDontUseAES() const { return _DontUseAES; };
00247
00249 const NLMISC::CVectorSString &getArgs () const { return _Args; }
00250
00252 bool haveArg (char argName) const;
00253
00259 std::string getArg (char argName) const;
00260
00263 bool haveLongArg (const char* argName) const;
00264
00268 std::string getLongArg (const char* argName) const;
00269
00271
00272
00273
00274
00275
00277 CCallbackNetBase::TRecordingState getRecordingState() const { return _RecordingState; }
00278
00279
00281
00282
00284
00285
00290 void setExitStatus (sint exitStatus) { _ExitStatus = exitStatus; }
00291
00294 void exit (sint code = 0x10);
00295
00303 void setUpdateTimeout (NLMISC::TTime timeout) { _UpdateTimeout = timeout; }
00304
00306
00308
00310 void setCurrentStatus(const std::string &status);
00312 void clearCurrentStatus(const std::string &status);
00314 void addStatusTag(const std::string &statusTag);
00316 void removeStatusTag(const std::string &statusTag);
00318 std::string getFullStatus() const;
00320
00322
00323
00324 NLMISC::CConfigFile ConfigFile;
00325
00326
00327 NLMISC::CLog CommandLog;
00328
00330
00331
00333
00334
00336 sint main (const char *serviceShortName, const char *serviceLongName, uint16 servicePort, const char *configDir, const char *logDir, const char *compilationDate);
00337
00339 void setArgs (int argc, const char **argv);
00340
00342 void setArgs (const char *args);
00343
00345 void setCallbackArray (TUnifiedCallbackItem *array, uint nbelem) { _CallbackArray = array; _CallbackArraySize = nbelem; }
00346
00348 void requireResetMeasures();
00349
00351 IService ();
00352
00354 virtual ~IService ();
00355
00357
00359
00360
00361 void registerUpdatable(IServiceUpdatable *updatable);
00363 void unregisterUpdatable(IServiceUpdatable *updatable);
00365
00367 NLMISC::CWindowDisplayer *WindowDisplayer;
00368
00371 NLMISC::CVariable<std::string> WriteFilesDirectory;
00372
00375 NLMISC::CVariable<std::string> SaveFilesDirectory;
00376
00378 NLMISC::CVariable<bool> ConvertSavesFilesDirectoryToFullPath;
00379
00384 void setDirectoryChangeCallback( NLMISC::IVariableChangedCallback *cbi ) { _DirectoryChangedCBI = cbi; }
00385
00386 void setVersion (const std::string &version) { Version = version; }
00387
00388 uint16 getPort() { return ListeningPort; }
00389
00390
00391 uint32 getShardId() const { return _ShardId; }
00392
00393 const NLMISC::CCPUTimeStat& getCPUUsageStats() const { return _CPUUsageStats; }
00394
00396 virtual std::string getServiceStatusString() const;
00397
00407 void setClosureClearanceCallback( TRequestClosureClearanceCallback cb ) { _RequestClosureClearanceCallback = cb; }
00408
00415 void clearForClosure() { _ClosureClearanceStatus = CCClearedForClosure; }
00416
00421 void anticipateShardId( uint32 shardId );
00422
00423 private:
00424
00426
00427
00429 void setRecordingState( CCallbackNetBase::TRecordingState rec ) { _RecordingState = rec; }
00430
00433 void setShardId( uint32 shardId );
00434
00436
00438
00439
00441 NLMISC::CVectorSString _Args;
00442
00444 std::string _HostName;
00446 NLMISC::CVariable<uint16> ListeningPort;
00447
00449 CCallbackNetBase::TRecordingState _RecordingState;
00450
00452 std::string _ShortName;
00453 std::string _LongName;
00454 std::string _AliasName;
00455
00457 static IService *_Instance;
00458
00460 NLMISC::TTime _UpdateTimeout;
00461
00463 TServiceId _SId;
00464
00466 sint _ExitStatus;
00467
00469 bool _Initialized;
00470
00472 NLMISC::CVariable<std::string> ConfigDirectory;
00473
00475 NLMISC::CVariable<std::string> LogDirectory;
00476
00478 NLMISC::CVariable<std::string> RunningDirectory;
00479
00480 NLMISC::CVariable<std::string> Version;
00481
00482 TUnifiedCallbackItem *_CallbackArray;
00483 uint _CallbackArraySize;
00484
00486 bool _DontUseNS;
00488 bool _DontUseAES;
00489
00491 bool _ResetMeasures;
00492
00494 uint32 _ShardId;
00495
00497 NLMISC::CCPUTimeStat _CPUUsageStats;
00498
00500 std::set<IServiceUpdatable*> _Updatables;
00501
00503
00505 std::vector<std::string> _ServiceStatusStack;
00507 std::set<std::string> _ServiveStatusTags;
00509
00510 enum TClosureClearanceStatus { CCMustRequestClearance, CCWaitingForClearance, CCClearedForClosure, CCCallbackThenClose=256 };
00511
00513 uint _ClosureClearanceStatus;
00514
00516 TRequestClosureClearanceCallback _RequestClosureClearanceCallback;
00517
00519 NLMISC::IVariableChangedCallback* _DirectoryChangedCBI;
00520
00521 friend void serviceGetView (uint32 rid, const std::string &rawvarpath, std::vector<std::string> &vara, std::vector<std::string> &vala);
00522 friend void cbAESConnection (const std::string &serviceName, TServiceId sid, void *arg);
00523 friend struct nel_serviceInfoClass;
00524 friend struct nel_getWinDisplayerInfoClass;
00525 friend void cbDirectoryChanged (NLMISC::IVariable &var);
00526 friend void cbReceiveShardId (NLNET::CMessage& msgin, const std::string &serviceName, TServiceId serviceId);
00527
00528 NLMISC_CATEGORISED_DYNVARIABLE_FRIEND(nel, State);
00529 };
00530
00531
00534 class IServiceUpdatable
00535 {
00536 public:
00537 IServiceUpdatable()
00538 {
00539 if (IService::isServiceInitialized())
00540 {
00541 IService::getInstance()->registerUpdatable(this);
00542 }
00543 else
00544 {
00545 nlwarning("IServiceUpdatable : IService is not initialized, IUpdatable will not be called");
00546 }
00547 }
00548 virtual ~IServiceUpdatable()
00549 {
00550 if (IService::isServiceInitialized())
00551 {
00552 IService *service = IService::getInstance();
00553
00554 service->unregisterUpdatable(this);
00555 }
00556 }
00557
00559 virtual void serviceLoopUpdate() =0;
00560 };
00561
00562
00563 inline IService *IService::getInstance()
00564 {
00565 if (_Instance == NULL)
00566 {
00567
00568 nlassertex(NLMISC::INelContext::isContextInitialised(), ("You are trying to access a safe singleton without having initialized a NeL context. The simplest correction is to add 'NLMISC::CApplicationContext myApplicationContext;' at the very begining of your application."));
00569
00570 _Instance = reinterpret_cast<IService*>(NLMISC::INelContext::getInstance().getSingletonPointer("IService"));
00571 }
00572 return _Instance;
00573 }
00574
00575
00576
00577 };
00578
00579 #endif // NL_SERVICE_H
00580
00581