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