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;
44 typedef detail::RawFragmentHeader::version_t version_t;
45 typedef detail::RawFragmentHeader::type_t type_t;
46 typedef detail::RawFragmentHeader::sequence_id_t sequence_id_t;
47 typedef detail::RawFragmentHeader::fragment_id_t fragment_id_t;
48 typedef detail::RawFragmentHeader::timestamp_t timestamp_t;
50 static constexpr version_t InvalidVersion =
51 detail::RawFragmentHeader::InvalidVersion;
52 static constexpr sequence_id_t InvalidSequenceID =
53 detail::RawFragmentHeader::InvalidSequenceID;
54 static constexpr fragment_id_t InvalidFragmentID =
55 detail::RawFragmentHeader::InvalidFragmentID;
56 static constexpr timestamp_t InvalidTimestamp =
57 detail::RawFragmentHeader::InvalidTimestamp;
59 static constexpr type_t InvalidFragmentType =
60 detail::RawFragmentHeader::InvalidFragmentType;
61 static constexpr type_t EndOfDataFragmentType =
62 detail::RawFragmentHeader::EndOfDataFragmentType;
63 static constexpr type_t DataFragmentType =
64 detail::RawFragmentHeader::DataFragmentType;
65 static constexpr type_t InitFragmentType =
66 detail::RawFragmentHeader::InitFragmentType;
67 static constexpr type_t EndOfRunFragmentType =
68 detail::RawFragmentHeader::EndOfRunFragmentType;
69 static constexpr type_t EndOfSubrunFragmentType =
70 detail::RawFragmentHeader::EndOfSubrunFragmentType;
71 static constexpr type_t ShutdownFragmentType =
72 detail::RawFragmentHeader::ShutdownFragmentType;
73 static constexpr type_t FirstUserFragmentType =
74 detail::RawFragmentHeader::FIRST_USER_TYPE;
75 static constexpr type_t EmptyFragmentType =
76 detail::RawFragmentHeader::EmptyFragmentType;
77 static constexpr type_t ContainerFragmentType =
78 detail::RawFragmentHeader::ContainerFragmentType;
80 static constexpr
bool isUserFragmentType(type_t fragmentType);
81 static constexpr
bool isSystemFragmentType(type_t fragmentType);
82 static std::map<type_t, std::string> MakeSystemTypeMap()
84 return detail::RawFragmentHeader::MakeSystemTypeMap();
87 typedef DATAVEC_T::reference reference;
88 typedef DATAVEC_T::iterator iterator;
89 typedef DATAVEC_T::const_iterator const_iterator;
90 typedef DATAVEC_T::value_type value_type;
91 typedef DATAVEC_T::difference_type difference_type;
92 typedef DATAVEC_T::size_type size_type;
102 static std::unique_ptr<Fragment> FragmentBytes(std::size_t nbytes) {
103 RawDataType nwords = ceil(nbytes / static_cast<double>(
sizeof(RawDataType)));
104 return std::unique_ptr<Fragment>(
new Fragment(nwords));
111 Fragment(std::size_t payload_size, sequence_id_t sequence_id,
112 fragment_id_t fragment_id, type_t type,
const T & metadata,
113 timestamp_t timestamp = Fragment::InvalidTimestamp);
120 static std::unique_ptr<Fragment> FragmentBytes(std::size_t payload_size_in_bytes,
121 sequence_id_t sequence_id,
122 fragment_id_t fragment_id,
123 type_t type,
const T & metadata,
124 timestamp_t timestamp = Fragment::InvalidTimestamp) {
125 RawDataType nwords = ceil(payload_size_in_bytes /
126 static_cast<double>(
sizeof(RawDataType)));
127 return std::unique_ptr<Fragment>(
new Fragment(nwords, sequence_id, fragment_id, type, metadata, timestamp));
132 Fragment(sequence_id_t sequenceID,
133 fragment_id_t fragID,
134 type_t type = Fragment::DataFragmentType,
135 timestamp_t timestamp = Fragment::InvalidTimestamp);
138 void print(std::ostream & os)
const;
141 std::size_t size()
const;
142 version_t version()
const;
144 sequence_id_t sequenceID()
const;
145 fragment_id_t fragmentID()
const;
146 timestamp_t timestamp()
const;
149 void setVersion(version_t version);
150 void setUserType(type_t type);
151 void setSystemType(type_t type);
152 void setSequenceID(sequence_id_t sequence_id);
153 void setFragmentID(fragment_id_t fragment_id);
154 void setTimestamp(timestamp_t timestamp);
157 std::size_t sizeBytes()
const {
return sizeof(RawDataType) * size(); }
161 std::size_t dataSize()
const;
164 std::size_t dataSizeBytes()
const {
165 return sizeof(RawDataType) * dataSize();
169 bool hasMetadata()
const;
173 template <
class T> T * metadata();
174 template <
class T> T
const * metadata()
const;
179 template <
class T>
void setMetadata(
const T & md);
182 template <
class T>
void updateMetadata(
const T & md);
185 void resize(std::size_t sz);
186 void resize(std::size_t sz, RawDataType v);
192 void resizeBytes(std::size_t szbytes);
193 void resizeBytes(std::size_t szbytes, byte_t v);
199 iterator dataBegin();
220 template <
typename T>
221 T reinterpret_cast_checked(
const RawDataType* in)
const {
222 T newpointer =
reinterpret_cast<T
>(in);
224 if (static_cast<const void*>(newpointer) !=
static_cast<const void*
>(in)) {
225 throw cet::exception(
"Error in Fragment.hh: reinterpret_cast failed to return expected address-- please contact John Freeman at jcfree@fnal.gov");
232 template <
typename T>
233 T reinterpret_cast_checked(RawDataType* in) {
234 T newpointer =
reinterpret_cast<T
>(in);
236 if (static_cast<void*>(newpointer) !=
static_cast<void*
>(in)) {
237 throw cet::exception(
"Error in Fragment.hh: reinterpret_cast failed to return expected address-- please contact John Freeman at jcfree@fnal.gov");
249 byte_t* dataBeginBytes() {
return reinterpret_cast_checked<byte_t*>(&* dataBegin()); }
250 byte_t* dataEndBytes() {
return reinterpret_cast_checked<byte_t*>(&* dataEnd()); }
254 iterator headerBegin();
257 byte_t* headerBeginBytes() {
return reinterpret_cast_checked<byte_t*>(&* headerBegin()); }
260 const_iterator dataBegin()
const;
261 const_iterator dataEnd()
const;
263 const byte_t* dataBeginBytes()
const {
264 return reinterpret_cast_checked<const byte_t*>(&* dataBegin());
267 const byte_t* dataEndBytes()
const {
268 return reinterpret_cast_checked<const byte_t*>(&* dataEnd());
272 const_iterator headerBegin()
const;
274 const byte_t* headerBeginBytes()
const {
275 return reinterpret_cast_checked<const byte_t*>(&* headerBegin());
281 void reserve(std::size_t cap);
282 void swap(Fragment & other);
283 void swap(DATAVEC_T & other) { vals_.swap(other); };
285 RawDataType * dataAddress();
286 RawDataType * metadataAddress();
287 RawDataType * headerAddress();
289 static std::unique_ptr<Fragment> eodFrag(
size_t nFragsToExpect);
292 template <
class InputIterator>
295 dataFrag(sequence_id_t sequenceID,
296 fragment_id_t fragID,
302 dataFrag(sequence_id_t sequenceID,
303 fragment_id_t fragID,
304 RawDataType
const * dataPtr,
306 timestamp_t timestamp = Fragment::InvalidTimestamp);
310 template <
typename T>
static std::size_t validatedMetadataSize_();
311 void updateFragmentHeaderWC_();
316 detail::RawFragmentHeader * fragmentHeader();
317 detail::RawFragmentHeader
const * fragmentHeader()
const;
326 isUserFragmentType(type_t fragmentType)
328 return fragmentType >= detail::RawFragmentHeader::FIRST_USER_TYPE &&
329 fragmentType <= detail::RawFragmentHeader::LAST_USER_TYPE;
336 isSystemFragmentType(type_t fragmentType)
338 return fragmentType >= detail::RawFragmentHeader::FIRST_SYSTEM_TYPE;
344 validatedMetadataSize_()
349 static_assert(
sizeof(
size_t) >=
350 sizeof(decltype(std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max())),
351 "metadata_word_count_t is too big!");
353 static size_t constexpr max_md_wc =
354 std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max();
355 size_t requested_md_wc =
356 std::ceil(
sizeof(T) / static_cast<double>(
sizeof(artdaq::RawDataType)));
357 if (requested_md_wc > max_md_wc) {
358 throw cet::exception(
"InvalidRequest")
359 <<
"The requested metadata structure is too large: "
360 <<
"requested word count = " << requested_md_wc
361 <<
", maximum word count = " << max_md_wc;
363 return requested_md_wc;
368 Fragment(std::size_t payload_size, sequence_id_t sequence_id,
369 fragment_id_t fragment_id,
370 type_t type,
const T & metadata, timestamp_t timestamp) :
371 vals_((artdaq::detail::RawFragmentHeader::num_words() +
372 validatedMetadataSize_<T>() +
376 updateFragmentHeaderWC_();
377 fragmentHeader()->sequence_id = sequence_id;
378 fragmentHeader()->fragment_id = fragment_id;
379 fragmentHeader()->timestamp = timestamp;
380 fragmentHeader()->type = type;
382 fragmentHeader()->metadata_word_count =
384 (artdaq::detail::RawFragmentHeader::num_words() + payload_size);
386 memcpy(metadataAddress(), &metadata,
sizeof(T));
391 artdaq::Fragment::size()
const
393 return fragmentHeader()->word_count;
397 artdaq::Fragment::version_t
398 artdaq::Fragment::version()
const
400 return fragmentHeader()->version;
404 artdaq::Fragment::type_t
405 artdaq::Fragment::type()
const
407 return static_cast<type_t
>(fragmentHeader()->type);
411 artdaq::Fragment::sequence_id_t
412 artdaq::Fragment::sequenceID()
const
414 return fragmentHeader()->sequence_id;
418 artdaq::Fragment::fragment_id_t
419 artdaq::Fragment::fragmentID()
const
421 return fragmentHeader()->fragment_id;
425 artdaq::Fragment::timestamp_t
426 artdaq::Fragment::timestamp()
const
428 return fragmentHeader()->timestamp;
433 artdaq::Fragment::setVersion(version_t version)
435 fragmentHeader()->version = version;
440 artdaq::Fragment::setUserType(type_t type)
442 fragmentHeader()->setUserType(static_cast<uint8_t>(type));
447 artdaq::Fragment::setSystemType(type_t type)
449 fragmentHeader()->setSystemType(static_cast<uint8_t>(type));
454 artdaq::Fragment::setSequenceID(sequence_id_t sequence_id)
456 assert(sequence_id <= detail::RawFragmentHeader::InvalidSequenceID);
457 fragmentHeader()->sequence_id = sequence_id;
462 artdaq::Fragment::setFragmentID(fragment_id_t fragment_id)
464 fragmentHeader()->fragment_id = fragment_id;
469 artdaq::Fragment::setTimestamp(timestamp_t timestamp)
471 fragmentHeader()->timestamp = timestamp;
476 artdaq::Fragment::updateFragmentHeaderWC_()
480 assert(vals_.size() < (1ULL << 32));
481 fragmentHeader()->word_count = vals_.size();
486 artdaq::Fragment::dataSize()
const
488 return vals_.size() - detail::RawFragmentHeader::num_words() -
489 fragmentHeader()->metadata_word_count;
494 artdaq::Fragment::hasMetadata()
const
496 return fragmentHeader()->metadata_word_count != 0;
501 artdaq::Fragment::metadata()
503 if (fragmentHeader()->metadata_word_count == 0) {
504 throw cet::exception(
"InvalidRequest")
505 <<
"No metadata has been stored in this Fragment.";
508 return reinterpret_cast_checked<T *>
509 (&vals_[detail::RawFragmentHeader::num_words()]);
514 artdaq::Fragment::metadata()
const
516 if (fragmentHeader()->metadata_word_count == 0) {
517 throw cet::exception(
"InvalidRequest")
518 <<
"No metadata has been stored in this Fragment.";
520 return reinterpret_cast_checked<T const *>
521 (&vals_[detail::RawFragmentHeader::num_words()]);
526 artdaq::Fragment::setMetadata(
const T & metadata)
528 if (fragmentHeader()->metadata_word_count != 0) {
529 throw cet::exception(
"InvalidRequest")
530 <<
"Metadata has already been stored in this Fragment.";
532 auto const mdSize = validatedMetadataSize_<T>();
533 vals_.insert(dataBegin(), mdSize, 0);
534 updateFragmentHeaderWC_();
535 fragmentHeader()->metadata_word_count = mdSize;
537 memcpy(metadataAddress(), &metadata,
sizeof(T));
542 artdaq::Fragment::updateMetadata(
const T & metadata)
544 if (fragmentHeader()->metadata_word_count == 0) {
545 throw cet::exception(
"InvalidRequest")
546 <<
"No metadata in fragment; please use Fragment::setMetadata instead of Fragment::updateMetadata";
549 auto const mdSize = validatedMetadataSize_<T>();
551 if (fragmentHeader()->metadata_word_count != mdSize) {
552 throw cet::exception(
"InvalidRequest")
553 <<
"Mismatch between type of metadata struct passed to updateMetadata and existing metadata struct";
556 memcpy(metadataAddress(), &metadata,
sizeof(T));
560 artdaq::Fragment::resize(std::size_t sz)
562 vals_.resize(sz + fragmentHeader()->metadata_word_count +
563 detail::RawFragmentHeader::num_words());
564 updateFragmentHeaderWC_();
568 artdaq::Fragment::resize(std::size_t sz, RawDataType v)
570 vals_.resize(sz + fragmentHeader()->metadata_word_count +
571 detail::RawFragmentHeader::num_words(), v);
572 updateFragmentHeaderWC_();
576 artdaq::Fragment::resizeBytes(std::size_t szbytes)
578 RawDataType nwords = ceil(szbytes / static_cast<double>(
sizeof(RawDataType)));
583 artdaq::Fragment::resizeBytes(std::size_t szbytes, byte_t v)
585 RawDataType defaultval;
586 byte_t* ptr = reinterpret_cast_checked<byte_t*>(&defaultval);
588 for (uint8_t i = 0; i <
sizeof(RawDataType); ++i) {
593 RawDataType nwords = ceil(szbytes / static_cast<double>(
sizeof(RawDataType)));
595 resize(nwords, defaultval);
601 artdaq::Fragment::autoResize()
603 vals_.resize(fragmentHeader()->word_count);
604 updateFragmentHeaderWC_();
608 artdaq::Fragment::iterator
609 artdaq::Fragment::dataBegin()
611 return vals_.begin() + detail::RawFragmentHeader::num_words() +
612 fragmentHeader()->metadata_word_count;
616 artdaq::Fragment::iterator
617 artdaq::Fragment::dataEnd()
623 artdaq::Fragment::iterator
624 artdaq::Fragment::headerBegin()
626 return vals_.begin();
630 artdaq::Fragment::const_iterator
631 artdaq::Fragment::dataBegin()
const
633 return vals_.begin() + detail::RawFragmentHeader::num_words() +
634 fragmentHeader()->metadata_word_count;
638 artdaq::Fragment::const_iterator
639 artdaq::Fragment::dataEnd()
const
645 artdaq::Fragment::const_iterator
646 artdaq::Fragment::headerBegin()
const
648 return vals_.begin();
654 artdaq::Fragment::clear()
656 vals_.erase(dataBegin(), dataEnd());
657 updateFragmentHeaderWC_();
662 artdaq::Fragment::empty()
664 return (vals_.size() - detail::RawFragmentHeader::num_words() -
665 fragmentHeader()->metadata_word_count) == 0;
670 artdaq::Fragment::reserve(std::size_t cap)
672 vals_.reserve(cap + detail::RawFragmentHeader::num_words() +
673 fragmentHeader()->metadata_word_count);
678 artdaq::Fragment::swap(Fragment & other)
680 vals_.swap(other.vals_);
684 artdaq::RawDataType *
685 artdaq::Fragment::dataAddress()
687 return &vals_[0] + detail::RawFragmentHeader::num_words() +
688 fragmentHeader()->metadata_word_count;
692 artdaq::RawDataType *
693 artdaq::Fragment::metadataAddress()
695 if (fragmentHeader()->metadata_word_count == 0) {
696 throw cet::exception(
"InvalidRequest")
697 <<
"No metadata has been stored in this Fragment.";
699 return &vals_[0] + detail::RawFragmentHeader::num_words();
703 artdaq::RawDataType *
704 artdaq::Fragment::headerAddress()
710 template <
class InputIterator>
713 dataFrag(sequence_id_t sequenceID,
714 fragment_id_t fragID,
718 Fragment result(sequenceID, fragID);
719 result.vals_.reserve(std::distance(i, e) + detail::RawFragmentHeader::num_words());
720 std::copy(i, e, std::back_inserter(result.vals_));
726 artdaq::Fragment::fragmentHeader()
728 return reinterpret_cast_checked<detail::RawFragmentHeader *>(&vals_[0]);
733 artdaq::Fragment::fragmentHeader()
const
735 return reinterpret_cast_checked<detail::RawFragmentHeader const *>(&vals_[0]);