Skip to content

Commit cf19cd9

Browse files
dstoccosawenzel
authored andcommitted
Improve the MID Raw buffer
- Allow to navigate on RDHs - Prevent crash on empty HBs - Save the last HB page in case it was not fully consumed (this prevents the invalidation of the pointer to the last RDH)
1 parent 2737f85 commit cf19cd9

File tree

3 files changed

+71
-54
lines changed

3 files changed

+71
-54
lines changed

Detectors/MUON/MID/Raw/include/MIDRaw/RawBuffer.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,21 @@ template <typename T>
2828
class RawBuffer
2929
{
3030
public:
31-
void setBuffer(gsl::span<const T> bytes, bool keepUnconsumed = true);
31+
enum class ResetMode {
32+
all, // Reset buffer and indexes
33+
keepUnconsumed, // Keep the last unconsumed HB
34+
bufferOnly // Do not reset indexes
35+
};
36+
37+
void setBuffer(gsl::span<const T> bytes, ResetMode resetMode = ResetMode::keepUnconsumed);
3238

3339
/// Gets the current RDH
3440
const header::RAWDataHeader* getRDH() { return mRDH; }
3541

3642
unsigned int next(unsigned int nBits);
3743
T next();
38-
bool nextHeader(gsl::span<const T> bytes);
44+
45+
bool nextHeader();
3946

4047
bool hasNext(unsigned int nBytes);
4148

@@ -46,9 +53,10 @@ class RawBuffer
4653
private:
4754
gsl::span<const T> mBytes{}; /// gsl span with encoded information
4855
gsl::span<const T> mCurrentBuffer{}; /// gsl span with the current encoded information
49-
std::vector<T> mUnconsumed; /// Unconsumed buffer
56+
std::vector<T> mUnconsumed{}; /// Unconsumed buffer
5057
size_t mElementIndex{0}; /// Index of the current element in the buffer
5158
size_t mBitIndex{0}; /// Index of the current bit
59+
size_t mHeaderIndex{0}; /// Index of the current header
5260
size_t mNextHeaderIndex{0}; /// Index of the next header
5361
size_t mEndOfPayloadIndex{0}; /// Index of the end of payload
5462
const unsigned int mElementSizeInBytes{sizeof(T)}; /// Element size in bytes

Detectors/MUON/MID/Raw/src/RawBuffer.cxx

Lines changed: 48 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ template <typename T>
2727
unsigned int RawBuffer<T>::next(unsigned int nBits)
2828
{
2929
/// Reads the next nBits
30+
if (mNextHeaderIndex == 0) {
31+
// This is the first entry
32+
nextPayload();
33+
}
3034
unsigned int value = 0;
3135
for (int ibit = 0; ibit < nBits; ++ibit) {
3236
if (mBitIndex == mElementSizeInBits) {
@@ -51,31 +55,42 @@ T RawBuffer<T>::next()
5155
return mBytes[mElementIndex++];
5256
}
5357

58+
template <typename T>
59+
bool RawBuffer<T>::nextHeader()
60+
{
61+
/// Goes to next RDH
62+
if (mNextHeaderIndex >= mBytes.size()) {
63+
// This is the end of the buffer
64+
if (mUnconsumed.empty()) {
65+
mElementIndex = mNextHeaderIndex;
66+
mEndOfPayloadIndex = mNextHeaderIndex;
67+
return false;
68+
}
69+
// We were reading the unconsumed part: switch to new buffer
70+
mUnconsumed.clear();
71+
reset();
72+
mBytes = mCurrentBuffer;
73+
}
74+
mHeaderIndex = mNextHeaderIndex;
75+
mRDH = reinterpret_cast<const header::RAWDataHeader*>(&mBytes[mHeaderIndex]);
76+
mEndOfPayloadIndex = mHeaderIndex + (mRDH->memorySize / mElementSizeInBytes);
77+
// Go to end of header, i.e. beginning of payload
78+
mElementIndex = mHeaderIndex + (mRDH->headerSize / mElementSizeInBytes);
79+
mNextHeaderIndex = mHeaderIndex + mRDH->offsetToNext / mElementSizeInBytes;
80+
mBitIndex = 0;
81+
82+
return true;
83+
}
84+
5485
template <typename T>
5586
bool RawBuffer<T>::nextPayload()
5687
{
5788
/// Goes to next payload
5889
while (mElementIndex == mEndOfPayloadIndex) {
59-
if (mNextHeaderIndex == mBytes.size()) {
60-
// This is the end of the buffer
61-
if (mUnconsumed.empty()) {
62-
mElementIndex = mNextHeaderIndex;
63-
mEndOfPayloadIndex = mNextHeaderIndex;
64-
return false;
65-
}
66-
// We were reading the unconsumed part: switch to new buffer
67-
mUnconsumed.clear();
68-
reset();
69-
mBytes = mCurrentBuffer;
90+
if (!nextHeader()) {
91+
return false;
7092
}
71-
mRDH = reinterpret_cast<const header::RAWDataHeader*>(&mBytes[mNextHeaderIndex]);
72-
mEndOfPayloadIndex = mNextHeaderIndex + (mRDH->memorySize / mElementSizeInBytes);
73-
// Go to end of header, i.e. beginning of payload
74-
mElementIndex = mNextHeaderIndex + (mRDH->headerSize / mElementSizeInBytes);
75-
mNextHeaderIndex += mRDH->offsetToNext / mElementSizeInBytes;
76-
mBitIndex = 0;
7793
}
78-
7994
return true;
8095
}
8196

@@ -84,6 +99,7 @@ void RawBuffer<T>::reset()
8499
{
85100
/// Rewind bytes
86101
mElementIndex = 0;
102+
mHeaderIndex = 0;
87103
mNextHeaderIndex = 0;
88104
mEndOfPayloadIndex = 0;
89105
mBitIndex = 0;
@@ -92,21 +108,23 @@ void RawBuffer<T>::reset()
92108
}
93109

94110
template <typename T>
95-
void RawBuffer<T>::setBuffer(gsl::span<const T> bytes, bool keepUnconsumed)
111+
void RawBuffer<T>::setBuffer(gsl::span<const T> bytes, ResetMode resetMode)
96112
{
97113
/// Sets the buffer and reset the internal indexes
98-
if (keepUnconsumed && !mUnconsumed.empty()) {
114+
if (resetMode == ResetMode::keepUnconsumed && !mUnconsumed.empty()) {
99115
// There are some unconsumed bytes from the previous buffer
100-
mNextHeaderIndex = mUnconsumed.size();
101-
mEndOfPayloadIndex -= mElementIndex;
102-
mElementIndex = 0;
116+
mNextHeaderIndex -= mHeaderIndex;
117+
mEndOfPayloadIndex -= mHeaderIndex;
118+
mElementIndex -= mHeaderIndex;
119+
mHeaderIndex = 0;
103120
mBytes = gsl::span<const T>(mUnconsumed);
104121
} else {
105122
mBytes = bytes;
106-
reset();
123+
if (resetMode != ResetMode::bufferOnly) {
124+
reset();
125+
}
107126
}
108127
mCurrentBuffer = bytes;
109-
nextPayload();
110128
}
111129

112130
template <typename T>
@@ -144,29 +162,16 @@ bool RawBuffer<T>::hasNext(unsigned int nBytes)
144162
// With lot of memory left in the buffer but no payload
145163
nextPayload();
146164
bool isOk = mCurrentBuffer.size() + mUnconsumed.size() - mNextHeaderIndex + mEndOfPayloadIndex - mElementIndex >= nBytes / mElementSizeInBytes;
147-
if (!isOk) {
165+
if (!isOk && mElementIndex != mCurrentBuffer.size()) {
148166
// Store the remaining bits for further use
149-
// We need to do it here because we know that the vector of which the mBytes is just a spas, is valid
150-
// If we do it in set buffer, this might not be the case anymore
151-
std::copy(mBytes.begin() + mElementIndex, mBytes.end(), std::back_inserter(mUnconsumed));
167+
// We need to do it here because the vector of which the mBytes is just a span might not be valid afterwards
168+
// (e.g. when we do the next setBuffer)
169+
// If we do not want to invalidate the mRDH pointer, we need to copy bytes from the last header
170+
mUnconsumed.insert(mUnconsumed.end(), mBytes.begin() + mHeaderIndex, mBytes.end());
152171
}
153172
return isOk;
154173
}
155174

156-
template <typename T>
157-
bool RawBuffer<T>::nextHeader(gsl::span<const T> bytes)
158-
{
159-
/// Go to next header
160-
/// This is only useful when one reads from file
161-
/// and wants to read up to the next header to find out how many bytes to read next
162-
mBytes = bytes;
163-
if (mElementIndex >= mBytes.size()) {
164-
reset();
165-
}
166-
mEndOfPayloadIndex = mElementIndex;
167-
return nextPayload();
168-
}
169-
170175
template class RawBuffer<raw::RawUnit>;
171176
template class RawBuffer<uint8_t>;
172177

Detectors/MUON/MID/Raw/src/RawFileReader.cxx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ void RawFileReader<T>::clear()
5353
{
5454
/// Clears the bytes and counters
5555
mBytes.clear();
56+
mBuffer.setBuffer(mBytes, RawBuffer<T>::ResetMode::all);
5657
mHBCounters.fill(0);
5758
}
5859

@@ -136,22 +137,25 @@ bool RawFileReader<T>::readHB(bool sendCompleteHBs)
136137
}
137138
replaceRDH(headerIndex);
138139
// We use the buffer only to correctly initialize the RDH
139-
mBuffer.nextHeader(mBytes);
140+
mBuffer.setBuffer(mBytes, RawBuffer<T>::ResetMode::bufferOnly);
141+
mBuffer.nextHeader();
140142
isHBClosed = mBuffer.isHBClosed();
141143
gbtId = mBuffer.getRDH()->feeId;
142-
// CAVEAT: do not call mBuffer.getRDH() beyond this line
143-
// To save memory/CPU time, the RawBuffer does not hold a copy of the buffer,
144-
// but just a span of it.
145-
// If we add bytes to mBytes, the vector can go beyond the capacity
146-
// and the memory is re-allocated.
147-
// If this happens, the span is no longer valid, and we can no longer
148-
// call mBuffer.getRDH() until we pass it mBytes again
149144
if (gbtId >= crateparams::sNGBTs) {
150145
// FIXME: this is a problem of the header of some test files
151146
gbtId = 0;
152147
}
153148
if (mBuffer.getRDH()->offsetToNext > raw::sHeaderSizeInBytes) {
154149
read(mBuffer.getRDH()->offsetToNext - raw::sHeaderSizeInBytes);
150+
// CAVEAT: to save memory / CPU time, the RawBuffer does not hold a copy of the buffer,
151+
// but just a span of it.
152+
// If we add bytes to mBytes, the vector can go beyond the capacity
153+
// and the memory is re-allocated.
154+
// If this happens, the span is no longer valid, and we can no longer
155+
// call mBuffer.getRDH() until we pass it mBytes again
156+
// To do so, you need to call:
157+
// mBuffer.setBuffer(mBytes, RawBuffer<T>::ResetMode::bufferOnly);
158+
// mBuffer.nextHeader();
155159
}
156160
if (!sendCompleteHBs) {
157161
break;

0 commit comments

Comments
 (0)