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