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