Line data Source code
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 126 : ClassImp(AliHLTDimServer)
32 :
33 : AliHLTDimServer::AliHLTDimServer()
34 0 : : TNamed()
35 0 : , fServices()
36 0 : , fState(kStateOff)
37 0 : , fpServerThread(NULL)
38 0 : , fUpdatePeriod(10000)
39 0 : {
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 0 : }
46 :
47 : AliHLTDimServer::AliHLTDimServer(const char* servername)
48 0 : : TNamed(servername, "AliHLTDimServer")
49 0 : , fServices()
50 0 : , fState(kStateOff)
51 0 : , fpServerThread(NULL)
52 0 : , fUpdatePeriod(10000)
53 0 : {
54 : // see header file for class documentation
55 0 : }
56 :
57 : AliHLTDimServer::AliHLTDimInterface* AliHLTDimServer::fgpInterface=NULL;
58 :
59 : AliHLTDimServer::~AliHLTDimServer()
60 0 : {
61 : // see header file for class documentation
62 0 : }
63 :
64 : int AliHLTDimServer::RegisterService(AliHLTDimService* pService)
65 : {
66 : // see header file for class documentation
67 0 : if (!pService) return -EINVAL;
68 0 : if (fServices.FindObject(pService)) {
69 0 : AliHLTLogging log;
70 0 : log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "RegisterService" , __FILE__ , __LINE__ , "duplicate service name %s, skip ...", pService->GetName());
71 : return -EEXIST;
72 0 : }
73 0 : fServices.Add(pService);
74 0 : return 0;
75 0 : }
76 :
77 : AliHLTDimServer::AliHLTDimService* AliHLTDimServer::CreateService(enum AliHLTDimServer::AliHLTDimServiceDataType type, const char* name)
78 : {
79 : // see header file for class documentation
80 0 : AliHLTDimService* service=new AliHLTDimService(type, name);
81 0 : int iResult=RegisterService(service);
82 0 : if (iResult<0) {
83 0 : AliHLTLogging log;
84 0 : log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "CreateService" , __FILE__ , __LINE__ , "failed to register service %s: %d", name, iResult);
85 0 : if (service) delete service;
86 : return NULL;
87 0 : }
88 0 : return service;
89 0 : }
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 0 : TObjArray* pServices=new TObjArray;
96 0 : AliHLTLogging log;
97 0 : if (pServices) {
98 0 : if (basename && count>0) {
99 : int digits=1;
100 : int i=count;
101 0 : while ((i/=10)>0) digits++;
102 0 : if (digits<9) {
103 0 : 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 0 : int namelen=strlen(basename)+5+digits;
108 0 : char* name=(char*)malloc(namelen);
109 0 : char* format=(char*)malloc(namelen);
110 0 : if (name && format) {
111 0 : memset(name, 0, namelen);
112 0 : memset(format, 0, namelen);
113 0 : const char* key=strchr(basename, '%');
114 0 : strncpy(format, basename, namelen-1);
115 0 : if (key && key[1]!=0) {
116 0 : int iPos=(key-basename)+1;
117 0 : if (key[1]=='d') {
118 0 : snprintf(format+iPos, namelen-iPos, "0*d"); // additional 3 chars
119 0 : iPos+=3;
120 0 : } else {
121 0 : *(format+iPos++)='%';
122 0 : *(format+iPos++)=key[1];
123 : }
124 0 : strncpy(format+iPos, &key[2], namelen-1-iPos);
125 0 : } else {
126 0 : snprintf(format+strlen(basename), namelen-strlen(basename), "_%%0*d"); // additional 5 chars
127 : }
128 0 : for (i=0; i<count && iResult>=0; i++) {
129 0 : snprintf(name, namelen, format, digits, i);
130 0 : AliHLTDimService* service=new AliHLTDimService(type, name);
131 0 : iResult=RegisterService(service);
132 : }
133 0 : } else {
134 : iResult=-ENOMEM;
135 : }
136 0 : if (name) free(name);
137 0 : if (format) free(format);
138 0 : }
139 0 : }
140 : }
141 : return pServices;
142 0 : }
143 :
144 : int AliHLTDimServer::UpdateServices()
145 : {
146 : /// Update all services via the Dim channel
147 0 : return 0;
148 : }
149 :
150 : AliHLTDimServer::AliHLTDimInterface* AliHLTDimServer::Interface()
151 : {
152 : // get instance of the interface
153 0 : if (!fgpInterface) {
154 0 : fgpInterface=new AliHLTDimInterface;
155 0 : if (fgpInterface) {
156 0 : if (fgpInterface->Init() != 0) {
157 0 : delete fgpInterface;
158 0 : fgpInterface = NULL;
159 0 : }
160 : }
161 : }
162 0 : return fgpInterface;
163 0 : }
164 :
165 : int AliHLTDimServer::Init(const char* dimNameServer)
166 : {
167 : // init the dim server, check if the interface is available and set the
168 : // DIM DNS node name
169 0 : AliHLTLogging log;
170 0 : const char* myname=GetName();
171 0 : if (myname==NULL || myname[0]==0) {
172 0 : log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Init" , __FILE__ , __LINE__ , "can not start without a server name, skipping initialization ...");
173 0 : return -EINVAL;
174 : }
175 :
176 0 : if (Interface()==NULL) return -ENODEV;
177 :
178 0 : Interface()->DisSetDnsNode(dimNameServer);
179 0 : return 0;
180 0 : }
181 :
182 : int AliHLTDimServer::Reset()
183 : {
184 : // reset the DIM server, functionality needs to be clarified
185 0 : return 0;
186 : }
187 :
188 : int AliHLTDimServer::Start()
189 : {
190 : // start the server in a separate thread
191 : int iResult=0;
192 0 : AliHLTLogging log;
193 0 : if (GetState()!=kStateOff) {
194 0 : log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Start" , __FILE__ , __LINE__ , "server is not off, currently in state %d", GetState());
195 0 : return -ENOENT;
196 : }
197 0 : fpServerThread=new TThread(ServerLoop, (void*)this);
198 0 : if (!fpServerThread) {
199 0 : log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Start" , __FILE__ , __LINE__ , "unable to create server thread");
200 0 : return -ENOMEM;
201 : }
202 0 : SetState(kStateStarting);
203 0 : fpServerThread->Run();
204 :
205 : int count=0;
206 : const int maxcount=100;
207 : const int maxsleepms=1000;
208 0 : while (GetState()==kStateStarting) {
209 0 : if (count++==maxcount) break;
210 0 : gSystem->Sleep(maxsleepms/maxcount);
211 : }
212 :
213 0 : if (GetState()!=kStateRunning) {
214 0 : log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Start" , __FILE__ , __LINE__ , "could not start server, currently in state %d", GetState());
215 0 : Reset();
216 : iResult=-EFAULT;
217 0 : }
218 : return iResult;
219 0 : }
220 :
221 : int AliHLTDimServer::Stop()
222 : {
223 : // stop the server thread
224 : int iResult=0;
225 0 : AliHLTLogging log;
226 0 : if (GetState()!=kStateRunning) {
227 0 : log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Stop" , __FILE__ , __LINE__ , "server is not running, currently in state %d", GetState());
228 0 : return -ENOENT;
229 : }
230 0 : SetState(kStateStopping);
231 : int count=0;
232 : const int maxcount=100;
233 0 : const int maxsleepms=2*fUpdatePeriod;
234 0 : while (GetState()==kStateStopping) {
235 0 : if (count++==maxcount) break;
236 0 : gSystem->Sleep(maxsleepms/maxcount);
237 : }
238 :
239 0 : if (GetState()!=kStateOff) {
240 0 : log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "Stop" , __FILE__ , __LINE__ , "could not stop server, currently in state %d", GetState());
241 0 : Reset();
242 : iResult=-EFAULT;
243 0 : }
244 : return iResult;
245 0 : }
246 :
247 : void* AliHLTDimServer::ServerLoop(void* param)
248 : {
249 : // see header file for class documentation
250 0 : if (!param) return (void*)0;
251 0 : AliHLTDimServer* server=reinterpret_cast<AliHLTDimServer*>(param);
252 0 : return server->ServerLoop();
253 0 : }
254 :
255 : void* AliHLTDimServer::ServerLoop()
256 : {
257 : // see header file for class documentation
258 0 : if (!Interface()) return (void*)-ENODEV;
259 :
260 0 : AliHLTLogging log;
261 0 : TIter next(&fServices);
262 : TObject* obj=NULL;
263 0 : while ((obj=next())!=NULL) {
264 0 : AliHLTDimService* pService=dynamic_cast<AliHLTDimService*>(obj);
265 0 : if (!pService) continue;
266 0 : TString name=GetName(); name+="_"; name+=pService->GetName();
267 : const char* type="";
268 0 : void* buffer=pService->GetLocation();
269 : int size=0;
270 0 : switch (pService->GetType()) {
271 : case kDataTypeCustom:
272 : case kDataTypeInt:
273 : case kDataTypeFloat:
274 0 : type=pService->GetTypeString();
275 0 : size=pService->GetDataSize();
276 0 : break;
277 : case kDataTypeString:
278 0 : log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "ServerLoop" , __FILE__ , __LINE__ , "ignoring dim service %s: type 'string' not yet implemented", name.Data());
279 : break;
280 : default:
281 0 : log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "ServerLoop" , __FILE__ , __LINE__ , "ignoring dim service %s: unknown type %d", name.Data(), pService->GetType());
282 : }
283 0 : if (type[0]!=0) {
284 0 : int id=Interface()->DisAddService(name.Data(), type, buffer, size);
285 0 : if (id<0) {
286 0 : log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "ServerLoop" , __FILE__ , __LINE__ , "failed to add dim service %s: error %d", name.Data(), id);
287 : } else {
288 0 : pService->SetId(id);
289 : }
290 0 : }
291 0 : }
292 :
293 0 : SetState(kStateRunning);
294 0 : Interface()->DisStartServing(GetName());
295 0 : while (GetState()==kStateRunning) {
296 0 : gSystem->Sleep(fUpdatePeriod);
297 : }
298 :
299 0 : if (GetState()!=kStateStopping) return (void*)0;
300 :
301 : // cleanup
302 0 : Interface()->DisStopServing();
303 0 : next.Reset();
304 0 : while ((obj=next())!=NULL) {
305 0 : const AliHLTDimService* pService=dynamic_cast<const AliHLTDimService*>(obj);
306 0 : if (!pService || pService->GetId()<0) continue;
307 : // int iResult=Interface()->DisRemoveService(pService->GetId());
308 : // if (iResult<0) {
309 : // log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "ServerLoop" , __FILE__ , __LINE__ , "failed to remove dim service %s: error %d", pService->GetName(), iResult);
310 : // }
311 0 : }
312 :
313 0 : SetState(kStateOff);
314 :
315 0 : return (void*)0;
316 0 : }
317 :
318 : AliHLTDimServer::AliHLTDimService::AliHLTDimService()
319 0 : : TNamed()
320 0 : , fData()
321 0 : , fType(kDataTypeUnknown)
322 0 : , fTypeString()
323 0 : , fDataBuffer(NULL)
324 0 : , fDataSize(0)
325 0 : , fId(-1)
326 0 : {
327 : // see header file for class documentation
328 0 : }
329 :
330 : AliHLTDimServer::AliHLTDimService::AliHLTDimService(enum AliHLTDimServiceDataType type, const char* servicename)
331 0 : : TNamed(servicename, "AliHLTDimService")
332 0 : , fData()
333 0 : , fType(type)
334 0 : , fTypeString()
335 0 : , fDataBuffer(NULL)
336 0 : , fDataSize(0)
337 0 : , fId(-1)
338 0 : {
339 : // see header file for class documentation
340 0 : AliHLTLogging log;
341 0 : switch (fType) {
342 : case kDataTypeCustom:
343 0 : log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "AliHLTDimService" , __FILE__ , __LINE__ , "cannot use the kDataTypeCustom type with this method");
344 : break;
345 : case kDataTypeInt:
346 0 : fTypeString="I";
347 0 : fDataBuffer=&fData.iVal;
348 0 : fDataSize=sizeof(int);
349 0 : break;
350 : case kDataTypeFloat:
351 0 : fTypeString="F";
352 0 : fDataBuffer=&fData.fVal;
353 0 : fDataSize=sizeof(float);
354 0 : break;
355 : case kDataTypeString:
356 0 : log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "AliHLTDimService" , __FILE__ , __LINE__ , "dim service type 'string' not yet implemented");
357 : break;
358 : default:
359 0 : log.LoggingVarargs(kHLTLogError, "AliHLTDimServer", "AliHLTDimService" , __FILE__ , __LINE__ , "Unknown dim service type %d", fType);
360 : };
361 0 : }
362 :
363 : AliHLTDimServer::AliHLTDimService::AliHLTDimService(const char* type, void* data, int size, const char* servicename)
364 0 : : TNamed(servicename, "AliHLTDimService")
365 0 : , fData()
366 0 : , fType(kDataTypeCustom)
367 0 : , fTypeString(type)
368 0 : , fDataBuffer(data)
369 0 : , fDataSize(size)
370 0 : , fId(-1)
371 0 : {
372 : // see header file for class documentation
373 0 : }
374 :
375 : void AliHLTDimServer::AliHLTDimService::Update()
376 : {
377 : // see header file for class documentation
378 : static bool bWarning=true;
379 0 : AliHLTLogging log;
380 0 : switch (fType) {
381 : case kDataTypeCustom: break;
382 : default:
383 0 : 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());
384 0 : bWarning=false;
385 0 : };
386 :
387 0 : AliHLTDimServer::Interface()->DisUpdateService(fId);
388 0 : }
389 :
390 : void AliHLTDimServer::AliHLTDimService::Update(const AliHLTDimServicePoint_t& sp)
391 : {
392 : // see header file for class documentation
393 : static bool bWarning=true;
394 0 : AliHLTLogging log;
395 0 : switch (fType) {
396 : case kDataTypeCustom:
397 0 : if (bWarning) log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "Update" , __FILE__ , __LINE__ , "Should not call this form of Update for custom type (kDataTypeCustom) service %s", GetName());
398 0 : bWarning=false;
399 0 : return;
400 0 : case kDataTypeInt: fData.iVal=sp.iVal; break;
401 0 : case kDataTypeFloat: fData.fVal=sp.fVal; break;
402 : case kDataTypeString:
403 0 : if (bWarning) log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "Update" , __FILE__ , __LINE__ , "Failed to update dim service %s: 'string' not yet implemented", GetName());
404 0 : bWarning=false;
405 0 : break;
406 : default:
407 0 : if (bWarning) log.LoggingVarargs(kHLTLogError, "AliHLTDimServer::AliHLTDimService", "Update" , __FILE__ , __LINE__ , "Failed to update dim service %s: unknown type %d", GetName(), fType);
408 0 : bWarning=false;
409 0 : };
410 :
411 0 : AliHLTDimServer::Interface()->DisUpdateService(fId);
412 0 : }
413 :
414 : AliHLTDimServer::AliHLTDimInterface::AliHLTDimInterface()
415 0 : : AliHLTLogging()
416 0 : , fpDisAddService(NULL)
417 0 : , fpDisRemoveService(NULL)
418 0 : , fpDisUpdateService(NULL)
419 0 : , fpDisStartServing(NULL)
420 0 : , fpDisStopServing(NULL)
421 0 : , fpDisSetDnsNode(NULL)
422 0 : {
423 0 : }
424 :
425 : AliHLTDimServer::AliHLTDimInterface::~AliHLTDimInterface()
426 0 : {
427 0 : }
428 :
429 :
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";
437 :
438 : int AliHLTDimServer::AliHLTDimInterface::Init()
439 : {
440 : /// load the dim library and function pointers
441 0 : if (gSystem->Load(fgkDimLibraryName)) {
442 0 : HLTFatal("failed to load dim library: %s", fgkDimLibraryName);
443 0 : return -ENODEV;
444 : }
445 :
446 0 : fpDisAddService=(fctDisAddService)FindSymbol(fgkDimLibraryName, fgkDisAddServiceSymbol);
447 0 : if (!fpDisAddService) return -ENODEV;
448 :
449 0 : fpDisRemoveService=(fctDisRemoveService)FindSymbol(fgkDimLibraryName, fgkDisRemoveServiceSymbol);
450 0 : if (!fpDisRemoveService) return -ENODEV;
451 :
452 0 : fpDisUpdateService=(fctDisUpdateService)FindSymbol(fgkDimLibraryName, fgkDisUpdateServiceSymbol);
453 0 : if (!fpDisUpdateService) return -ENODEV;
454 :
455 0 : fpDisStartServing=(fctDisCharArg)FindSymbol(fgkDimLibraryName, fgkDisStartServingSymbol);
456 0 : if (!fpDisStartServing) return -ENODEV;
457 :
458 0 : fpDisStopServing=(fctDisNoArg)FindSymbol(fgkDimLibraryName, fgkDisStopServingSymbol);
459 0 : if (!fpDisStopServing) return -ENODEV;
460 :
461 0 : fpDisSetDnsNode=(fctDisCharArg)FindSymbol(fgkDimLibraryName, fgkDisSetDnsNodeSymbol);
462 0 : if (!fpDisSetDnsNode) return -ENODEV;
463 :
464 0 : return 0;
465 0 : }
466 :
467 : AliHLTDimServer::fctVoid AliHLTDimServer::AliHLTDimInterface::FindSymbol(const char* library, const char* symbol) const
468 : {
469 : /// Find symbol in the dim library
470 0 : TString tmp=symbol;
471 0 : fctVoid fctptr=gSystem->DynFindSymbol(library, tmp.Data());
472 0 : if (!fctptr) {
473 : // do a 2nd try with appended '_'
474 0 : tmp+="_";
475 0 : fctptr=gSystem->DynFindSymbol(library, tmp.Data());
476 0 : }
477 0 : if (fctptr) return fctptr;
478 :
479 0 : HLTError("can not find symbol '%s' in %s", symbol, library);
480 0 : return NULL;
481 0 : }
|