Fix coding violations
[u/mrichter/AliRoot.git] / HLT / trigger / AliHLTGlobalTriggerComponent.cxx
CommitLineData
3da1c6d7 1// $Id$
1b9a175e 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"
e2bb8ddd 27#include "AliHLTGlobalTriggerDecision.h"
28#include "AliHLTGlobalTrigger.h"
52f67e50 29#include "AliHLTGlobalTriggerConfig.h"
30#include "AliHLTTriggerMenu.h"
474952b2 31#include "AliHLTCTPData.h"
3da1c6d7 32#include "AliCDBManager.h"
33#include "AliCDBStorage.h"
34#include "AliCDBEntry.h"
e2bb8ddd 35#include "TUUID.h"
36#include "TROOT.h"
72bc5ab0 37#include "TSystem.h"
52f67e50 38#include "TRegexp.h"
39#include "TClonesArray.h"
40#include "TObjString.h"
e2bb8ddd 41#include "TSystem.h"
52f67e50 42#include "TInterpreter.h"
d4ed5215 43#include "TDatime.h"
e2bb8ddd 44#include <fstream>
45#include <cerrno>
566a01d0 46#include <cassert>
1b9a175e 47
48ClassImp(AliHLTGlobalTriggerComponent)
49
3da1c6d7 50const char* AliHLTGlobalTriggerComponent::fgkTriggerMenuCDBPath = "HLT/ConfigHLT/HLTGlobalTrigger";
51
1b9a175e 52
53AliHLTGlobalTriggerComponent::AliHLTGlobalTriggerComponent() :
e2bb8ddd 54 AliHLTTrigger(),
52f67e50 55 fTrigger(NULL),
72bc5ab0 56 fDebugMode(false),
566a01d0 57 fRuntimeCompile(true),
58 fSkipCTPCounters(false),
59 fCodeFileName(),
60 fCTPDecisions(NULL)
1b9a175e 61{
62 // Default constructor.
acc7214e 63
64 ClearInfoForNewEvent(false);
1b9a175e 65}
66
67
68AliHLTGlobalTriggerComponent::~AliHLTGlobalTriggerComponent()
69{
70 // Default destructor.
e2bb8ddd 71
72 if (fTrigger != NULL) delete fTrigger;
566a01d0 73
74 if (fCTPDecisions) {
75 fCTPDecisions->Delete();
76 delete fCTPDecisions;
77 }
1b9a175e 78}
79
80
81void AliHLTGlobalTriggerComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier)
82{
83 // Returns the output data size estimate.
84
69452e88 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;
1b9a175e 93}
94
95
52f67e50 96Int_t AliHLTGlobalTriggerComponent::DoInit(int argc, const char** argv)
1b9a175e 97{
e2bb8ddd 98 // Initialises the global trigger component.
99
52f67e50 100 fDebugMode = false;
101 const char* configFileName = NULL;
102 const char* codeFileName = NULL;
e2bb8ddd 103 TString classname;
52f67e50 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;
566a01d0 158 continue;
159 }
160
161 if (strcmp(argv[i], "-cint") == 0)
162 {
163 fRuntimeCompile = false;
52f67e50 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 }
474952b2 190
191 if (strcmp(argv[i], "-skipctp") == 0)
192 {
193 HLTInfo("Skipping CTP counters in trigger decision");
566a01d0 194 fSkipCTPCounters=true;
474952b2 195 continue;
196 }
197
52f67e50 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
3da1c6d7 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
52f67e50 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 }
e2bb8ddd 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
52f67e50 271 fTrigger->FillFromMenu(*menu);
272 fTrigger->ResetCounters(menu->NumberOfItems());
474952b2 273
274 // setup the CTP accounting in AliHLTComponent
566a01d0 275 SetupCTPData();
474952b2 276
acc7214e 277 // Set the default values from the trigger menu.
278 SetDescription(menu->DefaultDescription());
279 SetTriggerDomain(menu->DefaultTriggerDomain());
280
e2bb8ddd 281 return 0;
282}
283
1b9a175e 284
e2bb8ddd 285Int_t AliHLTGlobalTriggerComponent::DoDeinit()
286{
287 // Cleans up the global trigger component.
288
289 if (fTrigger != NULL)
290 {
291 delete fTrigger;
292 fTrigger = NULL;
293 }
72bc5ab0 294
d4ed5215 295 if (!fCodeFileName.IsNull() && gSystem->AccessPathName(fCodeFileName)==0 && !fDebugMode) {
296 fCodeFileName.ReplaceAll(".cxx", "*");
72bc5ab0 297 TString command="rm "; command+=fCodeFileName;
298 gSystem->Exec(command);
299 }
d4ed5215 300 fCodeFileName="";
e2bb8ddd 301
566a01d0 302 if (fCTPDecisions) {
303 fCTPDecisions->Delete();
304 delete fCTPDecisions;
305 }
306 fCTPDecisions=NULL;
307
1b9a175e 308 return 0;
309}
4f1d6b68 310
311
312AliHLTComponent* AliHLTGlobalTriggerComponent::Spawn()
313{
314 // Creates a new object instance.
315
316 return new AliHLTGlobalTriggerComponent;
317}
318
e2bb8ddd 319
320int 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 }
2974f8dc 329
330 AliHLTUInt32_t eventType=0;
331 if (!IsDataEvent(&eventType)) {
332 if (eventType==gkAliEventTypeEndOfRun) PrintStatistics(fTrigger, kHLTLogImportant, 0);
333 return 0;
334 }
335
e2bb8ddd 336 fTrigger->NewEvent();
337
338 // Fill in the input data.
339 const TObject* obj = GetFirstInputObject();
340 while (obj != NULL)
52f67e50 341 {
342 fTrigger->Add(obj, GetDataType(), GetSpecification());
343 obj = GetNextInputObject();
344 }
345
a489a8dd 346 // add trigger decisions for every CTP class
347 const AliHLTCTPData* pCTPData=CTPData();
348 if (pCTPData) {
566a01d0 349 AddCTPDecisions(fTrigger, pCTPData, GetTriggerData());
a489a8dd 350 }
351
52f67e50 352 // Calculate the global trigger result and trigger domain, then create and push
353 // back the new global trigger decision object.
354 TString description;
acc7214e 355 AliHLTTriggerDomain triggerDomain;
356 bool triggerResult = fTrigger->CalculateTriggerDecision(triggerDomain, description);
52f67e50 357
acc7214e 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 );
48d98db9 365
366 // mask the readout list according to the CTP trigger
367 // if the classes have been initialized (mask non-zero)
48d98db9 368 if (pCTPData && pCTPData->Mask()) {
369 AliHLTEventDDL eventDDL=pCTPData->ReadoutList(*GetTriggerData());
370 AliHLTReadoutList ctpreadout(eventDDL);
45398383 371 ctpreadout.Enable(AliHLTReadoutList::kHLT);
372 AliHLTReadoutList maskedList=decision.ReadoutList();
373 maskedList.AndEq(ctpreadout);
374 decision.ReadoutList(maskedList);
48d98db9 375 }
376
566a01d0 377 decision.SetCounters(fTrigger->Counters(), GetEventCount()+1);
d4ed5215 378 static UInt_t lastTime=0;
379 TDatime time;
380 if (time.Get()-lastTime>5) {
381 lastTime=time.Get();
2974f8dc 382 PrintStatistics(fTrigger);
d4ed5215 383 }
52f67e50 384
385 // Add the input objects used to the global decision.
386 obj = GetFirstInputObject();
387 while (obj != NULL)
e2bb8ddd 388 {
389 if (obj->IsA() == AliHLTTriggerDecision::Class())
390 {
52f67e50 391 decision.AddTriggerInput( *static_cast<const AliHLTTriggerDecision*>(obj) );
e2bb8ddd 392 }
393 else
394 {
52f67e50 395 decision.AddInputObject(obj);
e2bb8ddd 396 }
397 obj = GetNextInputObject();
398 }
2974f8dc 399
566a01d0 400 if (!fSkipCTPCounters && CTPData()) decision.AddInputObject(CTPData());
474952b2 401
2974f8dc 402 CreateEventDoneReadoutFilter(decision.TriggerDomain(), 3);
403 CreateEventDoneReadoutFilter(decision.TriggerDomain(), 4);
52f67e50 404 TriggerEvent(&decision);
e2bb8ddd 405 return 0;
406}
407
408
52f67e50 409int AliHLTGlobalTriggerComponent::GenerateTrigger(
410 const AliHLTTriggerMenu* menu, TString& name,
411 const TClonesArray& includePaths, const TClonesArray& includeFiles
412 )
e2bb8ddd 413{
414 // Generates the global trigger class that will implement the specified trigger menu.
52f67e50 415 // See header for more details.
e2bb8ddd 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;
72bc5ab0 429 fCodeFileName = name + ".cxx";
e2bb8ddd 430
52f67e50 431 // Open a text file to write the code and generate the new class.
72bc5ab0 432 fstream code(fCodeFileName.Data(), ios_base::out | ios_base::trunc);
e2bb8ddd 433 if (not code.good())
434 {
72bc5ab0 435 HLTError("Could not open file '%s' for writing.", fCodeFileName.Data());
e2bb8ddd 436 return -EIO;
437 }
438
52f67e50 439 TClonesArray symbols(AliHLTTriggerMenuSymbol::Class());
440 int result = BuildSymbolList(menu, symbols);
441 if (result != 0) return result;
442
566a01d0 443 //code << "#ifndef __CINT__" << endl;
52f67e50 444 code << "#include <cstring>" << endl;
445 code << "#include \"TString.h\"" << endl;
446 code << "#include \"TClonesArray.h\"" << endl;
e2bb8ddd 447 code << "#include \"AliHLTGlobalTrigger.h\"" << endl;
448 code << "#include \"AliHLTGlobalTriggerDecision.h\"" << endl;
52f67e50 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;
566a01d0 455 //code << "#endif //__CINT__" << endl;
52f67e50 456
457 // Add any include files that were specified on the command line.
458 for (Int_t i = 0; i < includeFiles.GetEntriesFast(); i++)
459 {
7da191b6 460 TString file = static_cast<TObjString*>(includeFiles.UncheckedAt(i))->String();
52f67e50 461 code << "#include \"" << file.Data() << "\"" << endl;
462 }
463
e2bb8ddd 464 code << "class " << name << " : public AliHLTGlobalTrigger" << endl;
465 code << "{" << endl;
466 code << "public:" << endl;
52f67e50 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 }
e2bb8ddd 491 code << " }" << endl;
52f67e50 492
e2bb8ddd 493 code << " virtual ~" << name << "() {" << endl;
52f67e50 494 if (fDebugMode)
495 {
496 code << " HLTInfo(\"Deleting instance at %p.\", this);" << endl;
497 }
e2bb8ddd 498 code << " }" << endl;
52f67e50 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) );
f48dcb4e 523 code << " if (strcmp(symbol->Name(), \"" << symbol->RealName() << "\") == 0) {" << endl;
52f67e50 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 }
e2bb8ddd 538 code << " }" << endl;
52f67e50 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 }
e2bb8ddd 560 code << " }" << endl;
52f67e50 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 '"
f48dcb4e 586 << symbol->ObjectClass() << "', trigger name '" << symbol->RealName()
52f67e50 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(), \""
f48dcb4e 604 << symbol->RealName() << "\") == 0 and ";
52f67e50 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 }
e2bb8ddd 630 code << " }" << endl;
52f67e50 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 }
8d0b9722 638 code << " bool result=false;" << endl;
52f67e50 639 for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
640 {
641 const AliHLTTriggerMenuItem* item = menu->Item(i);
f48dcb4e 642 TString triggerCondision = item->TriggerCondision();
52f67e50 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";
f48dcb4e 650 mergeExpr.ReplaceAll(symbol->RealName(), newname);
651 triggerCondision.ReplaceAll(symbol->RealName(), symbol->Name());
52f67e50 652 }
653 if (fDebugMode)
654 {
655 code << " HLTDebug(\"Trying trigger condition " << i
656 << " (Description = '%s').\", fMenuItemDescription" << i << ".Data());"
657 << endl;
658 }
f48dcb4e 659 code << " if (" << triggerCondision << ") {" << endl;
52f67e50 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 }
8d0b9722 667 code << indentation << " _domain_ |= " << mergeExpr.Data() << ";" << endl;
668 code << indentation << " if (!_description_.IsNull()) _description_+= \",\";" << endl;
669 code << indentation << " _description_ += fMenuItemDescription" << i << ";" << endl;
52f67e50 670 if (fDebugMode)
671 {
672 code << indentation << " HLTDebug(\"Matched trigger condition " << i
673 << " (Description = '%s').\", fMenuItemDescription" << i << ".Data());" << endl;
674 }
8d0b9722 675 code << indentation << " result=true;" << endl;
52f67e50 676 if (item->PreScalar() != 0)
677 {
678 code << " }" << endl;
679 }
680 code << " }" << endl;
681 }
8d0b9722 682 code << " return result;" << endl;
e2bb8ddd 683 code << " }" << endl;
52f67e50 684
685 // Generate the custom Factory class.
e2bb8ddd 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;
e2bb8ddd 695 code << " };" << endl;
52f67e50 696
e2bb8ddd 697 code << "private:" << endl;
52f67e50 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 }
e2bb8ddd 713 code << "};" << endl;
e2bb8ddd 714
52f67e50 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;
e2bb8ddd 719
720 code.close();
721
52f67e50 722 // Now we need to compile and load the new class.
72bc5ab0 723 result = LoadTriggerClass(fCodeFileName, includePaths);
52f67e50 724 return result;
725}
726
727
728int 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();
566a01d0 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());
52f67e50 748 // Add any include paths that were specified on the command line.
749 for (Int_t i = 0; i < includePaths.GetEntriesFast(); i++)
750 {
7da191b6 751 TString path = static_cast<TObjString*>(includePaths.UncheckedAt(i))->String();
52f67e50 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.
566a01d0 777 TString cmd = ".x ";
52f67e50 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
795int 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
810int 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
f48dcb4e 827 TRegexp exp("[_a-zA-Z][-_a-zA-Z0-9]*");
3da1c6d7 828 TRegexp hexexp("x[a-fA-F0-9]+");
52f67e50 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;
52f67e50 839 start = pos+length;
840
3da1c6d7 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
52f67e50 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 }
3da1c6d7 870
52f67e50 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
e2bb8ddd 885 return 0;
886}
887
2974f8dc 888int AliHLTGlobalTriggerComponent::PrintStatistics(const AliHLTGlobalTrigger* pTrigger, AliHLTComponentLogSeverity level, int offset) const
889{
890 // print some statistics
8b29f84f 891 int totalEvents=GetEventCount()+offset;
566a01d0 892 for (int i=0; i<pTrigger->Counters().GetSize(); i++) {
8b29f84f 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);
2974f8dc 897 }
2974f8dc 898 return 0;
899}
566a01d0 900
901int 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}