1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 Revision 1.4 2007/09/14 16:46:14 jgrosseo
19 1) Connect and Close are called before and after each query, so one can
20 keep the same AliDCSClient object.
21 2) The splitting of a query is moved to GetDPValues/GetAliasValues.
22 3) Splitting interval can be specified in constructor
24 Revision 1.3 2007/09/11 16:42:02 jgrosseo
25 starting modifying AliDCSClient to transparently switch between single and multi query
26 first step: same alidcsclient can be used for several queries
28 Revision 1.2 2007/06/09 13:01:09 jgrosseo
29 Switching to retrieval of several DCS DPs at a time (multiDPrequest)
31 Revision 1.1 2006/11/06 14:22:47 jgrosseo
32 major update (Alberto)
33 o) reading of run parameters from the logbook
34 o) online offline naming conversion
35 o) standalone DCSclient package
37 Revision 1.6 2006/10/02 16:38:39 jgrosseo
40 storing of objects that failed to be stored to the grid before
41 interfacing of shuttle status table in daq system
43 Revision 1.5 2006/08/15 10:50:00 jgrosseo
44 effc++ corrections (alberto)
46 Revision 1.4 2006/07/04 14:59:57 jgrosseo
47 revision of AliDCSValue: Removed wrapper classes, reduced storage size per value by factor 2
49 Revision 1.3 2006/06/12 09:11:16 jgrosseo
50 coding conventions (Alberto)
52 Revision 1.2 2006/03/07 07:52:34 hristov
53 New version (B.Yordanov)
55 Revision 1.3 2005/11/17 17:47:34 byordano
56 TList changed to TObjArray
58 Revision 1.2 2005/11/17 14:43:23 byordano
61 Revision 1.1.1.1 2005/10/28 07:33:58 hristov
62 Initial import as subdirectory in AliRoot
64 Revision 1.1.1.1 2005/09/12 22:11:40 byordano
67 Revision 1.3 2005/08/30 10:53:23 byordano
68 some more descriptions added
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
80 // There are two type of read operations:
81 // Asking for single alias/dp or asking for set of aliases/dp
83 // In case of ServerError the coresponding error code and
84 // error string (description) could be got by GetServerErrorCode() and
85 // GetServerErrorString()
88 #include "AliDCSClient.h"
89 #include "AliDCSValue.h"
93 #include <TObjArray.h>
95 #include <TObjString.h>
98 ClassImp(AliDCSClient)
100 const char* AliDCSClient::fgkBadStateString = "BadState";
101 const char* AliDCSClient::fgkInvalidParameterString = "InvalidParameter";
102 const char* AliDCSClient::fgkTimeoutString = "Timeout";
103 const char* AliDCSClient::fgkBadMessageString = "BadMessage";
104 const char* AliDCSClient::fgkCommErrorString = "CommunicationError";
105 const char* AliDCSClient::fgkServerErrorString = "ServerError";
107 //______________________________________________________________________
108 AliDCSClient::AliDCSClient(const char* host, Int_t port, UInt_t timeout,
109 Int_t retries, Int_t multiSplit):
110 fSocket(NULL), fHost(host), fPort(port), fTimeout(timeout), fRetries(retries), fMultiSplit(multiSplit),
111 fServerErrorCode(AliDCSMessage::kNoneError), fServerError(""), fResultErrorCode(0)
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.
123 //______________________________________________________________________
124 AliDCSClient::~AliDCSClient()
131 //______________________________________________________________________
132 Bool_t AliDCSClient::Connect()
134 // connects to the AMANDA server
139 while (tries < fRetries)
141 fSocket = new TSocket(fHost, fPort);
142 if (fSocket->IsValid())
144 AliDebug(1, Form("Connected to %s:%d", fHost.Data(), fPort));
145 fSocket->SetOption(kNoBlock, 1);
149 AliDebug(1, Form("Connection timeout! tries <%d> ...", tries));
154 gSystem->Sleep(fTimeout);
161 //______________________________________________________________________
162 Int_t AliDCSClient::SendBuffer(const char* buffer, Int_t size)
164 // send buffer containing the message to the DCS server
169 while (sentSize < size && tries < fRetries) {
171 Int_t sResult = fSocket->Select(TSocket::kWrite, fTimeout);
174 AliDebug(1, Form("Timeout! tries <%d> ...", tries));
178 } else if (sResult < 0) {
179 AliDebug(1, Form("Communication error <%d>!",
180 fSocket->GetErrorCode()));
181 return AliDCSClient::fgkCommError;
184 sResult = fSocket->SendRaw(buffer + sentSize, size - sentSize,
190 AliDebug(1, Form("Communication error <%d>!",
191 fSocket->GetErrorCode()));
192 return AliDCSClient::fgkCommError;
196 if (tries == fRetries) {
197 return AliDCSClient::fgkTimeout;
203 //______________________________________________________________________
204 Int_t AliDCSClient::ReceiveBuffer(char* buffer, Int_t size)
206 // Receive message from the DCS server and fill buffer
208 Int_t receivedSize = 0;
211 while (receivedSize < size && tries < fRetries) {
213 Int_t sResult = fSocket->Select(TSocket::kRead, fTimeout);
216 AliDebug(1, Form("Timeout! tries <%d> ...", tries));
220 } else if (sResult < 0) {
221 AliDebug(1, Form("Communication error <%d>",
222 fSocket->GetErrorCode()));
223 return AliDCSClient::fgkCommError;
226 sResult = fSocket->RecvRaw(buffer + receivedSize,
227 size - receivedSize, kDontBlock);
230 receivedSize += sResult;
232 AliDebug(1, Form("Communication error <%d>",
233 fSocket->GetErrorCode()));
234 return AliDCSClient::fgkCommError;
238 if (tries == fRetries) {
239 return AliDCSClient::fgkTimeout;
245 //______________________________________________________________________
246 Int_t AliDCSClient::SendMessage(AliDCSMessage& message)
248 // send message to the DCS server
250 message.StoreToBuffer();
252 AliDebug(2, "Sending message.\n");
255 return SendBuffer(message.GetMessage(), message.GetMessageSize());
258 //______________________________________________________________________
259 Int_t AliDCSClient::ReceiveMessage(AliDCSMessage& message)
261 // receive message from the DCS server
263 char header[HEADER_SIZE];
267 if ((sResult = ReceiveBuffer(header, HEADER_SIZE)) < 0) {
268 AliDebug(1, Form("Can't receive message header! Reason: %s",
269 GetErrorString(sResult)));
273 if (!message.SetRawHeader(header)) {
274 return AliDCSClient::fgkBadMessage;
277 if ((sResult = ReceiveBuffer(message.GetBody(),
278 message.GetBodySize())) < 0) {
280 AliDebug(1, Form("Can't receive message body! Reason: %s",
281 GetErrorString(sResult)));
285 message.LoadFromBuffer();
287 AliDebug(2, "Message received.");
290 return HEADER_SIZE + sResult;
293 //______________________________________________________________________
294 Int_t AliDCSClient::GetValues(AliDCSMessage::RequestType reqType,
295 const char* reqString, UInt_t startTime, UInt_t endTime, TObjArray* result)
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
304 if (!IsConnected()) {
305 AliError("Not connected!");
306 return AliDCSClient::fgkBadState;
310 AliDCSMessage requestMessage;
311 requestMessage.CreateRequestMessage(reqType, startTime, endTime,
314 if ((sResult = SendMessage(requestMessage)) < 0) {
315 AliError(Form("Can't send request message! Reason: %s",
316 GetErrorString(sResult)));
321 sResult = ReceiveValueSet(result);
328 //______________________________________________________________________
329 TMap* AliDCSClient::GetValues(AliDCSMessage::RequestType reqType,
330 const TSeqCollection* list, UInt_t startTime, UInt_t endTime,
331 Int_t startIndex, Int_t endIndex)
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
336 // Result: map containing the array of alias names. It will be filled with
337 // the values retrieved for each alias
339 TMap* result = new TMap;
342 if (endIndex < 0 || endIndex > list->GetEntries())
343 endIndex = list->GetEntries();
345 for (Int_t subsetBegin = startIndex; subsetBegin < endIndex; subsetBegin += fMultiSplit)
351 AliError("Not connected!");
353 fResultErrorCode = fgkBadState;
357 Int_t subsetEnd = subsetBegin + fMultiSplit;
358 if (subsetEnd > endIndex)
359 subsetEnd = endIndex;
361 AliDCSMessage requestMessage;
362 if (fMultiSplit == 1)
366 TObjString* aRequest = (TObjString*) list->At(subsetBegin);
367 requestMessage.CreateRequestMessage(reqType, startTime, endTime, aRequest->String());
373 requestMessage.CreateMultiRequestMessage(reqType,
376 for (Int_t i=subsetBegin; i<subsetEnd; i++)
378 TObjString* aRequest = (TObjString*) list->At(i);
379 if (!requestMessage.AddRequestString(aRequest->String()))
382 fResultErrorCode = fgkBadMessage;
388 if ((fResultErrorCode = SendMessage(requestMessage)) < 0)
390 AliError(Form("Can't send request message! Reason: %s",
391 GetErrorString(fResultErrorCode)));
397 for (Int_t i=subsetBegin; i<subsetEnd; i++)
399 TObjString* aRequest = (TObjString*) list->At(i);
401 TObjArray* resultSet = new TObjArray();
402 resultSet->SetOwner(1);
404 if ((fResultErrorCode = ReceiveValueSet(resultSet)) < 0)
406 AliError(Form("Can't get values for %s!" ,
407 aRequest->String().Data()));
410 result->DeleteValues();
415 result->Add(aRequest, resultSet);
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()));
429 //______________________________________________________________________
430 Int_t AliDCSClient::ReceiveValueSet(TObjArray* result)
432 // receive set of values
436 AliDCSMessage responseMessage;
437 if ((sResult = ReceiveMessage(responseMessage)) < 0) {
438 AliError(Form("Can't receive response message! Reason: %s",
439 GetErrorString(sResult)));
445 if (responseMessage.GetType() == AliDCSMessage::kCount) {
446 valueCount = responseMessage.GetCount();
448 } else if (responseMessage.GetType() == AliDCSMessage::kError) {
449 fServerErrorCode = responseMessage.GetErrorCode();
450 fServerError = responseMessage.GetErrorString();
452 return AliDCSClient::fgkServerError;
455 AliError("Bad message type received!");
456 return AliDCSClient::fgkBadMessage;
459 UInt_t receivedValues = 0;
461 AliDCSValue::Type valueType = AliDCSValue::kInvalid;
463 while (receivedValues < valueCount) {
465 AliDCSMessage message;
467 if ((sResult = ReceiveMessage(message)) < 0) {
468 AliError(Form("Can't receive message! Reason: %s",
469 GetErrorString(sResult)));
473 if (message.GetType() == AliDCSMessage::kResultSet) {
475 if (valueType == AliDCSValue::kInvalid) {
476 valueType = message.GetValueType();
478 if (valueType != message.GetValueType()) {
479 AliError("Unexpected value type!");
480 return AliDCSClient::fgkBadMessage;
484 receivedValues += message.GetValues(result);
486 if (receivedValues > valueCount) {
487 AliError("Message contains more values than expected!");
488 return AliDCSClient::fgkBadMessage;
491 } else if (message.GetType() == AliDCSMessage::kError) {
493 responseMessage.GetErrorCode();
494 fServerError = responseMessage.GetErrorString();
496 return AliDCSClient::fgkServerError;
498 AliError("Bad message type received!");
499 return AliDCSClient::fgkBadMessage;
503 return receivedValues;
506 //______________________________________________________________________
507 Int_t AliDCSClient::GetDPValues(const char* dpName, UInt_t startTime,
508 UInt_t endTime, TObjArray* result)
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.
516 // If >= 0 , the number of values read.
517 // if < 0, the error code which has occured during the read.
520 return GetValues(AliDCSMessage::kDPName,
521 dpName, startTime, endTime, result);
524 //______________________________________________________________________
525 Int_t AliDCSClient::GetAliasValues(const char* alias, UInt_t startTime,
526 UInt_t endTime, TObjArray* result)
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.
534 // If >= 0 , the number of values read.
535 // if < 0, the error code which has occured during the read.
538 return GetValues(AliDCSMessage::kAlias,
539 alias, startTime, endTime, result);
542 //______________________________________________________________________
543 TMap* AliDCSClient::GetDPValues(const TSeqCollection* dpList, UInt_t startTime, UInt_t endTime,
544 Int_t startIndex, Int_t endIndex)
547 // For every entry (fron startIndex to endIndex) in dpList (which must be TObjString)
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
551 // TObjArray - collection of AliDCSValue, or result is an empty map in
555 // TMap of results, 0 in case of failure
558 return GetValues(AliDCSMessage::kDPName, dpList, startTime, endTime, startIndex, endIndex);
561 //______________________________________________________________________
562 TMap* AliDCSClient::GetAliasValues(const TSeqCollection* aliasList, UInt_t startTime, UInt_t endTime,
563 Int_t startIndex, Int_t endIndex)
566 // For every entry (fron startIndex to endIndex) in dpList (which must be TObjString)
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
570 // TObjArray - collection of AliDCSValue, or result is an empty map in
574 // TMap of results, 0 in case of failure
577 return GetValues(AliDCSMessage::kAlias, aliasList, startTime, endTime, startIndex, endIndex);
580 //______________________________________________________________________
581 Bool_t AliDCSClient::IsConnected()
584 // Returns kTRUE if there is a valid connection to the server.
588 return fSocket->IsValid();
594 //______________________________________________________________________
595 void AliDCSClient::Close()
598 // Close the connection.
608 //______________________________________________________________________
609 const char* AliDCSClient::GetErrorString(Int_t code)
612 // Returns a short string describing the error code.
613 // code: the error code.
618 case AliDCSClient::fgkBadState:
619 return AliDCSClient::fgkBadStateString;
621 case AliDCSClient::fgkInvalidParameter:
622 return AliDCSClient::fgkInvalidParameterString;
624 case AliDCSClient::fgkTimeout:
625 return AliDCSClient::fgkTimeoutString;
627 case AliDCSClient::fgkBadMessage:
628 return AliDCSClient::fgkBadMessageString;
630 case AliDCSClient::fgkCommError:
631 return AliDCSClient::fgkCommErrorString;
633 case AliDCSClient::fgkServerError:
634 return AliDCSClient::fgkServerErrorString;
637 AliErrorGeneral("AliDCSClient::GetErrorString",
638 "Unknown error code!");
639 return "UnknownCode";