]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/AliHLTDimServer.cxx
Bug Fix.
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTDimServer.cxx
1 // $Id$
2
3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project        * 
5 //* ALICE Experiment at CERN, All rights reserved.                         *
6 //*                                                                        *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
8 //*                  for The ALICE HLT Project.                            *
9 //*                                                                        *
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 //**************************************************************************
18
19 //  @file   AliHLTDimServer.cxx
20 //  @author Matthias Richter
21 //  @date   2010-03-10
22 //  @brief  HLT DIM server implementation and dynamic access
23 //          to DIM library
24
25 #include "AliHLTDimServer.h"
26 #include "TObjArray.h"
27 #include "TSystem.h"
28 #include "TThread.h"
29
30 /** ROOT macro for the implementation of ROOT specific class methods */
31 ClassImp(AliHLTDimServer)
32
33 AliHLTDimServer::AliHLTDimServer()
34   : TNamed()
35   , fServices()
36   , fState(kStateOff)
37   , fpServerThread(NULL)
38   , fUpdatePeriod(10000)
39 {
40   // see header file for class documentation
41   // or
42   // refer to README to build package
43   // or
44   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
45 }
46
47 AliHLTDimServer::AliHLTDimServer(const char* servername)
48   : TNamed(servername, "AliHLTDimServer")
49   , fServices()
50   , fState(kStateOff)
51   , fpServerThread(NULL)
52   , fUpdatePeriod(10000)
53 {
54   // see header file for class documentation
55 }
56
57 AliHLTDimServer::AliHLTDimInterface* AliHLTDimServer::fgpInterface=NULL;
58
59 AliHLTDimServer::~AliHLTDimServer()
60 {
61   // see header file for class documentation
62 }
63
64 int AliHLTDimServer::RegisterService(AliHLTDimService* pService)
65 {
66   // see header file for class documentation
67   if (!pService) return -EINVAL;
68   if (fServices.FindObject(pService)) {
69     AliHLTLogging log;
70     log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "RegisterService" , __FILE__ , __LINE__ , "duplicate service name %s, skip ...", pService->GetName());
71     return -EEXIST;
72   }
73   fServices.Add(pService);
74   return 0;
75 }
76
77 AliHLTDimServer::AliHLTDimService* AliHLTDimServer::CreateService(enum AliHLTDimServer::AliHLTDimServiceDataType type, const char* name)
78 {
79   // see header file for class documentation
80   AliHLTDimService* service=new AliHLTDimService(type, name);
81   int iResult=RegisterService(service);
82   if (iResult<0) {
83     AliHLTLogging log;
84     log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "CreateService" , __FILE__ , __LINE__ , "failed to register service %s: %d", name, iResult);
85     if (service) delete service;
86     return NULL;
87   }
88   return service;
89 }
90
91 TObjArray* AliHLTDimServer::CreateServiceGroup(enum AliHLTDimServer::AliHLTDimServiceDataType type, const char* basename, int count)
92 {
93   // see header file for class documentation
94   int iResult=0;
95   TObjArray* pServices=new TObjArray;
96   AliHLTLogging log;
97   if (pServices) {
98     if (basename && count>0) {
99       int digits=1;
100       int i=count;
101       while ((i/=10)>0) digits++;
102       if (digits<9) {
103         log.LoggingVarargs(kHLTLogDebug, "AliHLTDimServer", "CreateServiceGroup" , __FILE__ , __LINE__ , "basename=%s count=%d digits=%d\n", basename, count, digits);
104         int namelen=strlen(basename)+2+digits;
105         char* name=(char*)malloc(namelen);
106         char* format=(char*)malloc(namelen); // this has actually only indirect to do with namelen but its appropriate 
107         if (name && format) {
108           const char* key=strchr(basename, '%');
109           strcpy(format, basename);
110           if (key) {
111             int iPos=(key-basename)+1;
112             if (key[1]=='d') {
113               sprintf(format+iPos, "0*d");
114               iPos+=3;
115             } else {
116               *(format+iPos++)='%';
117               *(format+iPos++)=key[1];
118             }
119             strcpy(format+iPos, &key[2]);
120           } else {
121             sprintf(format+strlen(basename), "_%%0*d");
122           }
123           for (i=0; i<count && iResult>=0; i++) {
124             sprintf(name, format, digits, i);
125             AliHLTDimService* service=new AliHLTDimService(type, name);
126             iResult=RegisterService(service);
127           }
128         } else {
129           iResult=-ENOMEM;
130         }
131         if (name) free(name);
132         if (format) free(format);
133       }
134     }
135   }
136   return pServices;
137 }
138
139 int AliHLTDimServer::UpdateServices()
140 {
141   /// Update all services via the Dim channel
142   return 0;
143 }
144
145 AliHLTDimServer::AliHLTDimInterface* AliHLTDimServer::Interface()
146 {
147   // get instance of the interface
148   if (!fgpInterface) {
149     fgpInterface=new AliHLTDimInterface;
150     if (fgpInterface) {
151       fgpInterface->Init();
152     }
153   }
154   return fgpInterface;
155 }
156
157 int AliHLTDimServer::Init(const char* dimNameServer)
158 {
159   // init the dim server, check if the interface is available and set the
160   // DIM DNS node name
161   AliHLTLogging log;
162   const char* myname=GetName();
163   if (myname==NULL || myname[0]==0) {
164     log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Init" , __FILE__ , __LINE__ , "can not start without a server name, skipping initialization ...");
165     return -EINVAL;
166   }
167
168   if (Interface()==NULL) return -ENODEV;
169
170   Interface()->DisSetDnsNode(dimNameServer);
171   return 0;
172 }
173
174 int AliHLTDimServer::Reset()
175 {
176   // reset the DIM server, functionality needs to be clarified
177   return 0;
178 }
179
180 int AliHLTDimServer::Start()
181 {
182   // start the server in a separate thread
183   int iResult=0;
184   AliHLTLogging log;
185   if (GetState()!=kStateOff) {
186     log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Start" , __FILE__ , __LINE__ , "server is not off, currently in state %d", GetState());
187     return -ENOENT;
188   }
189   fpServerThread=new TThread(ServerLoop, (void*)this);
190   if (!fpServerThread) {
191     log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Start" , __FILE__ , __LINE__ , "unable to create server thread");
192     return -ENOMEM;
193   }
194   SetState(kStateStarting);
195   fpServerThread->Run();
196   
197   int count=0;
198   const int maxcount=100;
199   const int maxsleepms=1000;
200   while (GetState()==kStateStarting) {
201     if (count++==maxcount) break;
202     gSystem->Sleep(maxsleepms/maxcount);
203   }
204
205   if (GetState()!=kStateRunning) {
206     log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Start" , __FILE__ , __LINE__ , "could not start server, currently in state %d", GetState());
207     Reset();
208     iResult=-EFAULT;
209   }
210   return iResult;
211 }
212
213 int AliHLTDimServer::Stop() 
214 {
215   // stop the server thread
216   int iResult=0;
217   AliHLTLogging log;
218   if (GetState()!=kStateRunning) {
219     log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Stop" , __FILE__ , __LINE__ , "server is not running, currently in state %d", GetState());
220     return -ENOENT;
221   }
222   SetState(kStateStopping);
223   int count=0;
224   const int maxcount=100;
225   const int maxsleepms=2*fUpdatePeriod;
226   while (GetState()==kStateStopping) {
227     if (count++==maxcount) break;
228     gSystem->Sleep(maxsleepms/maxcount);
229   }
230
231   if (GetState()!=kStateOff) {
232     log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Stop" , __FILE__ , __LINE__ , "could not stop server, currently in state %d", GetState());
233     Reset();
234     iResult=-EFAULT;
235   }
236   return iResult;
237 }
238
239 void* AliHLTDimServer::ServerLoop(void* param)
240 {
241   // see header file for class documentation
242   if (!param) return (void*)0;
243   AliHLTDimServer* server=reinterpret_cast<AliHLTDimServer*>(param);
244   return server->ServerLoop();
245 }
246
247 void* AliHLTDimServer::ServerLoop()
248 {
249   // see header file for class documentation
250   if (!Interface()) return (void*)-ENODEV;
251
252   AliHLTLogging log;
253   TIter next(&fServices);
254   TObject* obj=NULL;
255   while ((obj=next())!=NULL) {
256     AliHLTDimService* pService=dynamic_cast<AliHLTDimService*>(obj);
257     if (!pService) continue;
258     TString name=GetName(); name+="_"; name+=pService->GetName();
259     const char* type="";
260     void* buffer=pService->GetLocation();
261     int size=0;
262     switch (pService->GetType()) {
263     case kDataTypeInt:
264       type="I";
265       size=sizeof(int);
266       break;
267     case kDataTypeFloat:
268       type="F";
269       size=sizeof(float);
270       break;
271     case kDataTypeString:
272       log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "ServerLoop" , __FILE__ , __LINE__ , "ignoring dim service %s: type 'string' not yet implemented", name.Data());
273       break;
274     default:
275       log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "ServerLoop" , __FILE__ , __LINE__ , "ignoring dim service %s: unknown type %d", name.Data(), pService->GetType());
276     }
277     if (type[0]!=0) {
278       int id=Interface()->DisAddService(name.Data(), type, buffer, size);
279       if (id<0) {
280         log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "ServerLoop" , __FILE__ , __LINE__ , "failed to add dim service %s: error %d", name.Data(), id);
281       } else {
282          pService->SetId(id);
283       }
284     }
285   }
286
287   SetState(kStateRunning);
288   Interface()->DisStartServing(GetName());
289   while (GetState()==kStateRunning) {
290     gSystem->Sleep(fUpdatePeriod);
291   }
292
293   if (GetState()!=kStateStopping) return (void*)0;
294
295   // cleanup
296   Interface()->DisStopServing();
297   next.Reset();
298   while ((obj=next())!=NULL) {
299     const AliHLTDimService* pService=dynamic_cast<const AliHLTDimService*>(obj);
300     if (!pService || pService->GetId()<0) continue;
301     // int iResult=Interface()->DisRemoveService(pService->GetId());
302     // if (iResult<0) {
303     //   log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "ServerLoop" , __FILE__ , __LINE__ , "failed to remove dim service %s: error %d", pService->GetName(), iResult);
304     // }
305   }
306
307   SetState(kStateOff);
308
309   return (void*)0;
310 }
311
312 AliHLTDimServer::AliHLTDimService::AliHLTDimService()
313   : TNamed()
314   , fData()
315   , fType(kDataTypeUnknown)
316   , fId(-1)
317 {
318   // see header file for class documentation
319 }
320
321 AliHLTDimServer::AliHLTDimService::AliHLTDimService(enum AliHLTDimServiceDataType type, const char* servicename)
322   : TNamed(servicename, "AliHLTDimService")
323   , fData()
324   , fType(type)
325   , fId(-1)
326 {
327   // see header file for class documentation
328   AliHLTLogging log;
329   switch (fType) {
330   case kDataTypeInt: break;
331   case kDataTypeFloat: break;
332   case kDataTypeString:
333     log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "AliHLTDimService" , __FILE__ , __LINE__ , "dim service type 'string' not yet implemented");
334     break;
335   default:
336     log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "AliHLTDimService" , __FILE__ , __LINE__ , "Unknown dim service type %d", fType);
337   };
338 }
339
340 void AliHLTDimServer::AliHLTDimService::Update(const AliHLTDimServicePoint_t& sp)
341 {
342   // see header file for class documentation
343   static bool bWarning=true;
344   AliHLTLogging log;
345   switch (fType) {
346   case kDataTypeInt: fData.iVal=sp.iVal; break;
347   case kDataTypeFloat: fData.fVal=sp.fVal; break;
348   case kDataTypeString:
349     if (bWarning) log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "Update" , __FILE__ , __LINE__ , "Failed to update dim service %s: 'string' not yet implemented", GetName());
350     bWarning=false;
351     break;
352   default:
353     if (bWarning) log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "Update" , __FILE__ , __LINE__ , "Failed to update dim service %s: unknown type %d", GetName(), fType);
354     bWarning=false;
355   };
356
357   AliHLTDimServer::Interface()->DisUpdateService(fId);
358 }
359
360 AliHLTDimServer::AliHLTDimInterface::AliHLTDimInterface()
361   : AliHLTLogging()
362   , fpDisAddService(NULL)
363   , fpDisRemoveService(NULL)
364   , fpDisUpdateService(NULL)
365   , fpDisStartServing(NULL)
366   , fpDisStopServing(NULL)
367   , fpDisSetDnsNode(NULL)
368 {
369 }
370
371 AliHLTDimServer::AliHLTDimInterface::~AliHLTDimInterface()
372 {
373 }
374
375
376 const char* AliHLTDimServer::AliHLTDimInterface::fgkDimLibraryName="libdim.so";
377 const char* AliHLTDimServer::AliHLTDimInterface::fgkDisAddServiceSymbol="dis_add_service";
378 const char* AliHLTDimServer::AliHLTDimInterface::fgkDisRemoveServiceSymbol="dis_remove_service";
379 const char* AliHLTDimServer::AliHLTDimInterface::fgkDisUpdateServiceSymbol="dis_update_service";
380 const char* AliHLTDimServer::AliHLTDimInterface::fgkDisStartServingSymbol="dis_start_serving";
381 const char* AliHLTDimServer::AliHLTDimInterface::fgkDisStopServingSymbol="dis_stop_serving";
382 const char* AliHLTDimServer::AliHLTDimInterface::fgkDisSetDnsNodeSymbol="dis_set_dns_node";
383
384 int AliHLTDimServer::AliHLTDimInterface::Init()
385 {
386   /// load the dim library and function pointers
387   if (gSystem->Load(fgkDimLibraryName)) {
388     HLTFatal("failed to load dim library: %s", fgkDimLibraryName);
389     return -ENODEV;
390   }
391
392   fpDisAddService=(fctDisAddService)FindSymbol(fgkDimLibraryName, fgkDisAddServiceSymbol);
393   if (!fpDisAddService) return -ENODEV;
394
395   fpDisRemoveService=(fctDisRemoveService)FindSymbol(fgkDimLibraryName, fgkDisRemoveServiceSymbol);
396   if (!fpDisRemoveService) return -ENODEV;
397
398   fpDisUpdateService=(fctDisUpdateService)FindSymbol(fgkDimLibraryName, fgkDisUpdateServiceSymbol);
399   if (!fpDisUpdateService) return -ENODEV;
400
401   fpDisStartServing=(fctDisCharArg)FindSymbol(fgkDimLibraryName, fgkDisStartServingSymbol);
402   if (!fpDisStartServing) return -ENODEV;
403
404   fpDisStopServing=(fctDisNoArg)FindSymbol(fgkDimLibraryName, fgkDisStopServingSymbol);
405   if (!fpDisStopServing) return -ENODEV;
406
407   fpDisSetDnsNode=(fctDisCharArg)FindSymbol(fgkDimLibraryName, fgkDisSetDnsNodeSymbol);
408   if (!fpDisSetDnsNode) return -ENODEV;
409
410   return 0;
411 }
412
413 AliHLTDimServer::fctVoid AliHLTDimServer::AliHLTDimInterface::FindSymbol(const char* library, const char* symbol) const
414 {
415   /// Find symbol in the dim library
416   TString tmp=symbol;
417   fctVoid fctptr=gSystem->DynFindSymbol(library, tmp.Data());
418   if (!fctptr) {
419     // do a 2nd try with appended '_'
420     tmp+="_";
421     fctptr=gSystem->DynFindSymbol(library, tmp.Data());
422   }
423   if (fctptr) return fctptr;
424
425   HLTError("can not find symbol '%s' in %s", symbol, library);
426   return NULL;
427 }