Adding trigger counting component.
authoraszostak <aszostak@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 12 Nov 2010 01:02:55 +0000 (01:02 +0000)
committeraszostak <aszostak@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 12 Nov 2010 01:02:55 +0000 (01:02 +0000)
HLT/BASE/AliHLTDataTypes.cxx
HLT/BASE/AliHLTDataTypes.h
HLT/libAliHLTTrigger.pkg
HLT/trigger/AliHLTTriggerAgent.cxx
HLT/trigger/AliHLTTriggerCounterComponent.cxx [new file with mode: 0644]
HLT/trigger/AliHLTTriggerCounterComponent.h [new file with mode: 0644]
HLT/trigger/AliHLTTriggerLinkDef.h
HLT/trigger/test/InitialCounterConfig.C [new file with mode: 0644]
HLT/trigger/test/Makefile.am
HLT/trigger/test/testTriggerCounterComponent.C [new file with mode: 0644]

index 3127aba..44e159d 100644 (file)
@@ -190,10 +190,6 @@ const AliHLTComponentDataType kAliHLTDataTypeHistogram = AliHLTComponentDataType
 const char kAliHLTTNtupleDataTypeIDstring[8] = kAliHLTTNtupleDataTypeID;
 const AliHLTComponentDataType kAliHLTDataTypeTNtuple = AliHLTComponentDataTypeInitializer(kAliHLTTNtupleDataTypeIDstring, kAliHLTDataOriginAny);
 
-/** AliHLTTriggerCounters object */
-const char kAliHLTTriggerCountersDataTypeIDstring[8] = kAliHLTTriggerCountersDataTypeID;
-const AliHLTComponentDataType kAliHLTDataTypeTriggerCounters = AliHLTComponentDataTypeInitializer(kAliHLTTriggerCountersDataTypeIDstring, kAliHLTDataOriginHLT);
-
 /** Array of HLT Tracks (AliHLTTracksData) */
 const char kAliHLTTrackDataTypeIDstring[8] = kAliHLTTrackDataTypeID;
 const AliHLTComponentDataType kAliHLTDataTypeTrack = AliHLTComponentDataTypeInitializer(kAliHLTTrackDataTypeIDstring, kAliHLTDataOriginAny);
@@ -222,6 +218,14 @@ const AliHLTComponentDataType kAliHLTDataTypedEdx = AliHLTComponentDataTypeIniti
 /** Container of dNdPt */
 const AliHLTComponentDataType kAliHLTDataTypedNdPt = AliHLTComponentDataTypeInitializer( "DNDPT   ", kAliHLTDataOriginAny );
 
+/** Input trigger counters */
+const char kAliHLTInputTriggerCountersDataTypeIDstring[8] = kAliHLTInputTriggerCountersDataTypeID;
+const AliHLTComponentDataType kAliHLTDataTypeInputTriggerCounters = AliHLTComponentDataTypeInitializer(kAliHLTInputTriggerCountersDataTypeIDstring, kAliHLTDataOriginHLT);
+
+/** Input trigger counters */
+const char kAliHLTOutputTriggerCountersDataTypeIDstring[8] = kAliHLTOutputTriggerCountersDataTypeID;
+const AliHLTComponentDataType kAliHLTDataTypeOutputTriggerCounters = AliHLTComponentDataTypeInitializer(kAliHLTOutputTriggerCountersDataTypeIDstring, kAliHLTDataOriginHLT);
+
 //////////////////////////////////////////////////////////////////////////
 //
 // Data origin variables, to be used with the operator|
index 6978ad2..18688a4 100644 (file)
@@ -66,8 +66,9 @@
  *           Adding data block type for ESD content
  *           Adding data block type for forwarded component table blocks
  *           Adding new event type for software triggers.
+ *  15       Modifying data block types for trigger counter blocks.
  */
-#define ALIHLT_DATA_TYPES_VERSION 14
+#define ALIHLT_DATA_TYPES_VERSION 15
 
 //////////////////////////////////////////////////////////////////////////
 //
@@ -492,12 +493,6 @@ const int kAliHLTComponentDataTypefIDsize=8;
  */
 #define kAliHLTTNtupleDataTypeID              {'R','O','O','T','T','U','P','L'}
 
-/** HLT trigger counters.
- * - For the AliHLTTriggerCounters object. Normally with HLT as origin.
- * @ingroup alihlt_component_datatypes
- */
-# define kAliHLTTriggerCountersDataTypeID       {'T','R','G','C','O','U','N','T'}
-
 /** HLT Track
  * - Struct for Tracks based on AliExternalTrackParam
  * - varying origin
@@ -535,6 +530,16 @@ const int kAliHLTComponentDataTypefIDsize=8;
  */
 # define kAliHLTdNdPtDataTypeID {'D','N','D','P','T',' ',' ',' '}
 
