Line data Source code
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 126 : 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 4 : fFctCreateReaderFromTCPPort(NULL),
47 4 : fFctCreateReaderFromTCPPorts(NULL),
48 4 : fFctCreateReaderFromBuffer(NULL),
49 4 : fFctDeleteReader(NULL),
50 4 : fFctCreateWriter(NULL),
51 4 : fFctDeleteWriter(NULL),
52 4 : fLoadedLib(NULL)
53 16 : {
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 8 : }
60 :
61 : AliHLTHOMERLibManager::~AliHLTHOMERLibManager()
62 16 : {
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 16 : }
70 :
71 : AliHLTHOMERReader* AliHLTHOMERLibManager::OpenReader(const char* hostname, unsigned short port )
72 : {
73 : // Open Reader instance for host
74 0 : if (fgLibraryStatus<0) return NULL;
75 :
76 0 : fgLibraryStatus=LoadHOMERLibrary();
77 0 : if (fgLibraryStatus <= 0) {
78 0 : return NULL;
79 : }
80 :
81 : AliHLTHOMERReader* pReader=NULL;
82 0 : if (fFctCreateReaderFromTCPPort!=NULL && (pReader=(((AliHLTHOMERReaderCreateFromTCPPort_t)fFctCreateReaderFromTCPPort)(hostname, port)))==NULL) {
83 0 : cout <<"can not create instance of HOMER reader from ports" << endl;
84 0 : }
85 :
86 : return pReader;
87 0 : }
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 0 : if (fgLibraryStatus<0) return NULL;
93 :
94 0 : fgLibraryStatus=LoadHOMERLibrary();
95 0 : if (fgLibraryStatus <= 0) {
96 0 : return NULL;
97 : }
98 :
99 : AliHLTHOMERReader* pReader=NULL;
100 0 : if (fFctCreateReaderFromTCPPorts!=NULL && (pReader=(((AliHLTHOMERReaderCreateFromTCPPorts_t)fFctCreateReaderFromTCPPorts)(tcpCnt, hostnames, ports)))==NULL) {
101 : //HLTError("can not create instance of HOMER reader (function %p)", fFctCreateReaderFromTCPPorts);
102 0 : cout << "can not create instance of HOMER reader from port"<<endl;
103 0 : }
104 :
105 : return pReader;
106 0 : }
107 :
108 : AliHLTHOMERReader* AliHLTHOMERLibManager::OpenReaderBuffer(const AliHLTUInt8_t* pBuffer, int size)
109 : {
110 : // Open Reader instance for a data buffer
111 0 : if (fgLibraryStatus<0) return NULL;
112 :
113 0 : fgLibraryStatus=LoadHOMERLibrary();
114 0 : if (fgLibraryStatus <= 0) {
115 0 : return NULL;
116 : }
117 :
118 : AliHLTHOMERReader* pReader=NULL;
119 0 : 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 0 : }
125 :
126 : int AliHLTHOMERLibManager::DeleteReader(AliHLTHOMERReader* pReader)
127 : {
128 : // delete a reader
129 :
130 : // the actual deletion function is inside the HOMER library
131 0 : if (fgLibraryStatus<0) return fgLibraryStatus;
132 :
133 0 : fgLibraryStatus=LoadHOMERLibrary();
134 0 : if (fgLibraryStatus <= 0) {
135 0 : return fgLibraryStatus;
136 : }
137 :
138 0 : if (fFctDeleteReader!=NULL) {
139 0 : ((AliHLTHOMERReaderDelete_t)fFctDeleteReader)(pReader);
140 0 : }
141 :
142 0 : return 0;
143 0 : }
144 :
145 : AliHLTHOMERWriter* AliHLTHOMERLibManager::OpenWriter()
146 : {
147 : // open a Writer instance
148 0 : if (fgLibraryStatus<0) return NULL;
149 :
150 0 : fgLibraryStatus=LoadHOMERLibrary();
151 0 : if (fgLibraryStatus <= 0) {
152 0 : return NULL;
153 : }
154 :
155 : AliHLTHOMERWriter* pWriter=NULL;
156 0 : 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 0 : }
162 :
163 : int AliHLTHOMERLibManager::DeleteWriter(AliHLTHOMERWriter* pWriter)
164 : {
165 : // see header file for class documentation
166 0 : if (fgLibraryStatus<0) return fgLibraryStatus;
167 :
168 0 : fgLibraryStatus=LoadHOMERLibrary();
169 0 : if (fgLibraryStatus <= 0) {
170 0 : return fgLibraryStatus;
171 : }
172 :
173 0 : if (fFctDeleteWriter!=NULL) {
174 0 : ((AliHLTHOMERWriterDelete_t)fFctDeleteWriter)(pWriter);
175 0 : }
176 :
177 0 : return 0;
178 0 : }
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 0 : do {
189 0 : TString libs = gSystem->GetLibraries();
190 0 : if (libs.Contains(*library) ||
191 0 : (gSystem->Load(*library)) >= 0) {
192 0 : ++(*refcount);
193 0 : fLoadedLib = *library;
194 : iResult=1;
195 0 : break;
196 : }
197 0 : ++library;
198 0 : ++refcount;
199 0 : } while ((*library)!=NULL);
200 :
201 0 : if (iResult>0 && *library!=NULL) {
202 : // print compile info
203 : typedef void (*CompileInfo)( char*& date, char*& time);
204 :
205 0 : fFctCreateReaderFromTCPPort=(void (*)())gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_CREATE_FROM_TCPPORT);
206 0 : fFctCreateReaderFromTCPPorts=(void (*)())gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_CREATE_FROM_TCPPORTS);
207 0 : fFctCreateReaderFromBuffer=(void (*)())gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_CREATE_FROM_BUFFER);
208 0 : fFctDeleteReader=(void (*)())gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_DELETE);
209 0 : fFctCreateWriter=(void (*)())gSystem->DynFindSymbol(*library, ALIHLTHOMERWRITER_CREATE);
210 0 : fFctDeleteWriter=(void (*)())gSystem->DynFindSymbol(*library, ALIHLTHOMERWRITER_DELETE);
211 0 : if (fFctCreateReaderFromTCPPort==NULL ||
212 0 : fFctCreateReaderFromTCPPorts==NULL ||
213 0 : fFctCreateReaderFromBuffer==NULL ||
214 0 : fFctDeleteReader==NULL ||
215 0 : fFctCreateWriter==NULL ||
216 0 : fFctDeleteWriter==NULL) {
217 : iResult=-ENOSYS;
218 0 : } else {
219 : }
220 : }
221 0 : if (iResult<0 || *library==NULL) {
222 0 : fFctCreateReaderFromTCPPort=NULL;
223 0 : fFctCreateReaderFromTCPPorts=NULL;
224 0 : fFctCreateReaderFromBuffer=NULL;
225 0 : fFctDeleteReader=NULL;
226 0 : fFctCreateWriter=NULL;
227 0 : fFctDeleteWriter=NULL;
228 0 : }
229 :
230 0 : return iResult;
231 0 : }
232 :
233 : int AliHLTHOMERLibManager::UnloadHOMERLibrary()
234 : {
235 : // unload HOMER library
236 : int iResult=0;
237 :
238 0 : if (fLoadedLib != NULL)
239 : {
240 : // Find the corresponding reference count.
241 : const char** library=&fgkLibraries[0];
242 : int* refcount = &fgkLibRefCount[0];
243 0 : while (*library != NULL)
244 : {
245 0 : if (strcmp(*library, fLoadedLib) == 0) break;
246 0 : ++library;
247 0 : ++refcount;
248 : }
249 :
250 : // Decrease the reference count and remove the library if it is zero.
251 0 : if (*refcount >= 0) --(*refcount);
252 0 : 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 0 : TString libstring = gSystem->GetLibraries();
260 0 : TString token, lastlib;
261 0 : Ssiz_t from = 0;
262 : Int_t numOfLibs = 0, posOfLib = -1;
263 0 : while (libstring.Tokenize(token, from, " "))
264 : {
265 0 : ++numOfLibs;
266 0 : lastlib = token;
267 0 : if (token.Contains(fLoadedLib)) posOfLib = numOfLibs;
268 : }
269 0 : if (numOfLibs == posOfLib)
270 : {
271 0 : gSystem->Unload(fLoadedLib);
272 :
273 : // Check that the library is gone, since Unload() does not return a status code.
274 0 : libstring = gSystem->GetLibraries();
275 0 : if (libstring.Contains(fLoadedLib)) iResult = -EBADF;
276 : }
277 : else
278 : {
279 0 : AliHLTLogging log;
280 0 : log.LoggingVarargs(kHLTLogWarning, Class_Name(), FUNCTIONNAME(), __FILE__, __LINE__,
281 0 : 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 0 : fLoadedLib, lastlib.Data()
285 : ));
286 0 : }
287 0 : }
288 0 : }
289 :
290 : // Clear the function pointers.
291 0 : fFctCreateReaderFromTCPPort = NULL;
292 0 : fFctCreateReaderFromTCPPorts = NULL;
293 0 : fFctCreateReaderFromBuffer = NULL;
294 0 : fFctDeleteReader = NULL;
295 0 : fFctCreateWriter = NULL;
296 0 : fFctDeleteWriter = NULL;
297 :
298 0 : return iResult;
299 0 : }
|