]>
Commit | Line | Data |
---|---|---|
db352b46 | 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 |