Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CPV: improve raw errors handling in RawReaderMemory to avoid infinite loop… #8662

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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