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