38#ifndef ALICEO2_FIT_DATABLOCKBASE_H_
39#define ALICEO2_FIT_DATABLOCKBASE_H_
47#include <boost/mpl/inherit.hpp>
48#include <boost/mpl/vector.hpp>
61static constexpr size_t SIZE_WORD = 16;
62static constexpr size_t SIZE_WORD_GBT = 10;
63static constexpr size_t SIZE_MAX_PAGE = 8192;
66template <
bool isPadded = true>
74 template <
typename,
typename =
void>
78 struct CheckTypeMaxNelem<U,
std::enable_if_t<std::is_same<decltype(U::MaxNelements), const std::size_t>::value>> : std::true_type {
81 template <
typename,
typename =
void>
85 struct CheckTypeMinNelem<U,
std::enable_if_t<std::is_same<decltype(U::MinNelements), const std::size_t>::value>> : std::true_type {
88 template <
typename,
typename =
void>
92 struct CheckTypePayloadSize<U,
std::enable_if_t<std::is_same<decltype(U::PayloadSize), const std::size_t>::value>> : std::true_type {
95 template <
typename,
typename =
void>
102 template <
typename,
typename =
void>
105 template <
typename U>
106 struct CheckMaxElemSize<U,
std::enable_if_t<((T::MaxNelements * T::PayloadSize <= SIZE_MAX_PAYLOAD) && (T::MaxNelements * T::PayloadPerGBTword <= SIZE_MAX_PAYLOAD))>> : std::true_type {
109 template <typename, typename = void>
110 struct CheckNelemRange : std::false_type {
112 template <typename U>
113 struct CheckNelemRange<U, std::enable_if_t<(T::MaxNelements >= T::MinNelements)>> : std::true_type {
123 static_assert(
CheckNelemRange<T>::value,
"Error! Check range for number of elements, max should be bigger or equal to min!");
128template <typename ConfigType, typename T, typename = typename std::enable_if_t<DataBlockHelper<T>::check()>>
134 constexpr static bool sIsPadded = Config_t::sIsPadded;
137 if constexpr (sIsPadded) {
140 return SIZE_WORD_GBT;
144 constexpr static std::size_t sSizeWord = getWordSize();
145 void serialize(std::vector<char>& vecBytes,
size_t nWords,
size_t& destPos)
const
147 const auto nBytesToWrite = nWords * sSizeWord;
148 if ((vecBytes.size() - destPos) < nBytesToWrite || nWords < MinNwords || nWords > MaxNwords) {
149 LOG(info) <<
"Warning! Incorrect serialisation procedure!";
151 }
else if (nWords == 0) {
155 const uint8_t* srcAddress = (uint8_t*)mData;
156 gsl::span<char> serializedBytes(vecBytes);
157 if constexpr (sIsPadded) {
158 int nSteps = std::get<kNSTEPS>(sReadingLookupTable[nWords]);
159 for (
int iStep = 0; iStep < nSteps; iStep++) {
160 memcpy(serializedBytes.data() + std::get<kSRCBYTEPOS>(sByteLookupTable[iStep]) + destPos, srcAddress + std::get<kDESTBYTEPOS>(sByteLookupTable[iStep]), std::get<kNBYTES>(sByteLookupTable[iStep]));
163 memcpy(serializedBytes.data() + destPos, srcAddress, nBytesToWrite);
165 destPos += nBytesToWrite;
168 void deserialize(
const gsl::span<const uint8_t> inputBytes,
size_t nWords,
size_t& srcPos)
171 const auto nBytesToRead = nWords * sSizeWord;
172 if ((inputBytes.size() - srcPos) < nBytesToRead || nWords < MinNwords || nWords > MaxNwords) {
174 LOG(error) <<
"Incomplete payload! |N GBT words " << nWords <<
" |bytes to read " << nBytesToRead <<
" |src pos " << srcPos <<
" |payload size " << inputBytes.size() <<
" |";
175 srcPos = inputBytes.size();
180 uint8_t* destAddress = (uint8_t*)mData;
181 mNelements = std::get<kNELEMENTS>(sReadingLookupTable[nWords]);
182 if constexpr (sIsPadded) {
183 int nSteps = std::get<kNSTEPS>(sReadingLookupTable[nWords]);
184 for (
int iStep = 0; iStep < nSteps; iStep++) {
185 memcpy(destAddress + std::get<kDESTBYTEPOS>(sByteLookupTable[iStep]), inputBytes.data() + std::get<kSRCBYTEPOS>(sByteLookupTable[iStep]) + srcPos, std::get<kNBYTES>(sByteLookupTable[iStep]));
188 memcpy(destAddress, inputBytes.data() + srcPos, nBytesToRead);
190 srcPos += nBytesToRead;
193 static constexpr int MaxNwords = Data_t::PayloadSize * Data_t::MaxNelements / Data_t::PayloadPerGBTword + (Data_t::PayloadSize * Data_t::MaxNelements % Data_t::PayloadPerGBTword > 0);
194 static constexpr int MaxNbytes = SIZE_WORD * MaxNwords;
196 static constexpr int MinNwords = Data_t::PayloadSize * Data_t::MinNelements / Data_t::PayloadPerGBTword + (Data_t::PayloadSize * Data_t::MinNelements % Data_t::PayloadPerGBTword > 0);
197 static constexpr int MinNbytes = SIZE_WORD * MinNwords;
203 size_t payloadFull = Data_t::MaxNelements * Data_t::PayloadSize;
204 size_t payloadInWord = Data_t::PayloadPerGBTword;
205 size_t payloadPerElem = Data_t::PayloadSize;
206 while (payloadFull > 0) {
207 if (payloadPerElem < payloadInWord) {
209 payloadFull -= payloadPerElem;
210 payloadInWord -= payloadPerElem;
214 payloadFull -= payloadInWord;
215 payloadPerElem -= payloadInWord;
218 if (payloadInWord == 0) {
219 payloadInWord = Data_t::PayloadPerGBTword;
221 if (payloadPerElem == 0) {
222 payloadPerElem = Data_t::PayloadSize;
240 static constexpr std::array<std::tuple<size_t, size_t, size_t, int, int>, getNsteps()>
GetByteLookupTable()
242 std::array<std::tuple<size_t, size_t, size_t, int, int>, getNsteps()> seqBytes{};
244 int countElement = 0;
246 size_t destBytePosPerElem = 0;
247 size_t srcBytePos = 0;
248 size_t payloadFull = Data_t::MaxNelements * Data_t::PayloadSize;
250 size_t bytesInWord = SIZE_WORD;
251 size_t payloadInWord = Data_t::PayloadPerGBTword;
253 size_t payloadPerElem = Data_t::PayloadSize;
255 uint64_t indexElem = 0;
256 uint64_t indexLastElem = Data_t::MaxNelements - 1;
258 while (payloadFull > 0) {
259 if (payloadPerElem < payloadInWord) {
260 std::get<kNBYTES>(seqBytes[
count]) = payloadPerElem;
261 std::get<kSRCBYTEPOS>(seqBytes[
count]) = srcBytePos;
262 std::get<kDESTBYTEPOS>(seqBytes[
count]) = destBytePosPerElem;
263 std::get<kELEMENTINDEX>(seqBytes[
count]) = countElement;
264 std::get<kWORDINDEX>(seqBytes[
count]) = countWord;
265 srcBytePos += payloadPerElem;
267 payloadFull -= payloadPerElem;
268 payloadInWord -= payloadPerElem;
269 bytesInWord -= payloadPerElem;
273 std::get<kNBYTES>(seqBytes[
count]) = payloadInWord;
274 std::get<kSRCBYTEPOS>(seqBytes[
count]) = srcBytePos;
275 std::get<kDESTBYTEPOS>(seqBytes[
count]) = destBytePosPerElem;
276 std::get<kELEMENTINDEX>(seqBytes[
count]) = countElement;
277 std::get<kWORDINDEX>(seqBytes[
count]) = countWord;
278 srcBytePos += bytesInWord;
280 destBytePosPerElem += payloadInWord;
282 payloadFull -= payloadInWord;
283 payloadPerElem -= payloadInWord;
288 if (payloadInWord == 0) {
289 payloadInWord = Data_t::PayloadPerGBTword;
291 if (payloadPerElem == 0) {
292 payloadPerElem = Data_t::PayloadSize;
294 destBytePosPerElem = countElement *
sizeof(T);
296 if (bytesInWord == 0) {
297 bytesInWord = SIZE_WORD;
303 static constexpr std::array<std::tuple<size_t, size_t, size_t, int, int>, getNsteps()> sByteLookupTable = GetByteLookupTable();
315 std::array<std::tuple<unsigned int, unsigned int, bool>, MaxNwords + 1> readingScheme{};
316 size_t payloadPerElem = Data_t::PayloadSize;
317 std::get<kNSTEPS>(readingScheme[0]) = 0;
318 std::get<kNELEMENTS>(readingScheme[0]) = 0;
319 std::get<kISPARTED>(readingScheme[0]) =
false;
321 for (
int iStep = 0; iStep < getNsteps(); iStep++) {
322 if (countWord - 1 < std::get<kWORDINDEX>((GetByteLookupTable())[iStep])) {
323 std::get<kNSTEPS>(readingScheme[countWord]) = iStep;
324 std::get<kNELEMENTS>(readingScheme[countWord]) = std::get<kELEMENTINDEX>((GetByteLookupTable())[iStep]);
325 if (payloadPerElem > 0) {
326 std::get<kISPARTED>(readingScheme[countWord]) =
true;
328 std::get<kISPARTED>(readingScheme[countWord]) =
false;
332 if (payloadPerElem == 0) {
333 payloadPerElem = Data_t::PayloadSize;
335 payloadPerElem -= std::get<kNBYTES>((GetByteLookupTable())[iStep]);
338 std::get<kNSTEPS>(readingScheme[countWord]) = getNsteps();
339 if (payloadPerElem > 0) {
340 std::get<kISPARTED>(readingScheme[countWord]) =
true;
341 std::get<kNELEMENTS>(readingScheme[countWord]) = std::get<kELEMENTINDEX>((GetByteLookupTable())[getNsteps() - 1]);
343 std::get<kISPARTED>(readingScheme[countWord]) =
false;
344 std::get<kNELEMENTS>(readingScheme[countWord]) = std::get<kELEMENTINDEX>((GetByteLookupTable())[getNsteps() - 1]) + 1;
346 return readingScheme;
348 static constexpr std::array<std::tuple<unsigned int, unsigned int, bool>, MaxNwords + 1> sReadingLookupTable = GetReadingLookupTable();
353 LOG(info) <<
"-------------------------------------------";
354 LOG(info) <<
"kNELEMENTS|kNSTEPS|kISPARTED";
355 for (
int i = 0;
i < MaxNwords + 1;
i++) {
356 LOG(info) << std::get<kNELEMENTS>(sReadingLookupTable[
i]) <<
"|"
357 << std::get<kNSTEPS>(sReadingLookupTable[
i]) <<
"|"
358 << std::get<kISPARTED>(sReadingLookupTable[
i]);
360 LOG(info) <<
"-------------------------------------------";
361 LOG(info) <<
"kELEMENTINDEX|kWORDINDEX|kNBYTES|kSRCBYTEPOS|kDESTBYTEPOS";
362 for (
int i = 0;
i < getNsteps();
i++) {
363 LOG(info) << std::get<kELEMENTINDEX>(sByteLookupTable[
i]) <<
"|"
364 << std::get<kWORDINDEX>(sByteLookupTable[
i]) <<
"|"
365 << std::get<kNBYTES>(sByteLookupTable[
i]) <<
"|"
366 << std::get<kSRCBYTEPOS>(sByteLookupTable[
i]) <<
"|"
367 << std::get<kDESTBYTEPOS>(sByteLookupTable[
i]);
372 assert(mNelements <= Data_t::MaxNelements);
373 for (
int i = 0;
i < mNelements;
i++) {
374 LOG(info) <<
"Printing element number: " <<
i;
385template <
template <
typename...>
class DataBlock,
typename ConfigType,
class Header,
class... DataStructures>
386class DataBlockBase :
public boost::mpl::inherit<DataBlockWrapper<ConfigType, Header>, DataBlockWrapper<ConfigType, DataStructures>...>
::type
414 LOG(info) <<
"HEADER";
434 size_t bytePos = srcPos;
435 static_cast<DataBlock_t*
>(
this)->deserialize(payload, bytePos);
436 mSize = bytePos - srcPos;
461 void mergeStatusBits(uint8_t& statusBitsResult, uint8_t statusBits) { statusBitsResult |= statusBits; }
DataBlock< typename Config_t::InvertedPadding_t, Header, DataStructures... > DataBlockInvertedPadding_t
static constexpr std::size_t sHeaderSize
RawDataMetric::Status_t mStatusBitsAll
static constexpr bool sIsPadded
void decodeBlock(gsl::span< const uint8_t > payload, size_t srcPos)
DataBlockWrapper< ConfigType, Header > DataBlockWrapperHeader_t
DataBlock< ConfigType, Header, DataStructures... > DataBlock_t
InteractionRecord getInteractionRecord() const
void mergeStatusBits(uint8_t &statusBitsResult, uint8_t statusBits)
bool isOnlyHeader() const
void setInteractionRecord(const InteractionRecord &intRec)
void isNonZeroBlockSizes(bool &flag, unsigned int nElements)
DataBlockBase(const DataBlockBase &)=default
void checkDeserialization(bool &flag, bool isIncorrect)
GLint GLint GLsizei GLint GLenum GLenum type
TFitResultPtr fit(const size_t nBins, const T *arr, const T xMin, const T xMax, TF1 &func, std::string_view option="")
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Defining DataPointCompositeObject explicitly as copiable.
DataBlockConfig<!sIsPadded > InvertedPadding_t
static constexpr bool sIsPadded
static constexpr bool check()
void deserialize(const gsl::span< const uint8_t > inputBytes, size_t nWords, size_t &srcPos)
static constexpr std::array< std::tuple< size_t, size_t, size_t, int, int >, getNsteps()> GetByteLookupTable()
void serialize(std::vector< char > &vecBytes, size_t nWords, size_t &destPos) const
Data_t mData[Data_t::MaxNelements]
DataBlockWrapper(const DataBlockWrapper &)=default
static constexpr std::array< std::tuple< unsigned int, unsigned int, bool >, MaxNwords+1 > GetReadingLookupTable()
DataBlockWrapper()=default
RawDataMetric::Status_t mStatusBits
static constexpr std::size_t getWordSize()
static constexpr size_t getNsteps()
static void setStatusBit(Status_t &metric, EStatusBits statusBit, bool val=true)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"