Skip to content

Commit 0748d47

Browse files
mfasDashahor02
authored andcommitted
[EMCAL-534] Add handling of non-fatal decoding errors
Non-fatal errors only skip parts of the decoding (i.e. channel) as part of the payload can be decoded, but do not skip the entire page - Add container for minor errors in AltroDecoder - Add error states for missing bunch header, unexpected end of payload, and payload out- of-bounds - Add category for minor errors in ErrorTypeFee - Add handling of minor errors in raw-to-cell converter
1 parent d88fccb commit 0748d47

File tree

5 files changed

+230
-45
lines changed

5 files changed

+230
-45
lines changed

DataFormats/Detectors/EMCAL/include/DataFormatsEMCAL/ErrorTypeFEE.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ namespace emcal
3636
///
3737
/// - PAGE_ERROR: This type handles all errors related to raw page decoding (not ALTRO payload)
3838
/// - ALTRO_ERROR: This type handles all errors related to decoding of the ALTRO payload
39+
/// - MINOR_ALTRO_ERROR: This type handles all errors related to decoding of the ALTRO payload
40+
/// which are not considered as fatal
3941
/// - FIT_ERROR: This type handles all error appearing during the raw fitting procedure
4042
/// - GEOMETRY_ERROR: This type handles all errors related to the calculation of the module position
4143
/// using the geometry
@@ -49,11 +51,12 @@ class ErrorTypeFEE
4951
/// \enum ErrorSource_t
5052
/// \brief Source of the error
5153
enum ErrorSource_t {
52-
PAGE_ERROR, ///< Raw page decoding failed
53-
ALTRO_ERROR, ///< Decoding of the ALTRO payload failed
54-
FIT_ERROR, ///< Raw fit failed
55-
GEOMETRY_ERROR, ///< Decoded position outside EMCAL
56-
UNDEFINED ///< Error source undefined
54+
PAGE_ERROR, ///< Raw page decoding failed
55+
ALTRO_ERROR, ///< Decoding of the ALTRO payload failed
56+
MINOR_ALTRO_ERROR, ///< Non-fatal error in decoding of the ALTRO payload
57+
FIT_ERROR, ///< Raw fit failed
58+
GEOMETRY_ERROR, ///< Decoded position outside EMCAL
59+
UNDEFINED ///< Error source undefined
5760
};
5861
/// \brief Constructor
5962
ErrorTypeFEE() = default;
@@ -75,6 +78,10 @@ class ErrorTypeFEE
7578
/// \param decodeError Error code of the decoding error
7679
void setDecodeErrorType(int decodeError) { setError(ErrorSource_t::ALTRO_ERROR, decodeError); }
7780

81+
/// \brief Set the error as minor (non-fatal) decoding error and store the error code
82+
/// \param decodeError Error code of the decoding error
83+
void setMinorDecodingErrorType(int decodeError) { setError(ErrorSource_t::MINOR_ALTRO_ERROR, decodeError); }
84+
7885
/// \brief Set the error as raw fitter error and store the error code
7986
/// \param rawfitterError Error code of the raw fitter error
8087
void setRawFitErrorType(int rawfitterError) { setError(ErrorSource_t::FIT_ERROR, rawfitterError); }
@@ -116,6 +123,10 @@ class ErrorTypeFEE
116123
/// \return Error code (-1 in case the object is not a decoding error)
117124
int getDecodeErrorType() const { return getRawErrorForType(ErrorSource_t::ALTRO_ERROR); }
118125

126+
/// \brief Get the error code of the obect in case the object is a decoding error
127+
/// \return Error code (-1 in case the object is not a decoding error)
128+
int getMinorDecodeErrorType() const { return getRawErrorForType(ErrorSource_t::MINOR_ALTRO_ERROR); }
129+
119130
/// \brief Get the error code of the obect in case the object is a raw fitter error
120131
/// \return Error code (-1 in case the object is not a raw fitter error)
121132
int getRawFitErrorType() const { return getRawErrorForType(ErrorSource_t::FIT_ERROR); }

