]> git.uio.no Git - u/mrichter/AliRoot.git/blame - HLT/trigger/AliHLTGlobalTriggerComponent.cxx
Changes required to handle software triggers correctly in the global trigger component.
[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///
def2ec97 23/// The AliHLTGlobalTriggerComponent class applies the global HLT trigger to all
1b9a175e 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"
9e14734f 35#include "AliRawDataHeader.h"
e2bb8ddd 36#include "TUUID.h"
37#include "TROOT.h"
72bc5ab0 38#include "TSystem.h"
52f67e50 39#include "TRegexp.h"
40#include "TClonesArray.h"
41#include "TObjString.h"
1b820a65 42#include "TString.h"
52f67e50 43#include "TInterpreter.h"
d4ed5215 44#include "TDatime.h"
81d62bb4 45#include "TClass.h"
d543303d 46#include "TNamed.h"
e2bb8ddd 47#include <fstream>
48#include <cerrno>
566a01d0 49#include <cassert>
81d62bb4 50#include <vector>
51#include <algorithm>
1b9a175e 52
53ClassImp(AliHLTGlobalTriggerComponent)
54
3da1c6d7 55const char* AliHLTGlobalTriggerComponent::fgkTriggerMenuCDBPath = "HLT/ConfigHLT/HLTGlobalTrigger";
56
1b9a175e 57
81d62bb4 58namespace
59{
60 /**
61 * This method is used as a comparison functor with the STL sort routines.
62 */
63 bool AliHLTDescendingNumbers(UInt_t a, UInt_t b)
64 {
65 return a > b;
66 }
67} // end of namespace
68
69
1b9a175e 70AliHLTGlobalTriggerComponent::AliHLTGlobalTriggerComponent() :
e2bb8ddd 71 AliHLTTrigger(),
52f67e50 72 fTrigger(NULL),
72bc5ab0 73 fDebugMode(false),
566a01d0 74 fRuntimeCompile(true),
81d62bb4 75 fDeleteCodeFile(false),
9e14734f 76 fMakeSoftwareTriggers(true),
566a01d0 77 fCodeFileName(),
81d62bb4 78 fClassName(),
79 fCTPDecisions(NULL),
80 fBufferSizeConst(2*(sizeof(AliHLTGlobalTriggerDecision) + sizeof(AliHLTReadoutList))),
81 fBufferSizeMultiplier(1.),
82 fIncludePaths(TObjString::Class()),
1b820a65 83 fIncludeFiles(TObjString::Class()),
6598c82b 84 fLibStateAtLoad(),
3d6ea577 85 fBits(0),
cc095616 86 fDataEventsOnly(true),
87 fMonitorPeriod(-1),
9e14734f 88 fUniqueID(0),
89 fSoftwareTrigger(true, "SOFTWARE"),
90 fTotalEventCounter(0)
1b9a175e 91{
92 // Default constructor.
acc7214e 93
94 ClearInfoForNewEvent(false);
1b9a175e 95}
96
97
98AliHLTGlobalTriggerComponent::~AliHLTGlobalTriggerComponent()
99{
100 // Default destructor.
e2bb8ddd 101
102 if (fTrigger != NULL) delete fTrigger;
566a01d0 103
104 if (fCTPDecisions) {
105 fCTPDecisions->Delete();
106 delete fCTPDecisions;
107 }
1b9a175e 108}
109
110
025443e0 111void AliHLTGlobalTriggerComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& list) const
112{
113 // Returns the kAliHLTDataTypeGlobalTrigger type as output.
114 list.push_back(kAliHLTDataTypeGlobalTrigger);
115}
116
117
1b9a175e 118void AliHLTGlobalTriggerComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier)
119{
120 // Returns the output data size estimate.
121
81d62bb4 122 constBase = fBufferSizeConst;
123 inputMultiplier = fBufferSizeMultiplier;
1b9a175e 124}
125
126
52f67e50 127Int_t AliHLTGlobalTriggerComponent::DoInit(int argc, const char** argv)
1b9a175e 128{
e2bb8ddd 129 // Initialises the global trigger component.
130
52f67e50 131 fDebugMode = false;
81d62bb4 132 fClassName = "";
133 fCodeFileName = "";
134 fDeleteCodeFile = false;
9e14734f 135 fMakeSoftwareTriggers = true;
52f67e50 136 const char* configFileName = NULL;
137 const char* codeFileName = NULL;
81d62bb4 138 fIncludePaths.Clear();
139 fIncludeFiles.Clear();
6598c82b 140 SetBit(kIncludeInput);
3d6ea577 141 fDataEventsOnly = true;
52f67e50 142
143 for (int i = 0; i < argc; i++)
144 {
145 if (strcmp(argv[i], "-config") == 0)
146 {
147 if (configFileName != NULL)
148 {
149 HLTWarning("Trigger configuration macro was already specified."
150 " Will replace previous value given by -config."
151 );
152 }
153 if (argc <= i+1)
154 {
155 HLTError("The trigger configuration macro filename was not specified." );
156 return -EINVAL;
157 }
158 configFileName = argv[i+1];
159 i++;
160 continue;
161 }
162
163 if (strcmp(argv[i], "-includepath") == 0)
164 {
165 if (argc <= i+1)
166 {
167 HLTError("The include path was not specified." );
168 return -EINVAL;
169 }
dda123c3 170 try
171 {
172 new (fIncludePaths[fIncludePaths.GetEntriesFast()]) TObjString(argv[i+1]);
173 }
174 catch (const std::bad_alloc&)
175 {
176 HLTError("Could not allocate more memory for the fIncludePaths array.");
177 return -ENOMEM;
178 }
52f67e50 179 i++;
180 continue;
181 }
182
183 if (strcmp(argv[i], "-include") == 0)
184 {
185 if (argc <= i+1)
186 {
187 HLTError("The include file name was not specified." );
188 return -EINVAL;
189 }
dda123c3 190 try
191 {
192 new (fIncludeFiles[fIncludeFiles.GetEntriesFast()]) TObjString(argv[i+1]);
193 }
194 catch (const std::bad_alloc&)
195 {
196 HLTError("Could not allocate more memory for the fIncludeFiles array.");
197 return -ENOMEM;
198 }
52f67e50 199 i++;
200 continue;
201 }
202
203 if (strcmp(argv[i], "-debug") == 0)
204 {
205 if (fDebugMode == true)
206 {
207 HLTWarning("The debug flag was already specified. Ignoring this instance.");
208 }
209 fDebugMode = true;
566a01d0 210 continue;
211 }
212
213 if (strcmp(argv[i], "-cint") == 0)
214 {
215 fRuntimeCompile = false;
52f67e50 216 continue;
217 }
218
219 if (strcmp(argv[i], "-usecode") == 0)
220 {
221 if (codeFileName != NULL)
222 {
223 HLTWarning("Custom trigger code file was already specified."
224 " Will replace previous value given by -usecode."
225 );
226 }
227 if (argc <= i+1)
228 {
229 HLTError("The custom trigger code filename was not specified." );
230 return -EINVAL;
231 }
232 codeFileName = argv[i+1];
233 if (argc <= i+2)
234 {
235 HLTError("The custom trigger class name was not specified." );
236 return -EINVAL;
237 }
81d62bb4 238 fClassName = argv[i+2];
52f67e50 239 i += 2;
240 continue;
241 }
474952b2 242
243 if (strcmp(argv[i], "-skipctp") == 0)
244 {
245 HLTInfo("Skipping CTP counters in trigger decision");
6598c82b 246 SetBit(kSkipCTP);
247 continue;
248 }
249
250 if (strcmp(argv[i], "-forward-input") == 0)
251 {
252 HLTInfo("Forwarding input objects and trigger decisions");
253 SetBit(kForwardInput);
254 SetBit(kIncludeShort);
255 SetBit(kIncludeInput, false);
256 continue;
257 }
258
d543303d 259 if (strstr(argv[i], "-include-input") == argv[i])
6598c82b 260 {
261 SetBit(kForwardInput,false);
262 TString param=argv[i];
263 param.ReplaceAll("-include-input", "");
264 if (param.CompareTo("=none")==0)
265 {
266 HLTInfo("skipping objects and trigger decisions");
267 SetBit(kIncludeShort, false);
268 SetBit(kIncludeInput, false);
269 }
270 else if (param.CompareTo("=short")==0)
271 {
d543303d 272 HLTInfo("including short info on objects and trigger decisions");
6598c82b 273 SetBit(kIncludeShort);
274 SetBit(kIncludeInput, false);
275 }
d543303d 276 else if (param.CompareTo("=both")==0)
277 {
278 HLTInfo("including input objects, trigger decisions and short info");
279 SetBit(kIncludeShort);
280 SetBit(kIncludeInput);
281 }
6598c82b 282 else if (param.CompareTo("=objects")==0 || param.IsNull())
283 {
284 HLTInfo("including input objects and trigger decisions");
285 SetBit(kIncludeShort, false);
286 SetBit(kIncludeInput);
287 }
288 else
289 {
290 HLTError("unknown parameter '%s' for argument '-include-input'", param.Data());
291 }
474952b2 292 continue;
293 }
3d6ea577 294
295 if (strcmp(argv[i], "-process-all-events") == 0)
296 {
297 fDataEventsOnly = false;
298 continue;
299 }
b375374f 300
301 if (strstr(argv[i], "-monitoring") == argv[i])
302 {
303 TString param=argv[i];
304 param.ReplaceAll("-monitoring", "");
305 if (param.IsNull())
306 {
307 // -monitoring
308 // enable monitoring trigger for all events
309 fMonitorPeriod=0;
310 } else {
311 // -monitoring=n
312 // enable monitoring trigger once every n seconds
313 param.ReplaceAll("=", "");
314 if (param.IsDigit()) {
315 fMonitorPeriod=param.Atoi();
316 } else {
317 HLTError("expecting number as parameter for argument '-monitoring=', got %s, skipping monitoring trigger", param.Data());
318 }
319 }
320 continue;
321 }
9e14734f 322
323 if (strcmp(argv[i], "-dont-make-software-triggers") == 0)
324 {
325 fMakeSoftwareTriggers = false;
326 continue;
327 }
3d6ea577 328
52f67e50 329 HLTError("Unknown option '%s'.", argv[i]);
330 return -EINVAL;
331 } // for loop
332
333 const AliHLTTriggerMenu* menu = NULL;
334 if (configFileName != NULL)
335 {
336 TString cmd = ".x ";
337 cmd += configFileName;
338 gROOT->ProcessLine(cmd);
339 menu = AliHLTGlobalTriggerConfig::Menu();
340 }
341
3da1c6d7 342 // Try load the trigger menu from the CDB if it is not loaded yet with the
343 // -config option
81d62bb4 344 int result = -ENOENT;
345 if (menu == NULL)
3da1c6d7 346 {
81d62bb4 347 result = LoadTriggerMenu(fgkTriggerMenuCDBPath, menu);
3da1c6d7 348 }
52f67e50 349 if (menu == NULL)
350 {
351 HLTError("No trigger menu configuration found or specified.");
81d62bb4 352 return result;
52f67e50 353 }
354
52f67e50 355 if (codeFileName == NULL)
356 {
81d62bb4 357 result = GenerateTrigger(menu, fClassName, fCodeFileName, fIncludePaths, fIncludeFiles);
358 if (result == 0) fDeleteCodeFile = true;
52f67e50 359 }
360 else
361 {
81d62bb4 362 result = LoadTriggerClass(codeFileName, fIncludePaths);
363 if (result == 0) fCodeFileName = codeFileName;
52f67e50 364 }
e2bb8ddd 365 if (result != 0) return result;
366
dda123c3 367 try
368 {
369 fTrigger = AliHLTGlobalTrigger::CreateNew(fClassName.Data());
370 }
371 catch (const std::bad_alloc&)
372 {
373 HLTError("Could not allocate memory for the AliHLTGlobalTrigger instance.");
374 return -ENOMEM;
375 }
e2bb8ddd 376 if (fTrigger == NULL)
377 {
81d62bb4 378 HLTError("Could not create a new instance of '%s'.", fClassName.Data());
e2bb8ddd 379 return -EIO;
380 }
381
52f67e50 382 fTrigger->FillFromMenu(*menu);
325e5e42 383 if (fTrigger->CallFailed()) return -EPROTO;
474952b2 384
385 // setup the CTP accounting in AliHLTComponent
566a01d0 386 SetupCTPData();
474952b2 387
acc7214e 388 // Set the default values from the trigger menu.
389 SetDescription(menu->DefaultDescription());
390 SetTriggerDomain(menu->DefaultTriggerDomain());
391
9e14734f 392 fTotalEventCounter = 0;
e2bb8ddd 393 return 0;
394}
395
1b9a175e 396
e2bb8ddd 397Int_t AliHLTGlobalTriggerComponent::DoDeinit()
398{
399 // Cleans up the global trigger component.
400
401 if (fTrigger != NULL)
402 {
403 delete fTrigger;
404 fTrigger = NULL;
405 }
406
566a01d0 407 if (fCTPDecisions) {
408 fCTPDecisions->Delete();
409 delete fCTPDecisions;
410 }
411 fCTPDecisions=NULL;
81d62bb4 412
413 Int_t result = UnloadTriggerClass(fCodeFileName);
414 if (result != 0) return result;
415
416 if (fDeleteCodeFile and !fCodeFileName.IsNull() && gSystem->AccessPathName(fCodeFileName)==0 && !fDebugMode) {
417 fCodeFileName.ReplaceAll(".cxx", "*");
418 TString command="rm "; command+=fCodeFileName;
419 gSystem->Exec(command);
420 }
421 fCodeFileName="";
422 fDeleteCodeFile=false;
566a01d0 423
1b9a175e 424 return 0;
425}
4f1d6b68 426
427
428AliHLTComponent* AliHLTGlobalTriggerComponent::Spawn()
429{
430 // Creates a new object instance.
dda123c3 431 AliHLTComponent* comp = NULL;
432 try
433 {
434 comp = new AliHLTGlobalTriggerComponent;
435 }
436 catch (const std::bad_alloc&)
437 {
438 HLTError("Could not allocate memory for a new instance of AliHLTGlobalTriggerComponent.");
439 return NULL;
440 }
441 return comp;
4f1d6b68 442}
443
e2bb8ddd 444
445int AliHLTGlobalTriggerComponent::DoTrigger()
446{
447 // This method will apply the global trigger decision.
448
449 if (fTrigger == NULL)
450 {
451 HLTFatal("Global trigger implementation object is NULL!");
452 return -EIO;
453 }
2974f8dc 454
455 AliHLTUInt32_t eventType=0;
456 if (!IsDataEvent(&eventType)) {
457 if (eventType==gkAliEventTypeEndOfRun) PrintStatistics(fTrigger, kHLTLogImportant, 0);
3d6ea577 458 if (fDataEventsOnly)
459 {
2f251ae6 460 IgnoreEvent(); // dont generate any trigger decision.
3d6ea577 461 return 0;
462 }
2974f8dc 463 }
464
81d62bb4 465 // Copy the trigger counters in case we need to set them back to their original
466 // value because the PushBack method fails with ENOSPC.
467 TArrayL64 originalCounters = fTrigger->GetCounters();
325e5e42 468 if (fTrigger->CallFailed()) return -EPROTO;
81d62bb4 469
e2bb8ddd 470 fTrigger->NewEvent();
325e5e42 471 if (fTrigger->CallFailed()) return -EPROTO;
e2bb8ddd 472
473 // Fill in the input data.
474 const TObject* obj = GetFirstInputObject();
475 while (obj != NULL)
52f67e50 476 {
477 fTrigger->Add(obj, GetDataType(), GetSpecification());
325e5e42 478 if (fTrigger->CallFailed()) return -EPROTO;
52f67e50 479 obj = GetNextInputObject();
480 }
481
a489a8dd 482 // add trigger decisions for every CTP class
483 const AliHLTCTPData* pCTPData=CTPData();
484 if (pCTPData) {
566a01d0 485 AddCTPDecisions(fTrigger, pCTPData, GetTriggerData());
a489a8dd 486 }
9e14734f 487
488 bool softwareTriggerIsValid = FillSoftwareTrigger();
489 if (softwareTriggerIsValid)
490 {
491 fTrigger->Add(&fSoftwareTrigger, kAliHLTDataTypeTriggerDecision, kAliHLTVoidDataSpec);
492 }
493
52f67e50 494 // Calculate the global trigger result and trigger domain, then create and push
495 // back the new global trigger decision object.
496 TString description;
acc7214e 497 AliHLTTriggerDomain triggerDomain;
498 bool triggerResult = fTrigger->CalculateTriggerDecision(triggerDomain, description);
325e5e42 499 if (fTrigger->CallFailed()) return -EPROTO;
acc7214e 500 AliHLTGlobalTriggerDecision decision(
501 triggerResult,
502 // The following will cause the decision to be generated with default values
503 // (set in fTriggerDomain and fDescription) if the trigger result is false.
504 (triggerResult == true) ? triggerDomain : GetTriggerDomain(),
505 (triggerResult == true) ? description.Data() : GetDescription()
506 );
48d98db9 507
cc095616 508 decision.SetUniqueID(fUniqueID);
9e14734f 509 decision.SetCounters(fTrigger->GetCounters(), fTotalEventCounter+1);
325e5e42 510 if (fTrigger->CallFailed()) return -EPROTO;
511
2f251ae6 512 TClonesArray shortInfo(TNamed::Class(), GetNumberOfInputBlocks());
52f67e50 513
2f251ae6 514 // Add the input objects used to make the global decision.
52f67e50 515 obj = GetFirstInputObject();
516 while (obj != NULL)
e2bb8ddd 517 {
2f251ae6 518 const AliHLTTriggerDecision* intrig = dynamic_cast<const AliHLTTriggerDecision*>(obj);
519
520 if (TestBit(kForwardInput)) Forward(obj);
521
522 if (TestBit(kIncludeInput))
e2bb8ddd 523 {
2f251ae6 524 if (intrig != NULL)
525 {
526 decision.AddTriggerInput(*intrig);
527 }
528 else
529 {
530 // The const_cast should be safe in this case because the list of inputObjects
531 // will be added to the global decision with AddInputObjectRef, which only
532 // modifies the kCanDelete bit and nothing else.
533 // This is necessary since GetFirstInputObject only returns const objects.
534 decision.AddInputObjectRef( const_cast<TObject*>(obj) );
535 }
e2bb8ddd 536 }
2f251ae6 537
538 if (TestBit(kIncludeShort))
e2bb8ddd 539 {
2f251ae6 540 int entries = shortInfo.GetEntriesFast();
dda123c3 541 try
542 {
2f251ae6 543 new (shortInfo[entries]) TNamed(obj->GetName(), obj->GetTitle());
dda123c3 544 }
545 catch (const std::bad_alloc&)
546 {
547 HLTError("Could not allocate more memory for the short list of input objects.");
dda123c3 548 return -ENOMEM;
549 }
2f251ae6 550 if (intrig != NULL)
551 {
552 shortInfo[entries]->SetBit(BIT(16)); // indicate that this is a trigger decision
553 shortInfo[entries]->SetBit(BIT(15), intrig->Result());
d543303d 554 }
555 }
556
e2bb8ddd 557 obj = GetNextInputObject();
558 }
2f251ae6 559 if (TestBit(kIncludeShort)) decision.AddInputObjectRef(&shortInfo);
560
561 // The const_cast should be safe in this case because AddInputObjectRef just
562 // modifies the kCanDelete bit and nothing else.
563 if (!TestBit(kSkipCTP) && CTPData()) decision.AddInputObjectRef(const_cast<AliHLTCTPData*>(CTPData()));
564
9e14734f 565 if (softwareTriggerIsValid and TestBit(kIncludeInput)) decision.AddTriggerInput(fSoftwareTrigger);
566
2f251ae6 567 static UInt_t lastTime=0;
568 TDatime time;
569 if (time.Get()-lastTime>60) {
570 lastTime=time.Get();
571 PrintStatistics(fTrigger, kHLTLogImportant);
d543303d 572 }
2974f8dc 573
0744f75d 574 // add readout filter to event done data
2974f8dc 575 CreateEventDoneReadoutFilter(decision.TriggerDomain(), 3);
b375374f 576
577 // add monitoring filter to event done data if enabled by setting
578 // a monitoring period >=0: -1 means off, 0 means for every event
579 // configured by argument '-monitoring[=n]'
580 if (fMonitorPeriod>=0) {
581 static UInt_t lastMonitorEvent=0;
582
583 AliHLTTriggerDomain monitoringFilter(decision.TriggerDomain());
584 if (decision.Result() &&
dd2e5959 585 int(time.Get()-lastMonitorEvent)>fMonitorPeriod) {
b375374f 586 lastMonitorEvent=time.Get();
587 // add monitoring event command for triggered events
588 CreateEventDoneReadoutFilter(decision.TriggerDomain(), 5);
589 } else {
590 // empty filter list if events are not triggered
591 // or within the monitoring interval
592 monitoringFilter.Clear();
593 }
594 // add monitoring filter list
595 CreateEventDoneReadoutFilter(monitoringFilter, 4);
0744f75d 596 }
b375374f 597
52fec07c 598 if (TriggerEvent(&decision, kAliHLTDataTypeGlobalTrigger) == -ENOSPC)
81d62bb4 599 {
600 // Increase the estimated buffer space required if the PushBack methods in TriggerEvent
601 // returned the "no buffer space" error code. Also remember to set the trigger counters
602 // back to what they were, otherwise triggers will be double counted when we try to reprocess
603 // this event with larger buffers.
604 fBufferSizeConst += 1024*1024;
605 fBufferSizeMultiplier *= 2.;
606 fTrigger->SetCounters(originalCounters);
325e5e42 607 if (fTrigger->CallFailed()) return -EPROTO;
81d62bb4 608 return -ENOSPC;
609 }
9e14734f 610
611 ++fTotalEventCounter;
81d62bb4 612 return 0;
613}
614
615
616int AliHLTGlobalTriggerComponent::Reconfigure(const char* cdbEntry, const char* chainId)
617{
618 // Reconfigure the component by loading the trigger menu and recreating the
619 // trigger logic class.
620
621 const char* path = fgkTriggerMenuCDBPath;
622 const char* id = "(unknown)";
623 if (cdbEntry != NULL) path = cdbEntry;
624 if (chainId != NULL and chainId[0] != '\0') id = chainId;
625 HLTInfo("Reconfiguring from '%s' for chain component '%s'.", path, id);
626
627 const AliHLTTriggerMenu* menu = NULL;
628 int result = LoadTriggerMenu(path, menu);
629 if (result != 0) return result;
630
631 TString className;
632 TString codeFileName;
633 result = GenerateTrigger(menu, className, codeFileName, fIncludePaths, fIncludeFiles);
634 if (result != 0) return result;
635
dda123c3 636 AliHLTGlobalTrigger* trigger = NULL;
637 try
638 {
639 trigger = AliHLTGlobalTrigger::CreateNew(className.Data());
640 }
641 catch (const std::bad_alloc&)
642 {
643 HLTError("Could not allocate memory for the AliHLTGlobalTrigger instance.");
644 return -ENOMEM;
645 }
81d62bb4 646 if (trigger == NULL)
647 {
648 HLTError("Could not create a new instance of '%s'.", className.Data());
649 // Make sure to cleanup after the new code file.
650 UnloadTriggerClass(codeFileName);
651 if (not codeFileName.IsNull() and gSystem->AccessPathName(codeFileName)==0 and not fDebugMode)
652 {
653 codeFileName.ReplaceAll(".cxx", "*");
654 TString command="rm "; command+=codeFileName;
655 gSystem->Exec(command);
656 }
657 return -EIO;
658 }
659
660 if (fTrigger != NULL)
661 {
662 delete fTrigger;
663 fTrigger = NULL;
664 }
665
666 fTrigger = trigger;
667 fTrigger->FillFromMenu(*menu);
325e5e42 668 if (fTrigger->CallFailed()) return -EPROTO;
81d62bb4 669
670 // Set the default values from the trigger menu.
671 SetDescription(menu->DefaultDescription());
672 SetTriggerDomain(menu->DefaultTriggerDomain());
673
674 // Cleanup the old class code.
675 UnloadTriggerClass(fCodeFileName);
676 if (fDeleteCodeFile and not fCodeFileName.IsNull() and gSystem->AccessPathName(fCodeFileName)==0 and not fDebugMode)
677 {
678 fCodeFileName.ReplaceAll(".cxx", "*");
679 TString command="rm "; command+=fCodeFileName;
680 gSystem->Exec(command);
681 }
682 fCodeFileName = codeFileName;
683 fDeleteCodeFile = true; // Since we generated a new class.
684
685 return 0;
686}
687
688
689int AliHLTGlobalTriggerComponent::LoadTriggerMenu(const char* cdbPath, const AliHLTTriggerMenu*& menu)
690{
691 // Loads the trigger menu object from the CDB path.
692
693 HLTDebug("Trying to load trigger menu from '%s'.", cdbPath);
694 if (AliCDBManager::Instance() == NULL)
695 {
696 HLTError("CDB manager object not found.");
697 return -EIO;
698 }
699 AliCDBStorage* store = AliCDBManager::Instance()->GetDefaultStorage();
700 if (store == NULL)
701 {
702 HLTError("Could not get the the default storage for the CDB.");
703 return -EIO;
704 }
705 Int_t version = store->GetLatestVersion(cdbPath, GetRunNo());
706 Int_t subVersion = store->GetLatestSubVersion(cdbPath, GetRunNo(), version);
707 AliCDBEntry* entry = AliCDBManager::Instance()->Get(cdbPath, GetRunNo(), version, subVersion);
708 if (entry == NULL)
709 {
710 HLTError("Could not get the CDB entry for \"%s\".", cdbPath);
711 return -EIO;
712 }
713 TObject* obj = entry->GetObject();
714 if (obj == NULL)
715 {
716 HLTError("Configuration object for \"%s\" is missing.", cdbPath);
717 return -ENOENT;
718 }
719 if (obj->IsA() != AliHLTTriggerMenu::Class())
720 {
721 HLTError("Wrong type for configuration object in \"%s\". Found a %s but we expect a AliHLTTriggerMenu.",
722 cdbPath, obj->ClassName()
723 );
724 return -EPROTO;
725 }
726 menu = static_cast<AliHLTTriggerMenu*>(obj);
e2bb8ddd 727 return 0;
728}
729
730
cc095616 731void AliHLTGlobalTriggerComponent::GenerateFileName(TString& name, TString& filename)
579a2996 732{
733 // Creates a unique file name for the generated code.
734
cc095616 735 TUUID guid = GenerateGUID();
736 UChar_t buf[16];
737 guid.GetUUID(buf);
738 fUniqueID = *reinterpret_cast<UInt_t*>(buf);
739 TString guidstr = guid.AsString();
740 // Replace '-' with '_' in string.
741 for (int i = 0; i < guidstr.Length(); ++i)
579a2996 742 {
cc095616 743 if (guidstr[i] == '-') guidstr[i] = '_';
744 }
579a2996 745 name = "AliHLTGlobalTriggerImpl_";
cc095616 746 name += guidstr;
579a2996 747 filename = name + ".cxx";
748
749 // For good measure, check that the file names are not used. If they are then regenerate.
750 fstream file(filename.Data(), ios_base::in);
751 if (file.good())
752 {
753 file.close();
754 GenerateFileName(name, filename);
755 }
756}
757
758
52f67e50 759int AliHLTGlobalTriggerComponent::GenerateTrigger(
81d62bb4 760 const AliHLTTriggerMenu* menu, TString& name, TString& filename,
52f67e50 761 const TClonesArray& includePaths, const TClonesArray& includeFiles
762 )
e2bb8ddd 763{
764 // Generates the global trigger class that will implement the specified trigger menu.
52f67e50 765 // See header for more details.
e2bb8ddd 766
579a2996 767 GenerateFileName(name, filename);
768 HLTDebug("Generating custom HLT trigger class named %s, in file %s, using trigger menu %p.",
769 name.Data(), filename.Data(), ((void*)menu)
770 );
e2bb8ddd 771
52f67e50 772 // Open a text file to write the code and generate the new class.
81d62bb4 773 fstream code(filename.Data(), ios_base::out | ios_base::trunc);
e2bb8ddd 774 if (not code.good())
775 {
81d62bb4 776 HLTError("Could not open file '%s' for writing.", filename.Data());
e2bb8ddd 777 return -EIO;
778 }
779
52f67e50 780 TClonesArray symbols(AliHLTTriggerMenuSymbol::Class());
781 int result = BuildSymbolList(menu, symbols);
782 if (result != 0) return result;
783
81d62bb4 784 code << "#if !defined(__CINT__) || defined(__MAKECINT__)" << endl;
52f67e50 785 code << "#include <cstring>" << endl;
2f251ae6 786 code << "#include \"TClass.h\"" << endl;
52f67e50 787 code << "#include \"TString.h\"" << endl;
788 code << "#include \"TClonesArray.h\"" << endl;
81d62bb4 789 code << "#include \"AliHLTLogging.h\"" << endl;
e2bb8ddd 790 code << "#include \"AliHLTGlobalTrigger.h\"" << endl;
791 code << "#include \"AliHLTGlobalTriggerDecision.h\"" << endl;
52f67e50 792 code << "#include \"AliHLTDomainEntry.h\"" << endl;
793 code << "#include \"AliHLTTriggerDomain.h\"" << endl;
794 code << "#include \"AliHLTReadoutList.h\"" << endl;
795 code << "#include \"AliHLTTriggerMenu.h\"" << endl;
796 code << "#include \"AliHLTTriggerMenuItem.h\"" << endl;
797 code << "#include \"AliHLTTriggerMenuSymbol.h\"" << endl;
798
799 // Add any include files that were specified on the command line.
800 for (Int_t i = 0; i < includeFiles.GetEntriesFast(); i++)
801 {
7da191b6 802 TString file = static_cast<TObjString*>(includeFiles.UncheckedAt(i))->String();
52f67e50 803 code << "#include \"" << file.Data() << "\"" << endl;
804 }
805
81d62bb4 806 if (fDebugMode)
807 {
808 code << "#else" << endl;
809 code << "const char* gFunctionName = \"???\";" << endl;
810 code << "#define HLTDebug(msg) if (CheckFilter(kHLTLogDebug) && CheckGroup(Class_Name())) SendMessage(kHLTLogDebug, Class_Name(), ::gFunctionName, __FILE__, __LINE__, msg)" << endl;
811 }
812 code << "#endif" << endl;
813
814 code << "class " << name << " :" << endl;
815 // Add appropriate #ifdef sections since we need to prevent inheritance from
816 // AliHLTGlobalTrigger. CINT does not seem to support multiple inheritance nor
817 // multiple levels of inheritance. Neither of the following schemes worked:
818 //
819 // 1) class AliHLTGlobalTrigger : public AliHLTLogging {};
820 // class AliHLTGlobalTriggerImpl_xyz : public AliHLTGlobalTrigger {};
821 //
822 // 2) class AliHLTGlobalTrigger {};
823 // class AliHLTGlobalTriggerImpl_xyz : public AliHLTGlobalTrigger, public AliHLTLogging {};
824 //
825 // Thus, we are forced to just inherit from AliHLTLogging when running in the CINT
826 // interpreter. But we anyway have to call the global trigger implementation class
827 // through the AliHLTGlobalTriggerWrapper so this is not such a problem.
828 code << "#if !defined(__CINT__) || defined(__MAKECINT__)" << endl;
829 code << " public AliHLTGlobalTrigger," << endl;
830 code << "#endif" << endl;
831 code << " public AliHLTLogging" << endl;
e2bb8ddd 832 code << "{" << endl;
833 code << "public:" << endl;
52f67e50 834
81d62bb4 835 // Generate constructor method.
836 code << " " << name << "() :" << endl;
837 code << "#if !defined(__CINT__) || defined(__MAKECINT__)" << endl;
838 code << " AliHLTGlobalTrigger()," << endl;
839 code << "#endif" << endl;
840 code << " AliHLTLogging()";
52f67e50 841 // Write the symbols in the trigger menu in the initialisation list.
842 for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
843 {
844 code << "," << endl;
845 AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
846 code << " " << symbol->Name() << "()," << endl;
847 if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0)
848 {
849 code << " " << symbol->Name() << "TriggerDomain()," << endl;
850 }
851 code << " " << symbol->Name() << "DomainEntry(kAliHLTAnyDataType)";
852 }
853 for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
854 {
855 code << "," << endl << " fMenuItemDescription" << i << "()";
856 }
857 code << endl << " {" << endl;
858 if (fDebugMode)
859 {
81d62bb4 860 code << "#ifdef __CINT__" << endl;
861 code << " gFunctionName = \"" << name.Data() <<"\";" << endl;
862 code << "#endif" << endl;
52f67e50 863 code << " SetLocalLoggingLevel(kHLTLogAll);" << endl;
81d62bb4 864 code << " HLTDebug(Form(\"Creating new instance at %p.\", this));" << endl;
52f67e50 865 }
e2bb8ddd 866 code << " }" << endl;
52f67e50 867
e2bb8ddd 868 code << " virtual ~" << name << "() {" << endl;
52f67e50 869 if (fDebugMode)
870 {
81d62bb4 871 code << "#ifdef __CINT__" << endl;
872 code << " gFunctionName = \"~" << name.Data() << "\";" << endl;
873 code << "#endif" << endl;
874 code << " HLTDebug(Form(\"Deleting instance at %p.\", this));" << endl;
52f67e50 875 }
e2bb8ddd 876 code << " }" << endl;
52f67e50 877
878 // Generate the FillFromMenu method.
879 code << " virtual void FillFromMenu(const AliHLTTriggerMenu& menu) {" << endl;
880 if (fDebugMode)
881 {
81d62bb4 882 code << "#ifdef __CINT__" << endl;
883 code << " gFunctionName = \"FillFromMenu\";" << endl;
884 code << "#endif" << endl;
885 code << " HLTDebug(Form(\"Filling description entries from trigger menu for global trigger %p.\", this));" << endl;
52f67e50 886 }
81d62bb4 887 code << " fCounter.Set(menu.NumberOfItems());" << endl;
52f67e50 888 for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
889 {
890 code << " fMenuItemDescription" << i << " = (menu.Item(" << i
891 << ") != NULL) ? menu.Item(" << i << ")->Description() : \"\";" << endl;
892 }
893 if (fDebugMode)
894 {
81d62bb4 895 code << " HLTDebug(Form(\"Finished filling description entries from trigger menu.\"));" << endl;
896 code << " HLTDebug(Form(\"Filling domain entries from trigger menu symbols for global trigger %p.\", this));" << endl;
52f67e50 897 }
898 code << " for (Int_t i = 0; i < menu.SymbolArray().GetEntriesFast(); i++) {" << endl;
325e5e42 899 // 30 Oct 2009 - CINT sometimes evaluates the dynamic_cast incorrectly.
900 // Have to use the TClass system for extra protection.
901 code << " if (menu.SymbolArray().UncheckedAt(i) == NULL) continue;" << endl;
902 code << " if (menu.SymbolArray().UncheckedAt(i)->IsA() != AliHLTTriggerMenuSymbol::Class()) continue;" << endl;
52f67e50 903 code << " const AliHLTTriggerMenuSymbol* symbol = dynamic_cast<const"
904 " AliHLTTriggerMenuSymbol*>(menu.SymbolArray().UncheckedAt(i));" << endl;
905 code << " if (symbol == NULL) continue;" << endl;
906 for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
907 {
908 AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
025443e0 909 code << " if (strcmp(symbol->RealName(), \"" << symbol->RealName() << "\") == 0) {" << endl;
52f67e50 910 if (fDebugMode)
911 {
81d62bb4 912 code << " HLTDebug(Form(\"Assinging domain entry value corresponding with symbol '%s' to '%s'.\","
025443e0 913 " symbol->RealName(), symbol->BlockType().AsString().Data()));" << endl;
52f67e50 914 }
915 code << " " << symbol->Name() << "DomainEntry = symbol->BlockType();" << endl;
916 code << " continue;" << endl;
917 code << " }" << endl;
918 }
919 code << " }" << endl;
2f251ae6 920 // The following is an optimisation where symbols without any assignment operators
921 // are treated as constant and only initialised in FillFromMenu rather than reseting
922 // them in the NewEvent method.
923 // Note: we putting this initialisation into the constructor can lead to seg faults
924 // under CINT interpretation. Thus we must put it into the FillFromMenu method instead.
925 for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
926 {
927 AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
928 if (TString(symbol->AssignExpression()) != "") continue;
929 if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0) continue;
930 // CINT has problems with the implicit equals operator for complex types, so if
931 // the type has an equals operater we need to write the operator call explicitly.
932 TClass* clas = TClass::GetClass(symbol->Type());
933 if (clas != NULL and clas->GetMethodAny("operator=") != NULL)
934 {
935 code << " " << symbol->Name() << ".operator = (" << symbol->DefaultValue() << ");" << endl;
936 }
937 else
938 {
939 code << " " << symbol->Name() << " = " << symbol->DefaultValue() << ";" << endl;
940 }
941 }
52f67e50 942 if (fDebugMode)
943 {
81d62bb4 944 code << " HLTDebug(Form(\"Finished filling domain entries from trigger menu symbols.\"));" << endl;
52f67e50 945 }
e2bb8ddd 946 code << " }" << endl;
52f67e50 947
948 // Generate the NewEvent method.
949 code << " virtual void NewEvent() {" << endl;
950 if (fDebugMode)
951 {
81d62bb4 952 code << "#ifdef __CINT__" << endl;
953 code << " gFunctionName = \"NewEvent\";" << endl;
954 code << "#endif" << endl;
955 code << " HLTDebug(Form(\"New event for global trigger object %p, initialising variables to default values.\", this));" << endl;
52f67e50 956 }
957 // Write code to initialise the symbols in the trigger menu to their default values.
958 for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
959 {
960 AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
2f251ae6 961 // The following is an optimisation. If the symbol does not have an assignment expression
962 // then it is effectively a constant symbol and can be initialised earlier and only once.
963 // In this case we initialise it in the FillFromMenu method instead.
964 if (TString(symbol->AssignExpression()) == "") continue;
81d62bb4 965 // CINT has problems with the implicit equals operator for complex types, so if
2f251ae6 966 // the type has an equals operater we need to write the operator call explicitly.
81d62bb4 967 TClass* clas = TClass::GetClass(symbol->Type());
968 if (clas != NULL and clas->GetMethodAny("operator=") != NULL)
969 {
970 code << " " << symbol->Name() << ".operator = (" << symbol->DefaultValue() << ");" << endl;
971 }
972 else
973 {
974 code << " " << symbol->Name() << " = " << symbol->DefaultValue() << ";" << endl;
975 }
52f67e50 976 if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0)
977 {
978 code << " " << symbol->Name() << "TriggerDomain.Clear();" << endl;
979 }
980 }
981 if (fDebugMode)
982 {
81d62bb4 983 code << " HLTDebug(Form(\"Finished initialising variables.\"));" << endl;
52f67e50 984 }
e2bb8ddd 985 code << " }" << endl;
52f67e50 986
987 // Generate the Add method.
8066c87b 988 bool haveAssignments = false;
989 for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
990 {
991 // First check if we have any symbols with assignment expressions.
992 // This is needed to get rid of the on the fly compilation warning about '_object_' not being used.
993 AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
994 TString expr = symbol->AssignExpression();
995 if (expr == "") continue; // Skip entries that have no assignment expression.
996 haveAssignments = true;
997 break;
998 }
999 if (haveAssignments or fDebugMode)
1000 {
1001 code << " virtual void Add(const TObject* _object_, const AliHLTComponentDataType& _type_, AliHLTUInt32_t _spec_) {" << endl;
1002 }
1003 else
1004 {
1005 code << " virtual void Add(const TObject* /*_object_*/, const AliHLTComponentDataType& _type_, AliHLTUInt32_t _spec_) {" << endl;
1006 }
81d62bb4 1007 if (fDebugMode)
1008 {
1009 code << "#ifdef __CINT__" << endl;
1010 code << " gFunctionName = \"Add\";" << endl;
1011 code << "#endif" << endl;
1012 }
52f67e50 1013 code << " AliHLTDomainEntry _type_spec_(_type_, _spec_);" << endl;
1014 if (fDebugMode)
1015 {
81d62bb4 1016 code << " HLTDebug(Form(\"Adding TObject %p, with class name '%s' from data block"
52f67e50 1017 " '%s', to global trigger object %p\", _object_, _object_->ClassName(),"
81d62bb4 1018 " _type_spec_.AsString().Data(), this));" << endl;
52f67e50 1019 code << " _object_->Print();" << endl;
1020 code << " bool _object_assigned_ = false;" << endl;
1021 }
1022 for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
1023 {
1024 // Write code to check if the block type, specification and class name is correct.
1025 // Then write code to assign the variable from the input object.
1026 AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
1027 TString expr = symbol->AssignExpression();
1028 if (expr == "") continue; // Skip entries that have no assignment expression.
1029 bool isTrigDecision = strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0;
1030 if (fDebugMode)
1031 {
1032 if (isTrigDecision)
1033 {
81d62bb4 1034 code << " HLTDebug(Form(\"Trying to match input object to class '"
f48dcb4e 1035 << symbol->ObjectClass() << "', trigger name '" << symbol->RealName()
52f67e50 1036 << "' and block type '%s'\", " << symbol->Name()
81d62bb4 1037 << "DomainEntry.AsString().Data()));" << endl;
52f67e50 1038 }
1039 else
1040 {
81d62bb4 1041 code << " HLTDebug(Form(\"Trying to match input object to class '"
52f67e50 1042 << symbol->ObjectClass() << "' and block type '%s'\", "
81d62bb4 1043 << symbol->Name() << "DomainEntry.AsString().Data()));" << endl;
52f67e50 1044 }
1045 }
325e5e42 1046 // 30 Oct 2009 - CINT sometimes evaluates the dynamic_cast incorrectly.
1047 // Have to use the TClass system for extra protection.
1048 code << " const " << symbol->ObjectClass() << "* " << symbol->Name() << "_object_ = NULL;" << endl;
f1cac1f9 1049 code << " if (_object_->InheritsFrom(" << symbol->ObjectClass() << "::Class())) " << symbol->Name()
52f67e50 1050 << "_object_ = dynamic_cast<const " << symbol->ObjectClass()
1051 << "*>(_object_);" << endl;
81d62bb4 1052 code << " if (" << symbol->Name() << "_object_ != NULL && ";
52f67e50 1053 if (isTrigDecision)
1054 {
1055 code << "strcmp(" << symbol->Name() << "_object_->Name(), \""
e9f09f57 1056 << symbol->RealName() << "\") == 0 && ";
52f67e50 1057 }
1058 code << symbol->Name() << "DomainEntry == _type_spec_) {" << endl;
1059 TString fullname = symbol->Name();
1060 fullname += "_object_";
1061 expr.ReplaceAll("this", fullname);
1062 code << " this->" << symbol->Name() << " = " << expr.Data() << ";" << endl;
1063 if (isTrigDecision)
1064 {
1065 code << " this->" << symbol->Name() << "TriggerDomain = "
1066 << fullname.Data() << "->TriggerDomain();" << endl;
1067 }
1068 if (fDebugMode)
1069 {
81d62bb4 1070 code << " HLTDebug(Form(\"Added TObject %p with class name '%s' to variable "
1071 << symbol->Name() << "\", _object_, _object_->ClassName()));" << endl;
52f67e50 1072 code << " _object_assigned_ = true;" << endl;
1073 }
1074 code << " }" << endl;
1075 }
1076 if (fDebugMode)
1077 {
81d62bb4 1078 code << " if (! _object_assigned_) {" << endl;
1079 code << " HLTDebug(Form(\"Did not assign TObject %p"
1080 " with class name '%s' to any variable.\", _object_, _object_->ClassName()));"
52f67e50 1081 << endl;
81d62bb4 1082 code << " }" << endl;
52f67e50 1083 }
e2bb8ddd 1084 code << " }" << endl;
52f67e50 1085
1086 // Generate the CalculateTriggerDecision method.
81d62bb4 1087 // This requires code to be generated that checks which items in the trigger menu
1088 // have their conditions asserted and then the trigger domain is generated from
1089 // those fired items.
1090 // The processing will start from the highest priority trigger group and stop
1091 // after at least one trigger from the current priority group being processed
1092 // is positive. For each priority group all the trigger menu items are checked.
1093 // Their combined trigger condition expression must be true for the trigger priority
1094 // group to be triggered positive. The full condition expression is formed by
1095 // concatenating the individual condition expressions. If no trailing operators are
1096 // used in the individual expressions then the default condition operator is placed
1097 // between two concatenated condition expressions.
1098 // If a trigger priority group has at least one trigger fired then the trigger domain
1099 // is calculated such that it will give the same result as the concatenated trigger
1100 // domain merging expressions for all the individual trigger menu items with
1101 // positive results. Again, if no trailing operators are used in the individual
1102 // merging expressions then the default domain operator is placed between two
1103 // expression fragments.
52f67e50 1104 code << " virtual bool CalculateTriggerDecision(AliHLTTriggerDomain& _domain_, TString& _description_) {" << endl;
1105 if (fDebugMode)
1106 {
81d62bb4 1107 code << "#ifdef __CINT__" << endl;
1108 code << " gFunctionName = \"CalculateTriggerDecision\";" << endl;
1109 code << "#endif" << endl;
1110 code << " HLTDebug(Form(\"Calculating global HLT trigger result with trigger object at %p.\", this));" << endl;
52f67e50 1111 }
81d62bb4 1112
1113 // Build a list of priorities used in the trigger menu.
1114 std::vector<UInt_t> priorities;
52f67e50 1115 for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
1116 {
1117 const AliHLTTriggerMenuItem* item = menu->Item(i);
81d62bb4 1118 bool priorityNotInList = std::find(priorities.begin(), priorities.end(), item->Priority()) == priorities.end();
1119 if (priorityNotInList) priorities.push_back(item->Priority());
1120 }
1121 std::sort(priorities.begin(), priorities.end(), AliHLTDescendingNumbers);
1122 // From the priority list, build the priority groups in the correct order,
1123 // i.e. highest priority first.
1124 // The priority group is a list of vectors of integers. The integers are the
1125 // index numbers into the trigger menu item list for the items which form part
1126 // of the priority group.
1127 std::vector<std::vector<Int_t> > priorityGroup;
1128 priorityGroup.insert(priorityGroup.begin(), priorities.size(), std::vector<Int_t>());
1129 for (size_t n = 0; n < priorities.size(); n++)
1130 {
1131 UInt_t priority = priorities[n];
1132 for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
52f67e50 1133 {
81d62bb4 1134 const AliHLTTriggerMenuItem* item = menu->Item(i);
1135 if (item->Priority() == priority) priorityGroup[n].push_back(i);
52f67e50 1136 }
81d62bb4 1137 }
1138
1139 for (size_t n = 0; n < priorityGroup.size(); n++)
1140 {
52f67e50 1141 if (fDebugMode)
1142 {
81d62bb4 1143 code << " HLTDebug(Form(\"Processing trigger priority group " << priorities[n] << "\"));" << endl;
52f67e50 1144 }
81d62bb4 1145 code << " ";
1146 if (n == 0) code << "UInt_t ";
1147 code << "_previous_match_ = 0xFFFFFFFF;" << endl;
1148 code << " ";
1149 if (n == 0) code << "bool ";
1150 code << "_trigger_matched_ = false;" << endl;
1151 code << " ";
1152 if (n == 0) code << "bool ";
1153 code << "_group_result_ = false;" << endl;
1154 std::vector<TString> conditionOperator;
1155 conditionOperator.insert(conditionOperator.begin(), priorityGroup[n].size(), TString(""));
1156 std::vector<TString> domainOperator;
1157 domainOperator.insert(domainOperator.begin(), priorityGroup[n].size(), TString(""));
1158 for (size_t m = 0; m < priorityGroup[n].size(); m++)
52f67e50 1159 {
81d62bb4 1160 UInt_t i = priorityGroup[n][m];
1161 const AliHLTTriggerMenuItem* item = menu->Item(i);
1162 TString triggerCondition = item->TriggerCondition();
1163 TString mergeExpr = item->MergeExpression();
1164 // Replace the symbols found in the trigger condition and merging expressions
1165 // with appropriate compilable versions.
1166 for (Int_t j = 0; j < symbols.GetEntriesFast(); j++)
1167 {
1168 AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(j) );
1169 bool symbolNamesDifferent = strcmp(symbol->RealName(), symbol->Name()) != 0;
1170 if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0)
1171 {
1172 TString newname = symbol->Name();
1173 newname += "TriggerDomain";
1174 mergeExpr.ReplaceAll(symbol->RealName(), newname);
1175 }
1176 else
1177 {
1178 if (symbolNamesDifferent) mergeExpr.ReplaceAll(symbol->RealName(), symbol->Name());
1179 }
1180 if (symbolNamesDifferent) triggerCondition.ReplaceAll(symbol->RealName(), symbol->Name());
1181 }
1182 // We allow the trigger conditions and merging expressions to have trailing operators.
1183 // Thus, we need to extract the operators and cleanup the expressions so that they will
1184 // compile. This means that we silently ignore the trailing operator if not needed.
1185 if (ExtractedOperator(triggerCondition, conditionOperator[m]))
1186 {
1187 // If the trailing operator is the same as the default operator then reset
1188 // the value in the operator list so that the default is used in the generated
1189 // code. This creates more compact code.
1190 if (conditionOperator[m] == menu->DefaultConditionOperator()) conditionOperator[m] = "";
1191 }
1192 if (ExtractedOperator(mergeExpr, domainOperator[m]))
1193 {
1194 if (domainOperator[m] == menu->DefaultDomainOperator()) domainOperator[m] = "";
1195 }
1196 if (fDebugMode)
1197 {
1198 code << " HLTDebug(Form(\"Trying trigger condition " << i
1199 << " (Description = '%s').\", fMenuItemDescription" << i << ".Data()));"
1200 << endl;
1201 }
1202 code << " ";
1203 if (n == 0 and m == 0) code << "bool ";
1204 code << "_item_result_ = false;" << endl;
1205 code << " if (" << triggerCondition << ") {" << endl;
1206 code << " ++fCounter[" << i << "];" << endl;
1207 const char* indentation = "";
1208 if (item->PreScalar() != 0)
1209 {
1210 indentation = " ";
1211 code << " if ((fCounter[" << i << "] % " << item->PreScalar() << ") == 1) {" << endl;
1212 }
1213 code << indentation << " _item_result_ = true;" << endl;
1214 if (fDebugMode)
1215 {
1216 code << indentation << " HLTDebug(Form(\"Matched trigger condition " << i
1217 << " (Description = '%s').\", fMenuItemDescription" << i << ".Data()));" << endl;
1218 }
1219 if (item->PreScalar() != 0)
1220 {
1221 code << " }" << endl;
1222 }
1223 code << " }" << endl;
1224 if (m == 0)
1225 {
1226 // Since this is the first item of the trigger group,
1227 // the generated trigger logic can be simplified a little.
1228 code << " _group_result_ = _item_result_;" << endl;
1229 code << " if (_item_result_) {" << endl;
1230 code << " _domain_ = " << mergeExpr.Data() << ";" << endl;
1231 code << " _description_ = fMenuItemDescription" << i << ";" << endl;
1232 code << " _previous_match_ = " << i << ";" << endl;
1233 code << " _trigger_matched_ = true;" << endl;
1234 code << " }" << endl;
1235 }
1236 else
1237 {
325e5e42 1238 if (conditionOperator[m-1] == "")
81d62bb4 1239 {
1240 code << " _group_result_ = _group_result_ "
1241 << menu->DefaultConditionOperator() << " _item_result_;" << endl;
1242 }
1243 else
1244 {
325e5e42 1245 code << " _group_result_ = _group_result_ "
1246 << conditionOperator[m-1] << " _item_result_;" << endl;
81d62bb4 1247 }
1248 code << " if (_item_result_) {" << endl;
1249 code << " if (_trigger_matched_) {" << endl;
325e5e42 1250 bool switchWillBeEmpty = true;
81d62bb4 1251 for (size_t k = 0; k < m; k++)
1252 {
1253 if (domainOperator[k] == "") continue;
1254 switchWillBeEmpty = false;
1255 }
1256 if (switchWillBeEmpty)
1257 {
1258 code << " _domain_ = _domain_ " << menu->DefaultDomainOperator() << " "
1259 << mergeExpr.Data() << ";" << endl;
1260 }
1261 else
1262 {
1263 code << " switch(_previous_match_) {" << endl;
1264 for (size_t k = 0; k < m; k++)
1265 {
1266 if (domainOperator[k] == "") continue;
1267 code << " case " << k << ": _domain_ = _domain_ "
1268 << domainOperator[k] << " " << mergeExpr.Data() << "; break;" << endl;
1269 }
1270 code << " default: _domain_ = _domain_ "
1271 << menu->DefaultDomainOperator() << " " << mergeExpr.Data() << ";" << endl;
1272 code << " }" << endl;
1273 }
1274 code << " _description_ += \",\";" << endl;
1275 code << " _description_ += fMenuItemDescription" << i << ";" << endl;
1276 code << " } else {" << endl;
1277 code << " _domain_ = " << mergeExpr.Data() << ";" << endl;
1278 code << " _description_ = fMenuItemDescription" << i << ";" << endl;
1279 code << " }" << endl;
1280 code << " _previous_match_ = " << i << ";" << endl;
1281 code << " _trigger_matched_ = true;" << endl;
1282 code << " }" << endl;
1283 }
52f67e50 1284 }
81d62bb4 1285 code << " if (_group_result_) {" << endl;
52f67e50 1286 if (fDebugMode)
1287 {
81d62bb4 1288 if (n < priorities.size() - 1)
1289 {
1290 code << " HLTDebug(Form(\"Matched triggers in trigger priority group " << priorities[n]
1291 << ". Stopping processing here because all other trigger groups have lower priority.\"));" << endl;
1292 }
1293 else
1294 {
1295 code << " HLTDebug(Form(\"Matched triggers in trigger priority group " << priorities[n] << ".\"));" << endl;
1296 }
52f67e50 1297 }
81d62bb4 1298 code << " return true;" << endl;
52f67e50 1299 code << " }" << endl;
1300 }
81d62bb4 1301 code << " _domain_.Clear();" << endl;
1302 code << " _description_ = \"\";" << endl;
1303 code << " return false;" << endl;
e2bb8ddd 1304 code << " }" << endl;
52f67e50 1305
81d62bb4 1306 // Generate getter and setter methods for the counters.
1307 code << " const TArrayL64& GetCounters() const { return fCounter; }" << endl;
1308 code << " void SetCounters(const TArrayL64& counters) { fCounter = counters; }" << endl;
52f67e50 1309
e2bb8ddd 1310 code << "private:" << endl;
52f67e50 1311 // Add the symbols in the trigger menu to the list of private variables.
1312 for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
1313 {
1314 AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
1315 code << " " << symbol->Type() << " " << symbol->Name() << ";" << endl;
1316 if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0)
1317 {
1318 code << " AliHLTTriggerDomain " << symbol->Name() << "TriggerDomain;" << endl;
1319 }
1320 code << " AliHLTDomainEntry " << symbol->Name() << "DomainEntry;" << endl;
1321 }
1322 for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
1323 {
1324 code << " TString fMenuItemDescription" << i << ";" << endl;
1325 }
81d62bb4 1326 code << " TArrayL64 fCounter;" << endl;
1327 code << "#if !defined(__CINT__) || defined(__MAKECINT__)" << endl;
1328 code << " ClassDef(" << name.Data() << ", 0)" << endl;
1329 code << "#else" << endl;
1330 code << " virtual const char* Class_Name() const { return \"" << name.Data() << "\"; }" << endl;
1331 code << "#endif" << endl;
e2bb8ddd 1332 code << "};" << endl;
81d62bb4 1333 code << "#if !defined(__CINT__) || defined(__MAKECINT__)" << endl;
1334 code << "ClassImp(" << name.Data() << ")" << endl;
1335 code << "#endif" << endl;
e2bb8ddd 1336
1337 code.close();
1338
52f67e50 1339 // Now we need to compile and load the new class.
81d62bb4 1340 result = LoadTriggerClass(filename, includePaths);
52f67e50 1341 return result;
1342}
1343
1344
1345int AliHLTGlobalTriggerComponent::LoadTriggerClass(
1346 const char* filename, const TClonesArray& includePaths
1347 )
1348{
1349 // Loads the code for a custom global trigger class implementation on the fly.
1350
81d62bb4 1351 HLTDebug("Loading HLT trigger class from file '%s'.", filename);
1352
52f67e50 1353 TString compiler = gSystem->GetBuildCompilerVersion();
566a01d0 1354 if (fRuntimeCompile && (compiler.Contains("gcc") or compiler.Contains("icc")))
1355 {
1356 TString includePath;
1357#if defined(PKGINCLUDEDIR)
1358 // this is especially for the HLT build system where the package is installed
1359 // in a specific directory including proper treatment of include files
1360 includePath.Form("-I%s", PKGINCLUDEDIR);
1361#else
1362 // the default AliRoot behavior, all include files can be found in the
1363 // $ALICE_ROOT subfolders
1364 includePath = "-I${ALICE_ROOT}/include -I${ALICE_ROOT}/HLT/BASE -I${ALICE_ROOT}/HLT/trigger";
1365#endif
52f67e50 1366 // Add any include paths that were specified on the command line.
1367 for (Int_t i = 0; i < includePaths.GetEntriesFast(); i++)
1368 {
7da191b6 1369 TString path = static_cast<TObjString*>(includePaths.UncheckedAt(i))->String();
81d62bb4 1370 includePath += " -I";
52f67e50 1371 includePath += path;
1372 }
81d62bb4 1373 HLTDebug("using include settings: %s", includePath.Data());
52f67e50 1374 gSystem->SetIncludePath(includePath);
1375 gSystem->SetFlagsOpt("-O3 -DNDEBUG");
1376 gSystem->SetFlagsDebug("-g3 -DDEBUG -D__DEBUG");
1377
1378 int result = kTRUE;
1379 if (fDebugMode)
1380 {
1381 result = gSystem->CompileMacro(filename, "g");
1382 }
1383 else
1384 {
1385 result = gSystem->CompileMacro(filename, "O");
1386 }
1387 if (result != kTRUE)
1388 {
1389 HLTFatal("Could not compile and load global trigger menu implementation.");
1390 return -ENOENT;
1391 }
1392 }
1393 else
1394 {
1b820a65 1395 // Store the library state to be checked later in UnloadTriggerClass.
1396 fLibStateAtLoad = gSystem->GetLibraries();
1397
52f67e50 1398 // If we do not support the compiler then try interpret the class instead.
81d62bb4 1399 TString cmd = ".L ";
52f67e50 1400 cmd += filename;
1401 Int_t errorcode = TInterpreter::kNoError;
1402 gROOT->ProcessLine(cmd, &errorcode);
1403 if (errorcode != TInterpreter::kNoError)
1404 {
1405 HLTFatal("Could not load interpreted global trigger menu implementation"
1406 " (Interpreter error code = %d).",
1407 errorcode
1408 );
1409 return -ENOENT;
1410 }
1411 }
1412
1413 return 0;
1414}
1415
1416
81d62bb4 1417int AliHLTGlobalTriggerComponent::UnloadTriggerClass(const char* filename)
1418{
1419 // Unloads the code previously loaded by LoadTriggerClass.
1420
1421 HLTDebug("Unloading HLT trigger class in file '%s'.", filename);
1422
1423 TString compiler = gSystem->GetBuildCompilerVersion();
1424 if (fRuntimeCompile && (compiler.Contains("gcc") or compiler.Contains("icc")))
1425 {
1b820a65 1426 // Generate the library name.
81d62bb4 1427 TString libname = filename;
1428 Ssiz_t dotpos = libname.Last('.');
1429 if (0 <= dotpos and dotpos < libname.Length()) libname[dotpos] = '_';
1430 libname += ".";
1431 libname += gSystem->GetSoExt();
1432
1b820a65 1433 // This is a workaround for a problem with unloading shared libraries in ROOT.
1434 // If the trigger logic library is loaded before the libAliHLTHOMER.so library
1435 // or any other library is loaded afterwards, then during the gInterpreter->UnloadFile
1436 // call all the subsequent libraries get unloded. This means that any objects created
1437 // from classes implemented in the libAliHLTHOMER.so library will generate segfaults
1438 // since the executable code has been unloaded.
1439 // We need to check if there are any more libraries loaded after the class we
1440 // are unloading and in that case don't unload the class.
1441 TString libstring = gSystem->GetLibraries();
1442 TString token, lastlib;
1443 Ssiz_t from = 0;
1444 Int_t numOfLibs = 0, posOfLib = -1;
1445 while (libstring.Tokenize(token, from, " "))
1446 {
1447 ++numOfLibs;
1448 lastlib = token;
1449 if (token.Contains(libname)) posOfLib = numOfLibs;
1450 }
1451 if (numOfLibs != posOfLib)
1452 {
1453 HLTWarning(Form("ROOT limitation! Cannot properly cleanup and unload the shared"
1454 " library '%s' since another library '%s' was loaded afterwards. Trying to"
1455 " unload this library will remove the others and lead to serious memory faults.",
1456 libname.Data(), lastlib.Data()
1457 ));
1458 return 0;
1459 }
1460
81d62bb4 1461 char* path = NULL;
1462 int result = 0;
1463 if ((path = gSystem->DynamicPathName(libname)) != NULL)
1464 {
1465 result = gInterpreter->UnloadFile(path);
1466 delete [] path;
1467 }
1468 if (result != TInterpreter::kNoError) return -ENOENT;
1469 }
1470 else
1471 {
1b820a65 1472 // This is again a workaround for the problem with unloading files in ROOT.
1473 // If the trigger logic class is loaded before the libAliHLTHOMER.so library
1474 // or any other library is loaded afterwards, then during the gInterpreter->UnloadFile
1475 // call all the subsequent libraries get unloded.
1476 // We need to check if the list of loaded libraries has changed since the last
1477 // call to LoadTriggerClass. If it has then don't unload the class.
1478 if (fLibStateAtLoad != gSystem->GetLibraries())
1479 {
1480 TString libstring = gSystem->GetLibraries();
1481 TString token;
1482 Ssiz_t from = 0;
1483 while (libstring.Tokenize(token, from, " "))
1484 {
1485 if (not fLibStateAtLoad.Contains(token)) break;
1486 }
1487 HLTWarning(Form("ROOT limitation! Cannot properly cleanup and unload the file"
1488 " '%s' since another library '%s' was loaded afterwards. Trying to unload"
1489 " this file will remove the other library and lead to serious memory faults.",
1490 filename, token.Data()
1491 ));
1492 return 0;
1493 }
1494
1495 // If we did not compile the trigger logic then remove the interpreted class.
81d62bb4 1496 TString cmd = ".U ";
1497 cmd += filename;
1498 Int_t errorcode = TInterpreter::kNoError;
1499 gROOT->ProcessLine(cmd, &errorcode);
1500 if (errorcode != TInterpreter::kNoError)
1501 {
1502 HLTFatal("Could not unload interpreted global trigger menu implementation"
1503 " (Interpreter error code = %d).",
1504 errorcode
1505 );
1506 return -ENOENT;
1507 }
1508 }
1509
1510 return 0;
1511}
1512
1513
52f67e50 1514int AliHLTGlobalTriggerComponent::FindSymbol(const char* name, const TClonesArray& list)
1515{
1516 // Searches for the named symbol in the given list.
1517 // See header for more details.
1518
1519 for (int i = 0; i < list.GetEntriesFast(); i++)
1520 {
1521 const AliHLTTriggerMenuSymbol* symbol = dynamic_cast<const AliHLTTriggerMenuSymbol*>( list.UncheckedAt(i) );
1522 if (symbol == NULL) continue;
1523 if (strcmp(symbol->Name(), name) == 0) return i;
1524 }
1525 return -1;
1526}
1527
1528
1529int AliHLTGlobalTriggerComponent::BuildSymbolList(const AliHLTTriggerMenu* menu, TClonesArray& list)
1530{
1531 // Builds the list of symbols to use in the custom global trigger menu
1532 // implementation class.
1533 // See header for more details.
1534
025443e0 1535 // Note: when we build the symbol list we must use the symbol name as returned
1536 // by the Name() method and not the RealName() method when using FindSymbol.
1537 // This is so that we avoid problems with the generated code not compiling
1538 // because names like "abc-xyz" and "abc_xyz" are synonymous.
1539 // Name() returns the converted C++ symbol name as used in the generated code.
1540
52f67e50 1541 for (UInt_t i = 0; i < menu->NumberOfSymbols(); i++)
1542 {
1543 const AliHLTTriggerMenuSymbol* symbol = menu->Symbol(i);
1544 if (FindSymbol(symbol->Name(), list) != -1)
1545 {
1546 HLTError("Multiple symbols with the name '%s' defined in the trigger menu.", symbol->Name());
1547 return -EIO;
1548 }
dda123c3 1549 try
1550 {
1551 new (list[list.GetEntriesFast()]) AliHLTTriggerMenuSymbol(*symbol);
1552 }
1553 catch (const std::bad_alloc&)
1554 {
1555 HLTError("Could not allocate more memory for the symbols list when adding a trigger menu symbol.");
1556 return -ENOMEM;
1557 }
52f67e50 1558 }
1559
f48dcb4e 1560 TRegexp exp("[_a-zA-Z][-_a-zA-Z0-9]*");
3da1c6d7 1561 TRegexp hexexp("x[a-fA-F0-9]+");
52f67e50 1562 for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
1563 {
1564 const AliHLTTriggerMenuItem* item = menu->Item(i);
81d62bb4 1565 TString str = item->TriggerCondition();
52f67e50 1566 Ssiz_t start = 0;
1567 do
1568 {
1569 Ssiz_t length = 0;
1570 Ssiz_t pos = exp.Index(str, &length, start);
1571 if (pos == kNPOS) break;
52f67e50 1572 start = pos+length;
1573
3da1c6d7 1574 // Check if there is a numerical character before the found
1575 // regular expression. If so, then the symbol is not a valid one
1576 // and should be skipped.
1577 if (pos > 0)
1578 {
1579 bool notValid = false;
1580 switch (str[pos-1])
1581 {
1582 case '0': case '1': case '2': case '3': case '4':
1583 case '5': case '6': case '7': case '8': case '9':
1584 notValid = true;
1585 break;
1586 default:
1587 notValid = false;
1588 break;
1589 }
1590 if (notValid) continue;
1591 }
1592 TString s = str(pos, length);
1593
52f67e50 1594 if (s == "and" or s == "and_eq" or s == "bitand" or s == "bitor" or
1595 s == "compl" or s == "not" or s == "not_eq" or s == "or" or
1596 s == "or_eq" or s == "xor" or s == "xor_eq" or s == "true" or
1597 s == "false"
1598 )
1599 {
1600 // Ignore iso646.h and other keywords.
1601 continue;
1602 }
3da1c6d7 1603
025443e0 1604 // Need to create the symbols first and check if its name is in the list
1605 // before actually adding it to the symbols list.
1606 AliHLTTriggerMenuSymbol newSymbol;
1607 newSymbol.Name(s.Data());
1608 newSymbol.Type("bool");
1609 newSymbol.ObjectClass("AliHLTTriggerDecision");
1610 newSymbol.AssignExpression("this->Result()");
1611 newSymbol.DefaultValue("false");
1612 if (FindSymbol(newSymbol.Name(), list) == -1)
52f67e50 1613 {
dda123c3 1614 try
1615 {
1616 new (list[list.GetEntriesFast()]) AliHLTTriggerMenuSymbol(newSymbol);
1617 }
1618 catch (const std::bad_alloc&)
1619 {
1620 HLTError("Could not allocate more memory for the symbols list when adding a trigger name symbol.");
1621 return -ENOMEM;
1622 }
52f67e50 1623 }
1624 }
1625 while (start < str.Length());
1626 }
1627
e2bb8ddd 1628 return 0;
1629}
1630
81d62bb4 1631
1632bool AliHLTGlobalTriggerComponent::ExtractedOperator(TString& expr, TString& op)
1633{
1634 // Extracts the trailing operator from the expression.
1635
1636 Ssiz_t i = 0;
1637 // First skip the trailing whitespace.
1638 bool whitespace = true;
1639 for (i = expr.Length()-1; i >= 0 and whitespace; i--)
1640 {
1641 switch (expr[i])
1642 {
1643 case ' ': case '\t': case '\r': case '\n':
1644 whitespace = true;
1645 break;
1646 default:
1647 whitespace = false;
1648 }
1649 }
1650 if (i < 0 or whitespace) return false;
1651
1652 // Now find the first whitespace character before the trailing symbol.
1653 bool nonwhitespace = true;
1654 for (; i >= 0 and nonwhitespace; i--)
1655 {
1656 switch (expr[i])
1657 {
1658 case ' ': case '\t': case '\r': case '\n':
1659 nonwhitespace = false;
1660 break;
1661 default:
1662 nonwhitespace = true;
1663 }
1664 }
1665 if (i < 0 or nonwhitespace) return false;
1666
1667 // Extract the last symbols and check if it is a valid operator.
1668 TString s = expr;
1669 s.Remove(0, i+2);
1670 if (s == "and" or s == "and_eq" or s == "bitand" or s == "bitor" or
1671 s == "compl" or s == "not" or s == "not_eq" or s == "or" or
1672 s == "or_eq" or s == "xor" or s == "xor_eq" or s == "&&" or
1673 s == "&=" or s == "&" or s == "|" or s == "~" or s == "!" or
1674 s == "!=" or s == "||" or s == "|=" or s == "^" or s == "^=" or
1675 s == "==" or s == "+" or s == "-" or s == "*" or s == "/" or
1676 s == "%" or s == ">" or s == "<" or s == ">=" or s == "<="
1677 )
1678 {
1679 expr.Remove(i+1);
1680 op = s;
1681 return true;
1682 }
1683
1684 return false;
1685}
1686
1687
9e14734f 1688bool AliHLTGlobalTriggerComponent::FillSoftwareTrigger()
1689{
1690 // Fills the fSoftwareTrigger structure.
1691 const AliRawDataHeader* cdh;
1692 if (ExtractTriggerData(*GetTriggerData(), NULL, NULL, &cdh, NULL) != 0) return false;
1693 UChar_t l1msg = cdh->GetL1TriggerMessage();
1694 if ((l1msg & 0x1) == 0x0) return false; // skip physics events.
1695 // From here on everything must be a software trigger.
1696 if (((l1msg >> 2) & 0xF) == 0xE)
1697 {
1698 fSoftwareTrigger.Name("START_OF_DATA");
1699 fSoftwareTrigger.Description("Generated internal start of data trigger.");
1700 }
1701 else if (((l1msg >> 2) & 0xF) == 0xF)
1702 {
1703 fSoftwareTrigger.Name("END_OF_DATA");
1704 fSoftwareTrigger.Description("Generated internal end of data trigger.");
1705 }
1706 else if (((l1msg >> 6) & 0x1) == 0x1)
1707 {
1708 fSoftwareTrigger.Name("CALIBRATION");
1709 fSoftwareTrigger.Description("Generated internal calibration trigger.");
1710 }
1711 else
1712 {
1713 fSoftwareTrigger.Name("SOFTWARE");
1714 fSoftwareTrigger.Description("Generated internal software trigger.");
1715 }
1716 UInt_t detectors = cdh->GetSubDetectors();
1717 fSoftwareTrigger.ReadoutList( AliHLTReadoutList(Int_t(detectors)) );
1718 return true;
1719}
1720
1721
2974f8dc 1722int AliHLTGlobalTriggerComponent::PrintStatistics(const AliHLTGlobalTrigger* pTrigger, AliHLTComponentLogSeverity level, int offset) const
1723{
1724 // print some statistics
8b29f84f 1725 int totalEvents=GetEventCount()+offset;
325e5e42 1726 const TArrayL64& counters = pTrigger->GetCounters();
1727 if (pTrigger->CallFailed()) return -EPROTO;
1728 for (int i = 0; i < counters.GetSize(); i++) {
1729 ULong64_t count = counters[i];
8b29f84f 1730 float ratio=0;
1731 if (totalEvents>0) ratio=100*(float)count/totalEvents;
81d62bb4 1732 HLTLog(level, "Item %d: total events: %d - counted events: %llu (%.1f%%)", i, totalEvents, count, ratio);
2974f8dc 1733 }
2974f8dc 1734 return 0;
1735}
566a01d0 1736
1737int AliHLTGlobalTriggerComponent::AddCTPDecisions(AliHLTGlobalTrigger* pTrigger, const AliHLTCTPData* pCTPData, const AliHLTComponentTriggerData* trigData)
1738{
1739 // add trigger decisions for the valid CTP classes
1740 if (!pCTPData || !pTrigger) return 0;
1741
1742 AliHLTUInt64_t triggerMask=pCTPData->Mask();
1743 AliHLTUInt64_t bit0=0x1;
1744 if (!fCTPDecisions) {
dda123c3 1745 try
1746 {
1747 fCTPDecisions=new TClonesArray(AliHLTTriggerDecision::Class(), gkNCTPTriggerClasses);
1748 }
1749 catch (const std::bad_alloc&)
1750 {
1751 HLTError("Could not allocate memory for the CTP decisions array.");
1752 return -ENOMEM;
1753 }
566a01d0 1754 if (!fCTPDecisions) return -ENOMEM;
1755
dda123c3 1756 try
1757 {
1758 fCTPDecisions->ExpandCreate(gkNCTPTriggerClasses);
1759 }
1760 catch (const std::bad_alloc&)
1761 {
1762 HLTError("Could not allocate more memory for the CTP decisions array.");
1763 return -ENOMEM;
1764 }
566a01d0 1765 for (int i=0; i<gkNCTPTriggerClasses; i++) {
1766 const char* name=pCTPData->Name(i);
1767 if (triggerMask&(bit0<<i) && name) {
1768 AliHLTTriggerDecision* pDecision=dynamic_cast<AliHLTTriggerDecision*>(fCTPDecisions->At(i));
1769 assert(pDecision);
1770 if (!pDecision) {
1771 delete fCTPDecisions;
1772 fCTPDecisions=NULL;
1773 return -ENOENT;
1774 }
1775 pDecision->Name(name);
1776 }
1777 }
1778 }
1779
1780 for (int i=0; i<gkNCTPTriggerClasses; i++) {
1781 const char* name=pCTPData->Name(i);
1782 if ((triggerMask&(bit0<<i))==0 || name==NULL) continue;
1783 AliHLTTriggerDecision* pDecision=dynamic_cast<AliHLTTriggerDecision*>(fCTPDecisions->At(i));
1784 HLTDebug("updating CTP trigger decision %d %s (%p casted %p)", i, name, fCTPDecisions->At(i), pDecision);
1785 if (!pDecision) return -ENOENT;
1786
1787 bool result=false;
2f251ae6 1788 // 13 March 2010 - Optimisation:
1789 // Dont use the EvaluateCTPTriggerClass method, which uses slow TFormula objects.
1790 AliHLTUInt64_t triggers = 0;
1791 if (trigData) triggers = pCTPData->ActiveTriggers(*trigData);
1792 else triggers = pCTPData->Triggers();
1793 result = (triggers&((AliHLTUInt64_t)0x1<<i)) ? true : false;
1794 //if (trigData) result=pCTPData->EvaluateCTPTriggerClass(name, *trigData);
1795 //else result=pCTPData->EvaluateCTPTriggerClass(name);
566a01d0 1796 pDecision->Result(result);
1797 pDecision->TriggerDomain().Clear();
1798 if (trigData) pDecision->TriggerDomain().Add(pCTPData->ReadoutList(*trigData));
1799 else pDecision->TriggerDomain().Add(pCTPData->ReadoutList());
1800
1801 pTrigger->Add(fCTPDecisions->At(i), kAliHLTDataTypeTriggerDecision, kAliHLTVoidDataSpec);
325e5e42 1802 if (pTrigger->CallFailed()) return -EPROTO;
566a01d0 1803 }
1804
1805 return 0;
1806}