+/** Global input trigger counters data block type.
+ * @ingroup alihlt_component_datatypes
+ */
+# define kAliHLTInputTriggerCountersDataTypeID      {'I','N','T','R','G','C','N','T'}
+
+/** Global output trigger counters data block type.
+ * @ingroup alihlt_component_datatypes
+ */
+# define kAliHLTOutputTriggerCountersDataTypeID     {'O','T','T','R','G','C','N','T'}
+
 using namespace std;
 
 extern "C" {
@@ -1166,10 +1171,17 @@ extern "C" {
    */                                                                  
   extern const AliHLTComponentDataType kAliHLTDataTypeTNtuple;           // {ROOTTUPL,"***"}
 
-  /** AliHLTTriggerCounters object for HLT global trigger counters.
+  /** Global input trigger counters.
+   * - origin : kAliHLTDataOriginOut ( HLT )
    * @ingroup alihlt_component_datatypes
-   */                                                                  
-  extern const AliHLTComponentDataType kAliHLTDataTypeTriggerCounters;           // {TRGCOUNT,"HLT "}
+   */
+  extern const AliHLTComponentDataType kAliHLTDataTypeInputTriggerCounters;     // {INTRGCNT:HLT }
+
+  /** Global output trigger counters.
+   * - origin : kAliHLTDataOriginOut ( HLT )
+   * @ingroup alihlt_component_datatypes
+   */
+  extern const AliHLTComponentDataType kAliHLTDataTypeOutputTriggerCounters;     // {OTTRGCNT:HLT }
 
   /** General track array for the barrel tracks based on AliExternalTrackParam
    * Data format defined by AliHLTTracksData
index 161d92c..993a8d7 100644 (file)
@@ -37,6 +37,7 @@ CLASS_HDRS:= \
                AliHLTMuonSpectroScalars.h                  \
                AliHLTMuonSpectroTriggerComponent.h         \
                AliHLTUpcTriggerComponent.h                 \
+               AliHLTTriggerCounterComponent.h             \
                AliHLTTriggerCounters.h
 
 # library sources
index afd3d05..920e0df 100644 (file)
@@ -50,6 +50,7 @@
 #include "AliHLTTriggerGammaConversion.h"
 #include "AliHLTMuonSpectroTriggerComponent.h"
 #include "AliHLTUpcTriggerComponent.h"
+#include "AliHLTTriggerCounterComponent.h"
 
 
 /** global instance for agent registration */
@@ -91,6 +92,7 @@ int AliHLTTriggerAgent::RegisterComponents(AliHLTComponentHandler* pHandler) con
   pHandler->AddComponent(new AliHLTTriggerGammaConversion);
   pHandler->AddComponent(new AliHLTMuonSpectroTriggerComponent);
   pHandler->AddComponent(new AliHLTUpcTriggerComponent);
+  pHandler->AddComponent(new AliHLTTriggerCounterComponent);
   return 0;
 }
 
diff --git a/HLT/trigger/AliHLTTriggerCounterComponent.cxx b/HLT/trigger/AliHLTTriggerCounterComponent.cxx
new file mode 100644 (file)
index 0000000..8d26fbb
--- /dev/null
@@ -0,0 +1,474 @@
+// $Id: AliHLTTriggerCounterComponent.cxx 43071 2010-08-25 08:41:44Z richterm $
+/**************************************************************************
+ * This file is property of and copyright by the ALICE HLT Project        *
+ * ALICE Experiment at CERN, All rights reserved.                         *
+ *                                                                        *
+ * Primary Authors: Artur Szostak <artursz@iafrica.com>                   *
+ *                  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   AliHLTTriggerCounterComponent.cxx
+/// @author Artur Szostak <artursz@iafrica.com>
+/// @date   3 Nov 2010
+/// @brief  Implementation of the AliHLTTriggerCounterComponent class.
+///
+/// The AliHLTTriggerCounterComponent is used to count HLT input and output
+/// triggers based on the global trigger decisions coming from the global HLT
+/// trigger component.
+
+#include "AliHLTTriggerCounterComponent.h"
+#include "AliHLTTriggerDecision.h"
+#include "AliHLTGlobalTriggerDecision.h"
+#include "AliHLTTriggerCounters.h"
+#include "AliHLTCTPData.h"
+#include "AliCDBManager.h"
+#include "AliCDBStorage.h"
+#include "AliCDBEntry.h"
+#include "TObjString.h"
+#include "TROOT.h"
+#include <cstring>
+#include <cassert>
+
+ClassImp(AliHLTTriggerCounterComponent)
+
+const char* AliHLTTriggerCounterComponent::fgkConfigCDBPath = "HLT/ConfigHLT/HLTTriggerCounter";
+TMap AliHLTTriggerCounterComponent::fgInitialCounterConfig(TCollection::kInitHashTableCapacity, 2);
+
+
+AliHLTTriggerCounterComponent::AliHLTTriggerCounterComponent() :
+       AliHLTProcessor(),
+       fOutputMultiplier(0),
+       fInputCounters(),
+       fOutputCounters(),
+       fInputTimes(TCollection::kInitHashTableCapacity, 2),
+       fOutputTimes(TCollection::kInitHashTableCapacity, 2),
+       fLastPublishTime(-1),
+       fPublishPeriod(-1)
+{
+       // Default constructor.
+       
+       fInputTimes.SetOwner(kTRUE);
+       fOutputTimes.SetOwner(kTRUE);
+}
+
+
+AliHLTTriggerCounterComponent::~AliHLTTriggerCounterComponent()
+{
+       // Default destructor.
+       
+}
+
+
+const char* AliHLTTriggerCounterComponent::GetComponentID()
+{
+       // Returns the component ID.
+       return "HLTTriggerCounter";
+}
+
+
+void AliHLTTriggerCounterComponent::GetInputDataTypes(AliHLTComponentDataTypeList& list)
+{
+       // Returns the list of input data types that are handled.
+       list.push_back(kAliHLTDataTypeGlobalTrigger);
+       list.push_back(kAliHLTDataTypeTriggerDecision);
+}
+
+
+AliHLTComponentDataType AliHLTTriggerCounterComponent::GetOutputDataType()
+{
+       // Returns kAliHLTMultipleDataType.
+       return kAliHLTMultipleDataType;
+}
+
+
+int AliHLTTriggerCounterComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& list)
+{
+       // Returns the list of output data block types generated.
+       list.push_back(kAliHLTDataTypeInputTriggerCounters);
+       list.push_back(kAliHLTDataTypeOutputTriggerCounters);
+       return int(list.size());
+}
+
+
+void AliHLTTriggerCounterComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier)
+{
+       // Returns the buffer size requirements.
+       constBase = 1024*16;
+       inputMultiplier = fOutputMultiplier;
+}
+
+
+AliHLTComponent* AliHLTTriggerCounterComponent::Spawn()
+{
+       // Creates a new instance of the component.
+       return new AliHLTTriggerCounterComponent;
+}
+
+
+Int_t AliHLTTriggerCounterComponent::DoInit(int argc, const char** argv)
+{
+       // Initialises the data checker component from the command line.
+       
+       HLTInfo("Starting HLT trigger counter component.");
+       
+       const char* configFileName = NULL;
+       fInputCounters.Clear();
+       fOutputCounters.Clear();
+       fInputTimes.Clear();
+       fOutputTimes.Clear();
+       fLastPublishTime = -1;
+       fPublishPeriod = -1;
+       bool loadCDBObject = true;
+       
+       for (int i = 0; i < argc; ++i)
+       {
+               if (strcmp(argv[i], "-config") == 0)
+               {
+                       if (configFileName != NULL)
+                       {
+                               HLTWarning("The configuration macro was already specified."
+                                       " Will replace previous value given by -config."
+                               );
+                       }
+                       if (argc <= i+1)
+                       {
+                               HLTError("The configuration macro filename was not specified." );
+                               return -EINVAL;
+                       }
+                       configFileName = argv[i+1];
+                       i++;
+                       continue;
+               }
+               
+               if (strcmp(argv[i], "-publishperiod") == 0)
+               {
+                       if (fPublishPeriod != -1)
+                       {
+                               HLTWarning("The publish period was already specified."
+                                       " Will replace previous value given by -publishperiod."
+                               );
+                       }
+                       if (argc <= i+1)
+                       {
+                               HLTError("Publish period value was not specified for -publishperiod.");
+                               return -EINVAL;
+                       }
+                       char* err = NULL;
+                       errno = 0;
+                       double tmpnum = strtod(argv[i+1], &err);
+                       if (err == NULL or *err != '\0')
+                       {
+                               HLTError("Cannot convert '%s' to a floating point value.", argv[i+1]);
+                               return false;
+                       }
+                       if (errno == ERANGE)
+                       {
+                               HLTError("The specified value '%s' is out of range.", argv[i+1]);
+                               return false;
+                       }
+                       fPublishPeriod = (tmpnum < 0 ? -1 : tmpnum);
+                       i++;
+                       continue;
+               }
+               
+               if (strcmp(argv[i], "-skipcdb") == 0)
+               {
+                       loadCDBObject = false;
+                       continue;
+               }
+               
+               HLTError("Unknown option '%s'.", argv[i]);
+               return -EINVAL;
+       } // for loop
+       
+       if (configFileName != NULL)
+       {
+               int result = LoadConfigFromFile(configFileName);
+               if (result != 0) return result;
+       }
+       else if (loadCDBObject)
+       {
+               int result = LoadConfigFromCDB(fgkConfigCDBPath);
+               if (result != 0) return result;
+       }
+       
+       return 0;
+}
+
+
+Int_t AliHLTTriggerCounterComponent::DoDeinit()
+{
+       // Cleans up the component.
+       
+       HLTInfo("Stopping HLT trigger counter component.");
+       fInputCounters.Clear();
+       fOutputCounters.Clear();
+       fInputTimes.Clear();
+       fOutputTimes.Clear();
+       return 0;
+}
+
+
+int AliHLTTriggerCounterComponent::DoEvent(const AliHLTComponentEventData& /*evtData*/, AliHLTComponentTriggerData& /*trigData*/)
+{
+       // Finds the global trigger objects and adds the triggers to the counters.
+       
+       fInputCounters.UpdateTimeStamp();
+       fOutputCounters.UpdateTimeStamp();
+       Double_t inputTime = fInputCounters.TimeStamp().AsDouble();
+       Double_t outputTime = fOutputCounters.TimeStamp().AsDouble();
+       
+       const TObject* obj = GetFirstInputObject(kAliHLTDataTypeGlobalTrigger, "AliHLTGlobalTriggerDecision");
+       while (obj != NULL)
+       {
+               const AliHLTGlobalTriggerDecision* decision = dynamic_cast<const AliHLTGlobalTriggerDecision*>(obj);
+               if (decision != NULL)
+               {
+                       HLTDebug("Received trigger decision object of type AliHLTGlobalTriggerDecision.");
+                       // Tokenise the global trigger description string which contains a
+                       // list of the triggers that were fired and increment the corresponding
+                       // counters.
+                       TString names = decision->Description();
+                       Ssiz_t from = 0;
+                       TString token;
+                       while (names.Tokenize(token, from, ","))
+                       {
+                               TObject* cntobj = fOutputCounters.FindObject(token.Data());
+                               if (cntobj != NULL)
+                               {
+                                       AliHLTTriggerCounters::AliCounter* counter = static_cast<AliHLTTriggerCounters::AliCounter*>(cntobj);
+                                       counter->Increment();
+                                       UpdateCounterRate(
+                                                       counter,
+                                                       static_cast<AliRingBuffer*>( fOutputTimes.FindObject(token.Data()) ),
+                                                       outputTime
+                                               );
+                               }
+                               else
+                               {
+                                       fOutputCounters.Add(token.Data(), "New trigger output counter found during the run.", 1, 1);
+                                       fOutputTimes.Add(new AliRingBuffer(token.Data(), outputTime));
+                               }
+                       }
+                       
+                       // Now add the CTP triggers.
+                       const AliHLTCTPData* ctp = dynamic_cast<const AliHLTCTPData*>( decision->InputObjects().FindObject("AliHLTCTPData") );
+                       if (ctp != NULL)
+                       {
+                               const TArrayL64& counters = ctp->Counters();
+                               for (Int_t i = 0; i < counters.GetSize(); ++i)
+                               {
+                                       const char* ctpName = ctp->Name(i);
+                                       // Check if CTP counter is initialised and skip if not.
+                                       if (strcmp(ctpName, "AliHLTReadoutList") == 0 and counters[i] == 0) continue;
+                                       TObject* cntobj = fInputCounters.FindObject(ctpName);
+                                       if (cntobj != NULL)
+                                       {
+                                               AliHLTTriggerCounters::AliCounter* counter = static_cast<AliHLTTriggerCounters::AliCounter*>(cntobj);
+                                               counter->Counter(counters[i]);
+                                               UpdateCounterRate(
+                                                               counter,
+                                                               static_cast<AliRingBuffer*>( fInputTimes.FindObject(ctpName) ),
+                                                               inputTime
+                                                       );
+                                       }
+                                       else
+                                       {
+                                               fInputCounters.Add(
+                                                               ctpName,
+                                                               "New CTP trigger input counter found during the run.",
+                                                               Double_t(counters[i]),
+                                                               counters[i]
+                                                       );
+                                               fInputTimes.Add(new AliRingBuffer(ctpName, inputTime));
+                                       }
+                               }
+                       }
+                       
+                       // Add the list of input triggers.
+                       for (Int_t i = 0; i < decision->NumberOfTriggerInputs(); ++i)
+                       {
+                               const AliHLTTriggerDecision* input = decision->TriggerInput(i);
+                               if (input == NULL or not input->Result()) continue;
+                               TObject* cntobj = fInputCounters.FindObject(input->Name());
+                               if (cntobj != NULL)
+                               {
+                                       AliHLTTriggerCounters::AliCounter* counter = static_cast<AliHLTTriggerCounters::AliCounter*>(cntobj);
+                                       counter->Increment();
+                                       counter->SetBit(BIT(14), true);  // mark counter as updated
+                                       UpdateCounterRate(
+                                                       counter,
+                                                       static_cast<AliRingBuffer*>( fInputTimes.FindObject(input->Name()) ),
+                                                       inputTime
+                                               );
+                               }
+                               else
+                               {
+                                       fInputCounters.Add(input->Name(), "New trigger input counter found during the run.", 1, 1);
+                                       fInputCounters.GetCounterN(fInputCounters.NumberOfCounters()-1).SetBit(BIT(14), true); // mark counter as updated
+                                       fInputTimes.Add(new AliRingBuffer(input->Name(), inputTime));
+                               }
+                       }
+               }
+               obj = GetNextInputObject();
+       }
+       
+       // Look for the individual trigger decision blocks to add if they are available.
+       obj = GetFirstInputObject(kAliHLTDataTypeTriggerDecision, "AliHLTTriggerDecision");
+       while (obj != NULL)
+       {
+               const AliHLTTriggerDecision* decision = dynamic_cast<const AliHLTTriggerDecision*>(obj);
+               if (decision != NULL and decision->Result())
+               {
+                       HLTDebug("Received trigger decision object of type AliHLTTriggerDecision.");
+                       TObject* cntobj = fInputCounters.FindObject(decision->Name());
+                       if (cntobj != NULL)
+                       {
+                               AliHLTTriggerCounters::AliCounter* counter = static_cast<AliHLTTriggerCounters::AliCounter*>(cntobj);
+                               if (not counter->TestBit(BIT(14)))  // Only update if marked as not updated.
+                               {
+                                       counter->Increment();
+                                       UpdateCounterRate(
+                                                       counter,
+                                                       static_cast<AliRingBuffer*>( fInputTimes.FindObject(decision->Name()) ),
+                                                       inputTime
+                                               );
+                               }
+                       }
+                       else
+                       {
+                               fInputCounters.Add(decision->Name(), "New trigger input counter found during the run.", 1, 1);
+                               fInputTimes.Add(new AliRingBuffer(decision->Name(), inputTime));
+                       }
+               }
+               obj = GetNextInputObject();
+       }
+       // Reset bit 14 which is used temporarily to mark updated counters.
+       for (UInt_t i = 0; i < fInputCounters.NumberOfCounters(); ++i)
+       {
+               fInputCounters.GetCounterN(i).SetBit(BIT(14), false);
+       }
+       
+       Double_t now = TTimeStamp();
+       if (fLastPublishTime == -1) fLastPublishTime = now;
+       if (now - fLastPublishTime > fPublishPeriod)
+       {
+               fLastPublishTime = now;
+               bool inputCountersNotPushed = PushBack(&fInputCounters, kAliHLTDataTypeInputTriggerCounters) != 0;
+               bool outputCountersNotPushed = PushBack(&fOutputCounters, kAliHLTDataTypeOutputTriggerCounters) != 0;
+               if (inputCountersNotPushed or outputCountersNotPushed)
+               {
+                       fOutputMultiplier = (fOutputMultiplier == 0 ? 1 : fOutputMultiplier*2);
+                       return -ENOSPC;
+               }
+       }
+       return 0;
+}
+
+
+void AliHLTTriggerCounterComponent::UpdateCounterRate(
+               AliHLTTriggerCounters::AliCounter* counter, AliRingBuffer* timeBuf, Double_t newTime
+       )
+{
+       // Updates the counter's rate value.
+       
+       assert(timeBuf != NULL);
+       Double_t dt = newTime - timeBuf->OldestTime();
+       Double_t rate = (dt != 0 ? (counter->Counter() - timeBuf->OldestCounter()) / dt : 0.);
+       counter->Rate(rate);
+       timeBuf->Increment(counter->Counter(), newTime);
+}
+
+
+int AliHLTTriggerCounterComponent::LoadConfigFromCDB(const char* cdbPath)
+{
+       // Loads the initial configuration of counters from the given CDB path.
+       
+       HLTDebug("Trying to load trigger menu from '%s'.", cdbPath);
+       
+       if (AliCDBManager::Instance() == NULL)
+       {
+               HLTError("CDB manager object not found.");
+               return -EIO;
+       }
+       AliCDBStorage* store = AliCDBManager::Instance()->GetDefaultStorage();
+       if (store == NULL)
+       {
+               HLTError("Could not get the the default storage for the CDB.");
+               return -EIO;
+       }
+       Int_t version = store->GetLatestVersion(cdbPath, GetRunNo());
+       if (version < 0)
+       {
+               HLTError("Could not find an entry in the CDB for \"%s\".", cdbPath);
+               return -EIO;
+       }
+       Int_t subVersion = store->GetLatestSubVersion(cdbPath, GetRunNo(), version);
+       AliCDBEntry* entry = AliCDBManager::Instance()->Get(cdbPath, GetRunNo(), version, subVersion);
+       if (entry == NULL)
+       {
+               HLTError("Could not get the CDB entry for \"%s\".", cdbPath);
+               return -EIO;
+       }
+       TObject* obj = entry->GetObject();
+       if (obj == NULL)
+       {
+               HLTError("Configuration object for \"%s\" is missing.", cdbPath);
+               return -ENOENT;
+       }
+       if (obj->IsA() != TMap::Class())
+       {
+               HLTError("Wrong type for configuration object in \"%s\". Found a %s but we expect a TMap.",
+                       cdbPath, obj->ClassName()
+               );
+               return -EPROTO;
+       }
+       TMap* counters = static_cast<TMap*>(obj);
+       SetInitialCounters(counters);
+       return 0;
+}
+
+
+int AliHLTTriggerCounterComponent::LoadConfigFromFile(const char* configFile)
+{
+       // Loads the initial configuration of counters from the given configuration file.
+       
+       TString cmd = ".x ";
+       cmd += configFile;
+       gROOT->ProcessLine(cmd);
+       SetInitialCounters(&fgInitialCounterConfig);
+       return 0;
+}
+
+
+void AliHLTTriggerCounterComponent::SetInitialCounters(const TMap* counters)
+{
+       // Sets the initial counter values from TMap objects containing name description pairs.
+       
+       Double_t now = TTimeStamp();
+       TMapIter next(counters);
+       TObject* key = NULL;
+       while ((key = next()) != NULL)
+       {
+               TObject* value = counters->GetValue(key);
+               if (value == NULL) continue;
+               if (key->TestBit(BIT(14)))
+               {
+                       fOutputCounters.Add(key->GetName(), value->GetName());
+                       fOutputTimes.Add(new AliRingBuffer(key->GetName(), now));
+               }
+               else
+               {
+                       fInputCounters.Add(key->GetName(), value->GetName());
+                       fInputTimes.Add(new AliRingBuffer(key->GetName(), now));
+               }
+       }
+}
diff --git a/HLT/trigger/AliHLTTriggerCounterComponent.h b/HLT/trigger/AliHLTTriggerCounterComponent.h
new file mode 100644 (file)
index 0000000..8b40564
--- /dev/null
@@ -0,0 +1,200 @@
+//-*- Mode: C++ -*-
+// $Id: $
+#ifndef ALIHLTTRIGGERCOUNTERCOMPONENT_H
+#define ALIHLTTRIGGERCOUNTERCOMPONENT_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   AliHLTTriggerCounterComponent.h
+/// \author Artur Szostak <artursz@iafrica.com>
+/// \date   3 Nov 2010
+/// \brief  Declaration of the AliHLTTriggerCounterComponent component class.
+
+#include "AliHLTProcessor.h"
+#include "AliHLTTriggerCounters.h"
+#include "THashTable.h"
+#include "TTimeStamp.h"
+#include "TMap.h"
+
+/**
+ * \class AliHLTTriggerCounterComponent
+ * This component is used to calculate online the trigger counters and rates for
+ * output HLT and input CTP / HLT triggers. The component should be connected to
+ * all the global trigger component instances in the chain and there should be
+ * only one instance of AliHLTTriggerCounterComponent in the chain. If more instances
+ * of AliHLTTriggerCounterComponent exist in the chain then the statistics will not
+ * be calculated correctly.
+ *
+ * <h2>General properties:</h2>
+ *
+ * Component ID: \b HLTTriggerCounter <br>
+ * Library: \b libAliHLTTrigger.so   <br>
+ * Input Data Types:  kAliHLTDataTypeGlobalTrigger | kAliHLTDataTypeTriggerDecision <br>
+ * Output Data Types: kAliHLTDataTypeInputTriggerCounters | kAliHLTDataTypeOutputTriggerCounters <br>
+ *
+ * <h2>Mandatory arguments:</h2>
+ * None.
+ *
+ * <h2>Optional arguments:</h2>
+ * \li -config <i>filename</i> <br>
+ *      Indicates the configuration macro file to use for the initial trigger counter lists.
+ * \li -publishperiod <i>period</i> <br>
+ *      Sets the period between publishing of the trigger counters in seconds.
+ *      The default is to publish for every event.
+ * \li -skipcdb  <br>
+ *      If specified then the initial counter configuration is not loaded from the CDB.
+ *
+ * <h2>Configuration:</h2>
+ * Can only be configured with the command line arguments.
+ *
+ * <h2>Default CDB entries:</h2>
+ * HLT/ConfigHLT/HLTTriggerCounter - Contains the initial counter configuration.
+ *
+ * <h2>Performance:</h2>
+ * Can run over 2kHz in HLT online system.
+ *
+ * <h2>Memory consumption:</h2>
+ * Negligible.
+ *
+ * <h2>Output size:</h2>
+ * Same order of magnitude as the input data size.
+ *
+ * \ingroup alihlt_tpc_components
+ */
+class AliHLTTriggerCounterComponent : public AliHLTProcessor
+{
+public:
+       
+       AliHLTTriggerCounterComponent();
+       virtual ~AliHLTTriggerCounterComponent();
+       
+       // Methods inherited from AliHLTComponent:
+       virtual const char* GetComponentID();
+       virtual void GetInputDataTypes(AliHLTComponentDataTypeList& list);
+       virtual AliHLTComponentDataType GetOutputDataType();
+       virtual int GetOutputDataTypes(AliHLTComponentDataTypeList& list);
+       virtual void GetOutputDataSize(unsigned long& constBase, double& inputMultiplier);
+       virtual AliHLTComponent* Spawn();
+       virtual Int_t DoInit(int argc, const char** argv);
+       virtual Int_t DoDeinit();
+       
+       /**
+        * Returns a reference to the initial counter configuration to use.
+        * This should be used in the configuration file passed to the component with
+        * the -config option to setup the initial counter configuration. The following
+        * is an example of such a config file.
+        * \code
+        *   void SetupConfig() {
+        *     TMap& counters = AliHLTTriggerCounterComponent::InitialCounterConfig();
+        *     counters.Add(new TObjString("TRIGGER-A"), new TObjString("Some input trigger"));
+        *     TObjString* outname = new TObjString("TRIGGER-B");
+        *     outname->SetBit(1<<14);
+        *     counters.Add(outname, new TObjString("Some output trigger"));
+        *   }
+        * \endcode
+        */
+       static TMap& InitialCounterConfig()
+       {
+               fgInitialCounterConfig.SetOwner(kTRUE); // Make sure its the owner of all objects.
+               return fgInitialCounterConfig;
+       }
+       
+protected:
+       
+       // Method inherited from AliHLTProcessor:
+       virtual int DoEvent(const AliHLTComponentEventData& evtData, AliHLTComponentTriggerData& trigData);
+       using AliHLTProcessor::DoEvent;
+       
+private:
+       
+       /// Implements a ring buffer for old counter and time stamp values.
+       class AliRingBuffer : public TObject
+       {
+       public:
+               enum 
+               {
+                       /// The maximum number of time stamp entries held in the ring buffers for rate calculations.
+                       /// The uncertainty in the rate should be ~ rate/sqrt(kTimeStampEntries)
+                       kTimeStampEntries = 100
+               };
+               
+               /// Constructor initialises the buffer
+               AliRingBuffer(const char* counterName, Double_t startTime) : TObject(), fCounterName(counterName), fPos(0)
+               {
+                       for (size_t i = 0; i < kTimeStampEntries; ++i) {
+                               fCounterBuffer[i] = 0; fTimeBuffer[i] = startTime;
+                       }
+               }
+               
+               /// Inherited form TObject. Returns the counter name this buffer is associated to.
+               virtual const char* GetName() const { return fCounterName.Data(); }
+               
+               /// Inherited from TObject. Returns a hash value calculated from the counter name.
+               virtual ULong_t Hash() const { return fCounterName.Hash(); }
+               
+               /// Returns the oldest counter value.
+               ULong64_t OldestCounter() const { return fCounterBuffer[fPos]; }
+               
+               /// Returns the oldest time value.
+               Double_t OldestTime() const { return fTimeBuffer[fPos]; }
+               
+               /**
+                * Increments the buffer. The new time and counter values are put into the
+                * current location to replace the existing values, then the current position
+                * is incremented (and wrapped around if necessary).
+                * \param newCounter  The new counter value to put into the buffer.
+                * \param newTime  The new time value to put into the buffer.
+                */
+               void Increment(ULong64_t newCounter, Double_t newTime)
+               {
+                       fCounterBuffer[fPos] = newCounter;
+                       fTimeBuffer[fPos] = newTime;
+                       fPos = (fPos+1) % kTimeStampEntries;
+               }
+               
+       private:
+               
+               TString fCounterName;  // The name of the counter.
+               UInt_t fPos;  // Current position in the buffers.
+               ULong64_t fCounterBuffer[kTimeStampEntries];  // The counter elements of the buffer.
+               Double_t fTimeBuffer[kTimeStampEntries];  // The time elements of the buffer.
+       };
+       
+       // Do not allow copying of this class.
+       AliHLTTriggerCounterComponent(const AliHLTTriggerCounterComponent& obj);
+       AliHLTTriggerCounterComponent& operator = (const AliHLTTriggerCounterComponent& obj);
+       
+       /// Updates the counter rate value.
+       void UpdateCounterRate(AliHLTTriggerCounters::AliCounter* counter, AliRingBuffer* timeBuf, Double_t newTime);
+       
+       /// Loads the initial configuration of counters from the given CDB path.
+       int LoadConfigFromCDB(const char* cdbPath);
+       
+       /// Loads the initial configuration of counters from the given configuration file.
+       int LoadConfigFromFile(const char* configFile);
+       
+       /**
+        * Sets the initial counter values from a TMap object containing name description pairs.
+        * \param counters  The list of counters to initialise. This TMap should contain TObjString
+        *     pairs where the key is the name of the counter and the TMap value is the description.
+        *     If the 14th bit is set in the key TObjString then the counter is considered an
+        *     output counter and an input counter otherwise.
+        */
+       void SetInitialCounters(const TMap* counters);
+       
+       double fOutputMultiplier;    //! Multiplier value for the output size estimate.
+       AliHLTTriggerCounters fInputCounters; //! Input trigger counters.
+       AliHLTTriggerCounters fOutputCounters; //! Output trigger counters.
+       THashTable fInputTimes;  //! Cyclic buffer storing the time stamps when the input counters were received.
+       THashTable fOutputTimes;  //! Cyclic buffer storing the time stamps when the output counters were received.
+       Double_t fLastPublishTime;  //! The last time the counters were pushed back to the output.
+       Double_t fPublishPeriod;  //! The time between calls to push back the counters to output.
+       
+       static const char* fgkConfigCDBPath;  //! CDB configuration path.
+       static TMap fgInitialCounterConfig;   //! Initial configuration information for the counters.
+       
+       ClassDef(AliHLTTriggerCounterComponent, 0)  // Component for counting HLT triggers.
+};
+
+#endif // ALIHLTTRIGGERCOUNTERCOMPONENT_H
index c546591..f90c99d 100644 (file)
@@ -32,6 +32,7 @@
 #pragma link C++ class AliHLTMuonSpectroScalars::AliScalar+;
 #pragma link C++ class AliHLTMuonSpectroTriggerComponent+;
 #pragma link C++ class AliHLTUpcTriggerComponent+;