DataFormats/Detectors/EMCAL/src/ErrorTypeFEE.cxx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ void ErrorTypeFEE::PrintStream(std::ostream& stream) const
2121
case ErrorSource_t::ALTRO_ERROR:
2222
typestring = "decode error";
2323
break;
24+
case ErrorSource_t::MINOR_ALTRO_ERROR:
25+
typestring = "decode error";
26+
break;
2427
case ErrorSource_t::FIT_ERROR:
2528
typestring = "fit error";
2629
break;

Detectors/EMCAL/reconstruction/include/EMCALReconstruction/AltroDecoder.h

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,74 @@ class AltroDecoderError : public std::exception
7878
std::string mErrorMessage; ///< Message connected to the error type
7979
};
8080

81+
/// \class MinorAltroDecodingError
82+
/// \brief Error handling for the ALTRO decoder for non-crashing errors
83+
/// \ingroup EMCALreconstruction
84+
class MinorAltroDecodingError
85+
{
86+
public:
87+
/// \enum ErrorType_t
88+
/// \brief Error codes connected with the ALTRO decoding
89+
enum class ErrorType_t {
90+
BUNCH_HEADER_NULL, ///< Bunch header is 0
91+
CHANNEL_END_PAYLOAD_UNEXPECT, ///< Unexpected end of payload (channel or trailer word in bunch words)
92+
CHANNEL_PAYLOAD_EXCEED ///< Exceeding channel payload block
93+
};
94+
95+
/// \brief Dummy constructor
96+
MinorAltroDecodingError() = default;
97+
98+
/// \brief Constructor, initializing the object
99+
/// \param errtype Type of the error
100+
/// \param channelHeader Header of the channel raising the error
101+
/// \param payloadword Payload word raising the error
102+
MinorAltroDecodingError(ErrorType_t errtype, uint32_t channelHeader, uint32_t payloadword) : mErrorType(errtype),
103+
mChannelHeader(channelHeader),
104+
mPayloadWord(payloadword)
105+
{
106+
}
107+
108+
/// \brief Destructor
109+
~MinorAltroDecodingError() noexcept = default;
110+
111+
/// \brief Get the header of the channel raising the error
112+
/// \return Hardware address
113+
uint32_t getChannelHeader() const noexcept { return mChannelHeader; };
114+
115+
/// \brief Get the payload word raising the error
116+
/// \return Payload word
117+
uint32_t getPayloadWord() const noexcept { return mPayloadWord; }
118+
119+
/// \brief Get the type of the error
120+
/// \return Error type
121+
ErrorType_t getErrorType() const noexcept { return mErrorType; }
122+
123+
/// \brief Create and return error message for different error types
124+
/// \return Error message
125+
///
126+
/// Object returning a std::string which can be owned by the caller.
127+
/// This is in contrast to exceptions inheriting from std::exception
128+
/// which must return const char * in order to comply with the interface.
129+
std::string what() const noexcept;
130+
131+
/// \brief convert the error type from symoblic constant into int
132+
/// \return the error number
133+
static int errorTypeToInt(ErrorType_t errortype);
134+
135+
/// \brief convert the error from number into a type (symbolic constant)
136+
/// \return the error type
137+
static ErrorType_t intToErrorType(int errornumber);
138+
139+
/// \brief Get the number of error types handled by the AltroDecoderError
140+
/// \return Number of error types
141+
static constexpr int getNumberOfErrorTypes() noexcept { return 2; }
142+
143+
private:
144+
ErrorType_t mErrorType; ///< Type of the error
145+
uint32_t mChannelHeader; ///< Hardware address raising the error
146+
uint32_t mPayloadWord; ///< Payload word raising the error
147+
};
148+
81149
/// \class AltroDecoder
82150
/// \brief Decoder of the ALTRO data in the raw page
83151
/// \ingroup EMCALreconstruction
@@ -130,6 +198,10 @@ class AltroDecoder
130198
/// \brief Read channels for the current event in the raw buffer
131199
void readChannels();
132200

201+
/// \brief Get list of minor decoding errors
202+
/// \return List of minor decoding errors
203+
const std::vector<MinorAltroDecodingError>& getMinorDecodingErrors() const { return mMinorDecodingErrors; }
204+
133205
private:
134206
/// \brief run checks on the RCU trailer
135207
/// \throw Error if the RCU trailer has inconsistencies
@@ -138,10 +210,11 @@ class AltroDecoder
138210
/// In case of failure an exception is thrown.
139211
void checkRCUTrailer();
140212

