3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project *
5 //* ALICE Experiment at CERN, All rights reserved. *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8 //* for The ALICE HLT Project. *
10 //* Permission to use, copy, modify and distribute this software and its *
11 //* documentation strictly for non-commercial purposes is hereby granted *
12 //* without fee, provided that the above copyright notice appears in all *
13 //* copies and that both the copyright notice and this permission notice *
14 //* appear in the supporting documentation. The authors make no claims *
15 //* about the suitability of this software for any purpose. It is *
16 //* provided "as is" without express or implied warranty. *
17 //**************************************************************************
19 // @file AliHLTDimServer.cxx
20 // @author Matthias Richter
22 // @brief HLT DIM server implementation and dynamic access
25 #include "AliHLTDimServer.h"
26 #include "TObjArray.h"
30 /** ROOT macro for the implementation of ROOT specific class methods */
31 ClassImp(AliHLTDimServer)
33 AliHLTDimServer::AliHLTDimServer()
37 , fpServerThread(NULL)
38 , fUpdatePeriod(10000)
40 // see header file for class documentation
42 // refer to README to build package
44 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
47 AliHLTDimServer::AliHLTDimServer(const char* servername)
48 : TNamed(servername, "AliHLTDimServer")
51 , fpServerThread(NULL)
52 , fUpdatePeriod(10000)
54 // see header file for class documentation
57 AliHLTDimServer::AliHLTDimInterface* AliHLTDimServer::fgpInterface=NULL;
59 AliHLTDimServer::~AliHLTDimServer()
61 // see header file for class documentation
64 int AliHLTDimServer::RegisterService(AliHLTDimService* pService)
66 // see header file for class documentation
67 if (!pService) return -EINVAL;
68 if (fServices.FindObject(pService)) {
70 log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "RegisterService" , __FILE__ , __LINE__ , "duplicate service name %s, skip ...", pService->GetName());
73 fServices.Add(pService);
77 AliHLTDimServer::AliHLTDimService* AliHLTDimServer::CreateService(enum AliHLTDimServer::AliHLTDimServiceDataType type, const char* name)
79 // see header file for class documentation
80 AliHLTDimService* service=new AliHLTDimService(type, name);
81 int iResult=RegisterService(service);
84 log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "CreateService" , __FILE__ , __LINE__ , "failed to register service %s: %d", name, iResult);
85 if (service) delete service;
91 TObjArray* AliHLTDimServer::CreateServiceGroup(enum AliHLTDimServer::AliHLTDimServiceDataType type, const char* basename, int count)
93 // see header file for class documentation
95 TObjArray* pServices=new TObjArray;
98 if (basename && count>0) {
101 while ((i/=10)>0) digits++;
103 log.LoggingVarargs(kHLTLogDebug, "AliHLTDimServer", "CreateServiceGroup" , __FILE__ , __LINE__ , "basename=%s count=%d digits=%d\n", basename, count, digits);
104 // length of name is at max strlen(basename) + 1 '_' + digits + 1 terminating zero
105 // length of format is independent of number of digits
106 // at max we need strlen(basename) + 5 chars + 1 terminating zero
107 int namelen=strlen(basename)+5+digits;
108 char* name=(char*)malloc(namelen);
109 char* format=(char*)malloc(namelen);
110 if (name && format) {
111 memset(name, 0, namelen);
112 memset(format, 0, namelen);
113 const char* key=strchr(basename, '%');
114 strncpy(format, basename, namelen-1);
115 if (key && key[1]!=0) {
116 int iPos=(key-basename)+1;
118 snprintf(format+iPos, namelen-iPos, "0*d"); // additional 3 chars
121 *(format+iPos++)='%';
122 *(format+iPos++)=key[1];
124 strncpy(format+iPos, &key[2], namelen-1-iPos);
126 snprintf(format+strlen(basename), namelen-strlen(basename), "_%%0*d"); // additional 5 chars
128 for (i=0; i<count && iResult>=0; i++) {
129 snprintf(name, namelen, format, digits, i);
130 AliHLTDimService* service=new AliHLTDimService(type, name);
131 iResult=RegisterService(service);
136 if (name) free(name);
137 if (format) free(format);
144 int AliHLTDimServer::UpdateServices()
146 /// Update all services via the Dim channel
150 AliHLTDimServer::AliHLTDimInterface* AliHLTDimServer::Interface()
152 // get instance of the interface
154 fgpInterface=new AliHLTDimInterface;
156 if (fgpInterface->Init() != 0) {
165 int AliHLTDimServer::Init(const char* dimNameServer)
167 // init the dim server, check if the interface is available and set the
170 const char* myname=GetName();
171 if (myname==NULL || myname[0]==0) {
172 log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Init" , __FILE__ , __LINE__ , "can not start without a server name, skipping initialization ...");
176 if (Interface()==NULL) return -ENODEV;
178 Interface()->DisSetDnsNode(dimNameServer);
182 int AliHLTDimServer::Reset()
184 // reset the DIM server, functionality needs to be clarified
188 int AliHLTDimServer::Start()
190 // start the server in a separate thread
193 if (GetState()!=kStateOff) {
194 log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Start" , __FILE__ , __LINE__ , "server is not off, currently in state %d", GetState());
197 fpServerThread=new TThread(ServerLoop, (void*)this);
198 if (!fpServerThread) {
199 log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Start" , __FILE__ , __LINE__ , "unable to create server thread");
202 SetState(kStateStarting);
203 fpServerThread->Run();
206 const int maxcount=100;
207 const int maxsleepms=1000;
208 while (GetState()==kStateStarting) {
209 if (count++==maxcount) break;
210 gSystem->Sleep(maxsleepms/maxcount);
213 if (GetState()!=kStateRunning) {
214 log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Start" , __FILE__ , __LINE__ , "could not start server, currently in state %d", GetState());
221 int AliHLTDimServer::Stop()
223 // stop the server thread
226 if (GetState()!=kStateRunning) {
227 log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Stop" , __FILE__ , __LINE__ , "server is not running, currently in state %d", GetState());
230 SetState(kStateStopping);
232 const int maxcount=100;
233 const int maxsleepms=2*fUpdatePeriod;
234 while (GetState()==kStateStopping) {
235 if (count++==maxcount) break;
236 gSystem->Sleep(maxsleepms/maxcount);
239 if (GetState()!=kStateOff) {
240 log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Stop" , __FILE__ , __LINE__ , "could not stop server, currently in state %d", GetState());
247 void* AliHLTDimServer::ServerLoop(void* param)
249 // see header file for class documentation
250 if (!param) return (void*)0;
251 AliHLTDimServer* server=reinterpret_cast<AliHLTDimServer*>(param);
252 return server->ServerLoop();
255 void* AliHLTDimServer::ServerLoop()
257 // see header file for class documentation
258 if (!Interface()) return (void*)-ENODEV;
261 TIter next(&fServices);
263 while ((obj=next())!=NULL) {
264 AliHLTDimService* pService=dynamic_cast<AliHLTDimService*>(obj);
265 if (!pService) continue;
266 TString name=GetName(); name+="_"; name+=pService->GetName();
268 void* buffer=pService->GetLocation();
270 switch (pService->GetType()) {
271 case kDataTypeCustom:
274 type=pService->GetTypeString();
275 size=pService->GetDataSize();
277 case kDataTypeString:
278 log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "ServerLoop" , __FILE__ , __LINE__ , "ignoring dim service %s: type 'string' not yet implemented", name.Data());
281 log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "ServerLoop" , __FILE__ , __LINE__ , "ignoring dim service %s: unknown type %d", name.Data(), pService->GetType());
284 int id=Interface()->DisAddService(name.Data(), type, buffer, size);
286 log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "ServerLoop" , __FILE__ , __LINE__ , "failed to add dim service %s: error %d", name.Data(), id);
293 SetState(kStateRunning);
294 Interface()->DisStartServing(GetName());
295 while (GetState()==kStateRunning) {
296 gSystem->Sleep(fUpdatePeriod);
299 if (GetState()!=kStateStopping) return (void*)0;
302 Interface()->DisStopServing();
304 while ((obj=next())!=NULL) {
305 const AliHLTDimService* pService=dynamic_cast<const AliHLTDimService*>(obj);
306 if (!pService || pService->GetId()<0) continue;
307 // int iResult=Interface()->DisRemoveService(pService->GetId());
309 // log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "ServerLoop" , __FILE__ , __LINE__ , "failed to remove dim service %s: error %d", pService->GetName(), iResult);
318 AliHLTDimServer::AliHLTDimService::AliHLTDimService()
321 , fType(kDataTypeUnknown)
327 // see header file for class documentation
330 AliHLTDimServer::AliHLTDimService::AliHLTDimService(enum AliHLTDimServiceDataType type, const char* servicename)
331 : TNamed(servicename, "AliHLTDimService")
339 // see header file for class documentation
342 case kDataTypeCustom:
343 log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "AliHLTDimService" , __FILE__ , __LINE__ , "cannot use the kDataTypeCustom type with this method");
347 fDataBuffer=&fData.iVal;
348 fDataSize=sizeof(int);
352 fDataBuffer=&fData.fVal;
353 fDataSize=sizeof(float);
355 case kDataTypeString:
356 log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "AliHLTDimService" , __FILE__ , __LINE__ , "dim service type 'string' not yet implemented");
359 log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "AliHLTDimService" , __FILE__ , __LINE__ , "Unknown dim service type %d", fType);
363 AliHLTDimServer::AliHLTDimService::AliHLTDimService(const char* type, void* data, int size, const char* servicename)
364 : TNamed(servicename, "AliHLTDimService")
366 , fType(kDataTypeCustom)
372 // see header file for class documentation
375 void AliHLTDimServer::AliHLTDimService::Update()
377 // see header file for class documentation
378 static bool bWarning=true;
381 case kDataTypeCustom: break;
383 if (bWarning) log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "Update" , __FILE__ , __LINE__ , "The service %s must be a custom type (kDataTypeCustom) to use this form of Update", GetName());
387 AliHLTDimServer::Interface()->DisUpdateService(fId);
390 void AliHLTDimServer::AliHLTDimService::Update(const AliHLTDimServicePoint_t& sp)
392 // see header file for class documentation
393 static bool bWarning=true;
396 case kDataTypeCustom:
397 if (bWarning) log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "Update" , __FILE__ , __LINE__ , "Should not call this form of Update for custom type (kDataTypeCustom) service %s", GetName());
400 case kDataTypeInt: fData.iVal=sp.iVal; break;
401 case kDataTypeFloat: fData.fVal=sp.fVal; break;
402 case kDataTypeString:
403 if (bWarning) log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "Update" , __FILE__ , __LINE__ , "Failed to update dim service %s: 'string' not yet implemented", GetName());
407 if (bWarning) log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "Update" , __FILE__ , __LINE__ , "Failed to update dim service %s: unknown type %d", GetName(), fType);
411 AliHLTDimServer::Interface()->DisUpdateService(fId);
414 AliHLTDimServer::AliHLTDimInterface::AliHLTDimInterface()
416 , fpDisAddService(NULL)
417 , fpDisRemoveService(NULL)
418 , fpDisUpdateService(NULL)
419 , fpDisStartServing(NULL)
420 , fpDisStopServing(NULL)
421 , fpDisSetDnsNode(NULL)
425 AliHLTDimServer::AliHLTDimInterface::~AliHLTDimInterface()
430 const char* AliHLTDimServer::AliHLTDimInterface::fgkDimLibraryName="libdim.so";
431 const char* AliHLTDimServer::AliHLTDimInterface::fgkDisAddServiceSymbol="dis_add_service";
432 const char* AliHLTDimServer::AliHLTDimInterface::fgkDisRemoveServiceSymbol="dis_remove_service";
433 const char* AliHLTDimServer::AliHLTDimInterface::fgkDisUpdateServiceSymbol="dis_update_service";
434 const char* AliHLTDimServer::AliHLTDimInterface::fgkDisStartServingSymbol="dis_start_serving";
435 const char* AliHLTDimServer::AliHLTDimInterface::fgkDisStopServingSymbol="dis_stop_serving";
436 const char* AliHLTDimServer::AliHLTDimInterface::fgkDisSetDnsNodeSymbol="dis_set_dns_node";
438 int AliHLTDimServer::AliHLTDimInterface::Init()
440 /// load the dim library and function pointers
441 if (gSystem->Load(fgkDimLibraryName)) {
442 HLTFatal("failed to load dim library: %s", fgkDimLibraryName);
446 fpDisAddService=(fctDisAddService)FindSymbol(fgkDimLibraryName, fgkDisAddServiceSymbol);
447 if (!fpDisAddService) return -ENODEV;
449 fpDisRemoveService=(fctDisRemoveService)FindSymbol(fgkDimLibraryName, fgkDisRemoveServiceSymbol);
450 if (!fpDisRemoveService) return -ENODEV;
452 fpDisUpdateService=(fctDisUpdateService)FindSymbol(fgkDimLibraryName, fgkDisUpdateServiceSymbol);
453 if (!fpDisUpdateService) return -ENODEV;
455 fpDisStartServing=(fctDisCharArg)FindSymbol(fgkDimLibraryName, fgkDisStartServingSymbol);
456 if (!fpDisStartServing) return -ENODEV;
458 fpDisStopServing=(fctDisNoArg)FindSymbol(fgkDimLibraryName, fgkDisStopServingSymbol);
459 if (!fpDisStopServing) return -ENODEV;
461 fpDisSetDnsNode=(fctDisCharArg)FindSymbol(fgkDimLibraryName, fgkDisSetDnsNodeSymbol);
462 if (!fpDisSetDnsNode) return -ENODEV;
467 AliHLTDimServer::fctVoid AliHLTDimServer::AliHLTDimInterface::FindSymbol(const char* library, const char* symbol) const
469 /// Find symbol in the dim library
471 fctVoid fctptr=gSystem->DynFindSymbol(library, tmp.Data());
473 // do a 2nd try with appended '_'
475 fctptr=gSystem->DynFindSymbol(library, tmp.Data());
477 if (fctptr) return fctptr;
479 HLTError("can not find symbol '%s' in %s", symbol, library);