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