coding conventions and compilation warnings
[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         if (cdbPath) {
195           component->InitCDB(cdbPath, this);
196         }
197         if ((iResult=component->Init(&fEnvironment, pEnvParam, argc, argv))!=0) {
198           HLTError("Initialization of component \"%s\" failed with error %d", componentID, iResult);
199           delete component;
200           component=NULL;
201         }
202       } else {
203         HLTError("can not spawn component \"%s\"", componentID);
204         iResult=-ENOENT;
205       }
206     } else {
207       HLTWarning("can not find component \"%s\"", componentID);
208       iResult=-ENOENT;
209     }
210   } else {
211     iResult=-EINVAL;
212   }
213   return iResult;
214 }
215
216 Int_t AliHLTComponentHandler::FindComponentIndex(const char* componentID)
217 {
218   // see header file for class documentation
219   Int_t iResult=0;
220   if (componentID) {
221     AliHLTComponentPList::iterator element=fComponentList.begin();
222     while (element!=fComponentList.end() && iResult>=0) {
223       if (strcmp(componentID, (*element)->GetComponentID())==0) {
224         break;
225       }
226       element++;
227       iResult++;
228     }
229     if (element==fComponentList.end()) iResult=-ENOENT;
230   } else {
231     iResult=-EINVAL;
232   }
233   return iResult;
234 }
235
236 AliHLTComponent* AliHLTComponentHandler::FindComponent(const char* componentID)
237 {
238   // see header file for class documentation
239   AliHLTComponent* pSample=NULL;
240   Int_t index=FindComponentIndex(componentID);
241   if (index>=0) {
242     pSample=(AliHLTComponent*)fComponentList.at(index);
243   }
244   return pSample;
245 }
246
247 Int_t AliHLTComponentHandler::InsertComponent(AliHLTComponent* pSample)
248 {
249   // see header file for class documentation
250   Int_t iResult=0;
251   if (pSample!=NULL) {
252     fComponentList.push_back(pSample);
253   } else {
254     iResult=-EINVAL;
255   }
256   return iResult;
257 }
258
259 void AliHLTComponentHandler::List() 
260 {
261   // see header file for class documentation
262   AliHLTComponentPList::iterator element=fComponentList.begin();
263   int index=0;
264   while (element!=fComponentList.end()) {
265     HLTInfo("%d. %s", index++, (*element++)->GetComponentID());
266   }
267 }
268
269 int AliHLTComponentHandler::HasOutputData( const char* componentID)
270 {
271   // see header file for class documentation
272   int iResult=0;
273   AliHLTComponent* pSample=FindComponent(componentID);
274   if (pSample) {
275     AliHLTComponent::TComponentType ct=AliHLTComponent::kUnknown;
276     ct=pSample->GetComponentType();
277     iResult=(ct==AliHLTComponent::kSource || ct==AliHLTComponent::kProcessor);
278   } else {
279     iResult=-ENOENT;
280   }
281   return iResult;
282 }
283
284 void AliHLTComponentHandler::SetEnvironment(AliHLTComponentEnvironment* pEnv) 
285 {
286   // see header file for class documentation
287   if (pEnv) {
288     memcpy(&fEnvironment, pEnv, sizeof(AliHLTComponentEnvironment));
289     if (fEnvironment.fLoggingFunc) {
290       // the AliHLTLogging::Init method also sets the stream output
291       // and notification handler to AliLog. This should only be done
292       // if the logging environment contains a logging function
293       // for redirection
294       AliHLTLogging::Init(fEnvironment.fLoggingFunc);
295     }
296   }
297 }
298
299 AliHLTComponentHandler::TLibraryMode AliHLTComponentHandler::SetLibraryMode(TLibraryMode mode)
300 {
301   // see header file for class documentation
302   TLibraryMode old=fLibraryMode;
303   fLibraryMode=mode;
304   return old;
305 }
306
307 int AliHLTComponentHandler::LoadLibrary( const char* libraryPath, int bActivateAgents)
308 {
309   // see header file for class documentation
310   int iResult=0;
311   if (libraryPath) {
312     // first activate all agents which are already loaded
313     if (bActivateAgents) ActivateAgents();
314
315     // set the global component handler for static component registration
316     AliHLTComponent::SetGlobalComponentHandler(this);
317
318     AliHLTLibHandle hLib;
319     const char* loadtype="";
320 #ifdef HAVE_DLFCN_H
321     // use interface to the dynamic linking loader
322
323     // exeption does not help in Root context, the Root exeption
324     // handler always catches the exeption before. Have to find out
325     // how exeptions can be used in Root
326     /*try*/ {
327       hLib.fHandle=dlopen(libraryPath, RTLD_NOW);
328       loadtype="dlopen";
329     }
330     /*
331     catch (...) {
332       // error message printed further down
333       loadtype="dlopen exeption";
334     }
335     */
336 #else
337     // use ROOT dynamic loader
338     // check if the library was already loaded, as Load returns
339     // 'failure' if the library was already loaded
340     /*try*/ {
341     AliHLTLibHandle* pLib=FindLibrary(libraryPath);
342     if (pLib) {
343         int* pRootHandle=reinterpret_cast<int*>(pLib->fHandle);
344         (*pRootHandle)++;
345         HLTDebug("instance %d of library %s loaded", (*pRootHandle), libraryPath);
346         hLib.fHandle=pRootHandle;
347     }
348     
349     if (hLib.fHandle==NULL && gSystem->Load(libraryPath)==0) {
350       int* pRootHandle=new int;
351       if (pRootHandle) *pRootHandle=1;
352       hLib.fHandle=pRootHandle;
353       //HLTDebug("library %s loaded via gSystem", libraryPath);
354     }
355     loadtype="gSystem";
356     }
357     /*
358     catch (...) {
359       // error message printed further down
360       loadtype="gSystem exeption";
361     }
362     */
363 #endif //HAVE_DLFCN_H
364     if (hLib.fHandle!=NULL) {
365       // create TString object to store library path and use pointer as handle 
366       hLib.fName=new TString(libraryPath);
367       hLib.fMode=fLibraryMode;
368       HLTImportant("library %s loaded (%s%s)", libraryPath, hLib.fMode==kStatic?"persistent, ":"", loadtype);
369       fLibraryList.insert(fLibraryList.begin(), hLib);
370       typedef void (*CompileInfo)( char*& date, char*& time);
371       CompileInfo fctInfo=(CompileInfo)FindSymbol(libraryPath, "CompileInfo");
372       if (fctInfo) {
373         char* date="";
374         char* time="";
375         (*fctInfo)(date, time);
376         if (!date) date="unknown";
377         if (!time) time="unknown";
378         HLTImportant("build on %s (%s)", date, time);
379       } else {
380         HLTImportant("no build info available (possible AliRoot embedded build)");
381       }
382
383       // static registration of components when library is loaded
384       iResult=RegisterScheduledComponents();
385
386     } else {
387       HLTError("can not load library %s (%s)", libraryPath, loadtype);
388 #ifdef HAVE_DLFCN_H
389       HLTError("dlopen error: %s", dlerror());
390 #endif //HAVE_DLFCN_H
391 #ifdef __APPLE__
392       iResult=-EFTYPE;
393 #else
394       iResult=-ELIBACC;
395 #endif
396     }
397     AliHLTComponent::UnsetGlobalComponentHandler();
398     
399     if (iResult>=0) {
400       // alternative dynamic registration by library agents
401       // !!! has to be done after UnsetGlobalComponentHandler
402       if (bActivateAgents) ActivateAgents();
403     }
404
405   } else {
406     iResult=-EINVAL;
407   }
408   return iResult;
409 }
410
411 int AliHLTComponentHandler::UnloadLibrary( const char* libraryPath )
412 {
413   // see header file for class documentation
414   int iResult=0;
415   if (libraryPath) {
416     vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
417     while (element!=fLibraryList.end()) {
418       TString* pName=reinterpret_cast<TString*>((*element).fName);
419       if (pName->CompareTo(libraryPath)==0) {
420         UnloadLibrary(*element);
421         fLibraryList.erase(element);
422         break;
423       }
424       element++;
425   }
426   } else {
427     iResult=-EINVAL;
428   }
429   return iResult;
430 }
431
432 int AliHLTComponentHandler::UnloadLibrary(AliHLTComponentHandler::AliHLTLibHandle &handle)
433 {
434   // see header file for class documentation
435   int iResult=0;
436   fgAliLoggingFunc=NULL;
437   TString* pName=reinterpret_cast<TString*>(handle.fName);
438   if (handle.fMode!=kStatic) {
439 #ifdef HAVE_DLFCN_H
440   // exeption does not help in Root context, the Root exeption
441   // handler always catches the exeption before. Have to find out
442   // how exeptions can be used in Root
443
444   /*try*/ {
445     dlclose(handle.fHandle);
446   }
447   /*
448   catch (...) {
449     HLTError("exeption caught during dlclose of library %s", pName!=NULL?pName->Data():"");
450   }
451   */
452 #else
453   int* pCount=reinterpret_cast<int*>(handle.fHandle);
454   if (--(*pCount)==0) {
455     if (pName) {
456       /** Matthias 26.04.2007
457        * I spent about a week to investigate a bug which seems to be in ROOT.
458        * Under certain circumstances, TSystem::Unload crashes. The crash occured
459        * for the first time, when libAliHLTUtil was loaded from AliHLTSystem right
460        * after the ComponentHandler was created. It does not occur when dlopen is
461        * used. 
462        * It has most likely to do with the garbage collection and automatic
463        * cleanup in ROOT. The crash occurs when ROOT is terminated and before
464        * an instance of AliHLTSystem was created.
465        *   root [0] AliHLTSystem gHLT
466        * It does not occur when the instance was created dynamically (but not even
467        * deleted)
468        *   root [0] AliHLTSystem* gHLT=new AliHLTSystem
469        *
470        * For that reason, the libraries are not unloaded here, even though there
471        * will be memory leaks.
472       gSystem->Unload(pName->Data());
473        */
474     }
475     else {
476       HLTError("missing library name, can not unload");
477     }
478     delete pCount;
479   }
480 #endif //HAVE_DLFCN_H
481   if (pName) {
482     HLTDebug("unload library %s", pName->Data());
483   } else {
484     HLTWarning("missing name for unloaded library");
485   }
486   }
487   handle.fName=NULL;
488   handle.fHandle=NULL;
489   if (pName) {
490     delete pName;
491   }
492   pName=NULL;
493   return iResult;
494 }
495
496 int AliHLTComponentHandler::UnloadLibraries()
497 {
498   // see header file for class documentation
499   int iResult=0;
500   vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
501   while (element!=fLibraryList.end()) {
502     UnloadLibrary(*element);
503     fLibraryList.erase(element);
504     element=fLibraryList.begin();
505   }
506   return iResult;
507 }
508
509 void* AliHLTComponentHandler::FindSymbol(const char* library, const char* symbol)
510 {
511   // see header file for class documentation
512   AliHLTLibHandle* hLib=FindLibrary(library);
513   if (hLib==NULL) return NULL;
514   void* pFunc=NULL;
515 #ifdef HAVE_DLFCN_H
516   pFunc=dlsym(hLib->fHandle, symbol);
517 #else
518   TString* name=reinterpret_cast<TString*>(hLib->fName);
519   pFunc=gSystem->DynFindSymbol(name->Data(), symbol);
520 #endif
521   return pFunc;
522 }
523
524 AliHLTComponentHandler::AliHLTLibHandle* AliHLTComponentHandler::FindLibrary(const char* library)
525 {
526   // see header file for class documentation
527   AliHLTLibHandle* hLib=NULL;
528   vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
529   while (element!=fLibraryList.end()) {
530     TString* name=reinterpret_cast<TString*>((*element).fName);
531     if (name->CompareTo(library)==0) {
532       hLib=&(*element);
533       break;
534     }
535     element++;
536   }
537   return hLib;
538 }
539
540 int AliHLTComponentHandler::AddStandardComponents()
541 {
542   // see header file for class documentation
543   int iResult=0;
544   AliHLTComponent::SetGlobalComponentHandler(this);
545   AliHLTComponent::UnsetGlobalComponentHandler();
546   iResult=RegisterScheduledComponents();
547   return iResult;
548 }
549
550 int AliHLTComponentHandler::RegisterScheduledComponents()
551 {
552   // see header file for class documentation
553   int iResult=0;
554   AliHLTComponentPList::iterator element=fScheduleList.begin();
555   int iLocalResult=0;
556   while (element!=fScheduleList.end()) {
557     iLocalResult=RegisterComponent(*element);
558     if (iResult==0) iResult=iLocalResult;
559     fScheduleList.erase(element);
560     element=fScheduleList.begin();
561   }
562   return iResult;
563 }
564
565 int AliHLTComponentHandler::ActivateAgents(const AliHLTModuleAgent** blackList, int size)
566 {
567   // see header file for class documentation
568   int iResult=0;
569   AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent();
570   while (pAgent && iResult>=0) {
571     if (blackList) {
572       int i=0;
573       for (; i<size; i++) {
574         if (blackList[i]==pAgent) break;
575       }
576       if (i<size) {
577         // this agent was in the list
578         pAgent=AliHLTModuleAgent::GetNextAgent();
579         continue;
580       }
581     }
582
583     pAgent->ActivateComponentHandler(this);
584     pAgent=AliHLTModuleAgent::GetNextAgent();
585   }
586   return iResult;
587 }
588
589 int AliHLTComponentHandler::DeleteOwnedComponents()
590 {
591   // see header file for class documentation
592   int iResult=0;
593   AliHLTComponentPList::iterator element=fOwnedComponents.begin();
594   while (element!=fOwnedComponents.end()) {
595     //DeregisterComponent((*element)->GetComponentID());
596     // exeption does not help in Root context, the Root exeption
597     // handler always catches the exeption before. Have to find out
598     // how exeptions can be used in Root
599     /*try*/ {
600       delete *element;
601     }
602     /*
603     catch (...) {
604       HLTError("delete managed sample %p", *element);
605     }
606     */
607     fOwnedComponents.erase(element);
608     element=fOwnedComponents.begin();
609   }
610   return iResult;
611 }