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