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