]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/AliHLTComponentHandler.cxx
code cleanup
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTComponentHandler.cxx
1 // $Id$
2
3 /**************************************************************************
4  * This file is property of and copyright by the ALICE HLT Project        * 
5  * ALICE Experiment at CERN, All rights reserved.                         *
6  *                                                                        *
7  * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
8  *                  Timm Steinbeck <timm@kip.uni-heidelberg.de>           *
9  *                  for The ALICE HLT Project.                            *
10  *                                                                        *
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  **************************************************************************/
19
20 /** @file   AliHLTComponentHandler.cxx
21     @author Matthias Richter, Timm Steinbeck
22     @date   
23     @brief  Implementation of HLT component handler. */
24
25 // see header file for class documentation
26 // or
27 // refer to README to build package
28 // or
29 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
30
31 #if __GNUC__>= 3
32 using namespace std;
33 #endif
34 //#undef HAVE_DLFCN_H
35 #ifdef HAVE_DLFCN_H
36 #include <dlfcn.h>
37 #else
38 //#include <Riostream.h>
39 #include <TSystem.h>
40 #endif //HAVE_DLFCN_H
41 //#include "AliHLTStdIncludes.h"
42 #include "AliHLTComponentHandler.h"
43 #include "AliHLTComponent.h"
44 #include "AliHLTDataTypes.h"
45 #include "AliHLTModuleAgent.h"
46 #include "TString.h"
47
48 /** ROOT macro for the implementation of ROOT specific class methods */
49 ClassImp(AliHLTComponentHandler)
50
51 AliHLTComponentHandler::AliHLTComponentHandler()
52   :
53   fComponentList(),
54   fScheduleList(),
55   fLibraryList(),
56   fEnvironment(),
57   fOwnedComponents(),
58   fLibraryMode(kDynamic),
59   fRunDesc(kAliHLTVoidRunDesc),
60   fRunType(NULL)
61 {
62   // see header file for class documentation
63   // or
64   // refer to README to build package
65   // or
66   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
67   memset(&fEnvironment, 0, sizeof(AliHLTAnalysisEnvironment));
68   fEnvironment.fStructSize=sizeof(AliHLTAnalysisEnvironment);
69   AddStandardComponents();
70 }
71
72 AliHLTComponentHandler::AliHLTComponentHandler(AliHLTAnalysisEnvironment* pEnv)
73   :
74   AliHLTLogging(),
75   fComponentList(),
76   fScheduleList(),
77   fLibraryList(),
78   fEnvironment(),
79   fOwnedComponents(),
80   fLibraryMode(kDynamic),
81   fRunDesc(kAliHLTVoidRunDesc),
82   fRunType(NULL)
83 {
84   // see header file for class documentation
85   if (pEnv) {
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
91       // for redirection
92       AliHLTLogging::Init(pEnv->fLoggingFunc);
93     }
94   }  else {
95     memset(&fEnvironment, 0, sizeof(AliHLTAnalysisEnvironment));
96     fEnvironment.fStructSize=sizeof(AliHLTAnalysisEnvironment);
97   }
98   //#ifndef __DEBUG
99   //SetLocalLoggingLevel(kHLTLogError);
100   //#else
101   //SetLocalLoggingLevel(kHLTLogInfo);
102   //#endif
103
104   AddStandardComponents();
105 }
106
107 AliHLTComponentHandler::~AliHLTComponentHandler()
108 {
109   // see header file for class documentation
110   DeleteOwnedComponents();
111   UnloadLibraries();
112   if (fRunType) delete [] fRunType;
113   fRunType=NULL;
114 }
115
116 AliHLTComponentHandler* AliHLTComponentHandler::fgpInstance=NULL;
117 int AliHLTComponentHandler::fgNofInstances=0;
118
119 AliHLTComponentHandler* AliHLTComponentHandler::CreateHandler()
120 {
121   // see header file for class documentation
122   if (!fgpInstance) fgpInstance=new AliHLTComponentHandler;
123   fgNofInstances++;
124   return fgpInstance;
125 }
126
127 int AliHLTComponentHandler::Destroy()
128 {
129   // see header file for class documentation
130   int nofInstances=0;
131   if (fgpInstance==this) {
132     nofInstances=fgNofInstances--;
133   }
134   if (nofInstances==0) delete this;
135   return nofInstances;
136 }
137
138 int AliHLTComponentHandler::AnnounceVersion()
139 {
140   // see header file for class documentation
141   int iResult=0;
142 #ifdef PACKAGE_STRING
143   extern void HLTbaseCompileInfo( const char*& date, const char*& time);
144   const char* date="";
145   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);
150 #else
151   HLTImportant("ALICE High Level Trigger build on %s (%s) (embedded AliRoot build)", __DATE__, __TIME__);
152 #endif
153   return iResult;
154 }
155
156 Int_t AliHLTComponentHandler::AddComponent(AliHLTComponent* pSample)
157 {
158   // see header file for class documentation
159   Int_t iResult=0;
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);
164   }
165   return iResult;
166 }
167
168 Int_t AliHLTComponentHandler::RegisterComponent(AliHLTComponent* pSample)
169 {
170   // see header file for class documentation
171   Int_t iResult=0;
172   if (pSample) {
173     if (FindComponent(pSample->GetComponentID())==NULL) {
174       iResult=InsertComponent(pSample);
175       if (iResult>=0) {
176         HLTInfo("component %s registered", pSample->GetComponentID());
177       }
178     } else {
179       // component already registered
180       HLTDebug("component %s already registered, skipped", pSample->GetComponentID());
181       iResult=-EEXIST;
182     }
183   } else {
184     iResult=-EINVAL;
185   }
186   return iResult;
187 }
188
189 int AliHLTComponentHandler::DeregisterComponent( const char* componentID )
190 {
191   // see header file for class documentation
192
193   int iResult=0;
194   if (componentID) {
195     HLTWarning("not yet implemented, please notify the developers if you need this function");
196   } else {
197     iResult=-EINVAL;
198   }
199   return iResult;
200 }
201
202 Int_t AliHLTComponentHandler::ScheduleRegister(AliHLTComponent* pSample)
203 {
204   // see header file for class documentation
205   Int_t iResult=0;
206   if (pSample) {
207     fScheduleList.push_back(pSample);
208   } else {
209     iResult=-EINVAL;
210   }
211   return iResult;
212 }
213
214 int AliHLTComponentHandler::CreateComponent(const char* componentID, void* pEnvParam, int argc, const char** argv, AliHLTComponent*& component)
215 {
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);
222           delete component;
223           component=NULL;
224         }
225   }
226   return iResult;
227 }
228
229 int AliHLTComponentHandler::CreateComponent(const char* componentID, AliHLTComponent*& component )
230 {
231   // see header file for class documentation
232   int iResult=0;
233   if (componentID) {
234     AliHLTComponent* pSample=FindComponent(componentID);
235     if (pSample!=NULL) {
236       component=pSample->Spawn();
237       if (component) {
238         HLTDebug("component \"%s\" created (%p)", componentID, component);
239       } else {
240         HLTError("can not spawn component \"%s\"", componentID);
241         iResult=-ENOENT;
242       }
243     } else {
244       HLTWarning("can not find component \"%s\"", componentID);
245       iResult=-ENOENT;
246     }
247   } else {
248     iResult=-EINVAL;
249   }
250   return iResult;
251 }
252
253 Int_t AliHLTComponentHandler::FindComponentIndex(const char* componentID)
254 {
255   // see header file for class documentation
256   Int_t iResult=0;
257   if (componentID) {
258     AliHLTComponentPList::iterator element=fComponentList.begin();
259     while (element!=fComponentList.end() && iResult>=0) {
260       if (strcmp(componentID, (*element)->GetComponentID())==0) {
261         break;
262       }
263       element++;
264       iResult++;
265     }
266     if (element==fComponentList.end()) iResult=-ENOENT;
267   } else {
268     iResult=-EINVAL;
269   }
270   return iResult;
271 }
272
273 AliHLTComponent* AliHLTComponentHandler::FindComponent(const char* componentID)
274 {
275   // see header file for class documentation
276   AliHLTComponent* pSample=NULL;
277   Int_t index=FindComponentIndex(componentID);
278   if (index>=0) {
279     pSample=(AliHLTComponent*)fComponentList.at(index);
280   }
281   return pSample;
282 }
283
284 Int_t AliHLTComponentHandler::InsertComponent(AliHLTComponent* pSample)
285 {
286   // see header file for class documentation
287   Int_t iResult=0;
288   if (pSample!=NULL) {
289     fComponentList.push_back(pSample);
290   } else {
291     iResult=-EINVAL;
292   }
293   return iResult;
294 }
295
296 void AliHLTComponentHandler::List() 
297 {
298   // see header file for class documentation
299   AliHLTComponentPList::iterator element=fComponentList.begin();
300   int index=0;
301   while (element!=fComponentList.end()) {
302     HLTInfo("%d. %s", index++, (*element++)->GetComponentID());
303   }
304 }
305
306 int AliHLTComponentHandler::HasOutputData( const char* componentID)
307 {
308   // see header file for class documentation
309   int iResult=0;
310   AliHLTComponent* pSample=FindComponent(componentID);
311   if (pSample) {
312     AliHLTComponent::TComponentType ct=AliHLTComponent::kUnknown;
313     ct=pSample->GetComponentType();
314     iResult=(ct==AliHLTComponent::kSource || ct==AliHLTComponent::kProcessor);
315   } else {
316     iResult=-ENOENT;
317   }
318   return iResult;
319 }
320
321 void AliHLTComponentHandler::SetEnvironment(AliHLTAnalysisEnvironment* pEnv) 
322 {
323   // see header file for class documentation
324   if (pEnv) {
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
332       // for redirection
333       AliHLTLogging::Init(fEnvironment.fLoggingFunc);
334     }
335   }
336 }
337
338 AliHLTComponentHandler::TLibraryMode AliHLTComponentHandler::SetLibraryMode(TLibraryMode mode)
339 {
340   // see header file for class documentation
341   TLibraryMode old=fLibraryMode;
342   fLibraryMode=mode;
343   return old;
344 }
345
346 int AliHLTComponentHandler::LoadLibrary( const char* libraryPath, int bActivateAgents)
347 {
348   // see header file for class documentation
349   int iResult=0;
350   if (libraryPath) {
351     TString libName=libraryPath;
352     int slash=-1;
353     while ((slash=libName.Index("/"))>=0) {
354       libName=libName.Remove(0, slash+1);
355     }
356     libName.ReplaceAll(".so","");
357
358     // set the global component handler for static component registration
359     AliHLTComponent::SetGlobalComponentHandler(this);
360
361     AliHLTLibHandle hLib;
362     AliHLTLibHandle* phSearch=FindLibrary(libraryPath);
363     const char* loadtype="";
364 #ifdef HAVE_DLFCN_H
365     // use interface to the dynamic linking loader
366
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
370     /*try*/ {
371       hLib.fHandle=dlopen(libraryPath, RTLD_NOW);
372       loadtype="dlopen";
373     }
374     /*
375     catch (...) {
376       // error message printed further down
377       loadtype="dlopen exeption";
378     }
379     */
380 #else
381     // use ROOT dynamic loader
382     // check if the library was already loaded, as Load returns
383     // 'failure' if the library was already loaded
384     /*try*/ {
385     if (phSearch) {
386         int* pRootHandle=reinterpret_cast<int*>(phSearch->fHandle);
387         (*pRootHandle)++;
388         HLTDebug("instance %d of library %s loaded", (*pRootHandle), libraryPath);
389         hLib.fHandle=pRootHandle;
390     }
391     
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);
397     }
398     loadtype="gSystem";
399     }
400     /*
401     catch (...) {
402       // error message printed further down
403       loadtype="gSystem exeption";
404     }
405     */
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);
412       if (!phSearch) {
413       typedef void (*CompileInfo)(const char*& date, const char*& time);
414       CompileInfo fctInfo=(CompileInfo)FindSymbol(libraryPath, "CompileInfo");
415       const char* date="";
416       const char* time="";
417       const char* buildOn="";
418       if (fctInfo) {
419         buildOn=" build on ";
420         (*fctInfo)(date, time);
421         if (!date) date="unknown";
422         if (!time) time="unknown";
423       }
424       HLTImportant("using %s plugin%s%s %s (%s%s)", libraryPath, buildOn, date, time, hLib.fMode==kStatic?"persistent, ":"", loadtype);
425       }
426
427       // static registration of components when library is loaded
428       iResult=RegisterScheduledComponents();
429
430     } else {
431       HLTError("can not load library %s (%s)", libraryPath, loadtype);
432 #ifdef HAVE_DLFCN_H
433       HLTError("dlopen error: %s", dlerror());
434 #endif //HAVE_DLFCN_H
435 #ifdef __APPLE__
436       iResult=-EFTYPE;
437 #else
438       iResult=-ELIBACC;
439 #endif
440     }
441     AliHLTComponent::UnsetGlobalComponentHandler();
442     
443     if (iResult>=0) {
444       // alternative dynamic registration by library agents
445       // !!! has to be done after UnsetGlobalComponentHandler
446       if (bActivateAgents) ActivateAgents(libName.Data());
447     }
448
449   } else {
450     iResult=-EINVAL;
451   }
452   return iResult;
453 }
454
455 int AliHLTComponentHandler::UnloadLibrary( const char* libraryPath )
456 {
457   // see header file for class documentation
458   int iResult=0;
459   if (libraryPath) {
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);
466         break;
467       }
468       element++;
469   }
470   } else {
471     iResult=-EINVAL;
472   }
473   return iResult;
474 }
475
476 int AliHLTComponentHandler::UnloadLibrary(AliHLTComponentHandler::AliHLTLibHandle &handle)
477 {
478   // see header file for class documentation
479   int iResult=0;
480   fgAliLoggingFunc=NULL;
481   TString* pName=reinterpret_cast<TString*>(handle.fName);
482   if (handle.fMode!=kStatic) {
483 #ifdef HAVE_DLFCN_H
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
487
488   /*try*/ {
489     dlclose(handle.fHandle);
490   }
491   /*
492   catch (...) {
493     HLTError("exeption caught during dlclose of library %s", pName!=NULL?pName->Data():"");
494   }
495   */
496 #else
497   int* pCount=reinterpret_cast<int*>(handle.fHandle);
498   if (--(*pCount)==0) {
499     if (pName) {
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
505        * used. 
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
511        * deleted)
512        *   root [0] AliHLTSystem* gHLT=new AliHLTSystem
513        *
514        * For that reason, the libraries are not unloaded here, even though there
515        * will be memory leaks.
516       gSystem->Unload(pName->Data());
517        */
518     }
519     else {
520       HLTError("missing library name, can not unload");
521     }
522     delete pCount;
523   }
524 #endif //HAVE_DLFCN_H
525   if (pName) {
526     HLTDebug("unload library %s", pName->Data());
527   } else {
528     HLTWarning("missing name for unloaded library");
529   }
530   }
531   handle.fName=NULL;
532   handle.fHandle=NULL;
533   if (pName) {
534     delete pName;
535   }
536   pName=NULL;
537   return iResult;
538 }
539
540 int AliHLTComponentHandler::UnloadLibraries()
541 {
542   // see header file for class documentation
543   int iResult=0;
544   vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
545   while (element!=fLibraryList.end()) {
546     UnloadLibrary(*element);
547     fLibraryList.erase(element);
548     element=fLibraryList.begin();
549   }
550   return iResult;
551 }
552
553 AliHLTfctVoid AliHLTComponentHandler::FindSymbol(const char* library, const char* symbol)
554 {
555   // see header file for class documentation
556   AliHLTLibHandle* hLib=FindLibrary(library);
557   if (hLib==NULL) return NULL;
558   void (*pFunc)()=NULL;
559 #ifdef HAVE_DLFCN_H
560   pFunc=(void (*)())dlsym(hLib->fHandle, symbol);
561 #else
562   TString* name=reinterpret_cast<TString*>(hLib->fName);
563   pFunc=(void (*)())gSystem->DynFindSymbol(name->Data(), symbol);
564 #endif
565   return pFunc;
566 }
567
568 AliHLTComponentHandler::AliHLTLibHandle* AliHLTComponentHandler::FindLibrary(const char* library)
569 {
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) {
576       hLib=&(*element);
577       break;
578     }
579     element++;
580   }
581   return hLib;
582 }
583
584 int AliHLTComponentHandler::AddStandardComponents()
585 {
586   // see header file for class documentation
587   int iResult=0;
588   AliHLTComponent::SetGlobalComponentHandler(this);
589   AliHLTComponent::UnsetGlobalComponentHandler();
590   iResult=RegisterScheduledComponents();
591   return iResult;
592 }
593
594 int AliHLTComponentHandler::RegisterScheduledComponents()
595 {
596   // see header file for class documentation
597   int iResult=0;
598   AliHLTComponentPList::iterator element=fScheduleList.begin();
599   int iLocalResult=0;
600   while (element!=fScheduleList.end()) {
601     iLocalResult=RegisterComponent(*element);
602     if (iResult==0) iResult=iLocalResult;
603     fScheduleList.erase(element);
604     element=fScheduleList.begin();
605   }
606   return iResult;
607 }
608
609 int AliHLTComponentHandler::ActivateAgents(const char* library, const char* blackList)
610 {
611   // see header file for class documentation
612   int iResult=0;
613   vector<AliHLTModuleAgent*> agents;
614   for (AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent(); 
615        pAgent && iResult>=0;
616        pAgent=AliHLTModuleAgent::GetNextAgent()) {
617
618     // check if we found the agent for the specified library
619     if (library) {
620       TString check="libAliHLT"; check+=pAgent->GetModuleId();
621       if (check.CompareTo(library)==0) {
622         agents.clear();
623         agents.push_back(pAgent);
624         break;
625       }
626     }
627
628     // check if the current agent is in the black list
629     if (blackList) {
630       const char* found=strstr(blackList, pAgent->GetModuleId());
631       if (found) {
632         found+=strlen(pAgent->GetModuleId());
633         // skip this agent as it is in the blacklist
634         if (*found==0 or *found==' ') continue;
635       }
636     }
637     agents.push_back(pAgent);
638   }
639
640   for (vector<AliHLTModuleAgent*>::iterator element=agents.begin();
641        element!=agents.end(); element++) {
642     (*element)->ActivateComponentHandler(this);
643   }
644
645   return agents.size();
646 }
647
648 int AliHLTComponentHandler::DeleteOwnedComponents()
649 {
650   // see header file for class documentation
651   int iResult=0;
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
658     /*try*/ {
659       delete *element;
660     }
661     /*
662     catch (...) {
663       HLTError("delete managed sample %p", *element);
664     }
665     */
666     fOwnedComponents.erase(element);
667     element=fOwnedComponents.begin();
668   }
669   return iResult;
670 }
671
672 int AliHLTComponentHandler::SetRunDescription(const AliHLTRunDesc* desc, const char* runType)
673 {
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);
678     return -EINVAL;
679   }
680
681   memcpy(&fRunDesc, desc, sizeof(AliHLTRunDesc));
682   if (runType) {
683     if (fRunType) delete [] fRunType;
684     fRunType=new char[sizeof(runType)+1];
685     if (fRunType) {
686       strcpy(fRunType, runType);
687     }
688   }
689   return 0;
690 }