]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/AliHLTComponentHandler.cxx
Corrected pragma: no need for newObj to access the target data members
[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   DeleteOwnedComponents();
102   UnloadLibraries();
103   if (fRunType) delete [] fRunType;
104   fRunType=NULL;
105 }
106
107 AliHLTComponentHandler* AliHLTComponentHandler::fgpInstance=NULL;
108 int AliHLTComponentHandler::fgNofInstances=0;
109
110 AliHLTComponentHandler* AliHLTComponentHandler::CreateHandler()
111 {
112   // create global instance of handler
113   if (!fgpInstance) fgpInstance=new AliHLTComponentHandler;
114   fgNofInstances++;
115   return fgpInstance;
116 }
117
118 int AliHLTComponentHandler::Destroy()
119 {
120   // destroy/delete 'this', checks if 'this' pointer is the global instance,
121   // reduce the instance counter and delete if there are no instances left
122   // IMPORTANT: the object must be considered self-destroyed after the function
123   int nofInstances=0;
124   if (fgpInstance==this) {
125     nofInstances=--fgNofInstances;
126   }
127   if (fgNofInstances==0) fgpInstance=NULL;
128   if (nofInstances==0) delete this;
129   return nofInstances;
130 }
131
132 int AliHLTComponentHandler::AnnounceVersion()
133 {
134   // printout for version
135   int iResult=0;
136 #ifdef PACKAGE_STRING
137   extern void HLTbaseCompileInfo( const char*& date, const char*& time);
138   const char* date="";
139   const char* time="";
140   HLTbaseCompileInfo(date, time);
141   if (!date) date="unknown";
142   if (!time) time="unknown";
143   HLTImportant("%s build on %s (%s)", PACKAGE_STRING, date, time);
144 #else
145   HLTImportant("ALICE High Level Trigger build on %s (%s) (embedded AliRoot build)", __DATE__, __TIME__);
146 #endif
147   return iResult;
148 }
149
150 Int_t AliHLTComponentHandler::AddComponent(AliHLTComponent* pSample)
151 {
152   // add and register a component, handler becomes owner
153   Int_t iResult=0;
154   if (pSample==NULL) return -EINVAL;
155   if ((iResult=RegisterComponent(pSample))>=0) {
156     //HLTDebug("sample %s (%p) managed by handler", pSample->GetComponentID(), pSample);
157     fOwnedComponents.push_back(pSample);
158   }
159   return iResult;
160 }
161
162 Int_t AliHLTComponentHandler::RegisterComponent(AliHLTComponent* pSample)
163 {
164   // register a component, handler creates clone of sample
165   Int_t iResult=0;
166   if (pSample) {
167     if (FindComponent(pSample->GetComponentID())==NULL) {
168       iResult=InsertComponent(pSample);
169       if (iResult>=0) {
170         HLTInfo("component %s registered", pSample->GetComponentID());
171       }
172     } else {
173       // component already registered
174       HLTDebug("component %s already registered, skipped", pSample->GetComponentID());
175       iResult=-EEXIST;
176     }
177   } else {
178     iResult=-EINVAL;
179   }
180   return iResult;
181 }
182
183 int AliHLTComponentHandler::DeregisterComponent( const char* componentID )
184 {
185   // deregister component
186
187   int iResult=0;
188   if (componentID) {
189     HLTWarning("not yet implemented, please notify the developers if you need this function");
190   } else {
191     iResult=-EINVAL;
192   }
193   return iResult;
194 }
195
196 Int_t AliHLTComponentHandler::ScheduleRegister(AliHLTComponent* pSample)
197 {
198   // schedule registration
199   Int_t iResult=0;
200   if (pSample) {
201     fScheduleList.push_back(pSample);
202   } else {
203     iResult=-EINVAL;
204   }
205   return iResult;
206 }
207
208 int AliHLTComponentHandler::CreateComponent(const char* componentID, void* pEnvParam, int argc, const char** argv, AliHLTComponent*& component)
209 {
210   // create a component
211   int iResult=CreateComponent(componentID, component);
212   if (iResult>=0 && component) {
213         HLTDebug("component \"%s\" created (%p)", componentID, component);
214         if ((iResult=component->Init(&fEnvironment, pEnvParam, argc, argv))!=0) {
215           HLTError("Initialization of component \"%s\" failed with error %d", componentID, iResult);
216           delete component;
217           component=NULL;
218         }
219   }
220   return iResult;
221 }
222
223 int AliHLTComponentHandler::CreateComponent(const char* componentID, AliHLTComponent*& component )
224 {
225   // create a component
226   int iResult=0;
227   if (componentID) {
228     AliHLTComponent* pSample=FindComponent(componentID);
229     if (pSample!=NULL) {
230       component=pSample->Spawn();
231       if (component) {
232         HLTDebug("component \"%s\" created (%p)", componentID, component);
233       } else {
234         HLTError("can not spawn component \"%s\"", componentID);
235         iResult=-ENOENT;
236       }
237     } else {
238       HLTWarning("can not find component \"%s\"", componentID);
239       iResult=-ENOENT;
240     }
241   } else {
242     iResult=-EINVAL;
243   }
244   return iResult;
245 }
246
247 Int_t AliHLTComponentHandler::FindComponentIndex(const char* componentID)
248 {
249   // find component by ID in the list and return index
250   Int_t iResult=0;
251   if (componentID) {
252     AliHLTComponentPList::iterator element=fComponentList.begin();
253     while (element!=fComponentList.end() && iResult>=0) {
254       if (strcmp(componentID, (*element)->GetComponentID())==0) {
255         break;
256       }
257       element++;
258       iResult++;
259     }
260     if (element==fComponentList.end()) iResult=-ENOENT;
261   } else {
262     iResult=-EINVAL;
263   }
264   return iResult;
265 }
266
267 AliHLTComponent* AliHLTComponentHandler::FindComponent(const char* componentID)
268 {
269   // find component sample by ID
270   AliHLTComponent* pSample=NULL;
271   Int_t index=FindComponentIndex(componentID);
272   if (index>=0) {
273     pSample=(AliHLTComponent*)fComponentList.at(index);
274   }
275   return pSample;
276 }
277
278 Int_t AliHLTComponentHandler::InsertComponent(AliHLTComponent* pSample)
279 {
280   // insert a component sample in the list
281   Int_t iResult=0;
282   if (pSample!=NULL) {
283     fComponentList.push_back(pSample);
284   } else {
285     iResult=-EINVAL;
286   }
287   return iResult;
288 }
289
290 void AliHLTComponentHandler::List() 
291 {
292   // print list content
293   // TODO: implement Print()
294   AliHLTComponentPList::iterator element=fComponentList.begin();
295   int index=0;
296   while (element!=fComponentList.end()) {
297     HLTInfo("%d. %s", index++, (*element++)->GetComponentID());
298   }
299 }
300
301 int AliHLTComponentHandler::HasOutputData( const char* componentID)
302 {
303   // check if a component has output data
304   int iResult=0;
305   AliHLTComponent* pSample=FindComponent(componentID);
306   if (pSample) {
307     AliHLTComponent::TComponentType ct=AliHLTComponent::kUnknown;
308     ct=pSample->GetComponentType();
309     iResult=(ct==AliHLTComponent::kSource || ct==AliHLTComponent::kProcessor);
310   } else {
311     iResult=-ENOENT;
312   }
313   return iResult;
314 }
315
316 void AliHLTComponentHandler::SetEnvironment(AliHLTAnalysisEnvironment* pEnv) 
317 {
318   // set global environment
319   if (pEnv) {
320     memset(&fEnvironment, 0, sizeof(AliHLTAnalysisEnvironment));
321     memcpy(&fEnvironment, pEnv, pEnv->fStructSize<sizeof(AliHLTAnalysisEnvironment)?pEnv->fStructSize:sizeof(AliHLTAnalysisEnvironment));
322     fEnvironment.fStructSize=sizeof(AliHLTAnalysisEnvironment);
323     if (fEnvironment.fLoggingFunc) {
324       // the AliHLTLogging::Init method also sets the stream output
325       // and notification handler to AliLog. This should only be done
326       // if the logging environment contains a logging function
327       // for redirection
328       AliHLTLogging::Init(fEnvironment.fLoggingFunc);
329     }
330   }
331 }
332
333 AliHLTComponentHandler::TLibraryMode AliHLTComponentHandler::SetLibraryMode(TLibraryMode mode)
334 {
335   // set library mode
336   TLibraryMode old=fLibraryMode;
337   fLibraryMode=mode;
338   return old;
339 }
340
341 int AliHLTComponentHandler::LoadLibrary( const char* libraryPath, int bActivateAgents)
342 {
343   // load a library
344   int iResult=0;
345   if (libraryPath) {
346     TString libName=libraryPath;
347     int slash=-1;
348     while ((slash=libName.Index("/"))>=0) {
349       libName=libName.Remove(0, slash+1);
350     }
351     libName.ReplaceAll(".so","");
352
353     // set the global component handler for static component registration
354     AliHLTComponent::SetGlobalComponentHandler(this);
355
356     AliHLTLibHandle hLib;
357     AliHLTLibHandle* phSearch=FindLibrary(libraryPath);
358     const char* loadtype="";
359 #ifdef HAVE_DLFCN_H
360     // use interface to the dynamic linking loader
361
362     // exeption does not help in Root context, the Root exeption
363     // handler always catches the exeption before. Have to find out
364     // how exeptions can be used in Root
365     /*try*/ {
366       hLib.fHandle=dlopen(libraryPath, RTLD_NOW);
367       loadtype="dlopen";
368     }
369     /*
370     catch (...) {
371       // error message printed further down
372       loadtype="dlopen exeption";
373     }
374     */
375 #else
376     // use ROOT dynamic loader
377     // check if the library was already loaded, as Load returns
378     // 'failure' if the library was already loaded
379     /*try*/ {
380     if (phSearch) {
381         int* pRootHandle=reinterpret_cast<int*>(phSearch->fHandle);
382         (*pRootHandle)++;
383         HLTDebug("instance %d of library %s loaded", (*pRootHandle), libraryPath);
384         hLib.fHandle=pRootHandle;
385     }
386     
387     if (hLib.fHandle==NULL && gSystem->Load(libraryPath)>=0) {
388       int* pRootHandle=new int;
389       if (pRootHandle) *pRootHandle=1;
390       hLib.fHandle=pRootHandle;
391       //HLTDebug("library %s loaded via gSystem", libraryPath);
392     }
393     loadtype="gSystem";
394     }
395     /*
396     catch (...) {
397       // error message printed further down
398       loadtype="gSystem exeption";
399     }
400     */
401 #endif //HAVE_DLFCN_H
402     if (hLib.fHandle!=NULL) {
403       // create TString object to store library path and use pointer as handle 
404       hLib.fName=new TString(libraryPath);
405       hLib.fMode=fLibraryMode;
406       fLibraryList.insert(fLibraryList.begin(), hLib);
407       if (!phSearch) {
408       typedef void (*CompileInfo)(const char*& date, const char*& time);
409       CompileInfo fctInfo=(CompileInfo)FindSymbol(libraryPath, "CompileInfo");
410       const char* date="";
411       const char* time="";
412       const char* buildOn="";
413       if (fctInfo) {
414         buildOn=" build on ";
415         (*fctInfo)(date, time);
416         if (!date) date="unknown";
417         if (!time) time="unknown";
418       }
419       HLTImportant("using %s plugin%s%s %s (%s%s)", libraryPath, buildOn, date, time, hLib.fMode==kStatic?"persistent, ":"", loadtype);
420       }
421
422       // static registration of components when library is loaded
423       iResult=RegisterScheduledComponents();
424
425     } else {
426       HLTError("can not load library %s (%s)", libraryPath, loadtype);
427 #ifdef HAVE_DLFCN_H
428       HLTError("dlopen error: %s", dlerror());
429 #endif //HAVE_DLFCN_H
430 #ifdef __APPLE__
431       iResult=-EFTYPE;
432 #else
433       iResult=-ELIBACC;
434 #endif
435     }
436     AliHLTComponent::UnsetGlobalComponentHandler();
437     
438     if (iResult>=0) {
439       // alternative dynamic registration by library agents
440       // !!! has to be done after UnsetGlobalComponentHandler
441       if (bActivateAgents) ActivateAgents(libName.Data());
442     }
443
444   } else {
445     iResult=-EINVAL;
446   }
447   return iResult;
448 }
449
450 int AliHLTComponentHandler::UnloadLibrary( const char* libraryPath )
451 {
452   // unload a library
453   int iResult=0;
454   if (libraryPath) {
455     vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
456     while (element!=fLibraryList.end()) {
457       TString* pName=reinterpret_cast<TString*>((*element).fName);
458       if (pName->CompareTo(libraryPath)==0) {
459         UnloadLibrary(*element);
460         fLibraryList.erase(element);
461         break;
462       }
463       element++;
464   }
465   } else {
466     iResult=-EINVAL;
467   }
468   return iResult;
469 }
470
471 int AliHLTComponentHandler::UnloadLibrary(AliHLTComponentHandler::AliHLTLibHandle &handle)
472 {
473   // unload a library
474   int iResult=0;
475   fgAliLoggingFunc=NULL;
476   TString* pName=reinterpret_cast<TString*>(handle.fName);
477   if (handle.fMode!=kStatic) {
478 #ifdef HAVE_DLFCN_H
479   // exeption does not help in Root context, the Root exeption
480   // handler always catches the exeption before. Have to find out
481   // how exeptions can be used in Root
482
483   /*try*/ {
484     dlclose(handle.fHandle);
485   }
486   /*
487   catch (...) {
488     HLTError("exeption caught during dlclose of library %s", pName!=NULL?pName->Data():"");
489   }
490   */
491 #else
492   int* pCount=reinterpret_cast<int*>(handle.fHandle);
493   if (--(*pCount)==0) {
494     if (pName) {
495       /** Matthias 26.04.2007
496        * I spent about a week to investigate a bug which seems to be in ROOT.
497        * Under certain circumstances, TSystem::Unload crashes. The crash occured
498        * for the first time, when libAliHLTUtil was loaded from AliHLTSystem right
499        * after the ComponentHandler was created. It does not occur when dlopen is
500        * used. 
501        * It has most likely to do with the garbage collection and automatic
502        * cleanup in ROOT. The crash occurs when ROOT is terminated and before
503        * an instance of AliHLTSystem was created.
504        *   root [0] AliHLTSystem gHLT
505        * It does not occur when the instance was created dynamically (but not even
506        * deleted)
507        *   root [0] AliHLTSystem* gHLT=new AliHLTSystem
508        *
509        * For that reason, the libraries are not unloaded here, even though there
510        * will be memory leaks.
511       gSystem->Unload(pName->Data());
512        */
513     }
514     else {
515       HLTError("missing library name, can not unload");
516     }
517     delete pCount;
518   }
519 #endif //HAVE_DLFCN_H
520   if (pName) {
521     HLTDebug("unload library %s", pName->Data());
522   } else {
523     HLTWarning("missing name for unloaded library");
524   }
525   }
526   handle.fName=NULL;
527   handle.fHandle=NULL;
528   if (pName) {
529     delete pName;
530   }
531   pName=NULL;
532   return iResult;
533 }
534
535 int AliHLTComponentHandler::UnloadLibraries()
536 {
537   // unload all libraries
538   int iResult=0;
539   vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
540   while (element!=fLibraryList.end()) {
541     UnloadLibrary(*element);
542     fLibraryList.erase(element);
543     element=fLibraryList.begin();
544   }
545   return iResult;
546 }
547
548 AliHLTfctVoid AliHLTComponentHandler::FindSymbol(const char* library, const char* symbol)
549 {
550   // find symbol in library
551   AliHLTLibHandle* hLib=FindLibrary(library);
552   if (hLib==NULL) return NULL;
553   void (*pFunc)()=NULL;
554 #ifdef HAVE_DLFCN_H
555   pFunc=(void (*)())dlsym(hLib->fHandle, symbol);
556 #else
557   TString* name=reinterpret_cast<TString*>(hLib->fName);
558   pFunc=(void (*)())gSystem->DynFindSymbol(name->Data(), symbol);
559 #endif
560   return pFunc;
561 }
562
563 AliHLTComponentHandler::AliHLTLibHandle* AliHLTComponentHandler::FindLibrary(const char* library)
564 {
565   // find a library by name
566   AliHLTLibHandle* hLib=NULL;
567   vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
568   while (element!=fLibraryList.end()) {
569     TString* name=reinterpret_cast<TString*>((*element).fName);
570     if (name->CompareTo(library)==0) {
571       hLib=&(*element);
572       break;
573     }
574     element++;
575   }
576   return hLib;
577 }
578
579 int AliHLTComponentHandler::AddStandardComponents()
580 {
581   // TODO: not quite clear what was the meaning behind this function
582   int iResult=0;
583   AliHLTComponent::SetGlobalComponentHandler(this);
584   AliHLTComponent::UnsetGlobalComponentHandler();
585   iResult=RegisterScheduledComponents();
586   return iResult;
587 }
588
589 int AliHLTComponentHandler::RegisterScheduledComponents()
590 {
591   // register all scheduled components
592   int iResult=0;
593   AliHLTComponentPList::iterator element=fScheduleList.begin();
594   int iLocalResult=0;
595   while (element!=fScheduleList.end()) {
596     iLocalResult=RegisterComponent(*element);
597     if (iResult==0) iResult=iLocalResult;
598     fScheduleList.erase(element);
599     element=fScheduleList.begin();
600   }
601   return iResult;
602 }
603
604 int AliHLTComponentHandler::ActivateAgents(const char* library, const char* blackList)
605 {
606   // activate module agents
607   vector<AliHLTModuleAgent*> agents;
608   for (AliHLTModuleAgent* pAgent=AliHLTModuleAgent::GetFirstAgent(); 
609        pAgent!=NULL;
610        pAgent=AliHLTModuleAgent::GetNextAgent()) {
611
612     // check if we found the agent for the specified library
613     if (library) {
614       TString check="libAliHLT"; check+=pAgent->GetModuleId();
615       if (check.CompareTo(library)==0) {
616         agents.clear();
617         agents.push_back(pAgent);
618         break;
619       }
620     }
621
622     // check if the current agent is in the black list
623     if (blackList) {
624       const char* found=strstr(blackList, pAgent->GetModuleId());
625       if (found) {
626         found+=strlen(pAgent->GetModuleId());
627         // skip this agent as it is in the blacklist
628         if (*found==0 or *found==' ') continue;
629       }
630     }
631     agents.push_back(pAgent);
632   }
633
634   for (vector<AliHLTModuleAgent*>::iterator element=agents.begin();
635        element!=agents.end(); element++) {
636     (*element)->ActivateComponentHandler(this);
637   }
638
639   return agents.size();
640 }
641
642 int AliHLTComponentHandler::DeleteOwnedComponents()
643 {
644   // delete all component samples owned by the handler
645   int iResult=0;
646   AliHLTComponentPList::iterator element=fOwnedComponents.begin();
647   while (element!=fOwnedComponents.end()) {
648     //DeregisterComponent((*element)->GetComponentID());
649     // exeption does not help in Root context, the Root exeption
650     // handler always catches the exeption before. Have to find out
651     // how exeptions can be used in Root
652     /*try*/ {
653       delete *element;
654     }
655     /*
656     catch (...) {
657       HLTError("delete managed sample %p", *element);
658     }
659     */
660     fOwnedComponents.erase(element);
661     element=fOwnedComponents.begin();
662   }
663   return iResult;
664 }
665
666 int AliHLTComponentHandler::SetRunDescription(const AliHLTRunDesc* desc, const char* runType)
667 {
668   // set global run description
669   if (!desc) return -EINVAL;
670   if (desc->fStructSize!=sizeof(AliHLTRunDesc)) {
671     HLTError("invalid size of RunDesc struct (%ul)", desc->fStructSize);
672     return -EINVAL;
673   }
674
675   memcpy(&fRunDesc, desc, sizeof(AliHLTRunDesc));
676   if (runType) {
677     if (fRunType) delete [] fRunType;
678     fRunType=new char[sizeof(runType)+1];
679     if (fRunType) {
680       strcpy(fRunType, runType);
681     }
682   }
683   return 0;
684 }