From 708b84e4659711df69abe24349c96fea3092773e Mon Sep 17 00:00:00 2001 From: sevdokim Date: Wed, 27 Apr 2022 10:17:36 +0200 Subject: [PATCH] improve raw errors handling in RawReaderMemory to avoid infinite loops in RawReaderMemory::next() --- .../CPVReconstruction/RawReaderMemory.h | 3 +- .../reconstruction/src/RawReaderMemory.cxx | 46 +++++++++------- .../workflow/src/RawToDigitConverterSpec.cxx | 55 ++++++++++--------- 3 files changed, 58 insertions(+), 46 deletions(-) diff --git a/Detectors/CPV/reconstruction/include/CPVReconstruction/RawReaderMemory.h b/Detectors/CPV/reconstruction/include/CPVReconstruction/RawReaderMemory.h index 56d48dbf26dd8..fad32018a0993 100644 --- a/Detectors/CPV/reconstruction/include/CPVReconstruction/RawReaderMemory.h +++ b/Detectors/CPV/reconstruction/include/CPVReconstruction/RawReaderMemory.h @@ -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, @@ -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: diff --git a/Detectors/CPV/reconstruction/src/RawReaderMemory.cxx b/Detectors/CPV/reconstruction/src/RawReaderMemory.cxx index f1de09027310c..7330a125bacb3 100644 --- a/Detectors/CPV/reconstruction/src/RawReaderMemory.cxx +++ b/Detectors/CPV/reconstruction/src/RawReaderMemory.cxx @@ -54,19 +54,21 @@ 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); @@ -74,8 +76,8 @@ RawErrorType_t RawReaderMemory::next() 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()) { @@ -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(); @@ -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]); @@ -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; } diff --git a/Detectors/CPV/workflow/src/RawToDigitConverterSpec.cxx b/Detectors/CPV/workflow/src/RawToDigitConverterSpec.cxx index 58f84f5f4b424..190a6faf89266 100644 --- a/Detectors/CPV/workflow/src/RawToDigitConverterSpec.cxx +++ b/Detectors/CPV/workflow/src/RawToDigitConverterSpec.cxx @@ -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."; @@ -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 (("; } @@ -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 @@ -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); @@ -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> 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) @@ -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 @@ -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); } @@ -287,7 +292,7 @@ o2::framework::DataProcessorSpec o2::cpv::reco_workflow::getRawToDigitConverterS { std::vector 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); } @@ -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"),