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