Skip to content

Commit

Permalink
improve raw errors handling in RawReaderMemory to avoid infinite loop…
Browse files Browse the repository at this point in the history
…s in RawReaderMemory::next()
  • Loading branch information
sevdokim authored and davidrohr committed Apr 27, 2022
1 parent 8cfc790 commit 1779da5
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ enum RawErrorType_t {
kNOT_CPV_RDH,
kSTOPBIT_NOTFOUND,
kPAGE_NOTFOUND,
kOFFSET_TO_NEXT_IS_0,
kPAYLOAD_INCOMPLETE,
kNO_CPVHEADER,
kNO_CPVTRAILER,
Expand All @@ -50,7 +51,7 @@ enum RawErrorType_t {
/// \author Dmitri Peresunko after Markus Fasel
/// \since Sept. 25, 2020
///
///It reads one HBF, stores HBF orbit number in getCurrentHBFOrbit() and produces digits in AddressChargeBC format
/// It reads one HBF, stores HBF orbit number in getCurrentHBFOrbit() and produces digits in AddressChargeBC format
class RawReaderMemory
{
public:
Expand Down
46 changes: 26 additions & 20 deletions Detectors/CPV/reconstruction/src/RawReaderMemory.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -54,28 +54,30 @@ void RawReaderMemory::init()
mIsJustInited = true;
}

//Read the next pages until the stop bit is found or new HBF reached
//it means we read 1 HBF per next() call
// Read the next pages until the stop bit is found or new HBF reached
// it means we read 1 HBF per next() call
RawErrorType_t RawReaderMemory::next()
{
mRawPayload.clear();
bool isStopBitFound = false;
do {
RawErrorType_t e = nextPage();
if (e == RawErrorType_t::kPAGE_NOTFOUND || // nothing left to read...
e == RawErrorType_t::kRDH_DECODING || // incorrect rdh -> fatal error
e == RawErrorType_t::kPAYLOAD_INCOMPLETE || // we reached end of mRawMemoryBuffer but payload size from rdh tells to read more
e == RawErrorType_t::kSTOPBIT_NOTFOUND) { //new HBF orbit started but no stop bit found, need to return
throw e; //some principal error occured -> stop reading.
if (e == RawErrorType_t::kPAGE_NOTFOUND || // nothing left to read...
e == RawErrorType_t::kRDH_DECODING || // incorrect rdh -> fatal error
e == RawErrorType_t::kPAYLOAD_INCOMPLETE || // we reached end of mRawMemoryBuffer but payload size from rdh tells to read more
e == RawErrorType_t::kSTOPBIT_NOTFOUND || // new HBF orbit started but no stop bit found, need to return
e == RawErrorType_t::kNOT_CPV_RDH || // not cpv rdh -> most probably
e == RawErrorType_t::kOFFSET_TO_NEXT_IS_0) { // offset to next package is 0 -> do not know how to read next
throw e; // some principal error occured -> stop reading.
}
isStopBitFound = RDHDecoder::getStop(mRawHeader);
} while (!isStopBitFound);

return RawErrorType_t::kOK;
}

//Read the next ONLY ONE page from the stream (single DMA page)
//note: 1 raw header per page
// Read the next ONLY ONE page from the stream (single DMA page)
// note: 1 raw header per page
RawErrorType_t RawReaderMemory::nextPage()
{
if (!hasNext()) {
Expand All @@ -88,27 +90,30 @@ RawErrorType_t RawReaderMemory::nextPage()
o2::header::RDHAny rawHeader;
try {
rawHeader = decodeRawHeader(mRawMemoryBuffer.data() + mCurrentPosition);
if (RDHDecoder::getOffsetToNext(rawHeader) == 0) { // dont' know how to read next -> skip to next HBF
return RawErrorType_t::kOFFSET_TO_NEXT_IS_0;
}
if (RDHDecoder::getSourceID(rawHeader) != 0x8) {
// Not a CPV RDH
mCurrentPosition += RDHDecoder::getOffsetToNext(rawHeader); //moving on
mCurrentPosition += RDHDecoder::getOffsetToNext(rawHeader); // not cpv rdh -> skip to next HBF
return RawErrorType_t::kNOT_CPV_RDH;
}
if (mIsJustInited || mStopBitWasNotFound) { //reading first time after init() or stopbit was not found
if (mIsJustInited || mStopBitWasNotFound) { // reading first time after init() or stopbit was not found
mCurrentHBFOrbit = RDHDecoder::getHeartBeatOrbit(rawHeader);
mRawHeader = rawHeader; //save RDH of first page as mRawHeader
mRawHeader = rawHeader; // save RDH of first page as mRawHeader
mRawHeaderInitialized = true;
mStopBitWasNotFound = false; //reset this flag as we start to read again
mStopBitWasNotFound = false; // reset this flag as we start to read again
mIsJustInited = false;
} else if (mCurrentHBFOrbit != RDHDecoder::getHeartBeatOrbit(rawHeader)) {
//next HBF started but we didn't find stop bit.
// next HBF started but we didn't find stop bit.
mStopBitWasNotFound = true;
mCurrentPosition += RDHDecoder::getOffsetToNext(mRawHeader); // moving on
return RawErrorType_t::kSTOPBIT_NOTFOUND; // Stop reading, this will be read again by calling next()
mCurrentPosition += RDHDecoder::getOffsetToNext(rawHeader); // moving on
return RawErrorType_t::kSTOPBIT_NOTFOUND; // Stop bit was not found -> skip to next HBF
}
} catch (...) {
return RawErrorType_t::kRDH_DECODING; //this is fatal error
return RawErrorType_t::kRDH_DECODING; // this is fatal error -> skip whole TF
}
mRawHeader = rawHeader; //save RDH of current page as mRawHeader
mRawHeader = rawHeader; // save RDH of current page as mRawHeader
mRawHeaderInitialized = true;

auto tmp = mRawMemoryBuffer.data();
Expand All @@ -117,7 +122,8 @@ RawErrorType_t RawReaderMemory::nextPage()
bool isPayloadIncomplete = false;
if (mCurrentPosition + RDHDecoder::getMemorySize(mRawHeader) > mRawMemoryBuffer.size()) {
// Payload incomplete
end = mRawMemoryBuffer.size(); //OK, lets read it anyway. Maybe there still are some completed events...
isPayloadIncomplete = true;
end = mRawMemoryBuffer.size(); // OK, lets read it anyway. Maybe there still are some completed events...
}
for (auto iword = start; iword < end; iword++) {
mRawPayload.push_back(tmp[iword]);
Expand All @@ -126,7 +132,7 @@ RawErrorType_t RawReaderMemory::nextPage()

mCurrentPosition += RDHDecoder::getOffsetToNext(mRawHeader); /// Assume fixed 8 kB page size
if (isPayloadIncomplete) {
return RawErrorType_t::kPAYLOAD_INCOMPLETE; //return error so we can it handle later
return RawErrorType_t::kPAYLOAD_INCOMPLETE; // skip to next HBF
}
return RawErrorType_t::kOK;
}
55 changes: 30 additions & 25 deletions Detectors/CPV/workflow/src/RawToDigitConverterSpec.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ void RawToDigitConverterSpec::init(framework::InitContext& ctx)
LOG(debug) << "Initializing RawToDigitConverterSpec...";
// Pedestal flag true/false
LOG(info) << "Pedestal run: " << (mIsPedestalData ? "YES" : "NO");
if (mIsPedestalData) { //no calibration for pedestal runs needed
if (mIsPedestalData) { // no calibration for pedestal runs needed
mIsUsingGainCalibration = false;
mIsUsingBadMap = false;
LOG(info) << "CCDB is not used. Task configuration is done.";
Expand All @@ -64,7 +64,7 @@ void RawToDigitConverterSpec::run(framework::ProcessingContext& ctx)
auto now = std::chrono::system_clock::now();
if (mIsMuteDecoderErrors) { // check if 10-minutes muting period passed
if (((now - mTimeWhenMuted) / std::chrono::minutes(1)) >= 10) {
mIsMuteDecoderErrors = false; //unmute
mIsMuteDecoderErrors = false; // unmute
if (mDecoderErrorsCounterWhenMuted) {
LOG(error) << "RawToDigitConverterSpec::run() : " << mDecoderErrorsCounterWhenMuted << " errors happened while it was muted ((";
}
Expand Down Expand Up @@ -102,7 +102,7 @@ void RawToDigitConverterSpec::run(framework::ProcessingContext& ctx)
ctx.outputs().snapshot(o2::framework::Output{"CPV", "DIGITTRIGREC", 0, o2::framework::Lifetime::Timeframe}, mOutputTriggerRecords);
mOutputHWErrors.clear();
ctx.outputs().snapshot(o2::framework::Output{"CPV", "RAWHWERRORS", 0, o2::framework::Lifetime::Timeframe}, mOutputHWErrors);
return; //empty TF, nothing to process
return; // empty TF, nothing to process
}
}
contDeadBeef = 0; // if good data, reset the counter
Expand Down Expand Up @@ -144,28 +144,33 @@ void RawToDigitConverterSpec::run(framework::ProcessingContext& ctx)
if (!mIsMuteDecoderErrors) {
LOG(error) << "Raw decoding error " << (int)e;
}
//add error list
//RawErrorType_t is defined in O2/Detectors/CPV/reconstruction/include/CPVReconstruction/RawReaderMemory.h
//RawDecoderError(short c, short d, short g, short p, RawErrorType_t e)
mOutputHWErrors.emplace_back(-1, 0, 0, 0, e); //Put general errors to non-existing ccId -1
//if problem in header, abandon this page
if (e == RawErrorType_t::kRDH_DECODING) {
// add error list
// RawErrorType_t is defined in O2/Detectors/CPV/reconstruction/include/CPVReconstruction/RawReaderMemory.h
// RawDecoderError(short c, short d, short g, short p, RawErrorType_t e)
mOutputHWErrors.emplace_back(-1, 0, 0, 0, e); // Put general errors to non-existing ccId -1
// if problem in header, abandon this page
if (e == RawErrorType_t::kRDH_DECODING) { // fatal error -> skip whole TF
LOG(error) << "RDH decoding error. Skipping this TF";
skipTF = true;
break;
}
//if problem in payload, try to continue
if (e == RawErrorType_t::kPAGE_NOTFOUND || // nothing left to read -> skip to next HBF
e == RawErrorType_t::kNOT_CPV_RDH || // not cpv rdh -> skip to next HBF
e == RawErrorType_t::kOFFSET_TO_NEXT_IS_0) { // offset to next package is 0 -> do not know how to read next -> skip to next HBF
break;
}
// if problem in payload, try to continue
continue;
}
auto& rdh = rawreader.getRawHeader();
auto triggerOrbit = o2::raw::RDHUtils::getTriggerOrbit(rdh);
auto mod = o2::raw::RDHUtils::getLinkID(rdh) + 2; //link=0,1,2 -> mod=2,3,4
//for now all modules are written to one LinkID
if (mod > o2::cpv::Geometry::kNMod || mod < 2) { //only 3 correct modules:2,3,4
auto mod = o2::raw::RDHUtils::getLinkID(rdh) + 2; // link=0,1,2 -> mod=2,3,4
// for now all modules are written to one LinkID
if (mod > o2::cpv::Geometry::kNMod || mod < 2) { // only 3 correct modules:2,3,4
if (!mIsMuteDecoderErrors) {
LOG(error) << "RDH linkId corresponds to module " << mod << " which does not exist";
}
mOutputHWErrors.emplace_back(-1, mod, 0, 0, kRDH_INVALID); //Add non-existing modules to non-existing ccId -1 and dilogic = mod
mOutputHWErrors.emplace_back(-1, mod, 0, 0, kRDH_INVALID); // Add non-existing modules to non-existing ccId -1 and dilogic = mod
continue;
}
o2::cpv::RawDecoder decoder(rawreader);
Expand Down Expand Up @@ -193,14 +198,14 @@ void RawToDigitConverterSpec::run(framework::ProcessingContext& ctx)
}

if (!(err == kOK || err == kOK_NO_PAYLOAD)) {
//TODO handle severe errors
//TODO: probably careful conversion of decoder errors to Fitter errors?
mOutputHWErrors.emplace_back(-1, mod, 0, 0, err); //assign general RDH errors to non-existing ccId -1 and dilogic = mod
// TODO handle severe errors
// TODO: probably careful conversion of decoder errors to Fitter errors?
mOutputHWErrors.emplace_back(-1, mod, 0, 0, err); // assign general RDH errors to non-existing ccId -1 and dilogic = mod
}

std::shared_ptr<std::vector<o2::cpv::Digit>> currentDigitContainer;
auto digilets = decoder.getDigits();
if (digilets.empty()) { //no digits -> continue to next pages
if (digilets.empty()) { // no digits -> continue to next pages
continue;
}
o2::InteractionRecord currentIR(0, triggerOrbit); //(bc, orbit)
Expand All @@ -219,9 +224,9 @@ void RawToDigitConverterSpec::run(framework::ProcessingContext& ctx)

AddressCharge ac = {adch};
unsigned short absId = ac.Address;
//if we deal with non-pedestal data?
if (!mIsPedestalData) { //not a pedestal data
//test bad map
// if we deal with non-pedestal data?
if (!mIsPedestalData) { // not a pedestal data
// test bad map
if (mIsUsingBadMap) {
if (!badMap->isChannelGood(absId)) {
continue; // skip bad channel
Expand All @@ -236,12 +241,12 @@ void RawToDigitConverterSpec::run(framework::ProcessingContext& ctx)
if (amp > 0) { // emplace new digit
currentDigitContainer->emplace_back(absId, amp, -1);
}
} else { //pedestal data, no calibration needed.
} else { // pedestal data, no calibration needed.
currentDigitContainer->emplace_back(absId, (float)ac.Charge, -1);
}
}
}
//Check and send list of hwErrors
// Check and send list of hwErrors
for (auto& er : decoder.getErrors()) {
mOutputHWErrors.push_back(er);
}
Expand Down Expand Up @@ -287,7 +292,7 @@ o2::framework::DataProcessorSpec o2::cpv::reco_workflow::getRawToDigitConverterS
{
std::vector<o2::framework::InputSpec> inputs;
inputs.emplace_back("RAWDATA", o2::framework::ConcreteDataTypeMatcher{"CPV", "RAWDATA"}, o2::framework::Lifetime::Optional);
//receive at least 1 guaranteed input (which will allow to acknowledge the TF)
// receive at least 1 guaranteed input (which will allow to acknowledge the TF)
if (askDISTSTF) {
inputs.emplace_back("STFDist", "FLP", "DISTSUBTIMEFRAME", 0, o2::framework::Lifetime::Timeframe);
}
Expand All @@ -305,7 +310,7 @@ o2::framework::DataProcessorSpec o2::cpv::reco_workflow::getRawToDigitConverterS
outputs.emplace_back("CPV", "DIGITS", 0, o2::framework::Lifetime::Timeframe);
outputs.emplace_back("CPV", "DIGITTRIGREC", 0, o2::framework::Lifetime::Timeframe);
outputs.emplace_back("CPV", "RAWHWERRORS", 0, o2::framework::Lifetime::Timeframe);
//note that for cpv we always have stream #0 (i.e. CPV/DIGITS/0)
// note that for cpv we always have stream #0 (i.e. CPV/DIGITS/0)

return o2::framework::DataProcessorSpec{"CPVRawToDigitConverterSpec",
inputs, // o2::framework::select("A:CPV/RAWDATA"),
Expand Down

0 comments on commit 1779da5

Please sign in to comment.