+#pragma link C++ class AliHLTTriggerCounterComponent+;
 #pragma link C++ class AliHLTTriggerCounters+;
 #pragma link C++ class AliHLTTriggerCounters::AliCounter+;
 
diff --git a/HLT/trigger/test/InitialCounterConfig.C b/HLT/trigger/test/InitialCounterConfig.C
new file mode 100644 (file)
index 0000000..7c3e947
--- /dev/null
@@ -0,0 +1,33 @@
+// $Id:  $
+/**************************************************************************
+ * This file is property of and copyright by the ALICE HLT Project        *
+ * ALICE Experiment at CERN, All rights reserved.                         *
+ *                                                                        *
+ * Primary Authors: Artur Szostak <artursz@iafrica.com>                   *
+ *                  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   InitialCounterConfig.C
+/// @author Artur Szostak <artursz@iafrica.com>
+/// @date   12 Nov 2009
+/// @brief  Implementation of initial counter configuration routine for testing.
+///
+/// The InitialCounterConfig routine generates the initial counter configuration
+/// to test the AliHLTTriggerCounterComponent class.
+
+void InitialCounterConfig()
+{
+       TMap& counters = AliHLTTriggerCounterComponent::InitialCounterConfig();
+       counters.Add(new TObjString("CINTA"), new TObjString("Input interaction trigger"));
+       TObjString* name = new TObjString("TRIGGER-A");
+       name->SetBit(1<<14); // mark as output trigger
+       counters.Add(name, new TObjString("Output trigger A"));
+}
index 1c7c160..df28e00 100644 (file)
@@ -8,7 +8,7 @@ AM_CPPFLAGS                     = -I$(top_srcdir)/BASE \
 
 EXTRA_DIST                     = 
 
-check_PROGRAMS                 = testTriggerDomain testGlobalTriggerComponent testMuonSpectroTrigger testAliHLTTriggerCounters
+check_PROGRAMS                 = testTriggerDomain testGlobalTriggerComponent testMuonSpectroTrigger testAliHLTTriggerCounters testTriggerCounterComponent
 
 testTriggerDomain_SOURCES      = testTriggerDomain.C
 
@@ -18,6 +18,8 @@ testMuonSpectroTrigger_SOURCES        = testMuonSpectroTrigger.C
 
 testAliHLTTriggerCounters_SOURCES = testAliHLTTriggerCounters.C
 
+testTriggerCounterComponent_SOURCES    = testTriggerCounterComponent.C
+
 # linker flags
 LDADD_COMMON                   = $(top_builddir)/BASE/libHLTbase.la \
                                  $(top_builddir)/MUON/libAliHLTMUON.la \
@@ -42,5 +44,8 @@ testMuonSpectroTrigger_LDFLAGS        = $(LDFLAGS_COMMON)
 testAliHLTTriggerCounters_LDADD   = $(LDADD_COMMON)
 testAliHLTTriggerCounters_LDFLAGS = $(LDFLAGS_COMMON)
 
+testTriggerCounterComponent_LDADD      = $(LDADD_COMMON)
+testTriggerCounterComponent_LDFLAGS    = $(LDFLAGS_COMMON)
+
 TESTS                          = $(check_PROGRAMS)
 
diff --git a/HLT/trigger/test/testTriggerCounterComponent.C b/HLT/trigger/test/testTriggerCounterComponent.C
new file mode 100644 (file)
index 0000000..051d223
--- /dev/null
@@ -0,0 +1,408 @@
+/**************************************************************************
+ * This file is property of and copyright by the ALICE HLT Project        *
+ * ALICE Experiment at CERN, All rights reserved.                         *
+ *                                                                        *
+ * Primary Authors: Artur Szostak <artursz@iafrica.com>                   *
+ *                  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   testTriggerCounterComponent.C
+ * @author Artur Szostak <artursz@iafrica.com>
+ * @date   5 Nov 2010
+ *
+ * This macro is used to test the AliHLTTriggerCounterComponent class.
+ * Tests are run with component within the AliHLTSystem framework to check that
+ * the trigger counters are generated correctly by the component.
+ */
+
+#if !defined(__CINT__) || defined(__MAKECINT__)
+#include "TSystem.h"
+#include "TFile.h"
+#include "AliLog.h"
+#include "AliHLTTriggerCounters.h"
+#include "AliHLTTriggerDecision.h"
+#include "AliHLTGlobalTriggerDecision.h"
+#include "AliHLTSystem.h"
+#include "AliHLTConfiguration.h"
+#include "AliHLTCTPData.h"
+#include "Riostream.h"
+#endif
+
+/**
+ * Generates some sample input data and writes it into 9 files named
+ * testInputFileTriggerCounter1.root ... testInputFileTriggerCounter9.root
+ */
+void GenerateInputData()
+{
+       AliHLTTriggerDecision td1(true, "TRIGGER-A", AliHLTTriggerDomain("TRACKS:TPC"));
+       AliHLTTriggerDecision td1f(false, "TRIGGER-A", AliHLTTriggerDomain());
+       AliHLTTriggerDecision td2(true, "TRIGGER-B", AliHLTTriggerDomain("CLUSTERS:TPC"));
+       AliHLTTriggerDecision td2f(false, "TRIGGER-B", AliHLTTriggerDomain());
+       AliHLTTriggerDecision td3(true, "TRIGGER-C", AliHLTTriggerDomain("*******:***"));
+       AliHLTTriggerDecision td3f(false, "TRIGGER-C", AliHLTTriggerDomain());
+       AliHLTGlobalTriggerDecision gd1(true, AliHLTTriggerDomain("TRACKS:TPC"), "TRIGGER-A");
+       AliHLTGlobalTriggerDecision gd2(true, AliHLTTriggerDomain("CLUSTERS:TPC"), "TRIGGER-B");
+       AliHLTGlobalTriggerDecision gd3(true, AliHLTTriggerDomain("*******:***"), "TRIGGER-B,TRIGGER-C");
+       
+       AliHLTCTPData ctp("CTP_TRIGGER_CLASS=00:CINTA:17,01:CINTB:00-01-02-03-04-05-06-07-08-09-10-11-12-13-14-15-16-17,02:CMUB:00-10-11-17");
+       gd1.AddInputObjectRef(&ctp);
+       gd2.AddInputObjectRef(&ctp);
+       gd3.AddInputObjectRef(&ctp);
+       
+       TFile* file = new TFile("testInputFileTriggerCounter1.root", "RECREATE");
+       ctp.Increment(int(0));
+       gd1.Write("HLTGlobalTrigger");
+       td1.Write("Trigger");
+       delete file;
+       
+       file = new TFile("testInputFileTriggerCounter2.root", "RECREATE");
+       ctp.Increment(int(1));
+       gd2.Write("HLTGlobalTrigger");
+       td1f.Write("Trigger");
+       td2.Write("Trigger");
+       td3f.Write("Trigger");
+       delete file;
+       
+       file = new TFile("testInputFileTriggerCounter3.root", "RECREATE");
+       ctp.Increment(int(2));
+       gd3.Write("HLTGlobalTrigger");
+       td1f.Write("Trigger");
+       td2.Write("Trigger");
+       td3.Write("Trigger");
+       delete file;
+       
+       gd1.AddTriggerInput(td1);
+       gd2.AddTriggerInput(td1f);
+       gd2.AddTriggerInput(td2);
+       gd2.AddTriggerInput(td3f);
+       gd3.AddTriggerInput(td1f);
+       gd3.AddTriggerInput(td2);
+       gd3.AddTriggerInput(td3);
+       
+       file = new TFile("testInputFileTriggerCounter4.root", "RECREATE");
+       ctp.Increment(int(0));
+       gd1.Write("HLTGlobalTrigger");
+       td1.Write("Trigger");
+       delete file;
+       
+       file = new TFile("testInputFileTriggerCounter5.root", "RECREATE");
+       ctp.Increment(int(1));
+       gd2.Write("HLTGlobalTrigger");
+       td1f.Write("Trigger");
+       td2.Write("Trigger");
+       delete file;
+       
+       file = new TFile("testInputFileTriggerCounter6.root", "RECREATE");
+       ctp.Increment(int(2));
+       gd3.Write("HLTGlobalTrigger");
+       td1f.Write("Trigger");
+       td2.Write("Trigger");
+       td3.Write("Trigger");
+       delete file;
+       
+       file = new TFile("testInputFileTriggerCounter7.root", "RECREATE");
+       ctp.Increment(int(0));
+       gd1.Write("HLTGlobalTrigger");
+       delete file;
+       
+       file = new TFile("testInputFileTriggerCounter8.root", "RECREATE");
+       ctp.Increment(int(1));
+       gd2.Write("HLTGlobalTrigger");
+       delete file;
+       
+       file = new TFile("testInputFileTriggerCounter9.root", "RECREATE");
+       ctp.Increment(int(2));
+       gd3.Write("HLTGlobalTrigger");
+       delete file;
+}
+
+/**
+ * Runs a small chain with the HLTTriggerCounter component to generate output that
+ * can be checked.
+ * \param debug  If true then full debug logging is enabled.
+ * \param numOfEvents  The number of events to run the chain for.
+ */
+void RunTriggerCounter(bool debug = false, int numOfEvents = 9)
+{
+       AliHLTSystem sys;
+       sys.LoadComponentLibraries("libAliHLTUtil.so");
+       sys.LoadComponentLibraries("libAliHLTTRD.so");
+       sys.LoadComponentLibraries("libAliHLTMUON.so");
+       sys.LoadComponentLibraries("libAliHLTTrigger.so");
+       if (debug)
+       {
+               AliLog::SetGlobalLogLevel(AliLog::kMaxType);
+               sys.SetGlobalLoggingLevel(kHLTLogAll);
+       }
+       
+       TString cmdline = "-datatype GLOBTRIG 'HLT ' -objectname HLTGlobalTrigger ";
+       for (int i = 1; i <= 9; i++)
+       {
+               if (i > 1) cmdline += " -nextevent";
+               cmdline += Form(" -datafile testInputFileTriggerCounter%d.root", i);
+       }
+       AliHLTConfiguration pub1("pub1", "ROOTFilePublisher", NULL, cmdline.Data());
+       cmdline = "-datatype TRIG_DEC 'HLT ' -objectname Trigger ";
+       for (int i = 1; i <= 9; i++)
+       {
+               if (i > 1) cmdline += " -nextevent";
+               cmdline += Form(" -datafile testInputFileTriggerCounter%d.root", i);
+       }
+       AliHLTConfiguration pub2("pub2", "ROOTFilePublisher", NULL, cmdline.Data());
+       AliHLTConfiguration proc("proc", "HLTTriggerCounter", "pub1 pub2", "-skipcdb -config InitialCounterConfig.C");
+       AliHLTConfiguration sink("sink", "ROOTFileWriter", "proc", "-datafile testOutputFileTriggerCounter.root -concatenate-events");
+       sys.BuildTaskList("sink");
+       sys.Run(numOfEvents);
+}
+
+/**
+ * Checks that the input and output counters have the expected values or not.
+ * If they do not an appropriate error message is printed.
+ * \param eventNum  The number of the event being checked.
+ * \param inputCounters  The input counters to check.
+ * \param outputCounters  The output counters to check.
+ * \param expectedInputCounters  The expected input counter values to check against.
+ * \param expectedOutputCounters  The expected output counter values to check against.
+ * \param expectedDescription  The expected resulting trigger description.
+ * \returns true if the counters are correct and false otherwise.
+ */
+bool CheckCounters(
+               int eventNum,
+               AliHLTTriggerCounters* inputCounters,
+               AliHLTTriggerCounters* outputCounters,
+               AliHLTTriggerCounters& expectedInputCounters,
+               AliHLTTriggerCounters& expectedOutputCounters
+       )
+{
+       if (inputCounters == NULL)
+       {
+               cerr << "ERROR: No trigger input counters were found for event "
+                    << eventNum << "." << endl;
+               return false;
+       }
+       if (outputCounters == NULL)
+       {
+               cerr << "ERROR: No trigger output counters were found for event "
+                    << eventNum << "." << endl;
+               return false;
+       }
+       // Copy over the Rates because these might not be identical since they are a
+       // run time parameter. The counter value and name must be identical however.
+       for (UInt_t i = 0; i < inputCounters->NumberOfCounters() && i < expectedInputCounters.NumberOfCounters(); ++i)
+       {
+               expectedInputCounters.GetCounterN(i).Rate( inputCounters->GetCounterN(i).Rate() );
+       }
+       for (UInt_t i = 0; i < outputCounters->NumberOfCounters() && i < expectedOutputCounters.NumberOfCounters(); ++i)
+       {
+               expectedOutputCounters.GetCounterN(i).Rate( outputCounters->GetCounterN(i).Rate() );
+       }
+       bool inputCountersAsExpected = (inputCounters->NumberOfCounters() == expectedInputCounters.NumberOfCounters());
+       bool outputCountersAsExpected = (outputCounters->NumberOfCounters() == expectedOutputCounters.NumberOfCounters());
+       for (UInt_t i = 0; i < inputCounters->NumberOfCounters() && i < expectedInputCounters.NumberOfCounters(); ++i)
+       {
+               if (strcmp(expectedInputCounters.GetCounterN(i).Name(), inputCounters->GetCounterN(i).Name()) != 0)
+               {
+                       inputCountersAsExpected = false;
+                       break;
+               }
+               if (expectedInputCounters.GetCounterN(i).Counter() != inputCounters->GetCounterN(i).Counter())
+               {
+                       inputCountersAsExpected = false;
+                       break;
+               }
+       }
+       for (UInt_t i = 0; i < outputCounters->NumberOfCounters() && i < expectedOutputCounters.NumberOfCounters(); ++i)
+       {
+               if (strcmp(expectedOutputCounters.GetCounterN(i).Name(), outputCounters->GetCounterN(i).Name()) != 0)
+               {
+                       outputCountersAsExpected = false;
+                       break;
+               }
+               if (expectedOutputCounters.GetCounterN(i).Counter() != outputCounters->GetCounterN(i).Counter())
+               {
+                       outputCountersAsExpected = false;
+                       break;
+               }
+       }
+       if (! inputCountersAsExpected)
+       {
+               cerr << "ERROR: The trigger input counters do not match the expected set of counters for event "
+                    << eventNum << "." << endl;
+               cout << "Found the following input counters: " << endl;  // using cout since Print() goes there.
+               inputCounters->Print();
+               cout << "But expected the following input counters: " << endl;
+               expectedInputCounters.Print();
+               return false;
+       }
+       if (! outputCountersAsExpected)
+       {
+               cerr << "ERROR: The trigger output counters do not match the expected set of counters for event "
+                    << eventNum << "." << endl;
+               cout << "Found the following output counters: " << endl;  // using cout since Print() goes there.
+               outputCounters->Print();
+               cout << "But expected the following output counters: " << endl;
+               expectedOutputCounters.Print();
+               return false;
+       }
+       return true;
+}
+
+
+/// Routine for checking the results file generated by the RunTriggerCounter routine.
+bool CheckTriggerCounterOutput()
+{
+       AliHLTTriggerCounters expectedInputCounters[11];
+       AliHLTTriggerCounters expectedOutputCounters[11];
+       
+       // Start-of-run event (should contain no values)
+       expectedInputCounters[0].Add("CINTA", "", 0, 0);
+       expectedOutputCounters[0].Add("TRIGGER-A", "", 0, 0);
+       
+       // Data events
+       expectedInputCounters[1].Add("CINTA", "", 0, 1);
+       expectedInputCounters[1].Add("CINTB", "", 0, 0);
+       expectedInputCounters[1].Add("CMUB", "", 0, 0);
+       expectedInputCounters[1].Add("TRIGGER-A", "", 0, 1);
+       expectedOutputCounters[1].Add("TRIGGER-A", "", 0, 1);
+       
+       expectedInputCounters[2].Add("CINTA", "", 0, 1);
+       expectedInputCounters[2].Add("CINTB", "", 0, 1);
+       expectedInputCounters[2].Add("CMUB", "", 0, 0);
+       expectedInputCounters[2].Add("TRIGGER-A", "", 0, 1);
+       expectedInputCounters[2].Add("TRIGGER-B", "", 0, 1);
+       expectedOutputCounters[2].Add("TRIGGER-A", "", 0, 1);
+       expectedOutputCounters[2].Add("TRIGGER-B", "", 0, 1);
+       
+       expectedInputCounters[3].Add("CINTA", "", 0, 1);
+       expectedInputCounters[3].Add("CINTB", "", 0, 1);
+       expectedInputCounters[3].Add("CMUB", "", 0, 1);
+       expectedInputCounters[3].Add("TRIGGER-A", "", 0, 1);
+       expectedInputCounters[3].Add("TRIGGER-B", "", 0, 2);
+       expectedInputCounters[3].Add("TRIGGER-C", "", 0, 1);
+       expectedOutputCounters[3].Add("TRIGGER-A", "", 0, 1);
+       expectedOutputCounters[3].Add("TRIGGER-B", "", 0, 2);
+       expectedOutputCounters[3].Add("TRIGGER-C", "", 0, 1);
+       
+       expectedInputCounters[4].Add("CINTA", "", 0, 2);
+       expectedInputCounters[4].Add("CINTB", "", 0, 1);
+       expectedInputCounters[4].Add("CMUB", "", 0, 1);
+       expectedInputCounters[4].Add("TRIGGER-A", "", 0, 2);
+       expectedInputCounters[4].Add("TRIGGER-B", "", 0, 2);
+       expectedInputCounters[4].Add("TRIGGER-C", "", 0, 1);
+       expectedOutputCounters[4].Add("TRIGGER-A", "", 0, 2);
+       expectedOutputCounters[4].Add("TRIGGER-B", "", 0, 2);
+       expectedOutputCounters[4].Add("TRIGGER-C", "", 0, 1);
+       
+       expectedInputCounters[5].Add("CINTA", "", 0, 2);
+       expectedInputCounters[5].Add("CINTB", "", 0, 2);
+       expectedInputCounters[5].Add("CMUB", "", 0, 1);
+       expectedInputCounters[5].Add("TRIGGER-A", "", 0, 2);
+       expectedInputCounters[5].Add("TRIGGER-B", "", 0, 3);
+       expectedInputCounters[5].Add("TRIGGER-C", "", 0, 1);
+       expectedOutputCounters[5].Add("TRIGGER-A", "", 0, 2);
+       expectedOutputCounters[5].Add("TRIGGER-B", "", 0, 3);
+       expectedOutputCounters[5].Add("TRIGGER-C", "", 0, 1);
+       
+       expectedInputCounters[6].Add("CINTA", "", 0, 2);
+       expectedInputCounters[6].Add("CINTB", "", 0, 2);
+       expectedInputCounters[6].Add("CMUB", "", 0, 2);
+       expectedInputCounters[6].Add("TRIGGER-A", "", 0, 2);
+       expectedInputCounters[6].Add("TRIGGER-B", "", 0, 4);
+       expectedInputCounters[6].Add("TRIGGER-C", "", 0, 2);
+       expectedOutputCounters[6].Add("TRIGGER-A", "", 0, 2);
+       expectedOutputCounters[6].Add("TRIGGER-B", "", 0, 4);
+       expectedOutputCounters[6].Add("TRIGGER-C", "", 0, 2);
+       
+       expectedInputCounters[7].Add("CINTA", "", 0, 3);
+       expectedInputCounters[7].Add("CINTB", "", 0, 2);
+       expectedInputCounters[7].Add("CMUB", "", 0, 2);
+       expectedInputCounters[7].Add("TRIGGER-A", "", 0, 3);
+       expectedInputCounters[7].Add("TRIGGER-B", "", 0, 4);
+       expectedInputCounters[7].Add("TRIGGER-C", "", 0, 2);
+       expectedOutputCounters[7].Add("TRIGGER-A", "", 0, 3);
+       expectedOutputCounters[7].Add("TRIGGER-B", "", 0, 4);
+       expectedOutputCounters[7].Add("TRIGGER-C", "", 0, 2);
+       
+       expectedInputCounters[8].Add("CINTA", "", 0, 3);
+       expectedInputCounters[8].Add("CINTB", "", 0, 3);
+       expectedInputCounters[8].Add("CMUB", "", 0, 2);
+       expectedInputCounters[8].Add("TRIGGER-A", "", 0, 3);
+       expectedInputCounters[8].Add("TRIGGER-B", "", 0, 5);
+       expectedInputCounters[8].Add("TRIGGER-C", "", 0, 2);
+       expectedOutputCounters[8].Add("TRIGGER-A", "", 0, 3);
+       expectedOutputCounters[8].Add("TRIGGER-B", "", 0, 5);
+       expectedOutputCounters[8].Add("TRIGGER-C", "", 0, 2);
+       
+       expectedInputCounters[9].Add("CINTA", "", 0, 3);
+       expectedInputCounters[9].Add("CINTB", "", 0, 3);
+       expectedInputCounters[9].Add("CMUB", "", 0, 3);
+       expectedInputCounters[9].Add("TRIGGER-A", "", 0, 3);
+       expectedInputCounters[9].Add("TRIGGER-B", "", 0, 6);
+       expectedInputCounters[9].Add("TRIGGER-C", "", 0, 3);
+       expectedOutputCounters[9].Add("TRIGGER-A", "", 0, 3);
+       expectedOutputCounters[9].Add("TRIGGER-B", "", 0, 6);
+       expectedOutputCounters[9].Add("TRIGGER-C", "", 0, 3);
+       
+       // End-of-run event
+       expectedInputCounters[10].Add("CINTA", "", 0, 3);
+       expectedInputCounters[10].Add("CINTB", "", 0, 3);
+       expectedInputCounters[10].Add("CMUB", "", 0, 3);
+       expectedInputCounters[10].Add("TRIGGER-A", "", 0, 3);
+       expectedInputCounters[10].Add("TRIGGER-B", "", 0, 6);
+       expectedInputCounters[10].Add("TRIGGER-C", "", 0, 3);
+       expectedOutputCounters[10].Add("TRIGGER-A", "", 0, 3);
+       expectedOutputCounters[10].Add("TRIGGER-B", "", 0, 6);
+       expectedOutputCounters[10].Add("TRIGGER-C", "", 0, 3);
+       
+       TFile* file = new TFile("testOutputFileTriggerCounter.root", "READ");
+       for (int i = 0; i < 11; ++i)
+       {
+               AliHLTTriggerCounters* inputCounters = dynamic_cast<AliHLTTriggerCounters*>( file->Get(Form("AliHLTTriggerCounters;%d", i*2+1)) );
+               AliHLTTriggerCounters* outputCounters = dynamic_cast<AliHLTTriggerCounters*>( file->Get(Form("AliHLTTriggerCounters;%d", i*2+2)) );
+               if (! CheckCounters(i-1, inputCounters, outputCounters, expectedInputCounters[i], expectedOutputCounters[i]))
+               {
+                       delete file;
+                       return false;
+               }
+       }
+       delete file;
+       return true;
+}
+
+/**
+ * Runs several tests for the AliHLTTriggerCounterComponent class.
+ * We specifically test if the generated counters are correctly generated.
+ * \param debug  If true then full debug logging is enabled.
+ * \param numOfEvents  The number of events to run the chain over.
+ * \returns true if all the tests succeeded and false otherwise.
+ */
+bool testTriggerCounterComponent(bool debug = false, int numOfEvents = 9)
+{
+       GenerateInputData();
+       RunTriggerCounter(debug, numOfEvents);
+       if (! CheckTriggerCounterOutput()) return false;
+       // Cleanup all temporary files generated.
+       gSystem->Exec("rm -f testOutputFileTriggerCounter.root testInputFileTriggerCounter*.root");
+       return true;
+}
+
+
+#ifndef __MAKECINT__
+
+int main(int /*argc*/, const char** /*argv*/)
+{
+       bool resultOk = testTriggerCounterComponent();
+       if (not resultOk) return 1;
+       return 0;
+}
+
+#endif // __MAKECINT__