c746fb32d5118045e24656513d849b58ed6254ec
[u/mrichter/AliRoot.git] / SHUTTLE / AliDCSMessage.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /*
17 $Log$
18 Revision 1.3  2005/11/17 17:47:34  byordano
19 TList changed to TObjArray
20
21 Revision 1.2  2005/11/17 14:43:23  byordano
22 import to local CVS
23
24 Revision 1.1.1.1  2005/10/28 07:33:58  hristov
25 Initial import as subdirectory in AliRoot
26
27 Revision 1.1.1.1  2005/09/12 22:11:40  byordano
28 SHUTTLE package
29
30 Revision 1.2  2005/08/30 10:53:23  byordano
31 some more descriptions added
32
33 */
34
35
36 //
37 // This class is a wrapper of AliDCSMessage.
38 // These are the messages which form AliDCSProtocol.
39 // Every message has header and body. The body size is written in the header.
40 // There are five message types:
41 //      1) Request - used by the client to form a single request to DCS server
42 //      2) Count - returned by the server to inidicate the total number of 
43 //              values which would be sent to the client.
44 //      3) ResultSet - returned by the server and contains part of values set
45 //              which forms the server resposen. 
46 //      4) Error - returned by the server in case of error
47 //      5) MultiRequest - used by the client to form multi request.
48 //              This is a request which serves many aliases/dp at the same time
49 //              For all aliases/dp the same time interval is used.      
50 // Short description of the schema:
51 //      The client sends a request (Request or MultiRequest) and the server 
52 //      returns:
53 //              1) Count - the total number of values that the client should 
54 //                      expect.
55 //              2) ResultSet* - every ResultSet message contains a part
56 //                      of valueSet (some values) which the client should expect
57 //                      The client can wait for ResultMessage until it gets
58 //                      all values (total number) which was returned by the
59 //                      Count message at the beginning of the ResutlSet sereie.
60 //      In case of error:
61 //              1) Error - contains the error code and error description
62 //
63
64 #include "AliDCSMessage.h"
65
66 #include "AliLog.h"
67
68 #include <Bytes.h>
69 #include <TObjString.h>
70
71 #include <ctype.h>
72 #include <assert.h>
73
74 ClassImp(AliDCSMessage)
75
76 AliDCSMessage::AliDCSMessage():
77         fMessage(NULL), fMessageSize(0), fType(kInvalid)
78 {
79
80 }
81
82 AliDCSMessage::AliDCSMessage(const char* message, UInt_t size):
83         fMessageSize(size), fType(kInvalid)
84 {
85         fMessage = new char[size];
86
87         memcpy(fMessage, message, size);
88 }
89
90 AliDCSMessage::~AliDCSMessage() {
91         DestroyMessage();
92         DestroyBuffer();
93 }
94
95 void AliDCSMessage::CreateRequestMessage(RequestType type, 
96         UInt_t startTime, UInt_t endTime, const char* request)
97 {
98         DestroyMessage();
99
100         fType = AliDCSMessage::kRequest;
101         fRequestType = type;
102         fStartTime = startTime;
103         fEndTime = endTime;
104         fRequestString = request;
105 }
106
107 void AliDCSMessage::CreateMultiRequestMessage(RequestType type, 
108         UInt_t startTime, UInt_t endTime)
109 {
110         DestroyMessage();
111
112         fType = AliDCSMessage::kMultiRequest;
113         fRequestType = type;
114         fStartTime = startTime;
115         fEndTime = endTime;
116 }
117         
118 void AliDCSMessage::CreateCountMessage(UInt_t count) {
119         DestroyMessage();
120
121         fType = AliDCSMessage::kCount;
122         fCount = count;
123 }
124
125 void AliDCSMessage::CreateResultSetMessage(AliSimpleValue::Type type) {
126         DestroyMessage();
127
128         fType = AliDCSMessage::kResultSet;
129         fSimpleValueType = type; 
130 }
131
132 void AliDCSMessage::CreateErrorMessage(ErrorCode errorCode, 
133         const char* errorString)
134 {
135         DestroyMessage();
136
137         fType = AliDCSMessage::kError;
138         fErrorCode = errorCode;
139         fErrorString = errorString;
140 }
141
142 /*
143 void AliDCSMessage::CreateNextMessage() {
144         DestroyMessage();
145
146         fType = AliDCSMessage::kNext;
147 } */
148
149 void AliDCSMessage::DestroyMessage() {
150         fType = kInvalid;
151         ClearValues();
152         ClearRequestStrings();
153 }
154
155 void AliDCSMessage::SetBool(char* buf, Bool_t val) {
156         tobuf(buf, val);
157 }
158
159 void AliDCSMessage::SetByte(char* buf, Char_t val) {
160         tobuf(buf, val);
161 }
162
163 void AliDCSMessage::SetUByte(char* buf, UChar_t val) {
164         tobuf(buf, val);
165 }
166
167 void AliDCSMessage::SetInt(char* buf, Int_t val) {
168         tobuf(buf, val);
169 }
170
171 void AliDCSMessage::SetUInt(char* buf, UInt_t val) {
172         tobuf(buf, val);
173 }
174
175 void AliDCSMessage::SetFloat(char* buf, Float_t val) {
176         tobuf(buf, val);
177 }
178
179 Bool_t AliDCSMessage::GetBool(const char* buf) {
180         Bool_t val;
181         char* aBuffer = (char*) buf;
182
183         frombuf(aBuffer, &val);
184
185         return val;
186 }
187
188 Char_t AliDCSMessage::GetByte(const char* buf) {
189         Char_t val;
190         char* aBuffer = (char*) buf;
191
192         frombuf(aBuffer, &val);
193
194         return val;
195 }
196
197 UChar_t AliDCSMessage::GetUByte(const char* buf) {
198         UChar_t val;
199         char* aBuffer = (char*) buf;
200
201         frombuf(aBuffer, &val);
202
203         return val;
204 }
205
206 Int_t AliDCSMessage::GetInt(const char* buf) {
207         Int_t val;
208         char* aBuffer = (char*) buf;
209
210         frombuf(aBuffer, &val);
211
212         return val;
213 }
214
215 UInt_t AliDCSMessage::GetUInt(const char* buf) {
216         UInt_t val;
217         char* aBuffer = (char*) buf;
218
219         frombuf(aBuffer, &val);
220
221         return val;
222 }
223
224 Float_t AliDCSMessage::GetFloat(const char* buf) {
225         Float_t val;
226         char* aBuffer = (char*) buf;
227
228         frombuf(aBuffer, &val);
229
230         return val;
231 }
232
233 TString AliDCSMessage::GetString(const char* buf, Int_t maxLen) {
234
235         for (Int_t k = 0; k < maxLen; k ++) {
236                 if (buf[k] == 0) {
237                         return TString(buf);
238                 }
239         }
240
241         return TString(buf, maxLen);
242 }
243
244 void AliDCSMessage::StoreHeader() {
245         
246         SetUByte(fMessage + ID_OFFSET, 'A');
247         SetUByte(fMessage + ID_OFFSET + 1, 'D');
248
249         SetUByte(fMessage + VERSION_OFFSET, 1);
250
251         SetUByte(fMessage + TYPE_OFFSET, fType);
252
253         SetUInt(fMessage + BODY_SIZE_OFFSET, fMessageSize - HEADER_SIZE);
254 }
255
256 void AliDCSMessage::StoreRequestMessage() {
257         
258         fMessageSize = REQUEST_STRING_OFFSET +
259                 fRequestString.Length() + 1;
260         
261         fMessage = new char[fMessageSize];
262
263         StoreHeader();
264
265         SetUByte(fMessage + REQUEST_TYPE_OFFSET, fRequestType);
266         SetUInt(fMessage + START_TIME_OFFSET, fStartTime);
267         SetUInt(fMessage + END_TIME_OFFSET, fEndTime);
268         strcpy(fMessage + REQUEST_STRING_OFFSET, fRequestString.Data());
269 }
270
271 void AliDCSMessage::StoreCountMessage() {
272
273         fMessageSize = COUNT_OFFSET + sizeof(UInt_t);
274
275         fMessage = new char[fMessageSize];
276
277         StoreHeader();
278
279         SetUInt(fMessage + COUNT_OFFSET, fCount);
280 }
281
282 void AliDCSMessage::StoreResultSetMessage() {
283
284         TIter iter(&fValues);
285         AliDCSValue* aValue;
286
287         UInt_t valueDataSize = 0;
288         while ((aValue = (AliDCSValue*) iter.Next())) {
289                 if (AliSimpleValue::IsDynamic(fSimpleValueType)) {
290                         valueDataSize +=  1;
291                 }       
292         
293                 valueDataSize += aValue->GetSize();
294         }
295         
296         fMessageSize = VALUES_OFFSET + valueDataSize;
297         
298         fMessage = new char[fMessageSize];
299
300         StoreHeader();
301
302         SetUByte(fMessage + SVT_OFFSET, fSimpleValueType);
303         SetUInt(fMessage + VALUE_COUNT_OFFSET, GetValueCount());
304
305         UInt_t cursor = VALUES_OFFSET;
306         
307         iter.Reset();
308
309         if (fSimpleValueType == AliSimpleValue::kBool) {
310                 while ((aValue = (AliDCSValue*) iter.Next())) {
311                         SetBool(fMessage + cursor, aValue->
312                                 GetSimpleValue().GetBool());
313                         cursor += 1;
314                         SetUInt(fMessage + cursor, aValue->GetTimeStamp());
315                         cursor += sizeof(UInt_t);
316                 }
317         } else if (fSimpleValueType == AliSimpleValue::kByte) {
318                 while ((aValue = (AliDCSValue*) iter.Next())) {
319                         SetByte(fMessage + cursor, aValue->
320                                 GetSimpleValue().GetByte());
321                         cursor += sizeof(Char_t);
322                         SetUInt(fMessage + cursor, aValue->GetTimeStamp());
323                         cursor += sizeof(UInt_t);
324                 }
325         } else if (fSimpleValueType == AliSimpleValue::kInt) {
326                 while ((aValue = (AliDCSValue*) iter.Next())) {
327                         SetInt(fMessage + cursor, aValue->
328                                 GetSimpleValue().GetInt());
329                         cursor += sizeof(Int_t);
330                         SetUInt(fMessage + cursor, aValue->GetTimeStamp());
331                         cursor += sizeof(UInt_t);
332                 }
333         } else if (fSimpleValueType == AliSimpleValue::kUInt) {
334                 while ((aValue = (AliDCSValue*) iter.Next())) {
335                         SetUInt(fMessage + cursor, aValue->
336                                 GetSimpleValue().GetUInt());
337                         cursor += sizeof(UInt_t);
338                         SetUInt(fMessage + cursor, aValue->GetTimeStamp());
339                         cursor += sizeof(UInt_t);
340                 }
341         } else if (fSimpleValueType == AliSimpleValue::kFloat) {
342                 while ((aValue = (AliDCSValue*) iter.Next())) {
343                         SetFloat(fMessage + cursor, aValue->
344                                 GetSimpleValue().GetFloat());
345                         cursor += sizeof(Float_t);
346                         SetUInt(fMessage + cursor, aValue->GetTimeStamp());
347                         cursor += sizeof(UInt_t);
348                 }
349 /*      } else if (fSimpleValueType == AliSimpleValue::kDynBool) {
350                 while ((aValue = (AliDCSValue*) iter.Next())) {
351                         Int_t dynSize = aValue->GetSimpleValue().
352                                 GetDynamicSize();
353                         SetUByte(fMessage + cursor, dynSize);
354                         cursor += 1;
355                         for (Int_t k = 0; k < dynSize; k ++) {
356                                 SetBool(fMessage + cursor, aValue->
357                                         GetSimpleValue().GetDynBool(k));
358                                 cursor += 1;
359                         }
360                         SetUInt(fMessage + cursor, aValue->GetTimeStamp());
361                         cursor += sizeof(UInt_t);
362                 }
363         } else if (fSimpleValueType == AliSimpleValue::kDynByte) {
364                 while ((aValue = (AliDCSValue*) iter.Next())) {
365                         Int_t dynSize = aValue->GetSimpleValue().
366                                 GetDynamicSize();
367                         SetUByte(fMessage + cursor, dynSize);
368                         cursor += 1;    
369                         for (Int_t k = 0; k < dynSize; k ++) {
370                                 SetByte(fMessage + cursor, aValue->
371                                         GetSimpleValue().GetDynByte(k));
372                                 cursor += sizeof(Char_t);
373                         }
374                         SetUInt(fMessage + cursor, aValue->GetTimeStamp());
375                         cursor += sizeof(UInt_t);
376                 }
377         } else if (fSimpleValueType == AliSimpleValue::kDynInt) {
378                  while ((aValue = (AliDCSValue*) iter.Next())) {
379                         Int_t dynSize = aValue->GetSimpleValue().
380                                 GetDynamicSize();
381                         SetUByte(fMessage + cursor, dynSize);
382                         cursor += 1;
383                         for (Int_t k = 0; k < dynSize; k ++) {
384                                 SetInt(fMessage + cursor, aValue->
385                                         GetSimpleValue().GetDynInt(k));
386                                 cursor += sizeof(Int_t);
387                         }
388                         SetUInt(fMessage + cursor, aValue->GetTimeStamp());
389                         cursor += sizeof(UInt_t);
390                 }
391         } else if (fSimpleValueType == AliSimpleValue::kDynUInt) {
392                 while ((aValue = (AliDCSValue*) iter.Next())) {
393                         Int_t dynSize = aValue->GetSimpleValue().
394                                 GetDynamicSize();
395                         SetUByte(fMessage + cursor, dynSize);
396                         cursor += 1;
397                         for (Int_t k = 0; k < dynSize; k ++) {
398                                 SetUInt(fMessage + cursor, aValue->
399                                         GetSimpleValue().GetDynUInt(k));
400                                 cursor += sizeof(UInt_t);
401                         }
402                         SetUInt(fMessage + cursor, aValue->GetTimeStamp());
403                         cursor += sizeof(UInt_t);
404                 }
405         } else if (fSimpleValueType == AliSimpleValue::kDynFloat) {
406                 while ((aValue = (AliDCSValue*) iter.Next())) {
407                         Int_t dynSize = aValue->GetSimpleValue().
408                                 GetDynamicSize();
409                         SetUByte(fMessage + cursor, dynSize);
410                         cursor += 1;
411                         for (Int_t k = 0; k < dynSize; k ++) {
412                                 SetFloat(fMessage + cursor, aValue->
413                                         GetSimpleValue().GetDynFloat(k));
414                                 cursor += sizeof(Float_t);
415                         }
416                         SetUInt(fMessage + cursor, aValue->GetTimeStamp());
417                         cursor += sizeof(UInt_t);
418                 } */
419         } else {
420                 AliError("Invalid or unknown SimpleValueType!");
421                 return;
422         }       
423
424 }
425
426 void AliDCSMessage::StoreErrorMessage() {
427
428         fMessageSize = ERROR_STRING_OFFSET + fErrorString.Length() + 1;
429
430         fMessage = new char[fMessageSize];
431
432         StoreHeader();
433
434         SetUByte(fMessage + ERROR_CODE_OFFSET, fErrorCode);
435         strcpy(fMessage + ERROR_STRING_OFFSET, fErrorString.Data());
436 }
437
438 void AliDCSMessage::StoreMultiRequestMessage() {
439         
440         UInt_t requestDataSize = 0;
441
442         TIter iter(&fRequestStrings);
443         TObjString* anObjString;
444
445         while ((anObjString = (TObjString*) iter.Next())) {
446                 assert(anObjString->String().Length() <= 255);
447                 requestDataSize += anObjString->String().Length() + 1;
448         }
449
450         fMessageSize = REQUEST_STRINGS_OFFSET + requestDataSize;
451
452         fMessage = new char[fMessageSize];
453         
454         StoreHeader();
455
456         SetUByte(fMessage + REQUEST_TYPE_OFFSET, fRequestType);
457         SetUInt(fMessage + START_TIME_OFFSET, fStartTime);
458         SetUInt(fMessage + END_TIME_OFFSET, fEndTime);
459         
460         iter.Reset();
461
462         UInt_t cursor = REQUEST_STRINGS_OFFSET;
463
464         while ((anObjString = (TObjString*) iter.Next())) {
465                 UChar_t strLength = anObjString->String().Length();
466                 SetUByte(fMessage + cursor, strLength);
467                 cursor += 1;
468                 strncpy(fMessage + cursor, anObjString->String().Data(), 
469                         strLength);
470                 cursor += strLength;
471         }
472 }
473
474 /*
475 void AliDCSMessage::StoreNextMessage() {
476
477         fMessageSize = HEADER_SIZE;
478
479         fMessage = new char[fMessageSize];
480
481         StoreHeader(); 
482 } */
483
484 Bool_t AliDCSMessage::ValidateHeader(const char* buf) {
485
486         if (!(buf[ID_OFFSET] == 'A' && buf[ID_OFFSET + 1] == 'D')) {
487                 AliError("Bad message ID!");
488                 return kFALSE;
489         }
490
491         if (buf[VERSION_OFFSET] != 1) {
492                 AliError("Bad message version!");
493                 return kFALSE;
494         }
495
496         Type type = (Type) GetUByte(buf + TYPE_OFFSET); 
497         switch (type) {
498                 case kRequest:
499                 case kCount:
500                 case kResultSet:
501                 case kError:
502                 case kMultiRequest:
503                         break;
504                 default:
505                         AliError("Unknown message type!");
506                         return kFALSE;
507         }
508
509         UInt_t bodySize = GetInt(buf + BODY_SIZE_OFFSET);
510         if (bodySize > MAX_BODY_SIZE) {
511                 AliError("Too big message body size!");
512                 return kFALSE;
513         } 
514
515         return kTRUE;
516 }
517
518 void AliDCSMessage::LoadRequestMessage() {
519
520         if (fMessageSize < REQUEST_STRING_OFFSET) {
521                 AliError("Body size is too small for request message!");
522                 return;
523         }
524
525         fRequestType = (RequestType) GetUByte(fMessage + REQUEST_TYPE_OFFSET);
526
527         fStartTime = GetUInt(fMessage + START_TIME_OFFSET);
528         fEndTime = GetUInt(fMessage + END_TIME_OFFSET);
529         fRequestString = GetString(fMessage + REQUEST_STRING_OFFSET,
530                 fMessageSize - REQUEST_STRING_OFFSET);
531
532         switch (fRequestType) {
533                 case kAlias:
534                 case kDPName:
535                         fType = kRequest;
536                         break;
537                 default:
538                         AliError("Invalid request type!");
539         }
540 }
541
542 void AliDCSMessage::LoadCountMessage() {
543
544         if (fMessageSize < HEADER_SIZE + sizeof(UInt_t)) {
545                 AliError("Body size is too small for count message!");
546                 return;
547         }
548
549         fCount = GetUInt(fMessage + COUNT_OFFSET);
550
551         fType = kCount;
552 }
553
554 void AliDCSMessage::LoadResultSetMessage() {
555
556         if (fMessageSize < VALUES_OFFSET) {
557                 AliError("Body size is too small for result set message!");
558                 return;
559         }       
560
561         fSimpleValueType = (AliSimpleValue::Type) GetUByte(
562                                 fMessage + SVT_OFFSET);
563         UInt_t count = GetUInt(fMessage + VALUE_COUNT_OFFSET);
564
565         UInt_t cursor = VALUES_OFFSET;
566
567         if (fSimpleValueType == AliSimpleValue::kBool) {
568                 if (VALUES_OFFSET + count + count * sizeof(UInt_t) > 
569                         fMessageSize) {
570                         AliError("Too many bool values for this buffer size!");
571                         return;
572                 }       
573         
574                 for (UInt_t k = 0; k < count; k ++) {
575                         Bool_t aBool = GetBool(fMessage + cursor);
576                         cursor += 1;
577                         UInt_t timeStamp = GetUInt(fMessage + cursor);
578                         cursor += sizeof(UInt_t);
579                         fValues.Add(new AliDCSValue(aBool, timeStamp));
580                 }
581         } else if (fSimpleValueType == AliSimpleValue::kByte) {
582                 if (VALUES_OFFSET + count + count * sizeof(UInt_t) > 
583                         fMessageSize) {
584                         AliError("Too many byte values for this buffer size!");
585                         return;
586                 }       
587         
588                 for (UInt_t k = 0; k < count; k ++) {
589                         Char_t aByte = GetByte(fMessage + cursor);
590                         cursor += sizeof(Char_t);
591                         UInt_t timeStamp = GetUInt(fMessage + cursor);
592                         cursor += sizeof(UInt_t);
593                         fValues.Add(new AliDCSValue(aByte, timeStamp));
594                 }
595         } else if (fSimpleValueType == AliSimpleValue::kInt) {
596                 if (VALUES_OFFSET + count * sizeof(Int_t) + 
597                         count * sizeof(UInt_t) > fMessageSize) {
598                         AliError("Too many int values for this buffer size!");
599                         return;
600                 }
601
602                 for (UInt_t k = 0; k < count; k ++) {
603                         Int_t aInt = GetInt(fMessage + cursor);
604                         cursor += sizeof(Int_t);
605                         UInt_t timeStamp = GetUInt(fMessage + cursor);
606                         cursor += sizeof(UInt_t);
607                         fValues.Add(new AliDCSValue(aInt, timeStamp));
608                 }
609
610         } else if (fSimpleValueType == AliSimpleValue::kUInt) {
611                 if (VALUES_OFFSET + count * sizeof(UInt_t) +  
612                         count * sizeof(UInt_t) > fMessageSize) {
613                         AliError("Too many uint values for this buffer size!");
614                         return;
615                 }
616
617                 for (UInt_t k = 0; k < count; k ++) {
618                         UInt_t aUInt = GetUInt(fMessage + cursor);
619                         cursor += sizeof(UInt_t);
620                         UInt_t timeStamp = GetUInt(fMessage + cursor);
621                         cursor += sizeof(UInt_t);
622                         fValues.Add(new AliDCSValue(aUInt, timeStamp));
623                 }
624         } else if (fSimpleValueType == AliSimpleValue::kFloat) {
625                 if (VALUES_OFFSET + count * sizeof(Float_t) +
626                         count * sizeof(UInt_t) > fMessageSize) {
627                         AliError("Too many float values for this buffer size!");
628                         return;
629                 }
630
631                 for (UInt_t k = 0; k < count; k ++) {
632                         Float_t aFloat = GetFloat(fMessage + cursor);
633                         cursor += sizeof(Float_t);
634                         UInt_t timeStamp = GetUInt(fMessage + cursor);
635                         cursor += sizeof(UInt_t);
636                         fValues.Add(new AliDCSValue(aFloat, timeStamp));
637                 }
638
639         } else {
640                 AliError("Unknown or invalid simple value type!");
641         }
642
643         fType = kResultSet;
644 }
645
646 void AliDCSMessage::LoadErrorMessage() {
647         
648         if (fMessageSize < ERROR_STRING_OFFSET) {
649                 AliError("Body size is too small for error message!");
650                 return;
651         }
652
653         fErrorCode = (ErrorCode) GetUByte(fMessage + ERROR_CODE_OFFSET);
654         fErrorString = GetString(fMessage + ERROR_STRING_OFFSET,
655                 fMessageSize - ERROR_STRING_OFFSET);
656
657         switch (fErrorCode) {
658                 case kUnknownAliasDPName:
659                 case kInvalidTimeRange:
660                 case kInvalidBufferSize:
661                 case kInvalidRequest:
662                 case kUnsupportedType:
663                 case kUnknownError:
664                         fType = kError;
665                         break;
666                 default:
667                         AliError("Invalid error code!");
668         }
669 }
670
671 void AliDCSMessage::LoadMultiRequestMessage() {
672         
673         if (fMessageSize - HEADER_SIZE < REQUEST_STRINGS_OFFSET) {
674                 AliError("Body size is too small for multi request message!");
675                 return;
676         }
677
678         fRequestType = (RequestType) GetUByte(fMessage + REQUEST_TYPE_OFFSET);
679
680         fStartTime = GetUInt(fMessage + START_TIME_OFFSET);
681         fEndTime = GetUInt(fMessage + END_TIME_OFFSET);
682
683         switch (fRequestType) { 
684                 case kAlias:
685                 case kDPName:
686                         fType = kRequest;
687                         break; 
688                 default:
689                         AliError("Invalid request type!");
690                         return;
691         }
692
693         UInt_t cursor = REQUEST_STRINGS_OFFSET;
694         
695         while ((cursor < fMessageSize)) {
696                 UChar_t strSize = GetUByte(fMessage + cursor);
697                 cursor += 1;
698
699                 if (cursor + strSize > fMessageSize) {
700                         AliError("Invalid multi request message!");
701                         return;
702                 }               
703
704                 TObjString* anObjString = new TObjString(
705                         GetString(fMessage + cursor, strSize));
706                 fRequestStrings.AddLast(anObjString);
707
708                 cursor += strSize;
709         }       
710
711         fType = kMultiRequest;
712 }
713
714 /*
715 void AliDCSMessage::LoadNextMessage() {
716         
717         fType = kNext;
718 } */
719
720 void AliDCSMessage::StoreToBuffer() {
721         //
722         // Creates an underlying message buffer which can be sent to the
723         // socket.
724         //
725
726         DestroyBuffer();
727         
728         switch (fType) {
729                 case kRequest: 
730                         StoreRequestMessage();
731                         break;
732                 case kCount:
733                         StoreCountMessage();
734                         break;
735                 case kResultSet:
736                         StoreResultSetMessage();
737                         break;
738                 case kError:
739                         StoreErrorMessage();
740                         break;
741                 case kMultiRequest:
742                         StoreMultiRequestMessage();
743                         break;
744 /*              case kNext:
745                         StoreNextMessage();
746                         break; */
747                 default:
748                         AliError("Can't store to buffer invalid message!");
749         }
750 }
751
752 void AliDCSMessage::LoadFromBuffer() {
753         //
754         // Reads the underlying message buffer and if it's valid message
755         // creates the corresponding message.  
756         // If not set the message type kInvalid.
757         // This buffer is read from the socket.
758         //
759         
760         DestroyMessage();
761
762         if (!fMessage) {
763                 AliError("Message buffer is empty! Can't load it.");
764                 return;
765         }
766         
767         if (fMessageSize < HEADER_SIZE) {
768                 AliError("Invalid message buffer. Too small for the header!");
769                 return;
770         }
771
772         if (!ValidateHeader(fMessage)) {
773                 AliError("Invalid message header!");
774                 return;
775         }
776
777         UInt_t bodySize = GetUInt(fMessage + BODY_SIZE_OFFSET);
778         if (bodySize > fMessageSize - HEADER_SIZE) {
779                 AliError("Message size is to small for the message body!");
780                 return;
781         }
782
783         fMessageSize = HEADER_SIZE + bodySize;
784
785         Type aType = (Type) GetUByte(fMessage + TYPE_OFFSET);
786         
787         switch (aType) {
788                 case kRequest:
789                         LoadRequestMessage();
790                         break;
791                 case kCount:
792                         LoadCountMessage();
793                         break;
794                 case kResultSet:
795                         LoadResultSetMessage();
796                         break;
797                 case kError:
798                         LoadErrorMessage();
799                         break;
800                 case kMultiRequest:
801                         LoadMultiRequestMessage();
802                         break;
803 /*              case kNext:
804                         LoadNextMessage();
805                         break; */
806                 default:
807                         AliError("Invalid message type!");
808         }       
809 }
810
811 AliDCSMessage::RequestType AliDCSMessage::GetRequestType() const {
812         //
813         // Request and MultiRequest.
814         // Returns the request type: alias or dp (Data Point)
815         //
816
817         if (!(fType == kRequest || fType == kMultiRequest)) {
818                 AliError("Invalid AliDCSMessage type!");
819                 return kNoneType;
820         }
821
822         return fRequestType;
823 }
824
825 UInt_t AliDCSMessage::GetStartTime() const {
826         //
827         // Request and MultiRequest.
828         // Returns the request start time. (begining of the time interval).
829         //
830
831         if (!(fType == kRequest || fType == kMultiRequest)) {
832                 AliError("Invalid AliDCSMessage type!");
833                 return 0;
834         }
835
836         return fStartTime;
837 }
838
839 UInt_t AliDCSMessage::GetEndTime() const {
840         //
841         // Request and MultiRequest.
842         // Returns the request start time. (end of the time interval).
843         //
844
845         
846         if (!(fType == kRequest || fType == kMultiRequest)) {
847                 AliError("Invalid AliDCSMessage type!");
848                 return 0;
849         }
850
851         return  fEndTime;
852 }
853
854 TString AliDCSMessage::GetRequestString() const {
855         //
856         // Request.
857         // Returns the request string. (alias or dp)
858         //
859
860         if (fType != kRequest) {
861                 AliError("Invalid AliDCSMessage type!");
862                 return TString("");
863         }
864
865         return fRequestString;
866 }
867
868 Bool_t AliDCSMessage::AddRequestString(const char* request) {
869         //
870         // MultRequest.
871         // Add a request to the request set.
872         // Returns kFALSE in case of invalid request (too long request string).
873         // Otherwise returns kTRUE.
874         //
875
876         
877         if (fType != kMultiRequest) {
878                 AliError("Invalid AliDCSMessage type!");
879                 return kFALSE;
880         }
881
882         if (strlen(request) > 255) {
883                 AliError("Alias/dpName is too long! Max size 255.");
884                 return kFALSE;  
885         }
886
887         fRequestStrings.AddLast(new TObjString(request));
888         return kTRUE;
889 }
890
891 void AliDCSMessage::ClearRequestStrings() {
892         //
893         // MultRequest.
894         // Clears the request set.
895         //
896
897         fRequestStrings.Delete();
898 }
899
900 void AliDCSMessage::GetRequestStrings(TObjArray& result) const {
901         //
902         // MultRequest.
903         // Returns all request strings in this message.
904         // result: container where the requests are returned. Collection of
905         // TObjString.
906         //
907
908
909         if (fType != kMultiRequest) {
910                 AliError("Invalid AliDCSMessage type!");
911                 return;
912         }
913
914         TIter iter(&fRequestStrings);
915         TObjString* anObjString;
916         
917         while ((anObjString = (TObjString*) iter.Next())) {
918                 result.AddLast(new TObjString(*anObjString));
919         }
920 }
921
922 UInt_t AliDCSMessage::GetCount() const {
923         //
924         // Count.
925         // Returns the total number of values.
926         //
927
928
929         if (fType != kCount) {
930                 AliError("Invalid AliDCSMessage type!");
931                 return 0;
932         }
933
934         return fCount;
935 }
936
937 AliSimpleValue::Type AliDCSMessage::GetSimpleValueType() const {
938         //
939         // ResultSet.
940         // Returns simple value type (see AliSimpleValue) for the values
941         // in this ResultSet.
942         //
943
944
945         if (fType != kResultSet) {
946                 AliError("Invalid AliDCSMessage type!");
947                 return AliSimpleValue::kInvalid;
948         }
949
950         return fSimpleValueType;
951 }
952
953 UInt_t AliDCSMessage::GetValueCount() const {
954         //
955         // ResultSet.
956         // Returns the count of values in this ResultSet.
957         //
958
959
960         if (fType != kResultSet) {
961                 AliError("Invalid AliDCSMessage type!");
962                 return 0;
963         }
964
965         return fValues.GetEntriesFast();
966 }
967
968 UInt_t AliDCSMessage::GetValues(TObjArray& result) const {
969         //
970         // ResultSet.
971         // Returns the number of values got from the message.
972         // result: used to return the values. Collection of AliDCSValue.
973         //
974
975
976         if (fType != kResultSet) {
977                 AliError("Invalid AliDCSMessage type!");
978                 return 0;
979         }
980
981         TIter iter(&fValues);
982         AliDCSValue* aValue;
983         
984         while ((aValue = (AliDCSValue*) iter.Next())) {
985                 result.AddLast(new AliDCSValue(*aValue));
986         }
987
988         return fValues.GetEntriesFast();
989 }
990
991 Bool_t AliDCSMessage::AddValue(const AliDCSValue& value) {
992         //
993         // ResultSet.
994         // Adds value to the ResultSet value list.
995         // Returns kFALSE in case of error.
996         // Otherwise returns kTRUE;
997         //
998
999         if (fType != kResultSet) {
1000                 AliError("Invalid AliDCSMessage type!");
1001                 return kFALSE;
1002         }
1003         
1004         if (value.GetSimpleValue().GetType() != fSimpleValueType) {
1005                 AliError(Form("Can't add value with type %s to this message!",
1006                         AliSimpleValue::GetTypeString(
1007                                 value.GetSimpleValue().GetType())));
1008                 return kFALSE;
1009         }
1010
1011         fValues.Add(new AliDCSValue(value));
1012
1013         return kTRUE;
1014 }
1015
1016 void AliDCSMessage::ClearValues() {
1017         fValues.Delete();
1018 }
1019
1020 AliDCSMessage::ErrorCode AliDCSMessage::GetErrorCode() const {
1021         //
1022         // Error.
1023         // Returns the error code which has this error message.
1024         //
1025
1026         if (fType != kError) {
1027                 AliError("Invalid AliDCSMessage type!");
1028                 return kNoneError;
1029         }
1030
1031         return fErrorCode;
1032 }
1033
1034 TString AliDCSMessage::GetErrorString() const {
1035         //
1036         // Error.
1037         // Returns the error string (error description) which has this 
1038         // error message.
1039         //
1040
1041         if (GetType() != kError) {
1042                 AliError("Invalid AliDCSMessage type!");
1043                 return TString("");
1044         }
1045
1046         return fErrorString;
1047 }
1048
1049
1050 void AliDCSMessage::Print(Option_t* /*option*/) const {
1051
1052         if (AliLog::GetGlobalDebugLevel() < 2) {
1053                 return;
1054         }
1055
1056         TString printString;
1057         printString += "\n <<AliDCSMessage>>\n";
1058
1059         printString += " Size: ";
1060         printString += fMessageSize;
1061         printString += '\n';
1062
1063         printString += " Type: ";
1064         switch (GetType()) {
1065                 case kRequest: {
1066                         printString += "Request\n";
1067
1068                         printString += " RequestType: ";
1069                         if (GetRequestType() == kDPName) {
1070                                 printString += "DPName";
1071                         } else {
1072                                 printString += "Alias";
1073                         }
1074                         printString += '\n';
1075
1076                         printString += " RequestString: ";
1077                         printString += GetRequestString();
1078                         printString += '\n';
1079                         printString += " StartTime: ";
1080                         printString += GetStartTime();
1081                         printString += '\n';
1082                         printString += " EndTime: ";
1083                         printString += GetEndTime();
1084                         printString += '\n';
1085                         break;
1086                 }
1087
1088                 case kCount: {
1089                         printString += "Count\n";
1090                         printString += " Count: ";
1091                         printString += GetCount();
1092                         printString += '\n';    
1093                         break;
1094                 } 
1095
1096                 case kResultSet: {
1097                         printString += "ResultSet\n";
1098                         printString += " SimpleValueType: ";
1099                         printString += AliSimpleValue::GetTypeString(
1100                                 fSimpleValueType);
1101                         printString += '\n';
1102                         printString += " ValueCount: ";
1103                         printString += GetValueCount();
1104                         printString += '\n';
1105                         break;
1106                 }
1107
1108                 case kError: {
1109                         printString += "Error\n";
1110                         printString += " ErrorCode: ";
1111                         switch (GetErrorCode()) {
1112                                 case AliDCSMessage::kNoneError:
1113                                         printString += "NoneError";
1114                                         break;
1115                                 case AliDCSMessage::kUnknownAliasDPName:
1116                                         printString += "UnknownAliasDPName";
1117                                         break;
1118                                 case AliDCSMessage::kInvalidTimeRange:
1119                                         printString += "InvalidTimeRange";
1120                                         break;
1121                                 case AliDCSMessage::kInvalidBufferSize:
1122                                         printString += "InvalidBufferSize";
1123                                         break;
1124                                 case AliDCSMessage::kInvalidRequest:
1125                                         printString += "InvalidRequest";
1126                                         break;
1127                                 case AliDCSMessage::kUnsupportedType:
1128                                         printString += "UnsupportedType";
1129                                         break;
1130                                 case AliDCSMessage::kUnknownError:
1131                                         printString += "UnknownError";
1132                                         break;
1133                                 default:
1134                                         printString += "Invalid";
1135                         }
1136
1137                         printString += '\n';
1138                         printString += " ErrorString: ";
1139                         printString += GetErrorString();
1140                         printString += '\n';
1141                         break;
1142                 }
1143
1144                 case kMultiRequest: {
1145                         printString += "MultiRequest\n";
1146
1147                         printString += " RequestType: ";
1148                         if (GetRequestType() == kDPName) {
1149                                 printString += "DPName";
1150                         } else {
1151                                 printString += "Alias";
1152                         }
1153                         printString += '\n';
1154
1155                         printString += " RequestStrings: ";
1156                         TIter iter(&fRequestStrings);
1157                         TObjString* anObjString;
1158                         while ((anObjString = (TObjString*) iter.Next())) {
1159                                 printString += anObjString->String();
1160                                 printString += ' ';
1161                         }
1162                         printString += '\n';
1163
1164                         printString += " StartTime: ";
1165                         printString += GetStartTime();
1166                         printString += '\n';
1167                         printString += " EndTime: ";
1168                         printString += GetEndTime();
1169                         printString += '\n';
1170                         break;
1171                 }       
1172
1173 /*              case kNext: {
1174                         printString += "Next\n";
1175                         break;
1176                 } */
1177
1178                 default:
1179                         printString += "Invalid\n";
1180         }
1181
1182         if (AliLog::GetGlobalDebugLevel() >= 3 && fMessage) {
1183                 PrintBuffer(fMessage, fMessageSize, printString);
1184         }
1185
1186         AliDebug(2, printString);
1187
1188
1189 Bool_t AliDCSMessage::SetRawHeader(const char* header) {
1190         //
1191         // Checks if the header buffer represents a valid header message.
1192         // If so it creates a message buffer with the appropriate body size
1193         // and returns true.
1194         // If not returns false.
1195         // header: header buffer
1196         //
1197
1198         if (!ValidateHeader(header)) {
1199                 AliError("Invalid message header!");
1200                 return kFALSE;
1201         }
1202         
1203         DestroyBuffer();
1204
1205         UInt_t bodySize = GetUInt(header + BODY_SIZE_OFFSET);
1206         fMessageSize = HEADER_SIZE + bodySize;
1207         
1208         fMessage = new char[fMessageSize];
1209         
1210         memcpy(fMessage, header, HEADER_SIZE);
1211
1212         return kTRUE;
1213 }
1214
1215
1216 void AliDCSMessage::DestroyBuffer() {
1217         //
1218         // Destroy the underlying message buffer.
1219         //
1220         
1221         if (fMessage) {
1222                 delete[] fMessage;
1223                 fMessage = NULL;
1224         }
1225
1226         fMessageSize = 0;
1227 }
1228
1229 void AliDCSMessage::PrintBuffer(const char* buffer, UInt_t size, 
1230                 TString& output)
1231 {
1232
1233         UInt_t index = 0;
1234
1235         while (index < size) {
1236                 if (!(index % 16)) {
1237                         output += Form("\n %.4x:", index); 
1238                 }       
1239
1240                 if (!(index % 8)) {
1241                         output += ' ';
1242                 }
1243
1244                 output += Form(" %.2x", (UChar_t) buffer[index]);
1245
1246                 if (!((index + 1) % 16) || index + 1 == size) {
1247                         if (index + 1 == size) {
1248                                 output.Append(' ',3 * (15 - index % 16));
1249                                 if (index % 16 < 8) {
1250                                         output.Append(' ');
1251                                 }
1252                         }
1253
1254                         output.Append(' ', 2);
1255                         for (Int_t k = index % 16; k >= 0; k --) {
1256                                 Char_t aChar = buffer[index - k];
1257                                 output += isgraph(aChar) ? aChar: '.';
1258                         }
1259                 } 
1260
1261                 index ++;
1262         }
1263
1264         output += '\n';
1265 }