3 //**************************************************************************
4 //* This file is property of and copyright by the *
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.
30 //#include <Riostream.h>
33 #include "AliHLTComponentHandler.h"
34 #include "AliHLTComponent.h"
35 #include "AliHLTDataTypes.h"
36 #include "AliHLTModuleAgent.h"
39 /** ROOT macro for the implementation of ROOT specific class methods */
40 ClassImp(AliHLTComponentHandler)
42 AliHLTComponentHandler::AliHLTComponentHandler()
49 fLibraryMode(kDynamic),
50 fRunDesc(kAliHLTVoidRunDesc),
53 // see header file for class documentation
55 // refer to README to build package
57 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
58 memset(&fEnvironment, 0, sizeof(AliHLTAnalysisEnvironment));
59 fEnvironment.fStructSize=sizeof(AliHLTAnalysisEnvironment);
60 AddStandardComponents();
63 AliHLTComponentHandler::AliHLTComponentHandler(AliHLTAnalysisEnvironment* pEnv)
71 fLibraryMode(kDynamic),
72 fRunDesc(kAliHLTVoidRunDesc),
75 // constructor with environment
77 memcpy(&fEnvironment, pEnv, sizeof(AliHLTAnalysisEnvironment));
78 if (pEnv->fLoggingFunc) {
79 // the AliHLTLogging::Init method also sets the stream output
80 // and notification handler to AliLog. This should only be done
81 // if the logging environment contains a logging function
83 AliHLTLogging::Init(pEnv->fLoggingFunc);
86 memset(&fEnvironment, 0, sizeof(AliHLTAnalysisEnvironment));
87 fEnvironment.fStructSize=sizeof(AliHLTAnalysisEnvironment);
90 //SetLocalLoggingLevel(kHLTLogError);
92 //SetLocalLoggingLevel(kHLTLogInfo);
95 AddStandardComponents();
98 AliHLTComponentHandler::~AliHLTComponentHandler()
102 DeleteOwnedComponents();
104 if (fRunType) delete [] fRunType;
108 AliHLTComponentHandler* AliHLTComponentHandler::fgpInstance=NULL;
109 int AliHLTComponentHandler::fgNofInstances=0;
111 AliHLTComponentHandler* AliHLTComponentHandler::CreateHandler()
113 // create global instance of handler
114 if (!fgpInstance) fgpInstance=new AliHLTComponentHandler;
119 int AliHLTComponentHandler::Destroy()
121 // destroy/delete 'this', checks if 'this' pointer is the global instance,
122 // reduce the instance counter and delete if there are no instances left
123 // IMPORTANT: the object must be considered self-destroyed after the function
125 if (fgpInstance==this) {
126 nofInstances=--fgNofInstances;
128 if (fgNofInstances==0) fgpInstance=NULL;
129 if (nofInstances==0) delete this;
133 int AliHLTComponentHandler::AnnounceVersion()
135 // printout for version
137 #ifdef PACKAGE_STRING
138 extern void HLTbaseCompileInfo( const char*& date, const char*& time);
141 HLTbaseCompileInfo(date, time);
142 if (!date) date="unknown";
143 if (!time) time="unknown";
144 HLTImportant("%s build on %s (%s)", PACKAGE_STRING, date, time);
146 HLTImportant("ALICE High Level Trigger build on %s (%s) (embedded AliRoot build)", __DATE__, __TIME__);
151 Int_t AliHLTComponentHandler::AddComponent(AliHLTComponent* pSample)
153 // add and register a component, handler becomes owner
155 if (pSample==NULL) return -EINVAL;
156 if ((iResult=RegisterComponent(pSample))>=0) {
157 //HLTDebug("sample %s (%p) managed by handler", pSample->GetComponentID(), pSample);
158 fOwnedComponents.push_back(pSample);
163 Int_t AliHLTComponentHandler::RegisterComponent(AliHLTComponent* pSample)
165 // register a component, handler creates clone of sample
168 if (FindComponent(pSample->GetComponentID())==NULL) {
169 iResult=InsertComponent(pSample);
171 HLTInfo("component %s registered", pSample->GetComponentID());
174 // component already registered
175 HLTDebug("component %s already registered, skipped", pSample->GetComponentID());
184 int AliHLTComponentHandler::DeregisterComponent( const char* componentID )
186 // deregister component
190 HLTWarning("not yet implemented, please notify the developers if you need this function");
197 Int_t AliHLTComponentHandler::ScheduleRegister(AliHLTComponent* pSample)
199 // schedule registration
202 fScheduleList.push_back(pSample);
209 int AliHLTComponentHandler::CreateComponent(const char* componentID, void* pEnvParam, int argc, const char** argv, AliHLTComponent*& component)
211 // create a component
212 int iResult=CreateComponent(componentID, component);
213 if (iResult>=0 && component) {
214 HLTDebug("component \"%s\" created (%p)", componentID, component);
215 if ((iResult=component->Init(&fEnvironment, pEnvParam, argc, argv))!=0) {
216 HLTError("Initialization of component \"%s\" failed with error %d", componentID, iResult);
224 int AliHLTComponentHandler::CreateComponent(const char* componentID, AliHLTComponent*& component )
226 // create a component
229 AliHLTComponent* pSample=FindComponent(componentID);
231 component=pSample->Spawn();
233 HLTDebug("component \"%s\" created (%p)", componentID, component);
235 HLTError("can not spawn component \"%s\"", componentID);
239 HLTWarning("can not find component \"%s\"", componentID);
248 Int_t AliHLTComponentHandler::FindComponentIndex(const char* componentID)
250 // find component by ID in the list and return index
253 AliHLTComponentPList::iterator element=fComponentList.begin();
254 while (element!=fComponentList.end() && iResult>=0) {
255 if (strcmp(componentID, (*element)->GetComponentID())==0) {
261 if (element==fComponentList.end()) iResult=-ENOENT;
268 AliHLTComponent* AliHLTComponentHandler::FindComponent(const char* componentID)
270 // find component sample by ID
271 AliHLTComponent* pSample=NULL;
272 Int_t index=FindComponentIndex(componentID);
274 pSample=(AliHLTComponent*)fComponentList.at(index);
279 Int_t AliHLTComponentHandler::InsertComponent(AliHLTComponent* pSample)
281 // insert a component sample in the list
284 fComponentList.push_back(pSample);
291 void AliHLTComponentHandler::List()
293 // print list content
294 // TODO: implement Print()
295 AliHLTComponentPList::iterator element=fComponentList.begin();
297 while (element!=fComponentList.end()) {
298 HLTInfo("%d. %s", index++, (*element++)->GetComponentID());
302 int AliHLTComponentHandler::HasOutputData( const char* componentID)
304 // check if a component has output data
306 AliHLTComponent* pSample=FindComponent(componentID);
308 AliHLTComponent::TComponentType ct=AliHLTComponent::kUnknown;
309 ct=pSample->GetComponentType();
310 iResult=(ct==AliHLTComponent::kSource || ct==AliHLTComponent::kProcessor);
317 void AliHLTComponentHandler::SetEnvironment(AliHLTAnalysisEnvironment* pEnv)
319 // set global environment
321 memset(&fEnvironment, 0, sizeof(AliHLTAnalysisEnvironment));
322 memcpy(&fEnvironment, pEnv, pEnv->fStructSize<sizeof(AliHLTAnalysisEnvironment)?pEnv->fStructSize:sizeof(AliHLTAnalysisEnvironment));
323 fEnvironment.fStructSize=sizeof(AliHLTAnalysisEnvironment);
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
329 AliHLTLogging::Init(fEnvironment.fLoggingFunc);
334 AliHLTComponentHandler::TLibraryMode AliHLTComponentHandler::SetLibraryMode(TLibraryMode mode)
337 TLibraryMode old=fLibraryMode;
342 int AliHLTComponentHandler::LoadLibrary( const char* libraryPath, int bActivateAgents)
347 TString libName=libraryPath;
349 while ((slash=libName.Index("/"))>=0) {
350 libName=libName.Remove(0, slash+1);
352 libName.ReplaceAll(".so","");
354 // set the global component handler for static component registration
355 AliHLTComponent::SetGlobalComponentHandler(this);
357 AliHLTLibHandle hLib;
358 AliHLTLibHandle* phSearch=FindLibrary(libraryPath);
359 const char* loadtype="";
361 // use interface to the dynamic linking loader
363 // exeption does not help in Root context, the Root exeption
364 // handler always catches the exeption before. Have to find out
365 // how exeptions can be used in Root
367 hLib.fHandle=dlopen(libraryPath, RTLD_NOW);
372 // error message printed further down
373 loadtype="dlopen exeption";
377 // use ROOT dynamic loader
378 // check if the library was already loaded, as Load returns
379 // 'failure' if the library was already loaded
382 int* pRootHandle=reinterpret_cast<int*>(phSearch->fHandle);
384 HLTDebug("instance %d of library %s loaded", (*pRootHandle), libraryPath);
385 hLib.fHandle=pRootHandle;
388 if (hLib.fHandle==NULL && gSystem->Load(libraryPath)>=0) {
389 int* pRootHandle=new int;
390 if (pRootHandle) *pRootHandle=1;
391 hLib.fHandle=pRootHandle;
392 //HLTDebug("library %s loaded via gSystem", libraryPath);
398 // error message printed further down
399 loadtype="gSystem exeption";
402 #endif //HAVE_DLFCN_H
403 if (hLib.fHandle!=NULL) {
404 // create TString object to store library path and use pointer as handle
405 hLib.fName=new TString(libraryPath);
406 hLib.fMode=fLibraryMode;
407 fLibraryList.insert(fLibraryList.begin(), hLib);
409 typedef void (*CompileInfo)(const char*& date, const char*& time);
410 CompileInfo fctInfo=(CompileInfo)FindSymbol(libraryPath, "CompileInfo");
413 const char* buildOn="";
415 buildOn=" build on ";
416 (*fctInfo)(date, time);
417 if (!date) date="unknown";
418 if (!time) time="unknown";
420 HLTImportant("using %s plugin%s%s %s (%s%s)", libraryPath, buildOn, date, time, hLib.fMode==kStatic?"persistent, ":"", loadtype);
423 // static registration of components when library is loaded
424 iResult=RegisterScheduledComponents();
427 HLTError("can not load library %s (%s)", libraryPath, loadtype);
429 HLTError("dlopen error: %s", dlerror());
430 #endif //HAVE_DLFCN_H
437 AliHLTComponent::UnsetGlobalComponentHandler();
440 // alternative dynamic registration by library agents
441 // !!! has to be done after UnsetGlobalComponentHandler
442 if (bActivateAgents) ActivateAgents(libName.Data());
451 int AliHLTComponentHandler::UnloadLibrary( const char* libraryPath )
456 vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
457 while (element!=fLibraryList.end()) {
458 TString* pName=reinterpret_cast<TString*>((*element).fName);
459 if (pName->CompareTo(libraryPath)==0) {
460 UnloadLibrary(*element);
461 fLibraryList.erase(element);
472 int AliHLTComponentHandler::UnloadLibrary(AliHLTComponentHandler::AliHLTLibHandle &handle)
476 fgAliLoggingFunc=NULL;
477 TString* pName=reinterpret_cast<TString*>(handle.fName);
478 if (handle.fMode!=kStatic) {
480 // exeption does not help in Root context, the Root exeption
481 // handler always catches the exeption before. Have to find out
482 // how exeptions can be used in Root
485 dlclose(handle.fHandle);
489 HLTError("exeption caught during dlclose of library %s", pName!=NULL?pName->Data():"");
493 int* pCount=reinterpret_cast<int*>(handle.fHandle);
494 if (--(*pCount)==0) {
496 /** Matthias 26.04.2007
497 * I spent about a week to investigate a bug which seems to be in ROOT.
498 * Under certain circumstances, TSystem::Unload crashes. The crash occured
499 * for the first time, when libAliHLTUtil was loaded from AliHLTSystem right
500 * after the ComponentHandler was created. It does not occur when dlopen is
502 * It has most likely to do with the garbage collection and automatic
503 * cleanup in ROOT. The crash occurs when ROOT is terminated and before
504 * an instance of AliHLTSystem was created.
505 * root [0] AliHLTSystem gHLT
506 * It does not occur when the instance was created dynamically (but not even
508 * root [0] AliHLTSystem* gHLT=new AliHLTSystem
510 * For that reason, the libraries are not unloaded here, even though there
511 * will be memory leaks.
512 gSystem->Unload(pName->Data());
516 HLTError("missing library name, can not unload");
520 #endif //HAVE_DLFCN_H
522 HLTDebug("unload library %s", pName->Data());
524 HLTWarning("missing name for unloaded library");
536 int AliHLTComponentHandler::UnloadLibraries()
538 // unload all libraries
540 vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
541 while (element!=fLibraryList.end()) {
542 UnloadLibrary(*element);
543 fLibraryList.erase(element);
544 element=fLibraryList.begin();
549 AliHLTfctVoid AliHLTComponentHandler::FindSymbol(const char* library, const char* symbol)
551 // find symbol in library
552 AliHLTLibHandle* hLib=FindLibrary(library);
553 if (hLib==NULL) return NULL;
554 void (*pFunc)()=NULL;
556 pFunc=(void (*)())dlsym(hLib->fHandle, symbol);
558 TString* name=reinterpret_cast<TString*>(hLib->fName);
559 pFunc=(void (*)())gSystem->DynFindSymbol(name->Data(), symbol);
564 AliHLTComponentHandler::AliHLTLibHandle* AliHLTComponentHandler::FindLibrary(const char* library)
566 // find a library by name
567 AliHLTLibHandle* hLib=NULL;
568 vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
569 while (element!=fLibraryList.end()) {
570 TString* name=reinterpret_cast<TString*>((*element).fName);
571 if (name->CompareTo(library)==0) {
580 int AliHLTComponentHandler::AddStandardComponents()
582 // TODO: not quite clear what was the meaning behind this function
584 AliHLTComponent::SetGlobalComponentHandler(this);
585 AliHLTComponent::UnsetGlobalComponentHandler();
586 iResult=RegisterScheduledComponents();
590 int AliHLTComponentHandler::RegisterScheduledComponents()
592 // register all scheduled components
594 AliHLTComponentPList::iterator element=fScheduleList.begin();
596 while (element!=fScheduleList.end()) {
597 iLocalResult=RegisterComponent(*element);
598 if (iResult==0) iResult=iLocalResult;
599 fScheduleList.erase(element);
600 element=fScheduleList.begin();
605 int AliHLTComponentHandler::ActivateAgents(const char* library, const char* blackList)
607 // activate module agents
608 vector<AliHLTModuleAgent*> agents;
609 for (AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent();
611 pAgent=AliHLTModuleAgent::GetNextAgent()) {
613 // check if we found the agent for the specified library
615 TString check="libAliHLT"; check+=pAgent->GetModuleId();
616 if (check.CompareTo(library)==0) {
618 agents.push_back(pAgent);
623 // check if the current agent is in the black list
625 const char* found=strstr(blackList, pAgent->GetModuleId());
627 found+=strlen(pAgent->GetModuleId());
628 // skip this agent as it is in the blacklist
629 if (*found==0 or *found==' ') continue;
632 agents.push_back(pAgent);
635 for (vector<AliHLTModuleAgent*>::iterator element=agents.begin();
636 element!=agents.end(); element++) {
637 (*element)->ActivateComponentHandler(this);
640 return agents.size();
643 int AliHLTComponentHandler::DeactivateAgents() const {
645 for (AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent();
646 pAgent!=NULL; pAgent=AliHLTModuleAgent::GetNextAgent()) {
647 if(pAgent->GetComponentHandler()==this){
648 pAgent->ActivateComponentHandler(NULL);
655 int AliHLTComponentHandler::DeleteOwnedComponents()
657 // delete all component samples owned by the handler
659 AliHLTComponentPList::iterator element=fOwnedComponents.begin();
660 while (element!=fOwnedComponents.end()) {
661 //DeregisterComponent((*element)->GetComponentID());
662 // exeption does not help in Root context, the Root exeption
663 // handler always catches the exeption before. Have to find out
664 // how exeptions can be used in Root
670 HLTError("delete managed sample %p", *element);
673 fOwnedComponents.erase(element);
674 element=fOwnedComponents.begin();
679 int AliHLTComponentHandler::SetRunDescription(const AliHLTRunDesc* desc, const char* runType)
681 // set global run description
682 if (!desc) return -EINVAL;
683 if (desc->fStructSize!=sizeof(AliHLTRunDesc)) {
684 HLTError("invalid size of RunDesc struct (%ul)", desc->fStructSize);
688 memcpy(&fRunDesc, desc, sizeof(AliHLTRunDesc));
690 if (fRunType) delete [] fRunType;
691 fRunType=new char[sizeof(runType)+1];
693 strcpy(fRunType, runType);