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. */
25 // see header file for class documentation
27 // refer to README to build package
29 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
38 //#include <Riostream.h>
41 //#include "AliHLTStdIncludes.h"
42 #include "AliHLTComponentHandler.h"
43 #include "AliHLTComponent.h"
44 #include "AliHLTDataTypes.h"
45 #include "AliHLTModuleAgent.h"
48 /** ROOT macro for the implementation of ROOT specific class methods */
49 ClassImp(AliHLTComponentHandler)
51 AliHLTComponentHandler::AliHLTComponentHandler()
58 fLibraryMode(kDynamic),
59 fRunDesc(kAliHLTVoidRunDesc),
62 // see header file for class documentation
64 // refer to README to build package
66 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
67 memset(&fEnvironment, 0, sizeof(AliHLTComponentEnvironment));
68 AddStandardComponents();
71 AliHLTComponentHandler::AliHLTComponentHandler(AliHLTComponentEnvironment* pEnv)
79 fLibraryMode(kDynamic),
80 fRunDesc(kAliHLTVoidRunDesc),
83 // see header file for class documentation
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
91 AliHLTLogging::Init(pEnv->fLoggingFunc);
94 memset(&fEnvironment, 0, sizeof(AliHLTComponentEnvironment));
97 //SetLocalLoggingLevel(kHLTLogError);
99 //SetLocalLoggingLevel(kHLTLogInfo);
102 AddStandardComponents();
105 AliHLTComponentHandler::~AliHLTComponentHandler()
107 // see header file for class documentation
108 DeleteOwnedComponents();
110 if (fRunType) delete [] fRunType;
114 AliHLTComponentHandler* AliHLTComponentHandler::fgpInstance=NULL;
115 int AliHLTComponentHandler::fgNofInstances=0;
117 AliHLTComponentHandler* AliHLTComponentHandler::CreateHandler()
119 // see header file for class documentation
120 if (!fgpInstance) fgpInstance=new AliHLTComponentHandler;
125 int AliHLTComponentHandler::Destroy()
127 // see header file for class documentation
129 if (fgpInstance==this) {
130 nofInstances=fgNofInstances--;
132 if (nofInstances==0) delete this;
136 int AliHLTComponentHandler::AnnounceVersion()
138 // see header file for class documentation
140 #ifdef PACKAGE_STRING
141 void HLTbaseCompileInfo( char*& date, 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);
149 HLTImportant("ALICE High Level Trigger build on %s (%s) (embedded AliRoot build)", __DATE__, __TIME__);
154 Int_t AliHLTComponentHandler::AddComponent(AliHLTComponent* pSample)
156 // see header file for class documentation
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);
166 Int_t AliHLTComponentHandler::RegisterComponent(AliHLTComponent* pSample)
168 // see header file for class documentation
171 if (FindComponent(pSample->GetComponentID())==NULL) {
172 iResult=InsertComponent(pSample);
174 HLTInfo("component %s registered", pSample->GetComponentID());
177 // component already registered
178 HLTDebug("component %s already registered, skipped", pSample->GetComponentID());
187 int AliHLTComponentHandler::DeregisterComponent( const char* componentID )
189 // see header file for class documentation
193 HLTWarning("not yet implemented, please notify the developers if you need this function");
200 Int_t AliHLTComponentHandler::ScheduleRegister(AliHLTComponent* pSample)
202 // see header file for class documentation
205 fScheduleList.push_back(pSample);
212 int AliHLTComponentHandler::CreateComponent(const char* componentID, void* pEnvParam, int argc, const char** argv, AliHLTComponent*& component)
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);
227 int AliHLTComponentHandler::CreateComponent(const char* componentID, AliHLTComponent*& component )
229 // see header file for class documentation
232 AliHLTComponent* pSample=FindComponent(componentID);
234 component=pSample->Spawn();
236 HLTDebug("component \"%s\" created (%p)", componentID, component);
238 HLTError("can not spawn component \"%s\"", componentID);
242 HLTWarning("can not find component \"%s\"", componentID);
251 Int_t AliHLTComponentHandler::FindComponentIndex(const char* componentID)
253 // see header file for class documentation
256 AliHLTComponentPList::iterator element=fComponentList.begin();
257 while (element!=fComponentList.end() && iResult>=0) {
258 if (strcmp(componentID, (*element)->GetComponentID())==0) {
264 if (element==fComponentList.end()) iResult=-ENOENT;
271 AliHLTComponent* AliHLTComponentHandler::FindComponent(const char* componentID)
273 // see header file for class documentation
274 AliHLTComponent* pSample=NULL;
275 Int_t index=FindComponentIndex(componentID);
277 pSample=(AliHLTComponent*)fComponentList.at(index);
282 Int_t AliHLTComponentHandler::InsertComponent(AliHLTComponent* pSample)
284 // see header file for class documentation
287 fComponentList.push_back(pSample);
294 void AliHLTComponentHandler::List()
296 // see header file for class documentation
297 AliHLTComponentPList::iterator element=fComponentList.begin();
299 while (element!=fComponentList.end()) {
300 HLTInfo("%d. %s", index++, (*element++)->GetComponentID());
304 int AliHLTComponentHandler::HasOutputData( const char* componentID)
306 // see header file for class documentation
308 AliHLTComponent* pSample=FindComponent(componentID);
310 AliHLTComponent::TComponentType ct=AliHLTComponent::kUnknown;
311 ct=pSample->GetComponentType();
312 iResult=(ct==AliHLTComponent::kSource || ct==AliHLTComponent::kProcessor);
319 void AliHLTComponentHandler::SetEnvironment(AliHLTComponentEnvironment* pEnv)
321 // see header file for class documentation
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
329 AliHLTLogging::Init(fEnvironment.fLoggingFunc);
334 AliHLTComponentHandler::TLibraryMode AliHLTComponentHandler::SetLibraryMode(TLibraryMode mode)
336 // see header file for class documentation
337 TLibraryMode old=fLibraryMode;
342 int AliHLTComponentHandler::LoadLibrary( const char* libraryPath, int bActivateAgents)
344 // see header file for class documentation
347 // first activate all agents which are already loaded
348 if (bActivateAgents) ActivateAgents();
350 // set the global component handler for static component registration
351 AliHLTComponent::SetGlobalComponentHandler(this);
353 AliHLTLibHandle hLib;
354 AliHLTLibHandle* phSearch=FindLibrary(libraryPath);
355 const char* loadtype="";
357 // use interface to the dynamic linking loader
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
363 hLib.fHandle=dlopen(libraryPath, RTLD_NOW);
368 // error message printed further down
369 loadtype="dlopen exeption";
373 // use ROOT dynamic loader
374 // check if the library was already loaded, as Load returns
375 // 'failure' if the library was already loaded
378 int* pRootHandle=reinterpret_cast<int*>(phSearch->fHandle);
380 HLTDebug("instance %d of library %s loaded", (*pRootHandle), libraryPath);
381 hLib.fHandle=pRootHandle;
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);
394 // error message printed further down
395 loadtype="gSystem exeption";
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);
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");
411 (*fctInfo)(date, time);
412 if (!date) date="unknown";
413 if (!time) time="unknown";
414 HLTImportant("build on %s (%s)", date, time);
416 HLTImportant("no build info available (possible AliRoot embedded build)");
420 // static registration of components when library is loaded
421 iResult=RegisterScheduledComponents();
424 HLTError("can not load library %s (%s)", libraryPath, loadtype);
426 HLTError("dlopen error: %s", dlerror());
427 #endif //HAVE_DLFCN_H
434 AliHLTComponent::UnsetGlobalComponentHandler();
437 // alternative dynamic registration by library agents
438 // !!! has to be done after UnsetGlobalComponentHandler
439 if (bActivateAgents) ActivateAgents();
448 int AliHLTComponentHandler::UnloadLibrary( const char* libraryPath )
450 // see header file for class documentation
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);
469 int AliHLTComponentHandler::UnloadLibrary(AliHLTComponentHandler::AliHLTLibHandle &handle)
471 // see header file for class documentation
473 fgAliLoggingFunc=NULL;
474 TString* pName=reinterpret_cast<TString*>(handle.fName);
475 if (handle.fMode!=kStatic) {
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
482 dlclose(handle.fHandle);
486 HLTError("exeption caught during dlclose of library %s", pName!=NULL?pName->Data():"");
490 int* pCount=reinterpret_cast<int*>(handle.fHandle);
491 if (--(*pCount)==0) {
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
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
505 * root [0] AliHLTSystem* gHLT=new AliHLTSystem
507 * For that reason, the libraries are not unloaded here, even though there
508 * will be memory leaks.
509 gSystem->Unload(pName->Data());
513 HLTError("missing library name, can not unload");
517 #endif //HAVE_DLFCN_H
519 HLTDebug("unload library %s", pName->Data());
521 HLTWarning("missing name for unloaded library");
533 int AliHLTComponentHandler::UnloadLibraries()
535 // see header file for class documentation
537 vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
538 while (element!=fLibraryList.end()) {
539 UnloadLibrary(*element);
540 fLibraryList.erase(element);
541 element=fLibraryList.begin();
546 void* AliHLTComponentHandler::FindSymbol(const char* library, const char* symbol)
548 // see header file for class documentation
549 AliHLTLibHandle* hLib=FindLibrary(library);
550 if (hLib==NULL) return NULL;
553 pFunc=dlsym(hLib->fHandle, symbol);
555 TString* name=reinterpret_cast<TString*>(hLib->fName);
556 pFunc=gSystem->DynFindSymbol(name->Data(), symbol);
561 AliHLTComponentHandler::AliHLTLibHandle* AliHLTComponentHandler::FindLibrary(const char* library)
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) {
577 int AliHLTComponentHandler::AddStandardComponents()
579 // see header file for class documentation
581 AliHLTComponent::SetGlobalComponentHandler(this);
582 AliHLTComponent::UnsetGlobalComponentHandler();
583 iResult=RegisterScheduledComponents();
587 int AliHLTComponentHandler::RegisterScheduledComponents()
589 // see header file for class documentation
591 AliHLTComponentPList::iterator element=fScheduleList.begin();
593 while (element!=fScheduleList.end()) {
594 iLocalResult=RegisterComponent(*element);
595 if (iResult==0) iResult=iLocalResult;
596 fScheduleList.erase(element);
597 element=fScheduleList.begin();
602 int AliHLTComponentHandler::ActivateAgents(const AliHLTModuleAgent** blackList, int size)
604 // see header file for class documentation
606 AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent();
607 while (pAgent && iResult>=0) {
610 for (; i<size; i++) {
611 if (blackList[i]==pAgent) break;
614 // this agent was in the list
615 pAgent=AliHLTModuleAgent::GetNextAgent();
620 pAgent->ActivateComponentHandler(this);
621 pAgent=AliHLTModuleAgent::GetNextAgent();
626 int AliHLTComponentHandler::DeleteOwnedComponents()
628 // see header file for class documentation
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
641 HLTError("delete managed sample %p", *element);
644 fOwnedComponents.erase(element);
645 element=fOwnedComponents.begin();
650 int AliHLTComponentHandler::SetRunDescription(const AliHLTRunDesc* desc, const char* runType)
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);
659 memcpy(&fRunDesc, desc, sizeof(AliHLTRunDesc));
661 if (fRunType) delete [] fRunType;
662 fRunType=new char[sizeof(runType)+1];
664 strcpy(fRunType, runType);