]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/AliHLTComponentHandler.cxx
- adding event type data block {EVENTTYP:PRIV} to component input blocks
[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   void HLTbaseCompileInfo( char*& date, char*& time);
144   char* date="";
145   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     // first activate all agents which are already loaded
352     if (bActivateAgents) ActivateAgents();
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       HLTImportant("library %s loaded (%s%s)", libraryPath, hLib.fMode==kStatic?"persistent, ":"", loadtype);
410       typedef void (*CompileInfo)( char*& date, char*& time);
411       CompileInfo fctInfo=(CompileInfo)FindSymbol(libraryPath, "CompileInfo");
412       if (fctInfo) {
413         char* date="";
414         char* time="";
415         (*fctInfo)(date, time);
416         if (!date) date="unknown";
417         if (!time) time="unknown";
418         HLTImportant("build on %s (%s)", date, time);
419       } else {
420         HLTImportant("no build info available (possible AliRoot embedded build)");
421       }
422       }
423
424       // static registration of components when library is loaded
425       iResult=RegisterScheduledComponents();
426
427     } else {
428       HLTError("can not load library %s (%s)", libraryPath, loadtype);
429 #ifdef HAVE_DLFCN_H
430       HLTError("dlopen error: %s", dlerror());
431 #endif //HAVE_DLFCN_H
432 #ifdef __APPLE__
433       iResult=-EFTYPE;
434 #else
435       iResult=-ELIBACC;
436 #endif
437     }
438     AliHLTComponent::UnsetGlobalComponentHandler();
439     
440     if (iResult>=0) {
441       // alternative dynamic registration by library agents
442       // !!! has to be done after UnsetGlobalComponentHandler
443       if (bActivateAgents) ActivateAgents();
444     }
445
446   } else {
447     iResult=-EINVAL;
448   }
449   return iResult;
450 }
451
452 int AliHLTComponentHandler::UnloadLibrary( const char* libraryPath )
453 {
454   // see header file for class documentation
455   int iResult=0;
456   if (libraryPath) {
457     vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
458     while (element!=fLibraryList.end()) {
459       TString* pName=reinterpret_cast<TString*>((*element).fName);
460       if (pName->CompareTo(libraryPath)==0) {
461         UnloadLibrary(*element);
462         fLibraryList.erase(element);
463         break;
464       }
465       element++;
466   }
467   } else {
468     iResult=-EINVAL;
469   }
470   return iResult;
471 }
472
473 int AliHLTComponentHandler::UnloadLibrary(AliHLTComponentHandler::AliHLTLibHandle &handle)
474 {
475   // see header file for class documentation
476   int iResult=0;
477   fgAliLoggingFunc=NULL;
478   TString* pName=reinterpret_cast<TString*>(handle.fName);
479   if (handle.fMode!=kStatic) {
480 #ifdef HAVE_DLFCN_H
481   // exeption does not help in Root context, the Root exeption
482   // handler always catches the exeption before. Have to find out
483   // how exeptions can be used in Root
484
485   /*try*/ {
486     dlclose(handle.fHandle);
487   }
488   /*
489   catch (...) {
490     HLTError("exeption caught during dlclose of library %s", pName!=NULL?pName->Data():"");
491   }
492   */
493 #else
494   int* pCount=reinterpret_cast<int*>(handle.fHandle);
495   if (--(*pCount)==0) {
496     if (pName) {
497       /** Matthias 26.04.2007
498        * I spent about a week to investigate a bug which seems to be in ROOT.
499        * Under certain circumstances, TSystem::Unload crashes. The crash occured
500        * for the first time, when libAliHLTUtil was loaded from AliHLTSystem right
501        * after the ComponentHandler was created. It does not occur when dlopen is
502        * used. 
503        * It has most likely to do with the garbage collection and automatic
504        * cleanup in ROOT. The crash occurs when ROOT is terminated and before
505        * an instance of AliHLTSystem was created.
506        *   root [0] AliHLTSystem gHLT
507        * It does not occur when the instance was created dynamically (but not even
508        * deleted)
509        *   root [0] AliHLTSystem* gHLT=new AliHLTSystem
510        *
511        * For that reason, the libraries are not unloaded here, even though there
512        * will be memory leaks.
513       gSystem->Unload(pName->Data());
514        */
515     }
516     else {
517       HLTError("missing library name, can not unload");
518     }
519     delete pCount;
520   }
521 #endif //HAVE_DLFCN_H
522   if (pName) {
523     HLTDebug("unload library %s", pName->Data());
524   } else {
525     HLTWarning("missing name for unloaded library");
526   }
527   }
528   handle.fName=NULL;
529   handle.fHandle=NULL;
530   if (pName) {
531     delete pName;
532   }
533   pName=NULL;
534   return iResult;
535 }
536
537 int AliHLTComponentHandler::UnloadLibraries()
538 {
539   // see header file for class documentation
540   int iResult=0;
541   vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
542   while (element!=fLibraryList.end()) {
543     UnloadLibrary(*element);
544     fLibraryList.erase(element);
545     element=fLibraryList.begin();
546   }
547   return iResult;
548 }
549
550 void* AliHLTComponentHandler::FindSymbol(const char* library, const char* symbol)
551 {
552   // see header file for class documentation
553   AliHLTLibHandle* hLib=FindLibrary(library);
554   if (hLib==NULL) return NULL;
555   void* pFunc=NULL;
556 #ifdef HAVE_DLFCN_H
557   pFunc=dlsym(hLib->fHandle, symbol);
558 #else
559   TString* name=reinterpret_cast<TString*>(hLib->fName);
560   pFunc=gSystem->DynFindSymbol(name->Data(), symbol);
561 #endif
562   return pFunc;
563 }
564
565 AliHLTComponentHandler::AliHLTLibHandle* AliHLTComponentHandler::FindLibrary(const char* library)
566 {
567   // see header file for class documentation
568   AliHLTLibHandle* hLib=NULL;
569   vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
570   while (element!=fLibraryList.end()) {
571     TString* name=reinterpret_cast<TString*>((*element).fName);
572     if (name->CompareTo(library)==0) {
573       hLib=&(*element);
574       break;
575     }
576     element++;
577   }
578   return hLib;
579 }
580
581 int AliHLTComponentHandler::AddStandardComponents()
582 {
583   // see header file for class documentation
584   int iResult=0;
585   AliHLTComponent::SetGlobalComponentHandler(this);
586   AliHLTComponent::UnsetGlobalComponentHandler();
587   iResult=RegisterScheduledComponents();
588   return iResult;
589 }
590
591 int AliHLTComponentHandler::RegisterScheduledComponents()
592 {
593   // see header file for class documentation
594   int iResult=0;
595   AliHLTComponentPList::iterator element=fScheduleList.begin();
596   int iLocalResult=0;
597   while (element!=fScheduleList.end()) {
598     iLocalResult=RegisterComponent(*element);
599     if (iResult==0) iResult=iLocalResult;
600     fScheduleList.erase(element);
601     element=fScheduleList.begin();
602   }
603   return iResult;
604 }
605
606 int AliHLTComponentHandler::ActivateAgents(const AliHLTModuleAgent** blackList, int size)
607 {
608   // see header file for class documentation
609   int iResult=0;
610   AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent();
611   while (pAgent && iResult>=0) {
612     if (blackList) {
613       int i=0;
614       for (; i<size; i++) {
615         if (blackList[i]==pAgent) break;
616       }
617       if (i<size) {
618         // this agent was in the list
619         pAgent=AliHLTModuleAgent::GetNextAgent();
620         continue;
621       }
622     }
623
624     pAgent->ActivateComponentHandler(this);
625     pAgent=AliHLTModuleAgent::GetNextAgent();
626   }
627   return iResult;
628 }
629
630 int AliHLTComponentHandler::DeleteOwnedComponents()
631 {
632   // see header file for class documentation
633   int iResult=0;
634   AliHLTComponentPList::iterator element=fOwnedComponents.begin();
635   while (element!=fOwnedComponents.end()) {
636     //DeregisterComponent((*element)->GetComponentID());
637     // exeption does not help in Root context, the Root exeption
638     // handler always catches the exeption before. Have to find out
639     // how exeptions can be used in Root
640     /*try*/ {
641       delete *element;
642     }
643     /*
644     catch (...) {
645       HLTError("delete managed sample %p", *element);
646     }
647     */
648     fOwnedComponents.erase(element);
649     element=fOwnedComponents.begin();
650   }
651   return iResult;
652 }
653
654 int AliHLTComponentHandler::SetRunDescription(const AliHLTRunDesc* desc, const char* runType)
655 {
656   // see header file for class documentation
657   if (!desc) return -EINVAL;
658   if (desc->fStructSize!=sizeof(AliHLTRunDesc)) {
659     HLTError("invalid size of RunDesc struct (%ul)", desc->fStructSize);
660     return -EINVAL;
661   }
662
663   memcpy(&fRunDesc, desc, sizeof(AliHLTRunDesc));
664   if (runType) {
665     if (fRunType) delete [] fRunType;
666     fRunType=new char[sizeof(runType)+1];
667     if (fRunType) {
668       strcpy(fRunType, runType);
669     }
670   }
671   return 0;
672 }