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();
108 AliHLTComponentHandler::~AliHLTComponentHandler()
110 // see header file for class documentation
111 DeleteOwnedComponents();
113 if (fRunType) delete [] fRunType;
117 AliHLTComponentHandler* AliHLTComponentHandler::fgpInstance=NULL;
118 int AliHLTComponentHandler::fgNofInstances=0;
120 AliHLTComponentHandler* AliHLTComponentHandler::CreateHandler()
122 // see header file for class documentation
123 if (!fgpInstance) fgpInstance=new AliHLTComponentHandler;
128 int AliHLTComponentHandler::Destroy()
130 // destroy/delete 'this', checks if 'this' pointer is the global instance,
131 // reduce the instance counter and delete if there are no instances left
132 // IMPORTANT: the object must be considered self-destroyed after the function
134 if (fgpInstance==this) {
135 nofInstances=--fgNofInstances;
137 if (fgNofInstances==0) fgpInstance=NULL;
138 if (nofInstances==0) delete this;
142 int AliHLTComponentHandler::AnnounceVersion()
144 // see header file for class documentation
146 #ifdef PACKAGE_STRING
147 extern void HLTbaseCompileInfo( const char*& date, const char*& time);
150 HLTbaseCompileInfo(date, time);
151 if (!date) date="unknown";
152 if (!time) time="unknown";
153 HLTImportant("%s build on %s (%s)", PACKAGE_STRING, date, time);
155 HLTImportant("ALICE High Level Trigger build on %s (%s) (embedded AliRoot build)", __DATE__, __TIME__);
160 Int_t AliHLTComponentHandler::AddComponent(AliHLTComponent* pSample)
162 // see header file for class documentation
164 if (pSample==NULL) return -EINVAL;
165 if ((iResult=RegisterComponent(pSample))>=0) {
166 //HLTDebug("sample %s (%p) managed by handler", pSample->GetComponentID(), pSample);
167 fOwnedComponents.push_back(pSample);
172 Int_t AliHLTComponentHandler::RegisterComponent(AliHLTComponent* pSample)
174 // see header file for class documentation
177 if (FindComponent(pSample->GetComponentID())==NULL) {
178 iResult=InsertComponent(pSample);
180 HLTInfo("component %s registered", pSample->GetComponentID());
183 // component already registered
184 HLTDebug("component %s already registered, skipped", pSample->GetComponentID());
193 int AliHLTComponentHandler::DeregisterComponent( const char* componentID )
195 // see header file for class documentation
199 HLTWarning("not yet implemented, please notify the developers if you need this function");
206 Int_t AliHLTComponentHandler::ScheduleRegister(AliHLTComponent* pSample)
208 // see header file for class documentation
211 fScheduleList.push_back(pSample);
218 int AliHLTComponentHandler::CreateComponent(const char* componentID, void* pEnvParam, int argc, const char** argv, AliHLTComponent*& component)
220 // see header file for class documentation
221 int iResult=CreateComponent(componentID, component);
222 if (iResult>=0 && component) {
223 HLTDebug("component \"%s\" created (%p)", componentID, component);
224 if ((iResult=component->Init(&fEnvironment, pEnvParam, argc, argv))!=0) {
225 HLTError("Initialization of component \"%s\" failed with error %d", componentID, iResult);
233 int AliHLTComponentHandler::CreateComponent(const char* componentID, AliHLTComponent*& component )
235 // see header file for class documentation
238 AliHLTComponent* pSample=FindComponent(componentID);
240 component=pSample->Spawn();
242 HLTDebug("component \"%s\" created (%p)", componentID, component);
244 HLTError("can not spawn component \"%s\"", componentID);
248 HLTWarning("can not find component \"%s\"", componentID);
257 Int_t AliHLTComponentHandler::FindComponentIndex(const char* componentID)
259 // see header file for class documentation
262 AliHLTComponentPList::iterator element=fComponentList.begin();
263 while (element!=fComponentList.end() && iResult>=0) {
264 if (strcmp(componentID, (*element)->GetComponentID())==0) {
270 if (element==fComponentList.end()) iResult=-ENOENT;
277 AliHLTComponent* AliHLTComponentHandler::FindComponent(const char* componentID)
279 // see header file for class documentation
280 AliHLTComponent* pSample=NULL;
281 Int_t index=FindComponentIndex(componentID);
283 pSample=(AliHLTComponent*)fComponentList.at(index);
288 Int_t AliHLTComponentHandler::InsertComponent(AliHLTComponent* pSample)
290 // see header file for class documentation
293 fComponentList.push_back(pSample);
300 void AliHLTComponentHandler::List()
302 // see header file for class documentation
303 AliHLTComponentPList::iterator element=fComponentList.begin();
305 while (element!=fComponentList.end()) {
306 HLTInfo("%d. %s", index++, (*element++)->GetComponentID());
310 int AliHLTComponentHandler::HasOutputData( const char* componentID)
312 // see header file for class documentation
314 AliHLTComponent* pSample=FindComponent(componentID);
316 AliHLTComponent::TComponentType ct=AliHLTComponent::kUnknown;
317 ct=pSample->GetComponentType();
318 iResult=(ct==AliHLTComponent::kSource || ct==AliHLTComponent::kProcessor);
325 void AliHLTComponentHandler::SetEnvironment(AliHLTAnalysisEnvironment* pEnv)
327 // see header file for class documentation
329 memset(&fEnvironment, 0, sizeof(AliHLTAnalysisEnvironment));
330 memcpy(&fEnvironment, pEnv, pEnv->fStructSize<sizeof(AliHLTAnalysisEnvironment)?pEnv->fStructSize:sizeof(AliHLTAnalysisEnvironment));
331 fEnvironment.fStructSize=sizeof(AliHLTAnalysisEnvironment);
332 if (fEnvironment.fLoggingFunc) {
333 // the AliHLTLogging::Init method also sets the stream output
334 // and notification handler to AliLog. This should only be done
335 // if the logging environment contains a logging function
337 AliHLTLogging::Init(fEnvironment.fLoggingFunc);
342 AliHLTComponentHandler::TLibraryMode AliHLTComponentHandler::SetLibraryMode(TLibraryMode mode)
344 // see header file for class documentation
345 TLibraryMode old=fLibraryMode;
350 int AliHLTComponentHandler::LoadLibrary( const char* libraryPath, int bActivateAgents)
352 // see header file for class documentation
355 TString libName=libraryPath;
357 while ((slash=libName.Index("/"))>=0) {
358 libName=libName.Remove(0, slash+1);
360 libName.ReplaceAll(".so","");
362 // set the global component handler for static component registration
363 AliHLTComponent::SetGlobalComponentHandler(this);
365 AliHLTLibHandle hLib;
366 AliHLTLibHandle* phSearch=FindLibrary(libraryPath);
367 const char* loadtype="";
369 // use interface to the dynamic linking loader
371 // exeption does not help in Root context, the Root exeption
372 // handler always catches the exeption before. Have to find out
373 // how exeptions can be used in Root
375 hLib.fHandle=dlopen(libraryPath, RTLD_NOW);
380 // error message printed further down
381 loadtype="dlopen exeption";
385 // use ROOT dynamic loader
386 // check if the library was already loaded, as Load returns
387 // 'failure' if the library was already loaded
390 int* pRootHandle=reinterpret_cast<int*>(phSearch->fHandle);
392 HLTDebug("instance %d of library %s loaded", (*pRootHandle), libraryPath);
393 hLib.fHandle=pRootHandle;
396 if (hLib.fHandle==NULL && gSystem->Load(libraryPath)>=0) {
397 int* pRootHandle=new int;
398 if (pRootHandle) *pRootHandle=1;
399 hLib.fHandle=pRootHandle;
400 //HLTDebug("library %s loaded via gSystem", libraryPath);
406 // error message printed further down
407 loadtype="gSystem exeption";
410 #endif //HAVE_DLFCN_H
411 if (hLib.fHandle!=NULL) {
412 // create TString object to store library path and use pointer as handle
413 hLib.fName=new TString(libraryPath);
414 hLib.fMode=fLibraryMode;
415 fLibraryList.insert(fLibraryList.begin(), hLib);
417 typedef void (*CompileInfo)(const char*& date, const char*& time);
418 CompileInfo fctInfo=(CompileInfo)FindSymbol(libraryPath, "CompileInfo");
421 const char* buildOn="";
423 buildOn=" build on ";
424 (*fctInfo)(date, time);
425 if (!date) date="unknown";
426 if (!time) time="unknown";
428 HLTImportant("using %s plugin%s%s %s (%s%s)", libraryPath, buildOn, date, time, hLib.fMode==kStatic?"persistent, ":"", loadtype);
431 // static registration of components when library is loaded
432 iResult=RegisterScheduledComponents();
435 HLTError("can not load library %s (%s)", libraryPath, loadtype);
437 HLTError("dlopen error: %s", dlerror());
438 #endif //HAVE_DLFCN_H
445 AliHLTComponent::UnsetGlobalComponentHandler();
448 // alternative dynamic registration by library agents
449 // !!! has to be done after UnsetGlobalComponentHandler
450 if (bActivateAgents) ActivateAgents(libName.Data());
459 int AliHLTComponentHandler::UnloadLibrary( const char* libraryPath )
461 // see header file for class documentation
464 vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
465 while (element!=fLibraryList.end()) {
466 TString* pName=reinterpret_cast<TString*>((*element).fName);
467 if (pName->CompareTo(libraryPath)==0) {
468 UnloadLibrary(*element);
469 fLibraryList.erase(element);
480 int AliHLTComponentHandler::UnloadLibrary(AliHLTComponentHandler::AliHLTLibHandle &handle)
482 // see header file for class documentation
484 fgAliLoggingFunc=NULL;
485 TString* pName=reinterpret_cast<TString*>(handle.fName);
486 if (handle.fMode!=kStatic) {
488 // exeption does not help in Root context, the Root exeption
489 // handler always catches the exeption before. Have to find out
490 // how exeptions can be used in Root
493 dlclose(handle.fHandle);
497 HLTError("exeption caught during dlclose of library %s", pName!=NULL?pName->Data():"");
501 int* pCount=reinterpret_cast<int*>(handle.fHandle);
502 if (--(*pCount)==0) {
504 /** Matthias 26.04.2007
505 * I spent about a week to investigate a bug which seems to be in ROOT.
506 * Under certain circumstances, TSystem::Unload crashes. The crash occured
507 * for the first time, when libAliHLTUtil was loaded from AliHLTSystem right
508 * after the ComponentHandler was created. It does not occur when dlopen is
510 * It has most likely to do with the garbage collection and automatic
511 * cleanup in ROOT. The crash occurs when ROOT is terminated and before
512 * an instance of AliHLTSystem was created.
513 * root [0] AliHLTSystem gHLT
514 * It does not occur when the instance was created dynamically (but not even
516 * root [0] AliHLTSystem* gHLT=new AliHLTSystem
518 * For that reason, the libraries are not unloaded here, even though there
519 * will be memory leaks.
520 gSystem->Unload(pName->Data());
524 HLTError("missing library name, can not unload");
528 #endif //HAVE_DLFCN_H
530 HLTDebug("unload library %s", pName->Data());
532 HLTWarning("missing name for unloaded library");
544 int AliHLTComponentHandler::UnloadLibraries()
546 // see header file for class documentation
548 vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
549 while (element!=fLibraryList.end()) {
550 UnloadLibrary(*element);
551 fLibraryList.erase(element);
552 element=fLibraryList.begin();
557 AliHLTfctVoid AliHLTComponentHandler::FindSymbol(const char* library, const char* symbol)
559 // see header file for class documentation
560 AliHLTLibHandle* hLib=FindLibrary(library);
561 if (hLib==NULL) return NULL;
562 void (*pFunc)()=NULL;
564 pFunc=(void (*)())dlsym(hLib->fHandle, symbol);
566 TString* name=reinterpret_cast<TString*>(hLib->fName);
567 pFunc=(void (*)())gSystem->DynFindSymbol(name->Data(), symbol);
572 AliHLTComponentHandler::AliHLTLibHandle* AliHLTComponentHandler::FindLibrary(const char* library)
574 // see header file for class documentation
575 AliHLTLibHandle* hLib=NULL;
576 vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
577 while (element!=fLibraryList.end()) {
578 TString* name=reinterpret_cast<TString*>((*element).fName);
579 if (name->CompareTo(library)==0) {
588 int AliHLTComponentHandler::AddStandardComponents()
590 // see header file for class documentation
592 AliHLTComponent::SetGlobalComponentHandler(this);
593 AliHLTComponent::UnsetGlobalComponentHandler();
594 iResult=RegisterScheduledComponents();
598 int AliHLTComponentHandler::RegisterScheduledComponents()
600 // see header file for class documentation
602 AliHLTComponentPList::iterator element=fScheduleList.begin();
604 while (element!=fScheduleList.end()) {
605 iLocalResult=RegisterComponent(*element);
606 if (iResult==0) iResult=iLocalResult;
607 fScheduleList.erase(element);
608 element=fScheduleList.begin();
613 int AliHLTComponentHandler::ActivateAgents(const char* library, const char* blackList)
615 // see header file for class documentation
616 vector<AliHLTModuleAgent*> agents;
617 for (AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent();
619 pAgent=AliHLTModuleAgent::GetNextAgent()) {
621 // check if we found the agent for the specified library
623 TString check="libAliHLT"; check+=pAgent->GetModuleId();
624 if (check.CompareTo(library)==0) {
626 agents.push_back(pAgent);
631 // check if the current agent is in the black list
633 const char* found=strstr(blackList, pAgent->GetModuleId());
635 found+=strlen(pAgent->GetModuleId());
636 // skip this agent as it is in the blacklist
637 if (*found==0 or *found==' ') continue;
640 agents.push_back(pAgent);
643 for (vector<AliHLTModuleAgent*>::iterator element=agents.begin();
644 element!=agents.end(); element++) {
645 (*element)->ActivateComponentHandler(this);
648 return agents.size();
651 int AliHLTComponentHandler::DeleteOwnedComponents()
653 // see header file for class documentation
655 AliHLTComponentPList::iterator element=fOwnedComponents.begin();
656 while (element!=fOwnedComponents.end()) {
657 //DeregisterComponent((*element)->GetComponentID());
658 // exeption does not help in Root context, the Root exeption
659 // handler always catches the exeption before. Have to find out
660 // how exeptions can be used in Root
666 HLTError("delete managed sample %p", *element);
669 fOwnedComponents.erase(element);
670 element=fOwnedComponents.begin();
675 int AliHLTComponentHandler::SetRunDescription(const AliHLTRunDesc* desc, const char* runType)
677 // see header file for class documentation
678 if (!desc) return -EINVAL;
679 if (desc->fStructSize!=sizeof(AliHLTRunDesc)) {
680 HLTError("invalid size of RunDesc struct (%ul)", desc->fStructSize);
684 memcpy(&fRunDesc, desc, sizeof(AliHLTRunDesc));
686 if (fRunType) delete [] fRunType;
687 fRunType=new char[sizeof(runType)+1];
689 strcpy(fRunType, runType);