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.8 2007/10/17 17:43:02 acolla
19 nextMessage removed from client
21 Revision 1.7 2007/10/16 15:02:20 jgrosseo
22 fixed bug if zero values collected
24 Revision 1.6 2007/10/16 14:37:16 jgrosseo
25 changing to AMANDA protocol version 2
27 Revision 1.5 2007/10/05 12:40:55 acolla
29 Result error code added to AliDCSClient data members (it was "lost" with the new implementation of TMap* GetAliasValues and GetDPValues).
31 Revision 1.4 2007/09/14 16:46:14 jgrosseo
32 1) Connect and Close are called before and after each query, so one can
33 keep the same AliDCSClient object.
34 2) The splitting of a query is moved to GetDPValues/GetAliasValues.
35 3) Splitting interval can be specified in constructor
37 Revision 1.3 2007/09/11 16:42:02 jgrosseo
38 starting modifying AliDCSClient to transparently switch between single and multi query
39 first step: same alidcsclient can be used for several queries
41 Revision 1.2 2007/06/09 13:01:09 jgrosseo
42 Switching to retrieval of several DCS DPs at a time (multiDPrequest)
44 Revision 1.1 2006/11/06 14:22:47 jgrosseo
45 major update (Alberto)
46 o) reading of run parameters from the logbook
47 o) online offline naming conversion
48 o) standalone DCSclient package
50 Revision 1.6 2006/10/02 16:38:39 jgrosseo
53 storing of objects that failed to be stored to the grid before
54 interfacing of shuttle status table in daq system
56 Revision 1.5 2006/08/15 10:50:00 jgrosseo
57 effc++ corrections (alberto)
59 Revision 1.4 2006/07/04 14:59:57 jgrosseo
60 revision of AliDCSValue: Removed wrapper classes, reduced storage size per value by factor 2
62 Revision 1.3 2006/06/12 09:11:16 jgrosseo
63 coding conventions (Alberto)
65 Revision 1.2 2006/03/07 07:52:34 hristov
66 New version (B.Yordanov)
68 Revision 1.3 2005/11/17 17:47:34 byordano
69 TList changed to TObjArray
71 Revision 1.2 2005/11/17 14:43:23 byordano
74 Revision 1.1.1.1 2005/10/28 07:33:58 hristov
75 Initial import as subdirectory in AliRoot
77 Revision 1.1.1.1 2005/09/12 22:11:40 byordano
80 Revision 1.3 2005/08/30 10:53:23 byordano
81 some more descriptions added
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
93 // There are two type of read operations:
94 // Asking for single alias/dp or asking for set of aliases/dp
96 // In case of ServerError the coresponding error code and
97 // error string (description) could be got by GetServerErrorCode() and
98 // GetServerErrorString()
101 #include "AliDCSClient.h"
102 #include "AliDCSValue.h"
106 #include <TObjArray.h>
108 #include <TObjString.h>
111 ClassImp(AliDCSClient)
113 const char* AliDCSClient::fgkBadStateString = "BadState";
114 const char* AliDCSClient::fgkInvalidParameterString = "InvalidParameter";
115 const char* AliDCSClient::fgkTimeoutString = "Timeout";
116 const char* AliDCSClient::fgkBadMessageString = "BadMessage";
117 const char* AliDCSClient::fgkCommErrorString = "CommunicationError";
118 const char* AliDCSClient::fgkServerErrorString = "ServerError";
119 const char* AliDCSClient::fgkUnknownDPString = "UnknownAlias/DP";
121 //______________________________________________________________________
122 AliDCSClient::AliDCSClient(const char* host, Int_t port, UInt_t timeout,
123 Int_t retries, Int_t multiSplit):
124 fSocket(NULL), fHost(host), fPort(port), fTimeout(timeout), fRetries(retries), fMultiSplit(multiSplit),
125 fServerErrorCode(AliDCSMessage::kNoneError), fServerError(""), fResultErrorCode(0)
128 // host: DCS server host
129 // port: DCS server port
130 // timeout: in case of communication error or socket read/write this
131 // timeout will be used before the next try is made.
132 // retries: the number of retries after which the connection is
133 // is considered as invalid and error is returned.
137 //______________________________________________________________________
138 AliDCSClient::~AliDCSClient()
145 //______________________________________________________________________
146 Bool_t AliDCSClient::Connect()
148 // connects to the AMANDA server
153 while (tries < fRetries)
155 fSocket = new TSocket(fHost, fPort);
156 if (fSocket->IsValid())
158 AliDebug(1, Form("Connected to %s:%d", fHost.Data(), fPort));
159 fSocket->SetOption(kNoBlock, 1);
163 AliDebug(1, Form("Connection timeout! tries <%d> ...", tries));
168 gSystem->Sleep(fTimeout);
175 //______________________________________________________________________
176 Int_t AliDCSClient::SendBuffer(const char* buffer, Int_t size)
178 // send buffer containing the message to the DCS server
183 while (sentSize < size && tries < fRetries) {
185 Int_t sResult = fSocket->Select(TSocket::kWrite, fTimeout);
188 AliDebug(1, Form("Timeout! tries <%d> ...", tries));
192 } else if (sResult < 0) {
193 AliDebug(1, Form("Communication error <%d>!",
194 fSocket->GetErrorCode()));
195 return AliDCSClient::fgkCommError;
198 sResult = fSocket->SendRaw(buffer + sentSize, size - sentSize,
204 AliDebug(1, Form("Communication error <%d>!",
205 fSocket->GetErrorCode()));
206 return AliDCSClient::fgkCommError;
210 if (tries == fRetries) {
211 return AliDCSClient::fgkTimeout;
217 //______________________________________________________________________
218 Int_t AliDCSClient::ReceiveBuffer(char* buffer, Int_t size)
220 // Receive message from the DCS server and fill buffer
222 Int_t receivedSize = 0;
225 while (receivedSize < size && tries < fRetries) {
227 Int_t sResult = fSocket->Select(TSocket::kRead, fTimeout);
230 AliDebug(1, Form("Timeout! tries <%d> ...", tries));
234 } else if (sResult < 0) {
235 AliDebug(1, Form("Communication error <%d>",
236 fSocket->GetErrorCode()));
237 return AliDCSClient::fgkCommError;
240 sResult = fSocket->RecvRaw(buffer + receivedSize,
241 size - receivedSize, kDontBlock);
244 receivedSize += sResult;
246 AliDebug(1, Form("Communication error <%d>",
247 fSocket->GetErrorCode()));
248 return AliDCSClient::fgkCommError;
252 if (tries == fRetries) {
253 return AliDCSClient::fgkTimeout;
259 //______________________________________________________________________
260 Int_t AliDCSClient::SendMessage(AliDCSMessage& message)
262 // send message to the DCS server
264 message.StoreToBuffer();
266 AliDebug(2, "Sending message.\n");
269 return SendBuffer(message.GetMessage(), message.GetMessageSize());
272 //______________________________________________________________________
273 Int_t AliDCSClient::ReceiveMessage(AliDCSMessage& message)
275 // receive message from the DCS server
277 char header[HEADER_SIZE];
281 if ((sResult = ReceiveBuffer(header, HEADER_SIZE)) < 0) {
282 AliDebug(1, Form("Can't receive message header! Reason: %s",
283 GetErrorString(sResult)));
287 if (!message.SetRawHeader(header)) {
288 return AliDCSClient::fgkBadMessage;
291 if ((sResult = ReceiveBuffer(message.GetBody(),
292 message.GetBodySize())) < 0) {
294 AliDebug(1, Form("Can't receive message body! Reason: %s",
295 GetErrorString(sResult)));
299 message.LoadFromBuffer();
301 AliDebug(2, "Message received.");
304 return HEADER_SIZE + sResult;
307 //______________________________________________________________________
308 Int_t AliDCSClient::GetValues(AliDCSMessage::RequestType reqType,
309 const char* reqString, UInt_t startTime, UInt_t endTime, TObjArray* result)
311 // get array of DCS values from the DCS server
312 // reqString: alias name
313 // startTime, endTime: start time and end time of the query
314 // result: contains the array of retrieved AliDCSValue's
318 if (!IsConnected()) {
319 AliError("Not connected!");
320 return AliDCSClient::fgkBadState;
324 AliDCSMessage requestMessage;
325 requestMessage.CreateRequestMessage(reqType, startTime, endTime,
328 if ((sResult = SendMessage(requestMessage)) < 0) {
329 AliError(Form("Can't send request message! Reason: %s",
330 GetErrorString(sResult)));
335 Int_t receivedValues = 0;
340 sResult = ReceiveValueSet(result, tmp);
343 receivedValues += sResult;
348 return receivedValues;
351 //______________________________________________________________________
352 TMap* AliDCSClient::GetValues(AliDCSMessage::RequestType reqType,
353 const TSeqCollection* list, UInt_t startTime, UInt_t endTime,
354 Int_t startIndex, Int_t endIndex)
356 // get array of DCS values from the DCS server
357 // list, startTime, endTime: list of dp/alias names, start time and end time of the query
359 // Result: map containing the array of alias names. It will be filled with
360 // the values retrieved for each alias
362 TMap* result = new TMap;
365 if (endIndex < 0 || endIndex > list->GetEntries())
366 endIndex = list->GetEntries();
368 for (Int_t subsetBegin = startIndex; subsetBegin < endIndex; subsetBegin += fMultiSplit)
374 AliError("Not connected!");
376 fResultErrorCode = fgkBadState;
380 Int_t subsetEnd = subsetBegin + fMultiSplit;
381 if (subsetEnd > endIndex)
382 subsetEnd = endIndex;
384 AliDCSMessage requestMessage;
385 if (fMultiSplit == 1)
389 TObjString* aRequest = (TObjString*) list->At(subsetBegin);
390 requestMessage.CreateRequestMessage(reqType, startTime, endTime, aRequest->String());
396 requestMessage.CreateMultiRequestMessage(reqType,
399 for (Int_t i=subsetBegin; i<subsetEnd; i++)
401 TObjString* aRequest = (TObjString*) list->At(i);
402 if (!requestMessage.AddRequestString(aRequest->String()))
405 fResultErrorCode = fgkBadMessage;
411 if ((fResultErrorCode = SendMessage(requestMessage)) < 0)
413 AliError(Form("Can't send request message! Reason: %s",
414 GetErrorString(fResultErrorCode)));
422 TObjArray* resultSet = new TObjArray();
423 resultSet->SetOwner(1);
425 Int_t ownerIndex = -1;
426 fResultErrorCode = ReceiveValueSet(resultSet, ownerIndex);
428 if (fResultErrorCode < 0)
430 if (fResultErrorCode == fgkUnknownDP)
432 AliError(Form("%s",fServerError.Data()));
435 AliError("Can't get values");
438 result->DeleteValues();
450 TObjString* aRequest = (TObjString*) list->At(ownerIndex + subsetBegin);
451 //AliInfo(Form("Received %d values for entry %d, that is %s", resultSet->GetEntries(),
452 // ownerIndex + subsetBegin, aRequest->String().Data()));
454 TObjArray* target = dynamic_cast<TObjArray*> (result->GetValue(aRequest));
457 target->AddAll(resultSet);
458 //AliInfo(Form("Now we have %d entries", target->GetEntries()));
459 resultSet->SetOwner(0);
463 result->Add(aRequest, resultSet);
469 TObjArray* example = (TObjArray*) result->GetValue(list->At(subsetBegin));
471 nValues = example->GetEntries();
472 AliInfo(Form("Retrieved entries %d..%d (total %d..%d); E.g. %s has %d values collected",
473 subsetBegin, subsetEnd-1, startIndex, endIndex-1, list->At(subsetBegin)->GetName(), nValues));
479 //______________________________________________________________________
480 Int_t AliDCSClient::ReceiveValueSet(TObjArray* result, Int_t& ownerIndex)
482 // receive set of values
484 AliDCSMessage message;
485 Int_t sResult = ReceiveMessage(message);
488 AliError(Form("Can't receive message! Reason: %s", GetErrorString(sResult)));
492 if (message.GetType() == AliDCSMessage::kResultSet)
494 // this was the last message
495 ownerIndex = message.GetOwnerIndex();
499 sResult = message.GetValues(result);
501 // AliDCSMessage nextMessage;
502 // nextMessage.CreateNextMessage();
504 // if ((fResultErrorCode = SendMessage(nextMessage)) < 0)
506 // AliError(Form("Can't send next message! Reason: %s",
507 // GetErrorString(fResultErrorCode)));
509 // return AliDCSClient::fgkCommError;
514 else if (message.GetType() == AliDCSMessage::kError)
516 fServerErrorCode = message.GetErrorCode();
517 fServerError = message.GetErrorString();
519 return AliDCSClient::fgkServerError;
522 else if (message.GetType() == AliDCSMessage::kUnknownDP)
524 fServerError = message.GetErrorString();
526 return AliDCSClient::fgkUnknownDP;
530 AliError("Bad message type received!");
531 return AliDCSClient::fgkBadMessage;
534 //______________________________________________________________________
535 Int_t AliDCSClient::GetDPValues(const char* dpName, UInt_t startTime,
536 UInt_t endTime, TObjArray* result)
539 // Reads a values from the server which correspond to this
540 // DataPoint (dpName) in time interval (startTime - endTime).
541 // result: Collection of AliDCSValue which contains the read values.
544 // If >= 0 , the number of values read.
545 // if < 0, the error code which has occured during the read.
548 return GetValues(AliDCSMessage::kDPName,
549 dpName, startTime, endTime, result);
552 //______________________________________________________________________
553 Int_t AliDCSClient::GetAliasValues(const char* alias, UInt_t startTime,
554 UInt_t endTime, TObjArray* result)
557 // Reads a values from the server which correspond to this
558 // alias (alias) in time interval (startTime - endTime).
559 // result: Collection of AliDCSValue which contains the read values.
562 // If >= 0 , the number of values read.
563 // if < 0, the error code which has occured during the read.
566 return GetValues(AliDCSMessage::kAlias,
567 alias, startTime, endTime, result);
570 //______________________________________________________________________
571 TMap* AliDCSClient::GetDPValues(const TSeqCollection* dpList, UInt_t startTime, UInt_t endTime,
572 Int_t startIndex, Int_t endIndex)
575 // For every entry (fron startIndex to endIndex) in dpList (which must be TObjString)
576 // reads a valueSet. The key represents particular DataPoint to be read.
577 // For all DataPoints time interval (startTime - endTime) is used.
578 // After the read, the correspoding value for every key is a
579 // TObjArray - collection of AliDCSValue, or result is an empty map in
583 // TMap of results, 0 in case of failure
586 return GetValues(AliDCSMessage::kDPName, dpList, startTime, endTime, startIndex, endIndex);
589 //______________________________________________________________________
590 TMap* AliDCSClient::GetAliasValues(const TSeqCollection* aliasList, UInt_t startTime, UInt_t endTime,
591 Int_t startIndex, Int_t endIndex)
594 // For every entry (fron startIndex to endIndex) in dpList (which must be TObjString)
595 // reads a valueSet. The key represents particular Alias to be read.
596 // For all aliases time interval (startTime - endTime) is used.
597 // After the read, the correspoding value for every key is a
598 // TObjArray - collection of AliDCSValue, or result is an empty map in
602 // TMap of results, 0 in case of failure
605 return GetValues(AliDCSMessage::kAlias, aliasList, startTime, endTime, startIndex, endIndex);
608 //______________________________________________________________________
609 Bool_t AliDCSClient::IsConnected()
612 // Returns kTRUE if there is a valid connection to the server.
616 return fSocket->IsValid();
622 //______________________________________________________________________
623 void AliDCSClient::Close()
626 // Close the connection.
636 //______________________________________________________________________
637 const char* AliDCSClient::GetErrorString(Int_t code)
640 // Returns a short string describing the error code.
641 // code: the error code.
646 case AliDCSClient::fgkBadState:
647 return AliDCSClient::fgkBadStateString;
649 case AliDCSClient::fgkInvalidParameter:
650 return AliDCSClient::fgkInvalidParameterString;
652 case AliDCSClient::fgkTimeout:
653 return AliDCSClient::fgkTimeoutString;
655 case AliDCSClient::fgkBadMessage:
656 return AliDCSClient::fgkBadMessageString;
658 case AliDCSClient::fgkCommError:
659 return AliDCSClient::fgkCommErrorString;
661 case AliDCSClient::fgkServerError:
662 return AliDCSClient::fgkServerErrorString;
664 case AliDCSClient::fgkUnknownDP:
665 return AliDCSClient::fgkUnknownDPString;
668 AliErrorGeneral("AliDCSClient::GetErrorString",
669 "Unknown error code!");
670 return "UnknownCode";