141-
RawReaderMemory& mRawReader; ///< underlying raw reader
142-
RCUTrailer mRCUTrailer; ///< RCU trailer
143-
std::vector<Channel> mChannels; ///< vector of channels in the raw stream
144-
bool mChannelsInitialized = false; ///< check whether the channels are initialized
213+
RawReaderMemory& mRawReader; ///< underlying raw reader
214+
RCUTrailer mRCUTrailer; ///< RCU trailer
215+
std::vector<Channel> mChannels; ///< vector of channels in the raw stream
216+
std::vector<MinorAltroDecodingError> mMinorDecodingErrors; ///< Container for minor (non-crashing) errors
217+
bool mChannelsInitialized = false; ///< check whether the channels are initialized
145218

146219
ClassDefNV(AltroDecoder, 1);
147220
};

Detectors/EMCAL/reconstruction/src/AltroDecoder.cxx

Lines changed: 90 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
99
// granted to it by virtue of its status as an Intergovernmental Organization
1010
// or submit itself to any jurisdiction.
1111
#include <cstring>
12+
#include <iomanip>
13+
#include <iostream>
1214
#include <boost/format.hpp>
1315
#include "InfoLogger/InfoLogger.hxx"
16+
#include "DetectorsRaw/RDHUtils.h"
1417
#include "EMCALReconstruction/AltroDecoder.h"
1518
#include "EMCALReconstruction/RawReaderMemory.h"
1619

@@ -25,6 +28,7 @@ AltroDecoder::AltroDecoder(RawReaderMemory& reader) : mRawReader(reader),
2528

