]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/BASE/AliHLTHOMERLibManager.cxx
Fixing bug related to incorrect unloading of shared library and class code.
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTHOMERLibManager.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  *                  for The ALICE HLT 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   AliHLTHOMERLibManager.cxx
20     @author Matthias Richter
21     @date   
22     @brief  dynamic HLT HOMER reader/writer generation and destruction.   */
23
24 // see header file for class documentation
25 // or
26 // refer to README to build package
27 // or
28 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
29
30 #include <cerrno>
31 #include <cassert>
32 #include "AliHLTHOMERLibManager.h"
33 #include "AliHLTHOMERReader.h"
34 #include "AliHLTHOMERWriter.h"
35 #include "AliHLTLogging.h"
36 #include "TString.h"
37 #include "TSystem.h"
38
39 /** ROOT macro for the implementation of ROOT specific class methods */
40 ClassImp(AliHLTHOMERLibManager)
41
42 // This list must be NULL terminated, since we use it as a marker to identify
43 // the end of the list.
44 const char* AliHLTHOMERLibManager::fgkLibraries[] = {"libAliHLTHOMER.so", "libHOMER.so", NULL};
45 // The size of the list of reference counts must be one less than fgkLibraries.
46 int AliHLTHOMERLibManager::fgkLibRefCount[] = {0, 0};
47
48 AliHLTHOMERLibManager::AliHLTHOMERLibManager()
49   :
50   fLibraryStatus(0),
51   fFctCreateReaderFromTCPPort(NULL),
52   fFctCreateReaderFromTCPPorts(NULL),
53   fFctCreateReaderFromBuffer(NULL),
54   fFctDeleteReader(NULL),
55   fFctCreateWriter(NULL),
56   fFctDeleteWriter(NULL),
57   fLoadedLib(NULL)
58 {
59   // see header file for class documentation
60   // or
61   // refer to README to build package
62   // or
63   // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
64 }
65
66 AliHLTHOMERLibManager::~AliHLTHOMERLibManager()
67 {
68   // see header file for class documentation
69   UnloadHOMERLibrary();
70 }
71
72 AliHLTHOMERReader* AliHLTHOMERLibManager::OpenReader(const char* hostname, unsigned short port )
73 {
74   // see header file for class documentation
75   if (fLibraryStatus<0) return NULL;
76
77   if (fLibraryStatus==0) {
78     fLibraryStatus=LoadHOMERLibrary();
79   }
80   
81   AliHLTHOMERReader* pReader=NULL;
82   if (fFctCreateReaderFromTCPPort!=NULL && (pReader=(((AliHLTHOMERReaderCreateFromTCPPort_t)fFctCreateReaderFromTCPPort)(hostname, port)))==NULL) {
83     //HLTError("can not create instance of HOMER reader (function %p)", fFctCreateReaderFromTCPPort);
84   }
85   
86   return pReader;
87 }
88
89 AliHLTHOMERReader* AliHLTHOMERLibManager::OpenReader(unsigned int tcpCnt, const char** hostnames, unsigned short* ports)
90 {
91   // see header file for class documentation
92   if (fLibraryStatus<0) return NULL;
93
94   if (fLibraryStatus==0) {
95     fLibraryStatus=LoadHOMERLibrary();
96   }
97   
98   AliHLTHOMERReader* pReader=NULL;
99   if (fFctCreateReaderFromTCPPorts!=NULL && (pReader=(((AliHLTHOMERReaderCreateFromTCPPorts_t)fFctCreateReaderFromTCPPorts)(tcpCnt, hostnames, ports)))==NULL) {
100     //HLTError("can not create instance of HOMER reader (function %p)", fFctCreateReaderFromTCPPorts);
101   }
102   
103   return pReader;
104 }
105
106 AliHLTHOMERReader* AliHLTHOMERLibManager::OpenReaderBuffer(const AliHLTUInt8_t* pBuffer, int size)
107 {
108   // see header file for class documentation
109   if (fLibraryStatus<0) return NULL;
110
111   if (fLibraryStatus==0) {
112     fLibraryStatus=LoadHOMERLibrary();
113   }
114   
115   AliHLTHOMERReader* pReader=NULL;
116   if (fFctCreateReaderFromBuffer!=NULL && (pReader=(((AliHLTHOMERReaderCreateFromBuffer_t)fFctCreateReaderFromBuffer)(pBuffer, size)))==NULL) {
117     //HLTError("can not create instance of HOMER reader (function %p)", fFctCreateReaderFromBuffer);
118   }
119   
120   return pReader;
121 }
122
123 int AliHLTHOMERLibManager::DeleteReader(AliHLTHOMERReader* pReader)
124 {
125   // see header file for class documentation
126   if (fLibraryStatus<0) return fLibraryStatus;
127
128   if (fLibraryStatus==0) {
129     fLibraryStatus=LoadHOMERLibrary();
130   }
131   
132   if (fFctDeleteReader!=NULL) {
133     ((AliHLTHOMERReaderDelete_t)fFctDeleteReader)(pReader);
134   }
135   
136   return 0;
137 }
138
139 AliHLTHOMERWriter* AliHLTHOMERLibManager::OpenWriter()
140 {
141   // see header file for class documentation
142   if (fLibraryStatus<0) return NULL;
143
144   if (fLibraryStatus==0) {
145     fLibraryStatus=LoadHOMERLibrary();
146   }
147   
148   AliHLTHOMERWriter* pWriter=NULL;
149   if (fFctCreateWriter!=NULL && (pWriter=(((AliHLTHOMERWriterCreate_t)fFctCreateWriter)()))==NULL) {
150 //     HLTError("can not create instance of HOMER writer (function %p)", fFctCreateWriter);
151   }
152   
153   return pWriter;
154 }
155
156 int AliHLTHOMERLibManager::DeleteWriter(AliHLTHOMERWriter* pWriter)
157 {
158   // see header file for class documentation
159   if (fLibraryStatus<0) return fLibraryStatus;
160
161   if (fLibraryStatus==0) {
162     fLibraryStatus=LoadHOMERLibrary();
163   }
164   
165   if (fFctDeleteWriter!=NULL) {
166     ((AliHLTHOMERWriterDelete_t)fFctDeleteWriter)(pWriter);
167   }
168   
169   return 0;
170 }
171
172 int AliHLTHOMERLibManager::LoadHOMERLibrary()
173 {
174   // see header file for class documentation
175   int iResult=-EBADF;
176   const char** library=&fgkLibraries[0];
177   int* refcount = &fgkLibRefCount[0];
178   do {
179     TString libs = gSystem->GetLibraries();
180     if (libs.Contains(*library)) {
181       iResult=1;
182       break;
183     }
184     if ((gSystem->Load(*library)) >= 0) {
185       ++(*refcount);
186       fLoadedLib = *library;
187       iResult=1;
188       break;
189     }
190     ++library;
191     ++refcount;
192   } while ((*library)!=NULL);
193
194   if (iResult>0 && *library!=NULL) {
195     // print compile info
196     typedef void (*CompileInfo)( char*& date, char*& time);
197     CompileInfo fctInfo=(CompileInfo)gSystem->DynFindSymbol(*library, "CompileInfo");
198     if (fctInfo) {
199       char* date=0;
200       char* time=0;
201       (*fctInfo)(date, time);
202       if (!date) {date=new Char_t[8]; strcpy(date,"unknown");}
203       if (!time) {time=new Char_t[8]; strcpy(time,"unknown");}
204       //HLTInfo("%s build on %s (%s)", *library, date, time);
205     } else {
206       //HLTInfo("no build info available for %s", *library);
207     }
208
209     fFctCreateReaderFromTCPPort=(void (*)())gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_CREATE_FROM_TCPPORT);
210     fFctCreateReaderFromTCPPorts=(void (*)())gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_CREATE_FROM_TCPPORTS);
211     fFctCreateReaderFromBuffer=(void (*)())gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_CREATE_FROM_BUFFER);
212     fFctDeleteReader=(void (*)())gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_DELETE);
213     fFctCreateWriter=(void (*)())gSystem->DynFindSymbol(*library, ALIHLTHOMERWRITER_CREATE);
214     fFctDeleteWriter=(void (*)())gSystem->DynFindSymbol(*library, ALIHLTHOMERWRITER_DELETE);
215     if (fFctCreateReaderFromTCPPort==NULL ||
216         fFctCreateReaderFromTCPPorts==NULL ||
217         fFctCreateReaderFromBuffer==NULL || 
218         fFctDeleteReader==NULL ||
219         fFctCreateWriter==NULL ||
220         fFctDeleteWriter==NULL) {
221       iResult=-ENOSYS;
222     } else {
223     }
224   }
225   if (iResult<0 || *library==NULL) {
226     fFctCreateReaderFromTCPPort=NULL;
227     fFctCreateReaderFromTCPPorts=NULL;
228     fFctCreateReaderFromBuffer=NULL;
229     fFctDeleteReader=NULL;
230     fFctCreateWriter=NULL;
231     fFctDeleteWriter=NULL;
232   }
233
234   return iResult;
235 }
236
237 int AliHLTHOMERLibManager::UnloadHOMERLibrary()
238 {
239   // see header file for class documentation
240   int iResult=0;
241   
242   if (fLoadedLib != NULL)
243   {
244     // Find the corresponding reference count.
245     const char** library=&fgkLibraries[0];
246     int* refcount = &fgkLibRefCount[0];
247     while (*library != NULL)
248     {
249       if (strcmp(*library, fLoadedLib) == 0) break;
250       ++library;
251       ++refcount;
252     }
253     
254     // Decrease the reference count and remove the library if it is zero.
255     if (*refcount >= 0) --(*refcount);
256     if (*refcount == 0)
257     {
258       // Check that the library we are trying to unload is actually the last library
259       // in the gSystem->GetLibraries() list. If not then we must abort the removal.
260       // This is because of a ROOT bug/feature/limitation. If we try unload the library
261       // then ROOT will also wipe all libraries in the gSystem->GetLibraries() list
262       // following the library we want to unload.
263       TString libstring = gSystem->GetLibraries();
264       TString token, lastlib;
265       Ssiz_t from = 0;
266       Int_t numOfLibs = 0, posOfLib = -1;
267       while (libstring.Tokenize(token, from, " "))
268       {
269         ++numOfLibs;
270         lastlib = token;
271         if (token.Contains(fLoadedLib)) posOfLib = numOfLibs;
272       }
273       if (numOfLibs == posOfLib)
274       {
275         gSystem->Unload(fLoadedLib);
276
277         // Check that the library is gone, since Unload() does not return a status code.
278         libstring = gSystem->GetLibraries();
279         if (libstring.Contains(fLoadedLib)) iResult = -EBADF;
280       }
281       else
282       {
283         AliHLTLogging log;
284         log.LoggingVarargs(kHLTLogWarning, Class_Name(), FUNCTIONNAME(), __FILE__, __LINE__,
285           Form("ROOT limitation! Cannot properly cleanup and unload the shared"
286             " library '%s' since another library '%s' was loaded afterwards. Trying to"
287             " unload this library will remove the others and lead to serious memory faults.",
288             fLoadedLib, lastlib.Data()
289         ));
290       }
291     }
292   }
293
294   // Clear the function pointers.
295   fFctCreateReaderFromTCPPort = NULL;
296   fFctCreateReaderFromTCPPorts = NULL;
297   fFctCreateReaderFromBuffer = NULL;
298   fFctDeleteReader = NULL;
299   fFctCreateWriter = NULL;
300   fFctDeleteWriter = NULL;
301
302   return iResult;
303 }