Update in HP decoders:
authorivana <ivana@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 25 Apr 2008 14:24:39 +0000 (14:24 +0000)
committerivana <ivana@f7af4fe6-9843-0410-8265-dc069ae4e863>
Fri, 25 Apr 2008 14:24:39 +0000 (14:24 +0000)
Added:
A new high performance decoder for the MUON trigger detector (AliMUONTriggerDDLDecoder).
The corresponding stream interface class AliMUONRawStreamTriggerHP has been created
to interface the decoder with AliRoot.
Also added the abstract class AliMUONVRawStreamTrigger and made both AliMUONRawStreamTrigger
and AliMUONRawStreamTriggerHP inherit from that. This allows easy exchange of the decoders.

Bug fix:
AliMUONRawStreamTrackerHP was not working for mixtures of empty events and partial events. This is now fixed.

Minor changes:
Made some documentation corrections to AliMUONRawStreamTrackerHP.
Also added static methods to the AliMUONTrackerDDLDecoder to be able to read out the raw data structure key constants from other classes, similarly to what is now done in AliMUONTriggerDDLDecoder.

(Artur)

15 files changed:
MUON/AliMUONRawStreamTrackerHP.cxx
MUON/AliMUONRawStreamTrackerHP.h
MUON/AliMUONRawStreamTrigger.cxx
MUON/AliMUONRawStreamTrigger.h
MUON/AliMUONRawStreamTriggerHP.cxx [new file with mode: 0644]
MUON/AliMUONRawStreamTriggerHP.h [new file with mode: 0644]
MUON/AliMUONTrackerDDLDecoder.h
MUON/AliMUONTriggerDDLDecoder.h [new file with mode: 0644]
MUON/AliMUONTriggerDDLDecoderEventHandler.h [new file with mode: 0644]
MUON/AliMUONVRawStreamTrigger.h [new file with mode: 0644]
MUON/MUONRawStreamTrigger.C
MUON/MUONTimeRawStreamTracker.C
MUON/MUONTimeRawStreamTrigger.C [new file with mode: 0644]
MUON/MUONrawLinkDef.h
MUON/libMUONraw.pkg

index 6332e351f08150a67b978c8874249ab2fd8d9634..48937336a69d242e0a799dd4d76df3ef75fe7599 100644 (file)
@@ -155,6 +155,11 @@ Bool_t AliMUONRawStreamTrackerHP::NextDDL()
 
        assert( GetReader() != NULL );
        
+       // Better to reset these pointers.
+       fCurrentBusPatch = NULL;
+       fCurrentData = NULL;
+       fEndOfData = NULL;
+       
        while (fDDL < GetMaxDDL())
        {
                GetReader()->Reset();
@@ -165,7 +170,7 @@ Bool_t AliMUONRawStreamTrackerHP::NextDDL()
        }
 
        // If we reach the end of the DDL list for this event then reset the
