- adding helper functionality for easier streaming and extraction of TObjects via...
authorrichterm <richterm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 3 Jul 2009 05:29:16 +0000 (05:29 +0000)
committerrichterm <richterm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 3 Jul 2009 05:29:16 +0000 (05:29 +0000)
- adding helper functions for direct access of TObjects in the HLTOUT data

HLT/BASE/AliHLTMessage.cxx
HLT/BASE/AliHLTMessage.h
HLT/BASE/AliHLTOUT.cxx
HLT/BASE/AliHLTOUT.h

index 838f447..687e33f 100644 (file)
@@ -31,6 +31,7 @@
 #include "AliHLTMessage.h"
 #include "Bytes.h"
 #include "TFile.h"
+#include "TClass.h"
 
 extern "C" void R__zip (Int_t cxlevel, Int_t *nin, char *bufin, Int_t *lout, char *bufout, Int_t *nout);
 extern "C" void R__unzip(Int_t *nin, UChar_t *bufin, Int_t *lout, char *bufout, Int_t *nout);
@@ -345,3 +346,79 @@ Int_t AliHLTMessage::Uncompress()
    return 0;
 }
 
+AliHLTMessage* AliHLTMessage::Stream(TObject* pSrc, Int_t compression, unsigned verbosity)
+{
+  /// Helper function to stream an object into an AliHLTMessage
+  /// The returned instance must be cleaned by the caller
+  ///
+  /// Get the data and data size from the message:
+  ///  first check
+  ///    pMsg->CompLength();
+  ///    pMsg->CompBuffer();
+  ///  if that is NULL
+  ///    pMsg->Length();
+  ///    pMsg->Buffer();
+  ///
+  /// Note: accessing scheme will be change din the future to just have the two
+  ///       latter ones.
+  if (!pSrc) return NULL;
+
+  AliHLTLogging log;
+  AliHLTMessage* pMsg=new AliHLTMessage(kMESS_OBJECT);
+  if (!pMsg) {
+    log.LoggingVarargs(kHLTLogError, "AliHLTMessage", "Stream" , __FILE__ , __LINE__ , "memory allocation failed");
+    return NULL;
+  }
+
+  pMsg->SetCompressionLevel(compression);
+  pMsg->WriteObject(pSrc);
+  if (pMsg->Length()>0) {
+    // Matthias Sep 2008
+    // NOTE: AliHLTMessage does implement it's own SetLength method
+    // which is not architecture independent. The original SetLength
+    // stores the size always in network byte order.
+    // I'm trying to remember the rational for that, might be that
+    // it was just some lack of knowledge. Want to change this, but
+    // has to be done carefully to be backward compatible.
+    pMsg->SetLength(); // sets the length to the first (reserved) word
+
+    // does nothing if the level is 0
+    pMsg->Compress();
+
+    if (pMsg->CompBuffer()) {
+      pMsg->SetLength(); // set once more to have the byte order
+      if (verbosity>0) log.LoggingVarargs(kHLTLogInfo, "AliHLTMessage", "Stream" , __FILE__ , __LINE__ , "object %p type %s streamed: size %d", pSrc, pSrc->GetName(), pMsg->CompLength());
+    } else {
+      if (verbosity>0) log.LoggingVarargs(kHLTLogInfo, "AliHLTMessage", "Stream" , __FILE__ , __LINE__ , "object %p type %s streamed: size %d", pSrc, pSrc->GetName(), pMsg->Length());
+    }
+  }
+  return pMsg;
+}
+
+TObject* AliHLTMessage::Extract(const void* pBuffer, unsigned bufferSize, unsigned verbosity)
+{
+   /// Helper function to extract an object from a buffer.
+   /// The returned object must be cleaned by the caller
+  AliHLTLogging log;
+  if (!pBuffer || bufferSize<sizeof(AliHLTUInt32_t)) {
+    if (verbosity>0) log.LoggingVarargs(kHLTLogWarning, "AliHLTMessage", "Extract" , __FILE__ , __LINE__ , "invalid input buffer %p %d", pBuffer, bufferSize);
+    return NULL;
+  }
+
+  AliHLTUInt32_t firstWord=*((AliHLTUInt32_t*)pBuffer);
+  if (firstWord==bufferSize-sizeof(AliHLTUInt32_t) &&
+      firstWord>=34 /*thats the minimum size of a streamed TObject*/) {
+    AliHLTMessage msg((AliHLTUInt8_t*)pBuffer, bufferSize);
+    TClass* objclass=msg.GetClass();
+    TObject* pObject=msg.ReadObject(objclass);
+    if (pObject && objclass) {
+      if (verbosity>0) log.LoggingVarargs(kHLTLogInfo, "AliHLTMessage", "Extract" , __FILE__ , __LINE__ , "object %p type %s created", pObject, objclass->GetName());
+      return pObject;
+    } else {
+      if (verbosity>0) log.LoggingVarargs(kHLTLogWarning, "AliHLTMessage", "Extract" , __FILE__ , __LINE__ , "failed to create object from buffer of size %d", bufferSize);
+    }
+  } else {
+    if (verbosity>0) log.LoggingVarargs(kHLTLogWarning, "AliHLTMessage", "Extract" , __FILE__ , __LINE__ , "not a streamed TObject: block size %d, indicated %d", bufferSize, firstWord+sizeof(AliHLTUInt32_t));
+  }
+  return NULL;
+}
index cee6bcc..6561b9c 100644 (file)
@@ -127,6 +127,18 @@ public:
    char    *CompBuffer() const { return fBufComp; }
    Int_t    CompLength() const { return (Int_t)(fBufCompCur - fBufComp); }
 
