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