adding warning in case result is outside of queried period
[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
73abe331 16//
17// This class represents the AliDCSClient.
18// The client used for data retrieval from DCS server.
19// There are two way 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 whole
22// experimnet.
23//
24// There are two type of read operations:
25// Asking for single alias/dp or asking for set of aliases/dp
26//
27// In case of ServerError the coresponding error code and
28// error string (description) could be got by GetServerErrorCode() and
29// GetServerErrorString()
30//
31
32#include "AliDCSClient.h"
73abe331 33#include "AliDCSValue.h"
34#include "AliLog.h"
35
58bc3020 36#include <TSocket.h>
d477ad88 37#include <TObjArray.h>
73abe331 38#include <TMap.h>
39#include <TObjString.h>
40#include <TSystem.h>
95d4aaef 41#include <TTimeStamp.h>
73abe331 42
43ClassImp(AliDCSClient)
44
73abe331 45const char* AliDCSClient::fgkBadStateString = "BadState";
73abe331 46const char* AliDCSClient::fgkInvalidParameterString = "InvalidParameter";
73abe331 47const char* AliDCSClient::fgkTimeoutString = "Timeout";
73abe331 48const char* AliDCSClient::fgkBadMessageString = "BadMessage";
73abe331 49const char* AliDCSClient::fgkCommErrorString = "CommunicationError";
73abe331 50const char* AliDCSClient::fgkServerErrorString = "ServerError";
fcbad67c 51const char* AliDCSClient::fgkUnknownDPString = "UnknownAlias/DP";
73abe331 52
58bc3020 53//______________________________________________________________________
73abe331 54AliDCSClient::AliDCSClient(const char* host, Int_t port, UInt_t timeout,
b41b252a 55 Int_t retries, Int_t multiSplit):
56 fSocket(NULL), fHost(host), fPort(port), fTimeout(timeout), fRetries(retries), fMultiSplit(multiSplit),
1790d4b7 57 fServerErrorCode(AliDCSMessage::kNoneError), fServerError(""), fResultErrorCode(0)
73abe331 58{
59 //
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.
66 //
73abe331 67}
68
58bc3020 69//______________________________________________________________________
bee83158 70AliDCSClient::~AliDCSClient()
58bc3020 71{
bee83158 72 // destructor
58bc3020 73
bee83158 74 Close();
58bc3020 75}
76
77//______________________________________________________________________
bee83158 78Bool_t AliDCSClient::Connect()
58bc3020 79{
bee83158 80 // connects to the AMANDA server
81
82 Close();
83
95d4aaef 84 Int_t tries = 0;
85 Int_t sleeptime=300;
86
bee83158 87 while (tries < fRetries)
88 {
89 fSocket = new TSocket(fHost, fPort);
95d4aaef 90
91 if (fSocket && fSocket->IsValid())
bee83158 92 {
95d4aaef 93 AliDebug(1, Form("%s *** Connected to %s:%d", TTimeStamp(time(0)).AsString("s"), fHost.Data(), fPort));
bee83158 94 fSocket->SetOption(kNoBlock, 1);
95 return kTRUE;
96 }
58bc3020 97
53b0c7f1 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));
58bc3020 100
73abe331 101 delete fSocket;
bee83158 102 fSocket = NULL;
103
95d4aaef 104 gSystem->Sleep(sleeptime);
bee83158 105 tries ++;
73abe331 106 }
bee83158 107
108 return kFALSE;
73abe331 109}
110
58bc3020 111//______________________________________________________________________
112Int_t AliDCSClient::SendBuffer(const char* buffer, Int_t size)
113{
114// send buffer containing the message to the DCS server
73abe331 115
116 Int_t sentSize = 0;
117 Int_t tries = 0;
118
119 while (sentSize < size && tries < fRetries) {
120
95d4aaef 121 Int_t sResult = fSocket->Select(TSocket::kWrite, fTimeout*1000); //timeout for TSocket::Select is in msec
73abe331 122
123 if (sResult == 0) {
124 AliDebug(1, Form("Timeout! tries <%d> ...", tries));
125 tries ++;
126 continue;
127
128 } else if (sResult < 0) {
129 AliDebug(1, Form("Communication error <%d>!",
130 fSocket->GetErrorCode()));
131 return AliDCSClient::fgkCommError;
132 }
133
134 sResult = fSocket->SendRaw(buffer + sentSize, size - sentSize,
135 kDontBlock);
136
137 if (sResult > 0) {
138 sentSize += sResult;
139 } else {
140 AliDebug(1, Form("Communication error <%d>!",
141 fSocket->GetErrorCode()));
142 return AliDCSClient::fgkCommError;
143 }
144 }
145
146 if (tries == fRetries) {
147 return AliDCSClient::fgkTimeout;
148 }
149
150 return sentSize;
151}
152
58bc3020 153//______________________________________________________________________
154Int_t AliDCSClient::ReceiveBuffer(char* buffer, Int_t size)
155{
156// Receive message from the DCS server and fill buffer
73abe331 157
158 Int_t receivedSize = 0;
159 Int_t tries = 0;
160
161 while (receivedSize < size && tries < fRetries) {
162
95d4aaef 163 Int_t sResult = fSocket->Select(TSocket::kRead, fTimeout*1000); //timeout for TSocket::Select is in msec
73abe331 164
165 if (sResult == 0) {
95d4aaef 166 AliDebug(1, Form("Time when timing out: %s Timeout value: %d seconds",TTimeStamp(time(0)).AsString("s"),fTimeout));
73abe331 167 AliDebug(1, Form("Timeout! tries <%d> ...", tries));
168 tries ++;
169 continue;
170
171 } else if (sResult < 0) {
172 AliDebug(1, Form("Communication error <%d>",
173 fSocket->GetErrorCode()));
174 return AliDCSClient::fgkCommError;
175 }
176
177 sResult = fSocket->RecvRaw(buffer + receivedSize,
178 size - receivedSize, kDontBlock);
179
180 if (sResult > 0) {
181 receivedSize += sResult;
182 } else {
183 AliDebug(1, Form("Communication error <%d>",
184 fSocket->GetErrorCode()));
185 return AliDCSClient::fgkCommError;
186 }
187 }
188
189 if (tries == fRetries) {
190 return AliDCSClient::fgkTimeout;
191 }
192
193 return receivedSize;
194}
195
58bc3020 196//______________________________________________________________________
197Int_t AliDCSClient::SendMessage(AliDCSMessage& message)
198{
199// send message to the DCS server
73abe331 200
201 message.StoreToBuffer();
202
203 AliDebug(2, "Sending message.\n");
204 message.Print();
205
206 return SendBuffer(message.GetMessage(), message.GetMessageSize());
207}
208
58bc3020 209//______________________________________________________________________
4e3d5771 210Int_t AliDCSClient::ReceiveMessage(AliDCSMessage& message)
58bc3020 211{
2109fca7 212 // receive message from the DCS server
73abe331 213
214 char header[HEADER_SIZE];
215
216 Int_t sResult;
217
218 if ((sResult = ReceiveBuffer(header, HEADER_SIZE)) < 0) {
219 AliDebug(1, Form("Can't receive message header! Reason: %s",
220 GetErrorString(sResult)));
221 return sResult;
222 }
223
224 if (!message.SetRawHeader(header)) {
225 return AliDCSClient::fgkBadMessage;
226 }
227
228 if ((sResult = ReceiveBuffer(message.GetBody(),
229 message.GetBodySize())) < 0) {
230
231 AliDebug(1, Form("Can't receive message body! Reason: %s",
232 GetErrorString(sResult)));
233 return sResult;
234 }
235
236 message.LoadFromBuffer();
237
238 AliDebug(2, "Message received.");
239 message.Print();
240
241 return HEADER_SIZE + sResult;
242}
243
58bc3020 244//______________________________________________________________________
73abe331 245Int_t AliDCSClient::GetValues(AliDCSMessage::RequestType reqType,
2bb7b766 246 const char* reqString, UInt_t startTime, UInt_t endTime, TObjArray* result)
73abe331 247{
bee83158 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
58bc3020 252
bee83158 253 Connect();
254
73abe331 255 if (!IsConnected()) {
256 AliError("Not connected!");
257 return AliDCSClient::fgkBadState;
258 }
259
bee83158 260 Int_t sResult = -1;
73abe331 261 AliDCSMessage requestMessage;
2bb7b766 262 requestMessage.CreateRequestMessage(reqType, startTime, endTime,
73abe331 263 reqString);
264
265 if ((sResult = SendMessage(requestMessage)) < 0) {
266 AliError(Form("Can't send request message! Reason: %s",
267 GetErrorString(sResult)));
268 Close();
269 return sResult;
2bb7b766 270 }
271
4e3d5771 272 Int_t receivedValues = 0;
273
274 while (1)
275 {
276 Int_t tmp = 0;
277 sResult = ReceiveValueSet(result, tmp);
278 if (sResult <= 0)
279 break;
280 receivedValues += sResult;
281 }
2bb7b766 282
73abe331 283 Close();
2109fca7 284
4e3d5771 285 return receivedValues;
73abe331 286}
287
58bc3020 288//______________________________________________________________________
a038aa70 289TMap* AliDCSClient::GetValues(AliDCSMessage::RequestType reqType,
290 const TSeqCollection* list, UInt_t startTime, UInt_t endTime,
291 Int_t startIndex, Int_t endIndex)
73abe331 292{
a038aa70 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
295 //
296 // Result: map containing the array of alias names. It will be filled with
297 // the values retrieved for each alias
58bc3020 298
b41b252a 299 TMap* result = new TMap;
300 result->SetOwner(1);
73abe331 301
a038aa70 302 if (endIndex < 0 || endIndex > list->GetEntries())
303 endIndex = list->GetEntries();
73abe331 304
b41b252a 305 for (Int_t subsetBegin = startIndex; subsetBegin < endIndex; subsetBegin += fMultiSplit)
a038aa70 306 {
4e3d5771 307 Connect();
308
309 if (!IsConnected())
b41b252a 310 {
4e3d5771 311 AliError("Not connected!");
312 delete result;
1790d4b7 313 fResultErrorCode = fgkBadState;
4e3d5771 314 return 0;
315 }
b41b252a 316
317 Int_t subsetEnd = subsetBegin + fMultiSplit;
318 if (subsetEnd > endIndex)
319 subsetEnd = endIndex;
320
321 AliDCSMessage requestMessage;
322 if (fMultiSplit == 1)
323 {
4e3d5771 324 // single dp request
325
326 TObjString* aRequest = (TObjString*) list->At(subsetBegin);
327 requestMessage.CreateRequestMessage(reqType, startTime, endTime, aRequest->String());
b41b252a 328 }
329 else
330 {
4e3d5771 331 // multi dp request
332
333 requestMessage.CreateMultiRequestMessage(reqType,
334 startTime, endTime);
b41b252a 335
336 for (Int_t i=subsetBegin; i<subsetEnd; i++)
337 {
338 TObjString* aRequest = (TObjString*) list->At(i);
339 if (!requestMessage.AddRequestString(aRequest->String()))
1790d4b7 340 {
341 delete result;
342 fResultErrorCode = fgkBadMessage;
b41b252a 343 return 0;
1790d4b7 344 }
4e3d5771 345 }
346 }
347
348 if ((fResultErrorCode = SendMessage(requestMessage)) < 0)
349 {
350 AliError(Form("Can't send request message! Reason: %s",
351 GetErrorString(fResultErrorCode)));
352 Close();
353 delete result;
354 return 0;
b41b252a 355 }
4e3d5771 356
357 while (1)
358 {
359 TObjArray* resultSet = new TObjArray();
b41b252a 360 resultSet->SetOwner(1);
73abe331 361
4e3d5771 362 Int_t ownerIndex = -1;
363 fResultErrorCode = ReceiveValueSet(resultSet, ownerIndex);
73abe331 364
4e3d5771 365 if (fResultErrorCode < 0)
366 {
fcbad67c 367 if (fResultErrorCode == fgkUnknownDP)
368 {
369 AliError(Form("%s",fServerError.Data()));
370 }
371
4e3d5771 372 AliError("Can't get values");
73abe331 373
4e3d5771 374 delete resultSet;
375 result->DeleteValues();
376 delete result;
377 return 0;
378 }
73abe331 379
4e3d5771 380 if (ownerIndex < 0)
381 {
382 // no more values
383 delete resultSet;
384 break;
385 }
73abe331 386
4e3d5771 387 TObjString* aRequest = (TObjString*) list->At(ownerIndex + subsetBegin);
2109fca7 388
389 for (Int_t i=0; i<resultSet->GetEntries(); i++)
390 {
391 AliDCSValue* value = (AliDCSValue*) resultSet->At(i);
392 if (!value)
393 continue;
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()));
396 }
397
4e3d5771 398 TObjArray* target = dynamic_cast<TObjArray*> (result->GetValue(aRequest));
399 if (target)
400 {
401 target->AddAll(resultSet);
4e3d5771 402 resultSet->SetOwner(0);
403 delete resultSet;
404 }
405 else
406 result->Add(aRequest, resultSet);
407 }
73abe331 408
4e3d5771 409 Close();
73abe331 410
e1c93495 411 Int_t nValues = 0;
412 TObjArray* example = (TObjArray*) result->GetValue(list->At(subsetBegin));
413 if (example)
414 nValues = example->GetEntries();
4e3d5771 415 AliInfo(Form("Retrieved entries %d..%d (total %d..%d); E.g. %s has %d values collected",
e1c93495 416 subsetBegin, subsetEnd-1, startIndex, endIndex-1, list->At(subsetBegin)->GetName(), nValues));
73abe331 417 }
418
4e3d5771 419 return result;
420}
421
422//______________________________________________________________________
423Int_t AliDCSClient::ReceiveValueSet(TObjArray* result, Int_t& ownerIndex)
424{
425 // receive set of values
73abe331 426
4e3d5771 427 AliDCSMessage message;
428 Int_t sResult = ReceiveMessage(message);
429 if (sResult < 0)
430 {
431 AliError(Form("Can't receive message! Reason: %s", GetErrorString(sResult)));
432 return sResult;
433 }
73abe331 434
4e3d5771 435 if (message.GetType() == AliDCSMessage::kResultSet)
436 {
437 // this was the last message
438 ownerIndex = message.GetOwnerIndex();
439 if (ownerIndex < 0)
440 return 0;
73abe331 441
4e3d5771 442 sResult = message.GetValues(result);
73abe331 443
4e3d5771 444 return sResult;
445 }
446 else if (message.GetType() == AliDCSMessage::kError)
447 {
448 fServerErrorCode = message.GetErrorCode();
449 fServerError = message.GetErrorString();
73abe331 450
4e3d5771 451 return AliDCSClient::fgkServerError;
452 }
fcbad67c 453
454 else if (message.GetType() == AliDCSMessage::kUnknownDP)
455 {
456 fServerError = message.GetErrorString();
457
458 return AliDCSClient::fgkUnknownDP;
459 }
460
73abe331 461
4e3d5771 462 AliError("Bad message type received!");
463 return AliDCSClient::fgkBadMessage;
73abe331 464}
4e3d5771 465
58bc3020 466//______________________________________________________________________
73abe331 467Int_t AliDCSClient::GetDPValues(const char* dpName, UInt_t startTime,
2bb7b766 468 UInt_t endTime, TObjArray* result)
73abe331 469{
470 //
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.
474 //
475 // Returns:
476 // If >= 0 , the number of values read.
477 // if < 0, the error code which has occured during the read.
478 //
479
480 return GetValues(AliDCSMessage::kDPName,
481 dpName, startTime, endTime, result);
482}
483
58bc3020 484//______________________________________________________________________
73abe331 485Int_t AliDCSClient::GetAliasValues(const char* alias, UInt_t startTime,
2bb7b766 486 UInt_t endTime, TObjArray* result)
73abe331 487{
488 //
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.
492 //
493 // Returns:
494 // If >= 0 , the number of values read.
495 // if < 0, the error code which has occured during the read.
496 //
497
498 return GetValues(AliDCSMessage::kAlias,
499 alias, startTime, endTime, result);
500}
501
58bc3020 502//______________________________________________________________________
a038aa70 503TMap* AliDCSClient::GetDPValues(const TSeqCollection* dpList, UInt_t startTime, UInt_t endTime,
504 Int_t startIndex, Int_t endIndex)
73abe331 505{
506 //
a038aa70 507 // For every entry (fron startIndex to endIndex) in dpList (which must be TObjString)
73abe331 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
d477ad88 511 // TObjArray - collection of AliDCSValue, or result is an empty map in
73abe331 512 // case of error.
513 //
514 // Returns:
a038aa70 515 // TMap of results, 0 in case of failure
73abe331 516 //
517
a038aa70 518 return GetValues(AliDCSMessage::kDPName, dpList, startTime, endTime, startIndex, endIndex);
73abe331 519}
520
58bc3020 521//______________________________________________________________________
a038aa70 522TMap* AliDCSClient::GetAliasValues(const TSeqCollection* aliasList, UInt_t startTime, UInt_t endTime,
523 Int_t startIndex, Int_t endIndex)
73abe331 524{
525 //
a038aa70 526 // For every entry (fron startIndex to endIndex) in dpList (which must be TObjString)
73abe331 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
d477ad88 530 // TObjArray - collection of AliDCSValue, or result is an empty map in
73abe331 531 // case of error.
532 //
533 // Returns:
a038aa70 534 // TMap of results, 0 in case of failure
73abe331 535 //
536
a038aa70 537 return GetValues(AliDCSMessage::kAlias, aliasList, startTime, endTime, startIndex, endIndex);
73abe331 538}
539
58bc3020 540//______________________________________________________________________
541Bool_t AliDCSClient::IsConnected()
542{
73abe331 543 //
544 // Returns kTRUE if there is a valid connection to the server.
545 //
546
547 if (fSocket) {
548 return fSocket->IsValid();
549 }
550
551 return kFALSE;
552}
553
58bc3020 554//______________________________________________________________________
555void AliDCSClient::Close()
556{
73abe331 557 //
558 // Close the connection.
559 //
560
561 if (fSocket) {
95d4aaef 562 AliDebug(1, Form("%s *** Closing connection to %s:%d", TTimeStamp(time(0)).AsString("s"), fHost.Data(), fPort));
73abe331 563 fSocket->Close();
bee83158 564 delete fSocket;
565 fSocket = 0;
73abe331 566 }
567}
568
58bc3020 569//______________________________________________________________________
570const char* AliDCSClient::GetErrorString(Int_t code)
571{
73abe331 572 //
573 // Returns a short string describing the error code.
574 // code: the error code.
575 //
576
577
578 switch (code) {
579 case AliDCSClient::fgkBadState:
580 return AliDCSClient::fgkBadStateString;
581
582 case AliDCSClient::fgkInvalidParameter:
583 return AliDCSClient::fgkInvalidParameterString;
584
585 case AliDCSClient::fgkTimeout:
586 return AliDCSClient::fgkTimeoutString;
587
588 case AliDCSClient::fgkBadMessage:
589 return AliDCSClient::fgkBadMessageString;
590
591 case AliDCSClient::fgkCommError:
592 return AliDCSClient::fgkCommErrorString;
593
594 case AliDCSClient::fgkServerError:
595 return AliDCSClient::fgkServerErrorString;
fcbad67c 596
597 case AliDCSClient::fgkUnknownDP:
598 return AliDCSClient::fgkUnknownDPString;
73abe331 599
600 default:
601 AliErrorGeneral("AliDCSClient::GetErrorString",
602 "Unknown error code!");
603 return "UnknownCode";
604 }
605}
606