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