2629
void AltroDecoder::decode()
2730
{
31+
mMinorDecodingErrors.clear();
2832
readRCUTrailer();
2933
checkRCUTrailer();
3034
readChannels();
@@ -45,6 +49,11 @@ void AltroDecoder::readRCUTrailer()
4549

4650
void AltroDecoder::checkRCUTrailer()
4751
{
52+
int trailersize = mRCUTrailer.getTrailerSize();
53+
int buffersize = mRawReader.getPayload().getPayloadWords().size();
54+
if (trailersize > buffersize) {
55+
throw AltroDecoderError(AltroDecoderError::ErrorType_t::RCU_TRAILER_SIZE_ERROR, (boost::format("Trailer size %d exceeding buffer size %d") % trailersize % buffersize).str().data());
56+
}
4857
}
4958

5059
void AltroDecoder::readChannels()
@@ -53,12 +62,14 @@ void AltroDecoder::readChannels()
5362
mChannels.clear();
5463
int currentpos = 0;
5564
auto& buffer = mRawReader.getPayload().getPayloadWords();
56-
while (currentpos < buffer.size() - mRCUTrailer.getTrailerSize()) {
65+
auto maxpayloadsize = buffer.size() - mRCUTrailer.getTrailerSize();
66+
while (currentpos < maxpayloadsize) {
5767
auto currentword = buffer[currentpos++];
5868
if (currentword >> 30 != 1) {
5969
continue;
6070
}
6171
// starting a new channel
72+
auto channelheader = currentword;
6273
mChannels.emplace_back(currentword & 0xFFF, (currentword >> 16) & 0x3FF);
6374
auto& currentchannel = mChannels.back();
6475
currentchannel.setBadChannel((currentword >> 29) & 0x1);
@@ -67,11 +78,13 @@ void AltroDecoder::readChannels()
6778
int numberofwords = (currentchannel.getPayloadSize() + 2) / 3;
6879
std::vector<uint16_t> bunchwords;
6980
for (int iword = 0; iword < numberofwords; iword++) {
81+
if (currentpos >= maxpayloadsize) {
82+
mMinorDecodingErrors.emplace_back(MinorAltroDecodingError::ErrorType_t::CHANNEL_PAYLOAD_EXCEED, channelheader, currentword);
83+
break; // Must break here in order not to prevent a buffer overrun
84+
}
7085
currentword = buffer[currentpos++];
7186
if ((currentword >> 30) != 0) {
72-
// AliceO2::InfoLogger::InfoLogger logger;
73-
// logger << "Unexpected end of payload in altro channel payload! DDL=" << std::setw(3) << std::setfill(0) << mRawReader.getRawHeader().getLink()
74-
// << ", Address=0x" << std::hex << current.getHardwareAddress() << ", word=0x" << currentword << std::dec;
87+
mMinorDecodingErrors.emplace_back(MinorAltroDecodingError::ErrorType_t::CHANNEL_END_PAYLOAD_UNEXPECT, channelheader, currentword);
7588
currentpos--;
7689
continue;
7790
}
@@ -83,6 +96,11 @@ void AltroDecoder::readChannels()
8396
// decode bunches
8497
int currentsample = 0;
8598
while (currentsample < currentchannel.getPayloadSize() && bunchwords.size() > currentsample + 2) {
99+
// Check if bunch word is 0 - if yes skip all following bunches as they can no longer be reliably decoded
100+
if (bunchwords[currentsample] == 0) {
101+
mMinorDecodingErrors.emplace_back(MinorAltroDecodingError::ErrorType_t::BUNCH_HEADER_NULL, channelheader, 0);
102+
break;
103+
}
86104
int bunchlength = bunchwords[currentsample] - 2, // remove words for bunchlength and starttime
87105
starttime = bunchwords[currentsample + 1];
88106
auto& currentbunch = currentchannel.createBunch(bunchlength, starttime);
@@ -182,5 +200,73 @@ AltroErrType AltroDecoderError::intToErrorType(int errornumber)
182200
break;
183201
}
184202

203+
return errorType;
204+
}
205+
206+
std::string MinorAltroDecodingError::what() const noexcept
207+
{
208+
std::stringstream result;
209+
switch (mErrorType) {
210+
case ErrorType_t::CHANNEL_END_PAYLOAD_UNEXPECT:
211+
result << "Unexpected end of payload in altro channel payload!";
212+
break;
213+
case ErrorType_t::CHANNEL_PAYLOAD_EXCEED:
214+
result << "Trying to access out-of-bound payload!";
215+
break;
216+
case ErrorType_t::BUNCH_HEADER_NULL:
217+
result << "Bunch header 0 or not configured!";
218+
break;
219+
};
220+
auto address = mChannelHeader & 0xFFF,
221+
payload = (mChannelHeader >> 16) & 0x3FF;
222+
bool good = (mChannelHeader >> 29) & 0x1;
223+
224+
result << " Channel header=0x" << std::hex << mChannelHeader
225+
<< " (Address=0x" << address << ", payload " << std::dec << payload << ", good " << (good ? "yes" : "no") << ")"
226+
<< ", word=0x" << std::hex << mPayloadWord << std::dec;
227+
return result.str();
228+
}
229+
230+
using MinorAltroErrType = o2::emcal::MinorAltroDecodingError::ErrorType_t;
231+
232+
int MinorAltroDecodingError::errorTypeToInt(MinorAltroErrType errortype)
233+
{
234+
235+
int errorNumber = -1;
236+
237+
switch (errortype) {
238+
case MinorAltroErrType::CHANNEL_END_PAYLOAD_UNEXPECT:
239+
errorNumber = 0;
240+
break;
241+
case MinorAltroErrType::CHANNEL_PAYLOAD_EXCEED:
242+
errorNumber = 1;
243+
break;
244+
case MinorAltroErrType::BUNCH_HEADER_NULL:
245+
errorNumber = 2;
246+
break;
247+
}
248+
249+
return errorNumber;
250+
}
251+
252+
MinorAltroErrType MinorAltroDecodingError::intToErrorType(int errornumber)
253+
{
254+
255+
MinorAltroErrType errorType;
256+
257+
switch (errornumber) {
258+
case 0:
259+
errorType = MinorAltroErrType::CHANNEL_END_PAYLOAD_UNEXPECT;
260+
break;
261+
case 1:
262+
errorType = MinorAltroErrType::CHANNEL_PAYLOAD_EXCEED;
263+
break;
264+
case 2:
265+
errorType = MinorAltroErrType::BUNCH_HEADER_NULL;
266+
break;
267+
default:
268+
break;
269+
}
270+
185271
return errorType;
186272
}

0 commit comments

Comments
 (0)