--- /dev/null
+/**************************************************************************
+ * This file is property of and copyright by the ALICE HLT Project *
+ * All rights reserved. *
+ * *
+ * Primary Authors: *
+ * Artur Szostak <artursz@iafrica.com> *
+ * *
+ * 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. *
+ **************************************************************************/
+
+/* $Id$ */
+
+///
+/// @file AliHLTMUONEmptyEventFilterComponent.cxx
+/// @author Artur Szostak <artursz@iafrica.com>
+/// @date 2007-12-12
+/// @brief Implementation of the empty event filter component.
+///
+/// This component is used to forward events for where there is at least one
+/// non-empty dHLT data block.
+///
+
+#include "AliHLTMUONEmptyEventFilterComponent.h"
+#include "AliHLTMUONRecHitsBlockStruct.h"
+#include "AliHLTMUONTriggerRecordsBlockStruct.h"
+#include "AliHLTMUONMansoTracksBlockStruct.h"
+#include "AliHLTMUONConstants.h"
+#include "AliHLTLogging.h"
+#include "AliHLTSystem.h"
+#include "AliHLTDefinitions.h"
+#include <cstdlib>
+#include <cerrno>
+#include <cassert>
+
+ClassImp(AliHLTMUONEmptyEventFilterComponent)
+
+
+AliHLTMUONEmptyEventFilterComponent::AliHLTMUONEmptyEventFilterComponent() :
+ AliHLTProcessor(),
+ fSendOnEmpty(false)
+{
+ ///
+ /// Default constructor.
+ ///
+}
+
+
+AliHLTMUONEmptyEventFilterComponent::~AliHLTMUONEmptyEventFilterComponent()
+{
+ ///
+ /// Default destructor.
+ ///
+}
+
+const char* AliHLTMUONEmptyEventFilterComponent::GetComponentID()
+{
+ ///
+ /// Inherited from AliHLTComponent. Returns the component ID.
+ ///
+
+ return AliHLTMUONConstants::EmptyEventFilterComponentId();
+}
+
+
+void AliHLTMUONEmptyEventFilterComponent::GetInputDataTypes( std::vector<AliHLTComponentDataType>& list)
+{
+ ///
+ /// Inherited from AliHLTProcessor. Returns the list of expected input data types.
+ /// At the moment this list is "any data type" since it is not known before
+ /// hand what kind of input blocks we will get.
+
+ assert( list.empty() );
+ list.push_back( kAliHLTAnyDataType );
+}
+
+
+AliHLTComponentDataType AliHLTMUONEmptyEventFilterComponent::GetOutputDataType()
+{
+ ///
+ /// Inherited from AliHLTComponent. Returns the output data type of
+ /// "any data type" with MUON origin.
+
+ return kAliHLTAnyDataType | kAliHLTDataOriginMUON;
+}
+
+
+void AliHLTMUONEmptyEventFilterComponent::GetOutputDataSize(
+ unsigned long& constBase, double& inputMultiplier
+ )
+{
+ ///
+ /// Inherited from AliHLTComponent.
+ /// Returns an estimate of the expected output data size.
+
+ // Both of these are zero because we will only ever pass on input data blocks
+ // and never generate data in this component.
+ constBase = 0;
+ inputMultiplier = 0;
+}
+
+
+AliHLTComponent* AliHLTMUONEmptyEventFilterComponent::Spawn()
+{
+ ///
+ /// Inherited from AliHLTComponent. Creates a new object instance.
+ ///
+
+ return new AliHLTMUONEmptyEventFilterComponent;
+}
+
+
+int AliHLTMUONEmptyEventFilterComponent::DoInit(int argc, const char** argv)
+{
+ ///
+ /// Inherited from AliHLTComponent.
+ /// Parses the command line parameters and initialises the component.
+ ///
+
+ fSendOnEmpty = false; // Set to the default value.
+
+ for (int i = 0; i < argc; i++)
+ {
+ if (strcmp(argv[i], "-sendempty") == 0)
+ {
+ fSendOnEmpty = true;
+ HLTInfo("Turning on anti-filtering. Will be passing all data on empty dHLT results.");
+ continue;
+ }
+
+ HLTError("Unknown option '%s'.", argv[i]);
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+
+int AliHLTMUONEmptyEventFilterComponent::DoDeinit()
+{
+ ///
+ /// Inherited from AliHLTComponent. Performs a cleanup of the component.
+ ///
+
+ return 0;
+}
+
+
+int AliHLTMUONEmptyEventFilterComponent::DoEvent(
+ const AliHLTComponentEventData& evtData,
+ const AliHLTComponentBlockData* blocks,
+ AliHLTComponentTriggerData& /*trigData*/,
+ AliHLTUInt8_t* /*outputPtr*/,
+ AliHLTUInt32_t& size,
+ std::vector<AliHLTComponentBlockData>& outputBlocks
+ )
+{
+ /// Inherited from AliHLTProcessor. Processes the new event data.
+ /// Here we go through the list of input data blocks looking for blocks
+ /// containing dHLT results. If all of these blocks are empty then we
+ /// mark the event for filtering.
+ /// What we actually do with the whole event will depend on the fSendOnEmpty
+ /// flag. If it is set to false (the default) then we will copy all the
+ /// input data blocks to output if the dHLT results were NOT empty.
+ /// If fSendOnEmpty is true then we will copy all the input data blocks
+ /// to the output if the dHLT results ARE empty.
+
+ HLTDebug("Processing event %llu with %u input data blocks.",
+ evtData.fEventID, evtData.fBlockCnt
+ );
+
+ bool emptyEvent = true;
+
+ for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
+ {
+#ifdef __DEBUG
+ char id[kAliHLTComponentDataTypefIDsize+1];
+ for (int i = 0; i < kAliHLTComponentDataTypefIDsize; i++)
+ id[i] = blocks[n].fDataType.fID[i];
+ id[kAliHLTComponentDataTypefIDsize] = '\0';
+ char origin[kAliHLTComponentDataTypefOriginSize+1];
+ for (int i = 0; i < kAliHLTComponentDataTypefOriginSize; i++)
+ origin[i] = blocks[n].fDataType.fOrigin[i];
+ origin[kAliHLTComponentDataTypefOriginSize] = '\0';
+#endif // __DEBUG
+ HLTDebug("Handling block: %u, with fDataType.fID = '%s',"
+ " fDataType.fID = '%s', fPtr = %p and fSize = %u bytes.",
+ n, static_cast<char*>(id), static_cast<char*>(origin),
+ blocks[n].fPtr, blocks[n].fSize
+ );
+
+ if (blocks[n].fDataType == AliHLTMUONConstants::TriggerRecordsBlockDataType())
+ {
+ AliHLTMUONTriggerRecordsBlockReader inblock(blocks[n].fPtr, blocks[n].fSize);
+ if (not BlockStructureOk(inblock, blocks[n].fSize)) continue;
+ if (inblock.Nentries() != 0) emptyEvent = false;
+ }
+ else if (blocks[n].fDataType == AliHLTMUONConstants::RecHitsBlockDataType())
+ {
+ AliHLTMUONRecHitsBlockReader inblock(blocks[n].fPtr, blocks[n].fSize);
+ if (not BlockStructureOk(inblock, blocks[n].fSize)) continue;
+ if (inblock.Nentries() != 0) emptyEvent = false;
+ }
+ else if (blocks[n].fDataType == AliHLTMUONConstants::MansoTracksBlockDataType())
+ {
+ AliHLTMUONMansoTracksBlockReader inblock(blocks[n].fPtr, blocks[n].fSize);
+ if (not BlockStructureOk(inblock, blocks[n].fSize)) continue;
+ if (inblock.Nentries() != 0) emptyEvent = false;
+ }
+ else if (blocks[n].fDataType == AliHLTMUONConstants::SinglesDecisionBlockDataType())
+ {
+ AliHLTMUONSinglesDecisionBlockReader inblock(blocks[n].fPtr, blocks[n].fSize);
+ if (not BlockStructureOk(inblock, blocks[n].fSize)) continue;
+ if (inblock.Nentries() != 0) emptyEvent = false;
+ }
+ else if (blocks[n].fDataType == AliHLTMUONConstants::PairsDecisionBlockDataType())
+ {
+ AliHLTMUONPairsDecisionBlockReader inblock(blocks[n].fPtr, blocks[n].fSize);
+ if (not BlockStructureOk(inblock, blocks[n].fSize)) continue;
+ if (inblock.Nentries() != 0) emptyEvent = false;
+ }
+ }
+
+ // If we are filtering or required to send only empty events then
+ // copy all the input blocks to the output.
+ if (emptyEvent and fSendOnEmpty or not emptyEvent and not fSendOnEmpty)
+ {
+ for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
+ {
+ outputBlocks.push_back(blocks[n]);
+ }
+ }
+
+ // Finally we set the total size of output memory we consumed which is
+ // zero since we just copied the input descriptors to output if anything.
+ size = 0;
+ return 0;
+}
+
+
+template <class BlockType>
+bool AliHLTMUONEmptyEventFilterComponent::BlockStructureOk(
+ const BlockType& inblock,
+ const char* blockName,
+ AliHLTUInt32_t blockBufferSize
+ ) const
+{
+ /// Performs basic checks to see if the input data block structure is OK,
+ /// that is that it is not corrupt, too short etc...
+
+ if (not inblock.BufferSizeOk())
+ {
+ size_t headerSize = sizeof(typename BlockType::HeaderType);
+ if (blockBufferSize < headerSize)
+ {
+ HLTError("Received a %s data block with a size of %d bytes,"
+ " which is smaller than the minimum valid header size of %d bytes."
+ " The block must be corrupt.",
+ blockName, blockBufferSize, headerSize
+ );
+ return false;
+ }
+
+ size_t expectedWidth = sizeof(typename BlockType::ElementType);
+ if (inblock.CommonBlockHeader().fRecordWidth != expectedWidth)
+ {
+ HLTError("Received a %s data block with a record"
+ " width of %d bytes, but the expected value is %d bytes."
+ " The block might be corrupt.",
+ blockName,
+ inblock.CommonBlockHeader().fRecordWidth,
+ expectedWidth
+ );
+ return false;
+ }
+
+ HLTError("Received a %s data block with a size of %d bytes,"
+ " but the block header claims the block should be %d bytes."
+ " The block might be corrupt.",
+ blockName, blockBufferSize, inblock.BytesUsed()
+ );
+ return false;
+ }
+
+ return true;
+}
+
--- /dev/null
+#ifndef ALIHLTMUONEMPTYEVENTFILTERCOMPONENT_H
+#define ALIHLTMUONEMPTYEVENTFILTERCOMPONENT_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 */
+
+/* $Id$ */
+
+///
+/// @file AliHLTMUONEmptyEventFilterComponent.h
+/// @author Artur Szostak <artursz@iafrica.com>
+/// @date 2007-12-12
+/// @brief Declaration of the empty event filter component.
+///
+
+#include "AliHLTProcessor.h"
+#include "AliHLTMUONDataBlockReader.h"
+
+#if __GNUC__ && __GNUC__ < 3
+#define std
+#endif
+
+/**
+ * @class AliHLTMUONEmptyEventFilterComponent
+ * This component class is a utility component for debugging. It is used to filter
+ * empty dHLT events. (Specifically built for the Dec 2007 Cosmic tests where the
+ * muon spectrometer should not see any hits. Therefor we would be interested to
+ * analysis the raw data for those cases where the hit reconstructor actuall found
+ * something, because this would be strange/abnormal.)
+ * The component will look for dHLT data blocks containing results like dHLT
+ * reconstructed hits, trigger records and dHLT tracks,
+ * if any of the found blocks are not empty then every data block that it received
+ * will be forwarded to the output.
+ * This component would normally subscribe to all the front end DDL processing
+ * components like MUONHitReconstructor and MUONTriggerReconstructor, the DDL
+ * RORCPublishers for the DDL data and also the MUONMansoTrackerFSM component.
+ * A dump subscriber can then connect to the empty event filter component to
+ * make sure it only receives events that are not empty.
+ *
+ * command line parameters:
+ * -sendempty This parameter causes the component to behave like an anti-filter
+ * meaning that it will send all events for which the dHLT results data
+ * blocks were empty. This is useful for collecting those events where dHLT
+ * is not finding anything but perhaps it should.
+ */
+class AliHLTMUONEmptyEventFilterComponent : public AliHLTProcessor
+{
+public:
+ AliHLTMUONEmptyEventFilterComponent();
+ virtual ~AliHLTMUONEmptyEventFilterComponent();
+
+ // Public functions to implement AliHLTComponent's interface.
+ // These functions are required for the registration process.
+
+ virtual const char* GetComponentID();
+ virtual void GetInputDataTypes(std::vector<AliHLTComponentDataType>& list);
+ virtual AliHLTComponentDataType GetOutputDataType();
+ virtual void GetOutputDataSize( unsigned long& constBase, double& inputMultiplier );
+ virtual AliHLTComponent* Spawn();
+
+protected:
+
+ // Method to check the block structure and log appropriate error messages.
+ template <class BlockType>
+ bool BlockStructureOk(
+ const BlockType& inblock,
+ const char* blockName,
+ AliHLTUInt32_t blockBufferSize
+ ) const;
+
+ bool BlockStructureOk(
+ const AliHLTMUONRecHitsBlockReader& inblock,
+ AliHLTUInt32_t blockBufferSize
+ ) const
+ {
+ return BlockStructureOk(inblock, "reconstructed hits", blockBufferSize);
+ }
+
+ bool BlockStructureOk(
+ const AliHLTMUONTriggerRecordsBlockReader& inblock,
+ AliHLTUInt32_t blockBufferSize
+ ) const
+ {
+ return BlockStructureOk(inblock, "trigger records", blockBufferSize);
+ }
+
+ bool BlockStructureOk(
+ const AliHLTMUONMansoTracksBlockReader& inblock,
+ AliHLTUInt32_t blockBufferSize
+ ) const
+ {
+ return BlockStructureOk(inblock, "manso tracks", blockBufferSize);
+ }
+
+ bool BlockStructureOk(
+ const AliHLTMUONSinglesDecisionBlockReader& inblock,
+ AliHLTUInt32_t blockBufferSize
+ ) const
+ {
+ return BlockStructureOk(inblock, "singles decision", blockBufferSize);
+ }
+
+ bool BlockStructureOk(
+ const AliHLTMUONPairsDecisionBlockReader& inblock,
+ AliHLTUInt32_t blockBufferSize
+ ) const
+ {
+ return BlockStructureOk(inblock, "pairs decision", blockBufferSize);
+ }
+
+ // Protected functions to implement AliHLTComponent's interface.
+ // These functions provide initialization as well as the actual processing
+ // capabilities of the component.
+
+ virtual int DoInit(int argc, const char** argv);
+ virtual int DoDeinit();
+ virtual int DoEvent(
+ const AliHLTComponentEventData& evtData,
+ const AliHLTComponentBlockData* blocks,
+ AliHLTComponentTriggerData& trigData,
+ AliHLTUInt8_t* outputPtr,
+ AliHLTUInt32_t& size,
+ std::vector<AliHLTComponentBlockData>& outputBlocks
+ );
+
+ using AliHLTProcessor::DoEvent;
+
+private:
+
+ // Do not allow copying of this class.
+ AliHLTMUONEmptyEventFilterComponent(const AliHLTMUONEmptyEventFilterComponent& /*obj*/);
+ AliHLTMUONEmptyEventFilterComponent& operator = (const AliHLTMUONEmptyEventFilterComponent& /*obj*/);
+
+ bool fSendOnEmpty; //! Flag indicating if we should implement the inverse filter and only send everything if dHLT internal data blocks are empty.
+
+ ClassDef(AliHLTMUONEmptyEventFilterComponent, 0)
+};
+
+#endif // ALIHLTMUONEMPTYEVENTFILTERCOMPONENT_H
+