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.5 2007/10/05 12:40:55 acolla
20 Result error code added to AliDCSClient data members (it was "lost" with the new implementation of TMap* GetAliasValues and GetDPValues).
22 Revision 1.4 2007/09/14 16:46:14 jgrosseo
23 1) Connect and Close are called before and after each query, so one can
24 keep the same AliDCSClient object.
25 2) The splitting of a query is moved to GetDPValues/GetAliasValues.
26 3) Splitting interval can be specified in constructor
28 Revision 1.3 2007/09/11 16:42:02 jgrosseo
29 starting modifying AliDCSClient to transparently switch between single and multi query
30 first step: same alidcsclient can be used for several queries
32 Revision 1.2 2007/06/09 13:01:09 jgrosseo
33 Switching to retrieval of several DCS DPs at a time (multiDPrequest)
35 Revision 1.1 2006/11/06 14:22:47 jgrosseo
36 major update (Alberto)
37 o) reading of run parameters from the logbook
38 o) online offline naming conversion
39 o) standalone DCSclient package
41 Revision 1.6 2006/10/02 16:38:39 jgrosseo
44 storing of objects that failed to be stored to the grid before
45 interfacing of shuttle status table in daq system
47 Revision 1.5 2006/08/15 10:50:00 jgrosseo
48 effc++ corrections (alberto)
50 Revision 1.4 2006/07/04 14:59:57 jgrosseo
51 revision of AliDCSValue: Removed wrapper classes, reduced storage size per value by factor 2
53 Revision 1.3 2006/06/12 09:11:16 jgrosseo
54 coding conventions (Alberto)
56 Revision 1.2 2006/03/07 07:52:34 hristov
57 New version (B.Yordanov)
59 Revision 1.3 2005/11/17 17:47:34 byordano
60 TList changed to TObjArray
62 Revision 1.2 2005/11/17 14:43:23 byordano
65 Revision 1.1.1.1 2005/10/28 07:33:58 hristov
66 Initial import as subdirectory in AliRoot
68 Revision 1.1.1.1 2005/09/12 22:11:40 byordano
71 Revision 1.3 2005/08/30 10:53:23 byordano
72 some more descriptions added
77 // This class represents the AliDCSClient.
78 // The client used for data retrieval from DCS server.
79 // There are two way for retrieving data from the server.
80 // 1) asking for DP (DataPoint) - usually changed frequently.
81 // 2) asking for Alias (Alias) - alias should be the same through whole
84 // There are two type of read operations:
85 // Asking for single alias/dp or asking for set of aliases/dp
87 // In case of ServerError the coresponding error code and
88 // error string (description) could be got by GetServerErrorCode() and
89 // GetServerErrorString()
92 #include "AliDCSClient.h"
93 #include "AliDCSValue.h"
97 #include <TObjArray.h>
99 #include <TObjString.h>
102 ClassImp(AliDCSClient)
104 const char* AliDCSClient::fgkBadStateString = "BadState";
105 const char* AliDCSClient::fgkInvalidParameterString = "InvalidParameter";
106 const char* AliDCSClient::fgkTimeoutString = "Timeout";
107 const char* AliDCSClient::fgkBadMessageString = "BadMessage";
108 const char* AliDCSClient::fgkCommErrorString = "CommunicationError";
109 const char* AliDCSClient::fgkServerErrorString = "ServerError";
111 //______________________________________________________________________
112 AliDCSClient::AliDCSClient(const char* host, Int_t port, UInt_t timeout,
113 Int_t retries, Int_t multiSplit):
114 fSocket(NULL), fHost(host), fPort(port), fTimeout(timeout), fRetries(retries), fMultiSplit(multiSplit),
115 fServerErrorCode(AliDCSMessage::kNoneError), fServerError(""), fResultErrorCode(0)
118 // host: DCS server host
119 // port: DCS server port
120 // timeout: in case of communication error or socket read/write this
121 // timeout will be used before the next try is made.
122 // retries: the number of retries after which the connection is
123 // is considered as invalid and error is returned.
127 //______________________________________________________________________
128 AliDCSClient::~AliDCSClient()
135 //______________________________________________________________________
136 Bool_t AliDCSClient::Connect()
138 // connects to the AMANDA server
143 while (tries < fRetries)
145 fSocket = new TSocket(fHost, fPort);
146 if (fSocket->IsValid())
148 AliDebug(1, Form("Connected to %s:%d", fHost.Data(), fPort));
149 fSocket->SetOption(kNoBlock, 1);
153 AliDebug(1, Form("Connection timeout! tries <%d> ...", tries));
158 gSystem->Sleep(fTimeout);
165 //______________________________________________________________________
166 Int_t AliDCSClient::SendBuffer(const char* buffer, Int_t size)
168 // send buffer containing the message to the DCS server
173 while (sentSize < size && tries < fRetries) {
175 Int_t sResult = fSocket->Select(TSocket::kWrite, fTimeout);
178 AliDebug(1, Form("Timeout! tries <%d> ...", tries));
182 } else if (sResult < 0) {
183 AliDebug(1, Form("Communication error <%d>!",
184 fSocket->GetErrorCode()));
185 return AliDCSClient::fgkCommError;
188 sResult = fSocket->SendRaw(buffer + sentSize, size - sentSize,
194 AliDebug(1, Form("Communication error <%d>!",
195 fSocket->GetErrorCode()));
196 return AliDCSClient::fgkCommError;
200 if (tries == fRetries) {
201 return AliDCSClient::fgkTimeout;
207 //______________________________________________________________________
208 Int_t AliDCSClient::ReceiveBuffer(char* buffer, Int_t size)
210 // Receive message from the DCS server and fill buffer
212 Int_t receivedSize = 0;
215 while (receivedSize < size && tries < fRetries) {
217 Int_t sResult = fSocket->Select(TSocket::kRead, fTimeout);
220 AliDebug(1, Form("Timeout! tries <%d> ...", tries));
224 } else if (sResult < 0) {
225 AliDebug(1, Form("Communication error <%d>",
226 fSocket->GetErrorCode()));
227 return AliDCSClient::fgkCommError;
230 sResult = fSocket->RecvRaw(buffer + receivedSize,
231 size - receivedSize, kDontBlock);
234 receivedSize += sResult;
236 AliDebug(1, Form("Communication error <%d>",
237 fSocket->GetErrorCode()));
238 return AliDCSClient::fgkCommError;
242 if (tries == fRetries) {
243 return AliDCSClient::fgkTimeout;
249 //______________________________________________________________________
250 Int_t AliDCSClient::SendMessage(AliDCSMessage& message)
252 // send message to the DCS server
254 message.StoreToBuffer();
256 AliDebug(2, "Sending message.\n");
259 return SendBuffer(message.GetMessage(), message.GetMessageSize());
262 //______________________________________________________________________
263 Int_t AliDCSClient::ReceiveMessage(AliDCSMessage& message)
265 // receive message from the DCS server
267 char header[HEADER_SIZE];
271 if ((sResult = ReceiveBuffer(header, HEADER_SIZE)) < 0) {
272 AliDebug(1, Form("Can't receive message header! Reason: %s",
273 GetErrorString(sResult)));
277 if (!message.SetRawHeader(header)) {
278 return AliDCSClient::fgkBadMessage;
281 if ((sResult = ReceiveBuffer(message.GetBody(),
282 message.GetBodySize())) < 0) {
284 AliDebug(1, Form("Can't receive message body! Reason: %s",
285 GetErrorString(sResult)));
289 message.LoadFromBuffer();
291 AliDebug(2, "Message received.");
294 return HEADER_SIZE + sResult;
297 //______________________________________________________________________
298 Int_t AliDCSClient::GetValues(AliDCSMessage::RequestType reqType,
299 const char* reqString, UInt_t startTime, UInt_t endTime, TObjArray* result)
301 // get array of DCS values from the DCS server
302 // reqString: alias name
303 // startTime, endTime: start time and end time of the query
304 // result: contains the array of retrieved AliDCSValue's
308 if (!IsConnected()) {
309 AliError("Not connected!");
310 return AliDCSClient::fgkBadState;
314 AliDCSMessage requestMessage;
315 requestMessage.CreateRequestMessage(reqType, startTime, endTime,
318 if ((sResult = SendMessage(requestMessage)) < 0) {
319 AliError(Form("Can't send request message! Reason: %s",
320 GetErrorString(sResult)));
325 Int_t receivedValues = 0;
330 sResult = ReceiveValueSet(result, tmp);
333 receivedValues += sResult;
338 return receivedValues;
341 //______________________________________________________________________
342 TMap* AliDCSClient::GetValues(AliDCSMessage::RequestType reqType,
343 const TSeqCollection* list, UInt_t startTime, UInt_t endTime,
344 Int_t startIndex, Int_t endIndex)
346 // get array of DCS values from the DCS server
347 // list, startTime, endTime: list of dp/alias names, start time and end time of the query
349 // Result: map containing the array of alias names. It will be filled with
350 // the values retrieved for each alias
352 TMap* result = new TMap;
355 if (endIndex < 0 || endIndex > list->GetEntries())
356 endIndex = list->GetEntries();
358 for (Int_t subsetBegin = startIndex; subsetBegin < endIndex; subsetBegin += fMultiSplit)
364 AliError("Not connected!");
366 fResultErrorCode = fgkBadState;
370 Int_t subsetEnd = subsetBegin + fMultiSplit;
371 if (subsetEnd > endIndex)
372 subsetEnd = endIndex;
374 AliDCSMessage requestMessage;
375 if (fMultiSplit == 1)
379 TObjString* aRequest = (TObjString*) list->At(subsetBegin);
380 requestMessage.CreateRequestMessage(reqType, startTime, endTime, aRequest->String());
386 requestMessage.CreateMultiRequestMessage(reqType,
389 for (Int_t i=subsetBegin; i<subsetEnd; i++)
391 TObjString* aRequest = (TObjString*) list->At(i);
392 if (!requestMessage.AddRequestString(aRequest->String()))
395 fResultErrorCode = fgkBadMessage;
401 if ((fResultErrorCode = SendMessage(requestMessage)) < 0)
403 AliError(Form("Can't send request message! Reason: %s",
404 GetErrorString(fResultErrorCode)));
412 TObjArray* resultSet = new TObjArray();
413 resultSet->SetOwner(1);
415 Int_t ownerIndex = -1;
416 fResultErrorCode = ReceiveValueSet(resultSet, ownerIndex);
418 if (fResultErrorCode < 0)
420 AliError("Can't get values");
423 result->DeleteValues();
435 TObjString* aRequest = (TObjString*) list->At(ownerIndex + subsetBegin);
436 //AliInfo(Form("Received %d values for entry %d, that is %s", resultSet->GetEntries(),
437 // ownerIndex + subsetBegin, aRequest->String().Data()));
439 TObjArray* target = dynamic_cast<TObjArray*> (result->GetValue(aRequest));
442 target->AddAll(resultSet);
443 //AliInfo(Form("Now we have %d entries", target->GetEntries()));
444 resultSet->SetOwner(0);
448 result->Add(aRequest, resultSet);
453 AliInfo(Form("Retrieved entries %d..%d (total %d..%d); E.g. %s has %d values collected",
454 subsetBegin, subsetEnd-1, startIndex, endIndex-1, list->At(subsetBegin)->GetName(), ((TObjArray*)
455 result->GetValue(list->At(subsetBegin)->GetName()))->GetEntriesFast()));
462 //______________________________________________________________________
463 Int_t AliDCSClient::ReceiveValueSet(TObjArray* result, Int_t& ownerIndex)
465 // receive set of values
467 AliDCSMessage message;
468 Int_t sResult = ReceiveMessage(message);
471 AliError(Form("Can't receive message! Reason: %s", GetErrorString(sResult)));
475 if (message.GetType() == AliDCSMessage::kResultSet)
477 // this was the last message
478 ownerIndex = message.GetOwnerIndex();
482 sResult = message.GetValues(result);
484 AliDCSMessage nextMessage;
485 nextMessage.CreateNextMessage();
487 if ((fResultErrorCode = SendMessage(nextMessage)) < 0)
489 AliError(Form("Can't send next message! Reason: %s",
490 GetErrorString(fResultErrorCode)));
492 return AliDCSClient::fgkCommError;
497 else if (message.GetType() == AliDCSMessage::kError)
499 fServerErrorCode = message.GetErrorCode();
500 fServerError = message.GetErrorString();
502 return AliDCSClient::fgkServerError;
505 AliError("Bad message type received!");
506 return AliDCSClient::fgkBadMessage;
509 //______________________________________________________________________
510 Int_t AliDCSClient::GetDPValues(const char* dpName, UInt_t startTime,
511 UInt_t endTime, TObjArray* result)
514 // Reads a values from the server which correspond to this
515 // DataPoint (dpName) in time interval (startTime - endTime).
516 // result: Collection of AliDCSValue which contains the read values.
519 // If >= 0 , the number of values read.
520 // if < 0, the error code which has occured during the read.
523 return GetValues(AliDCSMessage::kDPName,
524 dpName, startTime, endTime, result);
527 //______________________________________________________________________
528 Int_t AliDCSClient::GetAliasValues(const char* alias, UInt_t startTime,
529 UInt_t endTime, TObjArray* result)
532 // Reads a values from the server which correspond to this
533 // alias (alias) in time interval (startTime - endTime).
534 // result: Collection of AliDCSValue which contains the read values.
537 // If >= 0 , the number of values read.
538 // if < 0, the error code which has occured during the read.
541 return GetValues(AliDCSMessage::kAlias,
542 alias, startTime, endTime, result);
545 //______________________________________________________________________
546 TMap* AliDCSClient::GetDPValues(const TSeqCollection* dpList, UInt_t startTime, UInt_t endTime,
547 Int_t startIndex, Int_t endIndex)
550 // For every entry (fron startIndex to endIndex) in dpList (which must be TObjString)
551 // reads a valueSet. The key represents particular DataPoint to be read.
552 // For all DataPoints time interval (startTime - endTime) is used.
553 // After the read, the correspoding value for every key is a
554 // TObjArray - collection of AliDCSValue, or result is an empty map in
558 // TMap of results, 0 in case of failure
561 return GetValues(AliDCSMessage::kDPName, dpList, startTime, endTime, startIndex, endIndex);
564 //______________________________________________________________________
565 TMap* AliDCSClient::GetAliasValues(const TSeqCollection* aliasList, UInt_t startTime, UInt_t endTime,
566 Int_t startIndex, Int_t endIndex)
569 // For every entry (fron startIndex to endIndex) in dpList (which must be TObjString)
570 // reads a valueSet. The key represents particular Alias to be read.
571 // For all aliases time interval (startTime - endTime) is used.
572 // After the read, the correspoding value for every key is a
573 // TObjArray - collection of AliDCSValue, or result is an empty map in
577 // TMap of results, 0 in case of failure
580 return GetValues(AliDCSMessage::kAlias, aliasList, startTime, endTime, startIndex, endIndex);
583 //______________________________________________________________________
584 Bool_t AliDCSClient::IsConnected()
587 // Returns kTRUE if there is a valid connection to the server.
591 return fSocket->IsValid();
597 //______________________________________________________________________
598 void AliDCSClient::Close()
601 // Close the connection.
611 //______________________________________________________________________
612 const char* AliDCSClient::GetErrorString(Int_t code)
615 // Returns a short string describing the error code.
616 // code: the error code.
621 case AliDCSClient::fgkBadState:
622 return AliDCSClient::fgkBadStateString;
624 case AliDCSClient::fgkInvalidParameter:
625 return AliDCSClient::fgkInvalidParameterString;
627 case AliDCSClient::fgkTimeout:
628 return AliDCSClient::fgkTimeoutString;
630 case AliDCSClient::fgkBadMessage:
631 return AliDCSClient::fgkBadMessageString;
633 case AliDCSClient::fgkCommError:
634 return AliDCSClient::fgkCommErrorString;
636 case AliDCSClient::fgkServerError:
637 return AliDCSClient::fgkServerErrorString;
640 AliErrorGeneral("AliDCSClient::GetErrorString",
641 "Unknown error code!");
642 return "UnknownCode";