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