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