From 1b9a175e383f96959a8f390b3be62422230d01a8 Mon Sep 17 00:00:00 2001 From: aszostak Date: Thu, 27 Nov 2008 01:55:50 +0000 Subject: [PATCH] Adding trigger domain and trigger decision classes. AliHLTTrigger now produces an AliHLTTriggerDecision object as its result. Also adding a skeleton class for the global HLT trigger component. Cleaning up some documentation. --- HLT/libAliHLTTrigger.pkg | 8 +- HLT/trigger/AliHLTDomainEntry.h | 13 + HLT/trigger/AliHLTGlobalTriggerComponent.cxx | 58 ++ HLT/trigger/AliHLTGlobalTriggerComponent.h | 73 ++ HLT/trigger/AliHLTGlobalTriggerDecision.cxx | 92 +++ HLT/trigger/AliHLTGlobalTriggerDecision.h | 89 ++ HLT/trigger/AliHLTReadoutList.h | 19 + HLT/trigger/AliHLTTrigger.cxx | 23 +- HLT/trigger/AliHLTTrigger.h | 83 +- HLT/trigger/AliHLTTriggerDecision.cxx | 87 ++ HLT/trigger/AliHLTTriggerDecision.h | 148 ++++ HLT/trigger/AliHLTTriggerDomain.cxx | 825 +++++++++++++++++++ HLT/trigger/AliHLTTriggerDomain.h | 412 +++++++++ 13 files changed, 1902 insertions(+), 28 deletions(-) create mode 100644 HLT/trigger/AliHLTGlobalTriggerComponent.cxx create mode 100644 HLT/trigger/AliHLTGlobalTriggerComponent.h create mode 100644 HLT/trigger/AliHLTGlobalTriggerDecision.cxx create mode 100644 HLT/trigger/AliHLTGlobalTriggerDecision.h create mode 100644 HLT/trigger/AliHLTTriggerDecision.cxx create mode 100644 HLT/trigger/AliHLTTriggerDecision.h create mode 100644 HLT/trigger/AliHLTTriggerDomain.cxx create mode 100644 HLT/trigger/AliHLTTriggerDomain.h diff --git a/HLT/libAliHLTTrigger.pkg b/HLT/libAliHLTTrigger.pkg index baa35c6b42b..044d0f546b8 100644 --- a/HLT/libAliHLTTrigger.pkg +++ b/HLT/libAliHLTTrigger.pkg @@ -10,12 +10,18 @@ # will be created from the names of the header files CLASS_HDRS:= \ AliHLTTrigger.h \ + AliHLTTriggerDecision.h \ + AliHLTTriggerDomain.h \ + AliHLTDomainEntry.h \ + AliHLTReadoutList.h \ + AliHLTGlobalTriggerDecision.h \ + AliHLTGlobalTriggerComponent.h \ AliHLTTriggerAgent.h \ AliHLTEventSummary.h \ AliHLTEventSummaryProducerComponent.h \ AliHLTRunSummary.h \ AliHLTRunSummaryProducerComponent.h \ - AliHLTTriggerSelectiveReadoutComponent.h \ + AliHLTTriggerSelectiveReadoutComponent.h \ AliHLTTriggerMonitoringComponent.h diff --git a/HLT/trigger/AliHLTDomainEntry.h b/HLT/trigger/AliHLTDomainEntry.h index 89bb7dee4da..56da6b8978b 100644 --- a/HLT/trigger/AliHLTDomainEntry.h +++ b/HLT/trigger/AliHLTDomainEntry.h @@ -12,6 +12,19 @@ #include "TObject.h" #include "AliHLTDataTypes.h" +/** + * \class AliHLTDomainEntry + * The AliHLTDomainEntry class is used to store information identifying a particular + * HLT internal data block, or set of data blocks using wild card values. This + * class is used by AliHLTTriggerDomain to store a list of data block classes + * that should be readout by the HLT. The information identifying a data block is + * the following: + * - the data block type + * - the data block's origin (detector name) + * - the data block's specification (detector specific bits) + * Several useful operators and methods are defined to help manipulate this + * information in the AliHLTTriggerDomain class. + */ class AliHLTDomainEntry : public TObject { public: diff --git a/HLT/trigger/AliHLTGlobalTriggerComponent.cxx b/HLT/trigger/AliHLTGlobalTriggerComponent.cxx new file mode 100644 index 00000000000..0387d86712a --- /dev/null +++ b/HLT/trigger/AliHLTGlobalTriggerComponent.cxx @@ -0,0 +1,58 @@ +/************************************************************************** + * This file is property of and copyright by the ALICE HLT Project * + * ALICE Experiment at CERN, All rights reserved. * + * * + * Primary Authors: Artur Szostak * + * for The ALICE HLT Project. * + * * + * Permission to use, copy, modify and distribute this software and its * + * documentation strictly for non-commercial purposes is hereby granted * + * without fee, provided that the above copyright notice appears in all * + * copies and that both the copyright notice and this permission notice * + * appear in the supporting documentation. The authors make no claims * + * about the suitability of this software for any purpose. It is * + * provided "as is" without express or implied warranty. * + **************************************************************************/ + +/// @file AliHLTGlobalTriggerComponent.cxx +/// @author Artur Szostak +/// @date 26 Nov 2008 +/// @brief Implementation of the AliHLTGlobalTriggerComponent component class. +/// +/// The AliHLTGlobalTriggerComponentComponent class applies the global HLT trigger to all +/// trigger information produced by components deriving from AliHLTTrigger. + +#include "AliHLTGlobalTriggerComponent.h" + +ClassImp(AliHLTGlobalTriggerComponent) + + +AliHLTGlobalTriggerComponent::AliHLTGlobalTriggerComponent() : + AliHLTTrigger() +{ + // Default constructor. +} + + +AliHLTGlobalTriggerComponent::~AliHLTGlobalTriggerComponent() +{ + // Default destructor. +} + + +void AliHLTGlobalTriggerComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier) +{ + // Returns the output data size estimate. + + constBase = strlen(GetTriggerName()) + 1; + inputMultiplier = 1; +} + + +int AliHLTGlobalTriggerComponent::DoTrigger() +{ + // This method will apply the global trigger decision. + + //TODO + return 0; +} diff --git a/HLT/trigger/AliHLTGlobalTriggerComponent.h b/HLT/trigger/AliHLTGlobalTriggerComponent.h new file mode 100644 index 00000000000..75a8cdebf60 --- /dev/null +++ b/HLT/trigger/AliHLTGlobalTriggerComponent.h @@ -0,0 +1,73 @@ +#ifndef ALIHLTGLOBALTRIGGERCOMPONENT_H +#define ALIHLTGLOBALTRIGGERCOMPONENT_H +/* This file is property of and copyright by the ALICE HLT Project * + * ALICE Experiment at CERN, All rights reserved. * + * See cxx source for full Copyright notice */ + +/// @file AliHLTGlobalTriggerComponent.h +/// @author Artur Szostak +/// @date 26 Nov 2008 +/// @brief Declaration of the AliHLTGlobalTriggerComponent component class. + +#include "AliHLTTrigger.h" + +/** + * \class AliHLTGlobalTriggerComponent + * This class applies the global HLT trigger to all trigger information produced + * by components deriving from AliHLTTrigger. + * Any information delivered by other components in data blocks that contain + * TObjects can also be used for the trigger algorithm. + */ +class AliHLTGlobalTriggerComponent : public AliHLTTrigger +{ + public: + + AliHLTGlobalTriggerComponent(); + virtual ~AliHLTGlobalTriggerComponent(); + + /** + * Inherited from AliHLTTrigger. + * @return string containing the global trigger name. + */ + virtual const char* GetTriggerName() const { return "HLTGlobalTrigger"; }; + + /** + * Returns extra output data types this trigger generates. + * This returns an kAliHLTDataTypeTObject in list. + * @param list [out]: The list of data types to be filled. + */ + virtual void GetOutputDataTypes(AliHLTComponentDataTypeList& list) const + { + list.push_back(kAliHLTDataTypeTObject); + } + + /** + * Get a ratio by how much the data volume is shrunk or enhanced. + * The method returns a size proportional to the trigger name string length + * for constBase, and 1 for inputMultiplier. + * @param constBase [out]: additive part, independent of the + * input data volume + * @param inputMultiplier [out]: multiplication ratio + */ + virtual void GetOutputDataSize(unsigned long& constBase, double& inputMultiplier); + + protected: + + /// Not implemented. Do not allow copying of this object. + AliHLTGlobalTriggerComponent(const AliHLTGlobalTriggerComponent& obj); + /// Not implemented. Do not allow copying of this object. + AliHLTGlobalTriggerComponent& operator = (const AliHLTGlobalTriggerComponent& obj); + + /** + * Applies the global HLT trigger. + * @return Zero is returned on success and a negative error code on failure. + */ + virtual int DoTrigger(); + + private: + + ClassDef(AliHLTGlobalTriggerComponent, 0) // Global HLT trigger component class which produces the final trigger decision and readout list. +}; + +#endif // ALIHLTGLOBALTRIGGERCOMPONENT_H + diff --git a/HLT/trigger/AliHLTGlobalTriggerDecision.cxx b/HLT/trigger/AliHLTGlobalTriggerDecision.cxx new file mode 100644 index 00000000000..e4e74609329 --- /dev/null +++ b/HLT/trigger/AliHLTGlobalTriggerDecision.cxx @@ -0,0 +1,92 @@ +/************************************************************************** + * This file is property of and copyright by the ALICE HLT Project * + * ALICE Experiment at CERN, All rights reserved. * + * * + * Primary Authors: Artur Szostak * + * for The ALICE HLT Project. * + * * + * Permission to use, copy, modify and distribute this software and its * + * documentation strictly for non-commercial purposes is hereby granted * + * without fee, provided that the above copyright notice appears in all * + * copies and that both the copyright notice and this permission notice * + * appear in the supporting documentation. The authors make no claims * + * about the suitability of this software for any purpose. It is * + * provided "as is" without express or implied warranty. * + **************************************************************************/ + +/// @file AliHLTGlobalTriggerDecision.cxx +/// @author Artur Szostak +/// @date 26 Nov 2008 +/// @brief Implementation of the AliHLTGlobalTriggerDecision class. +/// +/// The global trigger decision class stores the global HLT decision. + +#include "AliHLTGlobalTriggerDecision.h" +#include "Riostream.h" + +ClassImp(AliHLTGlobalTriggerDecision) + + +AliHLTGlobalTriggerDecision::AliHLTGlobalTriggerDecision() : + AliHLTTriggerDecision(), + fContributingTriggers(AliHLTTriggerDecision::Class()), + fCounters() +{ + // Default constructor. +} + + +AliHLTGlobalTriggerDecision::AliHLTGlobalTriggerDecision( + bool result, const AliHLTReadoutList& readoutList, + const AliHLTTriggerDomain& triggerDomain, const char* description + ) : + AliHLTTriggerDecision(result, "HLTGlobalTrigger", readoutList, triggerDomain, description), + fContributingTriggers(AliHLTTriggerDecision::Class()), + fCounters() +{ + // Constructor specifying multiple information fields. + + Result(result); +} + + +AliHLTGlobalTriggerDecision::~AliHLTGlobalTriggerDecision() +{ + // Default destructor. +} + + +void AliHLTGlobalTriggerDecision::Print(Option_t* option) const +{ + // Prints the contents of the trigger decision. + + TString opt(option); + if (opt.Contains("short")) + { + cout << "Global "; + AliHLTTriggerDecision::Print(option); + cout << "==================== Input trigger decisions ===================="; + for (Int_t i = 0; i < NumberOfTriggerInputs(); i++) + { + TriggerInput(i)->Print(option); + } + } + else + { + cout << "Global "; + AliHLTTriggerDecision::Print(option); + cout << "#################### Input trigger decisions ####################"; + for (Int_t i = 0; i < NumberOfTriggerInputs(); i++) + { + cout << "-------------------- Input trigger decision " << i << " --------------------"; + TriggerInput(i)->Print(option); + } + cout << "#################### Event class counters ####################"; + cout << "Counter\tValue" << endl; + for (Int_t i = 0; i < fCounters.GetSize(); i++) + { + cout << i << "\t" << fCounters[i] << endl; + } + } +} + diff --git a/HLT/trigger/AliHLTGlobalTriggerDecision.h b/HLT/trigger/AliHLTGlobalTriggerDecision.h new file mode 100644 index 00000000000..c9254d0a799 --- /dev/null +++ b/HLT/trigger/AliHLTGlobalTriggerDecision.h @@ -0,0 +1,89 @@ +#ifndef ALIHLTGLOBALTRIGGERDECISION_H +#define ALIHLTGLOBALTRIGGERDECISION_H +/* This file is property of and copyright by the ALICE HLT Project * + * ALICE Experiment at CERN, All rights reserved. * + * See cxx source for full Copyright notice */ + +/// @file AliHLTGlobalTriggerDecision.h +/// @author Artur Szostak +/// @date 26 Nov 2008 +/// @brief Declaration of the AliHLTGlobalTriggerDecision class storing the global HLT decision. + +#include "AliHLTTriggerDecision.h" +#include "TArrayL.h" + +class AliHLTGlobalTriggerDecision : public AliHLTTriggerDecision +{ + public: + + /** + * Default constructor. + */ + AliHLTGlobalTriggerDecision(); + + /** + * Constructor specifying multiple information fields. + * \param result The result of the global trigger decision. + * \param readoutList The DDL readout list for the global trigger decision. + * \param triggerDomain The trigger domain for the global trigger decision. + * \param description The description of (reason for) the global trigger decision. + */ + AliHLTGlobalTriggerDecision( + bool result, const AliHLTReadoutList& readoutList, + const AliHLTTriggerDomain& triggerDomain, const char* description = "" + ); + + /** + * Default destructor. + */ + virtual ~AliHLTGlobalTriggerDecision(); + + /** + * Inherited from TObject, this prints the contents of the trigger decision. + * \param option Can be "short" which will print the short format. + */ + virtual void Print(Option_t* option = "") const; + + /** + * Returns the number of trigger inputs that contributed to this global trigger decision. + */ + Int_t NumberOfTriggerInputs() const { return fContributingTriggers.GetEntriesFast(); } + + /** + * Returns the i'th trigger input object in fContributingTriggers. + */ + const AliHLTTriggerDecision* TriggerInput(Int_t i) const + { + return static_cast( fContributingTriggers[i] ); + } + + /** + * Returns the list of trigger inputs used when making the global HLT trigger decision. + */ + const TClonesArray& TriggerInputs() const { return fContributingTriggers; } + + /** + * Adds a trigger input to the list of triggers that were considered when making + * this global trigger decision. + * \param decision The trigger decision object to add. + */ + void AddTriggerInput(const AliHLTTriggerDecision& decision) + { + new (fContributingTriggers[fContributingTriggers.GetEntriesFast()]) AliHLTTriggerDecision(decision); + } + + /** + * Returns the event trigger counters associated with the global trigger classes. + */ + const TArrayL& Counters() const { return fCounters; } + + private: + + TClonesArray fContributingTriggers; /// The list of contributing trigger decisions from all AliHLTTrigger components that were considered. + TArrayL fCounters; /// Event trigger counters. One counter for each trigger class in the global trigger. + + ClassDef(AliHLTGlobalTriggerDecision, 1) // Contains the HLT global trigger decision and information contributing to the decision. +}; + +#endif // ALIHLTGLOBALTRIGGERDECISION_H + diff --git a/HLT/trigger/AliHLTReadoutList.h b/HLT/trigger/AliHLTReadoutList.h index 7a9a01b4bef..3117bcc5fe6 100644 --- a/HLT/trigger/AliHLTReadoutList.h +++ b/HLT/trigger/AliHLTReadoutList.h @@ -12,6 +12,25 @@ #include "TObject.h" #include "AliHLTDataTypes.h" +/** + * \class AliHLTReadoutList + * This class is used as an interface or wrapper to the AliHLTEventDDL structure. + * It makes it easy to manipulate the bits in this structure, which define what DDLs + * should be readout by DAQ. + * Several operators are also overloaded which are meant to be used in the trigger + * menu specification for the AliHLTGlobalTrigger. It allows one to construct + * expressions for the readout lists, which is necessary to be able to evaluate + * or compose the final readout list, given multiple input readout lists received + * from individual components that derive from AliHLTTrigger. + * The operators implemented are: + * | applies a bitwise or on the DDL bits. + * & applies a bitwise and on the DDL bits. + * ^ applies a bitwise xor on the DDL bits. + * ~ applies a bitwise not on the DDL bits. + * + synonym for the '|' operator. + * - unsets the bits in readout list A that are set in readout list B. + * This effectively applies A & (A ^ B). + */ class AliHLTReadoutList : public TObject { public: diff --git a/HLT/trigger/AliHLTTrigger.cxx b/HLT/trigger/AliHLTTrigger.cxx index ed33337f379..49f4d8a8e9b 100644 --- a/HLT/trigger/AliHLTTrigger.cxx +++ b/HLT/trigger/AliHLTTrigger.cxx @@ -14,8 +14,16 @@ * provided "as is" without express or implied warranty. * **************************************************************************/ +/// @file AliHLTTrigger.h +/// @author Artur Szostak +/// @date 12 Aug 2008 +/// @brief Implementation of the AliHLTTrigger base component class. +/// +/// The AliHLTTrigger class is the base class from which all HLT trigger components +/// should be derived. + #include "AliHLTTrigger.h" -#include "TObjString.h" +#include "AliHLTTriggerDecision.h" ClassImp(AliHLTTrigger) @@ -26,7 +34,9 @@ AliHLTTrigger::AliHLTTrigger() : fTriggerData(NULL), fDecisionMade(false), fTriggerEventResult(0), - fReadoutList() + fDescription(), + fReadoutList(), + fTriggerDomain() { /// Default constructor sets pointers to NULL. } @@ -42,7 +52,7 @@ void AliHLTTrigger::GetOutputDataSize(unsigned long& constBase, double& inputMul { /// Returns output data size estimate. - constBase = strlen(GetTriggerName()) + sizeof(TObjString) + 1; + constBase = sizeof(AliHLTTriggerDecision); inputMultiplier = 1; } @@ -66,10 +76,6 @@ int AliHLTTrigger::DoEvent(const AliHLTComponentEventData& evtData, AliHLTCompon TriggerEvent(false); } -//TODO -// result = PushBack(&fReadoutList, kAliHLTDataTypeTObject|kAliHLTDataOriginOut); -// if (result != 0) return result; - // Cleanup fEventData = NULL; fTriggerData = NULL; @@ -82,8 +88,7 @@ void AliHLTTrigger::TriggerEvent(bool value) /// Sets the trigger decision for the current event. if (fTriggerEventResult != 0) return; // Do not do anything if a previous call failed. - TObjString triggerResult(GetTriggerName()); - triggerResult.SetBit(BIT(14), value); // Use bit 14 for the boolean decision. + AliHLTTriggerDecision triggerResult(value, GetTriggerName(), fReadoutList, fTriggerDomain, fDescription); fTriggerEventResult = PushBack(&triggerResult, kAliHLTDataTypeTObject|kAliHLTDataOriginOut); } diff --git a/HLT/trigger/AliHLTTrigger.h b/HLT/trigger/AliHLTTrigger.h index 71e107d6602..64d8185ee9b 100644 --- a/HLT/trigger/AliHLTTrigger.h +++ b/HLT/trigger/AliHLTTrigger.h @@ -1,11 +1,22 @@ #ifndef ALIHLTTRIGGER_H #define ALIHLTTRIGGER_H -/* This file is property of and copyright by the ALICE HLT Project * +/* This file is property of and copyright by the ALICE HLT Project * * ALICE Experiment at CERN, All rights reserved. * * See cxx source for full Copyright notice */ +/// @file AliHLTTrigger.cxx +/// @author Artur Szostak +/// @date 12 Aug 2008 +/// @brief Declaration of the AliHLTTrigger base component class. + #include "AliHLTProcessor.h" +#include "AliHLTReadoutList.h" +#include "AliHLTTriggerDomain.h" +/** + * \class AliHLTTrigger + * This is the base class from which all HLT trigger components should inherit. + */ class AliHLTTrigger : public AliHLTProcessor { public: @@ -40,15 +51,14 @@ class AliHLTTrigger : public AliHLTProcessor * Returns extra output data types this trigger generates. * This returns an empty list by default. * @param list [out]: The list of data types to be filled. + * \note The underlying non const version of GetOutputDataTypes adds the value + * kAliHLTDataTypeTObject to the list. */ - virtual void GetOutputDataTypes(AliHLTComponentDataTypeList& list) const - { - list.push_back(kAliHLTDataTypeTObject); - } + virtual void GetOutputDataTypes(AliHLTComponentDataTypeList& /*list*/) const {} /** - * Get a ratio by how much the data volume is shrinked or enhanced. - * The method returns a size proporional to the trigger name string length + * Get a ratio by how much the data volume is shrunk or enhanced. + * The method returns a size proportional to the trigger name string length * for constBase, and 1 for inputMultiplier. * @param constBase [out]: additive part, independent of the * input data volume @@ -65,7 +75,7 @@ class AliHLTTrigger : public AliHLTProcessor /** * This method needs to be implemented by child classes to implement the actual - * trigger algorithm. A possitive trigger decision is made by calling the TriggerEvent + * trigger algorithm. A positive trigger decision is made by calling the TriggerEvent * method with TriggerEvent(true), or TriggerEvent(false) for a negative result * (no trigger). * If the AliHLTComponentEventData structure is needed for the current event being @@ -125,15 +135,48 @@ class AliHLTTrigger : public AliHLTProcessor AliHLTComponent::SetDDLBit(fReadoutList, ddlId, state); } + /** + * Returns the DDL readout list. + */ + const AliHLTReadoutList& GetReadoutList() const { return fReadoutList; } + /** * Returns the DDL readout list for modification by hand. */ - const AliHLTEventDDL& GetReadoutList() const { return fReadoutList; } + AliHLTReadoutList& GetReadoutList() { return fReadoutList; } /** - * Returns the DDL readout list. + * Sets the readout list object. + * \param value The new value to use for the readout list. + */ + void SetReadoutList(const AliHLTReadoutList& value) { fReadoutList = value; } + + /** + * Returns the trigger domain object. */ - AliHLTEventDDL& GetReadoutList() { return fReadoutList; } + const AliHLTTriggerDomain& GetTriggerDomain() const { return fTriggerDomain; } + + /** + * Returns the trigger domain object for modification. + */ + AliHLTTriggerDomain& GetTriggerDomain() { return fTriggerDomain; } + + /** + * Sets the trigger domain object. + * \param value The new value to use for the trigger domain. + */ + void SetTriggerDomain(const AliHLTTriggerDomain& value) { fTriggerDomain = value; } + + /** + * Returns the trigger description string. + */ + const char* GetDescription() const { return fDescription.Data(); } + + /** + * Sets the trigger description string. + * \param value The new value to use for the description string. + */ + void SetDescription(const char* value) { fDescription = value; } private: @@ -155,21 +198,25 @@ class AliHLTTrigger : public AliHLTProcessor /** * Inherited from AliHLTComponent. This method is replaced with one that is * symmetric to GetInputDataTypes that returns void, so we make this method - * private. + * private. The list will always contain kAliHLTDataTypeTObject, including whatever + * values were added by the const version of GetOutputDataTypes. * @param list list to receive the output data types. * @return the number of elements in the list. */ virtual int GetOutputDataTypes(AliHLTComponentDataTypeList& list) { - GetOutputDataTypes(list); + const AliHLTTrigger* t = this; t->GetOutputDataTypes(list); + list.push_back(kAliHLTDataTypeTObject); return list.size(); } - const AliHLTComponentEventData* fEventData; ///! Event data for the current event. Only valid inside DoTrigger. - AliHLTComponentTriggerData* fTriggerData; ///! Trigger data for the current event. Only valid inside DoTrigger. - bool fDecisionMade; ///! Flag indicating if the trigger decision has been made for this trigger yet. - int fTriggerEventResult; ///! Result returned by PushBack method in the TriggerEvent method. - AliHLTEventDDL fReadoutList; ///! The readout DDL list. + const AliHLTComponentEventData* fEventData; //! Event data for the current event. Only valid inside DoTrigger. + AliHLTComponentTriggerData* fTriggerData; //! Trigger data for the current event. Only valid inside DoTrigger. + bool fDecisionMade; //! Flag indicating if the trigger decision has been made for this trigger yet. + int fTriggerEventResult; //! Result returned by PushBack method in the TriggerEvent method. + TString fDescription; //! The description to use for the trigger decision. + AliHLTReadoutList fReadoutList; //! The DDL readout list object for the current event being processed. + AliHLTTriggerDomain fTriggerDomain; //! The trigger domain object for the current event being processed. ClassDef(AliHLTTrigger, 0) // Base class for HLT triggers. diff --git a/HLT/trigger/AliHLTTriggerDecision.cxx b/HLT/trigger/AliHLTTriggerDecision.cxx new file mode 100644 index 00000000000..f9aef3f1642 --- /dev/null +++ b/HLT/trigger/AliHLTTriggerDecision.cxx @@ -0,0 +1,87 @@ +/************************************************************************** + * This file is property of and copyright by the ALICE HLT Project * + * ALICE Experiment at CERN, All rights reserved. * + * * + * Primary Authors: Artur Szostak * + * for The ALICE HLT Project. * + * * + * Permission to use, copy, modify and distribute this software and its * + * documentation strictly for non-commercial purposes is hereby granted * + * without fee, provided that the above copyright notice appears in all * + * copies and that both the copyright notice and this permission notice * + * appear in the supporting documentation. The authors make no claims * + * about the suitability of this software for any purpose. It is * + * provided "as is" without express or implied warranty. * + **************************************************************************/ + +/// @file AliHLTTriggerDecision.cxx +/// @author Artur Szostak +/// @date 21 Nov 2008 +/// @brief Implementation of the AliHLTTriggerDecision class. +/// +/// The trigger decision class stores the HLT decision from an AliHLTTrigger component. + +#include "AliHLTTriggerDecision.h" +#include "Riostream.h" + +ClassImp(AliHLTTriggerDecision) + + +AliHLTTriggerDecision::AliHLTTriggerDecision() : + TObject(), + fName(), + fDescription(), + fReadoutList(), + fTriggerDomain() +{ + // Default constructor. +} + + +AliHLTTriggerDecision::AliHLTTriggerDecision(bool result, const char* name) : + TObject(), + fName(name), + fDescription(), + fReadoutList(), + fTriggerDomain() +{ + // Constructor specifying the name and result of the trigger decision. + + Result(result); +} + + +AliHLTTriggerDecision::AliHLTTriggerDecision( + bool result, const char* name, const AliHLTReadoutList& readoutList, + const AliHLTTriggerDomain& triggerDomain, const char* description + ) : + TObject(), + fName(name), + fDescription(description), + fReadoutList(readoutList), + fTriggerDomain(triggerDomain) +{ + // Constructor specifying all information fields. + + Result(result); +} + + +AliHLTTriggerDecision::~AliHLTTriggerDecision() +{ + // Default destructor. +} + + +void AliHLTTriggerDecision::Print(Option_t* option) const +{ + // Prints the contents of the trigger decision. + + cout << "Trigger (" << fName.Data() << ") result = " << Result() << endl; + TString opt(option); + if (opt.Contains("short")) return; + cout << "Description = \"" << fDescription.Data() << "\"" << endl; + fReadoutList.Print(); + fTriggerDomain.Print(); +} + diff --git a/HLT/trigger/AliHLTTriggerDecision.h b/HLT/trigger/AliHLTTriggerDecision.h new file mode 100644 index 00000000000..dab60b92d0f --- /dev/null +++ b/HLT/trigger/AliHLTTriggerDecision.h @@ -0,0 +1,148 @@ +#ifndef ALIHLTTRIGGERDECISION_H +#define ALIHLTTRIGGERDECISION_H +/* This file is property of and copyright by the ALICE HLT Project * + * ALICE Experiment at CERN, All rights reserved. * + * See cxx source for full Copyright notice */ + +/// @file AliHLTTriggerDecision.h +/// @author Artur Szostak +/// @date 21 Nov 2008 +/// @brief Declaration of the AliHLTTriggerDecision class storing the a AliHLTTrigger component's decision. + +#include "TString.h" +#include "AliHLTReadoutList.h" +#include "AliHLTTriggerDomain.h" + +/** + * \class AliHLTTriggerDecision + * Stores the information and result of a trigger decision made by a component + * deriving from AliHLTTrigger. The information includes the DDL readout list + * indicating which DDLs to readout and the trigger domain specifying which HLT + * raw data blocks to forward to HLTOUT. + */ +class AliHLTTriggerDecision : public TObject +{ + public: + + /** + * Default constructor. + */ + AliHLTTriggerDecision(); + + /** + * Constructor specifying the result and trigger name. + * \param result The result of the trigger decision. + * \param name The name of the trigger decision. Should be the name of the + * AliHLTTrigger component. + */ + AliHLTTriggerDecision(bool result, const char* name); + + /** + * Constructor specifying all information fields. + * \param result The result of the trigger decision. + * \param name The name of the trigger decision. Should be the name of the + * AliHLTTrigger component. + * \param readoutList The DDL readout list for the trigger decision. + * \param triggerDomain The trigger domain for the trigger decision. + * \param description The description of (reason for) the trigger decision. + */ + AliHLTTriggerDecision( + bool result, const char* name, const AliHLTReadoutList& readoutList, + const AliHLTTriggerDomain& triggerDomain, const char* description = "" + ); + + /** + * Default destructor. + */ + virtual ~AliHLTTriggerDecision(); + + /** + * Inherited from TObject. Returns the name of the trigger decision. + */ + virtual const char* GetName() const { return fName.Data(); } + + /** + * Inherited from TObject. This prints the contents of the trigger decision. + * \param option Can be "short" which will print the short format. + */ + virtual void Print(Option_t* option = "") const; + + /** + * Returns the result of the trigger decision. + * \returns true if the event was triggered and should be readout. + */ + bool EventTriggered() const { return Result(); } + + /** + * Returns the result of the trigger decision. + * The decision is stored in bit 15 of the fBits field. + * \returns true if the event was triggered and should be readout. + */ + bool Result() const { return TestBit(15) == 1; } + + /** + * Sets the result of the trigger decision. + * The decision is stored in bit 15 of the fBits field. + * \param value The value to set; true if the event triggered and should be + * readout and false otherwise. + */ + void Result(bool value) { SetBit(15, value); } + + /** + * Returns the name of the trigger decision. + */ + const char* Name() const { return fName.Data(); } + + /** + * Sets the name of the trigger decision. + */ + void Name(const char* name) { fName = name; } + + /** + * Returns the description of (reason for) the trigger decision. + */ + const char* Description() const { return fDescription.Data(); } + + /** + * Sets the description of the trigger decision. + */ + void Description(const char* value) { fDescription = value; } + + /** + * Returns the DDL readout list associated with this trigger decision. + */ + const AliHLTReadoutList& ReadoutList() const { return fReadoutList; } + + /** + * Returns the DDL readout list associated with this trigger decision for + * modification. + */ + AliHLTReadoutList& ReadoutList() { return fReadoutList; } + + /** + * Sets the DDL readout list associated with this trigger decision. + */ + void ReadoutList(const AliHLTReadoutList& value) { fReadoutList = value; } + + /** + * Returns the trigger domain associated with this trigger decision. + */ + const AliHLTTriggerDomain& TriggerDomain() const { return fTriggerDomain; } + + /** + * Sets the trigger domain associated with this trigger decision. + */ + void TriggerDomain(const AliHLTTriggerDomain& value) { fTriggerDomain = value; } + + private: + + TString fName; /// The name of the trigger decision. Should be the name of the trigger component that generated it. + TString fDescription; /// Optional descriptive text giving the reason for the trigger. + AliHLTReadoutList fReadoutList; /// The readout DDL list. + AliHLTTriggerDomain fTriggerDomain; /// The trigger domain associated with this trigger. i.e. the HLT data blocks to read out. + + ClassDef(AliHLTTriggerDecision, 1) // HLT trigger decision object storing information about the readout list, trigger domain and result. +}; + +#endif // ALIHLTTRIGGERDECISION_H + diff --git a/HLT/trigger/AliHLTTriggerDomain.cxx b/HLT/trigger/AliHLTTriggerDomain.cxx new file mode 100644 index 00000000000..7687fe9b2d3 --- /dev/null +++ b/HLT/trigger/AliHLTTriggerDomain.cxx @@ -0,0 +1,825 @@ +/************************************************************************** + * This file is property of and copyright by the ALICE HLT Project * + * ALICE Experiment at CERN, All rights reserved. * + * * + * Primary Authors: Artur Szostak * + * for The ALICE HLT Project. * + * * + * Permission to use, copy, modify and distribute this software and its * + * documentation strictly for non-commercial purposes is hereby granted * + * without fee, provided that the above copyright notice appears in all * + * copies and that both the copyright notice and this permission notice * + * appear in the supporting documentation. The authors make no claims * + * about the suitability of this software for any purpose. It is * + * provided "as is" without express or implied warranty. * + **************************************************************************/ + +/// @file AliHLTTriggerDomain.cxx +/// @author Artur Szostak +/// @date 19 Nov 2008 +/// @brief Implementation of the AliHLTTriggerDomain class. +/// +/// The trigger domain class is the set of HLT raw data block types that should +/// be readout and sent to HLTOUT. + +#include "AliHLTTriggerDomain.h" +#include "AliHLTDomainEntry.h" +#include "Riostream.h" + +ClassImp(AliHLTTriggerDomain) + + +AliHLTTriggerDomain::AliHLTTriggerDomain() : + TObject(), fEntries(AliHLTDomainEntry::Class(), 10) +{ + // Default constructor. +} + + +AliHLTTriggerDomain::AliHLTTriggerDomain(const AliHLTTriggerDomain& domain) : + TObject(domain), + fEntries(AliHLTDomainEntry::Class(), domain.fEntries.GetEntriesFast()) +{ + // Copy constructor performs a deep copy. + // See header file for more details. + + for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++) + { + const AliHLTDomainEntry* entry = static_cast( domain.fEntries[i] ); + new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(*entry); + } +} + + +AliHLTTriggerDomain::~AliHLTTriggerDomain() +{ + // Default destructor. +} + + +void AliHLTTriggerDomain::Add(const AliHLTDomainEntry& entry) +{ + // Adds a new domain entry to the trigger domain. + // See header file for more details. + + AliHLTDomainEntry intersect; + bool anythingRemoved = false; + bool alreadyInSet = false; + + // Get the initial size of the fEntries array since we might add things to the + // end during the calculation. + Int_t count = fEntries.GetEntriesFast(); + + // Go through each entry that is already in fEntries and see if we can remove + // it because it will become redundant, or if we need to patch exclusion entries + // by adding inclusive intersects, or if we do not even need to add the new entry + // because it is already part of the trigger domain. + for (Int_t i = 0; i < count; i++) + { + const AliHLTDomainEntry* ientry = static_cast(fEntries[i]); + if (ientry->Inclusive()) + { + if (entry.SubsetOf(*ientry)) + { + alreadyInSet = true; + } + else if (ientry->SubsetOf(entry)) + { + fEntries.RemoveAt(i); + anythingRemoved = true; + } + } + else + { + if (ientry->SubsetOf(entry)) + { + fEntries.RemoveAt(i); + anythingRemoved = true; + } + else if (entry.SubsetOf(*ientry)) + { + alreadyInSet = false; + } + else if (ientry->IntersectWith(entry, intersect)) + { + new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(kFALSE, intersect); + alreadyInSet = true; + } + } + } + + // Check if we need to compress the array and if we need to add the new entry. + if (anythingRemoved) fEntries.Compress(); + if (not alreadyInSet) + { + new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(kFALSE, entry); + } +} + + +void AliHLTTriggerDomain::Add(const AliHLTComponentDataType& datatype) +{ + // Adds a new domain entry with the given data type to the trigger domain. + // But the data block specification is set to the any matching wild card. + // See header file for more details. + + Add(AliHLTDomainEntry(datatype)); +} + + +void AliHLTTriggerDomain::Add(const char* blocktype, const char* origin) +{ + // Adds a new domain entry with the given data type and origin to the trigger domain. + // But the data block specification is set to the any matching wild card. + // See header file for more details. + + Add(AliHLTDomainEntry(blocktype, origin)); +} + + +void AliHLTTriggerDomain::Add(const AliHLTComponentDataType& datatype, UInt_t spec) +{ + // Adds a new domain entry to the trigger domain with the data type and data block + // specification bits. + // See header file for more details. + + Add(AliHLTDomainEntry(datatype, spec)); +} + + +void AliHLTTriggerDomain::Add(const char* blocktype, const char* origin, UInt_t spec) +{ + // Adds a new domain entry to the trigger domain with the given data type, origin + // and data block specification bits. + // See header file for more details. + + Add(AliHLTDomainEntry(blocktype, origin, spec)); +} + + +void AliHLTTriggerDomain::Remove(const AliHLTDomainEntry& entry) +{ + // Removes the given domain entry from the trigger domain. + // See header file for more details. + + AliHLTDomainEntry intersect; + bool anythingRemoved = false; + bool addToExcludeSet = false; + + // Get the initial size of the fEntries array since we might add things to the + // end during the calculation. + Int_t count = fEntries.GetEntriesFast(); + + // We need to go through all existing entries and see if they need to be removed + // because they would become redundant when we add the new 'entry' to the end of + // the fEntries list. We also need to check if the new entry needs to be added + // at all because the trigger domain might already not contain those entries. + // Lastly, some intersection entries might need to be added to patch up existing + // inclusive trigger domain entries (rules / patterns). + for (Int_t i = 0; i < count; i++) + { + const AliHLTDomainEntry* ientry = static_cast(fEntries[i]); + if (ientry->Inclusive()) + { + if (ientry->SubsetOf(entry)) + { + fEntries.RemoveAt(i); + anythingRemoved = true; + } + else if (entry.SubsetOf(*ientry)) + { + addToExcludeSet = true; + } + else if (ientry->IntersectWith(entry, intersect)) + { + new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(kTRUE, intersect); + } + } + else + { + if (entry.SubsetOf(*ientry)) + { + addToExcludeSet = false; + } + else if (ientry->SubsetOf(entry)) + { + fEntries.RemoveAt(i); + anythingRemoved = true; + } + } + } + + // Check if we need to compress the array and if we need to add the new entry. + if (anythingRemoved) fEntries.Compress(); + if (addToExcludeSet) + { + new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(kTRUE, entry); + } +} + + +void AliHLTTriggerDomain::Remove(const AliHLTComponentDataType& datatype) +{ + // Removes the domain entries that have the given data type from the trigger domain. + // See header file for more details. + + Remove(AliHLTDomainEntry(datatype)); +} + + +void AliHLTTriggerDomain::Remove(const char* blocktype, const char* origin) +{ + // Removes the domain entries that have the given data type and origin from the + // trigger domain. + // See header file for more details. + + Remove(AliHLTDomainEntry(blocktype, origin)); +} + + +void AliHLTTriggerDomain::Remove(const AliHLTComponentDataType& datatype, UInt_t spec) +{ + // Removes the domain entries that have the given data type and data block + // specification bits from the trigger domain. + // See header file for more details. + + Remove(AliHLTDomainEntry(datatype, spec)); +} + + +void AliHLTTriggerDomain::Remove(const char* blocktype, const char* origin, UInt_t spec) +{ + // Removes the domain entries that have the given data type, origin and data + // block specification bits from the trigger domain. + // See header file for more details. + + Remove(AliHLTDomainEntry(blocktype, origin, spec)); +} + + +bool AliHLTTriggerDomain::Contains(const AliHLTDomainEntry& entry) const +{ + // Checks to see if the given domain entry is part of the trigger domain set. + // See header file for more details. + + // Simply go through the whole list of fEntries and for each entry see if the + // given domain entry 'entry' being checked matches. If there is a match then + // update the result depending on the entry type. i.e. set to false if the entry + // in fEntries is an exclusion and set to true if it is an inclusion. + bool result = false; + for (Int_t i = 0; i < fEntries.GetEntriesFast(); i++) + { + const AliHLTDomainEntry* ientry = static_cast(fEntries[i]); + if (ientry->Inclusive()) + { + if (*ientry == entry) result = true; + } + else + { + if (entry.SubsetOf(*ientry)) result = false; + } + } + return result; +} + + +bool AliHLTTriggerDomain::IncludeInReadout(const AliHLTComponentBlockData* block) const +{ + // Checks to see if the given data block is part of the trigger domain set and + // should be readout. + // See header file for more details. + + // Same algorithm as for Contains() but applied directly to the data block + // descriptor structure. + AliHLTDomainEntry blockEntry(block->fDataType, block->fSpecification); + bool result = false; + for (Int_t i = 0; i < fEntries.GetEntriesFast(); i++) + { + const AliHLTDomainEntry* entry = static_cast(fEntries[i]); + if (entry->Inclusive()) + { + if (*entry == block) result = true; + } + else + { + if (blockEntry.SubsetOf(*entry)) result = false; + } + } + return result; +} + + +void AliHLTTriggerDomain::Clear(Option_t* option) +{ + // Clears the trigger domain (Removes all entries). + + fEntries.Clear(option); +} + + +void AliHLTTriggerDomain::Print(Option_t* /*option*/) const +{ + // Prints the trigger domain entries in the order that they are applied. + // See header file for more details. + + cout << "Trigger domain rules (applied in order of first to last):" << endl; + for (Int_t i = 0; i < fEntries.GetEntriesFast(); i++) + { + const AliHLTDomainEntry* entry = static_cast( fEntries[i] ); + if (entry->Inclusive()) + { + cout << "Include "; + } + else + { + cout << "Exclude "; + } + entry->Print(); + } + if (fEntries.GetEntriesFast() == 0) + { + cout << "(empty)" << endl; + } +} + + +AliHLTTriggerDomain& AliHLTTriggerDomain::operator = (const AliHLTTriggerDomain& domain) +{ + // Assignment operator performs a deep copy. + // See header file for more details. + + if (this == &domain) return *this; + TObject::operator = (domain); + fEntries.Clear(); + for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++) + { + const AliHLTDomainEntry* entry = static_cast( domain.fEntries[i] ); + new (fEntries[fEntries.GetEntriesFast()]) AliHLTDomainEntry(*entry); + } + return *this; +} + + +AliHLTTriggerDomain& AliHLTTriggerDomain::operator |= (const AliHLTTriggerDomain& domain) +{ + // This operator performs the set union. + // See header file for more details. + + // Note that we partition the fEntries array into 3 regions for this calculation. + // - 0..entriesCount-1 : contains the initial entries of this trigger domain. + // - entriesCount..startOfIntersects-1 : is space reserved for the new entries + // from 'domain'. + // - startOfIntersects..fEntries.GetEntriesFast()-1 : This will grow as we add + // all the new domain intersections created during the calculation. + // + // Get the number of entries now before we start adding more entries from 'domain'. + Int_t count = fEntries.GetEntriesFast(); + // Mark the start location for new intersection entries. + Int_t startOfIntersects = count + domain.fEntries.GetEntriesFast(); + Int_t newIndex = startOfIntersects; + + // Allocate and initialise a single block of memory so that we do not call new twice. + bool* buffer = new bool[startOfIntersects]; + for (Int_t i = 0; i < startOfIntersects; i++) buffer[i] = false; + bool* removeThisEntry = buffer; + bool* removeDomainEntry = buffer + count; + + AliHLTDomainEntry intersect; + + // The idea behind this algorithm is that we need to add all inclusion domain + // entries from 'domain' to this object that will not be redundant, but for + // the exclusion entries we patch the fEntries rule set by adding the appropriate + // intersections to the end of fEntries. + for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++) + { + const AliHLTDomainEntry* newEntry = static_cast( domain.fEntries[i] ); + for (Int_t j = 0; j < count; j++) + { + const AliHLTDomainEntry* currentEntry = static_cast( fEntries[j] ); + if (currentEntry->Inclusive() and newEntry->Inclusive()) + { + // If either entry is a subset of the other then we do not need to add + // both, so make sure to remove the one that is redundant. + if (newEntry->SubsetOf(*currentEntry)) + { + removeDomainEntry[i] = true; + } + else if (currentEntry->SubsetOf(*newEntry)) + { + removeThisEntry[j] = true; + } + } + else + { + if (newEntry->IntersectWith(*currentEntry, intersect)) + { + // We can remove all intersections that were already added that will + // become redundant when this intersection is added to fEntries. + MarkForDeletionSubsetsOf(intersect, startOfIntersects); + + // Make the new intersection entry an exclusion if the newEntry and + // currentEntry flags are the same. + bool exclude = newEntry->Exclusive() == currentEntry->Exclusive(); + new (fEntries[newIndex++]) AliHLTDomainEntry(exclude, intersect); + + // We can also remove entries that are subsets of another entry in the + // opposite list, since they will be redundant when everything is merged + // together. For example, remove entry x from fEntries if it is a subset + // of entry y in domain.fEntries. + if (currentEntry->IdenticalTo(intersect)) removeThisEntry[j] = true; + if (newEntry->IdenticalTo(intersect)) removeDomainEntry[i] = true; + } + } + } + } + + MergeEntries(removeThisEntry, count, removeDomainEntry, startOfIntersects, domain); + delete [] buffer; + Optimise(); + return *this; +} + + +AliHLTTriggerDomain& AliHLTTriggerDomain::operator ^= (const AliHLTTriggerDomain& domain) +{ + // This operator performs the set union, less the set intersect (something like and xor). + // See header file for more details. + + // Note that we partition the fEntries array into 3 regions for this calculation. + // - 0..entriesCount-1 : contains the initial entries of this trigger domain. + // - entriesCount..startOfIntersects-1 : is space reserved for the new entries + // from 'domain'. + // - startOfIntersects..fEntries.GetEntriesFast()-1 : This will grow as we add + // all the new domain intersections created during the calculation. + // + // Get the number of entries now before we start adding more entries from 'domain'. + Int_t count = fEntries.GetEntriesFast(); + // Mark the start location for new intersection entries. + Int_t startOfIntersects = count + domain.fEntries.GetEntriesFast(); + Int_t newIndex = startOfIntersects; + + // Allocate and initialise a single block of memory so that we do not call new twice. + bool* buffer = new bool[startOfIntersects]; + for (Int_t i = 0; i < startOfIntersects; i++) buffer[i] = false; + bool* removeThisEntry = buffer; + bool* removeDomainEntry = buffer + count; + + AliHLTDomainEntry intersect; + + // This algorithm is similar to the case for the set union (operator |=), except + // that we make sure to remove from the trigger domain all parts where the entries + // from fEntries and domain.fEntries intersect. + // This is done by adding the intersections to the end of fEntries such that they + // effectively remove those overlapping trigger domain entries when calculating + // IncludeInReadout() or Contains(). + for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++) + { + const AliHLTDomainEntry* newEntry = static_cast( domain.fEntries[i] ); + for (Int_t j = 0; j < count; j++) + { + const AliHLTDomainEntry* currentEntry = static_cast( fEntries[j] ); + if (newEntry->IntersectWith(*currentEntry, intersect)) + { + // We can remove all intersections that were already added that will + // become redundant when this intersection is added to fEntries. + MarkForDeletionSubsetsOf(intersect, startOfIntersects); + + // Make the new intersection entry an exclusion if the newEntry and + // currentEntry flags are the same. + bool exclude = newEntry->Exclusive() == currentEntry->Exclusive(); + new (fEntries[newIndex++]) AliHLTDomainEntry(exclude, intersect); + + // We can also remove entries that are subsets of another entry in the + // opposite list, since they will be redundant when everything is merged + // together. For example, remove entry x from fEntries if it is a subset + // of entry y in domain.fEntries. + if (currentEntry->IdenticalTo(intersect)) removeThisEntry[j] = true; + if (newEntry->IdenticalTo(intersect)) removeDomainEntry[i] = true; + } + } + } + + MergeEntries(removeThisEntry, count, removeDomainEntry, startOfIntersects, domain); + delete [] buffer; + Optimise(); + return *this; +} + + +AliHLTTriggerDomain& AliHLTTriggerDomain::operator -= (const AliHLTTriggerDomain& domain) +{ + // This operator performs the set difference. + // See header file for more details. + + // Mark the number of entries in fEntries now before we start adding more + // entries from 'domain' or intersections. + Int_t startOfIntersects = fEntries.GetEntriesFast(); + Int_t newIndex = startOfIntersects; + + AliHLTDomainEntry intersect; + + // To compute the set difference we need to remove all all parts that overlap + // with 'domain'. i.e. we need to find all the intersects between the domain + // entries in fEntries and those in domain.fEntries, and add the intersects + // to the fEntries list, such that they will cancel or remove the overlapping + // parts of the two trigger domains. + for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++) + { + const AliHLTDomainEntry* checkEntry = static_cast( domain.fEntries[i] ); + if (checkEntry->Inclusive()) + { + // For inclusive entries we need to find the overlaps with the inclusive + // entries in fEntries and add exclusive entries that will remove that + // part of the trigger domain set. + for (Int_t j = 0; j < startOfIntersects; j++) + { + AliHLTDomainEntry* currentEntry = static_cast( fEntries[j] ); + + // We only need to consider the case where both entries are inclusive, + // since an exclusion in fEntries already eliminates those data blocks + // from the trigger domain set. + if (currentEntry->Exclusive()) continue; + + if (checkEntry->IntersectWith(*currentEntry, intersect)) + { + // We can remove all intersections that were already added that will + // become redundant when this intersection is added to fEntries. + MarkForDeletionSubsetsOf(intersect, startOfIntersects); + + new (fEntries[newIndex++]) AliHLTDomainEntry(kTRUE, intersect); + if (currentEntry->IdenticalTo(intersect)) + { + currentEntry->SetBit(14, true); + } + } + } + } + else + { + // For an exclusive entry in 'domain' we need to find the intersections with + // all of fEntries and re-apply these with the same exclude flags. + for (Int_t j = 0; j < startOfIntersects; j++) + { + AliHLTDomainEntry* currentEntry = static_cast( fEntries[j] ); + if (checkEntry->IntersectWith(*currentEntry, intersect)) + { + // We can remove all intersections that were already added that will + // become redundant when this intersection is added to fEntries. + MarkForDeletionSubsetsOf(intersect, startOfIntersects); + + new (fEntries[newIndex++]) AliHLTDomainEntry(currentEntry->Exclusive(), intersect); + } + } + } + } + + RemoveMarkedEntries(); + Optimise(); + return *this; +} + + +AliHLTTriggerDomain AliHLTTriggerDomain::operator ~ () const +{ + // Performs a set complement of the trigger domain. + + // The set complement is calculated by creating a new trigger domain which + // accepts all possible data blocks, and then apply all the trigger domain + // entries (rules / patterns) from top to bottom, but apply them with the + // opposite meaning. For example, this->fEntries contains an inclusive domain + // entry then remove it from the new trigger domain 'result', but if it is + // an exclusion then add it. + AliHLTTriggerDomain result; + result.Add(kAliHLTAnyDataType); + for (Int_t i = 0; i < fEntries.GetEntriesFast(); i++) + { + const AliHLTDomainEntry* entry = static_cast( fEntries[i] ); + if (entry->Inclusive()) + { + result.Remove(*entry); + } + else + { + result.Add(*entry); + } + } + return result; +} + + +AliHLTTriggerDomain AliHLTTriggerDomain::operator & (const AliHLTTriggerDomain& domain) const +{ + // This operator finds the set intersect. + // See header file for more details. + + AliHLTTriggerDomain result; + Int_t newIndex = 0; + AliHLTDomainEntry intersect; + + // To find the set intersect we need to compare each entry in 'domain' to those + // of fEntries. For each inclusive entry in 'domain' we need to add to the result + // the intersect between it and each entry of fEntries, with the same exclude flag + // value as the domain entry from fEntries. + // However, in principle, for the exclusion entries in 'domain' we just add them + // to the result, since those entries do not form part of the 'domain' trigger + // domain set, so they should not form part of the result (remember any data block + // must be contained in both trigger domains for a set intersect). + // In actual fact we just add the intersect of the exclusion entries in 'domain' + // with those of fEntries to the result. This has the same overall effect, but + // makes sure that all exclusion entries are always subsets of inclusion entries. + for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++) + { + const AliHLTDomainEntry* checkEntry = static_cast( domain.fEntries[i] ); + if (checkEntry->Inclusive()) + { + for (Int_t j = 0; j < fEntries.GetEntriesFast(); j++) + { + AliHLTDomainEntry* currentEntry = static_cast( fEntries[j] ); + if (checkEntry->IntersectWith(*currentEntry, intersect)) + { + // We can remove all entries that were already added to the result that + // will become redundent because they are subsets of the new entry. + result.MarkForDeletionSubsetsOf(intersect, 0); + + new (result.fEntries[newIndex++]) AliHLTDomainEntry(currentEntry->Exclusive(), intersect); + } + } + } + else + { + for (Int_t j = 0; j < fEntries.GetEntriesFast(); j++) + { + AliHLTDomainEntry* currentEntry = static_cast( fEntries[j] ); + if (checkEntry->IntersectWith(*currentEntry, intersect)) + { + // We can remove all entries that were already added to the result that + // will become redundant because they are subsets of the new entry. + result.MarkForDeletionSubsetsOf(intersect, 0); + + new (result.fEntries[newIndex++]) AliHLTDomainEntry(kTRUE, intersect); + } + } + } + } + + result.RemoveMarkedEntries(); + result.Optimise(); + return result; +} + + +void AliHLTTriggerDomain::MergeEntries( + const bool* removeThisEntry, Int_t entriesCount, + const bool* removeDomainEntry, Int_t startOfIntersects, + const AliHLTTriggerDomain& domain + ) +{ + // Merges the entries in this trigger domain with the ones in 'domain', while + // removing all entries that were marked for removal. + // See header file for more information. + + bool anythingRemoved = false; + + // Remember this method is used at the end of the calculation of the binary operators + // and that fEntries is expected to be partitioned into 3 regions. + // - 0..entriesCount-1 : contains the original (initial) entries of this trigger domain. + // - entriesCount..startOfIntersects-1 : is space reserved for the new entries + // from the given trigger domain 'domain' being processed. + // - startOfIntersects..fEntries.GetEntriesFast()-1 : contains all new domain entry + // intersection created and added to fEntries. + // + // First we need to remove all entries marked for removal from the original entries. + for (Int_t i = 0; i < entriesCount; i++) + { + if (removeThisEntry[i]) + { + fEntries.RemoveAt(i); + anythingRemoved = true; + } + } + + // Now we copy over all the new entries from 'domain' which were not marked for removal + // and indicate anythingRemoved = true since there will now be gaps in the clones array + // that need to be compressed away later. + for (Int_t i = 0; i < domain.fEntries.GetEntriesFast(); i++) + { + if (removeDomainEntry[i]) + { + anythingRemoved = true; + } + else + { + const AliHLTDomainEntry* newEntry = static_cast( domain.fEntries[i] ); + new (fEntries[entriesCount+i]) AliHLTDomainEntry(*newEntry); + } + } + + // Finally remove all new intersection entries that were marked for removal by + // the MarkForDeletionSubsetsOf method. + for (Int_t i = startOfIntersects; i < fEntries.GetEntriesFast(); i++) + { + const AliHLTDomainEntry* ientry = static_cast( fEntries[i] ); + if (ientry->TestBit(14)) + { + fEntries.RemoveAt(i); + anythingRemoved = true; + } + } + if (anythingRemoved) fEntries.Compress(); +} + + +void AliHLTTriggerDomain::MarkForDeletionSubsetsOf(const AliHLTDomainEntry& entry, Int_t min) +{ + // Marks for deletion all the entries in this trigger domain that are subsets + // of the given entry. + // See header file for more information. + + AliHLTDomainEntry intersect; + for (Int_t i = min; i < fEntries.GetEntriesFast(); i++) + { + AliHLTDomainEntry* ientry = static_cast( fEntries[i] ); + if (ientry->TestBit(14)) continue; + if (ientry->SubsetOf(entry)) + { + ientry->SetBit(14, true); + } + } +} + + +void AliHLTTriggerDomain::RemoveMarkedEntries() +{ + // Removes all entries in this trigger domain which were marked for removal.. + // See header file for more information. + + bool anythingRemoved = false; + for (Int_t i = 0; i < fEntries.GetEntriesFast(); i++) + { + const AliHLTDomainEntry* ientry = static_cast( fEntries[i] ); + if (ientry->TestBit(14)) + { + fEntries.RemoveAt(i); + anythingRemoved = true; + } + } + if (anythingRemoved) fEntries.Compress(); +} + + +void AliHLTTriggerDomain::Optimise() +{ + // Removes redundant trigger domain entries from the trigger domain. + // See header file for more information. + + AliHLTDomainEntry intersect; + + // Check that the first entry is not and exclusion which would be redundent. + if (fEntries.GetEntriesFast() == 0) return; + AliHLTDomainEntry* firstEntry = static_cast( fEntries[0] ); + if (firstEntry->Exclusive()) firstEntry->SetBit(14, true); + + for (Int_t i = 1; i < fEntries.GetEntriesFast(); i++) + { + AliHLTDomainEntry* ientry = static_cast( fEntries[i] ); + + // For the i'th entry in fEntries, compare it in reverse order with all other + // entries that are before it and look for redundant ones, i.e. that are subsets + // of the i'th entry. + for (Int_t j = i-1; j >= 0; j--) + { + AliHLTDomainEntry* jentry = static_cast( fEntries[j] ); + if (jentry->TestBit(14)) continue; + // Find entries that intersect + if (jentry->SubsetOf(*ientry)) + { + // jentry is a subset of ientry so it is redundant because for all values + // ientry will override jentry when calling IncludeInReadout. + jentry->SetBit(14, true); + } + else if (*ientry == *jentry) + { + // If intersecting entries have opposite exclude flags then search no further, + // we know that we will need this entry for correct behaviour of IncludeInReadout. + if (ientry->Inclusive() == jentry->Exclusive()) goto processNextEntry; + + if (ientry->SubsetOf(*jentry)) + { + ientry->SetBit(14, true); + goto processNextEntry; + } + } + } + + // If we got to this point then we hit the top of the trigger domain rules + // (pattern matching) list without hitting any and overlapping entries. + // So now we need to check if ientry is an exclusion. If it is, then it is + // redundant and we can mark it for removal. + if (ientry->Exclusive()) ientry->SetBit(14, true); + + processNextEntry: ; + } + + RemoveMarkedEntries(); +} + diff --git a/HLT/trigger/AliHLTTriggerDomain.h b/HLT/trigger/AliHLTTriggerDomain.h new file mode 100644 index 00000000000..34e7d3c7d3c --- /dev/null +++ b/HLT/trigger/AliHLTTriggerDomain.h @@ -0,0 +1,412 @@ +#ifndef ALIHLTTRIGGERDOMAIN_H +#define ALIHLTTRIGGERDOMAIN_H +/* This file is property of and copyright by the ALICE HLT Project * + * ALICE Experiment at CERN, All rights reserved. * + * See cxx source for full Copyright notice */ + +/// @file AliHLTDomainEntry.h +/// @author Artur Szostak +/// @date 19 Nov 2008 +/// @brief Declaration of the AliHLTTriggerDomain class used to store the set of data block types to readout. + +#include "TObject.h" +#include "TClonesArray.h" +#include "AliHLTDataTypes.h" + +class AliHLTDomainEntry; + +/** + * \class AliHLTTriggerDomain + * The trigger domain class is the set of HLT raw data block types that should + * be readout and sent to HLTOUT. + * It is implemented as a list of domain entries, where each domain entry is + * like a rule, or pattern to match against. When trying to decide if a given + * data block falls within the trigger domain, i.e. is part of the readout, the + * domain entries are applied one after the other from top to bottom. Two kinds + * of domain entries, inclusive and exclusive are possible, which indicate if a + * data block type or range, is part of the trigger domain or not. As we process + * the domain entries we update our decision of whether the data block is part + * of the trigger domain or not. If the domain entry is an inclusion then we update + * the decision to true, if it is an exclusion then we update the decision to false. + * The value of the result after applying the last domain entry then indicates + * if the data block is part of the trigger domain or not. + * In this way we can specify trigger domains as sets to arbitrary complexity + * and manipulate them as mathematical sets accordingly. + * + * The other feature of the AliHLTTriggerDomain class is that it overloads the + * following operators to provide set like behaviour: + * | this provides the set union operation (The + operator does the same). + * & this provides the set intersect operation. + * - this provides the set difference operation. + * ^ this provides an exclusive or (xor) operation. i.e. given two sets A and B + * the result C is given by: + * C = {x : x elf A and not x elf B, or x elf B and not x elf A} + * where 'elf' means "is an element of". + * ~ this returns the set complement. + * These operators then allow expressions to be formed from trigger domain objects + * which behave like sets. + */ +class AliHLTTriggerDomain : public TObject +{ + public: + + /** + * Default constructor. + */ + AliHLTTriggerDomain(); + + /** + * Copy constructor performs a deep copy. + * \param domain The domain entry to copy from. + */ + AliHLTTriggerDomain(const AliHLTTriggerDomain& domain); + + /** + * Default destructor. + */ + virtual ~AliHLTTriggerDomain(); + + /** + * Adds the given entry to this trigger domain as an inclusive entry. + * Existing entries are modified as required to optimise the trigger domain + * rule / pattern matching list. + * \param entry The domain entry object to add. + * \note The entry.Exclusive() flag is ignored and is treated as if it was kFALSE. + */ + void Add(const AliHLTDomainEntry& entry); + + /** + * Adds the given data type to the trigger domain such that all data blocks + * that match this type will form part of the trigger domain. + * \param datatype The data block type and origin to match. + */ + void Add(const AliHLTComponentDataType& datatype); + + /** + * Adds the given data type and origin to the trigger domain such that all data + * blocks that match will form part of this trigger domain. + * \param blocktype The data block type string of the data block that must match. + * The value of kAliHLTAnyDataTypeID can be used to specify the 'any' type + * wild card value. + * \param origin The origin of the data block, such as the detector name, that + * must match. The value of kAliHLTDataOriginAny can be used to specify the + * 'any' origin wild card value. + */ + void Add(const char* blocktype, const char* origin); + + /** + * Adds the given data type with particular specification bits to the trigger + * domain, such that all data blocks that match these will form part of this + * trigger domain. + * \param datatype The data block type and origin that must match. + * \param spec The specification bits that must match. + */ + void Add(const AliHLTComponentDataType& datatype, UInt_t spec); + + /** + * Adds the given data type, origin and specification bits of data blocks that + * should form part of this trigger domain. + * \param blocktype The data block type string of the data block that must match. + * The value of kAliHLTAnyDataTypeID can be used to specify the 'any' type + * wild card value. + * \param origin The origin of the data block, such as the detector name, that + * must match. The value of kAliHLTDataOriginAny can be used to specify the + * 'any' origin wild card value. + * \param spec The specification bits that must match. + */ + void Add(const char* blocktype, const char* origin, UInt_t spec); + + /** + * Removes or modifies all entries from the trigger domain, such that data blocks + * that match the given domain entry will not form part of this trigger domain. + * Existing entries are modified as required to optimise the trigger domain + * rule / pattern matching list. + * \param entry The domain entry object to indicating values that should be removed. + * \note The entry.Exclusive() flag is ignored and is treated as if it was kTRUE. + */ + void Remove(const AliHLTDomainEntry& entry); + + /** + * Removes the given data type from the trigger domain, such that all data blocks + * that match this type will not form part of the trigger domain. + * \param datatype The data block type and origin that must match the blocks not + * forming part of this trigger domain. + */ + void Remove(const AliHLTComponentDataType& datatype); + + /** + * Removes the given data type and origin from the trigger domain, such that all + * data blocks that match these will not form part of the trigger domain. + * \param blocktype The data block type string that must match the data blocks + * not forming part of this trigger domain. + * The value of kAliHLTAnyDataTypeID can be used to specify the 'any' type + * wild card value. + * \param origin The origin string, such as the detector name, that must match + * the data blocks not forming part of this trigger domain. + * The value of kAliHLTDataOriginAny can be used to specify the 'any' origin + * wild card value. + */ + void Remove(const char* blocktype, const char* origin); + + /** + * Removes the given data type with given specification bit from the trigger + * domain, such that all data blocks that match these will not form part of the + * trigger domain. + * \param datatype The data block type and origin that must match the blocks + * not forming part of this trigger domain. + * \param spec The specification bits that must match for the blocks that do + * not form part of this trigger domain. + */ + void Remove(const AliHLTComponentDataType& datatype, UInt_t spec); + + /** + * Removes the given data type, origin and specification from the trigger domain, + * such that all data blocks that match these will not form part of the trigger + * domain. + * \param blocktype The data block type string that must match the data blocks + * not forming part of this trigger domain. + * The value of kAliHLTAnyDataTypeID can be used to specify the 'any' type + * wild card value. + * \param origin The origin string, such as the detector name, that must match + * the data blocks not forming part of this trigger domain. + * The value of kAliHLTDataOriginAny can be used to specify the 'any' origin + * wild card value. + * \param spec The specification bits that must match for the blocks that do + * not form part of this trigger domain. + */ + void Remove(const char* blocktype, const char* origin, UInt_t spec); + + /** + * This checks to see if the given entry (or class of entries, if the entry uses + * wild card values) is part of the trigger domain. + * \param entry This is the entry to check for. + * \return true if data blocks that match the entry are part of this + * trigger domain and false otherwise. + * \note If the block contains the 'any' wild card values for the data type + * origin or specification, then the inclusive domains are treated + * optimistically and the exclusive domains pessimistically. This means that + * the wild card values are assumed to fall within the trigger domain for the + * optimistic case, but fall outside the domain for the pessimistic case. + */ + bool Contains(const AliHLTDomainEntry& entry) const; + + /** + * This checks to see if the given data block should be included in the HLT readout. + * \param block The data block descriptor to check. + * \return true if data block forms part of this trigger domain and should + * be part of the readout and false otherwise. + * \note If the block contains the 'any' wild card values for the data type + * or origin, then the inclusive domains are treated optimistically and the + * exclusive domains pessimistically. This means that the wild card values + * are assumed to fall within the trigger domain for the optimistic case, + * but fall outside the domain for the pessimistic case. + */ + bool IncludeInReadout(const AliHLTComponentBlockData* block) const; + + /** + * This checks to see if the given data block should not be included in the + * HLT readout. + * \param block The data block descriptor to check. + * \return true if data block does not form part of this trigger domain and + * false otherwise. + */ + bool ExcludeFromReadout(const AliHLTComponentBlockData* block) const + { + return ! IncludeInReadout(block); + } + + /** + * This method removes all entries in the trigger domain list, giving us and + * empty trigger domain set. + * \param option This is passed onto the internal fEntries TClonesArray. + * The method is inherited from TObject. + */ + virtual void Clear(Option_t* option = ""); + + /** + * Prints all the domain entries in this trigger domain in the order in which + * they are applied and if they are inclusive or exclusive. + * \param option This is not used by this method. + * The method is inherited from TObject. + */ + virtual void Print(Option_t* option = "") const; + + /** + * Assignment operator performs a deep copy. + * \param domain The domain entry to copy from. + * \return A reference to this object. + */ + AliHLTTriggerDomain& operator = (const AliHLTTriggerDomain& domain); + + /** + * This operator adds all domain entries in domain to this trigger domain + * in such a way, so as to effectively perform a set union. + * \param domain The domain object on the right hand side of the operator. + * \return A reference to this object. + */ + AliHLTTriggerDomain& operator |= (const AliHLTTriggerDomain& domain); + + /** + * This operator adds all domain entries in domain that do not exist in + * this trigger domain, but removes all entries that do exist, effectively + * performing an exclusive or (xor) operation. + * i.e. given two sets A and B the result C is given by: + * C = {x : x elf A and not x elf B, or x elf B and not x elf A} + * where 'elf' means "is an element of". + * \param domain The domain object on the right hand side of the operator. + * \return A reference to this object. + */ + AliHLTTriggerDomain& operator ^= (const AliHLTTriggerDomain& domain); + + /** + * This operator removes all domain entries from this trigger domain that do + * not also exist in domain, effectively performing a set intersect. + * \param domain The domain object on the right hand side of the operator. + * \return A reference to this object. + */ + AliHLTTriggerDomain& operator &= (const AliHLTTriggerDomain& domain) + { + return this->operator = (*this & domain); + } + + /** + * This operator performs the same operation as the '|=' operator. + * \param domain The domain object on the right hand side of the operator. + * \return A reference to this object. + */ + AliHLTTriggerDomain& operator += (const AliHLTTriggerDomain& domain) + { + return operator |= (domain); + } + + /** + * This operator removes all domain entries from this trigger domain that exisit + * in domain, effectively implementing a set difference. + * \param domain The domain object on the right hand side of the operator. + * \return A reference to this object. + */ + AliHLTTriggerDomain& operator -= (const AliHLTTriggerDomain& domain); + + /** + * This operator returns the set complement of the trigger domain. + * \return The complement of this trigger domain, such that any data block that + * returns true for AliHLTTriggerDomain::IncludeInReadout() for this trigger + * domain, will return false for the same method call in the returned object. + */ + AliHLTTriggerDomain operator ~ () const; + + /** + * This operator performs a set union between this trigger domain and domain. + * \param domain The domain object on the right hand side of the operator. + * \return a trigger domain object R, such that for each data block D, we will have + * R.IncludeInReadout(D) == this->IncludeInReadout(D) or domain.IncludeInReadout(D) + */ + AliHLTTriggerDomain operator | (const AliHLTTriggerDomain& domain) const; + + /** + * This operator performs an exclusive or (xor) like operation between this trigger + * domain and domain. + * \param domain The domain object on the right hand side of the operator. + * \return a trigger domain object R, such that for each data block D, we will have + * R.IncludeInReadout(D) == this->IncludeInReadout(D) xor domain.IncludeInReadout(D) + */ + AliHLTTriggerDomain operator ^ (const AliHLTTriggerDomain& domain) const + { + AliHLTTriggerDomain result = *this; + return result.operator ^= (domain); + } + + /** + * This operator performs a set intersect operation between this trigger domain + * and domain. + * \param domain The domain object on the right hand side of the operator. + * \return a trigger domain object R, such that for each data block D, we will have + * R.IncludeInReadout(D) == this->IncludeInReadout(D) and domain.IncludeInReadout(D) + */ + AliHLTTriggerDomain operator & (const AliHLTTriggerDomain& domain) const; + + /** + * This operator performs the same operation as the '|' operator. + * \param domain The domain object on the right hand side of the operator. + * \return a trigger domain object R, such that for each data block D, we will have + * R.IncludeInReadout(D) == this->IncludeInReadout(D) or domain.IncludeInReadout(D) + */ + AliHLTTriggerDomain operator + (const AliHLTTriggerDomain& domain) const + { + AliHLTTriggerDomain result = *this; + return result.operator += (domain); + } + + /** + * This operator implements the set difference between this trigger domain and + * domain. + * \param domain The domain object on the right hand side of the operator. + * \return a trigger domain object R, such that for each data block D, we will have + * R.IncludeInReadout(D) == this->IncludeInReadout(D) and not domain.IncludeInReadout(D) + */ + AliHLTTriggerDomain operator - (const AliHLTTriggerDomain& domain) const + { + AliHLTTriggerDomain result = *this; + return result.operator -= (domain); + } + + private: + + /** + * This method merges the domain entries from domain by copying them into + * fEntries, but only the ones not marked for removal in removeDomainEntry. + * Any entries that were marked for removal in fEntries are also removed. + * \param removeThisEntry Flags which indicate if the corresponding fEntries[i] + * should be removed. + * \param entriesCount The number of entries in removeThisEntry. + * \param removeDomainEntry Flags which indicate if the corresponding domain.fEntries[i] + * was marked for removal or not. If marked for removal then it will not be copied + * into this trigger domain. The size of the array is given by domain.GetEntriesFast(). + * \param startOfIntersects This is the start location of the new intersection domain + * entries that were added to fEntries. i.e. fEntries[startOfIntersects] is the + * first new intersect entry. + */ + void MergeEntries( + const bool* removeThisEntry, Int_t entriesCount, + const bool* removeDomainEntry, Int_t startOfIntersects, + const AliHLTTriggerDomain& domain + ); + + /** + * Goes throught the list of domain entries in fEntries from the first entry + * indicated by 'min' to the end of the list and marks for deletion all entries + * in fEntries that are subsets of 'entry'. + * The entries are marked by setting the 14'th bit in fBits with a call to + * AliHLTDomainEntry::SetBit(14, true). + * \param entry The entry that should be the super set of the entries we mark + * for removal. + * \param min This is the first entry we consider, all the way up to + * fEntries.GetEntriesFast() - 1. + */ + void MarkForDeletionSubsetsOf(const AliHLTDomainEntry& entry, Int_t min); + + /** + * Removes all entries in this trigger domain which were marked for removal. + * These are all domain entries that have the 14'th bit set in their fBits field + * with a call to AliHLTDomainEntry::SetBit(14, true). + */ + void RemoveMarkedEntries(); + + /** + * Removes any redundant trigger domain entries from the fEntries list. + * Entries that are subsets of each other are removed. Also exclusive entries + * that are not subsets of any inclusive entry are also removed, because we + * implicitly assume a data block does not form part of the trigger domain, + * unless explicitly included with an inclusive domain entry. So these kinds + * of entries are redundant. + */ + void Optimise(); + + TClonesArray fEntries; /// The list of domain entries used to decide if a data block forms part of trigger domain set. + + ClassDef(AliHLTTriggerDomain, 1) // This is a list of internal HLT data block types which should be forwarded for readout. + +}; + +#endif // ALIHLTTRIGGERDOMAIN_H + -- 2.43.0