Typo corrected.
[u/mrichter/AliRoot.git] / SHUTTLE / DCSClient / AliDCSClient.cxx
CommitLineData
73abe331 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$
eba76848 18Revision 1.6 2006/10/02 16:38:39 jgrosseo
19update (alberto):
20fixed memory leaks
21storing of objects that failed to be stored to the grid before
22interfacing of shuttle status table in daq system
23
2bb7b766 24Revision 1.5 2006/08/15 10:50:00 jgrosseo
25effc++ corrections (alberto)
26
4f0ab988 27Revision 1.4 2006/07/04 14:59:57 jgrosseo
28revision of AliDCSValue: Removed wrapper classes, reduced storage size per value by factor 2
29
45a493ce 30Revision 1.3 2006/06/12 09:11:16 jgrosseo
31coding conventions (Alberto)
32
58bc3020 33Revision 1.2 2006/03/07 07:52:34 hristov
34New version (B.Yordanov)
35
d477ad88 36Revision 1.3 2005/11/17 17:47:34 byordano
37TList changed to TObjArray
38
39Revision 1.2 2005/11/17 14:43:23 byordano
40import to local CVS
41
42Revision 1.1.1.1 2005/10/28 07:33:58 hristov
43Initial import as subdirectory in AliRoot
44
73abe331 45Revision 1.1.1.1 2005/09/12 22:11:40 byordano
46SHUTTLE package
47
48Revision 1.3 2005/08/30 10:53:23 byordano
49some more descriptions added
50
51*/
52
53//
54// This class represents the AliDCSClient.
55// The client used for data retrieval from DCS server.
56// There are two way for retrieving data from the server.
57// 1) asking for DP (DataPoint) - usually changed frequently.
58// 2) asking for Alias (Alias) - alias should be the same through whole
59// experimnet.
60//
61// There are two type of read operations:
62// Asking for single alias/dp or asking for set of aliases/dp
63//
64// In case of ServerError the coresponding error code and
65// error string (description) could be got by GetServerErrorCode() and
66// GetServerErrorString()
67//
68
69#include "AliDCSClient.h"
73abe331 70#include "AliDCSValue.h"
71#include "AliLog.h"
72
58bc3020 73#include <TSocket.h>
d477ad88 74#include <TObjArray.h>
73abe331 75#include <TMap.h>
76#include <TObjString.h>
77#include <TSystem.h>
78
79ClassImp(AliDCSClient)
80
73abe331 81const char* AliDCSClient::fgkBadStateString = "BadState";
73abe331 82const char* AliDCSClient::fgkInvalidParameterString = "InvalidParameter";
73abe331 83const char* AliDCSClient::fgkTimeoutString = "Timeout";
73abe331 84const char* AliDCSClient::fgkBadMessageString = "BadMessage";
73abe331 85const char* AliDCSClient::fgkCommErrorString = "CommunicationError";
73abe331 86const char* AliDCSClient::fgkServerErrorString = "ServerError";
87
58bc3020 88//______________________________________________________________________
73abe331 89AliDCSClient::AliDCSClient(const char* host, Int_t port, UInt_t timeout,
90 Int_t retries):
91 fSocket(NULL), fTimeout(timeout), fRetries(retries),
92 fServerErrorCode(AliDCSMessage::kNoneError), fServerError("")
93{
94 //
95 // host: DCS server host
96 // port: DCS server port
97 // timeout: in case of communication error or socket read/write this
98 // timeout will be used before the next try is made.
99 // retries: the number of retries after which the connection is
100 // is considered as invalid and error is returned.
101 //
102
103 Int_t tries = 0;
104
105 while (tries < fRetries) {
106 fSocket = new TSocket(host, port);
107 if (fSocket->IsValid()) {
108 AliDebug(1, Form("Connected to %s:%d", host, port));
109 fSocket->SetOption(kNoBlock, 1);
110 break;
111 }
4f0ab988 112
73abe331 113 AliDebug(1, Form("Connection timeout! tries <%d> ...", tries));
114
115 delete fSocket;
116 fSocket = NULL;
117
118 gSystem->Sleep(fTimeout);
119 tries ++;
120 }
121}
122
58bc3020 123//______________________________________________________________________
124AliDCSClient::AliDCSClient(const AliDCSClient& /*other*/):
4f0ab988 125 TObject(), fSocket(NULL), fTimeout(0), fRetries(0),
126 fServerErrorCode(AliDCSMessage::kNoneError), fServerError("")
127
58bc3020 128{
129// copy constructor (not implemented)
130
131}
132
133//______________________________________________________________________
134AliDCSClient &AliDCSClient::operator=(const AliDCSClient& /*other*/)
135{
136// assignment operator (not implemented)
137
138return *this;
139}
140
141//______________________________________________________________________
142AliDCSClient::~AliDCSClient()
143{
144// destructor
145
73abe331 146 if (fSocket) {
147 Close();
148 delete fSocket;
149 }
150}
151
58bc3020 152//______________________________________________________________________
153Int_t AliDCSClient::SendBuffer(const char* buffer, Int_t size)
154{
155// send buffer containing the message to the DCS server
73abe331 156
157 Int_t sentSize = 0;
158 Int_t tries = 0;
159
160 while (sentSize < size && tries < fRetries) {
161
162 Int_t sResult = fSocket->Select(TSocket::kWrite, fTimeout);
163
164 if (sResult == 0) {
165 AliDebug(1, Form("Timeout! tries <%d> ...", tries));
166 tries ++;
167 continue;
168
169 } else if (sResult < 0) {
170 AliDebug(1, Form("Communication error <%d>!",
171 fSocket->GetErrorCode()));
172 return AliDCSClient::fgkCommError;
173 }
174
175 sResult = fSocket->SendRaw(buffer + sentSize, size - sentSize,
176 kDontBlock);
177
178 if (sResult > 0) {
179 sentSize += sResult;
180 } else {
181 AliDebug(1, Form("Communication error <%d>!",
182 fSocket->GetErrorCode()));
183 return AliDCSClient::fgkCommError;
184 }
185 }
186
187 if (tries == fRetries) {
188 return AliDCSClient::fgkTimeout;
189 }
190
191 return sentSize;
192}
193
58bc3020 194//______________________________________________________________________
195Int_t AliDCSClient::ReceiveBuffer(char* buffer, Int_t size)
196{
197// Receive message from the DCS server and fill buffer
73abe331 198
199 Int_t receivedSize = 0;
200 Int_t tries = 0;
201
202 while (receivedSize < size && tries < fRetries) {
203
204 Int_t sResult = fSocket->Select(TSocket::kRead, fTimeout);
205
206 if (sResult == 0) {
207 AliDebug(1, Form("Timeout! tries <%d> ...", tries));
208 tries ++;
209 continue;
210
211 } else if (sResult < 0) {
212 AliDebug(1, Form("Communication error <%d>",
213 fSocket->GetErrorCode()));
214 return AliDCSClient::fgkCommError;
215 }
216
217 sResult = fSocket->RecvRaw(buffer + receivedSize,
218 size - receivedSize, kDontBlock);
219
220 if (sResult > 0) {
221 receivedSize += sResult;
222 } else {
223 AliDebug(1, Form("Communication error <%d>",
224 fSocket->GetErrorCode()));
225 return AliDCSClient::fgkCommError;
226 }
227 }
228
229 if (tries == fRetries) {
230 return AliDCSClient::fgkTimeout;
231 }
232
233 return receivedSize;
234}
235
58bc3020 236//______________________________________________________________________
237Int_t AliDCSClient::SendMessage(AliDCSMessage& message)
238{
239// send message to the DCS server
73abe331 240
241 message.StoreToBuffer();
242
243 AliDebug(2, "Sending message.\n");
244 message.Print();
245
246 return SendBuffer(message.GetMessage(), message.GetMessageSize());
247}
248
58bc3020 249//______________________________________________________________________
250Int_t AliDCSClient::ReceiveMessage(AliDCSMessage& message)
251{
252// receive message from the DCS server
73abe331 253
254 char header[HEADER_SIZE];
255
256 Int_t sResult;
257
258 if ((sResult = ReceiveBuffer(header, HEADER_SIZE)) < 0) {
259 AliDebug(1, Form("Can't receive message header! Reason: %s",
260 GetErrorString(sResult)));
261 return sResult;
262 }
263
264 if (!message.SetRawHeader(header)) {
265 return AliDCSClient::fgkBadMessage;
266 }
267
268 if ((sResult = ReceiveBuffer(message.GetBody(),
269 message.GetBodySize())) < 0) {
270
271 AliDebug(1, Form("Can't receive message body! Reason: %s",
272 GetErrorString(sResult)));
273 return sResult;
274 }
275
276 message.LoadFromBuffer();
277
278 AliDebug(2, "Message received.");
279 message.Print();
280
281 return HEADER_SIZE + sResult;
282}
283
58bc3020 284//______________________________________________________________________
73abe331 285Int_t AliDCSClient::GetValues(AliDCSMessage::RequestType reqType,
2bb7b766 286 const char* reqString, UInt_t startTime, UInt_t endTime, TObjArray* result)
73abe331 287{
58bc3020 288// get array of DCS values from the DCS server
289// reqString: alias name
290// startTime, endTime: start time and end time of the query
291// result: contains the array of retrieved AliDCSValue's
292
73abe331 293 if (!IsConnected()) {
294 AliError("Not connected!");
295 return AliDCSClient::fgkBadState;
296 }
297
298 Int_t sResult;
299 AliDCSMessage requestMessage;
2bb7b766 300 requestMessage.CreateRequestMessage(reqType, startTime, endTime,
73abe331 301 reqString);
302
303 if ((sResult = SendMessage(requestMessage)) < 0) {
304 AliError(Form("Can't send request message! Reason: %s",
305 GetErrorString(sResult)));
306 Close();
307 return sResult;
2bb7b766 308 }
309
73abe331 310 sResult = ReceiveValueSet(result);
2bb7b766 311
73abe331 312 Close();
313
314 return sResult;
315}
316
58bc3020 317//______________________________________________________________________
73abe331 318Int_t AliDCSClient::GetValues(AliDCSMessage::RequestType reqType,
2bb7b766 319 UInt_t startTime, UInt_t endTime, TMap& result)
73abe331 320{
58bc3020 321// get array of DCS values from the DCS server
322// startTime, endTime: start time and end time of the query
323// result: map containing the array of alias names. It will be filled with
324// the values retrieved for each alias
325
73abe331 326 if (!IsConnected()) {
327 AliError("Not connected!");
328 return AliDCSClient::fgkBadState;
2bb7b766 329 }
73abe331 330
331 AliDCSMessage multiRequestMessage;
2bb7b766 332 multiRequestMessage.CreateMultiRequestMessage(reqType,
73abe331 333 startTime, endTime);
334
d477ad88 335 TObjArray requests;
2bb7b766 336
73abe331 337 TIter iter(&result);
338 TObjString* aRequest;
2bb7b766 339
d477ad88 340 // copy request strings to temporary TObjArray because
73abe331 341 // TMap doesn't guarantee the order of elements!!!
342 while ((aRequest = (TObjString*) iter.Next())) {
d477ad88 343 requests.AddLast(aRequest);
73abe331 344 if (!multiRequestMessage.AddRequestString(aRequest->String()))
345 {
346 return AliDCSClient::fgkInvalidParameter;
347 }
348 }
349
350 Int_t sResult;
351 if ((sResult = SendMessage(multiRequestMessage)) < 0) {
352 AliError(Form("Can't send request message! Reason: %s",
353 GetErrorString(sResult)));
354 Close();
355 return sResult;
356 }
357
358 result.SetOwner(0);
359 result.Clear();
360
361 TIter reqIter(&requests);
362 while ((aRequest = (TObjString*) reqIter.Next())) {
d477ad88 363 TObjArray* resultSet = new TObjArray();
73abe331 364 resultSet->SetOwner(1);
365
2bb7b766 366 if ((sResult = ReceiveValueSet(resultSet)) < 0) {
73abe331 367 AliError(Form("Can't get values for %s!" ,
368 aRequest->String().Data()));
369
370 delete resultSet;
371 break;
372 }
373
374 result.Add(aRequest, resultSet);
375 }
376
377 if (sResult < 0) {
378 result.DeleteValues();
379 result.Clear();
380
381 requests.Delete();
382 } else {
383 result.SetOwner(1);
384 }
385
386 Close();
387
388 return sResult;
389}
390
58bc3020 391//______________________________________________________________________
2bb7b766 392Int_t AliDCSClient::ReceiveValueSet(TObjArray* result)
58bc3020 393{
394// receive set of values
73abe331 395
396 Int_t sResult;
397
398 AliDCSMessage responseMessage;
399 if ((sResult = ReceiveMessage(responseMessage)) < 0) {
400 AliError(Form("Can't receive response message! Reason: %s",
401 GetErrorString(sResult)));
402 return sResult;
403 }
404
405 UInt_t valueCount;
406
407 if (responseMessage.GetType() == AliDCSMessage::kCount) {
408 valueCount = responseMessage.GetCount();
409
410 } else if (responseMessage.GetType() == AliDCSMessage::kError) {
411 fServerErrorCode = responseMessage.GetErrorCode();
412 fServerError = responseMessage.GetErrorString();
413
414 return AliDCSClient::fgkServerError;
415
416 } else {
417 AliError("Bad message type received!");
418 return AliDCSClient::fgkBadMessage;
419 }
420
421 UInt_t receivedValues = 0;
422
45a493ce 423 AliDCSValue::Type valueType = AliDCSValue::kInvalid;
73abe331 424
425 while (receivedValues < valueCount) {
426
427 AliDCSMessage message;
428
429 if ((sResult = ReceiveMessage(message)) < 0) {
430 AliError(Form("Can't receive message! Reason: %s",
431 GetErrorString(sResult)));
432 return sResult;
433 }
434
435 if (message.GetType() == AliDCSMessage::kResultSet) {
436
45a493ce 437 if (valueType == AliDCSValue::kInvalid) {
438 valueType = message.GetValueType();
73abe331 439 } else {
45a493ce 440 if (valueType != message.GetValueType()) {
73abe331 441 AliError("Unexpected value type!");
442 return AliDCSClient::fgkBadMessage;
443 }
444 }
2bb7b766 445
73abe331 446 receivedValues += message.GetValues(result);
447
448 if (receivedValues > valueCount) {
449 AliError("Message contains more values than expected!");
450 return AliDCSClient::fgkBadMessage;
451 }
452
453 } else if (message.GetType() == AliDCSMessage::kError) {
454 fServerErrorCode =
455 responseMessage.GetErrorCode();
456 fServerError = responseMessage.GetErrorString();
457
458 return AliDCSClient::fgkServerError;
459 } else {
460 AliError("Bad message type received!");
461 return AliDCSClient::fgkBadMessage;
462 }
463 }
464
465 return receivedValues;
466}
467
58bc3020 468//______________________________________________________________________
73abe331 469Int_t AliDCSClient::GetDPValues(const char* dpName, UInt_t startTime,
2bb7b766 470 UInt_t endTime, TObjArray* result)
73abe331 471{
472 //
473 // Reads a values from the server which correspond to this
474 // DataPoint (dpName) in time interval (startTime - endTime).
475 // result: Collection of AliDCSValue which contains the read values.
476 //
477 // Returns:
478 // If >= 0 , the number of values read.
479 // if < 0, the error code which has occured during the read.
480 //
481
482 return GetValues(AliDCSMessage::kDPName,
483 dpName, startTime, endTime, result);
484}
485
58bc3020 486//______________________________________________________________________
73abe331 487Int_t AliDCSClient::GetAliasValues(const char* alias, UInt_t startTime,
2bb7b766 488 UInt_t endTime, TObjArray* result)
73abe331 489{
490 //
491 // Reads a values from the server which correspond to this
492 // alias (alias) in time interval (startTime - endTime).
493 // result: Collection of AliDCSValue which contains the read values.
494 //
495 // Returns:
496 // If >= 0 , the number of values read.
497 // if < 0, the error code which has occured during the read.
498 //
499
500 return GetValues(AliDCSMessage::kAlias,
501 alias, startTime, endTime, result);
502}
503
58bc3020 504//______________________________________________________________________
73abe331 505Int_t AliDCSClient::GetDPValues(UInt_t startTime, UInt_t endTime,
506 TMap& result)
507{
508 //
509 // For every key of 'result' (which must be TObjString)
510 // reads a valueSet. The key represents particular DataPoint to be read.
511 // For all DataPoints time interval (startTime - endTime) is used.
512 // After the read, the correspoding value for every key is a
d477ad88 513 // TObjArray - collection of AliDCSValue, or result is an empty map in
73abe331 514 // case of error.
515 //
516 // Returns:
517 // If >= 0 , the number of values read.
518 // if < 0, the error code which has occured during the read.
519 //
520
521 return GetValues(AliDCSMessage::kDPName, startTime, endTime, result);
522}
523
58bc3020 524//______________________________________________________________________
73abe331 525Int_t AliDCSClient::GetAliasValues(UInt_t startTime, UInt_t endTime,
2bb7b766 526 TMap& result)
73abe331 527{
528 //
529 // For every key of 'result' (which must be TObjString)
530 // reads a valueSet. The key represents particular Alias to be read.
531 // For all aliases time interval (startTime - endTime) is used.
532 // After the read, the correspoding value for every key is a
d477ad88 533 // TObjArray - collection of AliDCSValue, or result is an empty map in
73abe331 534 // case of error.
535 //
536 // Returns:
537 // If >= 0 , the number of values read.
538 // if < 0, the error code which has occured during the read.
539 //
540
541 return GetValues(AliDCSMessage::kAlias, startTime, endTime, result);
542}
543
58bc3020 544//______________________________________________________________________
545Bool_t AliDCSClient::IsConnected()
546{
73abe331 547 //
548 // Returns kTRUE if there is a valid connection to the server.
549 //
550
551 if (fSocket) {
552 return fSocket->IsValid();
553 }
554
555 return kFALSE;
556}
557
58bc3020 558//______________________________________________________________________
559void AliDCSClient::Close()
560{
73abe331 561 //
562 // Close the connection.
563 //
564
565 if (fSocket) {
566 fSocket->Close();
567 }
568}
569
58bc3020 570//______________________________________________________________________
571const char* AliDCSClient::GetErrorString(Int_t code)
572{
73abe331 573 //
574 // Returns a short string describing the error code.
575 // code: the error code.
576 //
577
578
579 switch (code) {
580 case AliDCSClient::fgkBadState:
581 return AliDCSClient::fgkBadStateString;
582
583 case AliDCSClient::fgkInvalidParameter:
584 return AliDCSClient::fgkInvalidParameterString;
585
586 case AliDCSClient::fgkTimeout:
587 return AliDCSClient::fgkTimeoutString;
588
589 case AliDCSClient::fgkBadMessage:
590 return AliDCSClient::fgkBadMessageString;
591
592 case AliDCSClient::fgkCommError:
593 return AliDCSClient::fgkCommErrorString;
594
595 case AliDCSClient::fgkServerError:
596 return AliDCSClient::fgkServerErrorString;
597
598 default:
599 AliErrorGeneral("AliDCSClient::GetErrorString",
600 "Unknown error code!");
601 return "UnknownCode";
602 }
603}
604