]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/AliHLTComponentHandler.cxx
workaround for ROOT bug: in order to avoid crashes when unloading
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTComponentHandler.cxx
1 // $Id$
2
3 /**************************************************************************
4  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
5  *                                                                        *
6  * Authors: Matthias Richter <Matthias.Richter@ift.uib.no>                *
7  *          Timm Steinbeck <timm@kip.uni-heidelberg.de>                   *
8  *          for The ALICE Off-line Project.                               *
9  *                                                                        *
10  * Permission to use, copy, modify and distribute this software and its   *
11  * documentation strictly for non-commercial purposes is hereby granted   *
12  * without fee, provided that the above copyright notice appears in all   *
13  * copies and that both the copyright notice and this permission notice   *
14  * appear in the supporting documentation. The authors make no claims     *
15  * about the suitability of this software for any purpose. It is          *
16  * provided "as is" without express or implied warranty.                  *
17  **************************************************************************/
18
19 /** @file   AliHLTComponentHandler.cxx
20     @author Matthias Richter, Timm Steinbeck
21     @date   
22     @brief  Implementation of HLT component handler. */
23
24 #if __GNUC__>= 3
25 using namespace std;
26 #endif
27 //#undef HAVE_DLFCN_H
28 #ifdef HAVE_DLFCN_H
29 #include <dlfcn.h>
30 #else
31 //#include <Riostream.h>
32 #include <TSystem.h>
33 #endif //HAVE_DLFCN_H
34 #include "AliHLTStdIncludes.h"
35 #include "AliHLTComponentHandler.h"
36 #include "AliHLTComponent.h"
37 #include "AliHLTDataTypes.h"
38 #include "AliHLTSystem.h"
39
40 // the standard components
41 // #include "AliHLTFilePublisher.h"
42 // #include "AliHLTFileWriter.h"
43 // #include "AliHLTRootFilePublisherComponent.h"
44 // #include "AliHLTRootFileWriterComponent.h"
45
46 /** ROOT macro for the implementation of ROOT specific class methods */
47 ClassImp(AliHLTComponentHandler)
48
49 AliHLTComponentHandler::AliHLTComponentHandler()
50   :
51   fComponentList(),
52   fScheduleList(),
53   fLibraryList(),
54   fEnvironment(),
55   fStandardList()
56 {
57   // see header file for class documentation
58   // or
59   // refer to README to build package
60   // or
61   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
62   memset(&fEnvironment, 0, sizeof(AliHLTComponentEnvironment));
63   AddStandardComponents();
64 }
65
66 AliHLTComponentHandler::AliHLTComponentHandler(AliHLTComponentEnvironment* pEnv)
67   :
68   fComponentList(),
69   fScheduleList(),
70   fLibraryList(),
71   fEnvironment(),
72   fStandardList()
73 {
74   // see header file for class documentation
75   if (pEnv) {
76     memcpy(&fEnvironment, pEnv, sizeof(AliHLTComponentEnvironment));
77     if (pEnv->fLoggingFunc) {
78       // the AliHLTLogging::Init method also sets the stream output
79       // and notification handler to AliLog. This should only be done
80       // if the logging environment contains a logging function
81       // for redirection
82       AliHLTLogging::Init(pEnv->fLoggingFunc);
83     }
84   }  else
85     memset(&fEnvironment, 0, sizeof(AliHLTComponentEnvironment));
86   AddStandardComponents();
87 }
88
89 AliHLTComponentHandler::~AliHLTComponentHandler()
90 {
91   // see header file for class documentation
92   DeleteStandardComponents();
93   UnloadLibraries();
94 }
95
96 int AliHLTComponentHandler::AnnounceVersion()
97 {
98   // see header file for class documentation
99   int iResult=0;
100 #ifdef PACKAGE_STRING
101   void HLTbaseCompileInfo( char*& date, char*& time);
102   char* date="";
103   char* time="";
104   HLTbaseCompileInfo(date, time);
105   if (!date) date="unknown";
106   if (!time) time="unknown";
107   HLTInfo("%s build on %s (%s)", PACKAGE_STRING, date, time);
108 #else
109   HLTInfo("ALICE High Level Trigger build on %s (%s) (embedded AliRoot build)", __DATE__, __TIME__);
110 #endif
111   return iResult;
112 }
113
114 Int_t AliHLTComponentHandler::RegisterComponent(AliHLTComponent* pSample)
115 {
116   // see header file for class documentation
117   Int_t iResult=0;
118   if (pSample) {
119     if (FindComponent(pSample->GetComponentID())==NULL) {
120       iResult=InsertComponent(pSample);
121       if (iResult>=0) {
122         HLTInfo("component %s registered", pSample->GetComponentID());
123       }
124     } else {
125       // component already registered
126       HLTDebug("component %s already registered, skipped", pSample->GetComponentID());
127       iResult=-EEXIST;
128     }
129   } else {
130     iResult=-EINVAL;
131   }
132   return iResult;
133 }
134
135 int AliHLTComponentHandler::DeregisterComponent( const char* componentID )
136 {
137   // see header file for class documentation
138   int iResult=0;
139   if (componentID) {
140   } else {
141     iResult=-EINVAL;
142   }
143   return iResult;
144 }
145
146 Int_t AliHLTComponentHandler::ScheduleRegister(AliHLTComponent* pSample)
147 {
148   // see header file for class documentation
149   Int_t iResult=0;
150   if (pSample) {
151     fScheduleList.push_back(pSample);
152   } else {
153     iResult=-EINVAL;
154   }
155   return iResult;
156 }
157
158 int AliHLTComponentHandler::CreateComponent(const char* componentID, void* pEnvParam, int argc, const char** argv, AliHLTComponent*& component )
159 {
160   // see header file for class documentation
161   int iResult=0;
162   if (componentID) {
163     AliHLTComponent* pSample=FindComponent(componentID);
164     if (pSample!=NULL) {
165       component=pSample->Spawn();
166       if (component) {
167         HLTDebug("component \"%s\" created (%p)", componentID, component);
168         if ((iResult=component->Init(&fEnvironment, pEnvParam, argc, argv))!=0) {
169           HLTError("Initialization of component \"%s\" failed with error %d", componentID, iResult);
170           delete component;
171           component=NULL;
172         }
173       } else {
174         HLTError("can not spawn component \"%s\"", componentID);
175         iResult=-ENOENT;
176       }
177     } else {
178       HLTWarning("can not find component \"%s\"", componentID);
179       iResult=-ENOENT;
180     }
181   } else {
182     iResult=-EINVAL;
183   }
184   return iResult;
185 }
186
187 Int_t AliHLTComponentHandler::FindComponentIndex(const char* componentID)
188 {
189   // see header file for class documentation
190   Int_t iResult=0;
191   if (componentID) {
192     vector<AliHLTComponent*>::iterator element=fComponentList.begin();
193     while (element!=fComponentList.end() && iResult>=0) {
194       if (strcmp(componentID, (*element)->GetComponentID())==0) {
195         break;
196       }
197       element++;
198       iResult++;
199     }
200     if (element==fComponentList.end()) iResult=-ENOENT;
201   } else {
202     iResult=-EINVAL;
203   }
204   return iResult;
205 }
206
207 AliHLTComponent* AliHLTComponentHandler::FindComponent(const char* componentID)
208 {
209   // see header file for class documentation
210   AliHLTComponent* pSample=NULL;
211   Int_t index=FindComponentIndex(componentID);
212   if (index>=0) {
213     pSample=(AliHLTComponent*)fComponentList.at(index);
214   }
215   return pSample;
216 }
217
218 Int_t AliHLTComponentHandler::InsertComponent(AliHLTComponent* pSample)
219 {
220   // see header file for class documentation
221   Int_t iResult=0;
222   if (pSample!=NULL) {
223     fComponentList.push_back(pSample);
224   } else {
225     iResult=-EINVAL;
226   }
227   return iResult;
228 }
229
230 void AliHLTComponentHandler::List() 
231 {
232   // see header file for class documentation
233   vector<AliHLTComponent*>::iterator element=fComponentList.begin();
234   int index=0;
235   while (element!=fComponentList.end()) {
236     HLTInfo("%d. %s", index++, (*element++)->GetComponentID());
237   }
238 }
239
240 void AliHLTComponentHandler::SetEnvironment(AliHLTComponentEnvironment* pEnv) 
241 {
242   // see header file for class documentation
243   if (pEnv) {
244     memcpy(&fEnvironment, pEnv, sizeof(AliHLTComponentEnvironment));
245     if (fEnvironment.fLoggingFunc) {
246       // the AliHLTLogging::Init method also sets the stream output
247       // and notification handler to AliLog. This should only be done
248       // if the logging environment contains a logging function
249       // for redirection
250       AliHLTLogging::Init(fEnvironment.fLoggingFunc);
251     }
252   }
253 }
254
255 int AliHLTComponentHandler::LoadLibrary( const char* libraryPath )
256 {
257   // see header file for class documentation
258   int iResult=0;
259   if (libraryPath) {
260     AliHLTComponent::SetGlobalComponentHandler(this);
261     AliHLTLibHandle hLib;
262     const char* loadtype="";
263 #ifdef HAVE_DLFCN_H
264     // use interface to the dynamic linking loader
265     hLib.handle=dlopen(libraryPath, RTLD_NOW);
266     loadtype="dlopen";
267 #else
268     // use ROOT dynamic loader
269     // check if the library was already loaded, as Load returns
270     // 'failure' if the library was already loaded
271     AliHLTLibHandle* pLib=FindLibrary(libraryPath);
272     if (pLib) {
273         int* pRootHandle=reinterpret_cast<int*>(pLib->handle);
274         (*pRootHandle)++;
275         HLTDebug("instance %d of library %s loaded", (*pRootHandle), libraryPath);
276         hLib.handle=pRootHandle;
277     }
278     
279     if (hLib.handle==NULL && gSystem->Load(libraryPath)==0) {
280       int* pRootHandle=new int;
281       if (pRootHandle) *pRootHandle=1;
282       hLib.handle=pRootHandle;
283       //HLTDebug("library %s loaded via gSystem", libraryPath);
284     }
285     loadtype="gSystem";
286 #endif //HAVE_DLFCN_H
287     if (hLib.handle!=NULL) {
288       // create TString object to store library path and use pointer as handle 
289       hLib.name=new TString(libraryPath);
290       HLTInfo("library %s loaded (%s)", libraryPath, loadtype);
291       fLibraryList.insert(fLibraryList.begin(), hLib);
292       iResult=RegisterScheduledComponents();
293     } else {
294       HLTError("can not load library %s", libraryPath);
295 #ifdef HAVE_DLFCN_H
296       HLTError("dlopen error: %s", dlerror());
297 #endif //HAVE_DLFCN_H
298 #ifdef __APPLE__
299       iResult=-EFTYPE;
300 #else
301       iResult=-ELIBACC;
302 #endif
303     }
304     AliHLTComponent::UnsetGlobalComponentHandler();
305   } else {
306     iResult=-EINVAL;
307   }
308   return iResult;
309 }
310
311 int AliHLTComponentHandler::UnloadLibrary( const char* libraryPath )
312 {
313   // see header file for class documentation
314   int iResult=0;
315   if (libraryPath) {
316     vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
317     while (element!=fLibraryList.end()) {
318       TString* pName=reinterpret_cast<TString*>((*element).name);
319       if (pName->CompareTo(libraryPath)==0) {
320         UnloadLibrary(*element);
321         fLibraryList.erase(element);
322         break;
323       }
324       element++;
325   }
326   } else {
327     iResult=-EINVAL;
328   }
329   return iResult;
330 }
331
332 int AliHLTComponentHandler::UnloadLibrary(AliHLTComponentHandler::AliHLTLibHandle &handle)
333 {
334   // see header file for class documentation
335   int iResult=0;
336   fgAliLoggingFunc=NULL;
337   TString* pName=reinterpret_cast<TString*>(handle.name);
338 #ifdef HAVE_DLFCN_H
339   dlclose(handle.handle);
340 #else
341   int* pCount=reinterpret_cast<int*>(handle.handle);
342   if (--(*pCount)==0) {
343     if (pName) {
344       /** Matthias 26.04.2007
345        * I spent about a week to investigate a bug which seems to be in ROOT.
346        * Under certain circumstances, TSystem::Unload crashes. The crash occured
347        * for the first time, when libAliHLTUtil was loaded from AliHLTSystem right
348        * after the ComponentHandler was created. It does not occur when dlopen is
349        * used. 
350        * It has most likely to do with the garbage collection and automatic
351        * cleanup in ROOT. The crash occurs when ROOT is terminated and before
352        * an instance of AliHLTSystem was created.
353        *   root [0] AliHLTSystem gHLT
354        * It does not occur when the instance was created dynamically (but not even
355        * deleted)
356        *   root [0] AliHLTSystem* gHLT=new AliHLTSystem
357        *
358        * For that reason, the libraries are not unloaded here, even though there
359        * will be memory leaks.
360       gSystem->Unload(pName->Data());
361        */
362     }
363     else {
364       HLTError("missing library name, can not unload");
365     }
366     delete pCount;
367   }
368 #endif //HAVE_DLFCN_H
369   handle.name=NULL;
370   handle.handle=NULL;
371   if (pName) {
372     HLTDebug("unload library %s", pName->Data());
373     delete pName;
374   } else {
375     HLTWarning("missing name for unloaded library");
376   }
377   pName=NULL;
378   return iResult;
379 }
380
381 int AliHLTComponentHandler::UnloadLibraries()
382 {
383   // see header file for class documentation
384   int iResult=0;
385   vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
386   while (element!=fLibraryList.end()) {
387     UnloadLibrary(*element);
388     fLibraryList.erase(element);
389     element=fLibraryList.begin();
390   }
391   return iResult;
392 }
393
394 void* AliHLTComponentHandler::FindSymbol(const char* library, const char* symbol)
395 {
396   // see header file for class documentation
397   AliHLTLibHandle* hLib=FindLibrary(library);
398   if (hLib==NULL) return NULL;
399   void* pFunc=NULL;
400 #ifdef HAVE_DLFCN_H
401   pFunc=dlsym(hLib->handle, symbol);
402 #else
403   TString* name=reinterpret_cast<TString*>(hLib->name);
404   pFunc=gSystem->DynFindSymbol(name->Data(), symbol);
405 #endif
406   return pFunc;
407 }
408
409 AliHLTComponentHandler::AliHLTLibHandle* AliHLTComponentHandler::FindLibrary(const char* library)
410 {
411   // see header file for class documentation
412   AliHLTLibHandle* hLib=NULL;
413   vector<AliHLTLibHandle>::iterator element=fLibraryList.begin();
414   while (element!=fLibraryList.end()) {
415     TString* name=reinterpret_cast<TString*>((*element).name);
416     if (name->CompareTo(library)==0) {
417       hLib=&(*element);
418       break;
419     }
420     element++;
421   }
422   return hLib;
423 }
424
425 int AliHLTComponentHandler::AddStandardComponents()
426 {
427   // see header file for class documentation
428   int iResult=0;
429   AliHLTComponent::SetGlobalComponentHandler(this);
430 //   fStandardList.push_back(new AliHLTFilePublisher);
431 //   fStandardList.push_back(new AliHLTFileWriter);
432 //   fStandardList.push_back(new AliHLTRootFilePublisherComponent);
433 //   fStandardList.push_back(new AliHLTRootFileWriterComponent);
434   AliHLTComponent::UnsetGlobalComponentHandler();
435   iResult=RegisterScheduledComponents();
436   return iResult;
437 }
438
439 int AliHLTComponentHandler::RegisterScheduledComponents()
440 {
441   // see header file for class documentation
442   int iResult=0;
443   vector<AliHLTComponent*>::iterator element=fScheduleList.begin();
444   int iLocalResult=0;
445   while (element!=fScheduleList.end()) {
446     iLocalResult=RegisterComponent(*element);
447     if (iResult==0) iResult=iLocalResult;
448     fScheduleList.erase(element);
449     element=fScheduleList.begin();
450   }
451   return iResult;
452 }
453
454 int AliHLTComponentHandler::DeleteStandardComponents()
455 {
456   // see header file for class documentation
457   int iResult=0;
458   vector<AliHLTComponent*>::iterator element=fStandardList.begin();
459   while (element!=fStandardList.end()) {
460     DeregisterComponent((*element)->GetComponentID());
461     delete(*element);
462     fStandardList.erase(element);
463     element=fStandardList.begin();
464   }
465   return iResult;
466 }