]>
Commit | Line | Data |
---|---|---|
742ae1c4 | 1 | // $Id: AliHLTTriggerCounterComponent.cxx 43071 2010-08-25 08:41:44Z richterm $ |
2 | /************************************************************************** | |
3 | * This file is property of and copyright by the ALICE HLT Project * | |
4 | * ALICE Experiment at CERN, All rights reserved. * | |
5 | * * | |
6 | * Primary Authors: Artur Szostak <artursz@iafrica.com> * | |
7 | * for The ALICE HLT Project. * | |
8 | * * | |
9 | * Permission to use, copy, modify and distribute this software and its * | |
10 | * documentation strictly for non-commercial purposes is hereby granted * | |
11 | * without fee, provided that the above copyright notice appears in all * | |
12 | * copies and that both the copyright notice and this permission notice * | |
13 | * appear in the supporting documentation. The authors make no claims * | |
14 | * about the suitability of this software for any purpose. It is * | |
15 | * provided "as is" without express or implied warranty. * | |
16 | **************************************************************************/ | |
17 | ||
18 | /// @file AliHLTTriggerCounterComponent.cxx | |
19 | /// @author Artur Szostak <artursz@iafrica.com> | |
20 | /// @date 3 Nov 2010 | |
21 | /// @brief Implementation of the AliHLTTriggerCounterComponent class. | |
22 | /// | |
23 | /// The AliHLTTriggerCounterComponent is used to count HLT input and output | |
24 | /// triggers based on the global trigger decisions coming from the global HLT | |
25 | /// trigger component. | |
26 | ||
27 | #include "AliHLTTriggerCounterComponent.h" | |
28 | #include "AliHLTTriggerDecision.h" | |
29 | #include "AliHLTGlobalTriggerDecision.h" | |
30 | #include "AliHLTTriggerCounters.h" | |
31 | #include "AliHLTCTPData.h" | |
32 | #include "AliCDBManager.h" | |
33 | #include "AliCDBStorage.h" | |
34 | #include "AliCDBEntry.h" | |
35 | #include "TObjString.h" | |
36 | #include "TROOT.h" | |
37 | #include <cstring> | |
38 | #include <cassert> | |
39 | ||
40 | ClassImp(AliHLTTriggerCounterComponent) | |
41 | ||
42 | const char* AliHLTTriggerCounterComponent::fgkConfigCDBPath = "HLT/ConfigHLT/HLTTriggerCounter"; | |
43 | TMap AliHLTTriggerCounterComponent::fgInitialCounterConfig(TCollection::kInitHashTableCapacity, 2); | |
44 | ||
45 | ||
46 | AliHLTTriggerCounterComponent::AliHLTTriggerCounterComponent() : | |
47 | AliHLTProcessor(), | |
48 | fOutputMultiplier(0), | |
49 | fInputCounters(), | |
50 | fOutputCounters(), | |
51 | fInputTimes(TCollection::kInitHashTableCapacity, 2), | |
52 | fOutputTimes(TCollection::kInitHashTableCapacity, 2), | |
53 | fLastPublishTime(-1), | |
54 | fPublishPeriod(-1) | |
55 | { | |
56 | // Default constructor. | |
57 | ||
58 | fInputTimes.SetOwner(kTRUE); | |
59 | fOutputTimes.SetOwner(kTRUE); | |
60 | } | |
61 | ||
62 | ||
63 | AliHLTTriggerCounterComponent::~AliHLTTriggerCounterComponent() | |
64 | { | |
65 | // Default destructor. | |
66 | ||
67 | } | |
68 | ||
69 | ||
70 | const char* AliHLTTriggerCounterComponent::GetComponentID() | |
71 | { | |
72 | // Returns the component ID. | |
73 | return "HLTTriggerCounter"; | |
74 | } | |
75 | ||
76 | ||
77 | void AliHLTTriggerCounterComponent::GetInputDataTypes(AliHLTComponentDataTypeList& list) | |
78 | { | |
79 | // Returns the list of input data types that are handled. | |
80 | list.push_back(kAliHLTDataTypeGlobalTrigger); | |
81 | list.push_back(kAliHLTDataTypeTriggerDecision); | |
82 | } | |
83 | ||
84 | ||
85 | AliHLTComponentDataType AliHLTTriggerCounterComponent::GetOutputDataType() | |
86 | { | |
87 | // Returns kAliHLTMultipleDataType. | |
88 | return kAliHLTMultipleDataType; | |
89 | } | |
90 | ||
91 | ||
92 | int AliHLTTriggerCounterComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& list) | |
93 | { | |
94 | // Returns the list of output data block types generated. | |
95 | list.push_back(kAliHLTDataTypeInputTriggerCounters); | |
96 | list.push_back(kAliHLTDataTypeOutputTriggerCounters); | |
97 | return int(list.size()); | |
98 | } | |
99 | ||
100 | ||
101 | void AliHLTTriggerCounterComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier) | |
102 | { | |
103 | // Returns the buffer size requirements. | |
104 | constBase = 1024*16; | |
105 | inputMultiplier = fOutputMultiplier; | |
106 | } | |
107 | ||
108 | ||
109 | AliHLTComponent* AliHLTTriggerCounterComponent::Spawn() | |
110 | { | |
111 | // Creates a new instance of the component. | |
112 | return new AliHLTTriggerCounterComponent; | |
113 | } | |
114 | ||
115 | ||
116 | Int_t AliHLTTriggerCounterComponent::DoInit(int argc, const char** argv) | |
117 | { | |
118 | // Initialises the data checker component from the command line. | |
119 | ||
120 | HLTInfo("Starting HLT trigger counter component."); | |
121 | ||
122 | const char* configFileName = NULL; | |
123 | fInputCounters.Clear(); | |
124 | fOutputCounters.Clear(); | |
125 | fInputTimes.Clear(); | |
126 | fOutputTimes.Clear(); | |
127 | fLastPublishTime = -1; | |
128 | fPublishPeriod = -1; | |
129 | bool loadCDBObject = true; | |
130 | ||
131 | for (int i = 0; i < argc; ++i) | |
132 | { | |
133 | if (strcmp(argv[i], "-config") == 0) | |
134 | { | |
135 | if (configFileName != NULL) | |
136 | { | |
137 | HLTWarning("The configuration macro was already specified." | |
138 | " Will replace previous value given by -config." | |
139 | ); | |
140 | } | |
141 | if (argc <= i+1) | |
142 | { | |
143 | HLTError("The configuration macro filename was not specified." ); | |
144 | return -EINVAL; | |
145 | } | |
146 | configFileName = argv[i+1]; | |
147 | i++; | |
148 | continue; | |
149 | } | |
150 | ||
151 | if (strcmp(argv[i], "-publishperiod") == 0) | |
152 | { | |
153 | if (fPublishPeriod != -1) | |
154 | { | |
155 | HLTWarning("The publish period was already specified." | |
156 | " Will replace previous value given by -publishperiod." | |
157 | ); | |
158 | } | |
159 | if (argc <= i+1) | |
160 | { | |
161 | HLTError("Publish period value was not specified for -publishperiod."); | |
162 | return -EINVAL; | |
163 | } | |
164 | char* err = NULL; | |
165 | errno = 0; | |
166 | double tmpnum = strtod(argv[i+1], &err); | |
167 | if (err == NULL or *err != '\0') | |
168 | { | |
169 | HLTError("Cannot convert '%s' to a floating point value.", argv[i+1]); | |
170 | return false; | |
171 | } | |
172 | if (errno == ERANGE) | |
173 | { | |
174 | HLTError("The specified value '%s' is out of range.", argv[i+1]); | |
175 | return false; | |
176 | } | |
177 | fPublishPeriod = (tmpnum < 0 ? -1 : tmpnum); | |
178 | i++; | |
179 | continue; | |
180 | } | |
181 | ||
182 | if (strcmp(argv[i], "-skipcdb") == 0) | |
183 | { | |
184 | loadCDBObject = false; | |
185 | continue; | |
186 | } | |
187 | ||
188 | HLTError("Unknown option '%s'.", argv[i]); | |
189 | return -EINVAL; | |
190 | } // for loop | |
191 | ||
192 | if (configFileName != NULL) | |
193 | { | |
194 | int result = LoadConfigFromFile(configFileName); | |
195 | if (result != 0) return result; | |
196 | } | |
197 | else if (loadCDBObject) | |
198 | { | |
199 | int result = LoadConfigFromCDB(fgkConfigCDBPath); | |
200 | if (result != 0) return result; | |
201 | } | |
202 | ||
203 | return 0; | |
204 | } | |
205 | ||
206 | ||
207 | Int_t AliHLTTriggerCounterComponent::DoDeinit() | |
208 | { | |
209 | // Cleans up the component. | |
210 | ||
211 | HLTInfo("Stopping HLT trigger counter component."); | |
212 | fInputCounters.Clear(); | |
213 | fOutputCounters.Clear(); | |
214 | fInputTimes.Clear(); | |
215 | fOutputTimes.Clear(); | |
216 | return 0; | |
217 | } | |
218 | ||
219 | ||
220 | int AliHLTTriggerCounterComponent::DoEvent(const AliHLTComponentEventData& /*evtData*/, AliHLTComponentTriggerData& /*trigData*/) | |
221 | { | |
222 | // Finds the global trigger objects and adds the triggers to the counters. | |
223 | ||
224 | fInputCounters.UpdateTimeStamp(); | |
225 | fOutputCounters.UpdateTimeStamp(); | |
226 | Double_t inputTime = fInputCounters.TimeStamp().AsDouble(); | |
227 | Double_t outputTime = fOutputCounters.TimeStamp().AsDouble(); | |
228 | ||
229 | const TObject* obj = GetFirstInputObject(kAliHLTDataTypeGlobalTrigger, "AliHLTGlobalTriggerDecision"); | |
230 | while (obj != NULL) | |
231 | { | |
232 | const AliHLTGlobalTriggerDecision* decision = dynamic_cast<const AliHLTGlobalTriggerDecision*>(obj); | |
233 | if (decision != NULL) | |
234 | { | |
235 | HLTDebug("Received trigger decision object of type AliHLTGlobalTriggerDecision."); | |
236 | // Tokenise the global trigger description string which contains a | |
237 | // list of the triggers that were fired and increment the corresponding | |
238 | // counters. | |
239 | TString names = decision->Description(); | |
240 | Ssiz_t from = 0; | |
241 | TString token; | |
242 | while (names.Tokenize(token, from, ",")) | |
243 | { | |
244 | TObject* cntobj = fOutputCounters.FindObject(token.Data()); | |
245 | if (cntobj != NULL) | |
246 | { | |
247 | AliHLTTriggerCounters::AliCounter* counter = static_cast<AliHLTTriggerCounters::AliCounter*>(cntobj); | |
248 | counter->Increment(); | |
249 | UpdateCounterRate( | |
250 | counter, | |
251 | static_cast<AliRingBuffer*>( fOutputTimes.FindObject(token.Data()) ), | |
252 | outputTime | |
253 | ); | |
254 | } | |
255 | else | |
256 | { | |
257 | fOutputCounters.Add(token.Data(), "New trigger output counter found during the run.", 1, 1); | |
258 | fOutputTimes.Add(new AliRingBuffer(token.Data(), outputTime)); | |
259 | } | |
260 | } | |
261 | ||
262 | // Now add the CTP triggers. | |
263 | const AliHLTCTPData* ctp = dynamic_cast<const AliHLTCTPData*>( decision->InputObjects().FindObject("AliHLTCTPData") ); | |
264 | if (ctp != NULL) | |
265 | { | |
266 | const TArrayL64& counters = ctp->Counters(); | |
267 | for (Int_t i = 0; i < counters.GetSize(); ++i) | |
268 | { | |
269 | const char* ctpName = ctp->Name(i); | |
270 | // Check if CTP counter is initialised and skip if not. | |
271 | if (strcmp(ctpName, "AliHLTReadoutList") == 0 and counters[i] == 0) continue; | |
272 | TObject* cntobj = fInputCounters.FindObject(ctpName); | |
273 | if (cntobj != NULL) | |
274 | { | |
275 | AliHLTTriggerCounters::AliCounter* counter = static_cast<AliHLTTriggerCounters::AliCounter*>(cntobj); | |
276 | counter->Counter(counters[i]); | |
277 | UpdateCounterRate( | |
278 | counter, | |
279 | static_cast<AliRingBuffer*>( fInputTimes.FindObject(ctpName) ), | |
280 | inputTime | |
281 | ); | |
282 | } | |
283 | else | |
284 | { | |
285 | fInputCounters.Add( | |
286 | ctpName, | |
287 | "New CTP trigger input counter found during the run.", | |
288 | Double_t(counters[i]), | |
289 | counters[i] | |
290 | ); | |
291 | fInputTimes.Add(new AliRingBuffer(ctpName, inputTime)); | |
292 | } | |
293 | } | |
294 | } | |
295 | ||
296 | // Add the list of input triggers. | |
297 | for (Int_t i = 0; i < decision->NumberOfTriggerInputs(); ++i) | |
298 | { | |
299 | const AliHLTTriggerDecision* input = decision->TriggerInput(i); | |
300 | if (input == NULL or not input->Result()) continue; | |
301 | TObject* cntobj = fInputCounters.FindObject(input->Name()); | |
302 | if (cntobj != NULL) | |
303 | { | |
304 | AliHLTTriggerCounters::AliCounter* counter = static_cast<AliHLTTriggerCounters::AliCounter*>(cntobj); | |
305 | counter->Increment(); | |
306 | counter->SetBit(BIT(14), true); // mark counter as updated | |
307 | UpdateCounterRate( | |
308 | counter, | |
309 | static_cast<AliRingBuffer*>( fInputTimes.FindObject(input->Name()) ), | |
310 | inputTime | |
311 | ); | |
312 | } | |
313 | else | |
314 | { | |
315 | fInputCounters.Add(input->Name(), "New trigger input counter found during the run.", 1, 1); | |
316 | fInputCounters.GetCounterN(fInputCounters.NumberOfCounters()-1).SetBit(BIT(14), true); // mark counter as updated | |
317 | fInputTimes.Add(new AliRingBuffer(input->Name(), inputTime)); | |
318 | } | |
319 | } | |
320 | } | |
321 | obj = GetNextInputObject(); | |
322 | } | |
323 | ||
324 | // Look for the individual trigger decision blocks to add if they are available. | |
325 | obj = GetFirstInputObject(kAliHLTDataTypeTriggerDecision, "AliHLTTriggerDecision"); | |
326 | while (obj != NULL) | |
327 | { | |
328 | const AliHLTTriggerDecision* decision = dynamic_cast<const AliHLTTriggerDecision*>(obj); | |
329 | if (decision != NULL and decision->Result()) | |
330 | { | |
331 | HLTDebug("Received trigger decision object of type AliHLTTriggerDecision."); | |
332 | TObject* cntobj = fInputCounters.FindObject(decision->Name()); | |
333 | if (cntobj != NULL) | |
334 | { | |
335 | AliHLTTriggerCounters::AliCounter* counter = static_cast<AliHLTTriggerCounters::AliCounter*>(cntobj); | |
336 | if (not counter->TestBit(BIT(14))) // Only update if marked as not updated. | |
337 | { | |
338 | counter->Increment(); | |
339 | UpdateCounterRate( | |
340 | counter, | |
341 | static_cast<AliRingBuffer*>( fInputTimes.FindObject(decision->Name()) ), | |
342 | inputTime | |
343 | ); | |
344 | } | |
345 | } | |
346 | else | |
347 | { | |
348 | fInputCounters.Add(decision->Name(), "New trigger input counter found during the run.", 1, 1); | |
349 | fInputTimes.Add(new AliRingBuffer(decision->Name(), inputTime)); | |
350 | } | |
351 | } | |
352 | obj = GetNextInputObject(); | |
353 | } | |
354 | // Reset bit 14 which is used temporarily to mark updated counters. | |
355 | for (UInt_t i = 0; i < fInputCounters.NumberOfCounters(); ++i) | |
356 | { | |
357 | fInputCounters.GetCounterN(i).SetBit(BIT(14), false); | |
358 | } | |
359 | ||
360 | Double_t now = TTimeStamp(); | |
361 | if (fLastPublishTime == -1) fLastPublishTime = now; | |
362 | if (now - fLastPublishTime > fPublishPeriod) | |
363 | { | |
364 | fLastPublishTime = now; | |
365 | bool inputCountersNotPushed = PushBack(&fInputCounters, kAliHLTDataTypeInputTriggerCounters) != 0; | |
366 | bool outputCountersNotPushed = PushBack(&fOutputCounters, kAliHLTDataTypeOutputTriggerCounters) != 0; | |
367 | if (inputCountersNotPushed or outputCountersNotPushed) | |
368 | { | |
369 | fOutputMultiplier = (fOutputMultiplier == 0 ? 1 : fOutputMultiplier*2); | |
370 | return -ENOSPC; | |
371 | } | |
372 | } | |
373 | return 0; | |
374 | } | |
375 | ||
376 | ||
377 | void AliHLTTriggerCounterComponent::UpdateCounterRate( | |
378 | AliHLTTriggerCounters::AliCounter* counter, AliRingBuffer* timeBuf, Double_t newTime | |
379 | ) | |
380 | { | |
381 | // Updates the counter's rate value. | |
382 | ||
383 | assert(timeBuf != NULL); | |
384 | Double_t dt = newTime - timeBuf->OldestTime(); | |
385 | Double_t rate = (dt != 0 ? (counter->Counter() - timeBuf->OldestCounter()) / dt : 0.); | |
386 | counter->Rate(rate); | |
387 | timeBuf->Increment(counter->Counter(), newTime); | |
388 | } | |
389 | ||
390 | ||
391 | int AliHLTTriggerCounterComponent::LoadConfigFromCDB(const char* cdbPath) | |
392 | { | |
393 | // Loads the initial configuration of counters from the given CDB path. | |
394 | ||
395 | HLTDebug("Trying to load trigger menu from '%s'.", cdbPath); | |
396 | ||
397 | if (AliCDBManager::Instance() == NULL) | |
398 | { | |
399 | HLTError("CDB manager object not found."); | |
400 | return -EIO; | |
401 | } | |
402 | AliCDBStorage* store = AliCDBManager::Instance()->GetDefaultStorage(); | |
403 | if (store == NULL) | |
404 | { | |
405 | HLTError("Could not get the the default storage for the CDB."); | |
406 | return -EIO; | |
407 | } | |
408 | Int_t version = store->GetLatestVersion(cdbPath, GetRunNo()); | |
409 | if (version < 0) | |
410 | { | |
411 | HLTError("Could not find an entry in the CDB for \"%s\".", cdbPath); | |
412 | return -EIO; | |
413 | } | |
414 | Int_t subVersion = store->GetLatestSubVersion(cdbPath, GetRunNo(), version); | |
415 | AliCDBEntry* entry = AliCDBManager::Instance()->Get(cdbPath, GetRunNo(), version, subVersion); | |
416 | if (entry == NULL) | |
417 | { | |
418 | HLTError("Could not get the CDB entry for \"%s\".", cdbPath); | |
419 | return -EIO; | |
420 | } | |
421 | TObject* obj = entry->GetObject(); | |
422 | if (obj == NULL) | |
423 | { | |
424 | HLTError("Configuration object for \"%s\" is missing.", cdbPath); | |
425 | return -ENOENT; | |
426 | } | |
427 | if (obj->IsA() != TMap::Class()) | |
428 | { | |
429 | HLTError("Wrong type for configuration object in \"%s\". Found a %s but we expect a TMap.", | |
430 | cdbPath, obj->ClassName() | |
431 | ); | |
432 | return -EPROTO; | |
433 | } | |
434 | TMap* counters = static_cast<TMap*>(obj); | |
435 | SetInitialCounters(counters); | |
436 | return 0; | |
437 | } | |
438 | ||
439 | ||
440 | int AliHLTTriggerCounterComponent::LoadConfigFromFile(const char* configFile) | |
441 | { | |
442 | // Loads the initial configuration of counters from the given configuration file. | |
443 | ||
444 | TString cmd = ".x "; | |
445 | cmd += configFile; | |
446 | gROOT->ProcessLine(cmd); | |
447 | SetInitialCounters(&fgInitialCounterConfig); | |
448 | return 0; | |
449 | } | |
450 | ||
451 | ||
452 | void AliHLTTriggerCounterComponent::SetInitialCounters(const TMap* counters) | |
453 | { | |
454 | // Sets the initial counter values from TMap objects containing name description pairs. | |
455 | ||
456 | Double_t now = TTimeStamp(); | |
457 | TMapIter next(counters); | |
458 | TObject* key = NULL; | |
459 | while ((key = next()) != NULL) | |
460 | { | |
461 | TObject* value = counters->GetValue(key); | |
462 | if (value == NULL) continue; | |
463 | if (key->TestBit(BIT(14))) | |
464 | { | |
465 | fOutputCounters.Add(key->GetName(), value->GetName()); | |
466 | fOutputTimes.Add(new AliRingBuffer(key->GetName(), now)); | |
467 | } | |
468 | else | |
469 | { | |
470 | fInputCounters.Add(key->GetName(), value->GetName()); | |
471 | fInputTimes.Add(new AliRingBuffer(key->GetName(), now)); | |
472 | } | |
473 | } | |
474 | } |