]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - HLT/BASE/AliHLTHOMERLibManager.cxx
ALIROOT-5600 - skip non-participating detector modules
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTHOMERLibManager.cxx
index 966fd2018a851e1b5f9c20cb77d16471b7534315..66c14210f3c2acd2b780e4ce5572bb702ebf4b2a 100644 (file)
  * provided "as is" without express or implied warranty.                  *
  **************************************************************************/
 
-/** @file   AliHLTHOMERLibManager.cxx
-    @author Matthias Richter
-    @date   
-    @brief  dynamic HLT HOMER reader/writer generation and destruction.   */
-
-// see header file for class documentation
-// or
-// refer to README to build package
-// or
-// visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
+/// @file   AliHLTHOMERLibManager.cxx
+/// @author Matthias Richter
+/// @date   
+/// @brief  dynamic HLT HOMER reader/writer generation and destruction.
 
 #include <cerrno>
 #include <cassert>
 #include "AliHLTHOMERLibManager.h"
 #include "AliHLTHOMERReader.h"
 #include "AliHLTHOMERWriter.h"
+#include "AliHLTLogging.h"
 #include "TString.h"
 #include "TSystem.h"
 
 /** ROOT macro for the implementation of ROOT specific class methods */
 ClassImp(AliHLTHOMERLibManager)
 
+// global flag of the library status
+int AliHLTHOMERLibManager::fgLibraryStatus=0;
+// This list must be NULL terminated, since we use it as a marker to identify
+// the end of the list.
+const char* AliHLTHOMERLibManager::fgkLibraries[] = {"libAliHLTHOMER.so", "libHOMER.so", NULL};
+// The size of the list of reference counts must be one less than fgkLibraries.
+int AliHLTHOMERLibManager::fgkLibRefCount[] = {0, 0};
+
 AliHLTHOMERLibManager::AliHLTHOMERLibManager()
   :
-  fLibraryStatus(0),
   fFctCreateReaderFromTCPPort(NULL),
   fFctCreateReaderFromTCPPorts(NULL),
   fFctCreateReaderFromBuffer(NULL),
   fFctDeleteReader(NULL),
   fFctCreateWriter(NULL),
