3 /** @file AliHLTMessage.cxx
4 @author Matthias Richter (customization of Root TMessage )
6 @brief Serialization of Root objects in the ALICE HLT. */
8 // This is the original Root TMessage implementation with a few minor
9 // modifications, original revision:
10 // root/net: v5-14-00 $: TMessage.cxx,v 1.6 2004/05/07 09:51:58 brun
11 // Author: Fons Rademakers 19/12/96
13 /*************************************************************************
14 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
15 * All rights reserved. *
17 * For the licensing terms see $ROOTSYS/LICENSE. *
18 * For the list of contributors see $ROOTSYS/README/CREDITS. *
19 *************************************************************************/
21 //////////////////////////////////////////////////////////////////////////
25 // Message buffer class used for serializing objects and sending them //
26 // over a network. This class inherits from TBuffer the basic I/O //
29 //////////////////////////////////////////////////////////////////////////
31 #include "AliHLTMessage.h"
35 extern "C" void R__zip (Int_t cxlevel, Int_t *nin, char *bufin, Int_t *lout, char *bufout, Int_t *nout);
36 extern "C" void R__unzip(Int_t *nin, UChar_t *bufin, Int_t *lout, char *bufout, Int_t *nout);
37 const Int_t kMAXBUF = 0xffffff;
39 ClassImp(AliHLTMessage)
41 //______________________________________________________________________________
42 AliHLTMessage::AliHLTMessage(UInt_t what)
44 # ifdef ROOT_TBufferFile
57 // Create a AliHLTMessage object for storing objects. The "what" integer
58 // describes the type of message. Predifined ROOT system message types
59 // can be found in MessageTypes.h. Make sure your own message types are
60 // unique from the ROOT defined message types (i.e. 0 - 10000 are
61 // reserved by ROOT). In case you OR "what" with kMESS_ACK, the message
62 // will wait for an acknowledgement from the remote side. This makes
63 // the sending process synchronous. In case you OR "what" with kMESS_ZIP,
64 // the message will be compressed in TSocket using the zip algorithm
65 // (only if message is > 256 bytes).
67 // space at the beginning of the message reserved for the message length
75 const Int_t AliHLTMessage::fgkMinimumSize=30;
76 UInt_t AliHLTMessage::fgkDefaultBuffer[2]={0,0};
78 //______________________________________________________________________________
79 AliHLTMessage::AliHLTMessage(void *buf, Int_t bufsize)
81 # if defined(ROOT_TBufferFile)
82 TBufferFile(kRead, bufsize>fgkMinimumSize?bufsize:sizeof(fgkDefaultBuffer), bufsize>fgkMinimumSize?buf:&fgkDefaultBuffer, 0),
84 TBuffer(kRead, bufsize>fgkMinimumSize?bufsize:sizeof(fgkDefaultBuffer), bufsize>fgkMinimumSize?buf:&fgkDefaultBuffer, 0),
94 // Create a AliHLTMessage object for reading objects. The objects will be
95 // read from buf. Use the What() method to get the message type.
97 // skip space at the beginning of the message reserved for the message length
98 fBufCur += sizeof(UInt_t);
102 if (fWhat & kMESS_ZIP) {
103 // if buffer has kMESS_ZIP set, move it to fBufComp and uncompress
105 fBufCompCur = fBuffer + bufsize;
110 if (fWhat == kMESS_OBJECT) {
112 fClass = ReadClass(); // get first the class stored in message
113 SetBufferOffset(sizeof(UInt_t) + sizeof(fWhat));
120 //______________________________________________________________________________
121 AliHLTMessage::~AliHLTMessage()
123 // Clean up compression buffer.
127 //______________________________________________________________________________
128 void AliHLTMessage::Forward()
130 // Change a buffer that was received into one that can be send, i.e.
131 // forward a just received message.
135 SetBufferOffset(fBufSize);
143 //______________________________________________________________________________
144 void AliHLTMessage::Reset()
146 // Reset the message buffer so we can use (i.e. fill) it again.
148 SetBufferOffset(sizeof(UInt_t) + sizeof(fWhat));
159 //______________________________________________________________________________
160 void AliHLTMessage::SetLength() const
162 // Set the message length at the beginning of the message buffer.
165 char *buf = Buffer();
166 *((UInt_t*)buf) = (UInt_t)(Length() - sizeof(UInt_t));
170 *((UInt_t*)buf) = (UInt_t)(Length() - sizeof(UInt_t));
175 //______________________________________________________________________________
176 void AliHLTMessage::SetWhat(UInt_t what)
178 // Using this method one can change the message type a-posteriory.
179 // In case you OR "what" with kMESS_ACK, the message will wait for
180 // an acknowledgement from the remote side. This makes the sending
181 // process synchronous.
185 char *buf = Buffer();
186 buf += sizeof(UInt_t); // skip reserved length space
191 buf += sizeof(UInt_t); // skip reserved length space
192 tobuf(buf, what | kMESS_ZIP);
196 //______________________________________________________________________________
197 void AliHLTMessage::SetCompressionLevel(Int_t level)
199 // Set the message compression level. Can be between 0 and 9 with 0
200 // being no compression and 9 maximum compression. In general the default
201 // level of 1 is the best compromise between achieved compression and
202 // cpu time. Compression will only happen when the message is > 256 bytes.
204 if (level < 0) level = 0;
205 if (level > 9) level = 9;
207 if (level != fCompress && fBufComp) {
216 //______________________________________________________________________________
217 Int_t AliHLTMessage::Compress()
219 // Compress the message. The message will only be compressed if the
220 // compression level > 0 and the if the message is > 256 bytes.
221 // Returns -1 in case of error (when compression fails or
222 // when the message increases in size in some pathological cases),
223 // otherwise returns 0.
225 if (fCompress == 0) {
226 // no compression specified
236 if (fBufComp && fCompPos == fBufCur) {
237 // the message was already compressed
241 // remove any existing compressed buffer before compressing modified message
249 if (Length() <= (Int_t)(256 + 2*sizeof(UInt_t))) {
250 // this message is too small to be compressed
254 Int_t hdrlen = 2*sizeof(UInt_t);
255 Int_t messlen = Length() - hdrlen;
256 Int_t nbuffers = messlen / kMAXBUF;
257 Int_t chdrlen = 3*sizeof(UInt_t); // compressed buffer header length
258 Int_t buflen = TMath::Max(512, chdrlen + messlen + 9*nbuffers);
259 fBufComp = new char[buflen];
260 char *messbuf = Buffer() + hdrlen;
261 char *bufcur = fBufComp + chdrlen;
265 for (Int_t i = 0; i <= nbuffers; i++) {
267 bufmax = messlen - nzip;
270 R__zip(fCompress, &bufmax, messbuf, &bufmax, bufcur, &nout);
271 if (nout == 0 || nout >= messlen) {
272 //this happens when the buffer cannot be compressed
284 fBufCompCur = bufcur;
288 tobuf(bufcur, (UInt_t)(CompLength() - sizeof(UInt_t)));
289 Int_t what = fWhat | kMESS_ZIP;
291 tobuf(bufcur, Length()); // original uncompressed buffer length
296 //______________________________________________________________________________
297 Int_t AliHLTMessage::Uncompress()
299 // Uncompress the message. The message will only be uncompressed when
300 // kMESS_ZIP is set. Returns -1 in case of error, 0 otherwise.
302 if (!fBufComp || !(fWhat & kMESS_ZIP))
306 Int_t hdrlen = 2*sizeof(UInt_t);
307 UChar_t *bufcur = (UChar_t*)fBufComp + hdrlen;
308 frombuf((char *&)bufcur, &buflen);
309 fBuffer = new char[buflen];
311 fBufCur = fBuffer + sizeof(UInt_t) + sizeof(fWhat);
312 fBufMax = fBuffer + fBufSize;
313 char *messbuf = fBuffer + hdrlen;
315 Int_t nin, nout, nbuf;
318 nin = 9 + ((Int_t)bufcur[3] | ((Int_t)bufcur[4] << 8) | ((Int_t)bufcur[5] << 16));
319 nbuf = (Int_t)bufcur[6] | ((Int_t)bufcur[7] << 8) | ((Int_t)bufcur[8] << 16);
320 R__unzip(&nin, bufcur, &nbuf, messbuf, &nout);
323 if (noutot >= buflen - hdrlen) break;