3 /**************************************************************************
4 * This file is property of and copyright by the ALICE HLT Project *
5 * ALICE Experiment at CERN, All rights reserved. *
7 * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8 * Timm Steinbeck <timm@kip.uni-heidelberg.de> *
9 * for The ALICE HLT Project. *
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 **************************************************************************/
20 /// @file AliHLTComponentHandler.cxx
21 /// @author Matthias Richter, Timm Steinbeck
23 /// @brief Implementation of HLT component handler.
26 // see header file for class documentation
28 // refer to README to build package
30 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
39 //#include <Riostream.h>
42 //#include "AliHLTStdIncludes.h"
43 #include "AliHLTComponentHandler.h"
44 #include "AliHLTComponent.h"
45 #include "AliHLTDataTypes.h"
46 #include "AliHLTModuleAgent.h"
49 /** ROOT macro for the implementation of ROOT specific class methods */
50 ClassImp(AliHLTComponentHandler)
52 AliHLTComponentHandler::AliHLTComponentHandler()
59 fLibraryMode(kDynamic),
60 fRunDesc(kAliHLTVoidRunDesc),
63 // see header file for class documentation
65 // refer to README to build package
67 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
68 memset(&fEnvironment, 0, sizeof(AliHLTAnalysisEnvironment));
69 fEnvironment.fStructSize=sizeof(AliHLTAnalysisEnvironment);
70 AddStandardComponents();
73 AliHLTComponentHandler::AliHLTComponentHandler(AliHLTAnalysisEnvironment* pEnv)
81 fLibraryMode(kDynamic),
82 fRunDesc(kAliHLTVoidRunDesc),
85 // see header file for class documentation
87 memcpy(&fEnvironment, pEnv, sizeof(AliHLTAnalysisEnvironment));
88 if (pEnv->fLoggingFunc) {
89 // the AliHLTLogging::Init method also sets the stream output
90 // and notification handler to AliLog. This should only be done
91 // if the logging environment contains a logging function
93 AliHLTLogging::Init(pEnv->fLoggingFunc);
96 memset(&fEnvironment, 0, sizeof(AliHLTAnalysisEnvironment));
97 fEnvironment.fStructSize=sizeof(AliHLTAnalysisEnvironment);
100 //SetLocalLoggingLevel(kHLTLogError);
102 //SetLocalLoggingLevel(kHLTLogInfo);
105 AddStandardComponents();
109 2010-09-06 TODO: This is a workaround for unresolved library dependencies
110 with the aliroot build system. Some of the component libraries might need
111 libraries not linked to the aliroot executable. I also tried to link component
112 libraries to their dependencies in aliroot, but there is some awkward dependency
113 and even a flaw in the build system leaving the library not built if the
114 dependency was not found.
115 Ideally we decouple library and component handler. The library handler needs to
116 manage all dependencies, the unload-problem, etc.
117 This issue is releated to https://savannah.cern.ch/task/?16325
119 const std::pair<const char*, const char*> AliHLTComponentHandler::fgkLibDep[] = {
120 make_pair("libAliHLTUtil.so", "libANALYSIS.so"),
121 make_pair("libAliHLTUtil.so", "libANALYSISalice.so")
124 AliHLTComponentHandler::~AliHLTComponentHandler()
126 // see header file for class documentation
127 DeleteOwnedComponents();
129 if (fRunType) delete [] fRunType;
133 AliHLTComponentHandler* AliHLTComponentHandler::fgpInstance=NULL;
134 int AliHLTComponentHandler::fgNofInstances=0;
136 AliHLTComponentHandler* AliHLTComponentHandler::CreateHandler()
138 // see header file for class documentation
139 if (!fgpInstance) fgpInstance=new AliHLTComponentHandler;
144 int AliHLTComponentHandler::Destroy()
146 // destroy/delete 'this', checks if 'this' pointer is the global instance,
147 // reduce the instance counter and delete if there are no instances left
148 // IMPORTANT: the object must be considered self-destroyed after the function
150 if (fgpInstance==this) {
151 nofInstances=--fgNofInstances;
153 if (fgNofInstances==0) fgpInstance=NULL;
154 if (nofInstances==0) delete this;
158 int AliHLTComponentHandler::AnnounceVersion()
160 // see header file for class documentation
162 #ifdef PACKAGE_STRING
163 extern void HLTbaseCompileInfo( const char*& date, const char*& time);
166 HLTbaseCompileInfo(date, time);
167 if (!date) date="unknown";
168 if (!time) time="unknown";
169 HLTImportant("%s build on %s (%s)", PACKAGE_STRING, date, time);
171 HLTImportant("ALICE High Level Trigger build on %s (%s) (embedded AliRoot build)", __DATE__, __TIME__);
176 Int_t AliHLTComponentHandler::AddComponent(AliHLTComponent* pSample)
178 // see header file for class documentation
180 if (pSample==NULL) return -EINVAL;
181 if ((iResult=RegisterComponent(pSample))>=0) {
182 //HLTDebug("sample %s (%p) managed by handler", pSample->GetComponentID(), pSample);
183 fOwnedComponents.push_back(pSample);
188 Int_t AliHLTComponentHandler::RegisterComponent(AliHLTComponent* pSample)
190 // see header file for class documentation
193 if (FindComponent(pSample->GetComponentID())==NULL) {
194 iResult=InsertComponent(pSample);
196 HLTInfo("component %s registered", pSample->GetComponentID());
199 // component already registered
200 HLTDebug("component %s already registered, skipped", pSample->GetComponentID());
209 int AliHLTComponentHandler::DeregisterComponent( const char* componentID )
211 // see header file for class documentation
215 HLTWarning("not yet implemented, please notify the developers if you need this function");
222 Int_t AliHLTComponentHandler::ScheduleRegister(AliHLTComponent* pSample)
224 // see header file for class documentation
227 fScheduleList.push_back(pSample);
234 int AliHLTComponentHandler::CreateComponent(const char* componentID, void* pEnvParam, int argc, const char** argv, AliHLTComponent*& component)
236 // see header file for class documentation
237 int iResult=CreateComponent(componentID, component);
238 if (iResult>=0 && component) {
239 HLTDebug("component \"%s\" created (%p)", componentID, component);
240 if ((iResult=component->Init(&fEnvironment, pEnvParam, argc, argv))!=0) {
241 HLTError("Initialization of component \"%s\" failed with error %d", componentID, iResult);
249 int AliHLTComponentHandler::CreateComponent(const char* componentID, AliHLTComponent*& component )
251 // see header file for class documentation
254 AliHLTComponent* pSample=FindComponent(componentID);
256 component=pSample->Spawn();
258 HLTDebug("component \"%s\" created (%p)", componentID, component);
260 HLTError("can not spawn component \"%s\"", componentID);
264 HLTWarning("can not find component \"%s\"", componentID);
273 Int_t AliHLTComponentHandler::FindComponentIndex(const char* componentID)
275 // see header file for class documentation
278 AliHLTComponentPList::iterator element=fComponentList.begin();
279 while (element!=fComponentList.end() && iResult>=0) {
280 if (strcmp(componentID, (*element)->GetComponentID())==0) {
286 if (element==fComponentList.end()) iResult=-ENOENT;
293 AliHLTComponent* AliHLTComponentHandler::FindComponent(const char* componentID)
295 // see header file for class documentation
296 AliHLTComponent* pSample=NULL;
297 Int_t index=FindComponentIndex(componentID);
299 pSample=(AliHLTComponent*)fComponentList.at(index);
304 Int_t AliHLTComponentHandler::InsertComponent(AliHLTComponent* pSample)
306 // see header file for class documentation
309 fComponentList.push_back(pSample);
316 void AliHLTComponentHandler::List()
318 // see header file for class documentation
319 AliHLTComponentPList::iterator element=fComponentList.begin();
321 while (element!=fComponentList.end()) {
322 HLTInfo("%d. %s", index++, (*element++)->GetComponentID());
326 int AliHLTComponentHandler::HasOutputData( const char* componentID)
328 // see header file for class documentation
330 AliHLTComponent* pSample=FindComponent(componentID);
332 AliHLTComponent::TComponentType ct=AliHLTComponent::kUnknown;
333 ct=pSample->GetComponentType();
334 iResult=(ct==AliHLTComponent::kSource || ct==AliHLTComponent::kProcessor);
341 void AliHLTComponentHandler::SetEnvironment(AliHLTAnalysisEnvironment* pEnv)
343 // see header file for class documentation
345 memset(&fEnvironment, 0, sizeof(AliHLTAnalysisEnvironment));
346 memcpy(&fEnvironment, pEnv, pEnv->fStructSize<sizeof(AliHLTAnalysisEnvironment)?pEnv->fStructSize:sizeof(AliHLTAnalysisEnvironment));
347 fEnvironment.fStructSize=sizeof(AliHLTAnalysisEnvironment);
348 if (fEnvironment.fLoggingFunc) {
349 // the AliHLTLogging::Init method also sets the stream output
350 // and notification handler to AliLog. This should only be done
351 // if the logging environment contains a logging function
353 AliHLTLogging::Init(fEnvironment.fLoggingFunc);
358 AliHLTComponentHandler::TLibraryMode AliHLTComponentHandler::SetLibraryMode(TLibraryMode mode)
360 // see header file for class documentation
361 TLibraryMode old=fLibraryMode;
366 int AliHLTComponentHandler::LoadLibrary( const char* libraryPath, int bActivateAgents)
368 // see header file for class documentation
371 TString libName=libraryPath;
373 while ((slash=libName.Index("/"))>=0) {
374 libName=libName.Remove(0, slash+1);
376 libName.ReplaceAll(".so","");
378 // set the global component handler for static component registration
379 AliHLTComponent::SetGlobalComponentHandler(this);
381 AliHLTLibHandle hLib;
382 AliHLTLibHandle* phSearch=FindLibrary(libraryPath);
383 const char* loadtype="";
385 // use interface to the dynamic linking loader
387 // exeption does not help in Root context, the Root exeption
388 // handler always catches the exeption before. Have to find out
389 // how exeptions can be used in Root
391 hLib.fHandle=dlopen(libraryPath, RTLD_NOW);
396 // error message printed further down
397 loadtype="dlopen exeption";
401 // use ROOT dynamic loader
402 // check if the library was already loaded, as Load returns
403 // 'failure' if the library was already loaded
406 int* pRootHandle=reinterpret_cast<int*>(phSearch->fHandle);
408 HLTDebug("instance %d of library %s loaded", (*pRootHandle), libraryPath);
409 hLib.fHandle=pRootHandle;
412 if (hLib.fHandle==NULL &&
413 LoadDependencies(libraryPath) >=0 &&
414 gSystem->Load(libraryPath)>=0) {
415 int* pRootHandle=new int;
416 if (pRootHandle) *pRootHandle=1;
417 hLib.fHandle=pRootHandle;
418 //HLTDebug("library %s loaded via gSystem", libraryPath);
424 // error message printed further down
425 loadtype="gSystem exeption";
428 #endif //HAVE_DLFCN_H
429 if (hLib.fHandle!=NULL) {
430 // create TString object to store library path and use pointer as handle
431 hLib.fName=new TString(libraryPath);
432 hLib.fMode=fLibraryMode;
433 fLibraryList.insert(fLibraryList.begin(), hLib);
435 typedef void (*CompileInfo)(const char*& date, const char*& time);
436 CompileInfo fctInfo=(CompileInfo)FindSymbol(libraryPath, "CompileInfo");
439 const char* buildOn="";
441 buildOn=" build on ";
442 (*fctInfo)(date, time);
443 if (!date) date="unknown";
444 if (!time) time="unknown";
446 HLTImportant("using %s plugin%s%s %s (%s%s)", libraryPath, buildOn, date, time, hLib.fMode==kStatic?"persistent, ":"", loadtype);
449 // static registration of components when library is loaded
450 iResult=RegisterScheduledComponents();
453 HLTError("can not load library %s (%s)", libraryPath, loadtype);
455 HLTError("dlopen error: %s", dlerror());
456 #endif //HAVE_DLFCN_H
463 AliHLTComponent::UnsetGlobalComponentHandler();
466 // alternative dynamic registration by library agents
467 // !!! has to be done after UnsetGlobalComponentHandler
468 if (bActivateAgents) ActivateAgents(libName.Data());
477 int AliHLTComponentHandler::LoadDependencies( const char* libraryPath)
479 // Load external library dependencies defined in a static array
480 if (!libraryPath) return -EINVAL;
483 for (unsigned i=0; i<sizeof(fgkLibDep)/sizeof(fgkLibDep[0]); i++) {
484 if (strcmp(libraryPath, (fgkLibDep[i]).first)==0) {
485 HLTInfo("loading library dependency for %s: %s", libraryPath, (fgkLibDep[i]).second);
486 int result=gSystem->Load((fgkLibDep[i]).second);
488 HLTError("failed to load library dependency for %s: %s", libraryPath, (fgkLibDep[i]).second);
494 static bool bWarning=true;
497 HLTWarning("function not supposed to be used with dlopen, all library dependencies need to be compiled in");
499 #endif // !HAVE_DLFCN_H
504 int AliHLTComponentHandler::UnloadLibrary( const char* libraryPath )
506 // see header file for class documentation
509 vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
510 while (element!=fLibraryList.end()) {
511 TString* pName=reinterpret_cast<TString*>((*element).fName);
512 if (pName->CompareTo(libraryPath)==0) {
513 UnloadLibrary(*element);
514 fLibraryList.erase(element);
525 int AliHLTComponentHandler::UnloadLibrary(AliHLTComponentHandler::AliHLTLibHandle &handle)
527 // see header file for class documentation
529 fgAliLoggingFunc=NULL;
530 TString* pName=reinterpret_cast<TString*>(handle.fName);
531 if (handle.fMode!=kStatic) {
533 // exeption does not help in Root context, the Root exeption
534 // handler always catches the exeption before. Have to find out
535 // how exeptions can be used in Root
538 dlclose(handle.fHandle);
542 HLTError("exeption caught during dlclose of library %s", pName!=NULL?pName->Data():"");
546 int* pCount=reinterpret_cast<int*>(handle.fHandle);
547 if (--(*pCount)==0) {
549 /** Matthias 26.04.2007
550 * I spent about a week to investigate a bug which seems to be in ROOT.
551 * Under certain circumstances, TSystem::Unload crashes. The crash occured
552 * for the first time, when libAliHLTUtil was loaded from AliHLTSystem right
553 * after the ComponentHandler was created. It does not occur when dlopen is
555 * It has most likely to do with the garbage collection and automatic
556 * cleanup in ROOT. The crash occurs when ROOT is terminated and before
557 * an instance of AliHLTSystem was created.
558 * root [0] AliHLTSystem gHLT
559 * It does not occur when the instance was created dynamically (but not even
561 * root [0] AliHLTSystem* gHLT=new AliHLTSystem
563 * For that reason, the libraries are not unloaded here, even though there
564 * will be memory leaks.
565 gSystem->Unload(pName->Data());
569 HLTError("missing library name, can not unload");
573 #endif //HAVE_DLFCN_H
575 HLTDebug("unload library %s", pName->Data());
577 HLTWarning("missing name for unloaded library");
589 int AliHLTComponentHandler::UnloadLibraries()
591 // see header file for class documentation
593 vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
594 while (element!=fLibraryList.end()) {
595 UnloadLibrary(*element);
596 fLibraryList.erase(element);
597 element=fLibraryList.begin();
602 AliHLTfctVoid AliHLTComponentHandler::FindSymbol(const char* library, const char* symbol)
604 // see header file for class documentation
605 AliHLTLibHandle* hLib=FindLibrary(library);
606 if (hLib==NULL) return NULL;
607 void (*pFunc)()=NULL;
609 pFunc=(void (*)())dlsym(hLib->fHandle, symbol);
611 TString* name=reinterpret_cast<TString*>(hLib->fName);
612 pFunc=(void (*)())gSystem->DynFindSymbol(name->Data(), symbol);
617 AliHLTComponentHandler::AliHLTLibHandle* AliHLTComponentHandler::FindLibrary(const char* library)
619 // see header file for class documentation
620 AliHLTLibHandle* hLib=NULL;
621 vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
622 while (element!=fLibraryList.end()) {
623 TString* name=reinterpret_cast<TString*>((*element).fName);
624 if (name->CompareTo(library)==0) {
633 int AliHLTComponentHandler::AddStandardComponents()
635 // see header file for class documentation
637 AliHLTComponent::SetGlobalComponentHandler(this);
638 AliHLTComponent::UnsetGlobalComponentHandler();
639 iResult=RegisterScheduledComponents();
643 int AliHLTComponentHandler::RegisterScheduledComponents()
645 // see header file for class documentation
647 AliHLTComponentPList::iterator element=fScheduleList.begin();
649 while (element!=fScheduleList.end()) {
650 iLocalResult=RegisterComponent(*element);
651 if (iResult==0) iResult=iLocalResult;
652 fScheduleList.erase(element);
653 element=fScheduleList.begin();
658 int AliHLTComponentHandler::ActivateAgents(const char* library, const char* blackList)
660 // see header file for class documentation
662 vector<AliHLTModuleAgent*> agents;
663 for (AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent();
664 pAgent && iResult>=0;
665 pAgent=AliHLTModuleAgent::GetNextAgent()) {
667 // check if we found the agent for the specified library
669 TString check="libAliHLT"; check+=pAgent->GetModuleId();
670 if (check.CompareTo(library)==0) {
672 agents.push_back(pAgent);
677 // check if the current agent is in the black list
679 const char* found=strstr(blackList, pAgent->GetModuleId());
681 found+=strlen(pAgent->GetModuleId());
682 // skip this agent as it is in the blacklist
683 if (*found==0 or *found==' ') continue;
686 agents.push_back(pAgent);
689 for (vector<AliHLTModuleAgent*>::iterator element=agents.begin();
690 element!=agents.end(); element++) {
691 (*element)->ActivateComponentHandler(this);
694 return agents.size();
697 int AliHLTComponentHandler::DeleteOwnedComponents()
699 // see header file for class documentation
701 AliHLTComponentPList::iterator element=fOwnedComponents.begin();
702 while (element!=fOwnedComponents.end()) {
703 //DeregisterComponent((*element)->GetComponentID());
704 // exeption does not help in Root context, the Root exeption
705 // handler always catches the exeption before. Have to find out
706 // how exeptions can be used in Root
712 HLTError("delete managed sample %p", *element);
715 fOwnedComponents.erase(element);
716 element=fOwnedComponents.begin();
721 int AliHLTComponentHandler::SetRunDescription(const AliHLTRunDesc* desc, const char* runType)
723 // see header file for class documentation
724 if (!desc) return -EINVAL;
725 if (desc->fStructSize!=sizeof(AliHLTRunDesc)) {
726 HLTError("invalid size of RunDesc struct (%ul)", desc->fStructSize);
730 memcpy(&fRunDesc, desc, sizeof(AliHLTRunDesc));
732 if (fRunType) delete [] fRunType;
733 fRunType=new char[sizeof(runType)+1];
735 strcpy(fRunType, runType);