-       // DDL counter, mark the iteration as done and 
+       // DDL counter, mark the iteration as done and exit.
        if (fDDL >= GetMaxDDL())
        {
                fDDL = 0;
@@ -267,6 +272,8 @@ Bool_t AliMUONRawStreamTrackerHP::Next(
        /// \return kTRUE if we read another digit and kFALSE if we have read all the
        ///    digits already, i.e. at the end of the iteration.
        
+       if (fCurrentData == NULL) return kFALSE;
+       
 retry:
        // Check if we still have data to be returned for the current bus patch.
        if (fCurrentData != fEndOfData)
@@ -474,7 +481,7 @@ void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::SetMaxStructs(
        fBlocks = new AliBlockHeader[maxBlocks];
        fDSPs = new AliDspHeader[maxBlocks*maxDsps];
        fBusPatches = new AliBusPatch[maxBlocks*maxDsps*maxBusPatches];
-       fEndOfBusPatches = fEndOfBusPatches;
+       fEndOfBusPatches = fBusPatches;
 }
 
 
@@ -533,7 +540,7 @@ void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnError(
        /// This is called by the high performance decoder when a error occurs
        /// when trying to decode the DDL payload. This indicates corruption in
        /// the data. This method converts the error code to a descriptive message
-       /// and log this with the raw reader.
+       /// and logs this with the raw reader.
        /// \param error  The error code indicating the problem.
        /// \param location  A pointer to the location within the DDL payload buffer
        ///              being decoded where the problem with the data was found.
@@ -547,6 +554,7 @@ void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnError(
        switch (error)
        {
        case kGlitchFound:
+               fGlitchErrors++;
                message = Form(
                        "Glitch error detected in DSP %d, skipping event ",
                        fCurrentBlock->GetDspId()
@@ -555,6 +563,7 @@ void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnError(
                break;
 
        case kBadPaddingWord:
+               fPaddingErrors++;
                // We subtract 1 from the current numbers of blocks, DSPs
                // and bus patches to get the indices.
                message = Form(
@@ -567,6 +576,7 @@ void AliMUONRawStreamTrackerHP::AliDecoderEventHandler::OnError(
                break;
 
        case kParityError:
+               fParityErrors++;
                // location points to the incorrect data word and
                // fCurrentBusPatch->GetData() returns a pointer to the start of
                // bus patches data, so the difference divided by 4 gives the 32
index a2acc1fa3e7b80d1e9cc8a10972ccedaad4576a1..a893da9eed83c4c674e815c00d61fef8e1fd6e94 100644 (file)
@@ -613,7 +613,7 @@ private:
        Int_t fDDL;         //!< The current DDL number being handled.
        Int_t fBufferSize;  //!< This is the buffer size in bytes of fBuffer.
        UChar_t* fBuffer;   //!< This is the buffer in which we store the DDL payload read from AliRawReader.
-       const AliBusPatch* fCurrentBusPatch;  //!< The current data word to return by Next().
+       const AliBusPatch* fCurrentBusPatch;  //!< The current bus patch being handled by Next().
        const UInt_t* fCurrentData;  //!< The current data word to return by Next().
        const UInt_t* fEndOfData;  //!< The last data word in the current bus patch.
        Bool_t fHadError;   //!< Flag indicating if there was a decoding error or not.
@@ -627,6 +627,7 @@ private:
 inline const AliMUONRawStreamTrackerHP::AliBusPatch* AliMUONRawStreamTrackerHP::Next()
 {
        /// Returns the next batch of decoded channel data.
+       if (fCurrentBusPatch == NULL) return NULL;
        do {
                if (fCurrentBusPatch != fDecoder.GetHandler().EndOfBusPatch())
                        return fCurrentBusPatch++;
index c4a309281f2ac8a80ade90e1c97be48ce29f4990..e3cf67fb16fa9e4d94ae95e50a4ac12743261041 100644 (file)
@@ -53,7 +53,7 @@ const Int_t AliMUONRawStreamTrigger::fgkMaxDDL = 2;
 
 //___________________________________________
 AliMUONRawStreamTrigger::AliMUONRawStreamTrigger()
-:   AliMUONRawStream(),
+:   AliMUONVRawStreamTrigger(),
     fPayload(new AliMUONPayloadTrigger()),
     fCurrentDDL(0x0),
     fCurrentDDLIndex(fgkMaxDDL),
@@ -77,7 +77,7 @@ AliMUONRawStreamTrigger::AliMUONRawStreamTrigger()
 
 //_________________________________________________________________
 AliMUONRawStreamTrigger::AliMUONRawStreamTrigger(AliRawReader* rawReader)
-  : AliMUONRawStream(rawReader),
+  : AliMUONVRawStreamTrigger(rawReader),
     fPayload(new AliMUONPayloadTrigger()),
     fCurrentDDL(0x0),
     fCurrentDDLIndex(fgkMaxDDL),
index ba1c9ba9f128028e7ee7c865bfff28b8976e4af0..27174a1a4d9ba5c592724e3c87eb3a7b37ee032b 100644 (file)
@@ -13,7 +13,7 @@
 
 #include <TObject.h>
 #include "AliMUONPayloadTrigger.h"
-#include "AliMUONRawStream.h"
+#include "AliMUONVRawStreamTrigger.h"
 class TArrayS;
 
 class AliRawReader;
@@ -22,7 +22,7 @@ class AliMUONDarcHeader;
 class AliMUONRegkHeader;
 class AliMUONLocalStruct;
 
-class AliMUONRawStreamTrigger: public AliMUONRawStream {
+class AliMUONRawStreamTrigger: public AliMUONVRawStreamTrigger {
   public :
     AliMUONRawStreamTrigger();
     AliMUONRawStreamTrigger(AliRawReader* rawReader);
diff --git a/MUON/AliMUONRawStreamTriggerHP.cxx b/MUON/AliMUONRawStreamTriggerHP.cxx
new file mode 100644 (file)
index 0000000..f2c0b9c
--- /dev/null
@@ -0,0 +1,607 @@
+/**************************************************************************
+ * 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$ */
+
+/// \class AliMUONRawStreamTriggerHP
+///
+/// Implementation of a streamer interface to the high performance trigger decoder.
+/// This is the raw stream class which interfaces between the high performance
+/// core decoder for MUON trigger chambers and the AliRawReader class.
+/// To gain the most out of the decoder, the Next() method should be used,
+/// for example:
+/// \code
+///   AliMUONRawStreamTriggerHP* rawStream;  // assume initialised
+///   const AliMUONRawStreamTriggerHP::AliLocalStruct* localStruct;
+///   while ((localStruct = rawStream->Next()) != NULL)
+///   {
+///      // Do something with localStruct here.
+///   }
+/// \endcode
+///
+/// This decoder tries to implement as similar an interface as possible to
+/// AliMUONRawStreamTrigger where possible. However certain constructs which
+/// would slow us down too much are avoided.
+///
+/// \author Artur Szostak <artursz@iafrica.com>
+
+#include "AliMUONRawStreamTriggerHP.h"
+#include "AliRawReader.h"
+#include "AliLog.h"
+#include <cassert>
+#include <iostream>
+#include <iomanip>
+using std::cout;
+using std::endl;
+using std::hex;
+using std::dec;
+
+/// \cond CLASSIMP
+ClassImp(AliMUONRawStreamTriggerHP)
+/// \endcond
+
+const Int_t AliMUONRawStreamTriggerHP::fgkMaxDDL = 2;
+
+
+AliMUONRawStreamTriggerHP::AliMUONRawStreamTriggerHP() :
+       AliMUONVRawStreamTrigger(),
+       fDecoder(),
+       fDDL(0),
+       fBufferSize(8192),
+       fBuffer(new UChar_t[8192]),
+       fCurrentLocalStruct(NULL),
+       fHadError(kFALSE),
+       fDone(kFALSE)
+{
+       ///
+       /// Default constructor.
+       ///
+       
+       fDecoder.ExitOnError(false);
+
+       fDecoder.GetHandler().SetMaxStructs(
+                       fDecoder.MaxRegionals(),
+                       fDecoder.MaxLocals()
+               );
+
+       fDecoder.GetHandler().SetRawStream(this);
+}
+
+
+AliMUONRawStreamTriggerHP::AliMUONRawStreamTriggerHP(AliRawReader* rawReader) :
+       AliMUONVRawStreamTrigger(rawReader),
+       fDecoder(),
+       fDDL(0),
+       fBufferSize(8192),
+       fBuffer(new UChar_t[8192]),
+       fCurrentLocalStruct(NULL),
+       fHadError(kFALSE),
+       fDone(kFALSE)
+{
+       ///
+       /// Constructor with AliRawReader as argument.
+       ///
+       
+       fDecoder.ExitOnError(false);
+
+       fDecoder.GetHandler().SetMaxStructs(
+                       fDecoder.MaxRegionals(),
+                       fDecoder.MaxLocals()
+               );
+       
+       fDecoder.GetHandler().SetRawStream(this);
+}
+
+
+AliMUONRawStreamTriggerHP::~AliMUONRawStreamTriggerHP()
+{
+       ///
+       /// Default destructor which cleans up the memory allocated.
+       ///
+       
+       if (fBuffer != NULL)
+       {
+               delete [] fBuffer;
+       }
+}
+
+
+void AliMUONRawStreamTriggerHP::First()
+{
+       /// Initialise or reset the iterator.
+       /// The first DDL will be found and decoded.
+       
+       assert( GetReader() != NULL );
+       
+       fDDL = 0;
+       fDone = kFALSE;
+       NextDDL();
+}
+
+
+Bool_t AliMUONRawStreamTriggerHP::NextDDL()
+{
+       /// Read in the next trigger DDL and decode the payload with the
+       /// high performance decoder.
+       /// \return kTRUE if the next DDL was successfully read and kFALSE
+       ///    otherwise.
+
+       assert( GetReader() != NULL );
+       
+       fCurrentLocalStruct = NULL;
+       
+       while (fDDL < GetMaxDDL())
+       {
+               GetReader()->Reset();
+               GetReader()->Select("MUONTRG", fDDL, fDDL);  // Select the DDL file to be read.
+               if (GetReader()->ReadHeader()) break;
+               AliDebug(3, Form("Skipping DDL %d which does not seem to be there", fDDL+1));
+               fDDL++;
+       }
+
+       // If we reach the end of the DDL list for this event then reset the
+       // DDL counter, mark the iteration as done and exit.
+       if (fDDL >= GetMaxDDL())
+       {
+               fDDL = 0;
+               fDone = kTRUE;
+               return kFALSE;
+       }
+       else
+       {
+               fDone = kFALSE;
+       }
+
+       AliDebug(3, Form("DDL Number %d\n", fDDL));
+       
+       Int_t dataSize = GetReader()->GetDataSize(); // in bytes
+       // Check if we have enough buffer space already in fBuffer. If we do then
+       // just continue reading otherwise we need to resize the buffer.
+       if (fBufferSize < dataSize)
+       {
+               if (fBuffer != NULL)
+               {
+                       delete [] fBuffer;
+                       fBuffer = NULL;
+                       fBufferSize = 0;
+               }
+               try
+               {
+                       fBuffer = new UChar_t[dataSize];
+                       fBufferSize = dataSize;
+               }
+               catch (const std::bad_alloc&)
+               {
+                       AliError("Could not allocate more buffer space. Cannot decode DDL.");
+                       return kFALSE;
+               }
+       }
+       
+       if (not GetReader()->ReadNext(fBuffer, dataSize))
+       {
+               return kFALSE;
+       }
+       
+#ifndef R__BYTESWAP
+       Swap(reinterpret_cast<UInt_t*>(fBuffer), dataSize / sizeof(UInt_t)); // Swap needed for mac power pc.
+#endif
+       
+       bool result = false;
+       try
+       {
+               // Since we might allocate memory inside OnNewBuffer in the event
+               // handler we need to trap any memory allocation exception to be robust.
+               result = fDecoder.Decode(fBuffer, dataSize);
+               fHadError = (result == true ? kFALSE : kTRUE);
+       }
+       catch (const std::bad_alloc&)
+       {
+               AliError("Could not allocate more buffer space. Cannot decode DDL.");
+               return kFALSE;
+       }
+
+       // Update the current local structure pointer.
+       fCurrentLocalStruct = fDecoder.GetHandler().FirstLocalStruct();
+
+       fDDL++; // Remember to increment index to next DDL.
+       return kTRUE;
+}
+
+
+Bool_t AliMUONRawStreamTriggerHP::IsDone() const
+{
+       /// Indicates whether the iteration is finished or not.
+       /// \return kTRUE if we already read all the digits and kFALSE if not.
+       
+       return fDone;
+}
+
+
+Bool_t AliMUONRawStreamTriggerHP::Next(
+               UChar_t& id,   UChar_t& dec,     Bool_t& trigY,
+               UChar_t& yPos, UChar_t& sXDev,   UChar_t& xDev,
+               UChar_t& xPos, Bool_t& triggerY, Bool_t& triggerX,
+               TArrayS& xPattern, TArrayS& yPattern
+       )
+{
+       const AliLocalStruct* localStruct = Next();
+       if (localStruct == NULL) return kFALSE;
+       
+       id    = localStruct->GetId();
+       dec   = localStruct->GetDec();
+       trigY = localStruct->GetTrigY();
+       yPos  = localStruct->GetYPos();
+       sXDev = localStruct->GetSXDev();
+       xDev  = localStruct->GetXDev();
+       xPos  = localStruct->GetXPos();
+       
+       triggerX = localStruct->GetTriggerX();
+       triggerY = localStruct->GetTriggerY();
+       
+       localStruct->GetXPattern(xPattern);
+       localStruct->GetYPattern(yPattern);
+
+       return kTRUE;
+}
+
+
+void AliMUONRawStreamTriggerHP::SetMaxRegAllowed(Int_t reg)
+{
+       /// Set the maximum allowed number of regional cards in the DDL.
+       
+       fDecoder.MaxRegionals( (UInt_t) reg );
+       
+       fDecoder.GetHandler().SetMaxStructs(
+                       fDecoder.MaxRegionals(),
+                       fDecoder.MaxLocals()
+               );
+}
+
+
+void AliMUONRawStreamTriggerHP::SetMaxLoc(Int_t loc)
+{
+       /// Sets the maximum number of local cards in the DDL.
+       
+       fDecoder.MaxLocals( (UInt_t) loc );
+       
+       fDecoder.GetHandler().SetMaxStructs(
+                       fDecoder.MaxRegionals(),
+                       fDecoder.MaxLocals()
+               );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void AliMUONRawStreamTriggerHP::AliHeader::Print() const
+{
+       /// Print DARC header, global header and global scalars to screen.
+       
+       cout << "===== DARC info =====" << endl;
+       cout << "Header bits : 0x" << hex << fDarcHeader << dec << endl;
+       if (fDarcScalars != NULL)
+       {
+               cout << "L0R :   " << fDarcScalars->fL0R << " (0x"
+                       << hex << fDarcScalars->fL0R << dec << ")" << endl;
+               cout << "L1P :   " << fDarcScalars->fL1P << " (0x"
+                       << hex << fDarcScalars->fL1P << dec << ")" << endl;
+               cout << "L1S :   " << fDarcScalars->fL1S << " (0x"
+                       << hex << fDarcScalars->fL1S << dec << ")" << endl;
+               cout << "L2A :   " << fDarcScalars->fL2A << " (0x"
+                       << hex << fDarcScalars->fL2A << dec << ")" << endl;
+               cout << "L2R :   " << fDarcScalars->fL2R << " (0x"
+                       << hex << fDarcScalars->fL2R << dec << ")" << endl;
+               cout << "Clock : " << fDarcScalars->fClk << " (0x"
+                       << hex << fDarcScalars->fClk << dec << ")" << endl;
+               cout << "Hold :  " << fDarcScalars->fHold << " (0x"
+                       << hex << fDarcScalars->fHold << dec << ")" << endl;
+               cout << "Spare : " << fDarcScalars->fSpare << " (0x"
+                       << hex << fDarcScalars->fSpare << dec << ")" << endl;
+       }
+       else
+       {
+               cout << "Scalars == NULL" << endl;
+       }
+       
+       cout << "===== Global info =====" << endl;
+       for (int i = 0; i < 4; i++)
+       {
+               cout << "Input[" << i << "] : " << fGlobalHeader->fInput[i] << " (0x"
+                       << hex << fGlobalHeader->fInput[i] << dec << ")" << endl;
+       }
+       cout << "Output :    " << fGlobalHeader->fOutput << " (0x"
+               << hex << fGlobalHeader->fOutput << dec << ")" << endl;
+       if (fGlobalScalars != NULL)
+       {
+               cout << "L0 :         " << fGlobalScalars->fL0 << " (0x"
+                       << hex << fGlobalScalars->fL0 << dec << ")" << endl;
+               cout << "Clock :     " << fGlobalScalars->fClk << " (0x"
+                       << hex << fGlobalScalars->fClk << dec << ")" << endl;
+               for (int j = 0; j < 4; j++)
+               {
+                       cout << "Scaler[" << j << "] : " << fGlobalScalars->fScaler[j] << " (0x"
+                               << hex << fGlobalScalars->fScaler[j] << dec << ")" << endl;
+               }
+               cout << "Hold :      " << fGlobalScalars->fHold << " (0x"
+                       << hex << fGlobalScalars->fHold << dec << ")" << endl;
+               cout << "Spare :     " << fGlobalScalars->fSpare << " (0x"
+                       << hex << fGlobalScalars->fSpare << dec << ")" << endl;
+       }
+       else
+       {
+               cout << "Scalars == NULL" << endl;
+       }
+}
+
+void AliMUONRawStreamTriggerHP::AliRegionalHeader::Print() const
+{
+       /// Print the regional header and scalars to screen.
+       
+       cout << "===== Regional card info =====" << endl;
+       cout << "DarcWord : " << fHeader->fDarcWord << " (0x"
+               << hex << fHeader->fDarcWord << dec << ")" << endl;
+       cout << "Word :     " << fHeader->fWord << " (0x"
+               << hex << fHeader->fWord << dec << ")" << endl;
+       cout << "Input[0] : " << fHeader->fInput[0] << " (0x"
+               << hex << fHeader->fInput[0] << dec << ")" << endl;
+       cout << "Input[1] : " << fHeader->fInput[1] << " (0x"
+               << hex << fHeader->fInput[1] << dec << ")" << endl;
+       cout << "L0/Mask :  " << fHeader->fL0CountAndMask << " (0x"
+               << hex << fHeader->fL0CountAndMask << dec << ")" << endl;
+       if (fScalars != NULL)
+       {
+               cout << "Clock :     " << fScalars->fClk << " (0x"
+                       << hex << fScalars->fClk << dec << ")" << endl;
+               for (int i = 0; i < 8; i++)
+               {
+                       cout << "Scaler[" << i << "] : " << fScalars->fScaler[i] << " (0x"
+                               << hex << fScalars->fScaler[i] << dec << ")" << endl;
+               }
+               cout << "Hold :      " << fScalars->fHold << " (0x"
+                       << hex << fScalars->fHold << dec << ")" << endl;
+       }
+       else
+       {
+               cout << "Scalars == NULL" << endl;
+       }
+}
+
+void AliMUONRawStreamTriggerHP::AliLocalStruct::Print() const
+{
+       /// Print local trigger structure and scalars to screen.
+       
+       cout << "===== Local card info =====" << endl;
+       cout << "X2X1 :         " << fLocalStruct->fX2X1 << " (0x"
+               << hex << fLocalStruct->fX2X1 << dec << ")" << endl;
+       cout << "X4X3 :         " << fLocalStruct->fX4X3 << " (0x"
+               << hex << fLocalStruct->fX4X3 << dec << ")" << endl;
+       cout << "Y2Y1 :         " << fLocalStruct->fY2Y1 << " (0x"
+               << hex << fLocalStruct->fY2Y1 << dec << ")" << endl;
+       cout << "Y4Y3 :         " << fLocalStruct->fY4Y3 << " (0x"
+               << hex << fLocalStruct->fY4Y3 << dec << ")" << endl;
+       cout << "Trigger bits : " << fLocalStruct->fTriggerBits << " (0x"
+               << hex << fLocalStruct->fTriggerBits << dec << ")" << endl;
+       if (fScalars != NULL)
+       {
+               cout << "L0 :           " << fScalars->fL0 << " (0x"
+                       << hex << fScalars->fL0 << dec << ")" << endl;
+               cout << "Hold :         " << fScalars->fHold << " (0x"
+                       << hex << fScalars->fHold << dec << ")" << endl;
+               cout << "Clock :        " << fScalars->fClk << " (0x"
+                       << hex << fScalars->fClk << dec << ")" << endl;
+               cout << "LPtNTrig :     " << fScalars->fLPtNTrig << " (0x"
+                       << hex << fScalars->fLPtNTrig << dec << ")" << endl;
+               cout << "HPtNTrig :     " << fScalars->fHPtNTrig << " (0x"
+                       << hex << fScalars->fHPtNTrig << dec << ")" << endl;
+               cout << "LPtRTrig :     " << fScalars->fLPtRTrig << " (0x"
+                       << hex << fScalars->fLPtRTrig << dec << ")" << endl;
+               cout << "HPtRTrig :     " << fScalars->fHPtRTrig << " (0x"
+                       << hex << fScalars->fHPtRTrig << dec << ")" << endl;
+               cout << "LPtLTrig :     " << fScalars->fLPtLTrig << " (0x"
+                       << hex << fScalars->fLPtLTrig << dec << ")" << endl;
+               cout << "HPtLTrig :     " << fScalars->fHPtLTrig << " (0x"
+                       << hex << fScalars->fHPtLTrig << dec << ")" << endl;
+               cout << "LPtSTrig :     " << fScalars->fLPtSTrig << " (0x"
+                       << hex << fScalars->fLPtSTrig << dec << ")" << endl;
+               cout << "HPtSTrig :     " << fScalars->fHPtSTrig << " (0x"
+                       << hex << fScalars->fHPtSTrig << dec << ")" << endl;
+               for (int i = 0; i < 8*4; i++)
+               {
+                       cout << "Scaler[" << i << "] :  " << fScalars->fScaler[i] << " (0x"
+                               << hex << fScalars->fScaler[i] << dec << ")" << endl;
+               }
+               cout << "EOS :          " << fScalars->fEOS << " (0x"
+                       << hex << fScalars->fEOS << dec << ")" << endl;
+               cout << "Reset :        " << fScalars->fReset << " (0x"
+                       << hex << fScalars->fReset << dec << ")" << endl;
+       }
+       else
+       {
+               cout << "Scalars == NULL" << endl;
+       }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+AliMUONRawStreamTriggerHP::AliDecoderEventHandler::AliDecoderEventHandler() :
+       fRawStream(NULL),
+       fBufferStart(NULL),
+       fDarcHeader(0),
+       fDarcScalars(NULL),
+       fHeaders(),
+       fRegionalsCount(0),
+       fRegionals(NULL),
+       fLocals(NULL),
+       fEndOfLocals(NULL),
+       fCurrentRegional(NULL),
+       fCurrentLocal(NULL),
+       fDarcEoWErrors(0),
+       fGlobalEoWErrors(0),
+       fRegEoWErrors(0),
+       fLocalEoWErrors(0),
+       fWarnings(kTRUE)
+{
+       /// Default constructor
+}
+
+
+AliMUONRawStreamTriggerHP::AliDecoderEventHandler::~AliDecoderEventHandler()
+{
+       /// Default destructor cleans up the allocated memory.
+       
+       if (fRegionals != NULL) delete [] fRegionals;
+       if (fLocals != NULL) delete [] fLocals;
+}
+
+
+void AliMUONRawStreamTriggerHP::AliDecoderEventHandler::SetMaxStructs(
+               UInt_t maxRegionals, UInt_t maxLocals
+       )
+{
+       /// Sets the maximum number of structures allowed.
+       
+       // Start by clearing the current arrays.
+       if (fRegionals != NULL)
+       {
+               delete [] fRegionals;
+               fRegionals = NULL;
+       }
+       if (fLocals != NULL)
+       {
+               delete [] fLocals;
+               fLocals = NULL;
+               fEndOfLocals = NULL;
+       }
+       fCurrentRegional = NULL;
+       fCurrentLocal = NULL;
+       
+       // Allocate new memory.
+       fRegionals = new AliRegionalHeader[maxRegionals];
+       fLocals = new AliLocalStruct[maxRegionals*maxLocals];
+       fEndOfLocals = fLocals;
+}
+
+
+void AliMUONRawStreamTriggerHP::AliDecoderEventHandler::OnNewBuffer(
+               const void* buffer, UInt_t /*bufferSize*/
+       )
+{
+       /// This is called by the high performance decoder when a new DDL payload
+       /// is about to be decoded.
+
+       assert( fRawStream != NULL );
+       
+       // remember the start of the buffer to be used in OnError.
+       fBufferStart = buffer;
+
+       // Reset error counters.
+       fDarcEoWErrors = 0;
+       fGlobalEoWErrors = 0;
+       fRegEoWErrors = 0;
+       fLocalEoWErrors = 0;
+       
+       // Reset the current pointers which will be used to track where we need to
+       // fill fRegionals and fLocals. We have to subtract one space because we
+       // will increment the pointer the first time in the OnNewRegionalStruct
+       // and OnLocalStruct methods.
+       fCurrentRegional = fRegionals-1;
+       fCurrentLocal = fLocals-1;
+       fRegionalsCount = 0;
+}
+
+
+void AliMUONRawStreamTriggerHP::AliDecoderEventHandler::OnError(
+               ErrorCode error, const void* location
+       )
+{
+       /// This is called by the high performance decoder when a error occurs
+       /// when trying to decode the DDL payload. This indicates corruption in
+       /// the data. This method converts the error code to a descriptive message
+       /// and logs this with the raw reader.
+       /// \param error  The error code indicating the problem.
+       /// \param location  A pointer to the location within the DDL payload buffer
+       ///              being decoded where the problem with the data was found.
+
+       assert( fRawStream != NULL );
+       assert( fRawStream->GetReader() != NULL );
+       
+       Char_t* message = NULL;
+       //UInt_t word = 0;
+
+       switch (error)
+       {
+       case kWrongEventType:
+               message = Form("Wrong event type obtained from the Darc header, take the one of CDH");
+               break;
+               
+       case kBadEndOfDarc:
+               fDarcEoWErrors++;
+               message = Form(
+                       "Wrong end of Darc word %x instead of %x\n",
+                       *reinterpret_cast<const UInt_t*>(location),
+                       AliMUONTriggerDDLDecoder<AliMUONTriggerDDLDecoderEventHandler>::EndOfDarcWord()
+               );
+               fRawStream->GetReader()->AddMajorErrorLog(kDarcEoWErr, message);
+               break;
+               
+       case kBadEndOfGlobal:
+               fGlobalEoWErrors++;
+               message = Form(
+                       "Wrong end of Global word %x instead of %x\n",
+                       *reinterpret_cast<const UInt_t*>(location),
+                       AliMUONTriggerDDLDecoder<AliMUONTriggerDDLDecoderEventHandler>::EndOfGlobalWord()
+               );
+               fRawStream->GetReader()->AddMajorErrorLog(kGlobalEoWErr, message);
+               break;
+               
+       case kBadEndOfRegional:
+               fRegEoWErrors++;
+               message = Form(
+                       "Wrong end of Regional word %x instead of %x\n",
+                       *reinterpret_cast<const UInt_t*>(location),
+                       AliMUONTriggerDDLDecoder<AliMUONTriggerDDLDecoderEventHandler>::EndOfRegionalWord()
+               );
+               fRawStream->GetReader()->AddMajorErrorLog(kRegEoWErr, message);
+               break;
+               
+       case kBadEndOfLocal:
+               fLocalEoWErrors++;
+               message = Form(
+                       "Wrong end of Local word %x instead of %x\n",
+                       *reinterpret_cast<const UInt_t*>(location),
+                       AliMUONTriggerDDLDecoder<AliMUONTriggerDDLDecoderEventHandler>::EndOfLocalWord()
+               );
+               fRawStream->GetReader()->AddMajorErrorLog(kLocalEoWErr, message);
+               break;
+               
+       default:
+               message = Form(
+                       "%s (At byte %d in DDL.)",
+                       ErrorCodeToMessage(error),
+                       (unsigned long)location - (unsigned long)fBufferStart + sizeof(AliRawDataHeader)
+               );
+               fRawStream->GetReader()->AddMajorErrorLog(error, message);
+               break;
+       }
+
+       if (fWarnings)
+       {
+               AliWarningGeneral(
+                               "AliMUONRawStreamTriggerHP::AliDecoderEventHandler",
+                               message
+                       );
+       }
+}
+
diff --git a/MUON/AliMUONRawStreamTriggerHP.h b/MUON/AliMUONRawStreamTriggerHP.h
new file mode 100644 (file)
index 0000000..8f03cad
--- /dev/null
@@ -0,0 +1,788 @@
+#ifndef ALIMUONRAWSTREAMTRIGGERHP_H
+#define ALIMUONRAWSTREAMTRIGGERHP_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$ */
+
+/// \ingroup raw
+/// \class AliMUONRawStreamTriggerHP
+/// \brief Higher performance decoder stream class for reading MUON raw trigger data.
+///
+//  This provides a streamer interface to the high performance decoder which
+//  is required for AliRoot.
+//
+//  Author Artur Szostak <artursz@iafrica.com>
+
+#include "AliMUONVRawStreamTrigger.h"
+#include "AliMUONTriggerDDLDecoder.h"
+#include "TArrayS.h"
+
+
+class AliMUONRawStreamTriggerHP : public AliMUONVRawStreamTrigger
+{
+public:
+       class AliLocalStruct;
+
+       AliMUONRawStreamTriggerHP();
+       AliMUONRawStreamTriggerHP(AliRawReader* rawReader);
+       virtual ~AliMUONRawStreamTriggerHP();
+       
+       /// Initialize iterator
+       virtual void First();
+       
+       /// DDL iterator 
+       virtual Bool_t NextDDL();
+       
+       /// Whether the iteration is finished or not
+       virtual Bool_t IsDone() const;
+       
+       /// Nothing is actually done in the AddErrorMessage method because we log
+       /// the error messages as we find them in AliDecoderEventHandler::OnError().
+       virtual void AddErrorMessage() { };
+       
+       /// Advance one step in the iteration. Returns false if finished.
+       virtual Bool_t Next(UChar_t& id,   UChar_t& dec,     Bool_t& trigY,
+                           UChar_t& yPos, UChar_t& sXDev,   UChar_t& xDev,
+                           UChar_t& xPos, Bool_t& triggerY, Bool_t& triggerX,
+                           TArrayS& xPattern, TArrayS& yPattern);
+       
+       /// Returns the next local trigger structure.
+       const AliLocalStruct* Next();
+       
+       /// Return maximum number of DDLs.
+       virtual Int_t GetMaxDDL() const { return fgkMaxDDL; }
+       
+       /// Return maximum number of regional cards in the DDL.
+       virtual Int_t GetMaxReg() const { return (Int_t) fDecoder.RegionalsDecoded(); }
+       
+       /// Return maximum allowed number of regional cards in the DDL.
+       virtual Int_t GetMaxRegAllowed() const { return (Int_t) fDecoder.MaxRegionals(); }
+       
+       /// Set the maximum allowed number of regional cards in the DDL.
+       virtual void SetMaxRegAllowed(Int_t reg);
+       
+       /// Return maximum number of local cards in the DDL.
+       virtual Int_t GetMaxLoc() const { return (Int_t) fDecoder.MaxLocals(); }
+       
+       /// Sets the maximum number of local cards in the DDL.
+       virtual void SetMaxLoc(Int_t loc);
+       
+       /// Return number of the current DDL being handled.
+       virtual Int_t GetDDL() const { return fDDL - 1; }
+       
+       /// check error/Warning presence
+       virtual Bool_t IsErrorMessage() const { return fHadError; }
+       
+       /// Set warnings flag to disable warnings on data errors.
+       virtual void DisableWarnings() { fDecoder.GetHandler().Warnings(kFALSE); }
+       /// Set warnings flag to enable warnings on data errors.
+       virtual void EnableWarnings() { fDecoder.GetHandler().Warnings(kTRUE); }
+       
+       /// Get number of end of DARC word errors.
+       UInt_t GetDarcEoWErrors() const {return fDecoder.GetHandler().GetDarcEoWErrors();}
+       
+       /// Get number of end of Global word errors.
+       UInt_t GetGlobalEoWErrors() const {return fDecoder.GetHandler().GetGlobalEoWErrors();}
+       
+       /// Get number of end of regional word errors.
+       UInt_t GetRegEoWErrors() const {return fDecoder.GetHandler().GetRegEoWErrors();}
+       
+       /// Get number of end of local word errors.
+       UInt_t GetLocalEoWErrors() const {return fDecoder.GetHandler().GetLocalEoWErrors();}
+       
+       /// Returns the "try to recover from errors" flag.
+       Bool_t TryRecover() const { return Bool_t(fDecoder.TryRecover()); }
+       
+       /// Sets the "try to recover from errors" flag.
+       /// i.e. should the decoder try to recover from errors found in the
+       /// payload headers.
+       void TryRecover(Bool_t value) { fDecoder.TryRecover(bool(value)); }
+       
+       /// Light weight interface class to the DARC and global header data.
+       class AliHeader
+       {
+       public:
+               /// Default constructor.
+               AliHeader(
+                               UInt_t darcHeader = 0,
+                               const AliMUONDarcScalarsStruct* darcScalars = NULL,
+                               const AliMUONGlobalHeaderStruct* globalHeader = NULL,
+                               const AliMUONGlobalScalarsStruct* globalScalars = NULL
+                       ) :
+                       fDarcHeader(darcHeader), fDarcScalars(darcScalars),
+                       fGlobalHeader(globalHeader), fGlobalScalars(globalScalars)
+               {
+               }
+               
+               /// Implement shallow copying in the copy constructor.
+               AliHeader(const AliHeader& o) :
+                       fDarcHeader(o.fDarcHeader), fDarcScalars(o.fDarcScalars),
+                       fGlobalHeader(o.fGlobalHeader), fGlobalScalars(o.fGlobalScalars)
+               {
+               }
+               
+               /// Implement shallow copying in the assignment operator.
+               AliHeader& operator = (const AliHeader& object)
+               {
+                       memcpy(this, &object, sizeof(AliHeader));
+                       return *this;
+               }
+       
+               /// Default destructor.
+               ~AliHeader() {};
+               
+               /// Return first word
+               UInt_t   GetWord()               const {return GetDarcHeader();}
+               /// Return global input
+               Int_t    GetGlobalInput(Int_t n) const {return fGlobalHeader->fInput[n];}
+               /// Return global output
+               UChar_t  GetGlobalOutput() const {return AliMUONTriggerDDLDecoderEventHandler::GetGlobalOutput(fGlobalHeader);}
+               /// Return global config
+               UShort_t GetGlobalConfig() const {return AliMUONTriggerDDLDecoderEventHandler::GetGlobalConfig(fGlobalHeader);}
+
+               /// Return event type
+               UChar_t GetEventType()  const {return AliMUONTriggerDDLDecoderEventHandler::GetDarcEventType(GetDarcHeader());}
+               /// Returns true if this was a physics event.
+               Bool_t IsPhysicsEvent() const {return GetEventType() == 0x1;}
+               /// Return Darc type
+               UChar_t GetDarcType()   const {return AliMUONTriggerDDLDecoderEventHandler::GetDarcType(GetDarcHeader());}
+               /// Return serial number
+               UChar_t GetSerialNb()   const {return AliMUONTriggerDDLDecoderEventHandler::GetDarcSerialNb(GetDarcHeader());}
+               /// Return version
+               UChar_t GetVersion()    const {return AliMUONTriggerDDLDecoderEventHandler::GetDarcVersion(GetDarcHeader());}
+               /// Return VME trig
+               Bool_t  GetVMETrig()    const {return AliMUONTriggerDDLDecoderEventHandler::GetDarcVMETrig(GetDarcHeader());}
+               /// Return global flag
+               Bool_t  GetGlobalFlag() const {return AliMUONTriggerDDLDecoderEventHandler::GetDarcGlobalFlag(GetDarcHeader());}
+               /// Return CPT trigger
+               Bool_t  GetCTPTrig()    const {return AliMUONTriggerDDLDecoderEventHandler::GetDarcCTPTrig(GetDarcHeader());}
+               /// Return DAQ flag
+               Bool_t  GetDAQFlag()    const {return AliMUONTriggerDDLDecoderEventHandler::GetDarcDAQFlag(GetDarcHeader());}
+               /// Return reg pattern
+               UChar_t GetRegPattern() const {return AliMUONTriggerDDLDecoderEventHandler::GetDarcRegPattern(GetDarcHeader());}
+       
+               // DARC get methods
+               /// Return DARC L0 received and used
+               UInt_t  GetDarcL0R()   const {return (fDarcScalars != NULL) ? fDarcScalars->fL0R : 0;}
+               /// Return DARC L1 physics
+               UInt_t  GetDarcL1P()   const {return (fDarcScalars != NULL) ? fDarcScalars->fL1P : 0;}
+               /// Return DARC L1 software
+               UInt_t  GetDarcL1S()   const {return (fDarcScalars != NULL) ? fDarcScalars->fL1S : 0;}
+               /// Return DARC L2 accept
+               UInt_t  GetDarcL2A()   const {return (fDarcScalars != NULL) ? fDarcScalars->fL2A : 0;}
+               /// Return DARC L2 reject
+               UInt_t  GetDarcL2R()   const {return (fDarcScalars != NULL) ? fDarcScalars->fL2R : 0;}
+               /// Return DARC clock
+               UInt_t  GetDarcClock() const {return (fDarcScalars != NULL) ? fDarcScalars->fClk : 0;}
+               /// Return DARC hold (dead time)
+               UInt_t  GetDarcHold()  const {return (fDarcScalars != NULL) ? fDarcScalars->fHold : 0;}
+               
+               // global get methods
+               /// Return global L0
+               UInt_t  GetGlobalL0()    const {return (fGlobalScalars != NULL) ? fGlobalScalars->fL0 : 0;}
+               /// Return global clock
+               UInt_t  GetGlobalClock() const {return (fGlobalScalars != NULL) ? fGlobalScalars->fClk : 0;}
+               /// Return global scalars or NULL if none exist.
+               const UInt_t* GetGlobalScaler()  const {return (fGlobalScalars != NULL) ? &fGlobalScalars->fScaler[0] : NULL;}
+               /// Return global hold (dead time)
+               UInt_t  GetGlobalHold()  const {return (fGlobalScalars != NULL) ? fGlobalScalars->fHold : 0;}
+               /// Return global spare
+               UInt_t  GetGlobalSpare() const {return (fGlobalScalars != NULL) ? fGlobalScalars->fSpare : 0;}
+               
+               /// Return true if type for DARC is default.
+               Bool_t DarcIsDefaultType() const {return GetDarcType() == AliMUONTriggerDDLDecoder<AliMUONTriggerDDLDecoderEventHandler>::DarcDefaultType();}
+               /// Return true if type for DARC is Vadorh.
+               Bool_t DarcIsVadohrType()  const {return GetDarcType() == AliMUONTriggerDDLDecoder<AliMUONTriggerDDLDecoderEventHandler>::DarcVadorhType();}
+               
+               /// Return the DARC header's raw data.
+               UInt_t GetDarcHeader() const {return fDarcHeader;}
+               
+               /// Return the DARC scalars raw data or NULL if none exist.
+               const AliMUONDarcScalarsStruct* GetDarcScalars() const {return fDarcScalars;}
+               
+               /// Return the global header's raw data.
+               const AliMUONGlobalHeaderStruct* GetGlobalHeader() const {return fGlobalHeader;}
+               
+               /// Return the global scalars raw data or NULL if none exist.
+               const AliMUONGlobalScalarsStruct* GetGlobalScalars() const {return fGlobalScalars;}
+               
+               /// Print the contents of the headers to screen.
+               void Print() const;
+       
+       private:
+       
+               UInt_t fDarcHeader;  ///< Pointer to DARC header in DDL payload.
+               const AliMUONDarcScalarsStruct* fDarcScalars;  ///< Pointer to DARC scalars in DDL payload.
+               const AliMUONGlobalHeaderStruct* fGlobalHeader;  ///< Pointer to global header in DDL payload.
+               const AliMUONGlobalScalarsStruct* fGlobalScalars;  ///< Pointer to global scalars in DDL payload.
+       };
+       
+       /// Light weight interface class to the regional card header data.
+       class AliRegionalHeader
+       {
+       public:
+               /// Default constructor.
+               AliRegionalHeader(
+                               const AliLocalStruct* localsArray = NULL,
+                               const AliMUONRegionalHeaderStruct* header = NULL,
+                               const AliMUONRegionalScalarsStruct* scalars = NULL
+                       ) :
+                       fNext(NULL), fLocalsCount(0), fFirstLocal(localsArray),
+                       fHeader(header), fScalars(scalars)
+               {
+               }
+               
+               /// Implement shallow copying in the copy constructor.
+               AliRegionalHeader(const AliRegionalHeader& o) :
+                       fNext(o.fNext), fLocalsCount(o.fLocalsCount),
+                       fFirstLocal(o.fFirstLocal), fHeader(o.fHeader),
+                       fScalars(o.fScalars)
+               {
+               }
+               
+               /// Implement shallow copying in the assignment operator.
+               AliRegionalHeader& operator = (const AliRegionalHeader& object)
+               {
+                       memcpy(this, &object, sizeof(AliRegionalHeader));
+                       return *this;
+               }
+               
+               /// Default destructor.
+               ~AliRegionalHeader() {};
+               
+               /// Return darc word
+               UInt_t   GetDarcWord()     const {return fHeader->fDarcWord;}
+               /// Return first reg word
+               UInt_t   GetWord()         const {return fHeader->fWord;}
+               /// Return regional input
+               UInt_t   GetInput(Int_t n) const {assert(n < 2); return fHeader->fInput[n];}
+               /// Return L0
+               UShort_t GetL0()           const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalL0(fHeader);}
+               /// Return mask
+               UShort_t GetMask()         const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalMask(fHeader);}
+               
+               //word: phys type:1, reset: 6, serialNb:5, Id:4, version: 8, regional output:8
+               //true for phys, false for soft
+               /// Return RegPhysFlag
+               Bool_t    GetRegPhysFlag() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalPhysFlag(fHeader);}
+               /// Return ResetNb
+               UChar_t   GetResetNb()     const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalResetNb(fHeader);}
+               /// Return SerialNb
+               UChar_t   GetSerialNb()    const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalSerialNb(fHeader);}
+               /// Return Id
+               UChar_t   GetId()          const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalId(fHeader);}
+               /// Return Version
+               UChar_t   GetVersion()     const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalVersion(fHeader);}
+               /// Return Output
+               UChar_t   GetOutput()      const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalOutput(fHeader);}
+               
+               //Darc Status: error:10, #fpag:3, MBZ:3, phys type:1, present:1, not_full:1
+               // not_empty:1, L2Rej:1, L2Acc:1, L1:1, L0:1, #evt:4, busy:4
+               /// Return ErrorBits
+               UShort_t GetErrorBits()       const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalErrorBits(fHeader);}
+               /// Return FPGANumber
+               UChar_t  GetFPGANumber()      const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalFPGANumber(fHeader);}
+               /// Return DarcPhysFlag
+               Bool_t   GetDarcPhysFlag()    const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalDarcPhysFlag(fHeader);}
+               /// Return PresentFlag
+               Bool_t   GetPresentFlag()     const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalPresentFlag(fHeader);}
+               /// Return RamNotFullFlag
+               Bool_t   GetRamNotFullFlag()  const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalRamNotFullFlag(fHeader);}
+               /// Return RamNotEmptyFlag
+               Bool_t   GetRamNotEmptyFlag() const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalRamNotEmptyFlag(fHeader);}
+               /// Return L2RejStatus
+               Bool_t   GetL2RejStatus()     const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalL2RejStatus(fHeader);}
+               /// Return L2AccStatus
+               Bool_t   GetL2AccStatus()     const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalL2AccStatus(fHeader);}
+               /// Return L1Status
+               Bool_t   GetL1Status()        const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalL1Status(fHeader);}
+               /// Return L0Status
+               Bool_t   GetL0Status()        const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalL0Status(fHeader);}
+               /// Return EventInRam
+               UChar_t  GetEventInRam()      const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalEventInRam(fHeader);}
+               /// Return Busy
+               UChar_t  GetBusy()            const {return AliMUONTriggerDDLDecoderEventHandler::GetRegionalBusy(fHeader);}
+               
+               // scalar methods
+               /// Return regional clock
+               UInt_t  GetClock()        const {return (fScalars != NULL) ? fScalars->fClk : 0;}
+               /// Return regional ouput
+               const UInt_t* GetScaler() const {return (fScalars != NULL) ? &fScalars->fScaler[0] : NULL;}
+               /// Return regional hold (dead time)
+               UInt_t  GetHold()         const {return (fScalars != NULL) ? fScalars->fHold : 0;}
+               
+               /// Return raw data of regional header.
+               const AliMUONRegionalHeaderStruct* GetHeader() const { return fHeader; }
+               
+               /// Return the raw data of the regional scalars or NULL if none exist.
+               const AliMUONRegionalScalarsStruct* GetScalars() const { return fScalars; }
+               
+               /// Return the next regional structure header.
+               const AliRegionalHeader* Next() const { return fNext; }
+               
+               /// Returns the first AliLocalStruct class in this regional structure.
+               const AliLocalStruct* GetFirstLocalStruct() const { return fFirstLocal; }
+               
+               /// Returns the number of local trigger structures within this regional structure.
+               UInt_t GetLocalStructCount() const { return fLocalsCount; }
+       
+               /// Return the i'th local trigger structure in this regional structure.
+               const AliLocalStruct* GetLocalStruct(UInt_t i) const
+               {
+                       return i < fLocalsCount ? GetFirstLocalStruct() + i : NULL;
+               }
+       
+               /// Sets the next regional structure header.
+               void SetNext(const AliRegionalHeader* next) { fNext = next; }
+
+               /// Increments the local trigger structure count.
+               void IncLocalStructCount() { fLocalsCount++; };
+               
+               /// Print the contents of the regional header and scalars to screen.
+               void Print() const;
+       
+       private:
+       
+               const AliRegionalHeader* fNext;  ///< Pointer to next regional header.
+               UInt_t fLocalsCount;  ///< The number of AliLocalStruct objects found in the array pointed to by fFirstLocal.
+               const AliLocalStruct* fFirstLocal;  ///< The first local trigger structure of this regional structure.
+               const AliMUONRegionalHeaderStruct* fHeader;  ///< Pointer to the regional header in the DDL payload.
+               const AliMUONRegionalScalarsStruct* fScalars;  ///< Pointer to the regional scalars in the DDL payload.
+       };
+       
+       /// Light weight interface class to the local trigger card data.
+       class AliLocalStruct
+       {
+       public:
+               /// Default constructor.
+               AliLocalStruct(
+                               const AliRegionalHeader* regionalHeader = NULL,
+                               const AliMUONLocalInfoStruct* localStruct = NULL,
+                               const AliMUONLocalScalarsStruct* scalars = NULL
+                       ) :
+                       fRegional(regionalHeader), fNext(NULL),
+                       fLocalStruct(localStruct), fScalars(scalars)
+               {
+               }
+               
+               /// Implement shallow copying in the copy constructor.
+               AliLocalStruct(const AliLocalStruct& o) :
+                       fRegional(o.fRegional), fNext(o.fNext),
+                       fLocalStruct(o.fLocalStruct), fScalars(o.fScalars)
+               {
+               }
+               
+               /// Implement shallow copying in the assignment operator.
+               AliLocalStruct& operator = (const AliLocalStruct& object)
+               {
+                       memcpy(this, &object, sizeof(AliLocalStruct));
+                       return *this;
+               }
+       
+               /// Default destructor.
+               ~AliLocalStruct() {};
+               
+               /// Return local data
+               UInt_t GetData(Int_t n) const
+               {
+                       assert(n < 5);
+                       return (reinterpret_cast<const UInt_t*>(fLocalStruct))[n];
+               }
+       
+               /// Return X2
+               UShort_t GetX2() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalX2(fLocalStruct);}
+               /// Return X1
+               UShort_t GetX1() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalX1(fLocalStruct);}
+               /// Return X4
+               UShort_t GetX4() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalX4(fLocalStruct);}
+               /// Return X3
+               UShort_t GetX3() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalX3(fLocalStruct);}
+       
+               /// Return Y2
+               UShort_t GetY2() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalY2(fLocalStruct);}
+               /// Return Y1
+               UShort_t GetY1() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalY1(fLocalStruct);}
+               /// Return Y4
+               UShort_t GetY4() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalY4(fLocalStruct);}
+               /// Return Y3
+               UShort_t GetY3() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalY3(fLocalStruct);}
+               
+               /// return X pattern array
+               void GetXPattern(TArrayS& array) const
+               {
+                       Short_t vec[4] = {GetX1(), GetX2(), GetX3(), GetX4()};
+                       array.Set(4, vec);
+               }
+       
+               /// return Y pattern array
+               void GetYPattern(TArrayS& array) const
+               {
+                       Short_t vec[4] = {GetY1(), GetY2(), GetY3(), GetY4()};
+                       array.Set(4, vec);
+               }
+       
+               /// Return Id
+               UChar_t GetId() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalId(fLocalStruct);}
+               /// Return Dec
+               UChar_t GetDec() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalDec(fLocalStruct);}
+               /// Return TrigY
+               Bool_t GetTrigY() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalTrigY(fLocalStruct);}
+               /// Return TriggerY
+               Bool_t GetTriggerY() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalTriggerY(fLocalStruct);}
+               /// Return Upos
+               UChar_t GetYPos() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalYPos(fLocalStruct);}
+               /// Get Sign of X deviation 
+               Bool_t GetSXDev() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalSXDev(fLocalStruct);}
+               /// Get X deviation 
+               UChar_t GetXDev() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalXDev(fLocalStruct);}
+               /// Return TriggerX
+               Bool_t GetTriggerX() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalTriggerX(fLocalStruct);}
+               /// Return Xpos
+               UChar_t GetXPos() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalXPos(fLocalStruct);}
+               /// Return LPT
+               UChar_t GetLpt() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalLpt(fLocalStruct);}
+               /// Return HPT
+               UChar_t GetHpt() const {return AliMUONTriggerDDLDecoderEventHandler::GetLocalHpt(fLocalStruct);}
+               
+               // Scaler methods
+               /// Return local L0
+               UInt_t  GetL0()      const {return (fScalars != NULL) ? fScalars->fL0 : 0;}
+               /// Return local hold (dead time)
+               UInt_t  GetHold()    const {return (fScalars != NULL) ? fScalars->fHold : 0;}
+               /// Return local clock
+               UInt_t  GetClock()   const {return (fScalars != NULL) ? fScalars->fClk : 0;}
+               
+               /// Return switch
+               UShort_t GetSwitch() const
+               {
+                       return (fScalars != NULL) ?
+                               AliMUONTriggerDDLDecoderEventHandler::GetLocalSwitch(fScalars) : 0;
+               }
+               
+               /// Return ComptXY
+               UChar_t GetComptXY() const
+               {
+                       return (fScalars != NULL) ?
+                               AliMUONTriggerDDLDecoderEventHandler::GetLocalComptXY(fScalars) : 0;
+               }
+       
+               /// Return XY1
+               UShort_t GetXY1(Int_t n) const
+               {
+                       return (fScalars != NULL) ?
+                               AliMUONTriggerDDLDecoderEventHandler::GetLocalXY1(fScalars, n) : 0;
+               }
+       
+               /// Return XY2
+               UShort_t GetXY2(Int_t n) const
+               {
+                       return (fScalars != NULL) ?
+                               AliMUONTriggerDDLDecoderEventHandler::GetLocalXY2(fScalars, n) : 0;
+               }
+       
+               /// Return XY3
+               UShort_t GetXY3(Int_t n) const
+               {
+                       return (fScalars != NULL) ?
+                               AliMUONTriggerDDLDecoderEventHandler::GetLocalXY3(fScalars, n) : 0;
+               }
+       
+               /// Return XY4
+               UShort_t GetXY4(Int_t n) const
+               {
+                       return (fScalars != NULL) ?
+                               AliMUONTriggerDDLDecoderEventHandler::GetLocalXY4(fScalars, n) : 0;
+               }
+
+               /// Return raw data of the local trigger structure.
+               const AliMUONLocalInfoStruct* GetData() const {return fLocalStruct;}
+               
+               /// Return raw data of the local trigger scalars.
+               /// Could be NULL if no scalars present.
+               const AliMUONLocalScalarsStruct* GetScalars() const {return fScalars;}
+               
+               /// Return the parent regional header.
+               const AliRegionalHeader* GetRegionalHeader() const { return fRegional; }
+               
+               /// Return the next local trigger structure.
+               const AliLocalStruct* Next() const { return fNext; }
+               
+               /// Sets the next local trigger structure.
+               void SetNext(const AliLocalStruct* next) { fNext = next; }
+               
+               /// Print the contents of the local trigger structure and contents to screen.
+               void Print() const;
+       
+       private:
+       
+               const AliRegionalHeader* fRegional;  ///< The regional structure this local trigger structure belongs to.
+               const AliLocalStruct* fNext;  ///< Next local structure object in the regional structure.
+               const AliMUONLocalInfoStruct* fLocalStruct;  ///< Pointer to the local trigger structure data in the DDL payload.
+               const AliMUONLocalScalarsStruct* fScalars;  ///< Pointer to the local trigger scalars data in the DDL payload.
+       };
+       
+       /// Returns the DARC and global headers plus scalars if they exist.
+       const AliHeader* GetHeaders() const { return fDecoder.GetHandler().GetHeaders(); }
+       
+       /// Return the number of regional structures in the DDL payload.
+       UInt_t GetRegionalHeaderCount() const
+       {
+               return fDecoder.GetHandler().RegionalHeaderCount();
+       }
+       
+       /// Return the first regional structure header.
+       const AliRegionalHeader* GetFirstRegionalHeader() const
+       {
+               return fDecoder.GetHandler().RegionalHeader(0);
+       }
+       
+       /// Return the i'th regional header or NULL if not found.
+       const AliRegionalHeader* GetRegionalHeader(UInt_t i) const
+       {
+               return fDecoder.GetHandler().RegionalHeader(i);
+       }
+       
+       /// Returns the number of local trigger structures for the given
+       /// regional structure number.
+       UInt_t GetLocalStructCount(UInt_t reg) const
+       {
+               const AliRegionalHeader* r = GetRegionalHeader(reg);
+               return r != NULL ? r->GetLocalStructCount() : 0;
+       }
+       
+       /// Returns the i'th local trigger structure for the given regional
+       /// structure number or NULL if not found.
+       const AliLocalStruct* GetLocalStruct(UInt_t reg, UInt_t i) const
+       {
+               const AliRegionalHeader* r = GetRegionalHeader(reg);
+               return r != NULL ? r->GetLocalStruct(i) : NULL;
+       }
+
+       /// Returns the current local struct being decoded or NULL if none found.
+       const AliLocalStruct* CurrentLocalStruct() const
+       {
+               return (fCurrentLocalStruct != fDecoder.GetHandler().EndOfLocalStructs()) ?
+                       fCurrentLocalStruct : NULL;
+       }
+
+       /// Returns the current regional structure being decoded
+       /// or NULL if none found.
+       const AliRegionalHeader* CurrentRegionalHeader() const
+       {
+               const AliLocalStruct* local = CurrentLocalStruct();
+               return (local != NULL) ? local->GetRegionalHeader() : NULL;
+       }
+       
+private:
+       /// Not implemented
+       AliMUONRawStreamTriggerHP(const AliMUONRawStreamTriggerHP& stream);
+       /// Not implemented
+       AliMUONRawStreamTriggerHP& operator = (const AliMUONRawStreamTriggerHP& stream);
+       
+       
+       /// This is the custom event handler (callback interface) class which
+       /// unpacks raw data words and fills an internal buffer with decoded digits
+       /// as they are decoded by the high performance decoder.
+       /// Any errors are logged to the parent AliMUONVRawStreamTrigger, so one
+       /// must set this pointer appropriately before decoding and DDL payload.
+       class AliDecoderEventHandler : public AliMUONTriggerDDLDecoderEventHandler
+       {
+       public:
+       
+               /// Default constructor.
+               AliDecoderEventHandler();
+               /// Default destructor.
+               virtual ~AliDecoderEventHandler();
+               
+               /// Sets the internal arrays based on the maximum number of structures allowed.
+               void SetMaxStructs(UInt_t maxRegionals, UInt_t maxLocals);
+               
+               /// Sets the raw stream object which should be the parent of this class.
+               void SetRawStream(AliMUONVRawStreamTrigger* rawStream) { fRawStream = rawStream; }
+               
+               /// Returns the decoded DARC and global headers (and scalars if they exist).
+               const AliHeader* GetHeaders() const { return &fHeaders; }
+               
+               /// Returns the number of regional headers.
+               UInt_t RegionalHeaderCount() const { return fRegionalsCount; }
+               
+               /// Return the i'th regional structure header.
+               const AliRegionalHeader* RegionalHeader(UInt_t i) const
+               {
+                       return i < fRegionalsCount ? &fRegionals[i] : NULL;
+               }
+               
+               /// Return the first local structure decoded.
+               const AliLocalStruct* FirstLocalStruct() const { return fLocals; }
+               
+               /// Returns the marker to the end of local structures.
+               /// i.e. one position past the last local structure in fLocals.
+               const AliLocalStruct* EndOfLocalStructs() const { return fEndOfLocals; }
+               
+               /// Get number of end of DARC word errors.
+               UInt_t GetDarcEoWErrors() const {return fDarcEoWErrors;}
+               
+               /// Get number of end of Global word errors.
+               UInt_t GetGlobalEoWErrors() const {return fGlobalEoWErrors;}
+               
+               /// Get number of end of regional word errors.
+               UInt_t GetRegEoWErrors() const {return fRegEoWErrors;}
+               
+               /// Get number of end of local word errors.
+               UInt_t GetLocalEoWErrors() const {return fLocalEoWErrors;}
+
+               /// Returns the warnings flag.
+               Bool_t Warnings() const { return fWarnings; }
+               /// Sets the warnings flag.
+               void Warnings(Bool_t value) { fWarnings = value; }
+               
+               // The following methods are inherited from AliMUONTriggerDDLDecoderEventHandler:
+               
+               /// New buffer handler.
+               void OnNewBuffer(const void* buffer, UInt_t bufferSize);
+
+               /// End of buffer handler marks the end of local trigger structures.
+               void OnEndOfBuffer(const void* /*buffer*/, UInt_t /*bufferSize*/)
+               {
+                       fEndOfLocals = fCurrentLocal+1;
+               }
+               
+               /// Handler for the DARC header which just remembers the pointers for later.
+               void OnDarcHeader(UInt_t header,
+                                 const AliMUONDarcScalarsStruct* scalars,
+                                 const void* /*data*/)
+               {
+                       fDarcHeader = header;
+                       fDarcScalars = scalars;
+               }
+               
+               /// Handler for the global header which stores the pointer to the headers.
+               void OnGlobalHeader(const AliMUONGlobalHeaderStruct* header,
+                                   const AliMUONGlobalScalarsStruct* scalars,
+                                   const void* /*data*/)
+               {
+                       fHeaders = AliHeader(fDarcHeader, fDarcScalars, header, scalars);
+               }
+               
+               /// Handler for new regional card structures.
+               void OnNewRegionalStruct(const AliMUONRegionalHeaderStruct* header,
+                                        const AliMUONRegionalScalarsStruct* scalars,
+                                        const void* data);
+               
+               /// Handler for new local card structures.
+               void OnLocalStruct(const AliMUONLocalInfoStruct* localStruct,
+                                  const AliMUONLocalScalarsStruct* scalars);
+               
+               /// Error handler.
+               void OnError(ErrorCode error, const void* location);
+       
+       private:
+       
+               // Do not allow copying of this class.
+                /// Not implemented
+               AliDecoderEventHandler(const AliDecoderEventHandler& /*obj*/);
+                /// Not implemented
+               AliDecoderEventHandler& operator = (const AliDecoderEventHandler& /*obj*/);
+
+               AliMUONVRawStreamTrigger* fRawStream; //!< Pointer to the parent raw stream object.
+               const void* fBufferStart;   //!< Pointer to the start of the current DDL payload buffer.
+               UInt_t fDarcHeader; //!< Currently decoded DARC header.
+               const AliMUONDarcScalarsStruct* fDarcScalars; //!< Currently decoded DARC scalars.
+               AliHeader fHeaders;  //!< Headers of the DDL payload.
+               UInt_t fRegionalsCount; //!< Number of regional headers filled in fRegionals.
+               AliRegionalHeader* fRegionals;  //!< Array of regional headers. [0..fMaxRegionals-1]
+               AliLocalStruct* fLocals; //!< Array of decoded local structured. [0..fMaxRegionals*fMaxLocals-1]
+               AliLocalStruct* fEndOfLocals; //!< Marker indicating the position just passed the last filled element in fLocals.
+               AliRegionalHeader* fCurrentRegional; //!< Current regional header position.
+               AliLocalStruct* fCurrentLocal; //!< Current local trigger structure.
+               UInt_t fDarcEoWErrors;    //!< Number of end of DARC word errors.
+               UInt_t fGlobalEoWErrors;  //!< Number of end of global word errors.
+               UInt_t fRegEoWErrors;     //!< Number of end of regional word errors.
+               UInt_t fLocalEoWErrors;   //!< Number of end of local word errors.
+               Bool_t fWarnings;       //!< Flag indicating if we should generate a warning for errors.
+       };
+       
+       AliMUONTriggerDDLDecoder<AliDecoderEventHandler> fDecoder;  //!< The decoder for the DDL payload.
+       Int_t fDDL;         //!< The current DDL number being handled.
+       Int_t fBufferSize;  //!< This is the buffer size in bytes of fBuffer.
+       UChar_t* fBuffer;   //!< This is the buffer in which we store the DDL payload read from AliRawReader.
+       const AliLocalStruct* fCurrentLocalStruct;  //!< The current local trigger structure being handled by Next().
+       Bool_t fHadError;   //!< Flag indicating if there was a decoding error or not.
+       Bool_t fDone;       //!< Flag indicating if the iteration is done or not.
+       
+       static const Int_t  fgkMaxDDL;     //!< Maximum number of DDLs
+       
+       ClassDef(AliMUONRawStreamTriggerHP, 0)  // Higher performance decoder class for MUON trigger rawdata.
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+inline const AliMUONRawStreamTriggerHP::AliLocalStruct* AliMUONRawStreamTriggerHP::Next()
+{
+       /// Iterates through all the local trigger structures for the event.
+       /// When no more local triggers are found then NULL is returned.
+
+       do {
+               if (fCurrentLocalStruct != fDecoder.GetHandler().EndOfLocalStructs())
+                       return fCurrentLocalStruct++;
+       } while (NextDDL());
+       return NULL;
+}
+
+
+inline void AliMUONRawStreamTriggerHP::AliDecoderEventHandler::OnNewRegionalStruct(
+               const AliMUONRegionalHeaderStruct* header,
+               const AliMUONRegionalScalarsStruct* scalars,
+               const void* /*data*/
+       )
+{
+       /// New regional structure handler is called by the decoder whenever a
+       /// new regional header is found. We just mark the header and increment
+       /// the appropriate counters.
+       
+       assert( header != NULL );
+       assert( fCurrentRegional != NULL );
+       assert( fRegionalsCount < (UInt_t)fRawStream->GetMaxReg() );
+       
+       // Link the previous regional structure unless it is the first one.
+       if (fRegionalsCount > 0)
+       {
+               fCurrentRegional->SetNext(fCurrentRegional+1);
+       }
+       
+       fCurrentRegional++;
+       *fCurrentRegional = AliRegionalHeader(fCurrentLocal+1, header, scalars);
+       fRegionalsCount++;
+}
+
+
+inline void AliMUONRawStreamTriggerHP::AliDecoderEventHandler::OnLocalStruct(
+               const AliMUONLocalInfoStruct* localStruct,
+               const AliMUONLocalScalarsStruct* scalars
+       )
+{
+       /// New local trigger structure handler.
+       /// This is called by the high performance decoder when a new local trigger
+       /// structure is found within the DDL payload.
+       /// We mark the location of the structure in the DDL paytload and increment
+       /// appropriate counters.
+
+       assert( localStruct != NULL );
+       assert( fCurrentLocal != NULL );
+       assert( fCurrentRegional != NULL );
+       assert( fCurrentRegional->GetLocalStructCount() < (UInt_t)fRawStream->GetMaxLoc() );
+       
+       // Link the previous local structure unless it is the first one. 
+       if (fCurrentRegional->GetLocalStructCount() > 0)
+       {
+               fCurrentLocal->SetNext(fCurrentLocal+1);
+       }
+       
+       fCurrentLocal++;
+       *fCurrentLocal = AliLocalStruct(fCurrentRegional, localStruct, scalars);
+       fCurrentRegional->IncLocalStructCount();
+}
+
+#endif // ALIMUONRAWSTREAMTRIGGERHP_H
index f9f38caa6f541541f2b1a0a4bc4c49a94293a8c8..9dfcb8248fe0368604b639e6bdc9d2780e04ed22 100644 (file)
@@ -181,6 +181,21 @@ public:
        /// This method decodes the DDL payload contained in the buffer.
        bool Decode(const void* buffer, UInt_t bufferSize);
        
