]>
Commit | Line | Data |
---|---|---|
1b9a175e | 1 | /************************************************************************** |
2 | * This file is property of and copyright by the ALICE HLT Project * | |
3 | * ALICE Experiment at CERN, All rights reserved. * | |
4 | * * | |
5 | * Primary Authors: Artur Szostak <artursz@iafrica.com> * | |
6 | * for The ALICE HLT Project. * | |
7 | * * | |
8 | * Permission to use, copy, modify and distribute this software and its * | |
9 | * documentation strictly for non-commercial purposes is hereby granted * | |
10 | * without fee, provided that the above copyright notice appears in all * | |
11 | * copies and that both the copyright notice and this permission notice * | |
12 | * appear in the supporting documentation. The authors make no claims * | |
13 | * about the suitability of this software for any purpose. It is * | |
14 | * provided "as is" without express or implied warranty. * | |
15 | **************************************************************************/ | |
16 | ||
17 | /// @file AliHLTGlobalTriggerComponent.cxx | |
18 | /// @author Artur Szostak <artursz@iafrica.com> | |
19 | /// @date 26 Nov 2008 | |
20 | /// @brief Implementation of the AliHLTGlobalTriggerComponent component class. | |
21 | /// | |
22 | /// The AliHLTGlobalTriggerComponentComponent class applies the global HLT trigger to all | |
23 | /// trigger information produced by components deriving from AliHLTTrigger. | |
24 | ||
25 | #include "AliHLTGlobalTriggerComponent.h" | |
e2bb8ddd | 26 | #include "AliHLTGlobalTriggerDecision.h" |
27 | #include "AliHLTGlobalTrigger.h" | |
52f67e50 | 28 | #include "AliHLTGlobalTriggerConfig.h" |
29 | #include "AliHLTTriggerMenu.h" | |
e2bb8ddd | 30 | #include "TUUID.h" |
31 | #include "TROOT.h" | |
52f67e50 | 32 | #include "TRegexp.h" |
33 | #include "TClonesArray.h" | |
34 | #include "TObjString.h" | |
e2bb8ddd | 35 | #include "TSystem.h" |
52f67e50 | 36 | #include "TInterpreter.h" |
e2bb8ddd | 37 | #include <fstream> |
38 | #include <cerrno> | |
1b9a175e | 39 | |
40 | ClassImp(AliHLTGlobalTriggerComponent) | |
41 | ||
42 | ||
43 | AliHLTGlobalTriggerComponent::AliHLTGlobalTriggerComponent() : | |
e2bb8ddd | 44 | AliHLTTrigger(), |
52f67e50 | 45 | fTrigger(NULL), |
46 | fDebugMode(false) | |
1b9a175e | 47 | { |
48 | // Default constructor. | |
49 | } | |
50 | ||
51 | ||
52 | AliHLTGlobalTriggerComponent::~AliHLTGlobalTriggerComponent() | |
53 | { | |
54 | // Default destructor. | |
e2bb8ddd | 55 | |
56 | if (fTrigger != NULL) delete fTrigger; | |
1b9a175e | 57 | } |
58 | ||
59 | ||
60 | void AliHLTGlobalTriggerComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier) | |
61 | { | |
62 | // Returns the output data size estimate. | |
63 | ||
e2bb8ddd | 64 | constBase = sizeof(AliHLTGlobalTriggerDecision); |
1b9a175e | 65 | inputMultiplier = 1; |
66 | } | |
67 | ||
68 | ||
52f67e50 | 69 | Int_t AliHLTGlobalTriggerComponent::DoInit(int argc, const char** argv) |
1b9a175e | 70 | { |
e2bb8ddd | 71 | // Initialises the global trigger component. |
72 | ||
52f67e50 | 73 | fDebugMode = false; |
74 | const char* configFileName = NULL; | |
75 | const char* codeFileName = NULL; | |
e2bb8ddd | 76 | TString classname; |
52f67e50 | 77 | TClonesArray includePaths(TObjString::Class()); |
78 | TClonesArray includeFiles(TObjString::Class()); | |
79 | ||
80 | for (int i = 0; i < argc; i++) | |
81 | { | |
82 | if (strcmp(argv[i], "-config") == 0) | |
83 | { | |
84 | if (configFileName != NULL) | |
85 | { | |
86 | HLTWarning("Trigger configuration macro was already specified." | |
87 | " Will replace previous value given by -config." | |
88 | ); | |
89 | } | |
90 | if (argc <= i+1) | |
91 | { | |
92 | HLTError("The trigger configuration macro filename was not specified." ); | |
93 | return -EINVAL; | |
94 | } | |
95 | configFileName = argv[i+1]; | |
96 | i++; | |
97 | continue; | |
98 | } | |
99 | ||
100 | if (strcmp(argv[i], "-includepath") == 0) | |
101 | { | |
102 | if (argc <= i+1) | |
103 | { | |
104 | HLTError("The include path was not specified." ); | |
105 | return -EINVAL; | |
106 | } | |
107 | new (includePaths[includePaths.GetEntriesFast()]) TObjString(argv[i+1]); | |
108 | i++; | |
109 | continue; | |
110 | } | |
111 | ||
112 | if (strcmp(argv[i], "-include") == 0) | |
113 | { | |
114 | if (argc <= i+1) | |
115 | { | |
116 | HLTError("The include file name was not specified." ); | |
117 | return -EINVAL; | |
118 | } | |
119 | new (includeFiles[includeFiles.GetEntriesFast()]) TObjString(argv[i+1]); | |
120 | i++; | |
121 | continue; | |
122 | } | |
123 | ||
124 | if (strcmp(argv[i], "-debug") == 0) | |
125 | { | |
126 | if (fDebugMode == true) | |
127 | { | |
128 | HLTWarning("The debug flag was already specified. Ignoring this instance."); | |
129 | } | |
130 | fDebugMode = true; | |
131 | i++; | |
132 | continue; | |
133 | } | |
134 | ||
135 | if (strcmp(argv[i], "-usecode") == 0) | |
136 | { | |
137 | if (codeFileName != NULL) | |
138 | { | |
139 | HLTWarning("Custom trigger code file was already specified." | |
140 | " Will replace previous value given by -usecode." | |
141 | ); | |
142 | } | |
143 | if (argc <= i+1) | |
144 | { | |
145 | HLTError("The custom trigger code filename was not specified." ); | |
146 | return -EINVAL; | |
147 | } | |
148 | codeFileName = argv[i+1]; | |
149 | if (argc <= i+2) | |
150 | { | |
151 | HLTError("The custom trigger class name was not specified." ); | |
152 | return -EINVAL; | |
153 | } | |
154 | classname = argv[i+2]; | |
155 | i += 2; | |
156 | continue; | |
157 | } | |
158 | ||
159 | HLTError("Unknown option '%s'.", argv[i]); | |
160 | return -EINVAL; | |
161 | } // for loop | |
162 | ||
163 | const AliHLTTriggerMenu* menu = NULL; | |
164 | if (configFileName != NULL) | |
165 | { | |
166 | TString cmd = ".x "; | |
167 | cmd += configFileName; | |
168 | gROOT->ProcessLine(cmd); | |
169 | menu = AliHLTGlobalTriggerConfig::Menu(); | |
170 | } | |
171 | ||
172 | if (menu == NULL) | |
173 | { | |
174 | HLTError("No trigger menu configuration found or specified."); | |
175 | return -ENOENT; | |
176 | } | |
177 | ||
178 | int result = 0; | |
179 | if (codeFileName == NULL) | |
180 | { | |
181 | HLTDebug("Generating custom HLT trigger class."); | |
182 | result = GenerateTrigger(menu, classname, includePaths, includeFiles); | |
183 | } | |
184 | else | |
185 | { | |
186 | HLTDebug("Loading HLT trigger class from file '%s'.", codeFileName); | |
187 | result = LoadTriggerClass(codeFileName, includePaths); | |
188 | } | |
e2bb8ddd | 189 | if (result != 0) return result; |
190 | ||
191 | fTrigger = AliHLTGlobalTrigger::CreateNew(classname.Data()); | |
192 | if (fTrigger == NULL) | |
193 | { | |
194 | HLTError("Could not create a new instance of '%s'.", classname.Data()); | |
195 | return -EIO; | |
196 | } | |
197 | ||
52f67e50 | 198 | fTrigger->FillFromMenu(*menu); |
199 | fTrigger->ResetCounters(menu->NumberOfItems()); | |
200 | ||
e2bb8ddd | 201 | return 0; |
202 | } | |
203 | ||
1b9a175e | 204 | |
e2bb8ddd | 205 | Int_t AliHLTGlobalTriggerComponent::DoDeinit() |
206 | { | |
207 | // Cleans up the global trigger component. | |
208 | ||
209 | if (fTrigger != NULL) | |
210 | { | |
211 | delete fTrigger; | |
212 | fTrigger = NULL; | |
213 | } | |
214 | ||
1b9a175e | 215 | return 0; |
216 | } | |
4f1d6b68 | 217 | |
218 | ||
219 | AliHLTComponent* AliHLTGlobalTriggerComponent::Spawn() | |
220 | { | |
221 | // Creates a new object instance. | |
222 | ||
223 | return new AliHLTGlobalTriggerComponent; | |
224 | } | |
225 | ||
e2bb8ddd | 226 | |
227 | int AliHLTGlobalTriggerComponent::DoTrigger() | |
228 | { | |
229 | // This method will apply the global trigger decision. | |
230 | ||
231 | if (fTrigger == NULL) | |
232 | { | |
233 | HLTFatal("Global trigger implementation object is NULL!"); | |
234 | return -EIO; | |
235 | } | |
236 | ||
237 | fTrigger->NewEvent(); | |
238 | ||
239 | // Fill in the input data. | |
240 | const TObject* obj = GetFirstInputObject(); | |
241 | while (obj != NULL) | |
52f67e50 | 242 | { |
243 | fTrigger->Add(obj, GetDataType(), GetSpecification()); | |
244 | obj = GetNextInputObject(); | |
245 | } | |
246 | ||
247 | // Calculate the global trigger result and trigger domain, then create and push | |
248 | // back the new global trigger decision object. | |
249 | TString description; | |
250 | GetTriggerDomain().Clear(); | |
251 | bool triggerResult = fTrigger->CalculateTriggerDecision(GetTriggerDomain(), description); | |
252 | SetDescription(description.Data()); | |
253 | ||
254 | AliHLTGlobalTriggerDecision decision(triggerResult, GetTriggerDomain(), GetDescription()); | |
255 | decision.SetCounters(fTrigger->Counters()); | |
256 | ||
257 | // Add the input objects used to the global decision. | |
258 | obj = GetFirstInputObject(); | |
259 | while (obj != NULL) | |
e2bb8ddd | 260 | { |
261 | if (obj->IsA() == AliHLTTriggerDecision::Class()) | |
262 | { | |
52f67e50 | 263 | decision.AddTriggerInput( *static_cast<const AliHLTTriggerDecision*>(obj) ); |
e2bb8ddd | 264 | } |
265 | else | |
266 | { | |
52f67e50 | 267 | decision.AddInputObject(obj); |
e2bb8ddd | 268 | } |
269 | obj = GetNextInputObject(); | |
270 | } | |
52f67e50 | 271 | |
272 | TriggerEvent(&decision); | |
e2bb8ddd | 273 | return 0; |
274 | } | |
275 | ||
276 | ||
52f67e50 | 277 | int AliHLTGlobalTriggerComponent::GenerateTrigger( |
278 | const AliHLTTriggerMenu* menu, TString& name, | |
279 | const TClonesArray& includePaths, const TClonesArray& includeFiles | |
280 | ) | |
e2bb8ddd | 281 | { |
282 | // Generates the global trigger class that will implement the specified trigger menu. | |
52f67e50 | 283 | // See header for more details. |
e2bb8ddd | 284 | |
285 | // Create a new UUID and replace the '-' characters with '_' to make it a valid | |
286 | // C++ symbol name. | |
287 | TUUID uuid; | |
288 | TString uuidstr = uuid.AsString(); | |
289 | for (Int_t i = 0; i < uuidstr.Length(); i++) | |
290 | { | |
291 | if (uuidstr[i] == '-') uuidstr[i] = '_'; | |
292 | } | |
293 | ||
294 | // Create the name of the new class. | |
295 | name = "AliHLTGlobalTriggerImpl_"; | |
296 | name += uuidstr; | |
297 | TString filename = name + ".cxx"; | |
298 | ||
52f67e50 | 299 | // Open a text file to write the code and generate the new class. |
e2bb8ddd | 300 | fstream code(filename.Data(), ios_base::out | ios_base::trunc); |
301 | if (not code.good()) | |
302 | { | |
303 | HLTError("Could not open file '%s' for writing.", filename.Data()); | |
304 | return -EIO; | |
305 | } | |
306 | ||
52f67e50 | 307 | TClonesArray symbols(AliHLTTriggerMenuSymbol::Class()); |
308 | int result = BuildSymbolList(menu, symbols); | |
309 | if (result != 0) return result; | |
310 | ||
311 | code << "#include <cstring>" << endl; | |
312 | code << "#include \"TString.h\"" << endl; | |
313 | code << "#include \"TClonesArray.h\"" << endl; | |
e2bb8ddd | 314 | code << "#include \"AliHLTGlobalTrigger.h\"" << endl; |
315 | code << "#include \"AliHLTGlobalTriggerDecision.h\"" << endl; | |
52f67e50 | 316 | code << "#include \"AliHLTDomainEntry.h\"" << endl; |
317 | code << "#include \"AliHLTTriggerDomain.h\"" << endl; | |
318 | code << "#include \"AliHLTReadoutList.h\"" << endl; | |
319 | code << "#include \"AliHLTTriggerMenu.h\"" << endl; | |
320 | code << "#include \"AliHLTTriggerMenuItem.h\"" << endl; | |
321 | code << "#include \"AliHLTTriggerMenuSymbol.h\"" << endl; | |
322 | ||
323 | // Add any include files that were specified on the command line. | |
324 | for (Int_t i = 0; i < includeFiles.GetEntriesFast(); i++) | |
325 | { | |
326 | TString file = static_cast<const TObjString*>(includeFiles.UncheckedAt(i))->String(); | |
327 | code << "#include \"" << file.Data() << "\"" << endl; | |
328 | } | |
329 | ||
e2bb8ddd | 330 | code << "class " << name << " : public AliHLTGlobalTrigger" << endl; |
331 | code << "{" << endl; | |
332 | code << "public:" << endl; | |
52f67e50 | 333 | |
334 | code << " " << name << "() : AliHLTGlobalTrigger()"; | |
335 | // Write the symbols in the trigger menu in the initialisation list. | |
336 | for (Int_t i = 0; i < symbols.GetEntriesFast(); i++) | |
337 | { | |
338 | code << "," << endl; | |
339 | AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) ); | |
340 | code << " " << symbol->Name() << "()," << endl; | |
341 | if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0) | |
342 | { | |
343 | code << " " << symbol->Name() << "TriggerDomain()," << endl; | |
344 | } | |
345 | code << " " << symbol->Name() << "DomainEntry(kAliHLTAnyDataType)"; | |
346 | } | |
347 | for (UInt_t i = 0; i < menu->NumberOfItems(); i++) | |
348 | { | |
349 | code << "," << endl << " fMenuItemDescription" << i << "()"; | |
350 | } | |
351 | code << endl << " {" << endl; | |
352 | if (fDebugMode) | |
353 | { | |
354 | code << " SetLocalLoggingLevel(kHLTLogAll);" << endl; | |
355 | code << " HLTInfo(\"Creating new instance at %p.\", this);" << endl; | |
356 | } | |
e2bb8ddd | 357 | code << " }" << endl; |
52f67e50 | 358 | |
e2bb8ddd | 359 | code << " virtual ~" << name << "() {" << endl; |
52f67e50 | 360 | if (fDebugMode) |
361 | { | |
362 | code << " HLTInfo(\"Deleting instance at %p.\", this);" << endl; | |
363 | } | |
e2bb8ddd | 364 | code << " }" << endl; |
52f67e50 | 365 | |
366 | // Generate the FillFromMenu method. | |
367 | code << " virtual void FillFromMenu(const AliHLTTriggerMenu& menu) {" << endl; | |
368 | if (fDebugMode) | |
369 | { | |
370 | code << " HLTDebug(\"Filling description entries from trigger menu for global trigger %p.\", this);" << endl; | |
371 | } | |
372 | for (UInt_t i = 0; i < menu->NumberOfItems(); i++) | |
373 | { | |
374 | code << " fMenuItemDescription" << i << " = (menu.Item(" << i | |
375 | << ") != NULL) ? menu.Item(" << i << ")->Description() : \"\";" << endl; | |
376 | } | |
377 | if (fDebugMode) | |
378 | { | |
379 | code << " HLTDebug(\"Finished filling description entries from trigger menu.\");" << endl; | |
380 | code << " HLTDebug(\"Filling domain entries from trigger menu symbols for global trigger %p.\", this);" << endl; | |
381 | } | |
382 | code << " for (Int_t i = 0; i < menu.SymbolArray().GetEntriesFast(); i++) {" << endl; | |
383 | code << " const AliHLTTriggerMenuSymbol* symbol = dynamic_cast<const" | |
384 | " AliHLTTriggerMenuSymbol*>(menu.SymbolArray().UncheckedAt(i));" << endl; | |
385 | code << " if (symbol == NULL) continue;" << endl; | |
386 | for (Int_t i = 0; i < symbols.GetEntriesFast(); i++) | |
387 | { | |
388 | AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) ); | |
389 | code << " if (strcmp(symbol->Name(), \"" << symbol->Name() << "\") == 0) {" << endl; | |
390 | if (fDebugMode) | |
391 | { | |
392 | code << " HLTDebug(\"Assinging domain entry value to match for symbol '%s' to '%s'.\"," | |
393 | " symbol->Name(), symbol->BlockType().AsString().Data());" << endl; | |
394 | } | |
395 | code << " " << symbol->Name() << "DomainEntry = symbol->BlockType();" << endl; | |
396 | code << " continue;" << endl; | |
397 | code << " }" << endl; | |
398 | } | |
399 | code << " }" << endl; | |
400 | if (fDebugMode) | |
401 | { | |
402 | code << " HLTDebug(\"Finished filling domain entries from trigger menu symbols.\");" << endl; | |
403 | } | |
e2bb8ddd | 404 | code << " }" << endl; |
52f67e50 | 405 | |
406 | // Generate the NewEvent method. | |
407 | code << " virtual void NewEvent() {" << endl; | |
408 | if (fDebugMode) | |
409 | { | |
410 | code << " HLTDebug(\"New event for global trigger object %p, initialising variables to default values.\", this);" << endl; | |
411 | } | |
412 | // Write code to initialise the symbols in the trigger menu to their default values. | |
413 | for (Int_t i = 0; i < symbols.GetEntriesFast(); i++) | |
414 | { | |
415 | AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) ); | |
416 | code << " " << symbol->Name() << " = " << symbol->DefaultValue() << ";" << endl; | |
417 | if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0) | |
418 | { | |
419 | code << " " << symbol->Name() << "TriggerDomain.Clear();" << endl; | |
420 | } | |
421 | } | |
422 | if (fDebugMode) | |
423 | { | |
424 | code << " HLTDebug(\"Finished initialising variables.\");" << endl; | |
425 | } | |
e2bb8ddd | 426 | code << " }" << endl; |
52f67e50 | 427 | |
428 | // Generate the Add method. | |
429 | code << " virtual void Add(const TObject* _object_, const AliHLTComponentDataType& _type_, AliHLTUInt32_t _spec_) {" << endl; | |
430 | code << " AliHLTDomainEntry _type_spec_(_type_, _spec_);" << endl; | |
431 | if (fDebugMode) | |
432 | { | |
433 | code << " HLTDebug(\"Adding TObject %p, with class name '%s' from data block" | |
434 | " '%s', to global trigger object %p\", _object_, _object_->ClassName()," | |
435 | " _type_spec_.AsString().Data(), this);" << endl; | |
436 | code << " _object_->Print();" << endl; | |
437 | code << " bool _object_assigned_ = false;" << endl; | |
438 | } | |
439 | for (Int_t i = 0; i < symbols.GetEntriesFast(); i++) | |
440 | { | |
441 | // Write code to check if the block type, specification and class name is correct. | |
442 | // Then write code to assign the variable from the input object. | |
443 | AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) ); | |
444 | TString expr = symbol->AssignExpression(); | |
445 | if (expr == "") continue; // Skip entries that have no assignment expression. | |
446 | bool isTrigDecision = strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0; | |
447 | if (fDebugMode) | |
448 | { | |
449 | if (isTrigDecision) | |
450 | { | |
451 | code << " HLTDebug(\"Trying to match input object to class '" | |
452 | << symbol->ObjectClass() << "', trigger name '" << symbol->Name() | |
453 | << "' and block type '%s'\", " << symbol->Name() | |
454 | << "DomainEntry.AsString().Data());" << endl; | |
455 | } | |
456 | else | |
457 | { | |
458 | code << " HLTDebug(\"Trying to match input object to class '" | |
459 | << symbol->ObjectClass() << "' and block type '%s'\", " | |
460 | << symbol->Name() << "DomainEntry.AsString().Data());" << endl; | |
461 | } | |
462 | } | |
463 | code << " const " << symbol->ObjectClass() << "* " << symbol->Name() | |
464 | << "_object_ = dynamic_cast<const " << symbol->ObjectClass() | |
465 | << "*>(_object_);" << endl; | |
466 | code << " if (" << symbol->Name() << "_object_ != NULL and "; | |
467 | if (isTrigDecision) | |
468 | { | |
469 | code << "strcmp(" << symbol->Name() << "_object_->Name(), \"" | |
470 | << symbol->Name() << "\") == 0 and "; | |
471 | } | |
472 | code << symbol->Name() << "DomainEntry == _type_spec_) {" << endl; | |
473 | TString fullname = symbol->Name(); | |
474 | fullname += "_object_"; | |
475 | expr.ReplaceAll("this", fullname); | |
476 | code << " this->" << symbol->Name() << " = " << expr.Data() << ";" << endl; | |
477 | if (isTrigDecision) | |
478 | { | |
479 | code << " this->" << symbol->Name() << "TriggerDomain = " | |
480 | << fullname.Data() << "->TriggerDomain();" << endl; | |
481 | } | |
482 | if (fDebugMode) | |
483 | { | |
484 | code << " HLTDebug(\"Added TObject %p with class name '%s' to variable " | |
485 | << symbol->Name() << "\", _object_, _object_->ClassName());" << endl; | |
486 | code << " _object_assigned_ = true;" << endl; | |
487 | } | |
488 | code << " }" << endl; | |
489 | } | |
490 | if (fDebugMode) | |
491 | { | |
492 | code << " if (not _object_assigned_) HLTDebug(\"Did not assign TObject %p" | |
493 | " with class name '%s' to any variable.\", _object_, _object_->ClassName());" | |
494 | << endl; | |
495 | } | |
e2bb8ddd | 496 | code << " }" << endl; |
52f67e50 | 497 | |
498 | // Generate the CalculateTriggerDecision method. | |
499 | code << " virtual bool CalculateTriggerDecision(AliHLTTriggerDomain& _domain_, TString& _description_) {" << endl; | |
500 | if (fDebugMode) | |
501 | { | |
502 | code << " HLTDebug(\"Calculating global HLT trigger result with trigger object at %p.\", this);" << endl; | |
503 | } | |
504 | for (UInt_t i = 0; i < menu->NumberOfItems(); i++) | |
505 | { | |
506 | const AliHLTTriggerMenuItem* item = menu->Item(i); | |
507 | TString mergeExpr = item->MergeExpression(); | |
508 | for (Int_t j = 0; j < symbols.GetEntriesFast(); j++) | |
509 | { | |
510 | AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(j) ); | |
511 | if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") != 0) continue; | |
512 | TString newname = symbol->Name(); | |
513 | newname += "TriggerDomain"; | |
514 | mergeExpr.ReplaceAll(symbol->Name(), newname); | |
515 | } | |
516 | if (fDebugMode) | |
517 | { | |
518 | code << " HLTDebug(\"Trying trigger condition " << i | |
519 | << " (Description = '%s').\", fMenuItemDescription" << i << ".Data());" | |
520 | << endl; | |
521 | } | |
522 | code << " if (" << item->TriggerCondision() << ") {" << endl; | |
523 | code << " IncrementCounter(" << i << ");" << endl; | |
524 | const char* indentation = ""; | |
525 | if (item->PreScalar() != 0) | |
526 | { | |
527 | indentation = " "; | |
528 | code << " if ((GetCounter(" << i << ") % " << item->PreScalar() << ") == 1) {" << endl; | |
529 | } | |
530 | code << indentation << " _domain_ = " << mergeExpr.Data() << ";" << endl; | |
531 | code << indentation << " _description_ = fMenuItemDescription" << i << ";" << endl; | |
532 | if (fDebugMode) | |
533 | { | |
534 | code << indentation << " HLTDebug(\"Matched trigger condition " << i | |
535 | << " (Description = '%s').\", fMenuItemDescription" << i << ".Data());" << endl; | |
536 | } | |
537 | code << indentation << " return true;" << endl; | |
538 | if (item->PreScalar() != 0) | |
539 | { | |
540 | code << " }" << endl; | |
541 | } | |
542 | code << " }" << endl; | |
543 | } | |
544 | code << " return false;" << endl; | |
e2bb8ddd | 545 | code << " }" << endl; |
52f67e50 | 546 | |
547 | // Generate the custom Factory class. | |
e2bb8ddd | 548 | code << " class FactoryImpl : public AliHLTGlobalTrigger::Factory" << endl; |
549 | code << " {" << endl; | |
550 | code << " public:" << endl; | |
551 | code << " virtual const char* ClassName() const {" << endl; | |
552 | code << " return \"" << name << "\";" << endl; | |
553 | code << " }" << endl; | |
554 | code << " virtual AliHLTGlobalTrigger* New() const {" << endl; | |
555 | code << " return new " << name << "();" << endl; | |
556 | code << " }" << endl; | |
e2bb8ddd | 557 | code << " };" << endl; |
52f67e50 | 558 | |
e2bb8ddd | 559 | code << "private:" << endl; |
52f67e50 | 560 | // Add the symbols in the trigger menu to the list of private variables. |
561 | for (Int_t i = 0; i < symbols.GetEntriesFast(); i++) | |
562 | { | |
563 | AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) ); | |
564 | code << " " << symbol->Type() << " " << symbol->Name() << ";" << endl; | |
565 | if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0) | |
566 | { | |
567 | code << " AliHLTTriggerDomain " << symbol->Name() << "TriggerDomain;" << endl; | |
568 | } | |
569 | code << " AliHLTDomainEntry " << symbol->Name() << "DomainEntry;" << endl; | |
570 | } | |
571 | for (UInt_t i = 0; i < menu->NumberOfItems(); i++) | |
572 | { | |
573 | code << " TString fMenuItemDescription" << i << ";" << endl; | |
574 | } | |
e2bb8ddd | 575 | code << "};" << endl; |
e2bb8ddd | 576 | |
52f67e50 | 577 | // Write a global object for the Factory class for automatic registration. |
578 | code << "namespace {" << endl; | |
579 | code << " const " << name << "::FactoryImpl gkFactoryImpl;" << endl; | |
580 | code << "};" << endl; | |
e2bb8ddd | 581 | |
582 | code.close(); | |
583 | ||
52f67e50 | 584 | // Now we need to compile and load the new class. |
585 | result = LoadTriggerClass(filename, includePaths); | |
586 | return result; | |
587 | } | |
588 | ||
589 | ||
590 | int AliHLTGlobalTriggerComponent::LoadTriggerClass( | |
591 | const char* filename, const TClonesArray& includePaths | |
592 | ) | |
593 | { | |
594 | // Loads the code for a custom global trigger class implementation on the fly. | |
595 | ||
596 | TString compiler = gSystem->GetBuildCompilerVersion(); | |
597 | if (compiler.Contains("gcc") or compiler.Contains("icc")) | |
598 | { | |
599 | TString includePath = "-I${ALICE_ROOT}/include -I${ALICE_ROOT}/HLT/BASE -I${ALICE_ROOT}/HLT/trigger"; | |
600 | // Add any include paths that were specified on the command line. | |
601 | for (Int_t i = 0; i < includePaths.GetEntriesFast(); i++) | |
602 | { | |
603 | TString path = static_cast<const TObjString*>(includePaths.UncheckedAt(i))->String(); | |
604 | includePath += " "; | |
605 | includePath += path; | |
606 | } | |
607 | gSystem->SetIncludePath(includePath); | |
608 | gSystem->SetFlagsOpt("-O3 -DNDEBUG"); | |
609 | gSystem->SetFlagsDebug("-g3 -DDEBUG -D__DEBUG"); | |
610 | ||
611 | int result = kTRUE; | |
612 | if (fDebugMode) | |
613 | { | |
614 | result = gSystem->CompileMacro(filename, "g"); | |
615 | } | |
616 | else | |
617 | { | |
618 | result = gSystem->CompileMacro(filename, "O"); | |
619 | } | |
620 | if (result != kTRUE) | |
621 | { | |
622 | HLTFatal("Could not compile and load global trigger menu implementation."); | |
623 | return -ENOENT; | |
624 | } | |
625 | } | |
626 | else | |
627 | { | |
628 | // If we do not support the compiler then try interpret the class instead. | |
629 | TString cmd = ".L "; | |
630 | cmd += filename; | |
631 | Int_t errorcode = TInterpreter::kNoError; | |
632 | gROOT->ProcessLine(cmd, &errorcode); | |
633 | if (errorcode != TInterpreter::kNoError) | |
634 | { | |
635 | HLTFatal("Could not load interpreted global trigger menu implementation" | |
636 | " (Interpreter error code = %d).", | |
637 | errorcode | |
638 | ); | |
639 | return -ENOENT; | |
640 | } | |
641 | } | |
642 | ||
643 | return 0; | |
644 | } | |
645 | ||
646 | ||
647 | int AliHLTGlobalTriggerComponent::FindSymbol(const char* name, const TClonesArray& list) | |
648 | { | |
649 | // Searches for the named symbol in the given list. | |
650 | // See header for more details. | |
651 | ||
652 | for (int i = 0; i < list.GetEntriesFast(); i++) | |
653 | { | |
654 | const AliHLTTriggerMenuSymbol* symbol = dynamic_cast<const AliHLTTriggerMenuSymbol*>( list.UncheckedAt(i) ); | |
655 | if (symbol == NULL) continue; | |
656 | if (strcmp(symbol->Name(), name) == 0) return i; | |
657 | } | |
658 | return -1; | |
659 | } | |
660 | ||
661 | ||
662 | int AliHLTGlobalTriggerComponent::BuildSymbolList(const AliHLTTriggerMenu* menu, TClonesArray& list) | |
663 | { | |
664 | // Builds the list of symbols to use in the custom global trigger menu | |
665 | // implementation class. | |
666 | // See header for more details. | |
667 | ||
668 | for (UInt_t i = 0; i < menu->NumberOfSymbols(); i++) | |
669 | { | |
670 | const AliHLTTriggerMenuSymbol* symbol = menu->Symbol(i); | |
671 | if (FindSymbol(symbol->Name(), list) != -1) | |
672 | { | |
673 | HLTError("Multiple symbols with the name '%s' defined in the trigger menu.", symbol->Name()); | |
674 | return -EIO; | |
675 | } | |
676 | new (list[list.GetEntriesFast()]) AliHLTTriggerMenuSymbol(*symbol); | |
677 | } | |
678 | ||
679 | TRegexp exp("[_a-zA-Z][_a-zA-Z0-9]*"); | |
680 | for (UInt_t i = 0; i < menu->NumberOfItems(); i++) | |
681 | { | |
682 | const AliHLTTriggerMenuItem* item = menu->Item(i); | |
683 | TString str = item->TriggerCondision(); | |
684 | Ssiz_t start = 0; | |
685 | do | |
686 | { | |
687 | Ssiz_t length = 0; | |
688 | Ssiz_t pos = exp.Index(str, &length, start); | |
689 | if (pos == kNPOS) break; | |
690 | TString s = str(pos, length); | |
691 | start = pos+length; | |
692 | ||
693 | if (s == "and" or s == "and_eq" or s == "bitand" or s == "bitor" or | |
694 | s == "compl" or s == "not" or s == "not_eq" or s == "or" or | |
695 | s == "or_eq" or s == "xor" or s == "xor_eq" or s == "true" or | |
696 | s == "false" | |
697 | ) | |
698 | { | |
699 | // Ignore iso646.h and other keywords. | |
700 | continue; | |
701 | } | |
702 | ||
703 | if (FindSymbol(s.Data(), list) == -1) | |
704 | { | |
705 | AliHLTTriggerMenuSymbol newSymbol; | |
706 | newSymbol.Name(s.Data()); | |
707 | newSymbol.Type("bool"); | |
708 | newSymbol.ObjectClass("AliHLTTriggerDecision"); | |
709 | newSymbol.AssignExpression("this->Result()"); | |
710 | newSymbol.DefaultValue("false"); | |
711 | new (list[list.GetEntriesFast()]) AliHLTTriggerMenuSymbol(newSymbol); | |
712 | } | |
713 | } | |
714 | while (start < str.Length()); | |
715 | } | |
716 | ||
e2bb8ddd | 717 | return 0; |
718 | } | |
719 |