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