#include "AliMUONBlockHeader.h"
#include "AliMUONBusStruct.h"
#include "AliMUONDDLTracker.h"
+#include "AliMUONLogger.h"
#include "AliRawReader.h"
#include "AliLog.h"
+#include "AliDAQ.h"
#include <cassert>
#include <iostream>
using std::cout;
ClassImp(AliMUONRawStreamTrackerHP)
/// \endcond
+const Int_t AliMUONRawStreamTrackerHP::fgkMaxDDL = 20;
AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP() :
- AliMUONVRawStreamTracker(),
+ TObject(),
+ fRawReader(NULL),
+ fLogger(NULL),
+ fDetailLevel(kMediumErrorDetail),
+ fEnableMUONErrorLogger(kFALSE),
+ fEnableRawReaderErrorLogger(kFALSE),
+ fWarnings(kTRUE),
fDecoder(),
fDDL(0),
fBufferSize(8192),
fkEndOfData(NULL),
fHadError(kFALSE),
fDone(kFALSE),
- fDDLObject(NULL)
+ fDDLObject(NULL),
+ fTotalNumberOfGlitchErrors(0),
+ fTotalNumberOfParityErrors(0),
+ fTotalNumberOfPaddingErrors(0),
+ fTotalNumberOfTokenLostErrors(0)
{
///
/// Default constructor.
fDecoder.MaxDSPs(),
fDecoder.MaxBusPatches()
);
-
+
fDecoder.GetHandler().SetRawStream(this);
}
AliMUONRawStreamTrackerHP::AliMUONRawStreamTrackerHP(AliRawReader* rawReader) :
- AliMUONVRawStreamTracker(rawReader),
+ TObject(),
+ fRawReader(rawReader),
+ fLogger(NULL),
+ fDetailLevel(kMediumErrorDetail),
+ fEnableMUONErrorLogger(kFALSE),
+ fEnableRawReaderErrorLogger(kFALSE),
+ fWarnings(kTRUE),
fDecoder(),
fDDL(0),
fBufferSize(8192),
fkEndOfData(NULL),
fHadError(kFALSE),
fDone(kFALSE),
- fDDLObject(NULL)
+ fDDLObject(NULL),
+ fTotalNumberOfGlitchErrors(0),
+ fTotalNumberOfParityErrors(0),
+ fTotalNumberOfPaddingErrors(0),
+ fTotalNumberOfTokenLostErrors(0)
{
///
/// Constructor with AliRawReader as argument.
fDDL = 0;
fDone = kFALSE;
NextDDL();
+ fTotalNumberOfGlitchErrors = 0;
+ fTotalNumberOfPaddingErrors = 0;
+ fTotalNumberOfParityErrors = 0;
+ fTotalNumberOfTokenLostErrors = 0;
}
Swap(reinterpret_cast<UInt_t*>(fBuffer), dataSize / sizeof(UInt_t)); // Swap needed for mac power pc.
#endif
+ fDDL++; // Remember to increment index to next DDL before the calls to
+ // fDecoder.Decode since the callback methods of the decoder will
+ // use AliMUONRawStreamTrackerHP::GetDDL()
+
bool result = false;
try
{
// handler we need to trap any memory allocation exception to be robust.
result = fDecoder.Decode(fBuffer, dataSize);
fHadError = (result == true ? kFALSE : kTRUE);
+ fTotalNumberOfGlitchErrors += fDecoder.GetHandler().GlitchErrorCount();
+ fTotalNumberOfParityErrors += fDecoder.GetHandler().ParityErrorCount();
+ fTotalNumberOfPaddingErrors += fDecoder.GetHandler().PaddingErrorCount();
+ fTotalNumberOfTokenLostErrors += fDecoder.GetHandler().TokenLostCount();
}
catch (const std::bad_alloc&)
{
fkCurrentData = fkEndOfData = NULL;
}
- fDDL++; // Remember to increment index to next DDL.
return kTRUE;
}
}
-Bool_t AliMUONRawStreamTrackerHP::Next(
- Int_t& busPatchId, UShort_t& manuId, UChar_t& manuChannel,
- UShort_t& adc, Bool_t skipParityErrors
- )
+Bool_t AliMUONRawStreamTrackerHP::Next(Int_t& busPatchId,
+ UShort_t& manuId,
+ UChar_t& manuChannel,
+ UShort_t& adc,
+ Bool_t skipParityErrors)
{
/// Advance one step in the iteration. Returns false if finished.
/// [out] \param busPatchId This is filled with the bus patch ID of the digit.
/// [out] \param manuId This is filled with the MANU ID of the digit.
/// [out] \param manuChannel This is filled with the MANU channel ID of the digit.
/// [out] \param adc This is filled with the ADC signal value of the digit.
- /// [in] \param skipParityErrors If this is kTRUE, we'll skip the buspatches that
- /// have some parity errors
+ /// [in] \param skipParityErrors If this is kTRUE, we'll skip the buspatches that
+ /// have some parity errors
/// \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 (fkCurrentData == NULL) return kFALSE;
- fDecoder.SendDataOnParityError(skipParityErrors);
-
retry:
// Check if we still have data to be returned for the current bus patch.
if (fkCurrentData != fkEndOfData)
{
fkCurrentData = fkCurrentBusPatch->GetData();
fkEndOfData = fkCurrentData + fkCurrentBusPatch->GetDataCount();
+ if ( skipParityErrors )
+ {
+ Bool_t ok(kTRUE);
+ for ( Int_t i = 0; i < fkCurrentBusPatch->GetLength() && ok; ++ i )
+ {
+ ok = fkCurrentBusPatch->IsParityOk(i);
+ }
+ if (!ok) fkCurrentData = fkEndOfData;
+ }
goto retry;
}
}
fParityErrors(0),
fGlitchErrors(0),
fPaddingErrors(0),
- fWarnings(kTRUE)
+ fTokenLostErrors(0),
+ fMaxBlocks(),
+ fMaxDsps(),
+ fMaxBusPatches()
{
/// Default constructor initialises the internal parity flags buffer to
/// store 8192 elements. This array will grow dynamically if needed.
fDSPs = new AliDspHeader[maxBlocks*maxDsps];
fBusPatches = new AliBusPatch[maxBlocks*maxDsps*maxBusPatches];
fEndOfBusPatches = fBusPatches;
+
+ fMaxBlocks = maxBlocks;
+ fMaxDsps = maxDsps;
+ fMaxBusPatches = maxBusPatches;
}
/// \param buffer The pointer to the buffer storing the DDL payload.
/// \param bufferSize The size of the buffer in bytes.
- assert( fRawStream != NULL );
-
// remember the start of the buffer to be used in OnError.
fBufferStart = buffer;
fParityErrors = 0;
fGlitchErrors = 0;
fPaddingErrors = 0;
+ fTokenLostErrors = 0;
// Check if we will have enough space in the fParityOk array.
// If we do not then we need to resize the array.
}
+void AliMUONRawStreamTrackerHP::Swap(UInt_t* buffer, Int_t size) const
+{
+ // swap from little to big endian
+
+ typedef struct {
+ UInt_t b1:8; ///< first byte word
+ UInt_t b2:8; ///< second byte word
+ UInt_t b3:8; ///< third byte word
+ UInt_t b4:8; ///< fourth byte word
+ } RawWord;
+
+ RawWord* word, temp;
+ word = (RawWord*) buffer;
+
+ for (Int_t i = 0; i < size; i++)
+ {
+ temp = *(((RawWord*)buffer)+i);
+ word->b1 = temp.b4;
+ word->b2 = temp.b3;
+ word->b3 = temp.b2;
+ word->b4 = temp.b1;
+ word++;
+ }
+}
+
+
void AliMUONRawStreamTrackerHP::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.
+ /// and logs this with the logger object.
/// \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;
+ assert(fRawStream != NULL);
+
+ const char* message = NULL;
UInt_t word = 0;
-
+ bool logAsMajorError = true;
+
+ // Build the detailed part of the error message if high detail selected.
+ const char* detail = "";
+ if (fRawStream->GetLoggingDetailLevel() == kHighErrorDetail)
+ {
+ bool blockPtrOk = fBlockCount > 0;
+ bool dspPtrOk = blockPtrOk ? fCurrentBlock->GetDspCount() > 0 : false;
+ bool buspatchPtrOk = dspPtrOk ? fCurrentDSP->GetBusPatchCount() > 0 : false;
+ // We subtract 1 from the current numbers of blocks, DSPs
+ // and bus patches to get the iBlock, iDsp and iBus indices.
+ detail = Form(
+ "At byte %lu in DDL %d, event %d, iBlock %d, iDsp %d [DSP ID: %d (0x%X)],"
+ " iBus %d [bus patch ID: %d (0x%X)].",
+ (unsigned long)location - (unsigned long)fBufferStart + sizeof(AliRawDataHeader),
+ AliDAQ::DdlID("MUONTRK", fRawStream->GetDDL()),
+ fRawStream->GetReader()->GetEventIndex(),
+ int(fBlockCount)-1,
+ blockPtrOk ? int(fCurrentBlock->GetDspCount())-1 : -1,
+ blockPtrOk ? fCurrentBlock->GetDspId() : -1,
+ blockPtrOk ? fCurrentBlock->GetDspId() : -1,
+ dspPtrOk ? int(fCurrentDSP->GetBusPatchCount())-1 : -1,
+ buspatchPtrOk ? fCurrentBusPatch->GetBusPatchId() : -1,
+ buspatchPtrOk ? fCurrentBusPatch->GetBusPatchId() : -1
+ );
+ }
+
+ // Build the log message.
switch (error)
{
case kGlitchFound:
fGlitchErrors++;
- message = Form(
- "Glitch error detected in DSP %d, skipping event ",
- fCurrentBlock->GetDspId()
- );
- fRawStream->GetReader()->AddMajorErrorLog(error, message);
+ switch (fRawStream->GetLoggingDetailLevel())
+ {
+ case kLowErrorDetail:
+ message = "Glitch error detected.";
+ break;
+ case kMediumErrorDetail:
+ message = Form(
+ "Glitch error detected in DSP %d (0x%X), skipping event.",
+ fCurrentBlock->GetDspId(), fCurrentBlock->GetDspId()
+ );
+ break;
+ case kHighErrorDetail:
+ default:
+ message = Form("%s %s", ErrorCodeToMessage(error), detail);
+ break;
+ }
+ logAsMajorError = true;
break;
case kBadPaddingWord:
fPaddingErrors++;
- // We subtract 1 from the current numbers of blocks, DSPs
- // and bus patches to get the indices.
- message = Form(
- "Padding word error for iBlock %d, iDsp %d, iBus %d\n",
- fBlockCount-1,
- fCurrentBlock->GetDspCount()-1,
- fCurrentDSP->GetBusPatchCount()-1
- );
- fRawStream->GetReader()->AddMinorErrorLog(error, message);
+ switch (fRawStream->GetLoggingDetailLevel())
+ {
+ case kLowErrorDetail:
+ message = "Padding word error detected.";
+ break;
+ case kMediumErrorDetail:
+ // We subtract 1 from the current numbers of blocks, DSPs
+ // and bus patches to get the indices.
+ message = Form(
+ "Padding word error for iBlock %d, iDsp %d, iBus %d.",
+ fBlockCount-1,
+ fCurrentBlock->GetDspCount()-1,
+ fCurrentDSP->GetBusPatchCount()-1
+ );
+ break;
+ case kHighErrorDetail:
+ default:
+ message = Form("%s %s", ErrorCodeToMessage(error), detail);
+ break;
+ }
+ logAsMajorError = false;
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
- // bit word number.
- word = ((unsigned long)location - (unsigned long)fCurrentBusPatch->GetData())
+ switch (fRawStream->GetLoggingDetailLevel())
+ {
+ case kLowErrorDetail:
+ message = "Parity error detected.";
+ break;
+ case kMediumErrorDetail:
+ message = Form(
+ "Parity error in buspatch %d (0x%X).",
+ fCurrentBusPatch->GetBusPatchId(),
+ fCurrentBusPatch->GetBusPatchId()
+ );
+ break;
+ case kHighErrorDetail:
+ default:
+ // 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
+ // bit word number.
+ word = (reinterpret_cast<size_t>(location) - reinterpret_cast<size_t>(fCurrentBusPatch->GetData()))
/ sizeof(UInt_t);
- message = Form(
- "Parity error in word %d for manuId %d and channel %d in buspatch %d\n",
- word,
- fCurrentBusPatch->GetManuId(word),
- fCurrentBusPatch->GetChannelId(word),
- fCurrentBusPatch->GetBusPatchId()
- );
- fRawStream->GetReader()->AddMinorErrorLog(error, message);
+ message = Form(
+ "Parity error in word %d for manuId %d and channel %d in buspatch %d. %s",
+ word,
+ fCurrentBusPatch->GetManuId(word),
+ fCurrentBusPatch->GetChannelId(word),
+ fCurrentBusPatch->GetBusPatchId(),
+ detail
+ );
+ break;
+ }
+ logAsMajorError = false;
+ break;
+
+ case kTokenLost:
+ fTokenLostErrors++;
+ switch (fRawStream->GetLoggingDetailLevel())
+ {
+ case kLowErrorDetail:
+ message = "Lost token error detected.";
+ break;
+ case kMediumErrorDetail:
+ word = *reinterpret_cast<const UInt_t*>(location);
+ message = Form(
+ "Lost token error detected with address 0x%X of DDL %d and code %d.",
+ ((word & 0xFFFF0000)),
+ fRawStream->GetDDL(),
+ (word & 0xF)
+ );
+ break;
+ case kHighErrorDetail:
+ default:
+ word = *reinterpret_cast<const UInt_t*>(location);
+ message = Form(
+ "Lost token error detected with address 0x%X and code %d. %s",
+ ((word & 0xFFFF0000)),
+ (word & 0xF),
+ detail
+ );
+ break;
+ }
+ logAsMajorError = false;
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);
+ switch (fRawStream->GetLoggingDetailLevel())
+ {
+ case kLowErrorDetail:
+ message = ErrorCodeToMessage(error);
+ break;
+ case kMediumErrorDetail:
+ message = Form(
+ "%s (At byte %lu)",
+ ErrorCodeToMessage(error),
+ (unsigned long)location - (unsigned long)fBufferStart + sizeof(AliRawDataHeader)
+ );
+ break;
+ case kHighErrorDetail:
+ default:
+ message = Form(
+ "%s Error code: %d (%s). %s",
+ ErrorCodeToMessage(error),
+ error, ErrorCodeToString(error),
+ detail
+ );
+ break;
+ }
+ logAsMajorError = true;
break;
}
-
- if (fWarnings)
+
+ // Now log the error message depending on the logging flags set.
+ if (fRawStream->IsRawReaderErrorLoggerEnabled())
+ {
+ if (logAsMajorError)
+ fRawStream->GetReader()->AddMajorErrorLog(Int_t(error), message);
+ else
+ fRawStream->GetReader()->AddMinorErrorLog(Int_t(error), message);
+ }
+ if (fRawStream->IsMUONErrorLoggerEnabled())
+ {
+ AliMUONLogger* logger = fRawStream->GetMUONErrorLogger();
+ if (logger != NULL)
+ {
+ logger->Log(message);
+ }
+ else
+ {
+ AliErrorGeneral(
+ "AliMUONRawStreamTrackerHP::AliDecoderEventHandler",
+ "Enabled logging to AliMUONLogger, but the logger object"
+ " was not set with SetMUONErrorLogger()."
+ );
+ }
+ }
+ if (fRawStream->IsWarningsEnabled())
{
AliWarningGeneral(
"AliMUONRawStreamTrackerHP::AliDecoderEventHandler",