+       /// Returns the block marker key.
+       static UInt_t BlockDataKeyWord() { return fgkBlockDataKey; }
+       
+       /// Returns the DSP marker key.
+       static UInt_t DspDataKeyWord() { return fgkDSPDataKey; }
+       
+       /// Returns the bus patch marker key.
+       static UInt_t BusPatchDataKeyWord() { return fgkBusPatchDataKey; }
+       
+       /// Returns the expected padding word value.
+       static UInt_t PaddingWord() { return fgkPaddingWord; }
+       
+       /// Returns the expected end of DDL marker.
+       static UInt_t EndOfDDLWord() { return fgkEndOfDDL; }
+       
 private:
 
        bool fExitOnError; ///< Indicates if we should exit on the very first error.
diff --git a/MUON/AliMUONTriggerDDLDecoder.h b/MUON/AliMUONTriggerDDLDecoder.h
new file mode 100644 (file)
index 0000000..c0985a2
--- /dev/null
@@ -0,0 +1,813 @@
+#ifndef ALIMUONTRIGGERDDLDECODER_H
+#define ALIMUONTRIGGERDDLDECODER_H
+/**************************************************************************
+ * 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   AliMUONTriggerDDLDecoder.h
+/// \author Artur Szostak <artursz@iafrica.com>
+/// \date   28-11-2007
+/// \brief  Implementation of a high performance DDL decoder for the muon trigger.
+///
+/// This file implementes the AliMUONTriggerDDLDecoder class, which contains
+/// the core logic for decoding the payload in DDL streams comming from the muon
+/// spectrometer's hardware trigger in a very efficient manner.
+///
+/// This implementation is derived from work done by Christian Finck for the
+/// AliMUONPayloadTrigger class.
+///
+/// Note to maintainers: Please remember that this file is used by the online
+/// dHLT system. As an online system, the dHLT requires the fastest code possible
+/// in the decoders to satisfy its timing constraints. The performance impact
+/// must be checked before any proposed modification is made to this file.
+///
+
+#include "AliMUONTriggerDDLDecoderEventHandler.h"
+
+/// \ingroup raw
+/// \class AliMUONTriggerDDLDecoder
+/// \brief A high performance decoder class for MUON trigger DDL data.
+///
+/// This class implements a high performance decoder for decoding DDL payload
+/// data coming from the muon spectrometers trigger stations.
+/// It has been implemented using the event driven paradigm with templates,
+/// which allows us to minimise the number of method calls made in the inner
+/// loops of the algorithm and minimise the memory footprint.
+/// At least for optimised production compilations.
+/// The decoder class only contains the basic decoding and error checking logic.
+/// It calls methods such as OnNewBuffer, OnDarcHeader, OnNewRegionalStruct,
+/// OnLocalStruct etc in the event handler during the decoding to return the
+/// decoded data and headers.
+/// The event handler class is nothing more than a callback interface to deliver
+/// the next chunks of decoded data.
+/// To actually do something with the data, one needs to implement a custom
+/// event handler (callback) class by inheriting from AliMUONTriggerDDLDecoderEventHandler
+/// and overriding the callback methods like so:
+/// \code
+///  class MyCustomHandler : public AliMUONTriggerDDLDecoderEventHandler
+///  {
+///  public:
+///     void OnLocalStruct(const AliMUONLocalInfoStruct* localStruct,
+///                        const AliMUONLocalScalarsStruct* scalars)
+///     {
+///       // I can do something with the data in 'localStruct' here.
+///       // and the 'scalars' if they are not NULL.
+///     }
+///  };
+/// \endcode
+///
+/// Once the custom handler is written then the decoder is instantiated as
+/// shown below, to use your new custom handler. Also to start decoding one needs
+/// to call the Decode() method of the decoder.
+/// \code
+///  AliMUONTriggerDDLDecoder<MyCustomHandler> myDecoder;
+///  muDecoder.Decoder(buffer, bufferSize);
+/// \endcode
+///
+/// Note that this class was written as a template on purpose. To maximise the
+/// compilers chance to make optimisations and inline the code we must use a template.
+/// Depending on exactly what you do inside your handler, the decoder could be
+/// significantly slower if run time polymorphism was used, i.e. making the class
+/// AliMUONTriggerDDLDecoderEventHandler abstract and using virtual methods.
+///
+template <class EventHandler>
+class AliMUONTriggerDDLDecoder
+{
+public:
+
+       /// Default contructor.
+       AliMUONTriggerDDLDecoder() :
+               fExitOnError(true), fTryRecover(false),
+               fAutoDetectScalars(false), fHadError(false),
+               fNoRegionals(0), fMaxRegionals(8), fMaxLocals(16),
+               fHandler()
+       {}
+       
+       /// Constant method to return the event handler instance.
+       const EventHandler& GetHandler() const { return fHandler; }
+       
+       /// Returns the event handler instance.
+       EventHandler& GetHandler() { return fHandler; }
+       
+       /// Returns the "exit on error" flag.
+       /// i.e. should the decoder stop on the very first error found.
+       bool ExitOnError() const { return fExitOnError; }
+       
+       /// Sets the "exit on error" flag.
+       /// i.e. should the decoder stop on the very first error found.
+       void ExitOnError(bool value) { fExitOnError = value; }
+       
+       /// Returns the "try to recover from errors" flag.
+       /// i.e. should the decoder try to recover from errors found in the
+       /// payload headers.
+       bool TryRecover() const { return fTryRecover; }
+       
+       /// Sets the "try to recover from errors" flag.
+       /// i.e. should the decoder try to recover from errors found in the
+       /// payload headers.
+       void TryRecover(bool value) { fTryRecover = value; }
+       
+       /// Returns the flag indicating if we should check for the scalars of
+       /// software triggers automatically or not.
+       bool AutoDetectScalars() const { return fAutoDetectScalars; }
+       
+       /// Sets the flag indicating if we should check for the scalars of
+       /// software triggers automatically or not. If set to true then the
+       /// scalarEvent parameter of the Decode method is ignored.
+       void AutoDetectScalars(bool value) { fAutoDetectScalars = value; }
+       
+       /// Returns the maximum regional structure count expected in the DDL payload.
+       UInt_t MaxRegionals() const { return fMaxRegionals; }
+       
+       /// Sets the maximum regional structure count expected in the DDL payload.
+       void MaxRegionals(UInt_t n) { fMaxRegionals = n; }
+       
+       /// Returns the number of regional structures we actually attempted to decode.
+       UInt_t RegionalsDecoded() const { return fNoRegionals; }
+       
+       /// Returns the maximum local structure count expected in any given regional
+       /// card structure within the DDL payload.
+       UInt_t MaxLocals() const { return fMaxLocals; }
+       
+       /// Sets the maximum local structure count expected in any given regional
+       /// card structure within the DDL payload.
+       void MaxLocals(UInt_t n) { fMaxLocals = n; }
+       
+       /// This method decodes the DDL payload contained in the buffer.
+       bool Decode(const void* buffer, UInt_t bufferSize, bool scalarEvent = false);
+       
+       /// Returns the end of DARC marker key.
+       static UInt_t EndOfDarcWord() { return fgkEndOfDarc; }
+       
+       /// Returns the end of global header marker key.
+       static UInt_t EndOfGlobalWord() { return fgkEndOfGlobal; }
+       
+       /// Returns the end of regional structure marker key.
+       static UInt_t EndOfRegionalWord() { return fgkEndOfReg; }
+       
+       /// Returns the regional error word.
+       static UInt_t RegionalErrorWord() { return fgkErrorWord; }
+       
+       /// Returns the end of local structure marker key.
+       static UInt_t EndOfLocalWord() { return fgkEndOfLocal; }
+       
+       /// Returns the local card disable word.
+       static UInt_t LocalDisableWord() { return fgkDisableWord; }
+       
+       /// Returns value of default DARC type.
+       static UInt_t DarcDefaultType() { return fgkDarcDefaultType; }
+       
+       /// Returns value of Vadorh DARC type.
+       static UInt_t DarcVadorhType()  { return fgkDarcVadorhType; }
+       
+private:
+
+       bool fExitOnError; ///< Indicates if we should exit on the very first error.
+       bool fTryRecover; ///< Indicates if we should try recover from a corrupt structures.
+       bool fAutoDetectScalars; ///< Flag to indicate if we should auto-detect if there are scalars in the data.
+       bool fHadError; ///< Indicates if we had an error decoding the data.
+       UInt_t fNoRegionals; ///< The number of regional card structures actually decoded.
+       UInt_t fMaxRegionals; ///< Maximum number of regional card structures allowed in a DDL stream.
+       UInt_t fMaxLocals; ///< Maximum number of local card structures per regional structure allowed in a DDL stream.
+       EventHandler fHandler; ///< The event handler which deals with the generated parsing events.
+
+       void DecodeBuffer(const UChar_t* start, const UChar_t* end, bool scalarEvent);
+       void DecodeRegionalStructs(const UChar_t* start, const UChar_t* end, bool scalarEvent);
+       const UChar_t* DecodeLocalStructs(const UChar_t* start, const UChar_t* end, bool scalarEvent);
+       
+       const UChar_t* FindKey(
+                       UInt_t key, const UChar_t* start, const UChar_t* end
+               );
+
+       static const UInt_t fgkEndOfDarc;   ///< Indicates the end of the DARC header.
+       static const UInt_t fgkEndOfGlobal; ///< Indicates the end of the global header just after the DARC header.
+       static const UInt_t fgkEndOfReg;    ///< Indicates the end of a regional card structure.
+       static const UInt_t fgkErrorWord;   ///< The error word when a regional board is missing.
+       static const UInt_t fgkEndOfLocal;  ///< Indicates the end of a local card structure.
+       static const UInt_t fgkDisableWord; ///< Word used to fill "empty" slots.
+       static const UInt_t fgkDarcDefaultType;   ///< default type for DARC def.
+       static const UInt_t fgkDarcVadorhType;    ///< default type for DARC vadorh
+};
+
+//_____________________________________________________________________________
+
+// The following are the structure key words which are used to demarcate (identify
+// the end) of the structures within the raw trigger data.
+template <class EventHandler>
+const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkEndOfDarc    = 0xDEADFACE;
+template <class EventHandler>
+const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkEndOfGlobal  = 0xDEADBEEF;
+template <class EventHandler>
+const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkEndOfReg     = 0xBEEFFACE;
+template <class EventHandler>
+const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkErrorWord    = 0xCAFEDEAD;
+template <class EventHandler>
+const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkEndOfLocal   = 0xCAFEFADE;
+template <class EventHandler>
+const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkDisableWord  = 0x010CDEAD;
+template <class EventHandler>
+const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkDarcDefaultType = 0x6;
+template <class EventHandler>
+const UInt_t AliMUONTriggerDDLDecoder<EventHandler>::fgkDarcVadorhType  = 0x4;
+
+
+template <class EventHandler>
+bool AliMUONTriggerDDLDecoder<EventHandler>::Decode(
+               const void* buffer, UInt_t bufferSize, bool scalarEvent
+       )
+{
+       /// This method should be called to actually decode the DDL payload
+       /// contained in a memory buffer. The payload should be in the muon trigger
+       /// system DDL stream format otherwise it will be recognised as corrupt.
+       /// As the decoder progresses it will make method calls to the event handler
+       /// instance (which can be accessed with the GetHandler() method) to indicate
+       /// the start of the DARC header, global header, new regional structures and
+       /// local card structures.
+       ///
+       /// If an error occurs during the parse, because the data is corrupt, then
+       /// the OnError method is called indicating what the problem was.
+       /// Decoding will stop at this point unless the fExitOnError flag is set
+       /// to false. There is an optional flag fTryRecover which can enable logic
+       /// which will attempt to recover from corruption of the data structures
+       /// in the DDL payload, if they are found to be inconsistent (assumed corrupt).
+       /// The recovery procedure simply involves trying to find in the DDL stream
+       /// the location of the expected end of header/structure marker/key or the
+       /// next expected key, and then continue decoding from there. This kind of
+       /// recovery logic is (and should be) turned off by default and only
+       /// enabled when trying to recover corrupted data.
+       ///
+       /// \param buffer  This is the pointer to the start of the memory buffer
+       ///     containing the DDL payload. Remember that this must be the start of
+       ///     the payload and not the DDL stream. That is, this pointer should be
+       ///     equal to: DDL start pointer + 8 * sizeof(UInt_t).
+       /// \param bufferSize  This is the pointer to the first byte just past the
+       ///     end of the block structure.
+       /// \param scalarEvent  Set to true if this DDL contains a scalar event
+       ///     and false if it is a normal physics event. If the fAutoDetectScalars
+       ///     flag is true then we ignore this parameter.
+       /// \return Returns false if there was any problem with decoding the data,
+       ///     and true otherwise. Note: the data may have been partially decoded
+       ///     even if false was returned, which would be indicated by at least one
+       ///     call to the event handler's OnLocalStruct or OnNewRegionalStruct methods.
+       
+       assert( buffer != NULL );
+       
+       fHadError = false;
+       
+       // We are basically implementing something like a recursive decent parser.
+       // So start by marking the start of buffer position and end of buffer.
+       const UChar_t* start = reinterpret_cast<const UChar_t*>(buffer);
+       const UChar_t* end = start + bufferSize;
+       
+       fHandler.OnNewBuffer(buffer, bufferSize);
+       DecodeBuffer(start, end, scalarEvent);
+       fHandler.OnEndOfBuffer(buffer, bufferSize);
+       return not fHadError;
+}
+
+
+template <class EventHandler>
+void AliMUONTriggerDDLDecoder<EventHandler>::DecodeBuffer(
+               const UChar_t* start, const UChar_t* end, bool scalarEvent
+       )
+{
+       /// This method does the work to decode the buffer's payload data. It
+       /// unpacks the DARC header, the global header, then calls the
+       /// DecodeRegionalStructs() method to decode the regional structures.
+       /// For the DARC and global headers the methods OnDarcHeader and
+       /// OnGlobalHeader of the event handler object are called respectively.
+       /// \param start  This is the pointer to the start of the buffer to decode.
+       /// \param end  This is the pointer to the first byte just past the
+       ///             end of the buffer.
+       /// \param scalarEvent  Set to true if this DDL contains a scalar event
+       ///     and false if it is a normal physics event.
+       ///
+       /// fHadError is set to true if there were any errors decoding the buffer
+       /// and the OnError method of the callback event handler is called for
+       /// each error.
+       
+       const UChar_t* current = start;
+       
+       // Mark the DARC header, but check that we do not overrun the buffer.
+       const UInt_t* darcHeader = reinterpret_cast<const UInt_t*>(current);
+       current += sizeof(UInt_t);
+       if (current > end)
+       {
+               // Indicate we had an error and stop the decoding because we
+               // hit the end of the buffer already.
+               fHandler.OnError(EventHandler::kNoDarcHeader, darcHeader);
+               fHadError = true;
+               return;
+       }
+       
+       // Check if we need to figure out if this is a scalar event.
+       // If we do, then we do this by checking the event type in the DARC header
+       // and double checking this by checking if the fgkEndOfDarc key is in the
+       // expected location for a scalar event DDL payload.
+       if (fAutoDetectScalars)
+       {
+               const UInt_t* expectedEndOfDarc = reinterpret_cast<const UInt_t*>(
+                               current + sizeof(AliMUONDarcScalarsStruct)
+                       );
+               
+               // First make sure not to read past the end of buffer. Then check
+               // the value of the event type in the DARC header.
+               // Physics events are indicated by the two trigger bits of the
+               // DARC header set to 01b. Everything else is a software trigger
+               // of some sort.
+               if (reinterpret_cast<const UChar_t*>(expectedEndOfDarc+1) <= end and
+                   EventHandler::GetDarcEventType(*darcHeader) != 0x1
+                   and *expectedEndOfDarc == fgkEndOfDarc
+                  )
+               {
+                       scalarEvent = true;
+               }
+               else
+               {
+                       scalarEvent = false;
+               }
+       }
+       
+       // Detect how many regional blocks we expect. If we have no idea then
+       // just use what the maximum setting is.
+       switch (EventHandler::GetDarcType(*darcHeader))
+       {
+       case fgkDarcVadorhType:  fNoRegionals = 1; break;
+       case fgkDarcDefaultType: fNoRegionals = 8; break;
+       default: fNoRegionals = fMaxRegionals; break;
+       }
+       
+       // Check if the DARC header indicates we expect more regionals than we
+       // are allowed to decode according to our max regional structures count.
+       // If we do then this is an error and we should indicate it and exit
+       // if so requested by the user. Also we can fix the number of regionals
+       // to expect if we are trying to recover from errors.
+       if (fNoRegionals > fMaxRegionals)
+       {
+               fHandler.OnError(EventHandler::kTooManyRegionals, darcHeader);
+               fHadError = true;
+               if (fExitOnError) return;
+               if (fTryRecover)
+               {
+                       fNoRegionals = fMaxRegionals;
+               }
+       }
+       
+       // Check that the DARC header indicates correctly if we are a scalar event or not.
+       bool darcShowsScalar = (EventHandler::GetDarcEventType(*darcHeader) != 0x1);
+       if (darcShowsScalar != scalarEvent)
+       {
+               // Indicate we had an error and stop the decoding if so requested
+               // by the user.
+               fHandler.OnError(EventHandler::kWrongEventType, darcHeader);
+               fHadError = true;
+               if (fExitOnError) return;
+       }
+       
+       // Decode the DARC scalars if this is a scalar event.
+       const AliMUONDarcScalarsStruct* darcScalars = NULL;
+       if (scalarEvent)
+       {
+               darcScalars = reinterpret_cast<const AliMUONDarcScalarsStruct*>(current);
+               current += sizeof(AliMUONDarcScalarsStruct);
+               if (current > end)
+               {
+                       // Indicate we had an error and stop the decoding because we
+                       // hit the end of the buffer already.
+                       fHandler.OnError(EventHandler::kNoDarcScalars, darcScalars);
+                       fHadError = true;
+                       return;
+               }
+       }
+       
+       // Now check that the end of DARC header marker is OK.
+       const UInt_t* endOfDarc = reinterpret_cast<const UInt_t*>(current);
+       current += sizeof(UInt_t);
+       if (current > end)
+       {
+               // Indicate we had an error and stop the decoding because we
+               // hit the end of the buffer already.
+               fHandler.OnError(EventHandler::kNoEndOfDarc, endOfDarc);
+               fHadError = true;
+               return;
+       }
+       if (*endOfDarc != fgkEndOfDarc)
+       {
+               // Indicate we had an error and stop the decoding if so requested
+               // by the user.
+               fHandler.OnError(EventHandler::kBadEndOfDarc, endOfDarc);
+               fHadError = true;
+               if (fExitOnError) return;
+               
+               // If the user requested for us to try and recover from structure
+               // errors then we need to try locate the key in the data stream
+               // and continue decoding from there.
+               if (fTryRecover)
+               {
+                       const UChar_t* keypos = FindKey(fgkEndOfDarc,
+                                       reinterpret_cast<const UChar_t*>(darcHeader),
+                                       end
+                               );
+                       if (keypos != NULL)
+                       {
+                               // remember to continue decoding just past the key.
+                               current = keypos + sizeof(UInt_t);
+                       }
+               }
+       }
+       
+       fHandler.OnDarcHeader(*darcHeader, darcScalars, current);
+       
+       // Next, we mark the Global header and check that we do not overrun the buffer.
+       const AliMUONGlobalHeaderStruct* globalHeader =
+               reinterpret_cast<const AliMUONGlobalHeaderStruct*>(current);
+       current += sizeof(AliMUONGlobalHeaderStruct);
+       if (current > end)
+       {
+               // Indicate we had an error and stop the decoding because we
+               // hit the end of the buffer already.
+               fHandler.OnError(EventHandler::kNoGlobalHeader, globalHeader);
+               fHadError = true;
+               return;
+       }
+       
+       // Decode the global scalars if this is a scalar event.
+       const AliMUONGlobalScalarsStruct* globalScalars = NULL;
+       if (scalarEvent)
+       {
+               globalScalars = reinterpret_cast<const AliMUONGlobalScalarsStruct*>(current);
+               current += sizeof(AliMUONGlobalScalarsStruct);
+               if (current > end)
+               {
+                       // Indicate we had an error and stop the decoding because we
+                       // hit the end of the buffer already.
+                       fHandler.OnError(EventHandler::kNoGlobalScalars, globalScalars);
+                       fHadError = true;
+                       return;
+               }
+       }
+       
+       // Now check that the end of global header marker is OK.
+       const UInt_t* endOfGlobal = reinterpret_cast<const UInt_t*>(current);
+       current += sizeof(UInt_t);
+       if (current > end)
+       {
+               // Indicate we had an error and stop the decoding because we
+               // hit the end of the buffer already.
+               fHandler.OnError(EventHandler::kNoEndOfGlobal, endOfGlobal);
+               fHadError = true;
+               return;
+       }
+       if (*endOfGlobal != fgkEndOfGlobal)
+       {
+               // Indicate we had an error and stop the decoding if so requested
+               // by the user.
+               fHandler.OnError(EventHandler::kBadEndOfGlobal, endOfGlobal);
+               fHadError = true;
+               if (fExitOnError) return;
+               
+               // If the user requested for us to try and recover from structure
+               // errors then we need to try locate the key in the data stream
+               // and continue decoding from there.
+               if (fTryRecover)
+               {
+                       const UChar_t* keypos = FindKey(fgkEndOfGlobal,
+                                       reinterpret_cast<const UChar_t*>(globalHeader),
+                                       end
+                               );
+                       if (keypos != NULL)
+                       {
+                               // remember to continue decoding just past the key.
+                               current = keypos + sizeof(UInt_t);
+                       }
+               }
+       }
+       
+       fHandler.OnGlobalHeader(globalHeader, globalScalars, current);
+       
+       DecodeRegionalStructs(current, end, scalarEvent);
+}
+
+
+template <class EventHandler>
+void AliMUONTriggerDDLDecoder<EventHandler>::DecodeRegionalStructs(
+               const UChar_t* start, const UChar_t* end, bool scalarEvent
+       )
+{
+       /// This method decodes the regional structures in the DDL data.
+       /// For each regional header found, the OnNewRegionalStruct method of
+       /// the event handler is called, to signal the start of each
+       /// new regional structure. The DecodeLocalStructs() method is then
+       /// called to decode the local trigger structures. Finally, a symmetrical
+       /// call to OnEndOfRegionalStruct of the event handler is called to
+       /// signal that the regional structure has been decoded.
+       /// \param start  This is the pointer to the start of the buffer.
+       /// \param end  This is the pointer to the first byte just past the
+       ///             end of the buffer.
+       /// \param scalarEvent  Set to true if this DDL contains a scalar event
+       ///     and false if it is a normal physics event.
+       ///
+       /// fHadError is set to true if there were any errors decoding the buffer
+       /// and the OnError method of the callback event handler is called for
+       /// each error.
+       
+       const UChar_t* current = start;
+       
+       for (UInt_t iReg = 0; iReg < fNoRegionals; iReg++)
+       {
+               const AliMUONRegionalHeaderStruct* regionalHeader =
+                       reinterpret_cast<const AliMUONRegionalHeaderStruct*>(current);
+               current += sizeof(AliMUONRegionalHeaderStruct);
+               
+               if (current > end)
+               {
+                       // So we only got part of a regional header, nothing to do but
+                       // report the error and exit.
+                       fHandler.OnError(EventHandler::kNoRegionalHeader, regionalHeader);
+                       fHadError = true;
+                       return;
+               }
+               
+               // Skip empty regional board (not connected or with error reading).
+               if (regionalHeader->fDarcWord == fgkErrorWord)
+               {
+                       //current += sizeof(AliMUONRegionalHeaderStruct);  // already done above
+                       if (scalarEvent)
+                               current += sizeof(AliMUONRegionalScalarsStruct);
+                       current += sizeof(UInt_t); // skip the end of regional structure key.
+                       
+                       // now also skip the local structure part:
+                       current += fMaxLocals * sizeof(AliMUONLocalInfoStruct);
+                       if (scalarEvent)
+                               current += fMaxLocals * sizeof(AliMUONLocalScalarsStruct);
+                       current += fMaxLocals * sizeof(UInt_t); // skip all the end of local structure keys.
+                       
+                       continue;
+               }
+               
+               // Decode the regional scalar words if this is a scalar event.
+               const AliMUONRegionalScalarsStruct* regionalScalars = NULL;
+               if (scalarEvent)
+               {
+                       regionalScalars = reinterpret_cast<const AliMUONRegionalScalarsStruct*>(current);
+                       current += sizeof(AliMUONRegionalScalarsStruct);
+                       if (current > end)
+                       {
+                               // Indicate we had an error and stop the decoding because we
+                               // hit the end of the buffer already.
+                               fHandler.OnError(EventHandler::kNoRegionalScalars, regionalScalars);
+                               fHadError = true;
+                               return;
+                       }
+               }
+               
+               // Now check that the end of regional header marker is OK.
+               const UInt_t* endOfRegional = reinterpret_cast<const UInt_t*>(current);
+               current += sizeof(UInt_t);
+               if (current > end)
+               {
+                       // Indicate we had an error and stop the decoding because we
+                       // hit the end of the buffer already.
+                       fHandler.OnError(EventHandler::kNoEndOfRegional, endOfRegional);
+                       fHadError = true;
+                       return;
+               }
+               if (*endOfRegional != fgkEndOfReg)
+               {
+                       // Indicate we had an error and stop the decoding if so requested
+                       // by the user.
+                       fHandler.OnError(EventHandler::kBadEndOfRegional, endOfRegional);
+                       fHadError = true;
+                       if (fExitOnError) return;
+                       
+                       // If the user requested for us to try and recover from structure
+                       // errors then we need to try locate the key in the data stream
+                       // and continue decoding from there.
+                       if (fTryRecover)
+                       {
+                               const UChar_t* keypos = FindKey(fgkEndOfReg,
+                                               reinterpret_cast<const UChar_t*>(regionalHeader),
+                                               end
+                                       );
+                               
+                               // If the fgkEndOfReg key was found exactly one regional
+                               // structure later then we should not adjust the current
+                               // decoding position because it is more likely that the
+                               // end of regional structure key was just corrupt rather
+                               // than offset.
+                               // If we could not find another good key then just continue.
+                               size_t sizeOfRegional = sizeof(AliMUONRegionalHeaderStruct) + sizeof(UInt_t)
+                                       + fMaxLocals * (sizeof(AliMUONLocalInfoStruct) + sizeof(UInt_t));
+                               if (scalarEvent)
+                               {
+                                       sizeOfRegional += sizeof(AliMUONRegionalScalarsStruct)
+                                               + fMaxLocals * sizeof(AliMUONLocalScalarsStruct);
+                               }
+                               
+                               if (keypos != NULL and keypos != current + sizeOfRegional)
+                               {
+                                       current = keypos + sizeof(UInt_t);
+                               }
+                       }
+               }
+               
+               // Tell the handler that we have a new regional block and decode it.
+               // When done, tell the handler again.
+               const UChar_t* startOfLocals = current;
+               fHandler.OnNewRegionalStruct(regionalHeader, regionalScalars, startOfLocals);
+               current = DecodeLocalStructs(current, end, scalarEvent);
+               fHandler.OnEndOfRegionalStruct(regionalHeader, regionalScalars, startOfLocals);
+       }
+       
+       // Now just check that there is no extra rubbish at the end of the DDL.
+       if (current != end)
+       {
+               fHandler.OnError(EventHandler::kBufferTooBig, current);
+               fHadError = true;
+       }
+}
+
+
+template <class EventHandler>
+const UChar_t* AliMUONTriggerDDLDecoder<EventHandler>::DecodeLocalStructs(
+               const UChar_t* start, const UChar_t* end, bool scalarEvent
+       )
+{
+       /// This method decodes the local structures in the DDL data for a
+       /// single regional structure. For each local trigger structure found,
+       /// the OnLocalStruct method of the event handler is called.
+       /// \param start  This is the pointer to the start of the regional structure
+       ///               payload (The pointer just past the regional header key).
+       /// \param end  This is the pointer to the first byte just past the
+       ///             end of the buffer.
+       /// \param scalarEvent  Set to true if this DDL contains a scalar event
+       ///     and false if it is a normal physics event.
+       /// \returns  The position in the buffer where this method stopped decoding.
+       ///
+       /// fHadError is set to true if there were any errors decoding the buffer
+       /// and the OnError method of the callback event handler is called for
+       /// each error.
+       
+       const UChar_t* current = start;
+       
+       for (UInt_t iLocal = 0; iLocal < fMaxLocals; iLocal++)
+       {
+               const AliMUONLocalInfoStruct* localStruct =
+                       reinterpret_cast<const AliMUONLocalInfoStruct*>(current);
+               current += sizeof(AliMUONLocalInfoStruct);
+               
+               if (current > end)
+               {
+                       // So we only got part of a local structure, nothing to do but
+                       // report the error and exit.
+                       fHandler.OnError(EventHandler::kNoLocalStruct, localStruct);
+                       fHadError = true;
+                       return end;
+               }
+               
+               // Skip empty local board if card not notified.
+               if (localStruct->fX2X1 == fgkDisableWord and
+                   localStruct->fX4X3 == fgkDisableWord and
+                   localStruct->fY2Y1 == fgkDisableWord and
+                   localStruct->fY4Y3 == fgkDisableWord and
+                   localStruct->fTriggerBits == fgkDisableWord
+                  )
+               {
+                       //current += sizeof(AliMUONLocalInfoStruct); // already done above
+                       if (scalarEvent)
+                               current += sizeof(AliMUONLocalScalarsStruct);
+                       current += sizeof(UInt_t); // skip the end of local structure key.
+                       continue;
+               }
+               
+               // Decode the regional scalar words if this is a scalar event.
+               const AliMUONLocalScalarsStruct* localScalars = NULL;
+               if (scalarEvent)
+               {
+                       localScalars = reinterpret_cast<const AliMUONLocalScalarsStruct*>(current);
+                       current += sizeof(AliMUONLocalScalarsStruct);
+                       if (current > end)
+                       {
+                               // Indicate we had an error and stop the decoding because we
+                               // hit the end of the buffer already.
+                               fHandler.OnError(EventHandler::kNoLocalScalars, localScalars);
+                               fHadError = true;
+                               return end;
+                       }
+               }
+               
+               // Now check that the end of regional header marker is OK.
+               const UInt_t* endOfLocal = reinterpret_cast<const UInt_t*>(current);
+               current += sizeof(UInt_t);
+               if (current > end)
+               {
+                       // Indicate we had an error and stop the decoding because we
+                       // hit the end of the buffer already. We can however signal that
+                       // we got a local structure, because the buffer contains enough
+                       // data to potencially contain the real data of the structure.
+                       fHandler.OnError(EventHandler::kNoEndOfLocal, endOfLocal);
+                       if (not fExitOnError)
+                       {
+                               fHandler.OnLocalStruct(localStruct, localScalars);
+                       }
+                       fHadError = true;
+                       return end;
+               }
+               if (*endOfLocal != fgkEndOfLocal)
+               {
+                       // Indicate we had an error and stop the decoding if so requested
+                       // by the user.
+                       fHandler.OnError(EventHandler::kBadEndOfLocal, endOfLocal);
+                       fHadError = true;
+                       if (fExitOnError) return current;
+                       
+                       // If the user requested for us to try and recover from structure
+                       // errors then we need to try locate the key in the data stream
+                       // and continue decoding from there.
+                       if (fTryRecover)
+                       {
+                               const UChar_t* searchPos = reinterpret_cast<const UChar_t*>(localStruct);
+                               const UChar_t* firstLocalKey = FindKey(fgkEndOfLocal, searchPos, end);
+                               const UChar_t* firstRegionalKey = FindKey(fgkEndOfReg, searchPos, end);
+                               
+                               // If a regional key was found first, then give up on
+                               // anymore local structures from this regional block and
+                               // continue decoding from the next regional block.
+                               // Also if the fgkEndOfLocal key was found exactly one
+                               // local structure later then we should not adjust the
+                               // current decoding position because it is more likely that
+                               // the end of local structure key was just corrupt rather
+                               // than offset.
+                               if (firstLocalKey != NULL and firstRegionalKey != NULL)
+                               {
+                                       if (firstLocalKey < firstRegionalKey)
+                                       {
+                                               size_t sizeOflocalStruct = sizeof(AliMUONLocalInfoStruct) + sizeof(UInt_t);
+                                               if (scalarEvent)
+                                                       sizeOflocalStruct += sizeof(AliMUONLocalScalarsStruct);
+                                               
+                                               if (firstLocalKey != current + sizeOflocalStruct)
+                                                       current = firstLocalKey + sizeof(UInt_t);
+                                       }
+                                       else
+                                       {
+                                               // Adjust back to the start of the regional header.
+                                               current = firstRegionalKey - sizeof(AliMUONRegionalHeaderStruct);
+                                               if (scalarEvent)
+                                                       current -= sizeof(AliMUONRegionalScalarsStruct);
+                                               break;
+                                       }
+                               }
+                               
+                               // If we could not find another good key then just continue.
+                       }
+               }
+               
+               fHandler.OnLocalStruct(localStruct, localScalars);
+       }
+       
+       return current;
+}
+
+
+template <class EventHandler>
+const UChar_t* AliMUONTriggerDDLDecoder<EventHandler>::FindKey(
+               UInt_t key, const UChar_t* start, const UChar_t* end
+       )
+{
+       /// Searches for the first occurrence of the key value in the buffer
+       /// marked by 'start' and 'end'. 'start' should point to the start of
+       /// the buffer and 'end' should point to 'start + bufferSize'.
+       /// \param key  The 32 bit word to look for.
+       /// \param start  The start location to begin the search at.
+       /// \param end  The pointer to the first byte just past end of the
+       ///             buffer to check.
+       /// \returns  The location of the first occurance of key in the buffer,
+       ///           otherwise NULL is returned if nothing was found.
+       const UChar_t* current = start;
+       while (current + sizeof(UInt_t) <= end)
+       {
+               UInt_t data = * reinterpret_cast<const UInt_t*>(current);
+               if (data == key) return current;
+               current++;
+       }
+       return NULL;
+}
+
+#endif // ALIMUONTRIGGERDDLDECODER_H
diff --git a/MUON/AliMUONTriggerDDLDecoderEventHandler.h b/MUON/AliMUONTriggerDDLDecoderEventHandler.h
new file mode 100644 (file)
index 0000000..794220b
--- /dev/null
@@ -0,0 +1,797 @@
+#ifndef ALIMUONTRIGGERDDLDECODEREVENTHANDLER_H
+#define ALIMUONTRIGGERDDLDECODEREVENTHANDLER_H
+/**************************************************************************
+ * 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   AliMUONTriggerDDLDecoderEventHandler.h
+/// \author Artur Szostak <artursz@iafrica.com>
+/// \date   28-11-2007
+/// \brief  Implementation of the high performance trigger DDL decoder event handler.
+///
+/// This file implementes the AliMUONTriggerDDLDecoderEventHandler class,
+/// which is the callback interface for the AliMUONTriggerDDLDecoder decoder class.
+///
+
+#include <cassert>
+#include <ostream>
+#include <Rtypes.h>
+
+
+// We use C binding for the structures because C is more uniform with its application
+// binary interface (ABI) between compilers.
+extern "C"
+{
+
+// The following structures are the headers found in the DDL payload coming from
+// the muon hardware trigger. The specification is given in ALICE-INT-2005-012
+// (https://edms.cern.ch/file/591904/1/ALICE-INT-2005-012.pdf)
+
+/// The optional DARC board scalars.
+struct AliMUONDarcScalarsStruct
+{
+       UInt_t     fL0R;       ///< DARC L0 received and used
+       UInt_t     fL1P;       ///< DARC L1 physics
+       UInt_t     fL1S;       ///< DARC L1 software
+       UInt_t     fL2A;       ///< DARC L2 accept
+       UInt_t     fL2R;       ///< DARC L2 reject
+       UInt_t     fClk;       ///< DARC clock
+       UInt_t     fHold;      ///< DARC hold (dead time)
+       UInt_t     fSpare;     ///< DARC Empty slot (for the moment)
+};
+
+/// The global input and output words just after the DARC header.
+struct AliMUONGlobalHeaderStruct
+{
+       UInt_t     fInput[4];    ///< Global input. 8-bit words comming from the each of the 16 regional controlers.
+       UInt_t     fOutput;      ///< Global ouput
+};
+
+/// The optional global card scalars.
+struct AliMUONGlobalScalarsStruct
+{
+       UInt_t     fL0;         ///< Global number of L0 triggers
+       UInt_t     fClk;        ///< Global number of clock cycles
+       UInt_t     fScaler[6];  ///< Global card ouput scalars.
+       UInt_t     fHold;       ///< Global number of hold (dead time)
+       UInt_t     fSpare;      ///< Global spare word
+};
+
+/// Regional header
+struct AliMUONRegionalHeaderStruct
+{
+       UInt_t    fDarcWord;        ///< darc word
+       UInt_t    fWord;            ///< first reg word
+       UInt_t    fInput[2];        ///< regional input
+       UInt_t    fL0CountAndMask;  ///< L0 counter (16 bits) and local mask ("poids faible" 16 bits)
+};
+
+/// Optional regional card scalars.
+struct AliMUONRegionalScalarsStruct
+{
+       UInt_t     fClk;        ///< Regional number of clock cycles.
+       UInt_t     fScaler[8];  ///< Regional ouput scalars.
+       UInt_t     fHold;       ///< Regional hold (dead time)
+};
+
+
+/// Local card trigger information.
+struct AliMUONLocalInfoStruct
+{
+       UInt_t fX2X1;  ///< 16 bits X2 position in 16 most significant bits and 16 bits of X1 in least significant bits.
+       UInt_t fX4X3;  ///< 16 bits X4 position in 16 most significant bits and 16 bits of X3 in least significant bits.
+       UInt_t fY2Y1;  ///< 16 bits Y2 position in 16 most significant bits and 16 bits of Y1 in least significant bits.
+       UInt_t fY4Y3;  ///< 16 bits Y4 position in 16 most significant bits and 16 bits of Y3 in least significant bits.
+       UInt_t fTriggerBits;  ///< Trigger bits and deviation.
+};
+
+/// Local card trigger scalars.
+struct AliMUONLocalScalarsStruct
+{
+       UInt_t     fL0;        ///< local number of L0 triggers.
+       UInt_t     fHold;      ///< local hold (dead time)
+       UInt_t     fClk;       ///< local number of clock cycles
+       
+       UInt_t     fLPtNTrig;  ///< local low Pt no trigger
+       UInt_t     fHPtNTrig;  ///< local high Pt no trigger
+       
+       UInt_t     fLPtRTrig;  ///< local low Pt right trigger
+       UInt_t     fHPtRTrig;  ///< local high Pt right trigger
+       
+       UInt_t     fLPtLTrig;  ///< local low Pt left trigger
+       UInt_t     fHPtLTrig;  ///< local high Pt left trigger
+       
+       UInt_t     fLPtSTrig;  ///< local low Pt straight trigger
+       UInt_t     fHPtSTrig;  ///< local high Pt straight trigger
+       
+       UInt_t     fScaler[8*4];   ///< local data
+       UInt_t     fEOS;           ///< contains switches conf. & flag for reading X (0) or Y (1) in fScaler
+       UInt_t     fReset;         ///< reset signal
+};
+
+} // extern "C"
+
+
+/// \ingroup raw
+/// \class AliMUONTriggerDDLDecoderEventHandler
+/// \brief Callback event handler class for the AliMUONTriggerDDLDecoder.
+/// This class is the base class defining what methods the event handler for the
+/// high performance decoder should have. This handler actually does nothing.
+/// The user of this decoder will have to derive from this class a custom event
+/// handler that actually does something within the callback methods OnNewRegionalHeader,
+/// OnLocalStruct, OnError etc...
+///
+class AliMUONTriggerDDLDecoderEventHandler
+{
+public:
+
+       /// The only reason for a virtual destructor is to make -Weffc++ shutup.
+       /// This should not really be here since we do not actually want or need
+       /// run-time polymorphism.
+       virtual ~AliMUONTriggerDDLDecoderEventHandler() {}
+
+       /// All the possible error codes from the parsing.
+       enum ErrorCode
+       {
+               kNoError = 0,              /// Decoding was successful.
+               kTooManyRegionals = 1,     /// Too many regional card structures are expected in the DDL payload.
+               kNoDarcHeader = 2,         /// The DARC header is missing. The DDL buffer is too short to hold a DARC header.
+               kNoDarcScalars = 3,        /// The DARC scalars are missing or corrupt. The DDL buffer is too short to contain them.
+               kWrongEventType = 4,       /// Wrong event type obtained from the Darc header.
+               kNoEndOfDarc = 5,          /// The DDL buffer is too short to contain an end of DARC header key word.
+               kBadEndOfDarc = 6,         /// End of DARC header key word is incorrect or corrupt.
+               kNoGlobalHeader = 7,       /// The global header is missing. The DDL buffer is too short to hold a global header.
+               kNoGlobalScalars = 8,      /// The global scalars are missing or corrupt. The DDL buffer is too short to contain them.
+               kNoEndOfGlobal = 9,        /// The DDL buffer is too short to contain an end of global header key word.
+               kBadEndOfGlobal = 10,      /// End of global header key word is incorrect or corrupt.
+               kNoRegionalHeader = 11,    /// The regional header is missing. The DDL buffer is too short to hold another regional header.
+               kNoRegionalScalars = 12,   /// The regional scalars are missing or corrupt. The DDL buffer is too short to contain them.
+               kNoEndOfRegional = 13,     /// The DDL buffer is too short to contain an end of regional header key word.
+               kBadEndOfRegional = 14,    /// End of regional header key word is incorrect or corrupt.
+               kNoLocalStruct = 15,       /// The local structure is missing. The DDL buffer is too short to hold another local structure.
+               kNoLocalScalars = 16,      /// The local scalars are missing or corrupt. The DDL buffer is too short to contain them.
+               kNoEndOfLocal = 17,        /// The DDL buffer is too short to contain an end of local structure key word.
+               kBadEndOfLocal = 18,       /// End of local structure key word is incorrect or corrupt.
+               kBufferTooBig = 19         /// The DDL raw data is larger than indicated by the headers; extra bytes are probably just garbage.
+       };
+
+       // The following methods should be overridden for specific processing to
+       // take place in your own event handler.
+
+       /// The OnNewBuffer method will be called whenever a new buffer containing
+       /// a DDL payload is about to be processed.
+       /// The default behaviour of this method is to do nothing.
+       /// - param const void*  The pointer to the start of the memory buffer storing
+       ///                the DDL payload.
+       /// - param UInt_t The size in bytes of the memory buffer.
+       void OnNewBuffer(const void* /*buffer*/, UInt_t /*bufferSize*/) {}
+       
+       /// The OnEndOfBuffer method will be called whenever the buffer containing
+       /// a DDL payload has been processed. For each OnNewBuffer method call a
+       /// symmetric call to OnEndOfBuffer is made at the end of processing (after
+       /// the last call to OnLocalStruct)
+       /// The default behaviour of this method is to do nothing.
+       /// - param const void*  The pointer to the start of the memory buffer storing
+       ///                the DDL payload.
+       /// - param UInt_t The size in bytes of the memory buffer.
+       void OnEndOfBuffer(const void* /*buffer*/, UInt_t /*bufferSize*/) {}
+       
+       /// The OnDarcHeader method will be called when the DARC header has been
+       /// found in the DDL payload.
+       /// The default behaviour of this method is to do nothing.
+       /// - param UInt_t  The DARC header word as found in the payload.
+       /// - param const AliMUONDarcScalarsStruct*  The DARC scalars found in the
+       ///       raw data. If there are no scalars in the data then this pointer
+       ///       is set to NULL.
+       /// - param const void*  A pointer to the remainder of the raw data after
+       ///       the DARC header and scalars.
+       void OnDarcHeader(
+                       UInt_t /*header*/,
+                       const AliMUONDarcScalarsStruct* /*scalars*/,
+                       const void* /*data*/
+               )
+       {
+       }
+       
+       /// The OnGlobalHeader method will be called when the global header has
+       /// been found in the DDL payload.
+       /// The default behaviour of this method is to do nothing.
+       /// - param const AliMUONGlobalHeaderStruct*  A pointer to the global header.
+       /// - param const AliMUONDarcScalarsStruct*  The global scalars found in the
+       ///       raw data. If there are no scalars in the data then this pointer
+       ///       is set to NULL.
+       /// - param const void*  A pointer to the start of the regional data blocks.
+       void OnGlobalHeader(
+                       const AliMUONGlobalHeaderStruct* /*header*/,
+                       const AliMUONGlobalScalarsStruct* /*scalars*/,
+                       const void* /*data*/
+               )
+       {
+       }
+       
+       /// The OnNewRegionalStruct method will be called for each regional header
+       /// found in the DDL payload.
+       /// The default behaviour of this method is to do nothing.
+       /// - param const AliMUONRegionalHeaderStruct*  A pointer to the regional
+       ///       structure header.
+       /// - param const AliMUONRegionalScalarsStruct*  The regional scalars found
+       ///       in the raw data. If there are no scalars in the data then this
+       ///       pointer is set to NULL.
+       /// - param const void*  A pointer to the start of the local trigger
+       ///       structures data for this regional block.
+       void OnNewRegionalStruct(
+                       const AliMUONRegionalHeaderStruct* /*regionalStruct*/,
+                       const AliMUONRegionalScalarsStruct* /*scalars*/,
+                       const void* /*data*/
+               )
+       {
+       }
+       
+       /// The OnEndOfRegionalStruct method will be called whenever a regional
+       /// structure has been processed. For each OnNewRegionalStruct method
+       /// call a symmetric call to OnEndOfRegionalStruct is made after processing
+       /// of the regional structure is done (after the last call to OnLocalStruct
+       /// for that regional structure).
+       /// - param const AliMUONRegionalHeaderStruct*  A pointer to the regional
+       ///       structure header.
+       /// - param const AliMUONRegionalScalarsStruct*  The regional scalars found
+       ///       in the raw data. If there are no scalars in the data then this
+       ///       pointer is set to NULL.
+       /// - param const void*  A pointer to the start of the local trigger
+       ///       structures data for this regional block.
+       void OnEndOfRegionalStruct(
+                       const AliMUONRegionalHeaderStruct* /*regionalStruct*/,
+                       const AliMUONRegionalScalarsStruct* /*scalars*/,
+                       const void* /*data*/
+               )
+       {
+       }
+       
+       /// The OnLocalStruct method will be called for each local trigger
+       /// structure found in the DDL payload. The user must overload this
+       /// method to process the local structures as needed.
+       /// The default behaviour of this method is to do nothing.
+       /// - param const AliMUONRegionalHeaderStruct*  A pointer to the local
+       ///       trigger structure found.
+       /// - param const AliMUONRegionalScalarsStruct*  The local scalars found
+       ///       in the raw data. If there are no scalars in the data then this
+       ///       pointer is set to NULL.
+       void OnLocalStruct(
+                       const AliMUONLocalInfoStruct* /*localStruct*/,
+                       const AliMUONLocalScalarsStruct* /*scalars*/
+               )
+       {
+       }
+       
+       // The following static methods are helper routines for decoding the
+       // DARC header bits.
+       
+       /// Return event type
+       /// \param header  Should be the header as given by the OnDarkHeader() method.
+       static UChar_t GetDarcEventType(UInt_t header) { return (UChar_t)(header >> 30) & 0x3; };
+       
+       /// Return Darc type
+       /// \param header  Should be the header as given by the OnDarkHeader() method.
+       static UChar_t GetDarcType(UInt_t header) { return (UChar_t)(header >> 24) & 0x7; }
+       
+       /// Return serial number
+       /// \param header  Should be the header as given by the OnDarkHeader() method.
+       static UChar_t GetDarcSerialNb(UInt_t header) { return (UChar_t)(header >> 20) & 0xF; }
+       
+       /// Return version
+       /// \param header  Should be the header as given by the OnDarkHeader() method.
+       static UChar_t GetDarcVersion(UInt_t header) { return (UChar_t)(header >> 12) & 0xFF; }
+       
+       /// Return VME trig
+       /// \param header  Should be the header as given by the OnDarkHeader() method.
+       static bool GetDarcVMETrig(UInt_t header) { return (header & 0x800); }
+       
+       /// Return global flag
+       /// \param header  Should be the header as given by the OnDarkHeader() method.
+       static bool GetDarcGlobalFlag(UInt_t header) { return (header & 0x400); }
+       
+       /// Return CPT trigger
+       /// \param header  Should be the header as given by the OnDarkHeader() method.
+       static bool GetDarcCTPTrig(UInt_t header) { return (header & 0x200); }
+       
+       /// Return DAQ flag
+       /// \param header  Should be the header as given by the OnDarkHeader() method.
+       static bool GetDarcDAQFlag(UInt_t header) { return (header & 0x100); }
+       
+       /// Return reg pattern
+       /// \param header  Should be the header as given by the OnDarkHeader() method.
+       static UChar_t GetDarcRegPattern(UInt_t header) { return (UChar_t)(header & 0xFF); }
+       
+       // The following static methods are helper routines for decoding the
+       // regional structure header bits.
+       
+       /// Return L0
+       static UShort_t GetRegionalL0(const AliMUONRegionalHeaderStruct* header)
+       {
+               assert( header != NULL );
+               return (header->fL0CountAndMask >> 16) & 0xFFFF;
+       }
+       
+       /// Return mask
+       static UShort_t GetRegionalMask(const AliMUONRegionalHeaderStruct* header)
+       {
+               assert( header != NULL );
+               return header->fL0CountAndMask & 0xFFFF;
+       }
+       
+       /// Return RegPhysFlag
+       static bool GetRegionalPhysFlag(const AliMUONRegionalHeaderStruct* header)
+       {
+               assert( header != NULL );
+               return (header->fWord & 0x80000000) != 0;
+       }
+       
+       /// Return ResetNb
+       static UChar_t GetRegionalResetNb(const AliMUONRegionalHeaderStruct* header)
+       {
+               assert( header != NULL );
+               return (UChar_t)(header->fWord >> 25) &  0x20;
+       }
+       
+       /// Return SerialNb
+       static UChar_t GetRegionalSerialNb(const AliMUONRegionalHeaderStruct* header)
+       {
+               assert( header != NULL );
+               return (UChar_t)(header->fWord >> 20) &  0x1F;
+       }
+       
+       /// Return Id
+       static UChar_t GetRegionalId(const AliMUONRegionalHeaderStruct* header)
+       {
+               assert( header != NULL );
+               return (UChar_t)(header->fWord >> 16) &  0x0F;
+       }
+       
+       /// Return Version
+       static UChar_t GetRegionalVersion(const AliMUONRegionalHeaderStruct* header)
+       {
+               assert( header != NULL );
+               return (UChar_t)(header->fWord >> 8)  &  0xFF;
+       }
+       
+       /// Return Output
+       static UChar_t GetRegionalOutput(const AliMUONRegionalHeaderStruct* header)
+       {
+               assert( header != NULL );
+               return (UChar_t)(header->fWord       &  0xFF);
+       }
+       
+       /// Return ErrorBits
+       static UShort_t GetRegionalErrorBits(const AliMUONRegionalHeaderStruct* header)
+       {
+               assert( header != NULL );
+               return (UShort_t)(header->fDarcWord >> 21) &  0x3FF;
+       }
+       
+       /// Return FPGANumber
+       static UChar_t GetRegionalFPGANumber(const AliMUONRegionalHeaderStruct* header)
+       {
+               assert( header != NULL );
+               return (UChar_t)  (header->fDarcWord >> 18) &  0x7;
+       }
+       
+       /// Return DarcPhysFlag
+       static bool GetRegionalDarcPhysFlag(const AliMUONRegionalHeaderStruct* header)
+       {
+               assert( header != NULL );
+               return (header->fDarcWord  &  0x1000) != 0;
+       }
+       
+       /// Return PresentFlag
+       static bool GetRegionalPresentFlag(const AliMUONRegionalHeaderStruct* header)
+       {
+               assert( header != NULL );
+               return (header->fDarcWord  &  0x800) != 0;
+       }
+       
+       /// Return RamNotFullFlag
+       static bool GetRegionalRamNotFullFlag(const AliMUONRegionalHeaderStruct* header)
+       {
+               assert( header != NULL );
+               return (header->fDarcWord  &  0x400) != 0;
+       }
+       
+       /// Return RamNotEmptyFlag
+       static bool GetRegionalRamNotEmptyFlag(const AliMUONRegionalHeaderStruct* header)
+       {
+               assert( header != NULL );
+               return (header->fDarcWord  &  0x200) != 0;
+       }
+       
+       /// Return L2RejStatus
+       static bool GetRegionalL2RejStatus(const AliMUONRegionalHeaderStruct* header)
+       {
+               assert( header != NULL );
+               return (header->fDarcWord  &  0x100) != 0;
+       }
+       
+       /// Return L2AccStatus
+       static bool GetRegionalL2AccStatus(const AliMUONRegionalHeaderStruct* header)
+       {
+               assert( header != NULL );
+               return (header->fDarcWord  &  0x80) != 0;
+       }
+       
+       /// Return L1Status
+       static bool GetRegionalL1Status(const AliMUONRegionalHeaderStruct* header)
+       {
+               assert( header != NULL );
+               return (header->fDarcWord  &  0x40) != 0;
+       }
+       
+       /// Return L0Status
+       static bool GetRegionalL0Status(const AliMUONRegionalHeaderStruct* header)
+       {
+               assert( header != NULL );
+               return (header->fDarcWord  &  0x20) != 0;
+       }
+       
+       /// Return EventInRam
+       static UChar_t GetRegionalEventInRam(const AliMUONRegionalHeaderStruct* header)
+       {
+               assert( header != NULL );
+               return (UChar_t)  (header->fDarcWord >> 4)  &  0x4;
+       }
+       
+       /// Return Busy
+       static UChar_t GetRegionalBusy(const AliMUONRegionalHeaderStruct* header)
+       {
+               assert( header != NULL );
+               return (UChar_t)  (header->fDarcWord)       &  0x4;
+       }
+       
+       // The following static methods are helper routines for decoding the
+       // global header bits.
+       
+       /// Return global output
+       /// \param header  Should be the header as given by the OnGlobalHeader() method.
+       static UChar_t GetGlobalOutput(const AliMUONGlobalHeaderStruct* header)
+       {
+               assert(header != NULL);
+               return header->fOutput & 0xFF;
+       }
+       
+       /// Return global config
+       /// \param header  Should be the header as given by the OnGlobalHeader() method.
+       static UShort_t GetGlobalConfig(const AliMUONGlobalHeaderStruct* header)
+       {
+               assert(header != NULL);
+               return (header->fOutput >> 16) & 0xFFFF;
+       }
+       
+       // The following static methods are helper routines for decoding the
+       // local trigger structure and scalar bits.
+       
+       /// Return X2
+       static UShort_t GetLocalX2(const AliMUONLocalInfoStruct* local)
+       {
+               assert(local != NULL);
+               return (local->fX2X1 >> 16) & 0xFFFF;
+       }
+       
+       /// Return X1
+       static UShort_t GetLocalX1(const AliMUONLocalInfoStruct* local)
+       {
+               assert(local != NULL);
+               return (local->fX2X1) & 0xFFFF;
+       }
+       
+       /// Return X4
+       static UShort_t GetLocalX4(const AliMUONLocalInfoStruct* local)
+       {
+               assert(local != NULL);
+               return (local->fX4X3 >> 16) & 0xFFFF;
+       }
+       
+       /// Return X3
+       static UShort_t GetLocalX3(const AliMUONLocalInfoStruct* local)
+       {
+               assert(local != NULL);
+               return (local->fX4X3) & 0xFFFF;
+       }
+
+       /// Return Y2
+       static UShort_t GetLocalY2(const AliMUONLocalInfoStruct* local)
+       {
+               assert(local != NULL);
+               return (local->fY2Y1 >> 16) & 0xFFFF;
+       }
+       
+       /// Return Y1
+       static UShort_t GetLocalY1(const AliMUONLocalInfoStruct* local)
+       {
+               assert(local != NULL);
+               return (local->fY2Y1) & 0xFFFF;
+       }
+       
+       /// Return Y4
+       static UShort_t GetLocalY4(const AliMUONLocalInfoStruct* local)
+       {
+               assert(local != NULL);
+               return (local->fY4Y3 >> 16) & 0xFFFF;
+       }
+       
+       /// Return Y3
+       static UShort_t GetLocalY3(const AliMUONLocalInfoStruct* local)
+       {
+               assert(local != NULL);
+               return (local->fY4Y3) & 0xFFFF;
+       }
+       
+       /// Return Id
+       static UChar_t GetLocalId(const AliMUONLocalInfoStruct* local)
+       {
+               assert(local != NULL);
+               return local->fTriggerBits >> 19 &  0xF;
+       }
+       
+       /// Return Dec
+       static UChar_t GetLocalDec(const AliMUONLocalInfoStruct* local)
+       {
+               assert(local != NULL);
+               return local->fTriggerBits >> 15 &  0xF;
+       }
+       
+       /// Return TrigY
+       static bool GetLocalTrigY(const AliMUONLocalInfoStruct* local)
+       {
+               assert(local != NULL);
+               return (local->fTriggerBits >> 14 & 0x1);
+       }
+       
+       /// Return TriggerY
+       static bool GetLocalTriggerY(const AliMUONLocalInfoStruct* local)
+       {
+               return not (GetLocalTrigY(local) and GetLocalYPos(local) == 15);
+       }
+       
+       /// Return Upos
+       static UChar_t GetLocalYPos(const AliMUONLocalInfoStruct* local)
+       {
+               assert(local != NULL);
+               return local->fTriggerBits >> 10 & 0xF;
+       }
+       
+       /// Get Sign of X deviation 
+       static bool GetLocalSXDev(const AliMUONLocalInfoStruct* local)
+       {
+               assert(local != NULL);
+               return (local->fTriggerBits >> 9 & 0x1);
+       }
+       
+       /// Get X deviation 
+       static UChar_t GetLocalXDev(const AliMUONLocalInfoStruct* local)
+       {
+               assert(local != NULL);
+               return local->fTriggerBits >> 5 & 0xF;
+       }
+       
+       /// Return TriggerX
+       static bool GetLocalTriggerX(const AliMUONLocalInfoStruct* local)
+       {
+               return not (GetLocalSXDev(local) and (GetLocalXDev(local) == 0)
+                           and GetLocalXPos(local) == 0);
+       }
+       
+       /// Return Xpos
+       static UChar_t GetLocalXPos(const AliMUONLocalInfoStruct* local)
+       {
+               assert(local != NULL);
+               return local->fTriggerBits & 0x1F;
+       }
+
+       /// Return LPT
+       static UChar_t GetLocalLpt(const AliMUONLocalInfoStruct* local) {return (GetLocalDec(local) & 0x3);}
+       
+       /// Return HPT
+       static UChar_t GetLocalHpt(const AliMUONLocalInfoStruct* local) {return (GetLocalDec(local) >> 2) & 0x3;}
+       
+       /// Return switch
+       static UShort_t GetLocalSwitch(const AliMUONLocalScalarsStruct* scalars)
+       {
+               assert(scalars != NULL);
+               return (scalars->fEOS >> 1) & 0x3FF;
+       }
+       
+       /// Return ComptXY
+       static UChar_t GetLocalComptXY(const AliMUONLocalScalarsStruct* scalars)
+       {
+               assert(scalars != NULL);
+               return scalars->fEOS & 0x1;
+       }
+       
+       /// Return XY1
+       static UShort_t GetLocalXY1(const AliMUONLocalScalarsStruct* scalars, UInt_t n)
+       {
+               assert(scalars != NULL and n < 16);
+               return  (n % 2 == 0) ? (scalars->fScaler[(n/2)] & 0xFFFF)
+                                    : ((scalars->fScaler[(n/2)] >> 16) &  0xFFFF);
+       }
+       
+       /// Return XY2
+       static UShort_t GetLocalXY2(const AliMUONLocalScalarsStruct* scalars, UInt_t n)
+       {
+               assert(scalars != NULL and n < 16);
+               return  (n % 2 == 0) ? (scalars->fScaler[8 + (n/2)] & 0xFFFF)
+                                    : ((scalars->fScaler[8 + (n/2)] >> 16) &  0xFFFF);
+       }
+       
+       /// Return XY3
+       static UShort_t GetLocalXY3(const AliMUONLocalScalarsStruct* scalars, UInt_t n)
+       {
+               assert(scalars != NULL and n < 16);
+               return  (n % 2 == 0) ? (scalars->fScaler[8*2 + (n/2)] & 0xFFFF)
+                                    : ((scalars->fScaler[8*2 + (n/2)] >> 16) &  0xFFFF);
+       }
+       
+       /// Return XY4
+       static UShort_t GetLocalXY4(const AliMUONLocalScalarsStruct* scalars, UInt_t n)
+       {
+               assert(scalars != NULL and n < 16);
+               return  (n % 2 == 0) ? (scalars->fScaler[8*3 + (n/2)] & 0xFFFF)
+                                    : ((scalars->fScaler[8*3 + (n/2)] >> 16) &  0xFFFF);
+       }
+       
+       /// Whenever a parsing error of the DDL payload is encountered because of
+       /// corruption of the raw data the OnError method is called immediately at
+       /// the point this error is discovered.
+       /// The default behaviour of this method is to do nothing.
+       /// -param error  This is an error code indicating the kind of problem
+       ///               encountered with the DDL payload.
+       /// -param location  This is a pointer into the DDL payload memory buffer
+       ///         indicating the exact location where the parsing error happened
+       ///         or i.e. the location of the corruption.
+       /// Note that a relative offset in bytes from the start of the memory buffer
+       /// can be calculated by: storing the buffer pointer recevied in OnNewBuffer
+       /// earlier in fBufferStart for example, and then the offset is given by:
+       ///   offset = (unsigned long)location - (unsigned long)fBufferStart;
+       void OnError(ErrorCode /*error*/, const void* /*location*/) {}
+       
+       /// This is a utility method which converts an error code to a string
+       /// representation for printing purposes.
+       /// \param code  The error code as received in OnError for example.
+       /// \return  An ANSI string containing the name of the error code symbol.
+       static const char* ErrorCodeToString(ErrorCode code);
+       
+       /// This is a utility method which converts an error code to user friendly
+       /// descriptive message useful for printing to the screen.
+       /// \param code  The error code as received in OnError for example.
+       /// \return  An ANSI string containing a descriptive message of the error.
+       static const char* ErrorCodeToMessage(ErrorCode code);
+};
+
+//_____________________________________________________________________________
+
+inline const char* AliMUONTriggerDDLDecoderEventHandler::ErrorCodeToString(ErrorCode code)
+{
+       /// This is a utility method which converts an error code to a string
+       /// representation for printing purposes.
+       /// \param code  The error code as received in OnError for example.
+       /// \return  An ANSI string containing the name of the error code symbol.
+       
+       switch (code)
+       {
+       case kNoError: return "kNoError";
+       case kTooManyRegionals: return "kTooManyRegionals";
+       case kNoDarcHeader: return "kNoDarcHeader";
+       case kNoDarcScalars: return "kNoDarcScalars";
+       case kWrongEventType: return "kWrongEventType";
+       case kNoEndOfDarc: return "kNoEndOfDarc";
+       case kBadEndOfDarc: return "kBadEndOfDarc";
+       case kNoGlobalHeader: return "kNoGlobalHeader";
+       case kNoGlobalScalars: return "kNoGlobalScalars";
+       case kNoEndOfGlobal: return "kNoEndOfGlobal";
+       case kBadEndOfGlobal: return "kBadEndOfGlobal";
+       case kNoRegionalHeader: return "kNoRegionalHeader";
+       case kNoRegionalScalars: return "kNoRegionalScalars";
+       case kNoEndOfRegional: return "kNoEndOfRegional";
+       case kBadEndOfRegional: return "kBadEndOfRegional";
+       case kNoLocalStruct: return "kNoLocalStruct";
+       case kNoLocalScalars: return "kNoLocalScalars";
+       case kNoEndOfLocal: return "kNoEndOfLocal";
+       case kBadEndOfLocal: return "kBadEndOfLocal";
+       case kBufferTooBig: return "kBufferTooBig";
+       default: return "INVALID";
+       }
+}
+
+
+inline const char* AliMUONTriggerDDLDecoderEventHandler::ErrorCodeToMessage(ErrorCode code)
+{
+       /// This is a utility method which converts an error code to user friendly
+       /// descriptive message useful for printing to the screen.
+       /// \param code  The error code as received in OnError for example.
+       /// \return  An ANSI string containing a descriptive message of the error.
+       
+       switch (code)
+       {
+       case kNoError:
+               return "Decoding was successful.";
+       case kTooManyRegionals:
+               return "Too many regional card structures are expected in the DDL payload.";
+       case kNoDarcHeader:
+               return "The DARC header is missing. The DDL buffer is too short"
+                       " to hold a DARC header.";
+       case kNoDarcScalars:
+               return "The DARC scalars are missing or corrupt."
+                       " The DDL buffer is too short to contain them.";
+       case kWrongEventType:
+               return "Wrong event type obtained from the Darc header.";
+       case kNoEndOfDarc:
+               return "The DDL buffer is too short to contain an end of DARC"
+                       " header key word.";
+       case kBadEndOfDarc:
+               return "End of DARC header key word is incorrect or corrupt.";
+       case kNoGlobalHeader:
+               return "The global header is missing. The DDL buffer is too"
+                       " short to hold a global header.";
+       case kNoGlobalScalars:
+               return "The global scalars are missing or corrupt. The DDL"
+                       " buffer is too short to contain them.";
+       case kNoEndOfGlobal:
+               return "The DDL buffer is too short to contain an end of global"
+                       " header key word.";
+       case kBadEndOfGlobal:
+               return "End of global header key word is incorrect or corrupt.";
+       case kNoRegionalHeader:
+               return "The regional header is missing. The DDL buffer is too"
+                       " short to hold another regional header.";
+       case kNoRegionalScalars:
+               return "The regional scalars are missing or corrupt. The DDL"
+                       " buffer is too short to contain them.";
+       case kNoEndOfRegional:
+               return "The DDL buffer is too short to contain an end of regional"
+                       " header key word.";
+       case kBadEndOfRegional:
+               return "End of regional header key word is incorrect or corrupt.";
+       case kNoLocalStruct:
+               return "The local structure is missing. The DDL buffer is too"
+                       " short to hold another local structure.";
+       case kNoLocalScalars:
+               return "The local scalars are missing or corrupt. The DDL buffer"
+                       " is too short to contain them.";
+       case kNoEndOfLocal:
+               return "The DDL buffer is too short to contain an end of local"
+                       " structure key word.";
+       case kBadEndOfLocal:
+               return "End of local structure key word is incorrect or corrupt.";
+       case kBufferTooBig:
+               return "The DDL raw data is larger than indicated by the headers;"
+                       " extra bytes are probably just garbage.";
+       default:
+               return "Unknown error code!";
+       }
+}
+
+
+inline std::ostream& operator << (std::ostream& os, AliMUONTriggerDDLDecoderEventHandler::ErrorCode code)
+{
+       /// This is the stream operator for std::ostream classes to be able to
+       /// easily write the error messages associated with the error codes generated
+       /// by the decoder to 'cout' or 'cerr' for example.
+       
+       os << AliMUONTriggerDDLDecoderEventHandler::ErrorCodeToMessage(code);
+       return os;
+}
+
+#endif // ALIMUONTRIGGERDDLDECODEREVENTHANDLER_H
diff --git a/MUON/AliMUONVRawStreamTrigger.h b/MUON/AliMUONVRawStreamTrigger.h
new file mode 100644 (file)
index 0000000..31c0976
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef ALIMUONVRAWSTREAMTRIGGER_H
+#define ALIMUONVRAWSTREAMTRIGGER_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$ */
+
+/// \ingroup raw
+/// \class AliMUONVRawStreamTrigger
+/// \brief Base class for reading MUON raw trigger data.
+///
+//  MUON trigger decoders must derive from this base class.
+//
+//  Author Artur Szostak <artursz@iafrica.com>
+
+#include <TObject.h>
+#include "AliMUONRawStream.h"
+
+class TArrayS;
+class AliRawReader;
+
+class AliMUONVRawStreamTrigger : public AliMUONRawStream
+{
+public:
+       AliMUONVRawStreamTrigger();
+       AliMUONVRawStreamTrigger(AliRawReader* rawReader);
+       virtual ~AliMUONVRawStreamTrigger();
+       
+       /// Advance one step in the iteration. Returns false if finished.
+       virtual Bool_t Next(UChar_t& id,   UChar_t& dec,     Bool_t& trigY,
+                           UChar_t& yPos, UChar_t& sXDev,   UChar_t& xDev,
+                           UChar_t& xPos, Bool_t& triggerY, Bool_t& triggerX,
+                           TArrayS& xPattern, TArrayS& yPattern) = 0;
+       
+       /// Return maximum number of DDLs
+       virtual Int_t GetMaxDDL() const = 0;
+       /// Return maximum number of regional cards in DATE file
+       virtual Int_t GetMaxReg() const = 0;
+       /// Return maximum number of local cards in DATE file
+       virtual Int_t GetMaxLoc() const = 0;
+       
+       virtual void SetMaxLoc(Int_t loc) = 0;
+       
+       /// Return number of DDL
+       virtual Int_t GetDDL() const = 0;
+       
+       /// Disable Warnings
+       virtual void DisableWarnings() = 0;
+       
+       /// error numbers
+       enum rawStreamTriggerError
+       {
+               kDarcEoWErr   = 6, ///< end of Darc word error 
+               kGlobalEoWErr = 7, ///< end of Global word error
+               kRegEoWErr    = 8, ///< end of Regional word error 
+               kLocalEoWErr  = 9  ///< end of local word error
+       };
+
+private:
+       /// Not implemented
+       AliMUONVRawStreamTrigger(const AliMUONVRawStreamTrigger& stream);
+       /// Not implemented
+       AliMUONVRawStreamTrigger& operator = (const AliMUONVRawStreamTrigger& stream);
+       
+       ClassDef(AliMUONVRawStreamTrigger, 0)  // Base class for MUON trigger rawdata decoders.
+};
+
+#endif // ALIMUONVRAWSTREAMTRIGGER_H
index 74e4bcd05d1e1d70b3755b95d671c399ab1f65b4..f6b3305bc927190f55973357b916f38e36975888 100644 (file)
 ///
 /// \author Ch. Finck, Subatech, April 2006
 ///
