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