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