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