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