1 #ifndef artdaq_core_Data_Fragment_hh
2 #define artdaq_core_Data_Fragment_hh
16 #include "artdaq-core/Data/detail/RawFragmentHeader.hh"
17 #include "artdaq-core/Data/dictionarycontrol.hh"
20 # include "QuickVec.hh"
21 # define DATAVEC_T QuickVec<RawDataType>
23 typedef detail::RawFragmentHeader::RawDataType RawDataType;
26 bool fragmentSequenceIDCompare(Fragment i, Fragment j);
28 std::ostream & operator<<(std::ostream & os, Fragment
const & f);
40 typedef uint8_t byte_t;
52 typedef detail::RawFragmentHeader::version_t version_t;
53 typedef detail::RawFragmentHeader::type_t type_t;
54 typedef detail::RawFragmentHeader::sequence_id_t sequence_id_t;
55 typedef detail::RawFragmentHeader::fragment_id_t fragment_id_t;
56 typedef detail::RawFragmentHeader::timestamp_t timestamp_t;
58 static constexpr version_t InvalidVersion =
59 detail::RawFragmentHeader::InvalidVersion;
60 static constexpr sequence_id_t InvalidSequenceID =
61 detail::RawFragmentHeader::InvalidSequenceID;
62 static constexpr fragment_id_t InvalidFragmentID =
63 detail::RawFragmentHeader::InvalidFragmentID;
64 static constexpr timestamp_t InvalidTimestamp =
65 detail::RawFragmentHeader::InvalidTimestamp;
67 static constexpr type_t InvalidFragmentType =
68 detail::RawFragmentHeader::InvalidFragmentType;
69 static constexpr type_t EndOfDataFragmentType =
70 detail::RawFragmentHeader::EndOfDataFragmentType;
71 static constexpr type_t DataFragmentType =
72 detail::RawFragmentHeader::DataFragmentType;
73 static constexpr type_t InitFragmentType =
74 detail::RawFragmentHeader::InitFragmentType;
75 static constexpr type_t EndOfRunFragmentType =
76 detail::RawFragmentHeader::EndOfRunFragmentType;
77 static constexpr type_t EndOfSubrunFragmentType =
78 detail::RawFragmentHeader::EndOfSubrunFragmentType;
79 static constexpr type_t ShutdownFragmentType =
80 detail::RawFragmentHeader::ShutdownFragmentType;
81 static constexpr type_t FirstUserFragmentType =
82 detail::RawFragmentHeader::FIRST_USER_TYPE;
83 static constexpr type_t EmptyFragmentType =
84 detail::RawFragmentHeader::EmptyFragmentType;
85 static constexpr type_t ContainerFragmentType =
86 detail::RawFragmentHeader::ContainerFragmentType;
88 static constexpr
bool isUserFragmentType(type_t fragmentType);
89 static constexpr
bool isSystemFragmentType(type_t fragmentType);
90 static std::map<type_t, std::string> MakeSystemTypeMap()
92 return detail::RawFragmentHeader::MakeSystemTypeMap();
95 typedef DATAVEC_T::reference reference;
96 typedef DATAVEC_T::iterator iterator;
97 typedef DATAVEC_T::const_iterator const_iterator;
98 typedef DATAVEC_T::value_type value_type;
99 typedef DATAVEC_T::difference_type difference_type;
100 typedef DATAVEC_T::size_type size_type;
110 static std::unique_ptr<Fragment> FragmentBytes(std::size_t nbytes) {
111 RawDataType nwords = ceil(nbytes / static_cast<double>(
sizeof(RawDataType)));
112 return std::unique_ptr<Fragment>(
new Fragment(nwords));
119 Fragment(std::size_t payload_size, sequence_id_t sequence_id,
120 fragment_id_t fragment_id, type_t type,
const T & metadata,
121 timestamp_t timestamp = Fragment::InvalidTimestamp);
128 static std::unique_ptr<Fragment> FragmentBytes(std::size_t payload_size_in_bytes,
129 sequence_id_t sequence_id,
130 fragment_id_t fragment_id,
131 type_t type,
const T & metadata,
132 timestamp_t timestamp = Fragment::InvalidTimestamp) {
133 RawDataType nwords = ceil(payload_size_in_bytes /
134 static_cast<double>(
sizeof(RawDataType)));
135 return std::unique_ptr<Fragment>(
new Fragment(nwords, sequence_id, fragment_id, type, metadata, timestamp));
140 Fragment(sequence_id_t sequenceID,
141 fragment_id_t fragID,
142 type_t type = Fragment::DataFragmentType,
143 timestamp_t timestamp = Fragment::InvalidTimestamp);
146 void print(std::ostream & os)
const;
149 std::size_t size()
const;
150 version_t version()
const;
152 sequence_id_t sequenceID()
const;
153 fragment_id_t fragmentID()
const;
154 timestamp_t timestamp()
const;
157 void setVersion(version_t version);
158 void setUserType(type_t type);
159 void setSystemType(type_t type);
160 void setSequenceID(sequence_id_t sequence_id);
161 void setFragmentID(fragment_id_t fragment_id);
162 void setTimestamp(timestamp_t timestamp);
165 std::size_t sizeBytes()
const {
return sizeof(RawDataType) * size(); }
169 std::size_t dataSize()
const;
172 std::size_t dataSizeBytes()
const {
173 return sizeof(RawDataType) * dataSize();
177 bool hasMetadata()
const;
181 template <
class T> T * metadata();
182 template <
class T> T
const * metadata()
const;
187 template <
class T>
void setMetadata(
const T & md);
190 template <
class T>
void updateMetadata(
const T & md);
193 void resize(std::size_t sz);
194 void resize(std::size_t sz, RawDataType v);
200 void resizeBytes(std::size_t szbytes);
201 void resizeBytes(std::size_t szbytes, byte_t v);
207 iterator dataBegin();
228 template <
typename T>
229 T reinterpret_cast_checked(
const RawDataType* in)
const {
230 T newpointer =
reinterpret_cast<T
>(in);
232 if (static_cast<const void*>(newpointer) !=
static_cast<const void*
>(in)) {
233 throw cet::exception(
"Error in Fragment.hh: reinterpret_cast failed to return expected address-- please contact John Freeman at jcfree@fnal.gov");
240 template <
typename T>
241 T reinterpret_cast_checked(RawDataType* in) {
242 T newpointer =
reinterpret_cast<T
>(in);
244 if (static_cast<void*>(newpointer) !=
static_cast<void*
>(in)) {
245 throw cet::exception(
"Error in Fragment.hh: reinterpret_cast failed to return expected address-- please contact John Freeman at jcfree@fnal.gov");
257 byte_t* dataBeginBytes() {
return reinterpret_cast_checked<byte_t*>(&* dataBegin()); }
258 byte_t* dataEndBytes() {
return reinterpret_cast_checked<byte_t*>(&* dataEnd()); }
262 iterator headerBegin();
265 byte_t* headerBeginBytes() {
return reinterpret_cast_checked<byte_t*>(&* headerBegin()); }
268 const_iterator dataBegin()
const;
269 const_iterator dataEnd()
const;
271 const byte_t* dataBeginBytes()
const {
272 return reinterpret_cast_checked<const byte_t*>(&* dataBegin());
275 const byte_t* dataEndBytes()
const {
276 return reinterpret_cast_checked<const byte_t*>(&* dataEnd());
280 const_iterator headerBegin()
const;
282 const byte_t* headerBeginBytes()
const {
283 return reinterpret_cast_checked<const byte_t*>(&* headerBegin());
289 void reserve(std::size_t cap);
290 void swap(Fragment & other);
291 void swap(DATAVEC_T & other) { vals_.swap(other); };
293 RawDataType * dataAddress();
294 RawDataType * metadataAddress();
295 RawDataType * headerAddress();
297 static std::unique_ptr<Fragment> eodFrag(
size_t nFragsToExpect);
300 template <
class InputIterator>
303 dataFrag(sequence_id_t sequenceID,
304 fragment_id_t fragID,
310 dataFrag(sequence_id_t sequenceID,
311 fragment_id_t fragID,
312 RawDataType
const * dataPtr,
314 timestamp_t timestamp = Fragment::InvalidTimestamp);
318 template <
typename T>
static std::size_t validatedMetadataSize_();
319 void updateFragmentHeaderWC_();
324 detail::RawFragmentHeader * fragmentHeader();
325 detail::RawFragmentHeader
const * fragmentHeader()
const;
335 inline artdaq::Fragment& artdaq::Fragment::operator=(artdaq::Fragment&&) noexcept = default;
341 isUserFragmentType(type_t fragmentType)
343 return fragmentType >= detail::RawFragmentHeader::FIRST_USER_TYPE &&
344 fragmentType <= detail::RawFragmentHeader::LAST_USER_TYPE;
351 isSystemFragmentType(type_t fragmentType)
353 return fragmentType >= detail::RawFragmentHeader::FIRST_SYSTEM_TYPE;
359 validatedMetadataSize_()
364 static_assert(
sizeof(
size_t) >=
365 sizeof(decltype(std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max())),
366 "metadata_word_count_t is too big!");
368 static size_t constexpr max_md_wc =
369 std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max();
370 size_t requested_md_wc =
371 std::ceil(
sizeof(T) / static_cast<double>(
sizeof(artdaq::RawDataType)));
372 if (requested_md_wc > max_md_wc) {
373 throw cet::exception(
"InvalidRequest")
374 <<
"The requested metadata structure is too large: "
375 <<
"requested word count = " << requested_md_wc
376 <<
", maximum word count = " << max_md_wc;
378 return requested_md_wc;
383 Fragment(std::size_t payload_size, sequence_id_t sequence_id,
384 fragment_id_t fragment_id,
385 type_t type,
const T & metadata, timestamp_t timestamp) :
386 vals_((artdaq::detail::RawFragmentHeader::num_words() +
387 validatedMetadataSize_<T>() +
391 updateFragmentHeaderWC_();
392 fragmentHeader()->sequence_id = sequence_id;
393 fragmentHeader()->fragment_id = fragment_id;
394 fragmentHeader()->timestamp = timestamp;
395 fragmentHeader()->type = type;
397 fragmentHeader()->metadata_word_count =
399 (artdaq::detail::RawFragmentHeader::num_words() + payload_size);
401 memcpy(metadataAddress(), &metadata,
sizeof(T));
406 artdaq::Fragment::size()
const
408 return fragmentHeader()->word_count;
412 artdaq::Fragment::version_t
413 artdaq::Fragment::version()
const
415 return fragmentHeader()->version;
419 artdaq::Fragment::type_t
420 artdaq::Fragment::type()
const
422 return static_cast<type_t
>(fragmentHeader()->type);
426 artdaq::Fragment::sequence_id_t
427 artdaq::Fragment::sequenceID()
const
429 return fragmentHeader()->sequence_id;
433 artdaq::Fragment::fragment_id_t
434 artdaq::Fragment::fragmentID()
const
436 return fragmentHeader()->fragment_id;
440 artdaq::Fragment::timestamp_t
441 artdaq::Fragment::timestamp()
const
443 return fragmentHeader()->timestamp;
448 artdaq::Fragment::setVersion(version_t version)
450 fragmentHeader()->version = version;
455 artdaq::Fragment::setUserType(type_t type)
457 fragmentHeader()->setUserType(static_cast<uint8_t>(type));
462 artdaq::Fragment::setSystemType(type_t type)
464 fragmentHeader()->setSystemType(static_cast<uint8_t>(type));
469 artdaq::Fragment::setSequenceID(sequence_id_t sequence_id)
471 assert(sequence_id <= detail::RawFragmentHeader::InvalidSequenceID);
472 fragmentHeader()->sequence_id = sequence_id;
477 artdaq::Fragment::setFragmentID(fragment_id_t fragment_id)
479 fragmentHeader()->fragment_id = fragment_id;
484 artdaq::Fragment::setTimestamp(timestamp_t timestamp)
486 fragmentHeader()->timestamp = timestamp;
491 artdaq::Fragment::updateFragmentHeaderWC_()
495 assert(vals_.size() < (1ULL << 32));
496 fragmentHeader()->word_count = vals_.size();
501 artdaq::Fragment::dataSize()
const
503 return vals_.size() - detail::RawFragmentHeader::num_words() -
504 fragmentHeader()->metadata_word_count;
509 artdaq::Fragment::hasMetadata()
const
511 return fragmentHeader()->metadata_word_count != 0;
516 artdaq::Fragment::metadata()
518 if (fragmentHeader()->metadata_word_count == 0) {
519 throw cet::exception(
"InvalidRequest")
520 <<
"No metadata has been stored in this Fragment.";
523 return reinterpret_cast_checked<T *>
524 (&vals_[detail::RawFragmentHeader::num_words()]);
529 artdaq::Fragment::metadata()
const
531 if (fragmentHeader()->metadata_word_count == 0) {
532 throw cet::exception(
"InvalidRequest")
533 <<
"No metadata has been stored in this Fragment.";
535 return reinterpret_cast_checked<T const *>
536 (&vals_[detail::RawFragmentHeader::num_words()]);
541 artdaq::Fragment::setMetadata(
const T & metadata)
543 if (fragmentHeader()->metadata_word_count != 0) {
544 throw cet::exception(
"InvalidRequest")
545 <<
"Metadata has already been stored in this Fragment.";
547 auto const mdSize = validatedMetadataSize_<T>();
548 vals_.insert(dataBegin(), mdSize, 0);
549 updateFragmentHeaderWC_();
550 fragmentHeader()->metadata_word_count = mdSize;
552 memcpy(metadataAddress(), &metadata,
sizeof(T));
557 artdaq::Fragment::updateMetadata(
const T & metadata)
559 if (fragmentHeader()->metadata_word_count == 0) {
560 throw cet::exception(
"InvalidRequest")
561 <<
"No metadata in fragment; please use Fragment::setMetadata instead of Fragment::updateMetadata";
564 auto const mdSize = validatedMetadataSize_<T>();
566 if (fragmentHeader()->metadata_word_count != mdSize) {
567 throw cet::exception(
"InvalidRequest")
568 <<
"Mismatch between type of metadata struct passed to updateMetadata and existing metadata struct";
571 memcpy(metadataAddress(), &metadata,
sizeof(T));
575 artdaq::Fragment::resize(std::size_t sz)
577 vals_.resize(sz + fragmentHeader()->metadata_word_count +
578 detail::RawFragmentHeader::num_words());
579 updateFragmentHeaderWC_();
583 artdaq::Fragment::resize(std::size_t sz, RawDataType v)
585 vals_.resize(sz + fragmentHeader()->metadata_word_count +
586 detail::RawFragmentHeader::num_words(), v);
587 updateFragmentHeaderWC_();
591 artdaq::Fragment::resizeBytes(std::size_t szbytes)
593 RawDataType nwords = ceil(szbytes / static_cast<double>(
sizeof(RawDataType)));
598 artdaq::Fragment::resizeBytes(std::size_t szbytes, byte_t v)
600 RawDataType defaultval;
601 byte_t* ptr = reinterpret_cast_checked<byte_t*>(&defaultval);
603 for (uint8_t i = 0; i <
sizeof(RawDataType); ++i) {
608 RawDataType nwords = ceil(szbytes / static_cast<double>(
sizeof(RawDataType)));
610 resize(nwords, defaultval);
616 artdaq::Fragment::autoResize()
618 vals_.resize(fragmentHeader()->word_count);
619 updateFragmentHeaderWC_();
623 artdaq::Fragment::iterator
624 artdaq::Fragment::dataBegin()
626 return vals_.begin() + detail::RawFragmentHeader::num_words() +
627 fragmentHeader()->metadata_word_count;
631 artdaq::Fragment::iterator
632 artdaq::Fragment::dataEnd()
638 artdaq::Fragment::iterator
639 artdaq::Fragment::headerBegin()
641 return vals_.begin();
645 artdaq::Fragment::const_iterator
646 artdaq::Fragment::dataBegin()
const
648 return vals_.begin() + detail::RawFragmentHeader::num_words() +
649 fragmentHeader()->metadata_word_count;
653 artdaq::Fragment::const_iterator
654 artdaq::Fragment::dataEnd()
const
660 artdaq::Fragment::const_iterator
661 artdaq::Fragment::headerBegin()
const
663 return vals_.begin();
669 artdaq::Fragment::clear()
671 vals_.erase(dataBegin(), dataEnd());
672 updateFragmentHeaderWC_();
677 artdaq::Fragment::empty()
679 return (vals_.size() - detail::RawFragmentHeader::num_words() -
680 fragmentHeader()->metadata_word_count) == 0;
685 artdaq::Fragment::reserve(std::size_t cap)
687 vals_.reserve(cap + detail::RawFragmentHeader::num_words() +
688 fragmentHeader()->metadata_word_count);
693 artdaq::Fragment::swap(Fragment & other)
695 vals_.swap(other.vals_);
699 artdaq::RawDataType *
700 artdaq::Fragment::dataAddress()
702 return &vals_[0] + detail::RawFragmentHeader::num_words() +
703 fragmentHeader()->metadata_word_count;
707 artdaq::RawDataType *
708 artdaq::Fragment::metadataAddress()
710 if (fragmentHeader()->metadata_word_count == 0) {
711 throw cet::exception(
"InvalidRequest")
712 <<
"No metadata has been stored in this Fragment.";
714 return &vals_[0] + detail::RawFragmentHeader::num_words();
718 artdaq::RawDataType *
719 artdaq::Fragment::headerAddress()
725 template <
class InputIterator>
728 dataFrag(sequence_id_t sequenceID,
729 fragment_id_t fragID,
733 Fragment result(sequenceID, fragID);
734 result.vals_.reserve(std::distance(i, e) + detail::RawFragmentHeader::num_words());
735 std::copy(i, e, std::back_inserter(result.vals_));
741 artdaq::Fragment::fragmentHeader()
743 return reinterpret_cast_checked<detail::RawFragmentHeader *>(&vals_[0]);
748 artdaq::Fragment::fragmentHeader()
const
750 return reinterpret_cast_checked<detail::RawFragmentHeader const *>(&vals_[0]);