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