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