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