Made ready for the analysis train
[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
16/*
17$Log$
e1c93495 18Revision 1.6 2007/10/16 14:37:16 jgrosseo
19changing to AMANDA protocol version 2
20
4e3d5771 21Revision 1.5 2007/10/05 12:40:55 acolla
22
23Result error code added to AliDCSClient data members (it was "lost" with the new implementation of TMap* GetAliasValues and GetDPValues).
24
1790d4b7 25Revision 1.4 2007/09/14 16:46:14 jgrosseo
261) Connect and Close are called before and after each query, so one can
27keep the same AliDCSClient object.
282) The splitting of a query is moved to GetDPValues/GetAliasValues.
293) Splitting interval can be specified in constructor
30
b41b252a 31Revision 1.3 2007/09/11 16:42:02 jgrosseo
32starting modifying AliDCSClient to transparently switch between single and multi query
33first step: same alidcsclient can be used for several queries
34
bee83158 35Revision 1.2 2007/06/09 13:01:09 jgrosseo
36Switching to retrieval of several DCS DPs at a time (multiDPrequest)
37
a038aa70 38Revision 1.1 2006/11/06 14:22:47 jgrosseo
39major update (Alberto)
40o) reading of run parameters from the logbook
41o) online offline naming conversion
42o) standalone DCSclient package
43
eba76848 44Revision 1.6 2006/10/02 16:38:39 jgrosseo
45update (alberto):
46fixed memory leaks
47storing of objects that failed to be stored to the grid before
48interfacing of shuttle status table in daq system
49
2bb7b766 50Revision 1.5 2006/08/15 10:50:00 jgrosseo
51effc++ corrections (alberto)
52
4f0ab988 53Revision 1.4 2006/07/04 14:59:57 jgrosseo
54revision of AliDCSValue: Removed wrapper classes, reduced storage size per value by factor 2
55
45a493ce 56Revision 1.3 2006/06/12 09:11:16 jgrosseo
57coding conventions (Alberto)
58
58bc3020 59Revision 1.2 2006/03/07 07:52:34 hristov
60New version (B.Yordanov)
61
d477ad88 62Revision 1.3 2005/11/17 17:47:34 byordano
63TList changed to TObjArray
64
65Revision 1.2 2005/11/17 14:43:23 byordano
66import to local CVS
67
68Revision 1.1.1.1 2005/10/28 07:33:58 hristov
69Initial import as subdirectory in AliRoot
70
73abe331 71Revision 1.1.1.1 2005/09/12 22:11:40 byordano
72SHUTTLE package
73
74Revision 1.3 2005/08/30 10:53:23 byordano
75some more descriptions added
76
77*/
78
79//
80// This class represents the AliDCSClient.
81// The client used for data retrieval from DCS server.
82// There are two way for retrieving data from the server.
83// 1) asking for DP (DataPoint) - usually changed frequently.
84// 2) asking for Alias (Alias) - alias should be the same through whole
85// experimnet.
86//
87// There are two type of read operations:
88// Asking for single alias/dp or asking for set of aliases/dp
89//
90// In case of ServerError the coresponding error code and
91// error string (description) could be got by GetServerErrorCode() and
92// GetServerErrorString()
93//
94
95#include "AliDCSClient.h"
73abe331 96#include "AliDCSValue.h"
97#include "AliLog.h"
98
58bc3020 99#include <TSocket.h>
d477ad88 100#include <TObjArray.h>
73abe331 101#include <TMap.h>
102#include <TObjString.h>
103#include <TSystem.h>
104
105ClassImp(AliDCSClient)
106
73abe331 107const char* AliDCSClient::fgkBadStateString = "BadState";
73abe331 108const char* AliDCSClient::fgkInvalidParameterString = "InvalidParameter";
73abe331 109const char* AliDCSClient::fgkTimeoutString = "Timeout";
73abe331 110const char* AliDCSClient::fgkBadMessageString = "BadMessage";
73abe331 111const char* AliDCSClient::fgkCommErrorString = "CommunicationError";
73abe331 112const char* AliDCSClient::fgkServerErrorString = "ServerError";
113
58bc3020 114//______________________________________________________________________
73abe331 115AliDCSClient::AliDCSClient(const char* host, Int_t port, UInt_t timeout,
b41b252a 116 Int_t retries, Int_t multiSplit):
117 fSocket(NULL), fHost(host), fPort(port), fTimeout(timeout), fRetries(retries), fMultiSplit(multiSplit),
1790d4b7 118 fServerErrorCode(AliDCSMessage::kNoneError), fServerError(""), fResultErrorCode(0)
73abe331 119{
120 //
121 // host: DCS server host
122 // port: DCS server port
123 // timeout: in case of communication error or socket read/write this
124 // timeout will be used before the next try is made.
125 // retries: the number of retries after which the connection is
126 // is considered as invalid and error is returned.
127 //
73abe331 128}
129
58bc3020 130//______________________________________________________________________
bee83158 131AliDCSClient::~AliDCSClient()
58bc3020 132{
bee83158 133 // destructor
58bc3020 134
bee83158 135 Close();
58bc3020 136}
137
138//______________________________________________________________________
bee83158 139Bool_t AliDCSClient::Connect()
58bc3020 140{
bee83158 141 // connects to the AMANDA server
142
143 Close();
144
145 Int_t tries = 0;
146 while (tries < fRetries)
147 {
148 fSocket = new TSocket(fHost, fPort);
149 if (fSocket->IsValid())
150 {
151 AliDebug(1, Form("Connected to %s:%d", fHost.Data(), fPort));
152 fSocket->SetOption(kNoBlock, 1);
153 return kTRUE;
154 }
58bc3020 155
bee83158 156 AliDebug(1, Form("Connection timeout! tries <%d> ...", tries));
58bc3020 157
73abe331 158 delete fSocket;
bee83158 159 fSocket = NULL;
160
161 gSystem->Sleep(fTimeout);
162 tries ++;
73abe331 163 }
bee83158 164
165 return kFALSE;
73abe331 166}
167
58bc3020 168//______________________________________________________________________
169Int_t AliDCSClient::SendBuffer(const char* buffer, Int_t size)
170{
171// send buffer containing the message to the DCS server
73abe331 172
173 Int_t sentSize = 0;
174 Int_t tries = 0;
175
176 while (sentSize < size && tries < fRetries) {
177
178 Int_t sResult = fSocket->Select(TSocket::kWrite, fTimeout);
179
180 if (sResult == 0) {
181 AliDebug(1, Form("Timeout! tries <%d> ...", tries));
182 tries ++;
183 continue;
184
185 } else if (sResult < 0) {
186 AliDebug(1, Form("Communication error <%d>!",
187 fSocket->GetErrorCode()));
188 return AliDCSClient::fgkCommError;
189 }
190
191 sResult = fSocket->SendRaw(buffer + sentSize, size - sentSize,
192 kDontBlock);
193
194 if (sResult > 0) {
195 sentSize += sResult;
196 } else {
197 AliDebug(1, Form("Communication error <%d>!",
198 fSocket->GetErrorCode()));
199 return AliDCSClient::fgkCommError;
200 }
201 }
202
203 if (tries == fRetries) {
204 return AliDCSClient::fgkTimeout;
205 }
206
207 return sentSize;
208}
209
58bc3020 210//______________________________________________________________________
211Int_t AliDCSClient::ReceiveBuffer(char* buffer, Int_t size)
212{
213// Receive message from the DCS server and fill buffer
73abe331 214
215 Int_t receivedSize = 0;
216 Int_t tries = 0;
217
218 while (receivedSize < size && tries < fRetries) {
219
220 Int_t sResult = fSocket->Select(TSocket::kRead, fTimeout);
221
222 if (sResult == 0) {
223 AliDebug(1, Form("Timeout! tries <%d> ...", tries));
224 tries ++;
225 continue;
226
227 } else if (sResult < 0) {
228 AliDebug(1, Form("Communication error <%d>",
229 fSocket->GetErrorCode()));
230 return AliDCSClient::fgkCommError;
231 }
232
233 sResult = fSocket->RecvRaw(buffer + receivedSize,
234 size - receivedSize, kDontBlock);
235
236 if (sResult > 0) {
237 receivedSize += sResult;
238 } else {
239 AliDebug(1, Form("Communication error <%d>",
240 fSocket->GetErrorCode()));
241 return AliDCSClient::fgkCommError;
242 }
243 }
244
245 if (tries == fRetries) {
246 return AliDCSClient::fgkTimeout;
247 }
248
249 return receivedSize;
250}
251
58bc3020 252//______________________________________________________________________
253Int_t AliDCSClient::SendMessage(AliDCSMessage& message)
254{
255// send message to the DCS server
73abe331 256
257 message.StoreToBuffer();
258
259 AliDebug(2, "Sending message.\n");
260 message.Print();
261
262 return SendBuffer(message.GetMessage(), message.GetMessageSize());
263}
264
58bc3020 265//______________________________________________________________________
4e3d5771 266Int_t AliDCSClient::ReceiveMessage(AliDCSMessage& message)
58bc3020 267{
268// receive message from the DCS server
73abe331 269
270 char header[HEADER_SIZE];
271
272 Int_t sResult;
273
274 if ((sResult = ReceiveBuffer(header, HEADER_SIZE)) < 0) {
275 AliDebug(1, Form("Can't receive message header! Reason: %s",
276 GetErrorString(sResult)));
277 return sResult;
278 }
279
280 if (!message.SetRawHeader(header)) {
281 return AliDCSClient::fgkBadMessage;
282 }
283
284 if ((sResult = ReceiveBuffer(message.GetBody(),
285 message.GetBodySize())) < 0) {
286
287 AliDebug(1, Form("Can't receive message body! Reason: %s",
288 GetErrorString(sResult)));
289 return sResult;
290 }
291
292 message.LoadFromBuffer();
293
294 AliDebug(2, "Message received.");
295 message.Print();
296
297 return HEADER_SIZE + sResult;
298}
299
58bc3020 300//______________________________________________________________________
73abe331 301Int_t AliDCSClient::GetValues(AliDCSMessage::RequestType reqType,
2bb7b766 302 const char* reqString, UInt_t startTime, UInt_t endTime, TObjArray* result)
73abe331 303{
bee83158 304 // get array of DCS values from the DCS server
305 // reqString: alias name
306 // startTime, endTime: start time and end time of the query
307 // result: contains the array of retrieved AliDCSValue's
58bc3020 308
bee83158 309 Connect();
310
73abe331 311 if (!IsConnected()) {
312 AliError("Not connected!");
313 return AliDCSClient::fgkBadState;
314 }
315
bee83158 316 Int_t sResult = -1;
73abe331 317 AliDCSMessage requestMessage;
2bb7b766 318 requestMessage.CreateRequestMessage(reqType, startTime, endTime,
73abe331 319 reqString);
320
321 if ((sResult = SendMessage(requestMessage)) < 0) {
322 AliError(Form("Can't send request message! Reason: %s",
323 GetErrorString(sResult)));
324 Close();
325 return sResult;
2bb7b766 326 }
327
4e3d5771 328 Int_t receivedValues = 0;
329
330 while (1)
331 {
332 Int_t tmp = 0;
333 sResult = ReceiveValueSet(result, tmp);
334 if (sResult <= 0)
335 break;
336 receivedValues += sResult;
337 }
2bb7b766 338
73abe331 339 Close();
340
4e3d5771 341 return receivedValues;
73abe331 342}
343
58bc3020 344//______________________________________________________________________
a038aa70 345TMap* AliDCSClient::GetValues(AliDCSMessage::RequestType reqType,
346 const TSeqCollection* list, UInt_t startTime, UInt_t endTime,
347 Int_t startIndex, Int_t endIndex)
73abe331 348{
a038aa70 349 // get array of DCS values from the DCS server
350 // list, startTime, endTime: list of dp/alias names, start time and end time of the query
351 //
352 // Result: map containing the array of alias names. It will be filled with
353 // the values retrieved for each alias
58bc3020 354
b41b252a 355 TMap* result = new TMap;
356 result->SetOwner(1);
73abe331 357
a038aa70 358 if (endIndex < 0 || endIndex > list->GetEntries())
359 endIndex = list->GetEntries();
73abe331 360
b41b252a 361 for (Int_t subsetBegin = startIndex; subsetBegin < endIndex; subsetBegin += fMultiSplit)
a038aa70 362 {
4e3d5771 363 Connect();
364
365 if (!IsConnected())
b41b252a 366 {
4e3d5771 367 AliError("Not connected!");
368 delete result;
1790d4b7 369 fResultErrorCode = fgkBadState;
4e3d5771 370 return 0;
371 }
b41b252a 372
373 Int_t subsetEnd = subsetBegin + fMultiSplit;
374 if (subsetEnd > endIndex)
375 subsetEnd = endIndex;
376
377 AliDCSMessage requestMessage;
378 if (fMultiSplit == 1)
379 {
4e3d5771 380 // single dp request
381
382 TObjString* aRequest = (TObjString*) list->At(subsetBegin);
383 requestMessage.CreateRequestMessage(reqType, startTime, endTime, aRequest->String());
b41b252a 384 }
385 else
386 {
4e3d5771 387 // multi dp request
388
389 requestMessage.CreateMultiRequestMessage(reqType,
390 startTime, endTime);
b41b252a 391
392 for (Int_t i=subsetBegin; i<subsetEnd; i++)
393 {
394 TObjString* aRequest = (TObjString*) list->At(i);
395 if (!requestMessage.AddRequestString(aRequest->String()))
1790d4b7 396 {
397 delete result;
398 fResultErrorCode = fgkBadMessage;
b41b252a 399 return 0;
1790d4b7 400 }
4e3d5771 401 }
402 }
403
404 if ((fResultErrorCode = SendMessage(requestMessage)) < 0)
405 {
406 AliError(Form("Can't send request message! Reason: %s",
407 GetErrorString(fResultErrorCode)));
408 Close();
409 delete result;
410 return 0;
b41b252a 411 }
4e3d5771 412
413 while (1)
414 {
415 TObjArray* resultSet = new TObjArray();
b41b252a 416 resultSet->SetOwner(1);
73abe331 417
4e3d5771 418 Int_t ownerIndex = -1;
419 fResultErrorCode = ReceiveValueSet(resultSet, ownerIndex);
73abe331 420
4e3d5771 421 if (fResultErrorCode < 0)
422 {
423 AliError("Can't get values");
73abe331 424
4e3d5771 425 delete resultSet;
426 result->DeleteValues();
427 delete result;
428 return 0;
429 }
73abe331 430
4e3d5771 431 if (ownerIndex < 0)
432 {
433 // no more values
434 delete resultSet;
435 break;
436 }
73abe331 437
4e3d5771 438 TObjString* aRequest = (TObjString*) list->At(ownerIndex + subsetBegin);
439 //AliInfo(Form("Received %d values for entry %d, that is %s", resultSet->GetEntries(),
440 // ownerIndex + subsetBegin, aRequest->String().Data()));
441
442 TObjArray* target = dynamic_cast<TObjArray*> (result->GetValue(aRequest));
443 if (target)
444 {
445 target->AddAll(resultSet);
446 //AliInfo(Form("Now we have %d entries", target->GetEntries()));
447 resultSet->SetOwner(0);
448 delete resultSet;
449 }
450 else
451 result->Add(aRequest, resultSet);
452 }
73abe331 453
4e3d5771 454 Close();
73abe331 455
e1c93495 456 Int_t nValues = 0;
457 TObjArray* example = (TObjArray*) result->GetValue(list->At(subsetBegin));
458 if (example)
459 nValues = example->GetEntries();
4e3d5771 460 AliInfo(Form("Retrieved entries %d..%d (total %d..%d); E.g. %s has %d values collected",
e1c93495 461 subsetBegin, subsetEnd-1, startIndex, endIndex-1, list->At(subsetBegin)->GetName(), nValues));
73abe331 462 }
463
4e3d5771 464 return result;
465}
466
467//______________________________________________________________________
468Int_t AliDCSClient::ReceiveValueSet(TObjArray* result, Int_t& ownerIndex)
469{
470 // receive set of values
73abe331 471
4e3d5771 472 AliDCSMessage message;
473 Int_t sResult = ReceiveMessage(message);
474 if (sResult < 0)
475 {
476 AliError(Form("Can't receive message! Reason: %s", GetErrorString(sResult)));
477 return sResult;
478 }
73abe331 479
4e3d5771 480 if (message.GetType() == AliDCSMessage::kResultSet)
481 {
482 // this was the last message
483 ownerIndex = message.GetOwnerIndex();
484 if (ownerIndex < 0)
485 return 0;
73abe331 486
4e3d5771 487 sResult = message.GetValues(result);
73abe331 488
4e3d5771 489 AliDCSMessage nextMessage;
490 nextMessage.CreateNextMessage();
2bb7b766 491
4e3d5771 492 if ((fResultErrorCode = SendMessage(nextMessage)) < 0)
493 {
494 AliError(Form("Can't send next message! Reason: %s",
495 GetErrorString(fResultErrorCode)));
496 Close();
497 return AliDCSClient::fgkCommError;
498 }
73abe331 499
4e3d5771 500 return sResult;
501 }
502 else if (message.GetType() == AliDCSMessage::kError)
503 {
504 fServerErrorCode = message.GetErrorCode();
505 fServerError = message.GetErrorString();
73abe331 506
4e3d5771 507 return AliDCSClient::fgkServerError;
508 }
73abe331 509
4e3d5771 510 AliError("Bad message type received!");
511 return AliDCSClient::fgkBadMessage;
73abe331 512}
4e3d5771 513
58bc3020 514//______________________________________________________________________
73abe331 515Int_t AliDCSClient::GetDPValues(const char* dpName, UInt_t startTime,
2bb7b766 516 UInt_t endTime, TObjArray* result)
73abe331 517{
518 //
519 // Reads a values from the server which correspond to this
520 // DataPoint (dpName) in time interval (startTime - endTime).
521 // result: Collection of AliDCSValue which contains the read values.
522 //
523 // Returns:
524 // If >= 0 , the number of values read.
525 // if < 0, the error code which has occured during the read.
526 //
527
528 return GetValues(AliDCSMessage::kDPName,
529 dpName, startTime, endTime, result);
530}
531
58bc3020 532//______________________________________________________________________
73abe331 533Int_t AliDCSClient::GetAliasValues(const char* alias, UInt_t startTime,
2bb7b766 534 UInt_t endTime, TObjArray* result)
73abe331 535{
536 //
537 // Reads a values from the server which correspond to this
538 // alias (alias) in time interval (startTime - endTime).
539 // result: Collection of AliDCSValue which contains the read values.
540 //
541 // Returns:
542 // If >= 0 , the number of values read.
543 // if < 0, the error code which has occured during the read.
544 //
545
546 return GetValues(AliDCSMessage::kAlias,
547 alias, startTime, endTime, result);
548}
549
58bc3020 550//______________________________________________________________________
a038aa70 551TMap* AliDCSClient::GetDPValues(const TSeqCollection* dpList, UInt_t startTime, UInt_t endTime,
552 Int_t startIndex, Int_t endIndex)
73abe331 553{
554 //
a038aa70 555 // For every entry (fron startIndex to endIndex) in dpList (which must be TObjString)
73abe331 556 // reads a valueSet. The key represents particular DataPoint to be read.
557 // For all DataPoints time interval (startTime - endTime) is used.
558 // After the read, the correspoding value for every key is a
d477ad88 559 // TObjArray - collection of AliDCSValue, or result is an empty map in
73abe331 560 // case of error.
561 //
562 // Returns:
a038aa70 563 // TMap of results, 0 in case of failure
73abe331 564 //
565
a038aa70 566 return GetValues(AliDCSMessage::kDPName, dpList, startTime, endTime, startIndex, endIndex);
73abe331 567}
568
58bc3020 569//______________________________________________________________________
a038aa70 570TMap* AliDCSClient::GetAliasValues(const TSeqCollection* aliasList, UInt_t startTime, UInt_t endTime,
571 Int_t startIndex, Int_t endIndex)
73abe331 572{
573 //
a038aa70 574 // For every entry (fron startIndex to endIndex) in dpList (which must be TObjString)
73abe331 575 // reads a valueSet. The key represents particular Alias to be read.
576 // For all aliases time interval (startTime - endTime) is used.
577 // After the read, the correspoding value for every key is a
d477ad88 578 // TObjArray - collection of AliDCSValue, or result is an empty map in
73abe331 579 // case of error.
580 //
581 // Returns:
a038aa70 582 // TMap of results, 0 in case of failure
73abe331 583 //
584
a038aa70 585 return GetValues(AliDCSMessage::kAlias, aliasList, startTime, endTime, startIndex, endIndex);
73abe331 586}
587
58bc3020 588//______________________________________________________________________
589Bool_t AliDCSClient::IsConnected()
590{
73abe331 591 //
592 // Returns kTRUE if there is a valid connection to the server.
593 //
594
595 if (fSocket) {
596 return fSocket->IsValid();
597 }
598
599 return kFALSE;
600}
601
58bc3020 602//______________________________________________________________________
603void AliDCSClient::Close()
604{
73abe331 605 //
606 // Close the connection.
607 //
608
609 if (fSocket) {
610 fSocket->Close();
bee83158 611 delete fSocket;
612 fSocket = 0;
73abe331 613 }
614}
615
58bc3020 616//______________________________________________________________________
617const char* AliDCSClient::GetErrorString(Int_t code)
618{
73abe331 619 //
620 // Returns a short string describing the error code.
621 // code: the error code.
622 //
623
624
625 switch (code) {
626 case AliDCSClient::fgkBadState:
627 return AliDCSClient::fgkBadStateString;
628
629 case AliDCSClient::fgkInvalidParameter:
630 return AliDCSClient::fgkInvalidParameterString;
631
632 case AliDCSClient::fgkTimeout:
633 return AliDCSClient::fgkTimeoutString;
634
635 case AliDCSClient::fgkBadMessage:
636 return AliDCSClient::fgkBadMessageString;
637
638 case AliDCSClient::fgkCommError:
639 return AliDCSClient::fgkCommErrorString;
640
641 case AliDCSClient::fgkServerError:
642 return AliDCSClient::fgkServerErrorString;
643
644 default:
645 AliErrorGeneral("AliDCSClient::GetErrorString",
646 "Unknown error code!");
647 return "UnknownCode";
648 }
649}
650