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