+/// Added example routines to show how to use the interface of the high
+/// performance decoder AliMUONRawStreamTriggerrHP.
+///    --  Artur Szostak <artursz@iafrica.com>
+///
 /// Implement "digits" iterator.
 /// This macro is interface with AliRawReader for RAW.
 /// The different stucture of the patload are readout and stored in TClonesArray
 
 // RAW includes
 #include "AliRawReader.h"
+#include "AliRawReaderFile.h"
+#include "AliRawReaderRoot.h"
 
 // MUON includes
 #include "AliMUONRawStreamTrigger.h"
+#include "AliMUONRawStreamTriggerHP.h"
 #include "AliMUONDarcHeader.h"
 #include "AliMUONRegHeader.h"
 #include "AliMUONLocalStruct.h"
@@ -154,6 +161,289 @@ void MUONRawStreamTrigger(Int_t maxEvent = 1, Int_t minDDL = 0, Int_t maxDDL = 1
 }
 
 
+void MUONRawStreamTriggerHPExpert(Int_t maxEvent = 1, Int_t minDDL = 0, Int_t maxDDL = 1, TString fileName = "./")
+{
+   /// Decodes raw MUON trigger data using the fast decoder.
+   
+   TStopwatch timer;
+   timer.Start(kTRUE);
+
+   AliRawReader* rawReader = AliRawReader::Create(fileName.Data());
+
+   // Load mapping
+   if ( ! AliMpCDB::LoadDDLStore() ) {
+     printf("Could not access mapping from OCDB !\n");
+   }
+
+   // raw stream
+   AliMUONRawStreamTriggerHP* rawStream = new AliMUONRawStreamTriggerHP(rawReader);
+
+   // Light weight interfaces to the raw data.
+   const AliMUONRawStreamTriggerHP::AliHeader*          darcHeader  = 0x0;
+   const AliMUONRawStreamTriggerHP::AliRegionalHeader*  regHeader   = 0x0;
+   const AliMUONRawStreamTriggerHP::AliLocalStruct*     localStruct = 0x0;
+
+   // Loop over events.
+   Int_t iEvent = 0;
+
+   while (rawReader->NextEvent()) {
+
+     if (iEvent == maxEvent)
+       break;
+
+     printf("Event %d\n",iEvent++);
+
+     // read DDL while < 2 DDL
+     while(rawStream->NextDDL()) {
+
+      if (rawStream->GetDDL() < minDDL || rawStream->GetDDL() > maxDDL)
+        continue;
+
+       printf("\niDDL %d\n", rawStream->GetDDL());
+
+       darcHeader = rawStream->GetHeaders();
+
+       printf("Global output %x\n", (Int_t)darcHeader->GetGlobalOutput());
+
+       // loop over regional structures
+       Int_t nReg = (Int_t) rawStream->GetRegionalHeaderCount();
+       for(Int_t iReg = 0; iReg < nReg ;iReg++){   //REG loop
+
+//      printf("RegionalId %d\n", iReg);
+
+        regHeader =  rawStream->GetRegionalHeader(iReg);
+
+        // crate info
+        AliMpTriggerCrate* crate = AliMpDDLStore::Instance()->
+                                   GetTriggerCrate(rawStream->GetDDL(), iReg);
+
+        // loop over local structures
+        Int_t nLocal = rawStream->GetLocalStructCount(iReg);
+        for(Int_t iLocal = 0; iLocal < nLocal; iLocal++) {
+
+          localStruct = rawStream->GetLocalStruct(iReg, iLocal);
+
+          Int_t iLocCard = crate->GetLocalBoardId(localStruct->GetId());
+
+          if ( !iLocCard ) continue; // empty slot
+               
+          // check if trigger 
+          if (localStruct->GetTriggerX() 
+              || localStruct->GetTriggerY()) { // no empty data
+
+            printf("LocalId %d\n", localStruct->GetId());
+
+            Int_t loStripX  = (Int_t)localStruct->GetXPos();
+            Int_t loStripY  = (Int_t)localStruct->GetYPos();
+            Int_t loDev     = (Int_t)localStruct->GetXDev();
+
+            printf("iLocCard: %d, XPos: %d, YPos: %d Dev: %d\n", iLocCard, loStripX, loStripY, loDev);
+
+          }
+        } // iLocal
+       } // iReg
+     } // NextDDL
+   }// NextEvent
+
+   delete rawReader;
+   delete rawStream;
+
+   timer.Print();
+
+}
+
+
+void MUONRawStreamTriggerHPExpert2(Int_t maxEvent = 1, Int_t minDDL = 0, Int_t maxDDL = 1, TString fileName = "./")
+{
+   /// Decodes raw MUON trigger data using the fast decoder.
+   /// This method shows a slightly different method of iteration over the
+   /// data using the AliMUONRawStreamTriggerHP interface.
+   
+   TStopwatch timer;
+   timer.Start(kTRUE);
+
+   AliRawReader* rawReader = AliRawReader::Create(fileName.Data());
+
+   // Load mapping
+   if ( ! AliMpCDB::LoadDDLStore() ) {
+     printf("Could not access mapping from OCDB !\n");
+   }
+
+   // raw stream
+   AliMUONRawStreamTriggerHP* rawStream = new AliMUONRawStreamTriggerHP(rawReader);
+
+   // Light weight interfaces to the raw data.
+   const AliMUONRawStreamTriggerHP::AliHeader*          darcHeader  = 0x0;
+   const AliMUONRawStreamTriggerHP::AliRegionalHeader*  regHeader   = 0x0;
+   const AliMUONRawStreamTriggerHP::AliLocalStruct*     localStruct = 0x0;
+
+   // Loop over events.
+   Int_t iEvent = 0;
+
+   while (rawReader->NextEvent()) {
+
+     if (iEvent == maxEvent)
+       break;
+
+     printf("Event %d\n",iEvent++);
+
+     // read DDL while < 2 DDL
+     while(rawStream->NextDDL()) {
+
+      if (rawStream->GetDDL() < minDDL || rawStream->GetDDL() > maxDDL)
+        continue;
+
+       printf("\niDDL %d\n", rawStream->GetDDL());
+
+       darcHeader = rawStream->GetHeaders();
+
+       printf("Global output %x\n", (Int_t)darcHeader->GetGlobalOutput());
+
+       // loop over regional structures
+       Int_t nReg = (Int_t) rawStream->GetRegionalHeaderCount();
+       for(Int_t iReg = 0; iReg < nReg ;iReg++){   //REG loop
+
+//      printf("RegionalId %d\n", iReg);
+
+        regHeader =  rawStream->GetRegionalHeader(iReg);
+
+        // crate info
+        AliMpTriggerCrate* crate = AliMpDDLStore::Instance()->
+                                   GetTriggerCrate(rawStream->GetDDL(), iReg);
+
+        // loop over local structures
+        Int_t nLocal = regHeader->GetLocalStructCount();
+        for(Int_t iLocal = 0; iLocal < nLocal; iLocal++) {
+
+          localStruct = regHeader->GetLocalStruct(iLocal);
+
+          Int_t iLocCard = crate->GetLocalBoardId(localStruct->GetId());
+
+          if ( !iLocCard ) continue; // empty slot
+               
+          // check if trigger 
+          if (localStruct->GetTriggerX() 
+              || localStruct->GetTriggerY()) { // no empty data
+
+            printf("LocalId %d\n", localStruct->GetId());
+
+            Int_t loStripX  = (Int_t)localStruct->GetXPos();
+            Int_t loStripY  = (Int_t)localStruct->GetYPos();
+            Int_t loDev     = (Int_t)localStruct->GetXDev();
+
+            printf("iLocCard: %d, XPos: %d, YPos: %d Dev: %d\n", iLocCard, loStripX, loStripY, loDev);
+
+          }
+        } // iLocal
+       } // iReg
+     } // NextDDL
+   }// NextEvent
+
+   delete rawReader;
+   delete rawStream;
+
+   timer.Print();
+
+}
+
+
+void MUONRawStreamTriggerHPExpert3(Int_t maxEvent = 1, Int_t minDDL = 0, Int_t maxDDL = 1, TString fileName = "./")
+{
+   /// Decodes raw MUON trigger data using the fast decoder.
+   /// This method shows a jet another method of iteration over the
+   /// data using the AliMUONRawStreamTriggerHP interface.
+   
+   TStopwatch timer;
+   timer.Start(kTRUE);
+
+   AliRawReader* rawReader = AliRawReader::Create(fileName.Data());
+
+   // Load mapping
+   if ( ! AliMpCDB::LoadDDLStore() ) {
+     printf("Could not access mapping from OCDB !\n");
+   }
+
+   // raw stream
+   AliMUONRawStreamTriggerHP* rawStream = new AliMUONRawStreamTriggerHP(rawReader);
+
+   // Light weight interfaces to the raw data.
+   const AliMUONRawStreamTriggerHP::AliHeader*          darcHeader  = 0x0;
+   const AliMUONRawStreamTriggerHP::AliRegionalHeader*  regHeader   = 0x0;
+   const AliMUONRawStreamTriggerHP::AliLocalStruct*     localStruct = 0x0;
+
+   // Loop over events.
+   Int_t iEvent = 0;
+
+   while (rawReader->NextEvent()) {
+
+     if (iEvent == maxEvent)
+       break;
+
+     printf("Event %d\n",iEvent++);
+
+     // read DDL while < 2 DDL
+     while(rawStream->NextDDL()) {
+
+      if (rawStream->GetDDL() < minDDL || rawStream->GetDDL() > maxDDL)
+        continue;
+
+       printf("\niDDL %d\n", rawStream->GetDDL());
+
+       darcHeader = rawStream->GetHeaders();
+
+       printf("Global output %x\n", (Int_t)darcHeader->GetGlobalOutput());
+
+       // loop over regional structures
+       Int_t iReg = 0;
+       regHeader = rawStream->GetFirstRegionalHeader();
+       while (regHeader != NULL)
+       {
+//      printf("RegionalId %d\n", iReg);
+
+        regHeader =  rawStream->GetRegionalHeader(iReg);
+
+        // crate info
+        AliMpTriggerCrate* crate = AliMpDDLStore::Instance()->
+                                   GetTriggerCrate(rawStream->GetDDL(), iReg);
+
+        // loop over local structures
+        Int_t iLocal = 0;
+        localStruct = regHeader->GetFirstLocalStruct();
+        while (localStruct != NULL)
+        {
+          Int_t iLocCard = crate->GetLocalBoardId(localStruct->GetId());
+          if ( !iLocCard ) continue; // empty slot
+               
+          // check if trigger 
+          if (localStruct->GetTriggerX() 
+              || localStruct->GetTriggerY()) { // no empty data
+
+            printf("LocalId %d\n", localStruct->GetId());
+
+            Int_t loStripX  = (Int_t)localStruct->GetXPos();
+            Int_t loStripY  = (Int_t)localStruct->GetYPos();
+            Int_t loDev     = (Int_t)localStruct->GetXDev();
+
+            printf("iLocCard: %d, XPos: %d, YPos: %d Dev: %d\n", iLocCard, loStripX, loStripY, loDev);
+
+          }
+          iLocal++;
+          localStruct = localStruct->Next();
+        } // iLocal
+        iReg++;
+        regHeader = regHeader->Next();
+       } // iReg
+     } // NextDDL
+   }// NextEvent
+
+   delete rawReader;
+   delete rawStream;
+
+   timer.Print();
+
+}
+
+
 void MUONRawStreamTriggerSimple(Int_t maxEvent = 1, TString fileName = "./")
 {
   /// Reads the raw data in fileName, using a simplified interface (iterator
@@ -223,3 +513,102 @@ void MUONRawStreamTriggerSimple(Int_t maxEvent = 1, TString fileName = "./")
    timer.Print();
 
 }