-  fFctDeleteWriter(NULL)
+  fFctDeleteWriter(NULL),
+  fLoadedLib(NULL)
 {
-  // see header file for class documentation
-  // or
-  // refer to README to build package
-  // or
-  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
+  // constructor
+  // 
+  // Interface to the HLT Online Monitoring Including Root (HOMER) library.
+  // It allows to decouple the HLT base library from this additional library
+  // while providing the basic functionality to the component libraries
 }
 
 AliHLTHOMERLibManager::~AliHLTHOMERLibManager()
 {
-  // see header file for class documentation
+  // destructor
+  //
+  // the library load strategy has been changed in March 2013 in order to
+  // stabilize the runtime memory layout of AliRoot in an attemp to get control
+  // over memory corruptions
+  //  UnloadHOMERLibrary();
 }
 
 AliHLTHOMERReader* AliHLTHOMERLibManager::OpenReader(const char* hostname, unsigned short port )
 {
-  // see header file for class documentation
-  if (fLibraryStatus<0) return NULL;
+  // Open Reader instance for host
+  if (fgLibraryStatus<0) return NULL;
 
-  if (fLibraryStatus==0) {
-    fLibraryStatus=LoadHOMERLibrary();
+  fgLibraryStatus=LoadHOMERLibrary();
+  if (fgLibraryStatus <= 0) {
+       return NULL;
   }
   
   AliHLTHOMERReader* pReader=NULL;
   if (fFctCreateReaderFromTCPPort!=NULL && (pReader=(((AliHLTHOMERReaderCreateFromTCPPort_t)fFctCreateReaderFromTCPPort)(hostname, port)))==NULL) {
-    //HLTError("can not create instance of HOMER reader (function %p)", fFctCreateReaderFromTCPPort);
+    cout <<"can not create instance of HOMER reader from ports" << endl;
   }
   
   return pReader;
@@ -79,28 +88,31 @@ AliHLTHOMERReader* AliHLTHOMERLibManager::OpenReader(const char* hostname, unsig
 
 AliHLTHOMERReader* AliHLTHOMERLibManager::OpenReader(unsigned int tcpCnt, const char** hostnames, unsigned short* ports)
 {
-  // see header file for class documentation
-  if (fLibraryStatus<0) return NULL;
+  // Open Reader instance for a list of hosts
+  if (fgLibraryStatus<0) return NULL;
 
-  if (fLibraryStatus==0) {
-    fLibraryStatus=LoadHOMERLibrary();
+  fgLibraryStatus=LoadHOMERLibrary();
+  if (fgLibraryStatus <= 0) {
+       return NULL;
   }
   
   AliHLTHOMERReader* pReader=NULL;
   if (fFctCreateReaderFromTCPPorts!=NULL && (pReader=(((AliHLTHOMERReaderCreateFromTCPPorts_t)fFctCreateReaderFromTCPPorts)(tcpCnt, hostnames, ports)))==NULL) {
     //HLTError("can not create instance of HOMER reader (function %p)", fFctCreateReaderFromTCPPorts);
+    cout << "can not create instance of HOMER reader from port"<<endl;
   }
   
   return pReader;
 }
 
-AliHLTHOMERReader* AliHLTHOMERLibManager::OpenReader(const AliHLTUInt8_t* pBuffer, int size)
+AliHLTHOMERReader* AliHLTHOMERLibManager::OpenReaderBuffer(const AliHLTUInt8_t* pBuffer, int size)
 {
-  // see header file for class documentation
-  if (fLibraryStatus<0) return NULL;
+  // Open Reader instance for a data buffer
+  if (fgLibraryStatus<0) return NULL;
 
-  if (fLibraryStatus==0) {
-    fLibraryStatus=LoadHOMERLibrary();
+  fgLibraryStatus=LoadHOMERLibrary();
+  if (fgLibraryStatus <= 0) {
+       return NULL;
   }
   
   AliHLTHOMERReader* pReader=NULL;
@@ -113,11 +125,14 @@ AliHLTHOMERReader* AliHLTHOMERLibManager::OpenReader(const AliHLTUInt8_t* pBuffe
 
 int AliHLTHOMERLibManager::DeleteReader(AliHLTHOMERReader* pReader)
 {
-  // see header file for class documentation
-  if (fLibraryStatus<0) return fLibraryStatus;
+  // delete a reader
+
+  // the actual deletion function is inside the HOMER library
+  if (fgLibraryStatus<0) return fgLibraryStatus;
 
-  if (fLibraryStatus==0) {
-    fLibraryStatus=LoadHOMERLibrary();
+  fgLibraryStatus=LoadHOMERLibrary();
+  if (fgLibraryStatus <= 0) {
+       return fgLibraryStatus;
   }
   
   if (fFctDeleteReader!=NULL) {
@@ -129,11 +144,12 @@ int AliHLTHOMERLibManager::DeleteReader(AliHLTHOMERReader* pReader)
 
 AliHLTHOMERWriter* AliHLTHOMERLibManager::OpenWriter()
 {
-  // see header file for class documentation
-  if (fLibraryStatus<0) return NULL;
+  // open a Writer instance
+  if (fgLibraryStatus<0) return NULL;
 
-  if (fLibraryStatus==0) {
-    fLibraryStatus=LoadHOMERLibrary();
+  fgLibraryStatus=LoadHOMERLibrary();
+  if (fgLibraryStatus <= 0) {
+       return NULL;
   }
   
   AliHLTHOMERWriter* pWriter=NULL;
@@ -147,10 +163,11 @@ AliHLTHOMERWriter* AliHLTHOMERLibManager::OpenWriter()
 int AliHLTHOMERLibManager::DeleteWriter(AliHLTHOMERWriter* pWriter)
 {
   // see header file for class documentation
-  if (fLibraryStatus<0) return fLibraryStatus;
+  if (fgLibraryStatus<0) return fgLibraryStatus;
 
-  if (fLibraryStatus==0) {
-    fLibraryStatus=LoadHOMERLibrary();
+  fgLibraryStatus=LoadHOMERLibrary();
+  if (fgLibraryStatus <= 0) {
+       return fgLibraryStatus;
   }
   
   if (fFctDeleteWriter!=NULL) {
@@ -162,40 +179,35 @@ int AliHLTHOMERLibManager::DeleteWriter(AliHLTHOMERWriter* pWriter)
 
 int AliHLTHOMERLibManager::LoadHOMERLibrary()
 {
-  // see header file for class documentation
+  // delete a writer
+
+  // the actual deletion function is inside the HOMER library
   int iResult=-EBADF;
-  const char* libraries[]={"libAliHLTHOMER.so", "libHOMER.so", NULL};
-  const char** library=&libraries[0];
+  const char** library=&fgkLibraries[0];
+  int* refcount = &fgkLibRefCount[0];
   do {
     TString libs = gSystem->GetLibraries();
     if (libs.Contains(*library) ||
        (gSystem->Load(*library)) >= 0) {
+      ++(*refcount);
+      fLoadedLib = *library;
       iResult=1;
       break;
     }
-  } while (*(++library)!=NULL);
+    ++library;
+    ++refcount;
+  } while ((*library)!=NULL);
 
   if (iResult>0 && *library!=NULL) {
     // print compile info
     typedef void (*CompileInfo)( char*& date, char*& time);
-    CompileInfo fctInfo=(CompileInfo)gSystem->DynFindSymbol(*library, "CompileInfo");
-    if (fctInfo) {
-      char* date="";
-      char* time="";
-      (*fctInfo)(date, time);
-      if (!date) date="unknown";
-      if (!time) time="unknown";
-      //HLTInfo("%s build on %s (%s)", *library, date, time);
-    } else {
-      //HLTInfo("no build info available for %s", *library);
-    }
 
-    fFctCreateReaderFromTCPPort=gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_CREATE_FROM_TCPPORT);
-    fFctCreateReaderFromTCPPorts=gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_CREATE_FROM_TCPPORTS);
-    fFctCreateReaderFromBuffer=gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_CREATE_FROM_BUFFER);
-    fFctDeleteReader=gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_DELETE);
-    fFctCreateWriter=gSystem->DynFindSymbol(*library, ALIHLTHOMERWRITER_CREATE);
-    fFctDeleteWriter=gSystem->DynFindSymbol(*library, ALIHLTHOMERWRITER_DELETE);
+    fFctCreateReaderFromTCPPort=(void (*)())gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_CREATE_FROM_TCPPORT);
+    fFctCreateReaderFromTCPPorts=(void (*)())gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_CREATE_FROM_TCPPORTS);
+    fFctCreateReaderFromBuffer=(void (*)())gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_CREATE_FROM_BUFFER);
+    fFctDeleteReader=(void (*)())gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_DELETE);
+    fFctCreateWriter=(void (*)())gSystem->DynFindSymbol(*library, ALIHLTHOMERWRITER_CREATE);
+    fFctDeleteWriter=(void (*)())gSystem->DynFindSymbol(*library, ALIHLTHOMERWRITER_DELETE);
     if (fFctCreateReaderFromTCPPort==NULL ||
        fFctCreateReaderFromTCPPorts==NULL ||
        fFctCreateReaderFromBuffer==NULL || 
@@ -217,3 +229,71 @@ int AliHLTHOMERLibManager::LoadHOMERLibrary()
 
   return iResult;
 }
+
+int AliHLTHOMERLibManager::UnloadHOMERLibrary()
+{
+  // unload HOMER library
+  int iResult=0;
+  
+  if (fLoadedLib != NULL)
+  {
+    // Find the corresponding reference count.
+    const char** library=&fgkLibraries[0];
+    int* refcount = &fgkLibRefCount[0];
+    while (*library != NULL)
+    {
+      if (strcmp(*library, fLoadedLib) == 0) break;
+      ++library;
+      ++refcount;
+    }
+    
+    // Decrease the reference count and remove the library if it is zero.
+    if (*refcount >= 0) --(*refcount);
+    if (*refcount == 0)
+    {
+      // Check that the library we are trying to unload is actually the last library
+      // in the gSystem->GetLibraries() list. If not then we must abort the removal.
+      // This is because of a ROOT bug/feature/limitation. If we try unload the library
+      // then ROOT will also wipe all libraries in the gSystem->GetLibraries() list
+      // following the library we want to unload.
+      TString libstring = gSystem->GetLibraries();
+      TString token, lastlib;
+      Ssiz_t from = 0;
+      Int_t numOfLibs = 0, posOfLib = -1;
+      while (libstring.Tokenize(token, from, " "))
+      {
+        ++numOfLibs;
+        lastlib = token;
+        if (token.Contains(fLoadedLib)) posOfLib = numOfLibs;
+      }
+      if (numOfLibs == posOfLib)
+      {
+        gSystem->Unload(fLoadedLib);
+
+        // Check that the library is gone, since Unload() does not return a status code.
+        libstring = gSystem->GetLibraries();
+        if (libstring.Contains(fLoadedLib)) iResult = -EBADF;
+      }
+      else
+      {
+        AliHLTLogging log;
+        log.LoggingVarargs(kHLTLogWarning, Class_Name(), FUNCTIONNAME(), __FILE__, __LINE__,
+          Form("ROOT limitation! Cannot properly cleanup and unload the shared"
+            " library '%s' since another library '%s' was loaded afterwards. Trying to"
+            " unload this library will remove the others and lead to serious memory faults.",
+            fLoadedLib, lastlib.Data()
+        ));
+      }
+    }
+  }
+
+  // Clear the function pointers.
+  fFctCreateReaderFromTCPPort = NULL;
+  fFctCreateReaderFromTCPPorts = NULL;
+  fFctCreateReaderFromBuffer = NULL;
+  fFctDeleteReader = NULL;
+  fFctCreateWriter = NULL;
+  fFctDeleteWriter = NULL;
+
+  return iResult;
+}