2 /**************************************************************************
3 * This file is property of and copyright by the ALICE HLT Project *
4 * ALICE Experiment at CERN, All rights reserved. *
6 * Primary Authors: Artur Szostak <artursz@iafrica.com> *
7 * for The ALICE HLT Project. *
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 **************************************************************************/
18 /// @file AliHLTGlobalTriggerComponent.cxx
19 /// @author Artur Szostak <artursz@iafrica.com>
21 /// @brief Implementation of the AliHLTGlobalTriggerComponent component class.
23 /// The AliHLTGlobalTriggerComponentComponent class applies the global HLT trigger to all
24 /// trigger information produced by components deriving from AliHLTTrigger.
26 #include "AliHLTGlobalTriggerComponent.h"
27 #include "AliHLTGlobalTriggerDecision.h"
28 #include "AliHLTGlobalTrigger.h"
29 #include "AliHLTGlobalTriggerConfig.h"
30 #include "AliHLTTriggerMenu.h"
34 #include "TClonesArray.h"
35 #include "TObjString.h"
37 #include "TInterpreter.h"
41 ClassImp(AliHLTGlobalTriggerComponent)
44 AliHLTGlobalTriggerComponent::AliHLTGlobalTriggerComponent() :
49 // Default constructor.
51 ClearInfoForNewEvent(false);
55 AliHLTGlobalTriggerComponent::~AliHLTGlobalTriggerComponent()
57 // Default destructor.
59 if (fTrigger != NULL) delete fTrigger;
63 void AliHLTGlobalTriggerComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier)
65 // Returns the output data size estimate.
67 constBase = sizeof(AliHLTGlobalTriggerDecision);
72 Int_t AliHLTGlobalTriggerComponent::DoInit(int argc, const char** argv)
74 // Initialises the global trigger component.
77 const char* configFileName = NULL;
78 const char* codeFileName = NULL;
80 TClonesArray includePaths(TObjString::Class());
81 TClonesArray includeFiles(TObjString::Class());
83 for (int i = 0; i < argc; i++)
85 if (strcmp(argv[i], "-config") == 0)
87 if (configFileName != NULL)
89 HLTWarning("Trigger configuration macro was already specified."
90 " Will replace previous value given by -config."
95 HLTError("The trigger configuration macro filename was not specified." );
98 configFileName = argv[i+1];
103 if (strcmp(argv[i], "-includepath") == 0)
107 HLTError("The include path was not specified." );
110 new (includePaths[includePaths.GetEntriesFast()]) TObjString(argv[i+1]);
115 if (strcmp(argv[i], "-include") == 0)
119 HLTError("The include file name was not specified." );
122 new (includeFiles[includeFiles.GetEntriesFast()]) TObjString(argv[i+1]);
127 if (strcmp(argv[i], "-debug") == 0)
129 if (fDebugMode == true)
131 HLTWarning("The debug flag was already specified. Ignoring this instance.");
138 if (strcmp(argv[i], "-usecode") == 0)
140 if (codeFileName != NULL)
142 HLTWarning("Custom trigger code file was already specified."
143 " Will replace previous value given by -usecode."
148 HLTError("The custom trigger code filename was not specified." );
151 codeFileName = argv[i+1];
154 HLTError("The custom trigger class name was not specified." );
157 classname = argv[i+2];
162 HLTError("Unknown option '%s'.", argv[i]);
166 const AliHLTTriggerMenu* menu = NULL;
167 if (configFileName != NULL)
170 cmd += configFileName;
171 gROOT->ProcessLine(cmd);
172 menu = AliHLTGlobalTriggerConfig::Menu();
177 HLTError("No trigger menu configuration found or specified.");
182 if (codeFileName == NULL)
184 HLTDebug("Generating custom HLT trigger class.");
185 result = GenerateTrigger(menu, classname, includePaths, includeFiles);
189 HLTDebug("Loading HLT trigger class from file '%s'.", codeFileName);
190 result = LoadTriggerClass(codeFileName, includePaths);
192 if (result != 0) return result;
194 fTrigger = AliHLTGlobalTrigger::CreateNew(classname.Data());
195 if (fTrigger == NULL)
197 HLTError("Could not create a new instance of '%s'.", classname.Data());
201 fTrigger->FillFromMenu(*menu);
202 fTrigger->ResetCounters(menu->NumberOfItems());
204 // Set the default values from the trigger menu.
205 SetDescription(menu->DefaultDescription());
206 SetTriggerDomain(menu->DefaultTriggerDomain());
212 Int_t AliHLTGlobalTriggerComponent::DoDeinit()
214 // Cleans up the global trigger component.
216 if (fTrigger != NULL)
226 AliHLTComponent* AliHLTGlobalTriggerComponent::Spawn()
228 // Creates a new object instance.
230 return new AliHLTGlobalTriggerComponent;
234 int AliHLTGlobalTriggerComponent::DoTrigger()
236 // This method will apply the global trigger decision.
238 if (fTrigger == NULL)
240 HLTFatal("Global trigger implementation object is NULL!");
244 fTrigger->NewEvent();
246 // Fill in the input data.
247 const TObject* obj = GetFirstInputObject();
250 fTrigger->Add(obj, GetDataType(), GetSpecification());
251 obj = GetNextInputObject();
254 // Calculate the global trigger result and trigger domain, then create and push
255 // back the new global trigger decision object.
257 AliHLTTriggerDomain triggerDomain;
258 bool triggerResult = fTrigger->CalculateTriggerDecision(triggerDomain, description);
260 AliHLTGlobalTriggerDecision decision(
262 // The following will cause the decision to be generated with default values
263 // (set in fTriggerDomain and fDescription) if the trigger result is false.
264 (triggerResult == true) ? triggerDomain : GetTriggerDomain(),
265 (triggerResult == true) ? description.Data() : GetDescription()
267 decision.SetCounters(fTrigger->Counters());
269 // Add the input objects used to the global decision.
270 obj = GetFirstInputObject();
273 if (obj->IsA() == AliHLTTriggerDecision::Class())
275 decision.AddTriggerInput( *static_cast<const AliHLTTriggerDecision*>(obj) );
279 decision.AddInputObject(obj);
281 obj = GetNextInputObject();
284 TriggerEvent(&decision);
289 int AliHLTGlobalTriggerComponent::GenerateTrigger(
290 const AliHLTTriggerMenu* menu, TString& name,
291 const TClonesArray& includePaths, const TClonesArray& includeFiles
294 // Generates the global trigger class that will implement the specified trigger menu.
295 // See header for more details.
297 // Create a new UUID and replace the '-' characters with '_' to make it a valid
300 TString uuidstr = uuid.AsString();
301 for (Int_t i = 0; i < uuidstr.Length(); i++)
303 if (uuidstr[i] == '-') uuidstr[i] = '_';
306 // Create the name of the new class.
307 name = "AliHLTGlobalTriggerImpl_";
309 TString filename = name + ".cxx";
311 // Open a text file to write the code and generate the new class.
312 fstream code(filename.Data(), ios_base::out | ios_base::trunc);
315 HLTError("Could not open file '%s' for writing.", filename.Data());
319 TClonesArray symbols(AliHLTTriggerMenuSymbol::Class());
320 int result = BuildSymbolList(menu, symbols);
321 if (result != 0) return result;
323 code << "#include <cstring>" << endl;
324 code << "#include \"TString.h\"" << endl;
325 code << "#include \"TClonesArray.h\"" << endl;
326 code << "#include \"AliHLTGlobalTrigger.h\"" << endl;
327 code << "#include \"AliHLTGlobalTriggerDecision.h\"" << endl;
328 code << "#include \"AliHLTDomainEntry.h\"" << endl;
329 code << "#include \"AliHLTTriggerDomain.h\"" << endl;
330 code << "#include \"AliHLTReadoutList.h\"" << endl;
331 code << "#include \"AliHLTTriggerMenu.h\"" << endl;
332 code << "#include \"AliHLTTriggerMenuItem.h\"" << endl;
333 code << "#include \"AliHLTTriggerMenuSymbol.h\"" << endl;
335 // Add any include files that were specified on the command line.
336 for (Int_t i = 0; i < includeFiles.GetEntriesFast(); i++)
338 TString file = static_cast<const TObjString*>(includeFiles.UncheckedAt(i))->String();
339 code << "#include \"" << file.Data() << "\"" << endl;
342 code << "class " << name << " : public AliHLTGlobalTrigger" << endl;
344 code << "public:" << endl;
346 code << " " << name << "() : AliHLTGlobalTrigger()";
347 // Write the symbols in the trigger menu in the initialisation list.
348 for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
351 AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
352 code << " " << symbol->Name() << "()," << endl;
353 if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0)
355 code << " " << symbol->Name() << "TriggerDomain()," << endl;
357 code << " " << symbol->Name() << "DomainEntry(kAliHLTAnyDataType)";
359 for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
361 code << "," << endl << " fMenuItemDescription" << i << "()";
363 code << endl << " {" << endl;
366 code << " SetLocalLoggingLevel(kHLTLogAll);" << endl;
367 code << " HLTInfo(\"Creating new instance at %p.\", this);" << endl;
369 code << " }" << endl;
371 code << " virtual ~" << name << "() {" << endl;
374 code << " HLTInfo(\"Deleting instance at %p.\", this);" << endl;
376 code << " }" << endl;
378 // Generate the FillFromMenu method.
379 code << " virtual void FillFromMenu(const AliHLTTriggerMenu& menu) {" << endl;
382 code << " HLTDebug(\"Filling description entries from trigger menu for global trigger %p.\", this);" << endl;
384 for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
386 code << " fMenuItemDescription" << i << " = (menu.Item(" << i
387 << ") != NULL) ? menu.Item(" << i << ")->Description() : \"\";" << endl;
391 code << " HLTDebug(\"Finished filling description entries from trigger menu.\");" << endl;
392 code << " HLTDebug(\"Filling domain entries from trigger menu symbols for global trigger %p.\", this);" << endl;
394 code << " for (Int_t i = 0; i < menu.SymbolArray().GetEntriesFast(); i++) {" << endl;
395 code << " const AliHLTTriggerMenuSymbol* symbol = dynamic_cast<const"
396 " AliHLTTriggerMenuSymbol*>(menu.SymbolArray().UncheckedAt(i));" << endl;
397 code << " if (symbol == NULL) continue;" << endl;
398 for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
400 AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
401 code << " if (strcmp(symbol->Name(), \"" << symbol->Name() << "\") == 0) {" << endl;
404 code << " HLTDebug(\"Assinging domain entry value to match for symbol '%s' to '%s'.\","
405 " symbol->Name(), symbol->BlockType().AsString().Data());" << endl;
407 code << " " << symbol->Name() << "DomainEntry = symbol->BlockType();" << endl;
408 code << " continue;" << endl;
409 code << " }" << endl;
411 code << " }" << endl;
414 code << " HLTDebug(\"Finished filling domain entries from trigger menu symbols.\");" << endl;
416 code << " }" << endl;
418 // Generate the NewEvent method.
419 code << " virtual void NewEvent() {" << endl;
422 code << " HLTDebug(\"New event for global trigger object %p, initialising variables to default values.\", this);" << endl;
424 // Write code to initialise the symbols in the trigger menu to their default values.
425 for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
427 AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
428 code << " " << symbol->Name() << " = " << symbol->DefaultValue() << ";" << endl;
429 if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0)
431 code << " " << symbol->Name() << "TriggerDomain.Clear();" << endl;
436 code << " HLTDebug(\"Finished initialising variables.\");" << endl;
438 code << " }" << endl;
440 // Generate the Add method.
441 code << " virtual void Add(const TObject* _object_, const AliHLTComponentDataType& _type_, AliHLTUInt32_t _spec_) {" << endl;
442 code << " AliHLTDomainEntry _type_spec_(_type_, _spec_);" << endl;
445 code << " HLTDebug(\"Adding TObject %p, with class name '%s' from data block"
446 " '%s', to global trigger object %p\", _object_, _object_->ClassName(),"
447 " _type_spec_.AsString().Data(), this);" << endl;
448 code << " _object_->Print();" << endl;
449 code << " bool _object_assigned_ = false;" << endl;
451 for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
453 // Write code to check if the block type, specification and class name is correct.
454 // Then write code to assign the variable from the input object.
455 AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
456 TString expr = symbol->AssignExpression();
457 if (expr == "") continue; // Skip entries that have no assignment expression.
458 bool isTrigDecision = strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0;
463 code << " HLTDebug(\"Trying to match input object to class '"
464 << symbol->ObjectClass() << "', trigger name '" << symbol->Name()
465 << "' and block type '%s'\", " << symbol->Name()
466 << "DomainEntry.AsString().Data());" << endl;
470 code << " HLTDebug(\"Trying to match input object to class '"
471 << symbol->ObjectClass() << "' and block type '%s'\", "
472 << symbol->Name() << "DomainEntry.AsString().Data());" << endl;
475 code << " const " << symbol->ObjectClass() << "* " << symbol->Name()
476 << "_object_ = dynamic_cast<const " << symbol->ObjectClass()
477 << "*>(_object_);" << endl;
478 code << " if (" << symbol->Name() << "_object_ != NULL and ";
481 code << "strcmp(" << symbol->Name() << "_object_->Name(), \""
482 << symbol->Name() << "\") == 0 and ";
484 code << symbol->Name() << "DomainEntry == _type_spec_) {" << endl;
485 TString fullname = symbol->Name();
486 fullname += "_object_";
487 expr.ReplaceAll("this", fullname);
488 code << " this->" << symbol->Name() << " = " << expr.Data() << ";" << endl;
491 code << " this->" << symbol->Name() << "TriggerDomain = "
492 << fullname.Data() << "->TriggerDomain();" << endl;
496 code << " HLTDebug(\"Added TObject %p with class name '%s' to variable "
497 << symbol->Name() << "\", _object_, _object_->ClassName());" << endl;
498 code << " _object_assigned_ = true;" << endl;
500 code << " }" << endl;
504 code << " if (not _object_assigned_) HLTDebug(\"Did not assign TObject %p"
505 " with class name '%s' to any variable.\", _object_, _object_->ClassName());"
508 code << " }" << endl;
510 // Generate the CalculateTriggerDecision method.
511 code << " virtual bool CalculateTriggerDecision(AliHLTTriggerDomain& _domain_, TString& _description_) {" << endl;
514 code << " HLTDebug(\"Calculating global HLT trigger result with trigger object at %p.\", this);" << endl;
516 for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
518 const AliHLTTriggerMenuItem* item = menu->Item(i);
519 TString mergeExpr = item->MergeExpression();
520 for (Int_t j = 0; j < symbols.GetEntriesFast(); j++)
522 AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(j) );
523 if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") != 0) continue;
524 TString newname = symbol->Name();
525 newname += "TriggerDomain";
526 mergeExpr.ReplaceAll(symbol->Name(), newname);
530 code << " HLTDebug(\"Trying trigger condition " << i
531 << " (Description = '%s').\", fMenuItemDescription" << i << ".Data());"
534 code << " if (" << item->TriggerCondision() << ") {" << endl;
535 code << " IncrementCounter(" << i << ");" << endl;
536 const char* indentation = "";
537 if (item->PreScalar() != 0)
540 code << " if ((GetCounter(" << i << ") % " << item->PreScalar() << ") == 1) {" << endl;
542 code << indentation << " _domain_ = " << mergeExpr.Data() << ";" << endl;
543 code << indentation << " _description_ = fMenuItemDescription" << i << ";" << endl;
546 code << indentation << " HLTDebug(\"Matched trigger condition " << i
547 << " (Description = '%s').\", fMenuItemDescription" << i << ".Data());" << endl;
549 code << indentation << " return true;" << endl;
550 if (item->PreScalar() != 0)
552 code << " }" << endl;
554 code << " }" << endl;
556 code << " return false;" << endl;
557 code << " }" << endl;
559 // Generate the custom Factory class.
560 code << " class FactoryImpl : public AliHLTGlobalTrigger::Factory" << endl;
561 code << " {" << endl;
562 code << " public:" << endl;
563 code << " virtual const char* ClassName() const {" << endl;
564 code << " return \"" << name << "\";" << endl;
565 code << " }" << endl;
566 code << " virtual AliHLTGlobalTrigger* New() const {" << endl;
567 code << " return new " << name << "();" << endl;
568 code << " }" << endl;
569 code << " };" << endl;
571 code << "private:" << endl;
572 // Add the symbols in the trigger menu to the list of private variables.
573 for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
575 AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
576 code << " " << symbol->Type() << " " << symbol->Name() << ";" << endl;
577 if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0)
579 code << " AliHLTTriggerDomain " << symbol->Name() << "TriggerDomain;" << endl;
581 code << " AliHLTDomainEntry " << symbol->Name() << "DomainEntry;" << endl;
583 for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
585 code << " TString fMenuItemDescription" << i << ";" << endl;
587 code << "};" << endl;
589 // Write a global object for the Factory class for automatic registration.
590 code << "namespace {" << endl;
591 code << " const " << name << "::FactoryImpl gkFactoryImpl;" << endl;
592 code << "};" << endl;
596 // Now we need to compile and load the new class.
597 result = LoadTriggerClass(filename, includePaths);
602 int AliHLTGlobalTriggerComponent::LoadTriggerClass(
603 const char* filename, const TClonesArray& includePaths
606 // Loads the code for a custom global trigger class implementation on the fly.
608 TString compiler = gSystem->GetBuildCompilerVersion();
609 if (compiler.Contains("gcc") or compiler.Contains("icc"))
611 TString includePath = "-I${ALICE_ROOT}/include -I${ALICE_ROOT}/HLT/BASE -I${ALICE_ROOT}/HLT/trigger";
612 // Add any include paths that were specified on the command line.
613 for (Int_t i = 0; i < includePaths.GetEntriesFast(); i++)
615 TString path = static_cast<const TObjString*>(includePaths.UncheckedAt(i))->String();
619 gSystem->SetIncludePath(includePath);
620 gSystem->SetFlagsOpt("-O3 -DNDEBUG");
621 gSystem->SetFlagsDebug("-g3 -DDEBUG -D__DEBUG");
626 result = gSystem->CompileMacro(filename, "g");
630 result = gSystem->CompileMacro(filename, "O");
634 HLTFatal("Could not compile and load global trigger menu implementation.");
640 // If we do not support the compiler then try interpret the class instead.
643 Int_t errorcode = TInterpreter::kNoError;
644 gROOT->ProcessLine(cmd, &errorcode);
645 if (errorcode != TInterpreter::kNoError)
647 HLTFatal("Could not load interpreted global trigger menu implementation"
648 " (Interpreter error code = %d).",
659 int AliHLTGlobalTriggerComponent::FindSymbol(const char* name, const TClonesArray& list)
661 // Searches for the named symbol in the given list.
662 // See header for more details.
664 for (int i = 0; i < list.GetEntriesFast(); i++)
666 const AliHLTTriggerMenuSymbol* symbol = dynamic_cast<const AliHLTTriggerMenuSymbol*>( list.UncheckedAt(i) );
667 if (symbol == NULL) continue;
668 if (strcmp(symbol->Name(), name) == 0) return i;
674 int AliHLTGlobalTriggerComponent::BuildSymbolList(const AliHLTTriggerMenu* menu, TClonesArray& list)
676 // Builds the list of symbols to use in the custom global trigger menu
677 // implementation class.
678 // See header for more details.
680 for (UInt_t i = 0; i < menu->NumberOfSymbols(); i++)
682 const AliHLTTriggerMenuSymbol* symbol = menu->Symbol(i);
683 if (FindSymbol(symbol->Name(), list) != -1)
685 HLTError("Multiple symbols with the name '%s' defined in the trigger menu.", symbol->Name());
688 new (list[list.GetEntriesFast()]) AliHLTTriggerMenuSymbol(*symbol);
691 TRegexp exp("[_a-zA-Z][_a-zA-Z0-9]*");
692 for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
694 const AliHLTTriggerMenuItem* item = menu->Item(i);
695 TString str = item->TriggerCondision();
700 Ssiz_t pos = exp.Index(str, &length, start);
701 if (pos == kNPOS) break;
702 TString s = str(pos, length);
705 if (s == "and" or s == "and_eq" or s == "bitand" or s == "bitor" or
706 s == "compl" or s == "not" or s == "not_eq" or s == "or" or
707 s == "or_eq" or s == "xor" or s == "xor_eq" or s == "true" or
711 // Ignore iso646.h and other keywords.
715 if (FindSymbol(s.Data(), list) == -1)
717 AliHLTTriggerMenuSymbol newSymbol;
718 newSymbol.Name(s.Data());
719 newSymbol.Type("bool");
720 newSymbol.ObjectClass("AliHLTTriggerDecision");
721 newSymbol.AssignExpression("this->Result()");
722 newSymbol.DefaultValue("false");
723 new (list[list.GetEntriesFast()]) AliHLTTriggerMenuSymbol(newSymbol);
726 while (start < str.Length());