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