1 /**************************************************************************
2 * This file is property of and copyright by the ALICE HLT Project *
3 * ALICE Experiment at CERN, All rights reserved. *
5 * Primary Authors: Artur Szostak <artursz@iafrica.com> *
6 * for The ALICE HLT Project. *
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 **************************************************************************/
17 /// @file AliHLTGlobalTriggerComponent.cxx
18 /// @author Artur Szostak <artursz@iafrica.com>
20 /// @brief Implementation of the AliHLTGlobalTriggerComponent component class.
22 /// The AliHLTGlobalTriggerComponentComponent class applies the global HLT trigger to all
23 /// trigger information produced by components deriving from AliHLTTrigger.
25 #include "AliHLTGlobalTriggerComponent.h"
26 #include "AliHLTGlobalTriggerDecision.h"
27 #include "AliHLTGlobalTrigger.h"
28 #include "AliHLTGlobalTriggerConfig.h"
29 #include "AliHLTTriggerMenu.h"
33 #include "TClonesArray.h"
34 #include "TObjString.h"
36 #include "TInterpreter.h"
40 ClassImp(AliHLTGlobalTriggerComponent)
43 AliHLTGlobalTriggerComponent::AliHLTGlobalTriggerComponent() :
48 // Default constructor.
50 ClearInfoForNewEvent(false);
54 AliHLTGlobalTriggerComponent::~AliHLTGlobalTriggerComponent()
56 // Default destructor.
58 if (fTrigger != NULL) delete fTrigger;
62 void AliHLTGlobalTriggerComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier)
64 // Returns the output data size estimate.
66 constBase = sizeof(AliHLTGlobalTriggerDecision);
71 Int_t AliHLTGlobalTriggerComponent::DoInit(int argc, const char** argv)
73 // Initialises the global trigger component.
76 const char* configFileName = NULL;
77 const char* codeFileName = NULL;
79 TClonesArray includePaths(TObjString::Class());
80 TClonesArray includeFiles(TObjString::Class());
82 for (int i = 0; i < argc; i++)
84 if (strcmp(argv[i], "-config") == 0)
86 if (configFileName != NULL)
88 HLTWarning("Trigger configuration macro was already specified."
89 " Will replace previous value given by -config."
94 HLTError("The trigger configuration macro filename was not specified." );
97 configFileName = argv[i+1];
102 if (strcmp(argv[i], "-includepath") == 0)
106 HLTError("The include path was not specified." );
109 new (includePaths[includePaths.GetEntriesFast()]) TObjString(argv[i+1]);
114 if (strcmp(argv[i], "-include") == 0)
118 HLTError("The include file name was not specified." );
121 new (includeFiles[includeFiles.GetEntriesFast()]) TObjString(argv[i+1]);
126 if (strcmp(argv[i], "-debug") == 0)
128 if (fDebugMode == true)
130 HLTWarning("The debug flag was already specified. Ignoring this instance.");
137 if (strcmp(argv[i], "-usecode") == 0)
139 if (codeFileName != NULL)
141 HLTWarning("Custom trigger code file was already specified."
142 " Will replace previous value given by -usecode."
147 HLTError("The custom trigger code filename was not specified." );
150 codeFileName = argv[i+1];
153 HLTError("The custom trigger class name was not specified." );
156 classname = argv[i+2];
161 HLTError("Unknown option '%s'.", argv[i]);
165 const AliHLTTriggerMenu* menu = NULL;
166 if (configFileName != NULL)
169 cmd += configFileName;
170 gROOT->ProcessLine(cmd);
171 menu = AliHLTGlobalTriggerConfig::Menu();
176 HLTError("No trigger menu configuration found or specified.");
181 if (codeFileName == NULL)
183 HLTDebug("Generating custom HLT trigger class.");
184 result = GenerateTrigger(menu, classname, includePaths, includeFiles);
188 HLTDebug("Loading HLT trigger class from file '%s'.", codeFileName);
189 result = LoadTriggerClass(codeFileName, includePaths);
191 if (result != 0) return result;
193 fTrigger = AliHLTGlobalTrigger::CreateNew(classname.Data());
194 if (fTrigger == NULL)
196 HLTError("Could not create a new instance of '%s'.", classname.Data());
200 fTrigger->FillFromMenu(*menu);
201 fTrigger->ResetCounters(menu->NumberOfItems());
203 // Set the default values from the trigger menu.
204 SetDescription(menu->DefaultDescription());
205 SetTriggerDomain(menu->DefaultTriggerDomain());
211 Int_t AliHLTGlobalTriggerComponent::DoDeinit()
213 // Cleans up the global trigger component.
215 if (fTrigger != NULL)
225 AliHLTComponent* AliHLTGlobalTriggerComponent::Spawn()
227 // Creates a new object instance.
229 return new AliHLTGlobalTriggerComponent;
233 int AliHLTGlobalTriggerComponent::DoTrigger()
235 // This method will apply the global trigger decision.
237 if (fTrigger == NULL)
239 HLTFatal("Global trigger implementation object is NULL!");
243 fTrigger->NewEvent();
245 // Fill in the input data.
246 const TObject* obj = GetFirstInputObject();
249 fTrigger->Add(obj, GetDataType(), GetSpecification());
250 obj = GetNextInputObject();
253 // Calculate the global trigger result and trigger domain, then create and push
254 // back the new global trigger decision object.
256 AliHLTTriggerDomain triggerDomain;
257 bool triggerResult = fTrigger->CalculateTriggerDecision(triggerDomain, description);
259 AliHLTGlobalTriggerDecision decision(
261 // The following will cause the decision to be generated with default values
262 // (set in fTriggerDomain and fDescription) if the trigger result is false.
263 (triggerResult == true) ? triggerDomain : GetTriggerDomain(),
264 (triggerResult == true) ? description.Data() : GetDescription()
266 decision.SetCounters(fTrigger->Counters());
268 // Add the input objects used to the global decision.
269 obj = GetFirstInputObject();
272 if (obj->IsA() == AliHLTTriggerDecision::Class())
274 decision.AddTriggerInput( *static_cast<const AliHLTTriggerDecision*>(obj) );
278 decision.AddInputObject(obj);
280 obj = GetNextInputObject();
283 TriggerEvent(&decision);
288 int AliHLTGlobalTriggerComponent::GenerateTrigger(
289 const AliHLTTriggerMenu* menu, TString& name,
290 const TClonesArray& includePaths, const TClonesArray& includeFiles
293 // Generates the global trigger class that will implement the specified trigger menu.
294 // See header for more details.
296 // Create a new UUID and replace the '-' characters with '_' to make it a valid
299 TString uuidstr = uuid.AsString();
300 for (Int_t i = 0; i < uuidstr.Length(); i++)
302 if (uuidstr[i] == '-') uuidstr[i] = '_';
305 // Create the name of the new class.
306 name = "AliHLTGlobalTriggerImpl_";
308 TString filename = name + ".cxx";
310 // Open a text file to write the code and generate the new class.
311 fstream code(filename.Data(), ios_base::out | ios_base::trunc);
314 HLTError("Could not open file '%s' for writing.", filename.Data());
318 TClonesArray symbols(AliHLTTriggerMenuSymbol::Class());
319 int result = BuildSymbolList(menu, symbols);
320 if (result != 0) return result;
322 code << "#include <cstring>" << endl;
323 code << "#include \"TString.h\"" << endl;
324 code << "#include \"TClonesArray.h\"" << endl;
325 code << "#include \"AliHLTGlobalTrigger.h\"" << endl;
326 code << "#include \"AliHLTGlobalTriggerDecision.h\"" << endl;
327 code << "#include \"AliHLTDomainEntry.h\"" << endl;
328 code << "#include \"AliHLTTriggerDomain.h\"" << endl;
329 code << "#include \"AliHLTReadoutList.h\"" << endl;
330 code << "#include \"AliHLTTriggerMenu.h\"" << endl;
331 code << "#include \"AliHLTTriggerMenuItem.h\"" << endl;
332 code << "#include \"AliHLTTriggerMenuSymbol.h\"" << endl;
334 // Add any include files that were specified on the command line.
335 for (Int_t i = 0; i < includeFiles.GetEntriesFast(); i++)
337 TString file = static_cast<const TObjString*>(includeFiles.UncheckedAt(i))->String();
338 code << "#include \"" << file.Data() << "\"" << endl;
341 code << "class " << name << " : public AliHLTGlobalTrigger" << endl;
343 code << "public:" << endl;
345 code << " " << name << "() : AliHLTGlobalTrigger()";
346 // Write the symbols in the trigger menu in the initialisation list.
347 for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
350 AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
351 code << " " << symbol->Name() << "()," << endl;
352 if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0)
354 code << " " << symbol->Name() << "TriggerDomain()," << endl;
356 code << " " << symbol->Name() << "DomainEntry(kAliHLTAnyDataType)";
358 for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
360 code << "," << endl << " fMenuItemDescription" << i << "()";
362 code << endl << " {" << endl;
365 code << " SetLocalLoggingLevel(kHLTLogAll);" << endl;
366 code << " HLTInfo(\"Creating new instance at %p.\", this);" << endl;
368 code << " }" << endl;
370 code << " virtual ~" << name << "() {" << endl;
373 code << " HLTInfo(\"Deleting instance at %p.\", this);" << endl;
375 code << " }" << endl;
377 // Generate the FillFromMenu method.
378 code << " virtual void FillFromMenu(const AliHLTTriggerMenu& menu) {" << endl;
381 code << " HLTDebug(\"Filling description entries from trigger menu for global trigger %p.\", this);" << endl;
383 for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
385 code << " fMenuItemDescription" << i << " = (menu.Item(" << i
386 << ") != NULL) ? menu.Item(" << i << ")->Description() : \"\";" << endl;
390 code << " HLTDebug(\"Finished filling description entries from trigger menu.\");" << endl;
391 code << " HLTDebug(\"Filling domain entries from trigger menu symbols for global trigger %p.\", this);" << endl;
393 code << " for (Int_t i = 0; i < menu.SymbolArray().GetEntriesFast(); i++) {" << endl;
394 code << " const AliHLTTriggerMenuSymbol* symbol = dynamic_cast<const"
395 " AliHLTTriggerMenuSymbol*>(menu.SymbolArray().UncheckedAt(i));" << endl;
396 code << " if (symbol == NULL) continue;" << endl;
397 for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
399 AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
400 code << " if (strcmp(symbol->Name(), \"" << symbol->Name() << "\") == 0) {" << endl;
403 code << " HLTDebug(\"Assinging domain entry value to match for symbol '%s' to '%s'.\","
404 " symbol->Name(), symbol->BlockType().AsString().Data());" << endl;
406 code << " " << symbol->Name() << "DomainEntry = symbol->BlockType();" << endl;
407 code << " continue;" << endl;
408 code << " }" << endl;
410 code << " }" << endl;
413 code << " HLTDebug(\"Finished filling domain entries from trigger menu symbols.\");" << endl;
415 code << " }" << endl;
417 // Generate the NewEvent method.
418 code << " virtual void NewEvent() {" << endl;
421 code << " HLTDebug(\"New event for global trigger object %p, initialising variables to default values.\", this);" << endl;
423 // Write code to initialise the symbols in the trigger menu to their default values.
424 for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
426 AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
427 code << " " << symbol->Name() << " = " << symbol->DefaultValue() << ";" << endl;
428 if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0)
430 code << " " << symbol->Name() << "TriggerDomain.Clear();" << endl;
435 code << " HLTDebug(\"Finished initialising variables.\");" << endl;
437 code << " }" << endl;
439 // Generate the Add method.
440 code << " virtual void Add(const TObject* _object_, const AliHLTComponentDataType& _type_, AliHLTUInt32_t _spec_) {" << endl;
441 code << " AliHLTDomainEntry _type_spec_(_type_, _spec_);" << endl;
444 code << " HLTDebug(\"Adding TObject %p, with class name '%s' from data block"
445 " '%s', to global trigger object %p\", _object_, _object_->ClassName(),"
446 " _type_spec_.AsString().Data(), this);" << endl;
447 code << " _object_->Print();" << endl;
448 code << " bool _object_assigned_ = false;" << endl;
450 for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
452 // Write code to check if the block type, specification and class name is correct.
453 // Then write code to assign the variable from the input object.
454 AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
455 TString expr = symbol->AssignExpression();
456 if (expr == "") continue; // Skip entries that have no assignment expression.
457 bool isTrigDecision = strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0;
462 code << " HLTDebug(\"Trying to match input object to class '"
463 << symbol->ObjectClass() << "', trigger name '" << symbol->Name()
464 << "' and block type '%s'\", " << symbol->Name()
465 << "DomainEntry.AsString().Data());" << endl;
469 code << " HLTDebug(\"Trying to match input object to class '"
470 << symbol->ObjectClass() << "' and block type '%s'\", "
471 << symbol->Name() << "DomainEntry.AsString().Data());" << endl;
474 code << " const " << symbol->ObjectClass() << "* " << symbol->Name()
475 << "_object_ = dynamic_cast<const " << symbol->ObjectClass()
476 << "*>(_object_);" << endl;
477 code << " if (" << symbol->Name() << "_object_ != NULL and ";
480 code << "strcmp(" << symbol->Name() << "_object_->Name(), \""
481 << symbol->Name() << "\") == 0 and ";
483 code << symbol->Name() << "DomainEntry == _type_spec_) {" << endl;
484 TString fullname = symbol->Name();
485 fullname += "_object_";
486 expr.ReplaceAll("this", fullname);
487 code << " this->" << symbol->Name() << " = " << expr.Data() << ";" << endl;
490 code << " this->" << symbol->Name() << "TriggerDomain = "
491 << fullname.Data() << "->TriggerDomain();" << endl;
495 code << " HLTDebug(\"Added TObject %p with class name '%s' to variable "
496 << symbol->Name() << "\", _object_, _object_->ClassName());" << endl;
497 code << " _object_assigned_ = true;" << endl;
499 code << " }" << endl;
503 code << " if (not _object_assigned_) HLTDebug(\"Did not assign TObject %p"
504 " with class name '%s' to any variable.\", _object_, _object_->ClassName());"
507 code << " }" << endl;
509 // Generate the CalculateTriggerDecision method.
510 code << " virtual bool CalculateTriggerDecision(AliHLTTriggerDomain& _domain_, TString& _description_) {" << endl;
513 code << " HLTDebug(\"Calculating global HLT trigger result with trigger object at %p.\", this);" << endl;
515 for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
517 const AliHLTTriggerMenuItem* item = menu->Item(i);
518 TString mergeExpr = item->MergeExpression();
519 for (Int_t j = 0; j < symbols.GetEntriesFast(); j++)
521 AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(j) );
522 if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") != 0) continue;
523 TString newname = symbol->Name();
524 newname += "TriggerDomain";
525 mergeExpr.ReplaceAll(symbol->Name(), newname);
529 code << " HLTDebug(\"Trying trigger condition " << i
530 << " (Description = '%s').\", fMenuItemDescription" << i << ".Data());"
533 code << " if (" << item->TriggerCondision() << ") {" << endl;
534 code << " IncrementCounter(" << i << ");" << endl;
535 const char* indentation = "";
536 if (item->PreScalar() != 0)
539 code << " if ((GetCounter(" << i << ") % " << item->PreScalar() << ") == 1) {" << endl;
541 code << indentation << " _domain_ = " << mergeExpr.Data() << ";" << endl;
542 code << indentation << " _description_ = fMenuItemDescription" << i << ";" << endl;
545 code << indentation << " HLTDebug(\"Matched trigger condition " << i
546 << " (Description = '%s').\", fMenuItemDescription" << i << ".Data());" << endl;
548 code << indentation << " return true;" << endl;
549 if (item->PreScalar() != 0)
551 code << " }" << endl;
553 code << " }" << endl;
555 code << " return false;" << endl;
556 code << " }" << endl;
558 // Generate the custom Factory class.
559 code << " class FactoryImpl : public AliHLTGlobalTrigger::Factory" << endl;
560 code << " {" << endl;
561 code << " public:" << endl;
562 code << " virtual const char* ClassName() const {" << endl;
563 code << " return \"" << name << "\";" << endl;
564 code << " }" << endl;
565 code << " virtual AliHLTGlobalTrigger* New() const {" << endl;
566 code << " return new " << name << "();" << endl;
567 code << " }" << endl;
568 code << " };" << endl;
570 code << "private:" << endl;
571 // Add the symbols in the trigger menu to the list of private variables.
572 for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
574 AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
575 code << " " << symbol->Type() << " " << symbol->Name() << ";" << endl;
576 if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0)
578 code << " AliHLTTriggerDomain " << symbol->Name() << "TriggerDomain;" << endl;
580 code << " AliHLTDomainEntry " << symbol->Name() << "DomainEntry;" << endl;
582 for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
584 code << " TString fMenuItemDescription" << i << ";" << endl;
586 code << "};" << endl;
588 // Write a global object for the Factory class for automatic registration.
589 code << "namespace {" << endl;
590 code << " const " << name << "::FactoryImpl gkFactoryImpl;" << endl;
591 code << "};" << endl;
595 // Now we need to compile and load the new class.
596 result = LoadTriggerClass(filename, includePaths);
601 int AliHLTGlobalTriggerComponent::LoadTriggerClass(
602 const char* filename, const TClonesArray& includePaths
605 // Loads the code for a custom global trigger class implementation on the fly.
607 TString compiler = gSystem->GetBuildCompilerVersion();
608 if (compiler.Contains("gcc") or compiler.Contains("icc"))
610 TString includePath = "-I${ALICE_ROOT}/include -I${ALICE_ROOT}/HLT/BASE -I${ALICE_ROOT}/HLT/trigger";
611 // Add any include paths that were specified on the command line.
612 for (Int_t i = 0; i < includePaths.GetEntriesFast(); i++)
614 TString path = static_cast<const TObjString*>(includePaths.UncheckedAt(i))->String();
618 gSystem->SetIncludePath(includePath);
619 gSystem->SetFlagsOpt("-O3 -DNDEBUG");
620 gSystem->SetFlagsDebug("-g3 -DDEBUG -D__DEBUG");
625 result = gSystem->CompileMacro(filename, "g");
629 result = gSystem->CompileMacro(filename, "O");
633 HLTFatal("Could not compile and load global trigger menu implementation.");
639 // If we do not support the compiler then try interpret the class instead.
642 Int_t errorcode = TInterpreter::kNoError;
643 gROOT->ProcessLine(cmd, &errorcode);
644 if (errorcode != TInterpreter::kNoError)
646 HLTFatal("Could not load interpreted global trigger menu implementation"
647 " (Interpreter error code = %d).",
658 int AliHLTGlobalTriggerComponent::FindSymbol(const char* name, const TClonesArray& list)
660 // Searches for the named symbol in the given list.
661 // See header for more details.
663 for (int i = 0; i < list.GetEntriesFast(); i++)
665 const AliHLTTriggerMenuSymbol* symbol = dynamic_cast<const AliHLTTriggerMenuSymbol*>( list.UncheckedAt(i) );
666 if (symbol == NULL) continue;
667 if (strcmp(symbol->Name(), name) == 0) return i;
673 int AliHLTGlobalTriggerComponent::BuildSymbolList(const AliHLTTriggerMenu* menu, TClonesArray& list)
675 // Builds the list of symbols to use in the custom global trigger menu
676 // implementation class.
677 // See header for more details.
679 for (UInt_t i = 0; i < menu->NumberOfSymbols(); i++)
681 const AliHLTTriggerMenuSymbol* symbol = menu->Symbol(i);
682 if (FindSymbol(symbol->Name(), list) != -1)
684 HLTError("Multiple symbols with the name '%s' defined in the trigger menu.", symbol->Name());
687 new (list[list.GetEntriesFast()]) AliHLTTriggerMenuSymbol(*symbol);
690 TRegexp exp("[_a-zA-Z][_a-zA-Z0-9]*");
691 for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
693 const AliHLTTriggerMenuItem* item = menu->Item(i);
694 TString str = item->TriggerCondision();
699 Ssiz_t pos = exp.Index(str, &length, start);
700 if (pos == kNPOS) break;
701 TString s = str(pos, length);
704 if (s == "and" or s == "and_eq" or s == "bitand" or s == "bitor" or
705 s == "compl" or s == "not" or s == "not_eq" or s == "or" or
706 s == "or_eq" or s == "xor" or s == "xor_eq" or s == "true" or
710 // Ignore iso646.h and other keywords.
714 if (FindSymbol(s.Data(), list) == -1)
716 AliHLTTriggerMenuSymbol newSymbol;
717 newSymbol.Name(s.Data());
718 newSymbol.Type("bool");
719 newSymbol.ObjectClass("AliHLTTriggerDecision");
720 newSymbol.AssignExpression("this->Result()");
721 newSymbol.DefaultValue("false");
722 new (list[list.GetEntriesFast()]) AliHLTTriggerMenuSymbol(newSymbol);
725 while (start < str.Length());