]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - HLT/BASE/AliHLTMessage.cxx
high-level component interface added
[u/mrichter/AliRoot.git] / HLT / BASE / AliHLTMessage.cxx
diff --git a/HLT/BASE/AliHLTMessage.cxx b/HLT/BASE/AliHLTMessage.cxx
new file mode 100644 (file)
index 0000000..4dccc80
--- /dev/null
@@ -0,0 +1,316 @@
+// $Id$
+
+/** @file   AliHLTMessage.cxx
+    @author Matthias Richter (customization of Root TMessage )
+    @date   
+    @brief  Serialization of Root objects in the ALICE HLT. */
+
+// This is the original Root TMessage implementation with a few minor
+// modifications, original revision:
+// root/net: v5-14-00 $: TMessage.cxx,v 1.6 2004/05/07 09:51:58 brun
+// Author: Fons Rademakers   19/12/96
+
+/*************************************************************************
+ * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * For the licensing terms see $ROOTSYS/LICENSE.                         *
+ * For the list of contributors see $ROOTSYS/README/CREDITS.             *
+ *************************************************************************/
+
+//////////////////////////////////////////////////////////////////////////
+//                                                                      //
+// TMessage                                                             //
+//                                                                      //
+// Message buffer class used for serializing objects and sending them   //
+// over a network. This class inherits from TBuffer the basic I/O       //
+// serializer.                                                          //
+//                                                                      //
+//////////////////////////////////////////////////////////////////////////
+
+#include "AliHLTMessage.h"
+#include "Bytes.h"
+#include "TFile.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);
+const Int_t kMAXBUF = 0xffffff;
+
+
+ClassImp(AliHLTMessage)
+
+//______________________________________________________________________________
+AliHLTMessage::AliHLTMessage(UInt_t what) : TBuffer(kWrite)
+{
+   // Create a AliHLTMessage object for storing objects. The "what" integer
+   // describes the type of message. Predifined ROOT system message types
+   // can be found in MessageTypes.h. Make sure your own message types are
+   // unique from the ROOT defined message types (i.e. 0 - 10000 are
+   // reserved by ROOT). In case you OR "what" with kMESS_ACK, the message
+   // will wait for an acknowledgement from the remote side. This makes
+   // the sending process synchronous. In case you OR "what" with kMESS_ZIP,
+   // the message will be compressed in TSocket using the zip algorithm
+   // (only if message is > 256 bytes).
+
+   // space at the beginning of the message reserved for the message length
+   UInt_t   reserved = 0;
+   *this << reserved;
+
+   fWhat  = what;
+   *this << what;
+
+   fClass      = 0;
+   fCompress   = 0;
+   fBufComp    = 0;
+   fBufCompCur = 0;
+   fCompPos    = 0;
+}
+
+//______________________________________________________________________________
+AliHLTMessage::AliHLTMessage(void *buf, Int_t bufsize) : TBuffer(kRead, bufsize, buf, 0)
+{
+   // Create a AliHLTMessage object for reading objects. The objects will be
+   // read from buf. Use the What() method to get the message type.
+
+   // skip space at the beginning of the message reserved for the message length
+   fBufCur += sizeof(UInt_t);
+
+   *this >> fWhat;
+
+   fCompress   = 0;
+   fBufComp    = 0;
+   fBufCompCur = 0;
+   fCompPos    = 0;
+
+   if (fWhat & kMESS_ZIP) {
+      // if buffer has kMESS_ZIP set, move it to fBufComp and uncompress
+      fBufComp    = fBuffer;
+      fBufCompCur = fBuffer + bufsize;
+      fBuffer     = 0;
+      Uncompress();
+   }
+
+   if (fWhat == kMESS_OBJECT) {
+      InitMap();
+      fClass = ReadClass();     // get first the class stored in message
+      SetBufferOffset(sizeof(UInt_t) + sizeof(fWhat));
+      ResetMap();
+   } else {
+      fClass = 0;
+   }
+}
+
+//______________________________________________________________________________
+AliHLTMessage::~AliHLTMessage()
+{
+   // Clean up compression buffer.
+   delete [] fBufComp;
+}
+
+//______________________________________________________________________________
+void AliHLTMessage::Forward()
+{
+   // Change a buffer that was received into one that can be send, i.e.
+   // forward a just received message.
+
+   if (IsReading()) {
+      SetWriteMode();
+      SetBufferOffset(fBufSize);
+
+      if (fBufComp) {
+         fCompPos = fBufCur;
+      }
+   }
+}
+
+//______________________________________________________________________________
+void AliHLTMessage::Reset()
+{
+   // Reset the message buffer so we can use (i.e. fill) it again.
+
+   SetBufferOffset(sizeof(UInt_t) + sizeof(fWhat));
+   ResetMap();
+
+   if (fBufComp) {
+      delete [] fBufComp;
+      fBufComp    = 0;
+      fBufCompCur = 0;
+      fCompPos    = 0;
+   }
+}
+
+//______________________________________________________________________________
+void AliHLTMessage::SetLength() const
+{
+   // Set the message length at the beginning of the message buffer.
+
+   if (IsWriting()) {
+      char *buf = Buffer();
+      *((UInt_t*)buf) = (UInt_t)(Length() - sizeof(UInt_t));
+
+      if (fBufComp) {
+         buf = fBufComp;
+        *((UInt_t*)buf) = (UInt_t)(Length() - sizeof(UInt_t));
+      }
+   }
+}
+
+//______________________________________________________________________________
+void AliHLTMessage::SetWhat(UInt_t what)
+{
+   // Using this method one can change the message type a-posteriory.
+   // In case you OR "what" with kMESS_ACK, the message will wait for
+   // an acknowledgement from the remote side. This makes the sending
+   // process synchronous.
+
+   fWhat = what;
+
+   char *buf = Buffer();
+   buf += sizeof(UInt_t);   // skip reserved length space
+   tobuf(buf, what);
+
+   if (fBufComp) {
+      buf = fBufComp;
+      buf += sizeof(UInt_t);   // skip reserved length space
+      tobuf(buf, what | kMESS_ZIP);
+   }
+}
+
+//______________________________________________________________________________
+void AliHLTMessage::SetCompressionLevel(Int_t level)
+{
+   // Set the message compression level. Can be between 0 and 9 with 0
+   // being no compression and 9 maximum compression. In general the default
+   // level of 1 is the best compromise between achieved compression and
+   // cpu time. Compression will only happen when the message is > 256 bytes.
+
+   if (level < 0) level = 0;
+   if (level > 9) level = 9;
+
+   if (level != fCompress && fBufComp) {
+      delete [] fBufComp;
+      fBufComp    = 0;
+      fBufCompCur = 0;
+      fCompPos    = 0;
+   }
+   fCompress = level;
+}
+
+//______________________________________________________________________________
+Int_t AliHLTMessage::Compress()
+{
+   // Compress the message. The message will only be compressed if the
+   // compression level > 0 and the if the message is > 256 bytes.
+   // Returns -1 in case of error (when compression fails or
+   // when the message increases in size in some pathological cases),
+   // otherwise returns 0.
+
+   if (fCompress == 0) {
+      // no compression specified
+      if (fBufComp) {
+         delete [] fBufComp;
+         fBufComp    = 0;
+         fBufCompCur = 0;
+         fCompPos    = 0;
+      }
+      return 0;
+   }
+
+   if (fBufComp && fCompPos == fBufCur) {
+      // the message was already compressed
+      return 0;
+   }
+
+   // remove any existing compressed buffer before compressing modified message
+   if (fBufComp) {
+      delete [] fBufComp;
+      fBufComp    = 0;
+      fBufCompCur = 0;
+      fCompPos    = 0;
+   }
+
+   if (Length() <= (Int_t)(256 + 2*sizeof(UInt_t))) {
+      // this message is too small to be compressed
+      return 0;
+   }
+
+   Int_t hdrlen   = 2*sizeof(UInt_t);
+   Int_t messlen  = Length() - hdrlen;
+   Int_t nbuffers = messlen / kMAXBUF;
+   Int_t chdrlen  = 3*sizeof(UInt_t);   // compressed buffer header length
+   Int_t buflen   = TMath::Max(512, chdrlen + messlen + 9*nbuffers);
+   fBufComp       = new char[buflen];
+   char *messbuf  = Buffer() + hdrlen;
+   char *bufcur   = fBufComp + chdrlen;
+   Int_t noutot   = 0;
+   Int_t nzip     = 0;
+   Int_t nout, bufmax;
+   for (Int_t i = 0; i <= nbuffers; i++) {
+      if (i == nbuffers)
+         bufmax = messlen - nzip;
+      else
+         bufmax = kMAXBUF;
+      R__zip(fCompress, &bufmax, messbuf, &bufmax, bufcur, &nout);
+      if (nout == 0 || nout >= messlen) {
+         //this happens when the buffer cannot be compressed
+         delete [] fBufComp;
+         fBufComp    = 0;
+         fBufCompCur = 0;
+         fCompPos    = 0;
+         return -1;
+      }
+      bufcur  += nout;
+      noutot  += nout;
+      messbuf += kMAXBUF;
+      nzip    += kMAXBUF;
+   }
+   fBufCompCur = bufcur;
+   fCompPos    = fBufCur;
+
+   bufcur = fBufComp;
+   tobuf(bufcur, (UInt_t)(CompLength() - sizeof(UInt_t)));
+   Int_t what = fWhat | kMESS_ZIP;
+   tobuf(bufcur, what);
+   tobuf(bufcur, Length());    // original uncompressed buffer length
+
+   return 0;
+}
+
+//______________________________________________________________________________
+Int_t AliHLTMessage::Uncompress()
+{
+   // Uncompress the message. The message will only be uncompressed when
+   // kMESS_ZIP is set. Returns -1 in case of error, 0 otherwise.
+
+   if (!fBufComp || !(fWhat & kMESS_ZIP))
+      return -1;
+
+   Int_t buflen;
+   Int_t hdrlen = 2*sizeof(UInt_t);
+   UChar_t *bufcur = (UChar_t*)fBufComp + hdrlen;
+   frombuf((char *&)bufcur, &buflen);
+   fBuffer  = new char[buflen];
+   fBufSize = buflen;
+   fBufCur  = fBuffer + sizeof(UInt_t) + sizeof(fWhat);
+   fBufMax  = fBuffer + fBufSize;
+   char *messbuf = fBuffer + hdrlen;
+
+   Int_t nin, nout, nbuf;
+   Int_t noutot = 0;
+   while (1) {
+      nin  = 9 + ((Int_t)bufcur[3] | ((Int_t)bufcur[4] << 8) | ((Int_t)bufcur[5] << 16));
+      nbuf = (Int_t)bufcur[6] | ((Int_t)bufcur[7] << 8) | ((Int_t)bufcur[8] << 16);
+      R__unzip(&nin, bufcur, &nbuf, messbuf, &nout);
+      if (!nout) break;
+      noutot += nout;
+      if (noutot >= buflen - hdrlen) break;
+      bufcur  += nin;
+      messbuf += nout;
+   }
+
+   fWhat &= ~kMESS_ZIP;
+   fCompress = 1;
+
+   return 0;
+}
+