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