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