+
+
+void MUONRawStreamTriggerHPSimple(Int_t maxEvent = 1, TString fileName = "./")
+{
+  /// Reads the raw data in fileName, using the simplified interface of the
+  /// high performance decoder.
+
+  TStopwatch timer;
+  timer.Start(kTRUE);
+
+  AliRawReader* rawReader = AliRawReader::Create(fileName.Data());
+  AliMUONRawStreamTriggerHP* rawStream   = new AliMUONRawStreamTriggerHP(rawReader);
+
+  UChar_t id;
+  UChar_t dec;
+  Bool_t trigY;
+  UChar_t yPos;
+  UChar_t sXDev;
+  UChar_t xDev;
+  UChar_t xPos;
+  Bool_t triggerX;
+  Bool_t triggerY;
+  TArrayS xPattern;
+  TArrayS yPattern;
+
+  // Loop over events
+  Int_t iEvent = 0;
+
+  while (rawReader->NextEvent())
+  {
+
+    if (iEvent == maxEvent)
+       break;
+
+     printf("Event %d\n", iEvent++);
+
+     rawStream->First();
+
+     // read while there are digits
+     while ( rawStream->Next(id, dec, trigY, yPos, sXDev, xDev, xPos,
+                            triggerX, triggerY, xPattern, yPattern) )
+     {
+       if ( triggerX || triggerY )  // no empty data
+          printf("iLocCard: %d, XPos: %d, YPos: %d Dev: %d\n", id, xPos, yPos, xDev);
+     }// Next
+  }// NextEvent
+
+  delete rawReader;
+  delete rawStream;
+
+  timer.Print();
+}
+
+
+void MUONRawStreamTriggerHPSimple2(Int_t maxEvent = 1, TString fileName = "./")
+{
+  /// Reads the raw data in fileName, using the simplified interface of the
+  /// high performance decoder.
+
+  TStopwatch timer;
+  timer.Start(kTRUE);
+
+  AliRawReader* rawReader = AliRawReader::Create(fileName.Data());
+  AliMUONRawStreamTriggerHP* rawStream   = new AliMUONRawStreamTriggerHP(rawReader);
+
+  const AliMUONRawStreamTriggerHP::AliLocalStruct* localStruct;
+
+  // Loop over events
+  Int_t iEvent = 0;
+
+  while (rawReader->NextEvent())
+  {
+
+    if (iEvent == maxEvent)
+       break;
+
+     printf("Event %d\n", iEvent++);
+
+     rawStream->First();
+
+     // read while there are digits
+     while ( (localStruct = rawStream->Next()) != NULL )
+     {
+       if ( localStruct->GetTriggerX() || localStruct->GetTriggerY() )  // no empty data
+          printf("iLocCard: %d, XPos: %d, YPos: %d Dev: %d\n",
+               localStruct->GetId(),
+               localStruct->GetXPos(),
+               localStruct->GetYPos(),
+               localStruct->GetXDev()
+          );
+     }// Next
+  }// NextEvent
+
+  delete rawReader;
+  delete rawStream;
+
+  timer.Print();
+}
+
index e3366cea7846fa70212ec6a8760544fa560829ea..3b90aea2f16b6a80dac994700569b6205358a218 100644 (file)
@@ -143,7 +143,7 @@ UInt_t LoadFiles(AliBufferInfo*& list, TString fileName = "./", Int_t maxEvent =
 
 UInt_t CountMaxDigits(AliBufferInfo* list)
 {
-       /// Deletes the memory allocated for the linked list of buffers.
+       /// Counts the maximum number of digits possible in all the buffers.
 
        UInt_t total = 0;
        AliBufferInfo* current = list;
@@ -200,9 +200,9 @@ Double_t TimeUsingOldDecoder(AliBufferInfo* list, AliDigitInfo* buffer, UInt_t m
                {
                        if (i < maxBufferSize)
                        {
-                               buffer->fManuId = manuId;
-                               buffer->fAdc = adc;
-                               buffer->fChannelId = manuChannel;
+                               buffer[i].fManuId = manuId;
+                               buffer[i].fAdc = adc;
+                               buffer[i].fChannelId = manuChannel;
                                i++;
                        }
                }
@@ -246,9 +246,9 @@ Double_t TimeUsingNewDecoder(AliBufferInfo* list, AliDigitInfo* buffer, UInt_t m
                                buspatch->GetData(j, manuId, manuChannel, adc);
                                if (i < maxBufferSize)
                                {
-                                       buffer->fManuId = manuId;
-                                       buffer->fAdc = adc;
-                                       buffer->fChannelId = manuChannel;
+                                       buffer[i].fManuId = manuId;
+                                       buffer[i].fAdc = adc;
+                                       buffer[i].fChannelId = manuChannel;
                                        i++;
                                }
                        }
@@ -291,9 +291,9 @@ Double_t TimeUsingNewDecoderOldInterface(AliBufferInfo* list, AliDigitInfo* buff
                {
                        if (i < maxBufferSize)
                        {
-                               buffer->fManuId = manuId;
-                               buffer->fAdc = adc;
-                               buffer->fChannelId = manuChannel;
+                               buffer[i].fManuId = manuId;
+                               buffer[i].fAdc = adc;
+                               buffer[i].fChannelId = manuChannel;
                                i++;
                        }
                }
@@ -304,6 +304,7 @@ Double_t TimeUsingNewDecoderOldInterface(AliBufferInfo* list, AliDigitInfo* buff
        return timer.RealTime();
 }
 
+
 void Loop(const char* filename, Bool_t newDecoder)
 {
   AliCodeTimerAutoGeneral(Form("Loop %s",(newDecoder ? "NEW":"OLD")));
@@ -339,6 +340,7 @@ void Loop(const char* filename, Bool_t newDecoder)
   delete reader;
 }
 
+
 void MUONTimeRawStreamTrackerDumb(TString fileName)
 {
   AliCodeTimer::Instance()->Reset();
@@ -361,6 +363,7 @@ void MUONTimeRawStreamTrackerDumb(TString fileName)
   AliCodeTimer::Instance()->Print();
 }
 
+
 void MUONTimeRawStreamTracker(TString fileName = "./", Int_t maxEvent = 1000)
 {
        /// Performs a timing of old and new decoders and reports this.
diff --git a/MUON/MUONTimeRawStreamTrigger.C b/MUON/MUONTimeRawStreamTrigger.C
new file mode 100644 (file)
index 0000000..3d0119b
--- /dev/null
@@ -0,0 +1,429 @@
+/**************************************************************************
+ * 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.                  *
+ **************************************************************************/
+
+/// \ingroup macros
+/// \file MUONTimeRawStreamTrigger.C
+/// \brief Macro for checking the timing (speed) performace of the two different trigger decoders.
+///
+/// \author Artur Szostak <artursz@iafrica.com>
+///
+/// This macro is used to check the timing (speed) performance of the existing
+/// offline decoder for the trigger DDLs and also for the new high performance
+/// decoder. It can be invoked as follows:
+/// 
+///  $ aliroot
+/// .L $ALICE_ROOT/MUON/MUONTimeRawStreamTrigger.C+
+///  MUONTimeRawStreamTrigger(filename, maxEvent);
+///
+/// where \em filename is the name of a file containing the raw data, or alternatively
+/// the directory containing rawX (X being an integer) paths with the raw DDL
+/// data. The \em maxEvent value is the maximum event to process (default set to
+/// 1000). Thus the macro will time the algorithm for all events in the range
+/// [0 .. maxEvent-1].
+///
+
+#if !defined(__CINT__) || defined(__MAKECINT__)
+
+#include "AliCodeTimer.h"
+
+// MUON includes
+#include "AliMUONRawStreamTrigger.h"
+#include "AliMUONRawStreamTriggerHP.h"
+#include "AliMUONDarcHeader.h"
+#include "AliMUONRegHeader.h"
+#include "AliMUONLocalStruct.h"
+#include "AliMUONDDLTrigger.h"
+
+// RAW includes
+#include "AliRawReader.h"
+#include "AliRawReaderMemory.h"
+#include "AliRawDataHeader.h"
+
+#include "TStopwatch.h"
+#include "TMath.h"
+#include "Riostream.h"
+
+#endif
+
+
+// Linked list node for buffer structures.
+struct AliBufferInfo
+{
+       AliBufferInfo* fNext;
+       Int_t fEquipId;
+       UInt_t fBufferSize;
+       UChar_t* fBuffer;
+};
+
+
+// local structure information to store
+struct AliLocalStructInfo
+{
+       UChar_t fId;
+       UChar_t fDec;
+       Bool_t fTrigY;
+       UChar_t fYPos;
+       UChar_t fSXDev;
+       UChar_t fXDev;
+       UChar_t fXPos;
+       Bool_t fTriggerY;
+       Bool_t fTriggerX;
+};
+
+
+UInt_t LoadFiles(AliBufferInfo*& list, TString fileName = "./", Int_t maxEvent = 1000)
+{
+       /// Reads in the DDL files into memory buffers as a linked list.
+
+       AliRawReader* rawReader = AliRawReader::Create(fileName.Data()); 
+
+       if (rawReader == NULL)
+       {
+               cerr << "ERROR: Could not create AliRawReader." << endl;
+               delete rawReader;
+               return 0;
+       }
+
+       UInt_t count = 0;
+       Int_t iEvent = 0;
+       list = NULL;
+       while (rawReader->NextEvent())
+       {
+               if (iEvent++ >= maxEvent) break;
+
+               rawReader->Select("MUONTRG", 0, 1);
+               while (rawReader->ReadHeader())
+               {
+                       AliBufferInfo* info = new AliBufferInfo;
+                       if (info == NULL)
+                       {
+                               cerr << "ERROR: Out of memory, sorry. You should limit the number of events read in." << endl;
+                               delete rawReader;
+                               return count;
+                       }
+                       info->fNext = list;
+                       info->fEquipId = rawReader->GetEquipmentId();
+                       info->fBufferSize = rawReader->GetDataSize() + sizeof(AliRawDataHeader);
+                       info->fBuffer = new UChar_t[info->fBufferSize];
+                       if (info->fBuffer == NULL)
+                       {
+                               cerr << "ERROR: Out of memory, sorry. You should limit the number of events read in." << endl;
+                               delete rawReader;
+                               return count;
+                       }
+                       list = info;
+                       
+                       // Copy the header.
+                       memcpy(info->fBuffer, rawReader->GetDataHeader(), sizeof(AliRawDataHeader));
+
+                       // Now copy the payload.
+                       if (! rawReader->ReadNext(
+                                               info->fBuffer + sizeof(AliRawDataHeader),
+                                               info->fBufferSize - sizeof(AliRawDataHeader)
+                                       )
+                          )
+                       {
+                               cerr << "ERROR: Failed to read from AliRawReader." << endl;
+                       }
+                       count++;
+               }
+       }
+
+       delete rawReader;
+       return count;
+}
+
+
+UInt_t CountMaxStructs(AliBufferInfo* list)
+{
+       /// Counts the maximum number of local structures possible
+
+       UInt_t total = 0;
+       AliBufferInfo* current = list;
+       while (current != NULL)
+       {
+               total += current->fBufferSize / 5;
+               current = current->fNext;
+       }
+       return total;
+}
+
+
+void ReleaseBuffers(AliBufferInfo* list)
+{
+       /// Deletes the memory allocated for the linked list of buffers.
+
+       AliBufferInfo* current = list;
+       while (current != NULL)
+       {
+               AliBufferInfo* tmp = current;
+               current = current->fNext;
+               delete [] tmp->fBuffer;
+               delete tmp;
+       }
+}
+
+
+Double_t TimeUsingOldDecoder(AliBufferInfo* list, AliLocalStructInfo* buffer, UInt_t maxBufferSize)
+{
+       /// Perform a timing using the old decoder.
+
+       AliRawReaderMemory rawReader;
+       AliMUONRawStreamTrigger rawStream(&rawReader);
+       rawReader.NextEvent();
+
+       TStopwatch timer;
+       timer.Start(kTRUE);
+
+       UInt_t i = 0;
+       AliBufferInfo* current = list;
+       while (current != NULL)
+       {
+               rawReader.SetMemory(current->fBuffer, current->fBufferSize);
+               rawReader.SetEquipmentID(current->fEquipId);
+               rawReader.Reset();
+
+               rawStream.First();
+               
+               TArrayS fXPattern;
+               TArrayS fYPattern;
+
+               while ( rawStream.Next(buffer[i].fId, buffer[i].fDec, buffer[i].fTrigY,
+                                      buffer[i].fYPos, buffer[i].fSXDev, buffer[i].fXDev,
+                                      buffer[i].fXPos, buffer[i].fTriggerY, buffer[i].fTriggerX,
+                                      fXPattern, fYPattern)
+                     )
+               {
+                       if (i < maxBufferSize-1) i++;
+               }
+
+               current = current->fNext;
+       }
+
+       return timer.RealTime();
+}
+
+
+Double_t TimeUsingNewDecoder(AliBufferInfo* list, AliLocalStructInfo* buffer, UInt_t maxBufferSize)
+{
+       /// Perform a timing using the new decoder.
+
+       AliRawReaderMemory rawReader;
+       AliMUONRawStreamTriggerHP rawStream(&rawReader);
+       rawReader.NextEvent();
+
+       TStopwatch timer;
+       timer.Start(kTRUE);
+
+       UInt_t i = 0;
+       AliBufferInfo* current = list;
+       while (current != NULL)
+       {
+               rawReader.SetMemory(current->fBuffer, current->fBufferSize);
+               rawReader.SetEquipmentID(current->fEquipId);
+               rawReader.Reset();
+
+               rawStream.First();
+
+               const AliMUONRawStreamTriggerHP::AliLocalStruct* local = NULL;
+               while ( (local = rawStream.Next()) != NULL )
+               {
+                       if (i < maxBufferSize)
+                       {
+                               buffer[i].fId = local->GetId();
+                               buffer[i].fDec = local->GetDec();
+                               buffer[i].fTrigY = local->GetTrigY();
+                               buffer[i].fYPos = local->GetYPos();
+                               buffer[i].fSXDev = local->GetSXDev();
+                               buffer[i].fXDev = local->GetXDev();
+                               buffer[i].fXPos = local->GetXPos();
+                               buffer[i].fTriggerY = local->GetTriggerY();
+                               buffer[i].fTriggerX = local->GetTriggerX();
+                               i++;
+                       }
+               }
+
+               current = current->fNext;
+       }
+
+       return timer.RealTime();
+}
+
+
+Double_t TimeUsingNewDecoderOldInterface(AliBufferInfo* list, AliLocalStructInfo* buffer, UInt_t maxBufferSize)
+{
+       /// Perform a timing using the new decoder but the old Next() method
+       /// as the interface.
+
+       AliRawReaderMemory rawReader;
+       AliMUONRawStreamTriggerHP rawStream(&rawReader);
+       rawReader.NextEvent();
+
+       TStopwatch timer;
+       timer.Start(kTRUE);
+
+       UInt_t i = 0;
+       AliBufferInfo* current = list;
+       while (current != NULL)
+       {
+               rawReader.SetMemory(current->fBuffer, current->fBufferSize);
+               rawReader.SetEquipmentID(current->fEquipId);
+               rawReader.Reset();
+
+               rawStream.First();
+               
+               TArrayS fXPattern;
+               TArrayS fYPattern;
+
+               while ( rawStream.Next(buffer[i].fId, buffer[i].fDec, buffer[i].fTrigY,
+                                      buffer[i].fYPos, buffer[i].fSXDev, buffer[i].fXDev,
+                                      buffer[i].fXPos, buffer[i].fTriggerY, buffer[i].fTriggerX,
+                                      fXPattern, fYPattern)
+                     )
+               {
+                       if (i < maxBufferSize-1) i++;
+               }
+
+               current = current->fNext;
+       }
+
+       return timer.RealTime();
+}
+
+
+void Loop(const char* filename, Bool_t newDecoder)
+{
+  AliCodeTimerAutoGeneral(Form("Loop %s",(newDecoder ? "NEW":"OLD")));
+  
+  AliRawReader* reader = AliRawReader::Create(filename);
+  
+  AliMUONVRawStreamTrigger* stream;
+  
+  if ( newDecoder ) 
+  {
+    stream = new AliMUONRawStreamTriggerHP(reader);
+  }
+  else
+  {
+    stream = new AliMUONRawStreamTrigger(reader);
+  }
+
+  UChar_t id;
+  UChar_t dec;
+  Bool_t trigY;
+  UChar_t yPos;
+  UChar_t sXDev;
+  UChar_t xDev;
+  UChar_t xPos;
+  Bool_t triggerY;
+  Bool_t triggerX;
+  TArrayS xPattern;
+  TArrayS yPattern;
+  
+  while ( reader->NextEvent() )
+  {
+    stream->First();
+    
+    while ( stream->Next(id, dec, trigY, yPos, sXDev, xDev, xPos,
+                        triggerY, triggerX, xPattern, yPattern) )
+    {
+      id *= 2;
+    }
+  }
+  
+  delete stream;
+  delete reader;
+}
+
+
+void MUONTimeRawStreamTriggerDumb(TString fileName)
+{
+  AliCodeTimer::Instance()->Reset();
+  
+  // first check we can open the stream
+  AliRawReader* reader = AliRawReader::Create(fileName.Data());
+  if (!reader)
+  {
+    cerr << "Cannot create reader from " << fileName.Data() << endl;
+    return;
+  }
+  delete reader;
+  
+  // now start the timing per se
+  
+  Loop(fileName,kFALSE);
+  
+  Loop(fileName,kTRUE);
+  
+  AliCodeTimer::Instance()->Print();
+}
+
+
+void MUONTimeRawStreamTrigger(TString fileName = "./", Int_t maxEvent = 1000)
+{
+       /// Performs a timing of old and new decoders and reports this.
+
+       AliBufferInfo* list = NULL;
+       UInt_t bufferCount = LoadFiles(list, fileName, maxEvent);
+       if (bufferCount == 0)
+       {
+               cerr << "ERROR: No DDL files found or read in." << endl;
+               return;
+       }
+
+       UInt_t maxBufferSize = CountMaxStructs(list);
+       AliLocalStructInfo* buffer = new AliLocalStructInfo[maxBufferSize];
+       if (buffer == NULL)
+       {
+               ReleaseBuffers(list);
+               cerr << "ERROR: Out of memory, sorry. You should limit the number of events read in." << endl;
+               return;
+       }
+       Double_t oldTimes[100];
+       for (Int_t i = 0; i < 100; i++)
+       {
+               cout << "Timing old decoder: timing iteration " << i+1 << " of 100" << endl;
+               oldTimes[i] = TimeUsingOldDecoder(list, buffer, maxBufferSize);
+       }
+       Double_t newTimes[100];
+       for (Int_t i = 0; i < 100; i++)
+       {
+               cout << "Timing new decoder: timing iteration " << i+1 << " of 100" << endl;
+               newTimes[i] = TimeUsingNewDecoder(list, buffer, maxBufferSize);
+       }
+       Double_t newTimes2[100];
+       for (Int_t i = 0; i < 100; i++)
+       {
+               cout << "Timing new decoder with old interface: timing iteration " << i+1 << " of 100" << endl;
+               newTimes2[i] = TimeUsingNewDecoderOldInterface(list, buffer, maxBufferSize);
+       }
+
+       ReleaseBuffers(list);
+       delete buffer;
+
+       Double_t oldTime = TMath::Mean(100, oldTimes) / Double_t(bufferCount);
+       Double_t oldTimeErr = TMath::RMS(100, oldTimes) / Double_t(bufferCount);
+       Double_t newTime = TMath::Mean(100, newTimes) / Double_t(bufferCount);
+       Double_t newTimeErr = TMath::RMS(100, newTimes) / Double_t(bufferCount);
+       Double_t newTime2 = TMath::Mean(100, newTimes2) / Double_t(bufferCount);
+       Double_t newTime2Err = TMath::RMS(100, newTimes2) / Double_t(bufferCount);
+
+       cout << "Average processing time per DDL for:" << endl;
+       cout << "                   Old decoder = " << oldTime*1e6 << " +/- " << oldTimeErr*1e6/TMath::Sqrt(100) << " micro seconds" << endl;
+       cout << "                   New decoder = " << newTime*1e6 << " +/- " << newTimeErr*1e6/TMath::Sqrt(100) << " micro seconds" << endl;
+       cout << "New decoder with old interface = " << newTime2*1e6 << " +/- " << newTime2Err*1e6/TMath::Sqrt(100) << " micro seconds" << endl;
+}
+
index 1058e52a837e7d8a4191ff807db09ca83f1cf8e1..68709073542b2109f634c3a1bba7eda1fbbfdcf7 100644 (file)
 #pragma link C++ class AliMUONRawStreamTrackerHP::AliBlockHeader+;
 #pragma link C++ class AliMUONRawStreamTrackerHP::AliDspHeader+;
 #pragma link C++ class AliMUONRawStreamTrackerHP::AliBusPatch+;
+#pragma link C++ class AliMUONVRawStreamTrigger+;
 #pragma link C++ class AliMUONRawStreamTrigger+;
+#pragma link C++ class AliMUONRawStreamTriggerHP+;
+#pragma link C++ class AliMUONRawStreamTriggerHP::AliHeader+;
+#pragma link C++ class AliMUONRawStreamTriggerHP::AliRegionalHeader+;
+#pragma link C++ class AliMUONRawStreamTriggerHP::AliLocalStruct+;
 #pragma link C++ class AliMUONRawStream+;
 
 #endif
index d6c4a9b56284447d0ef0643e19c86087bfb1f77f..5e1dfa3cd7a4e99a9ba01d17dee34c05d4602a15 100644 (file)
@@ -12,9 +12,11 @@ SRCS:= AliMUONDDLTrigger.cxx \
        AliMUONBusStruct.cxx \
        AliMUONPayloadTracker.cxx \
        AliMUONVRawStreamTracker.cxx \
+       AliMUONVRawStreamTrigger.cxx \
        AliMUONRawStreamTracker.cxx \
        AliMUONRawStreamTrackerHP.cxx \
        AliMUONRawStreamTrigger.cxx \
+       AliMUONRawStreamTriggerHP.cxx \
        AliMUONRawStream.cxx
 
 HDRS:= $(SRCS:.cxx=.h)