b298d3948c83697c28ebde6f42edf07f4f9585c5
[u/mrichter/AliRoot.git] / MONITOR / AliNetMessage.cxx
1 #include <TVirtualStreamerInfo.h>
2 #include <Bytes.h>
3 #include <TFile.h>
4 #include <TClass.h>
5
6 #include "AliNetMessage.h"
7
8 Bool_t AliNetMessage::fgEvolution = kFALSE;
9
10 ClassImp(AliNetMessage)
11
12 //______________________________________________________________________________
13 AliNetMessage::AliNetMessage(UInt_t what) 
14   :
15   TBufferFile(kWrite),
16   fWhat(what),
17   fClass(0),
18   fBufUncompressed(0), 
19   fInfos(NULL), 
20   fEvolution(kFALSE)
21 {
22    // Create a AliNetMessage object for storing objects. The "what" integer
23    // describes the type of message. Predifined ROOT system message types
24    // can be found in MessageTypes.h. Make sure your own message types are
25    // unique from the ROOT defined message types (i.e. 0 - 10000 are
26    // reserved by ROOT). In case you OR "what" with kMESS_ACK, the message
27    // will wait for an acknowledgement from the remote side. This makes
28    // the sending process synchronous. In case you OR "what" with kMESS_ZIP,
29    // the message will be compressed in TSocket using the zip algorithm
30    // (only if message is > 256 bytes).
31
32    // space at the beginning of the message reserved for the message length
33    UInt_t   reserved = 0;
34    *this << reserved;
35
36    *this << what;
37
38    SetBit(kCannotHandleMemberWiseStreaming);
39 }
40
41
42 //______________________________________________________________________________
43 AliNetMessage::AliNetMessage(void *buf, Int_t bufsize)
44   :
45   TBufferFile(kRead, bufsize, buf),
46   fWhat(0),
47   fClass(0),
48   fBufUncompressed(0), 
49   fInfos(NULL), 
50   fEvolution(kFALSE)
51 {
52    // Create a AliNetMessage object for reading objects. The objects will be
53    // read from buf. Use the What() method to get the message type.
54
55    // skip space at the beginning of the message reserved for the message length
56    fBufCur += sizeof(UInt_t);
57
58    *this >> fWhat;
59
60    if (fWhat == kMESS_OBJECT) {
61       InitMap();
62       fClass = ReadClass();     // get first the class stored in message
63       SetBufferOffset(sizeof(UInt_t) + sizeof(fWhat));
64       ResetMap();
65    } else {
66       fClass = 0;
67    }
68 }
69
70 //______________________________________________________________________________
71 AliNetMessage::~AliNetMessage()
72 {
73    // Clean up
74   Reset();
75 }
76
77 //______________________________________________________________________________
78 void AliNetMessage::EnableSchemaEvolutionForAll(Bool_t enable)
79 {
80    // Static function enabling or disabling the automatic schema evolution.
81    // By default schema evolution support is off.
82
83    fgEvolution = enable;
84 }
85
86 //______________________________________________________________________________
87 Bool_t AliNetMessage::UsesSchemaEvolutionForAll()
88 {
89    // Static function returning status of global schema evolution.
90
91    return fgEvolution;
92 }
93
94 //______________________________________________________________________________
95 void AliNetMessage::ForceWriteInfo(TVirtualStreamerInfo *info, Bool_t /* force */)
96 {
97    // Force writing the TStreamerInfo to the message.
98
99    if (fgEvolution || fEvolution) {
100       if (!fInfos) fInfos = new TList();
101                                 fInfos->Add(info);
102    }
103 }
104
105 //______________________________________________________________________________
106 void AliNetMessage::Forward()
107 {
108    // Change a buffer that was received into one that can be send, i.e.
109    // forward a just received message.
110
111    if (IsReading()) {
112       SetWriteMode();
113       SetBufferOffset(fBufSize);
114       SetBit(kCannotHandleMemberWiseStreaming);
115    }
116 }
117
118 //______________________________________________________________________________
119 void AliNetMessage::TagStreamerInfo(TVirtualStreamerInfo *info)
120 {
121    // Remember that the StreamerInfo is being used in writing.
122
123    if (fgEvolution || fEvolution) {
124       if (!fInfos) fInfos = new TList();
125       fInfos->Add(info);
126    }
127 }
128
129 //______________________________________________________________________________
130 void AliNetMessage::IncrementLevel(TVirtualStreamerInfo *info)
131 {
132    // Increment level.
133
134    TBufferFile::IncrementLevel(info);
135
136    if (!info) return;
137    if (fgEvolution || fEvolution) {
138       if (!fInfos) fInfos = new TList();
139
140       // add the streamer info, but only once
141       // this assumes that there is only one version
142       if (fInfos->FindObject(info->GetName())==NULL) {
143                                 fInfos->Add(info);
144       }
145    }
146 }
147
148 //______________________________________________________________________________
149 void AliNetMessage::Reset()
150 {
151    // Reset the message buffer so we can use (i.e. fill) it again.
152
153    SetBufferOffset(sizeof(UInt_t) + sizeof(fWhat));
154    ResetMap();
155
156    if (fBufUncompressed) {
157      delete [] fBufUncompressed;
158      fBufUncompressed=NULL;
159    }
160 }
161
162 //______________________________________________________________________________
163 void AliNetMessage::SetLength() const
164 {
165    // Set the message length at the beginning of the message buffer.
166
167    if (IsWriting()) {
168       char *buf = Buffer();
169       *((UInt_t*)buf) = (UInt_t)(Length() - sizeof(UInt_t));
170    }
171 }
172
173 //______________________________________________________________________________
174 void AliNetMessage::SetWhat(UInt_t what)
175 {
176    // Using this method one can change the message type a-posteriory.
177    // In case you OR "what" with kMESS_ACK, the message will wait for
178    // an acknowledgement from the remote side. This makes the sending
179    // process synchronous.
180
181    fWhat = what;
182
183    char *buf = Buffer();
184    buf += sizeof(UInt_t);   // skip reserved length space
185    tobuf(buf, what);
186 }
187
188 //______________________________________________________________________________
189 void AliNetMessage::WriteObject(const TObject *obj)
190 {
191    // Write object to message buffer.
192    // When support for schema evolution is enabled the list of TStreamerInfo
193    // used to stream this object is kept in fInfos. This information is used
194    // by TSocket::Send that sends this list through the socket. This list is in
195    // turn used by TSocket::Recv to store the TStreamerInfo objects in the
196    // relevant TClass in case the TClass does not know yet about a particular
197    // class version. This feature is implemented to support clients and servers
198    // with either different ROOT versions or different user classes versions.
199
200    if (fgEvolution || fEvolution) {
201       if (fInfos)
202          fInfos->Clear();
203       else
204          fInfos = new TList();
205    }
206
207    WriteObjectAny(obj, TObject::Class());
208 }
209