]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/AliHLTComponentHandler.cxx
reverse logic of header checks in order to avoid unnecessary -D flags
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTComponentHandler.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  *                  Timm Steinbeck <timm@kip.uni-heidelberg.de>           *
9  *                  for The ALICE HLT Project.                            *
10  *                                                                        *
11  * Permission to use, copy, modify and distribute this software and its   *
12  * documentation strictly for non-commercial purposes is hereby granted   *
13  * without fee, provided that the above copyright notice appears in all   *
14  * copies and that both the copyright notice and this permission notice   *
15  * appear in the supporting documentation. The authors make no claims     *
16  * about the suitability of this software for any purpose. It is          *
17  * provided "as is" without express or implied warranty.                  *
18  **************************************************************************/
19
20 /** @file   AliHLTComponentHandler.cxx
21     @author Matthias Richter, Timm Steinbeck
22     @date   
23     @brief  Implementation of HLT component handler. */
24
25 // see header file for class documentation
26 // or
27 // refer to README to build package
28 // or
29 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
30
31 #if __GNUC__>= 3
32 using namespace std;
33 #endif
34 //#undef HAVE_DLFCN_H
35 #ifdef HAVE_DLFCN_H
36 #include <dlfcn.h>
37 #else
38 //#include <Riostream.h>
39 #include <TSystem.h>
40 #endif //HAVE_DLFCN_H
41 //#include "AliHLTStdIncludes.h"
42 #include "AliHLTComponentHandler.h"
43 #include "AliHLTComponent.h"
44 #include "AliHLTDataTypes.h"
45 #include "AliHLTModuleAgent.h"
46 #include "TString.h"
47
48 /** ROOT macro for the implementation of ROOT specific class methods */
49 ClassImp(AliHLTComponentHandler)
50
51 AliHLTComponentHandler::AliHLTComponentHandler()
52   :
53   fComponentList(),
54   fScheduleList(),
55   fLibraryList(),
56   fEnvironment(),
57   fOwnedComponents(),
58   fLibraryMode(kDynamic)
59 {
60   // see header file for class documentation
61   // or
62   // refer to README to build package
63   // or
64   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
65   memset(&fEnvironment, 0, sizeof(AliHLTComponentEnvironment));
66   AddStandardComponents();
67 }
68
69 AliHLTComponentHandler::AliHLTComponentHandler(AliHLTComponentEnvironment* pEnv)
70   :
71   AliHLTLogging(),
72   fComponentList(),
73   fScheduleList(),
74   fLibraryList(),
75   fEnvironment(),
76   fOwnedComponents(),
77   fLibraryMode(kDynamic)
78 {
79   // see header file for class documentation
80   if (pEnv) {
81     memcpy(&fEnvironment, pEnv, sizeof(AliHLTComponentEnvironment));
82     if (pEnv->fLoggingFunc) {
83       // the AliHLTLogging::Init method also sets the stream output
84       // and notification handler to AliLog. This should only be done
85       // if the logging environment contains a logging function
86       // for redirection
87       AliHLTLogging::Init(pEnv->fLoggingFunc);
88     }
89   }  else {
90     memset(&fEnvironment, 0, sizeof(AliHLTComponentEnvironment));
91   }
92   //#ifndef __DEBUG
93   //SetLocalLoggingLevel(kHLTLogError);
94   //#else
95   //SetLocalLoggingLevel(kHLTLogInfo);
96   //#endif
97
98   AddStandardComponents();
99 }
100
101 AliHLTComponentHandler::~AliHLTComponentHandler()
102 {
103   // see header file for class documentation
104   DeleteOwnedComponents();
105   UnloadLibraries();
106 }
107
108 int AliHLTComponentHandler::AnnounceVersion()
109 {
110   // see header file for class documentation
111   int iResult=0;
112 #ifdef PACKAGE_STRING
113   void HLTbaseCompileInfo( char*& date, char*& time);
114   char* date="";
115   char* time="";
116   HLTbaseCompileInfo(date, time);
117   if (!date) date="unknown";
118   if (!time) time="unknown";
119   HLTImportant("%s build on %s (%s)", PACKAGE_STRING, date, time);
120 #else
121   HLTImportant("ALICE High Level Trigger build on %s (%s) (embedded AliRoot build)", __DATE__, __TIME__);
122 #endif
123   return iResult;
124 }
125
126 Int_t AliHLTComponentHandler::AddComponent(AliHLTComponent* pSample)
127 {
128   // see header file for class documentation
129   Int_t iResult=0;
130   if (pSample==NULL) return -EINVAL;
131   if ((iResult=RegisterComponent(pSample))>=0) {
132     //HLTDebug("sample %s (%p) managed by handler", pSample->GetComponentID(), pSample);
133     fOwnedComponents.push_back(pSample);
134   }
135   return iResult;
136 }
137
138 Int_t AliHLTComponentHandler::RegisterComponent(AliHLTComponent* pSample)
139 {
140   // see header file for class documentation
141   Int_t iResult=0;
142   if (pSample) {
143     if (FindComponent(pSample->GetComponentID())==NULL) {
144       iResult=InsertComponent(pSample);
145       if (iResult>=0) {
146         HLTInfo("component %s registered", pSample->GetComponentID());
147       }
148     } else {
149       // component already registered
150       HLTDebug("component %s already registered, skipped", pSample->GetComponentID());
151       iResult=-EEXIST;
152     }
153   } else {
154     iResult=-EINVAL;
155   }
156   return iResult;
157 }
158
159 int AliHLTComponentHandler::DeregisterComponent( const char* componentID )
160 {
161   // see header file for class documentation
162
163   int iResult=0;
164   if (componentID) {
165     HLTWarning("not yet implemented, please notify the developers if you need this function");
166   } else {
167     iResult=-EINVAL;
168   }
169   return iResult;
170 }
171
172 Int_t AliHLTComponentHandler::ScheduleRegister(AliHLTComponent* pSample)
173 {
174   // see header file for class documentation
175   Int_t iResult=0;
176   if (pSample) {
177     fScheduleList.push_back(pSample);
178   } else {
179     iResult=-EINVAL;
180   }
181   return iResult;
182 }
183
184 int AliHLTComponentHandler::CreateComponent(const char* componentID, void* pEnvParam, int argc, const char** argv, AliHLTComponent*& component, const char* cdbPath )
185 {
186   // see header file for class documentation
187   int iResult=0;
188   if (componentID) {
189     AliHLTComponent* pSample=FindComponent(componentID);
190     if (pSample!=NULL) {
191       component=pSample->Spawn();
192       if (component) {
193         HLTDebug("component \"%s\" created (%p)", componentID, component);
194         component->InitCDB(cdbPath, this);
195         if ((iResult=component->Init(&fEnvironment, pEnvParam, argc, argv))!=0) {
196           HLTError("Initialization of component \"%s\" failed with error %d", componentID, iResult);
197           delete component;
198           component=NULL;
199         }
200       } else {
201         HLTError("can not spawn component \"%s\"", componentID);
202         iResult=-ENOENT;
203       }
204     } else {
205       HLTWarning("can not find component \"%s\"", componentID);
206       iResult=-ENOENT;
207     }
208   } else {
209     iResult=-EINVAL;
210   }
211   return iResult;
212 }
213
214 Int_t AliHLTComponentHandler::FindComponentIndex(const char* componentID)
215 {
216   // see header file for class documentation
217   Int_t iResult=0;
218   if (componentID) {
219     AliHLTComponentPList::iterator element=fComponentList.begin();
220     while (element!=fComponentList.end() && iResult>=0) {
221       if (strcmp(componentID, (*element)->GetComponentID())==0) {
222         break;
223       }
224       element++;
225       iResult++;
226     }
227     if (element==fComponentList.end()) iResult=-ENOENT;
228   } else {
229     iResult=-EINVAL;
230   }
231   return iResult;
232 }
233
234 AliHLTComponent* AliHLTComponentHandler::FindComponent(const char* componentID)
235 {
236   // see header file for class documentation
237   AliHLTComponent* pSample=NULL;
238   Int_t index=FindComponentIndex(componentID);
239   if (index>=0) {
240     pSample=(AliHLTComponent*)fComponentList.at(index);
241   }
242   return pSample;
243 }
244
245 Int_t AliHLTComponentHandler::InsertComponent(AliHLTComponent* pSample)
246 {
247   // see header file for class documentation
248   Int_t iResult=0;
249   if (pSample!=NULL) {
250     fComponentList.push_back(pSample);
251   } else {
252     iResult=-EINVAL;
253   }
254   return iResult;
255 }
256
257 void AliHLTComponentHandler::List() 
258 {
259   // see header file for class documentation
260   AliHLTComponentPList::iterator element=fComponentList.begin();
261   int index=0;
262   while (element!=fComponentList.end()) {
263     HLTInfo("%d. %s", index++, (*element++)->GetComponentID());
264   }
265 }
266
267 int AliHLTComponentHandler::HasOutputData( const char* componentID)
268 {
269   // see header file for class documentation
270   int iResult=0;
271   AliHLTComponent* pSample=FindComponent(componentID);
272   if (pSample) {
273     AliHLTComponent::TComponentType ct=AliHLTComponent::kUnknown;
274     ct=pSample->GetComponentType();
275     iResult=(ct==AliHLTComponent::kSource || ct==AliHLTComponent::kProcessor);
276   } else {
277     iResult=-ENOENT;
278   }
279   return iResult;
280 }
281
282 void AliHLTComponentHandler::SetEnvironment(AliHLTComponentEnvironment* pEnv) 
283 {
284   // see header file for class documentation
285   if (pEnv) {
286     memcpy(&fEnvironment, pEnv, sizeof(AliHLTComponentEnvironment));
287     if (fEnvironment.fLoggingFunc) {
288       // the AliHLTLogging::Init method also sets the stream output
289       // and notification handler to AliLog. This should only be done
290       // if the logging environment contains a logging function
291       // for redirection
292       AliHLTLogging::Init(fEnvironment.fLoggingFunc);
293     }
294   }
295 }
296
297 AliHLTComponentHandler::TLibraryMode AliHLTComponentHandler::SetLibraryMode(TLibraryMode mode)
298 {
299   // see header file for class documentation
300   TLibraryMode old=fLibraryMode;
301   fLibraryMode=mode;
302   return old;
303 }
304
305 int AliHLTComponentHandler::LoadLibrary( const char* libraryPath, int bActivateAgents)
306 {
307   // see header file for class documentation
308   int iResult=0;
309   if (libraryPath) {
310     // first activate all agents which are already loaded
311     if (bActivateAgents) ActivateAgents();
312
313     // set the global component handler for static component registration
314     AliHLTComponent::SetGlobalComponentHandler(this);
315
316     AliHLTLibHandle hLib;
317     const char* loadtype="";
318 #ifdef HAVE_DLFCN_H
319     // use interface to the dynamic linking loader
320
321     // exeption does not help in Root context, the Root exeption
322     // handler always catches the exeption before. Have to find out
323     // how exeptions can be used in Root
324     /*try*/ {
325       hLib.fHandle=dlopen(libraryPath, RTLD_NOW);
326       loadtype="dlopen";
327     }
328     /*
329     catch (...) {
330       // error message printed further down
331       loadtype="dlopen exeption";
332     }
333     */
334 #else
335     // use ROOT dynamic loader
336     // check if the library was already loaded, as Load returns
337     // 'failure' if the library was already loaded
338     /*try*/ {
339     AliHLTLibHandle* pLib=FindLibrary(libraryPath);
340     if (pLib) {
341         int* pRootHandle=reinterpret_cast<int*>(pLib->fHandle);
342         (*pRootHandle)++;
343         HLTDebug("instance %d of library %s loaded", (*pRootHandle), libraryPath);
344         hLib.fHandle=pRootHandle;
345     }
346     
347     if (hLib.fHandle==NULL && gSystem->Load(libraryPath)>=0) {
348       int* pRootHandle=new int;
349       if (pRootHandle) *pRootHandle=1;
350       hLib.fHandle=pRootHandle;
351       //HLTDebug("library %s loaded via gSystem", libraryPath);
352     }
353     loadtype="gSystem";
354     }
355     /*
356     catch (...) {
357       // error message printed further down
358       loadtype="gSystem exeption";
359     }
360     */
361 #endif //HAVE_DLFCN_H
362     if (hLib.fHandle!=NULL) {
363       // create TString object to store library path and use pointer as handle 
364       hLib.fName=new TString(libraryPath);
365       hLib.fMode=fLibraryMode;
366       HLTImportant("library %s loaded (%s%s)", libraryPath, hLib.fMode==kStatic?"persistent, ":"", loadtype);
367       fLibraryList.insert(fLibraryList.begin(), hLib);
368       typedef void (*CompileInfo)( char*& date, char*& time);
369       CompileInfo fctInfo=(CompileInfo)FindSymbol(libraryPath, "CompileInfo");
370       if (fctInfo) {
371         char* date="";
372         char* time="";
373         (*fctInfo)(date, time);
374         if (!date) date="unknown";
375         if (!time) time="unknown";
376         HLTImportant("build on %s (%s)", date, time);
377       } else {
378         HLTImportant("no build info available (possible AliRoot embedded build)");
379       }
380
381       // static registration of components when library is loaded
382       iResult=RegisterScheduledComponents();
383
384     } else {
385       HLTError("can not load library %s (%s)", libraryPath, loadtype);
386 #ifdef HAVE_DLFCN_H
387       HLTError("dlopen error: %s", dlerror());
388 #endif //HAVE_DLFCN_H
389 #ifdef __APPLE__
390       iResult=-EFTYPE;
391 #else
392       iResult=-ELIBACC;
393 #endif
394     }
395     AliHLTComponent::UnsetGlobalComponentHandler();
396     
397     if (iResult>=0) {
398       // alternative dynamic registration by library agents
399       // !!! has to be done after UnsetGlobalComponentHandler
400       if (bActivateAgents) ActivateAgents();
401     }
402
403   } else {
404     iResult=-EINVAL;
405   }
406   return iResult;
407 }
408
409 int AliHLTComponentHandler::UnloadLibrary( const char* libraryPath )
410 {
411   // see header file for class documentation
412   int iResult=0;
413   if (libraryPath) {
414     vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
415     while (element!=fLibraryList.end()) {
416       TString* pName=reinterpret_cast<TString*>((*element).fName);
417       if (pName->CompareTo(libraryPath)==0) {
418         UnloadLibrary(*element);
419         fLibraryList.erase(element);
420         break;
421       }
422       element++;
423   }
424   } else {
425     iResult=-EINVAL;
426   }
427   return iResult;
428 }
429
430 int AliHLTComponentHandler::UnloadLibrary(AliHLTComponentHandler::AliHLTLibHandle &handle)
431 {
432   // see header file for class documentation
433   int iResult=0;
434   fgAliLoggingFunc=NULL;
435   TString* pName=reinterpret_cast<TString*>(handle.fName);
436   if (handle.fMode!=kStatic) {
437 #ifdef HAVE_DLFCN_H
438   // exeption does not help in Root context, the Root exeption
439   // handler always catches the exeption before. Have to find out
440   // how exeptions can be used in Root
441
442   /*try*/ {
443     dlclose(handle.fHandle);
444   }
445   /*
446   catch (...) {
447     HLTError("exeption caught during dlclose of library %s", pName!=NULL?pName->Data():"");
448   }
449   */
450 #else
451   int* pCount=reinterpret_cast<int*>(handle.fHandle);
452   if (--(*pCount)==0) {
453     if (pName) {
454       /** Matthias 26.04.2007
455        * I spent about a week to investigate a bug which seems to be in ROOT.
456        * Under certain circumstances, TSystem::Unload crashes. The crash occured
457        * for the first time, when libAliHLTUtil was loaded from AliHLTSystem right
458        * after the ComponentHandler was created. It does not occur when dlopen is
459        * used. 
460        * It has most likely to do with the garbage collection and automatic
461        * cleanup in ROOT. The crash occurs when ROOT is terminated and before
462        * an instance of AliHLTSystem was created.
463        *   root [0] AliHLTSystem gHLT
464        * It does not occur when the instance was created dynamically (but not even
465        * deleted)
466        *   root [0] AliHLTSystem* gHLT=new AliHLTSystem
467        *
468        * For that reason, the libraries are not unloaded here, even though there
469        * will be memory leaks.
470       gSystem->Unload(pName->Data());
471        */
472     }
473     else {
474       HLTError("missing library name, can not unload");
475     }
476     delete pCount;
477   }
478 #endif //HAVE_DLFCN_H
479   if (pName) {
480     HLTDebug("unload library %s", pName->Data());
481   } else {
482     HLTWarning("missing name for unloaded library");
483   }
484   }
485   handle.fName=NULL;
486   handle.fHandle=NULL;
487   if (pName) {
488     delete pName;
489   }
490   pName=NULL;
491   return iResult;
492 }
493
494 int AliHLTComponentHandler::UnloadLibraries()
495 {
496   // see header file for class documentation
497   int iResult=0;
498   vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
499   while (element!=fLibraryList.end()) {
500     UnloadLibrary(*element);
501     fLibraryList.erase(element);
502     element=fLibraryList.begin();
503   }
504   return iResult;
505 }
506
507 void* AliHLTComponentHandler::FindSymbol(const char* library, const char* symbol)
508 {
509   // see header file for class documentation
510   AliHLTLibHandle* hLib=FindLibrary(library);
511   if (hLib==NULL) return NULL;
512   void* pFunc=NULL;
513 #ifdef HAVE_DLFCN_H
514   pFunc=dlsym(hLib->fHandle, symbol);
515 #else
516   TString* name=reinterpret_cast<TString*>(hLib->fName);
517   pFunc=gSystem->DynFindSymbol(name->Data(), symbol);
518 #endif
519   return pFunc;
520 }
521
522 AliHLTComponentHandler::AliHLTLibHandle* AliHLTComponentHandler::FindLibrary(const char* library)
523 {
524   // see header file for class documentation
525   AliHLTLibHandle* hLib=NULL;
526   vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
527   while (element!=fLibraryList.end()) {
528     TString* name=reinterpret_cast<TString*>((*element).fName);
529     if (name->CompareTo(library)==0) {
530       hLib=&(*element);
531       break;
532     }
533     element++;
534   }
535   return hLib;
536 }
537
538 int AliHLTComponentHandler::AddStandardComponents()
539 {
540   // see header file for class documentation
541   int iResult=0;
542   AliHLTComponent::SetGlobalComponentHandler(this);
543   AliHLTComponent::UnsetGlobalComponentHandler();
544   iResult=RegisterScheduledComponents();
545   return iResult;
546 }
547
548 int AliHLTComponentHandler::RegisterScheduledComponents()
549 {
550   // see header file for class documentation
551   int iResult=0;
552   AliHLTComponentPList::iterator element=fScheduleList.begin();
553   int iLocalResult=0;
554   while (element!=fScheduleList.end()) {
555     iLocalResult=RegisterComponent(*element);
556     if (iResult==0) iResult=iLocalResult;
557     fScheduleList.erase(element);
558     element=fScheduleList.begin();
559   }
560   return iResult;
561 }
562
563 int AliHLTComponentHandler::ActivateAgents(const AliHLTModuleAgent** blackList, int size)
564 {
565   // see header file for class documentation
566   int iResult=0;
567   AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent();
568   while (pAgent && iResult>=0) {
569     if (blackList) {
570       int i=0;
571       for (; i<size; i++) {
572         if (blackList[i]==pAgent) break;
573       }
574       if (i<size) {
575         // this agent was in the list
576         pAgent=AliHLTModuleAgent::GetNextAgent();
577         continue;
578       }
579     }
580
581     pAgent->ActivateComponentHandler(this);
582     pAgent=AliHLTModuleAgent::GetNextAgent();
583   }
584   return iResult;
585 }
586
587 int AliHLTComponentHandler::DeleteOwnedComponents()
588 {
589   // see header file for class documentation
590   int iResult=0;
591   AliHLTComponentPList::iterator element=fOwnedComponents.begin();
592   while (element!=fOwnedComponents.end()) {
593     //DeregisterComponent((*element)->GetComponentID());
594     // exeption does not help in Root context, the Root exeption
595     // handler always catches the exeption before. Have to find out
596     // how exeptions can be used in Root
597     /*try*/ {
598       delete *element;
599     }
600     /*
601     catch (...) {
602       HLTError("delete managed sample %p", *element);
603     }
604     */
605     fOwnedComponents.erase(element);
606     element=fOwnedComponents.begin();
607   }
608   return iResult;
609 }