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(AliHLTAnalysisEnvironment));
68 fEnvironment.fStructSize=sizeof(AliHLTAnalysisEnvironment);
69 AddStandardComponents();
72 AliHLTComponentHandler::AliHLTComponentHandler(AliHLTAnalysisEnvironment* pEnv)
80 fLibraryMode(kDynamic),
81 fRunDesc(kAliHLTVoidRunDesc),
84 // see header file for class documentation
86 memcpy(&fEnvironment, pEnv, sizeof(AliHLTAnalysisEnvironment));
87 if (pEnv->fLoggingFunc) {
88 // the AliHLTLogging::Init method also sets the stream output
89 // and notification handler to AliLog. This should only be done
90 // if the logging environment contains a logging function
92 AliHLTLogging::Init(pEnv->fLoggingFunc);
95 memset(&fEnvironment, 0, sizeof(AliHLTAnalysisEnvironment));
96 fEnvironment.fStructSize=sizeof(AliHLTAnalysisEnvironment);
99 //SetLocalLoggingLevel(kHLTLogError);
101 //SetLocalLoggingLevel(kHLTLogInfo);
104 AddStandardComponents();
107 AliHLTComponentHandler::~AliHLTComponentHandler()
109 // see header file for class documentation
110 DeleteOwnedComponents();
112 if (fRunType) delete [] fRunType;
116 AliHLTComponentHandler* AliHLTComponentHandler::fgpInstance=NULL;
117 int AliHLTComponentHandler::fgNofInstances=0;
119 AliHLTComponentHandler* AliHLTComponentHandler::CreateHandler()
121 // see header file for class documentation
122 if (!fgpInstance) fgpInstance=new AliHLTComponentHandler;
127 int AliHLTComponentHandler::Destroy()
129 // see header file for class documentation
131 if (fgpInstance==this) {
132 nofInstances=fgNofInstances--;
134 if (nofInstances==0) delete this;
138 int AliHLTComponentHandler::AnnounceVersion()
140 // see header file for class documentation
142 #ifdef PACKAGE_STRING
143 extern void HLTbaseCompileInfo( const char*& date, const char*& time);
146 HLTbaseCompileInfo(date, time);
147 if (!date) date="unknown";
148 if (!time) time="unknown";
149 HLTImportant("%s build on %s (%s)", PACKAGE_STRING, date, time);
151 HLTImportant("ALICE High Level Trigger build on %s (%s) (embedded AliRoot build)", __DATE__, __TIME__);
156 Int_t AliHLTComponentHandler::AddComponent(AliHLTComponent* pSample)
158 // see header file for class documentation
160 if (pSample==NULL) return -EINVAL;
161 if ((iResult=RegisterComponent(pSample))>=0) {
162 //HLTDebug("sample %s (%p) managed by handler", pSample->GetComponentID(), pSample);
163 fOwnedComponents.push_back(pSample);
168 Int_t AliHLTComponentHandler::RegisterComponent(AliHLTComponent* pSample)
170 // see header file for class documentation
173 if (FindComponent(pSample->GetComponentID())==NULL) {
174 iResult=InsertComponent(pSample);
176 HLTInfo("component %s registered", pSample->GetComponentID());
179 // component already registered
180 HLTDebug("component %s already registered, skipped", pSample->GetComponentID());
189 int AliHLTComponentHandler::DeregisterComponent( const char* componentID )
191 // see header file for class documentation
195 HLTWarning("not yet implemented, please notify the developers if you need this function");
202 Int_t AliHLTComponentHandler::ScheduleRegister(AliHLTComponent* pSample)
204 // see header file for class documentation
207 fScheduleList.push_back(pSample);
214 int AliHLTComponentHandler::CreateComponent(const char* componentID, void* pEnvParam, int argc, const char** argv, AliHLTComponent*& component)
216 // see header file for class documentation
217 int iResult=CreateComponent(componentID, component);
218 if (iResult>=0 && component) {
219 HLTDebug("component \"%s\" created (%p)", componentID, component);
220 if ((iResult=component->Init(&fEnvironment, pEnvParam, argc, argv))!=0) {
221 HLTError("Initialization of component \"%s\" failed with error %d", componentID, iResult);
229 int AliHLTComponentHandler::CreateComponent(const char* componentID, AliHLTComponent*& component )
231 // see header file for class documentation
234 AliHLTComponent* pSample=FindComponent(componentID);
236 component=pSample->Spawn();
238 HLTDebug("component \"%s\" created (%p)", componentID, component);
240 HLTError("can not spawn component \"%s\"", componentID);
244 HLTWarning("can not find component \"%s\"", componentID);
253 Int_t AliHLTComponentHandler::FindComponentIndex(const char* componentID)
255 // see header file for class documentation
258 AliHLTComponentPList::iterator element=fComponentList.begin();
259 while (element!=fComponentList.end() && iResult>=0) {
260 if (strcmp(componentID, (*element)->GetComponentID())==0) {
266 if (element==fComponentList.end()) iResult=-ENOENT;
273 AliHLTComponent* AliHLTComponentHandler::FindComponent(const char* componentID)
275 // see header file for class documentation
276 AliHLTComponent* pSample=NULL;
277 Int_t index=FindComponentIndex(componentID);
279 pSample=(AliHLTComponent*)fComponentList.at(index);
284 Int_t AliHLTComponentHandler::InsertComponent(AliHLTComponent* pSample)
286 // see header file for class documentation
289 fComponentList.push_back(pSample);
296 void AliHLTComponentHandler::List()
298 // see header file for class documentation
299 AliHLTComponentPList::iterator element=fComponentList.begin();
301 while (element!=fComponentList.end()) {
302 HLTInfo("%d. %s", index++, (*element++)->GetComponentID());
306 int AliHLTComponentHandler::HasOutputData( const char* componentID)
308 // see header file for class documentation
310 AliHLTComponent* pSample=FindComponent(componentID);
312 AliHLTComponent::TComponentType ct=AliHLTComponent::kUnknown;
313 ct=pSample->GetComponentType();
314 iResult=(ct==AliHLTComponent::kSource || ct==AliHLTComponent::kProcessor);
321 void AliHLTComponentHandler::SetEnvironment(AliHLTAnalysisEnvironment* pEnv)
323 // see header file for class documentation
325 memset(&fEnvironment, 0, sizeof(AliHLTAnalysisEnvironment));
326 memcpy(&fEnvironment, pEnv, pEnv->fStructSize<sizeof(AliHLTAnalysisEnvironment)?pEnv->fStructSize:sizeof(AliHLTAnalysisEnvironment));
327 fEnvironment.fStructSize=sizeof(AliHLTAnalysisEnvironment);
328 if (fEnvironment.fLoggingFunc) {
329 // the AliHLTLogging::Init method also sets the stream output
330 // and notification handler to AliLog. This should only be done
331 // if the logging environment contains a logging function
333 AliHLTLogging::Init(fEnvironment.fLoggingFunc);
338 AliHLTComponentHandler::TLibraryMode AliHLTComponentHandler::SetLibraryMode(TLibraryMode mode)
340 // see header file for class documentation
341 TLibraryMode old=fLibraryMode;
346 int AliHLTComponentHandler::LoadLibrary( const char* libraryPath, int bActivateAgents)
348 // see header file for class documentation
351 TString libName=libraryPath;
353 while ((slash=libName.Index("/"))>=0) {
354 libName=libName.Remove(0, slash+1);
356 libName.ReplaceAll(".so","");
358 // set the global component handler for static component registration
359 AliHLTComponent::SetGlobalComponentHandler(this);
361 AliHLTLibHandle hLib;
362 AliHLTLibHandle* phSearch=FindLibrary(libraryPath);
363 const char* loadtype="";
365 // use interface to the dynamic linking loader
367 // exeption does not help in Root context, the Root exeption
368 // handler always catches the exeption before. Have to find out
369 // how exeptions can be used in Root
371 hLib.fHandle=dlopen(libraryPath, RTLD_NOW);
376 // error message printed further down
377 loadtype="dlopen exeption";
381 // use ROOT dynamic loader
382 // check if the library was already loaded, as Load returns
383 // 'failure' if the library was already loaded
386 int* pRootHandle=reinterpret_cast<int*>(phSearch->fHandle);
388 HLTDebug("instance %d of library %s loaded", (*pRootHandle), libraryPath);
389 hLib.fHandle=pRootHandle;
392 if (hLib.fHandle==NULL && gSystem->Load(libraryPath)>=0) {
393 int* pRootHandle=new int;
394 if (pRootHandle) *pRootHandle=1;
395 hLib.fHandle=pRootHandle;
396 //HLTDebug("library %s loaded via gSystem", libraryPath);
402 // error message printed further down
403 loadtype="gSystem exeption";
406 #endif //HAVE_DLFCN_H
407 if (hLib.fHandle!=NULL) {
408 // create TString object to store library path and use pointer as handle
409 hLib.fName=new TString(libraryPath);
410 hLib.fMode=fLibraryMode;
411 fLibraryList.insert(fLibraryList.begin(), hLib);
413 typedef void (*CompileInfo)(const char*& date, const char*& time);
414 CompileInfo fctInfo=(CompileInfo)FindSymbol(libraryPath, "CompileInfo");
417 const char* buildOn="";
419 buildOn=" build on ";
420 (*fctInfo)(date, time);
421 if (!date) date="unknown";
422 if (!time) time="unknown";
424 HLTImportant("using %s plugin%s%s %s (%s%s)", libraryPath, buildOn, date, time, hLib.fMode==kStatic?"persistent, ":"", loadtype);
427 // static registration of components when library is loaded
428 iResult=RegisterScheduledComponents();
431 HLTError("can not load library %s (%s)", libraryPath, loadtype);
433 HLTError("dlopen error: %s", dlerror());
434 #endif //HAVE_DLFCN_H
441 AliHLTComponent::UnsetGlobalComponentHandler();
444 // alternative dynamic registration by library agents
445 // !!! has to be done after UnsetGlobalComponentHandler
446 if (bActivateAgents) ActivateAgents(libName.Data());
455 int AliHLTComponentHandler::UnloadLibrary( const char* libraryPath )
457 // see header file for class documentation
460 vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
461 while (element!=fLibraryList.end()) {
462 TString* pName=reinterpret_cast<TString*>((*element).fName);
463 if (pName->CompareTo(libraryPath)==0) {
464 UnloadLibrary(*element);
465 fLibraryList.erase(element);
476 int AliHLTComponentHandler::UnloadLibrary(AliHLTComponentHandler::AliHLTLibHandle &handle)
478 // see header file for class documentation
480 fgAliLoggingFunc=NULL;
481 TString* pName=reinterpret_cast<TString*>(handle.fName);
482 if (handle.fMode!=kStatic) {
484 // exeption does not help in Root context, the Root exeption
485 // handler always catches the exeption before. Have to find out
486 // how exeptions can be used in Root
489 dlclose(handle.fHandle);
493 HLTError("exeption caught during dlclose of library %s", pName!=NULL?pName->Data():"");
497 int* pCount=reinterpret_cast<int*>(handle.fHandle);
498 if (--(*pCount)==0) {
500 /** Matthias 26.04.2007
501 * I spent about a week to investigate a bug which seems to be in ROOT.
502 * Under certain circumstances, TSystem::Unload crashes. The crash occured
503 * for the first time, when libAliHLTUtil was loaded from AliHLTSystem right
504 * after the ComponentHandler was created. It does not occur when dlopen is
506 * It has most likely to do with the garbage collection and automatic
507 * cleanup in ROOT. The crash occurs when ROOT is terminated and before
508 * an instance of AliHLTSystem was created.
509 * root [0] AliHLTSystem gHLT
510 * It does not occur when the instance was created dynamically (but not even
512 * root [0] AliHLTSystem* gHLT=new AliHLTSystem
514 * For that reason, the libraries are not unloaded here, even though there
515 * will be memory leaks.
516 gSystem->Unload(pName->Data());
520 HLTError("missing library name, can not unload");
524 #endif //HAVE_DLFCN_H
526 HLTDebug("unload library %s", pName->Data());
528 HLTWarning("missing name for unloaded library");
540 int AliHLTComponentHandler::UnloadLibraries()
542 // see header file for class documentation
544 vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
545 while (element!=fLibraryList.end()) {
546 UnloadLibrary(*element);
547 fLibraryList.erase(element);
548 element=fLibraryList.begin();
553 void (*AliHLTComponentHandler::FindSymbol(const char* library, const char* symbol))()
555 // see header file for class documentation
556 AliHLTLibHandle* hLib=FindLibrary(library);
557 if (hLib==NULL) return NULL;
558 void (*pFunc)()=NULL;
560 pFunc=(void (*)())dlsym(hLib->fHandle, symbol);
562 TString* name=reinterpret_cast<TString*>(hLib->fName);
563 pFunc=(void (*)())gSystem->DynFindSymbol(name->Data(), symbol);
568 AliHLTComponentHandler::AliHLTLibHandle* AliHLTComponentHandler::FindLibrary(const char* library)
570 // see header file for class documentation
571 AliHLTLibHandle* hLib=NULL;
572 vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
573 while (element!=fLibraryList.end()) {
574 TString* name=reinterpret_cast<TString*>((*element).fName);
575 if (name->CompareTo(library)==0) {
584 int AliHLTComponentHandler::AddStandardComponents()
586 // see header file for class documentation
588 AliHLTComponent::SetGlobalComponentHandler(this);
589 AliHLTComponent::UnsetGlobalComponentHandler();
590 iResult=RegisterScheduledComponents();
594 int AliHLTComponentHandler::RegisterScheduledComponents()
596 // see header file for class documentation
598 AliHLTComponentPList::iterator element=fScheduleList.begin();
600 while (element!=fScheduleList.end()) {
601 iLocalResult=RegisterComponent(*element);
602 if (iResult==0) iResult=iLocalResult;
603 fScheduleList.erase(element);
604 element=fScheduleList.begin();
609 int AliHLTComponentHandler::ActivateAgents(const char* library, const char* blackList)
611 // see header file for class documentation
613 vector<AliHLTModuleAgent*> agents;
614 for (AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent();
615 pAgent && iResult>=0;
616 pAgent=AliHLTModuleAgent::GetNextAgent()) {
618 // check if we found the agent for the specified library
620 TString check="libAliHLT"; check+=pAgent->GetModuleId();
621 if (check.CompareTo(library)==0) {
623 agents.push_back(pAgent);
628 // check if the current agent is in the black list
630 const char* found=strstr(blackList, pAgent->GetModuleId());
632 found+=strlen(pAgent->GetModuleId());
633 // skip this agent as it is in the blacklist
634 if (*found==0 or *found==' ') continue;
637 agents.push_back(pAgent);
640 for (vector<AliHLTModuleAgent*>::iterator element=agents.begin();
641 element!=agents.end(); element++) {
642 (*element)->ActivateComponentHandler(this);
645 return agents.size();
648 int AliHLTComponentHandler::DeleteOwnedComponents()
650 // see header file for class documentation
652 AliHLTComponentPList::iterator element=fOwnedComponents.begin();
653 while (element!=fOwnedComponents.end()) {
654 //DeregisterComponent((*element)->GetComponentID());
655 // exeption does not help in Root context, the Root exeption
656 // handler always catches the exeption before. Have to find out
657 // how exeptions can be used in Root
663 HLTError("delete managed sample %p", *element);
666 fOwnedComponents.erase(element);
667 element=fOwnedComponents.begin();
672 int AliHLTComponentHandler::SetRunDescription(const AliHLTRunDesc* desc, const char* runType)
674 // see header file for class documentation
675 if (!desc) return -EINVAL;
676 if (desc->fStructSize!=sizeof(AliHLTRunDesc)) {
677 HLTError("invalid size of RunDesc struct (%ul)", desc->fStructSize);
681 memcpy(&fRunDesc, desc, sizeof(AliHLTRunDesc));
683 if (fRunType) delete [] fRunType;
684 fRunType=new char[sizeof(runType)+1];
686 strcpy(fRunType, runType);