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