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 **************************************************************************/
17 // This class represents the AliDCSClient, the client used for
18 // data retrieval from the DCS server.
19 // There are two ways for retrieving data from the server:
20 // 1) asking for DP (DataPoint) - usually changed frequently.
21 // 2) asking for Alias (Alias) - alias should be the same through
22 // the whole experiment.
24 // There are two types of read operations:
25 // Asking for a single alias/DP or asking for a set of aliases/DPs
27 // In case of ServerError the corresponding error code and
28 // error string (description) could be got by GetServerErrorCode() and
29 // GetServerErrorString()
32 #include "AliDCSClient.h"
33 #include "AliDCSValue.h"
37 #include <TObjArray.h>
39 #include <TObjString.h>
41 #include <TTimeStamp.h>
43 ClassImp(AliDCSClient)
45 const char* AliDCSClient::fgkBadStateString = "BadState";
46 const char* AliDCSClient::fgkInvalidParameterString = "InvalidParameter";
47 const char* AliDCSClient::fgkTimeoutString = "Timeout";
48 const char* AliDCSClient::fgkBadMessageString = "BadMessage";
49 const char* AliDCSClient::fgkCommErrorString = "CommunicationError";
50 const char* AliDCSClient::fgkServerErrorString = "ServerError";
51 const char* AliDCSClient::fgkUnknownDPString = "UnknownAlias/DP";
53 //______________________________________________________________________
54 AliDCSClient::AliDCSClient(const char* host, Int_t port, UInt_t timeout,
55 Int_t retries, Int_t multiSplit):
56 fSocket(NULL), fHost(host), fPort(port), fTimeout(timeout), fRetries(retries), fMultiSplit(multiSplit),
57 fServerErrorCode(AliDCSMessage::kNoneError), fServerError(""), fResultErrorCode(0)
60 // host: DCS server host
61 // port: DCS server port
62 // timeout: in case of communication error or socket read/write this
63 // timeout will be used before the next try is made.
64 // retries: the number of retries after which the connection is
65 // is considered as invalid and error is returned.
69 //______________________________________________________________________
70 AliDCSClient::~AliDCSClient()
77 //______________________________________________________________________
78 Bool_t AliDCSClient::Connect()
80 // connects to the AMANDA server
87 while (tries < fRetries)
89 fSocket = new TSocket(fHost, fPort);
91 if (fSocket && fSocket->IsValid())
93 AliDebug(1, Form("%s *** Connected to %s:%d", TTimeStamp(time(0)).AsString("s"), fHost.Data(), fPort));
94 fSocket->SetOption(kNoBlock, 1);
98 AliError(Form(" *** Connection to AMANDA server failed Tried <%d> times ...", tries+1));
99 if(tries<fRetries-1) AliInfo(Form(" *** Waiting %d seconds before next retry.", sleeptime));
104 gSystem->Sleep(sleeptime);
111 //______________________________________________________________________
112 Int_t AliDCSClient::SendBuffer(const char* buffer, Int_t size)
114 // send buffer containing the message to the DCS server
119 while (sentSize < size && tries < fRetries) {
121 Int_t sResult = fSocket->Select(TSocket::kWrite, fTimeout*1000); //timeout for TSocket::Select is in msec
124 AliDebug(1, Form("Timeout! tries <%d> ...", tries));
128 } else if (sResult < 0) {
129 AliDebug(1, Form("Communication error <%d>!",
130 fSocket->GetErrorCode()));
131 return AliDCSClient::fgkCommError;
134 sResult = fSocket->SendRaw(buffer + sentSize, size - sentSize,
140 AliDebug(1, Form("Communication error <%d>!",
141 fSocket->GetErrorCode()));
142 return AliDCSClient::fgkCommError;
146 if (tries == fRetries) {
147 return AliDCSClient::fgkTimeout;
153 //______________________________________________________________________
154 Int_t AliDCSClient::ReceiveBuffer(char* buffer, Int_t size)
156 // Receive message from the DCS server and fill buffer
158 Int_t receivedSize = 0;
161 while (receivedSize < size && tries < fRetries) {
163 Int_t sResult = fSocket->Select(TSocket::kRead, fTimeout*1000); //timeout for TSocket::Select is in msec
166 AliDebug(1, Form("Time when timing out: %s Timeout value: %d seconds",TTimeStamp(time(0)).AsString("s"),fTimeout));
167 AliDebug(1, Form("Timeout! tries <%d> ...", tries));
171 } else if (sResult < 0) {
172 AliDebug(1, Form("Communication error <%d>",
173 fSocket->GetErrorCode()));
174 return AliDCSClient::fgkCommError;
177 sResult = fSocket->RecvRaw(buffer + receivedSize,
178 size - receivedSize, kDontBlock);
181 receivedSize += sResult;
183 AliDebug(1, Form("Communication error <%d>",
184 fSocket->GetErrorCode()));
185 return AliDCSClient::fgkCommError;
189 if (tries == fRetries) {
190 return AliDCSClient::fgkTimeout;
196 //______________________________________________________________________
197 Int_t AliDCSClient::SendMessage(AliDCSMessage& message)
199 // send message to the DCS server
201 message.StoreToBuffer();
203 AliDebug(2, "Sending message.\n");
206 return SendBuffer(message.GetMessage(), message.GetMessageSize());
209 //______________________________________________________________________
210 Int_t AliDCSClient::ReceiveMessage(AliDCSMessage& message)
212 // receive message from the DCS server
214 char header[HEADER_SIZE];
218 if ((sResult = ReceiveBuffer(header, HEADER_SIZE)) < 0) {
219 AliDebug(1, Form("Can't receive message header! Reason: %s",
220 GetErrorString(sResult)));
224 if (!message.SetRawHeader(header)) {
225 return AliDCSClient::fgkBadMessage;
228 if ((sResult = ReceiveBuffer(message.GetBody(),
229 message.GetBodySize())) < 0) {
231 AliDebug(1, Form("Can't receive message body! Reason: %s",
232 GetErrorString(sResult)));
236 message.LoadFromBuffer();
238 AliDebug(2, "Message received.");
241 return HEADER_SIZE + sResult;
244 //______________________________________________________________________
245 Int_t AliDCSClient::GetValues(AliDCSMessage::RequestType reqType,
246 const char* reqString, UInt_t startTime, UInt_t endTime, TObjArray* result)
248 // get array of DCS values from the DCS server
249 // reqString: alias name
250 // startTime, endTime: start time and end time of the query
251 // result: contains the array of retrieved AliDCSValue's
255 if (!IsConnected()) {
256 AliError("Not connected!");
257 return AliDCSClient::fgkBadState;
261 AliDCSMessage requestMessage;
262 requestMessage.CreateRequestMessage(reqType, startTime, endTime,
265 if ((sResult = SendMessage(requestMessage)) < 0) {
266 AliError(Form("Can't send request message! Reason: %s",
267 GetErrorString(sResult)));
272 Int_t receivedValues = 0;
277 sResult = ReceiveValueSet(result, tmp);
280 receivedValues += sResult;
285 return receivedValues;
288 //______________________________________________________________________
289 TMap* AliDCSClient::GetValues(AliDCSMessage::RequestType reqType,
290 const TSeqCollection* list, UInt_t startTime, UInt_t endTime,
291 Int_t startIndex, Int_t endIndex)
293 // get array of DCS values from the DCS server
294 // list, startTime, endTime: list of dp/alias names, start time and end time of the query
296 // Result: map containing the array of alias names. It will be filled with
297 // the values retrieved for each alias
299 TMap* result = new TMap;
302 if (endIndex < 0 || endIndex > list->GetEntries())
303 endIndex = list->GetEntries();
305 for (Int_t subsetBegin = startIndex; subsetBegin < endIndex; subsetBegin += fMultiSplit)
311 AliError("Not connected!");
313 fResultErrorCode = fgkBadState;
317 Int_t subsetEnd = subsetBegin + fMultiSplit;
318 if (subsetEnd > endIndex)
319 subsetEnd = endIndex;
321 AliDCSMessage requestMessage;
322 if (fMultiSplit == 1)
326 TObjString* aRequest = (TObjString*) list->At(subsetBegin);
327 requestMessage.CreateRequestMessage(reqType, startTime, endTime, aRequest->String());
333 requestMessage.CreateMultiRequestMessage(reqType,
336 for (Int_t i=subsetBegin; i<subsetEnd; i++)
338 TObjString* aRequest = (TObjString*) list->At(i);
339 if (!requestMessage.AddRequestString(aRequest->String()))
342 fResultErrorCode = fgkBadMessage;
348 if ((fResultErrorCode = SendMessage(requestMessage)) < 0)
350 AliError(Form("Can't send request message! Reason: %s",
351 GetErrorString(fResultErrorCode)));
359 TObjArray* resultSet = new TObjArray();
360 resultSet->SetOwner(1);
362 Int_t ownerIndex = -1;
363 fResultErrorCode = ReceiveValueSet(resultSet, ownerIndex);
365 if (fResultErrorCode < 0)
367 if (fResultErrorCode == fgkUnknownDP)
369 AliError(Form("%s",fServerError.Data()));
372 AliError("Can't get values");
375 result->DeleteValues();
387 TObjString* aRequest = (TObjString*) list->At(ownerIndex + subsetBegin);
389 for (Int_t i=0; i<resultSet->GetEntries(); i++)
391 AliDCSValue* value = (AliDCSValue*) resultSet->At(i);
394 if (value->GetTimeStamp() < startTime || value->GetTimeStamp() > endTime)
395 AliWarning(Form("Value for %s outside of queried interval (%d to %d): %d", aRequest->String().Data(), startTime, endTime, value->GetTimeStamp()));
398 TObjArray* target = dynamic_cast<TObjArray*> (result->GetValue(aRequest));
401 target->AddAll(resultSet);
402 resultSet->SetOwner(0);
406 result->Add(aRequest, resultSet);
412 TObjArray* example = (TObjArray*) result->GetValue(list->At(subsetBegin));
414 nValues = example->GetEntries();
415 AliInfo(Form("Retrieved entries %d..%d (total %d..%d); E.g. %s has %d values collected",
416 subsetBegin, subsetEnd-1, startIndex, endIndex-1, list->At(subsetBegin)->GetName(), nValues));
422 //______________________________________________________________________
423 Int_t AliDCSClient::ReceiveValueSet(TObjArray* result, Int_t& ownerIndex)
425 // receive set of values
427 AliDCSMessage message;
428 Int_t sResult = ReceiveMessage(message);
431 AliError(Form("Can't receive message! Reason: %s", GetErrorString(sResult)));
435 if (message.GetType() == AliDCSMessage::kResultSet)
437 // this was the last message
438 ownerIndex = message.GetOwnerIndex();
442 sResult = message.GetValues(result);
446 else if (message.GetType() == AliDCSMessage::kError)
448 fServerErrorCode = message.GetErrorCode();
449 fServerError = message.GetErrorString();
451 return AliDCSClient::fgkServerError;
454 else if (message.GetType() == AliDCSMessage::kUnknownDP)
456 fServerError = message.GetErrorString();
458 return AliDCSClient::fgkUnknownDP;
462 AliError("Bad message type received!");
463 return AliDCSClient::fgkBadMessage;
466 //______________________________________________________________________
467 Int_t AliDCSClient::GetDPValues(const char* dpName, UInt_t startTime,
468 UInt_t endTime, TObjArray* result)
471 // Reads a values from the server which correspond to this
472 // DataPoint (dpName) in time interval (startTime - endTime).
473 // result: Collection of AliDCSValue which contains the read values.
476 // If >= 0 , the number of values read.
477 // if < 0, the error code which has occured during the read.
480 return GetValues(AliDCSMessage::kDPName,
481 dpName, startTime, endTime, result);
484 //______________________________________________________________________
485 Int_t AliDCSClient::GetAliasValues(const char* alias, UInt_t startTime,
486 UInt_t endTime, TObjArray* result)
489 // Reads a values from the server which correspond to this
490 // alias (alias) in time interval (startTime - endTime).
491 // result: Collection of AliDCSValue which contains the read values.
494 // If >= 0 , the number of values read.
495 // if < 0, the error code which has occured during the read.
498 return GetValues(AliDCSMessage::kAlias,
499 alias, startTime, endTime, result);
502 //______________________________________________________________________
503 TMap* AliDCSClient::GetDPValues(const TSeqCollection* dpList, UInt_t startTime, UInt_t endTime,
504 Int_t startIndex, Int_t endIndex)
507 // For every entry (fron startIndex to endIndex) in dpList (which must be TObjString)
508 // reads a valueSet. The key represents particular DataPoint to be read.
509 // For all DataPoints time interval (startTime - endTime) is used.
510 // After the read, the correspoding value for every key is a
511 // TObjArray - collection of AliDCSValue, or result is an empty map in
515 // TMap of results, 0 in case of failure
518 return GetValues(AliDCSMessage::kDPName, dpList, startTime, endTime, startIndex, endIndex);
521 //______________________________________________________________________
522 TMap* AliDCSClient::GetAliasValues(const TSeqCollection* aliasList, UInt_t startTime, UInt_t endTime,
523 Int_t startIndex, Int_t endIndex)
526 // For every entry (fron startIndex to endIndex) in dpList (which must be TObjString)
527 // reads a valueSet. The key represents particular Alias to be read.
528 // For all aliases time interval (startTime - endTime) is used.
529 // After the read, the correspoding value for every key is a
530 // TObjArray - collection of AliDCSValue, or result is an empty map in
534 // TMap of results, 0 in case of failure
537 return GetValues(AliDCSMessage::kAlias, aliasList, startTime, endTime, startIndex, endIndex);
540 //______________________________________________________________________
541 Bool_t AliDCSClient::IsConnected()
544 // Returns kTRUE if there is a valid connection to the server.
548 return fSocket->IsValid();
554 //______________________________________________________________________
555 void AliDCSClient::Close()
558 // Close the connection.
562 AliDebug(1, Form("%s *** Closing connection to %s:%d", TTimeStamp(time(0)).AsString("s"), fHost.Data(), fPort));
569 //______________________________________________________________________
570 const char* AliDCSClient::GetErrorString(Int_t code)
573 // Returns a short string describing the error code.
574 // code: the error code.
579 case AliDCSClient::fgkBadState:
580 return AliDCSClient::fgkBadStateString;
582 case AliDCSClient::fgkInvalidParameter:
583 return AliDCSClient::fgkInvalidParameterString;
585 case AliDCSClient::fgkTimeout:
586 return AliDCSClient::fgkTimeoutString;
588 case AliDCSClient::fgkBadMessage:
589 return AliDCSClient::fgkBadMessageString;
591 case AliDCSClient::fgkCommError:
592 return AliDCSClient::fgkCommErrorString;
594 case AliDCSClient::fgkServerError:
595 return AliDCSClient::fgkServerErrorString;
597 case AliDCSClient::fgkUnknownDP:
598 return AliDCSClient::fgkUnknownDPString;
601 AliErrorGeneral("AliDCSClient::GetErrorString",
602 "Unknown error code!");
603 return "UnknownCode";