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