+   /**
+    * Helper function to stream an object into an AliHLTMessage
+    * The returned instance must be cleaned by the caller
+    */
+   static AliHLTMessage* Stream(TObject* pSrc, Int_t compression=1, unsigned verbosity=0);
+
+   /**
+    * Helper function to extract an object from a buffer.
+    * The returned object must be cleaned by the caller
+    */
+   static TObject* Extract(const void* pBuffer, unsigned bufferSize, unsigned verbosity=0);
+
 private:
    UInt_t   fWhat;        //!Message type
    TClass  *fClass;       //!If message is kMESS_OBJECT pointer to object's class
index 1850a16..6f48671 100644 (file)
@@ -25,6 +25,7 @@
 #include <cerrno>
 #include <cassert>
 #include "AliHLTOUT.h"
+#include "AliHLTMessage.h"
 #include "TSystem.h"
 #include "TClass.h"
 #include "TROOT.h"
@@ -44,6 +45,9 @@ AliHLTOUT::AliHLTOUT()
   fDataHandlers(),
   fbVerbose(true),
   fLog()
+  , fpDataObject(NULL)
+  , fpObjectBuffer(NULL)
+  , fObjectBufferSize(0)
 {
   // see header file for class documentation
   // or
@@ -58,6 +62,11 @@ AliHLTOUT::~AliHLTOUT()
   if (CheckStatusFlag(kIsSubCollection)) {
     fLog.LoggingVarargs(kHLTLogWarning, "AliHLTOUT", "~AliHLTOUT" , __FILE__ , __LINE__ , "severe internal error: collection has not been released, potential crash due to invalid pointer");
   }
+
+  if (fpDataObject) {
+    fLog.LoggingVarargs(kHLTLogWarning, "AliHLTOUT", "GetDataObject" , __FILE__ , __LINE__ , "data object has not been released, potential memory leak");
+  }
+  fpDataObject=NULL;
 }
 AliHLTOUT* AliHLTOUT::fgGlobalInstance=NULL;
 
@@ -816,3 +825,41 @@ const AliHLTOUT::AliHLTOUTHandlerListEntry& AliHLTOUT::AliHLTOUTBlockDescriptor:
   }
   return const_cast<AliHLTOUT::AliHLTOUTHandlerListEntry&>(AliHLTOUT::AliHLTOUTHandlerListEntry::fgkVoidHandlerListEntry);
 }
+
+TObject* AliHLTOUT::GetDataObject()
+{
+  // see header file for class documentation
+  if (fpDataObject) {
+    fLog.LoggingVarargs(kHLTLogWarning, "AliHLTOUT", "GetDataObject" , __FILE__ , __LINE__ , "data object has not been released, potential memory leak");
+    ReleaseDataBuffer(fpObjectBuffer);
+  }
+  fpObjectBuffer=NULL;
+  fObjectBufferSize=0;
+  fpDataObject=NULL;
+
+  if (GetDataBuffer(fpObjectBuffer, fObjectBufferSize)>=0) {
+    fpDataObject=AliHLTMessage::Extract(fpObjectBuffer, fObjectBufferSize);
+  } else {
+    fLog.LoggingVarargs(kHLTLogError, "AliHLTOUT", "GetDataObject" , __FILE__ , __LINE__ , "can not fetch data buffer");    
+  }
+
+  return fpDataObject;
+}
+
+int AliHLTOUT::ReleaseDataObject(TObject* pObject)
+{
+  // see header file for class documentation
+  if (!pObject) return -EINVAL;
+  if (pObject!=fpDataObject) {
+    fLog.LoggingVarargs(kHLTLogError, "AliHLTOUT", "GetDataObject" , __FILE__ , __LINE__ , "attempt to release wrong data object %p, expected %p", pObject, fpDataObject);
+    return -EINVAL;
+  }
+
+  delete fpDataObject;
+  fpDataObject=NULL;
+  ReleaseDataBuffer(fpObjectBuffer);
+  fpObjectBuffer=NULL;
+  fObjectBufferSize=0;
+
+  return 0;
+}
index 0dc1011..89bd008 100644 (file)
@@ -438,6 +438,17 @@ class AliHLTOUT {
   int ReleaseDataBuffer(const AliHLTUInt8_t* pBuffer);
 
   /**
+   * Get a TObject from the data buffer
+   * @return TObject pointer if data block is a streamed object
+   */
+  TObject* GetDataObject();
+
+  /**
+   * Release data object
+   */
+  int ReleaseDataObject(TObject* pObject);
+
+  /**
    * Add the current data block to the selection.
    * Note: enables also the block selection
    */
@@ -764,6 +775,11 @@ class AliHLTOUT {
   /** logging methods */
   AliHLTLogging fLog; //! transient
 
-  ClassDef(AliHLTOUT, 4)
+  /** current buffer converted to a TObject */
+  TObject* fpDataObject; //!
+  const AliHLTUInt8_t* fpObjectBuffer; //!
+  AliHLTUInt32_t fObjectBufferSize; //!
+
+  ClassDef(AliHLTOUT, 5)
 };
 #endif