1 #ifndef artdaq_core_Data_Fragment_hh
2 #define artdaq_core_Data_Fragment_hh
15 #include "artdaq-core/Data/detail/RawFragmentHeader.hh"
16 #include "artdaq-core/Data/dictionarycontrol.hh"
19 # include "QuickVec.hh"
20 # define QUICKVEC_T QuickVec<RawDataType>
22 typedef detail::RawFragmentHeader::RawDataType RawDataType;
25 bool fragmentSequenceIDCompare(Fragment i, Fragment j);
27 std::ostream & operator<<(std::ostream & os, Fragment
const & f);
39 typedef uint8_t byte_t;
43 typedef detail::RawFragmentHeader::version_t version_t;
44 typedef detail::RawFragmentHeader::type_t type_t;
45 typedef detail::RawFragmentHeader::sequence_id_t sequence_id_t;
46 typedef detail::RawFragmentHeader::fragment_id_t fragment_id_t;
47 typedef detail::RawFragmentHeader::timestamp_t timestamp_t;
49 static constexpr version_t InvalidVersion =
50 detail::RawFragmentHeader::InvalidVersion;
51 static constexpr sequence_id_t InvalidSequenceID =
52 detail::RawFragmentHeader::InvalidSequenceID;
53 static constexpr fragment_id_t InvalidFragmentID =
54 detail::RawFragmentHeader::InvalidFragmentID;
55 static constexpr timestamp_t InvalidTimestamp =
56 detail::RawFragmentHeader::InvalidTimestamp;
58 static constexpr type_t InvalidFragmentType =
59 detail::RawFragmentHeader::InvalidFragmentType;
60 static constexpr type_t EndOfDataFragmentType =
61 detail::RawFragmentHeader::EndOfDataFragmentType;
62 static constexpr type_t DataFragmentType =
63 detail::RawFragmentHeader::DataFragmentType;
64 static constexpr type_t InitFragmentType =
65 detail::RawFragmentHeader::InitFragmentType;
66 static constexpr type_t EndOfRunFragmentType =
67 detail::RawFragmentHeader::EndOfRunFragmentType;
68 static constexpr type_t EndOfSubrunFragmentType =
69 detail::RawFragmentHeader::EndOfSubrunFragmentType;
70 static constexpr type_t ShutdownFragmentType =
71 detail::RawFragmentHeader::ShutdownFragmentType;
72 static constexpr type_t FirstUserFragmentType =
73 detail::RawFragmentHeader::FIRST_USER_TYPE;
74 static constexpr type_t EmptyFragmentType =
75 detail::RawFragmentHeader::EmptyFragmentType;
76 static constexpr type_t ContainerFragmentType =
77 detail::RawFragmentHeader::ContainerFragmentType;
79 static constexpr
bool isUserFragmentType(type_t fragmentType);
80 static constexpr
bool isSystemFragmentType(type_t fragmentType);
81 static std::map<type_t, std::string> MakeSystemTypeMap()
83 return detail::RawFragmentHeader::MakeSystemTypeMap();
87 typedef std::vector<RawDataType>::reference reference;
88 typedef std::vector<RawDataType>::iterator iterator;
89 typedef std::vector<RawDataType>::const_iterator const_iterator;
90 typedef std::vector<RawDataType>::value_type value_type;
91 typedef std::vector<RawDataType>::difference_type difference_type;
92 typedef std::vector<RawDataType>::size_type size_type;
94 typedef QUICKVEC_T::reference reference;
95 typedef QUICKVEC_T::iterator iterator;
96 typedef QUICKVEC_T::const_iterator const_iterator;
97 typedef QUICKVEC_T::value_type value_type;
98 typedef QUICKVEC_T::difference_type difference_type;
99 typedef QUICKVEC_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);
292 RawDataType * dataAddress();
293 RawDataType * metadataAddress();
294 RawDataType * headerAddress();
296 static std::unique_ptr<Fragment> eodFrag(
size_t nFragsToExpect);
299 template <
class InputIterator>
302 dataFrag(sequence_id_t sequenceID,
303 fragment_id_t fragID,
309 dataFrag(sequence_id_t sequenceID,
310 fragment_id_t fragID,
311 RawDataType
const * dataPtr,
313 timestamp_t timestamp = Fragment::InvalidTimestamp);
317 template <
typename T>
static std::size_t validatedMetadataSize_();
318 void updateFragmentHeaderWC_();
320 std::vector<RawDataType> vals_;
326 detail::RawFragmentHeader * fragmentHeader();
327 detail::RawFragmentHeader
const * fragmentHeader()
const;
336 isUserFragmentType(type_t fragmentType)
338 return fragmentType >= detail::RawFragmentHeader::FIRST_USER_TYPE &&
339 fragmentType <= detail::RawFragmentHeader::LAST_USER_TYPE;
346 isSystemFragmentType(type_t fragmentType)
348 return fragmentType >= detail::RawFragmentHeader::FIRST_SYSTEM_TYPE;
354 validatedMetadataSize_()
359 static_assert(
sizeof(
size_t) >=
360 sizeof(decltype(std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max())),
361 "metadata_word_count_t is too big!");
363 static size_t constexpr max_md_wc =
364 std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max();
365 size_t requested_md_wc =
366 std::ceil(
sizeof(T) / static_cast<double>(
sizeof(artdaq::RawDataType)));
367 if (requested_md_wc > max_md_wc) {
368 throw cet::exception(
"InvalidRequest")
369 <<
"The requested metadata structure is too large: "
370 <<
"requested word count = " << requested_md_wc
371 <<
", maximum word count = " << max_md_wc;
373 return requested_md_wc;
378 Fragment(std::size_t payload_size, sequence_id_t sequence_id,
379 fragment_id_t fragment_id,
380 type_t type,
const T & metadata, timestamp_t timestamp) :
381 vals_((artdaq::detail::RawFragmentHeader::num_words() +
382 validatedMetadataSize_<T>() +
386 updateFragmentHeaderWC_();
387 fragmentHeader()->sequence_id = sequence_id;
388 fragmentHeader()->fragment_id = fragment_id;
389 fragmentHeader()->timestamp = timestamp;
390 fragmentHeader()->type = type;
392 fragmentHeader()->metadata_word_count =
394 (artdaq::detail::RawFragmentHeader::num_words() + payload_size);
396 memcpy(metadataAddress(), &metadata,
sizeof(T));
401 artdaq::Fragment::size()
const
403 return fragmentHeader()->word_count;
407 artdaq::Fragment::version_t
408 artdaq::Fragment::version()
const
410 return fragmentHeader()->version;
414 artdaq::Fragment::type_t
415 artdaq::Fragment::type()
const
417 return static_cast<type_t
>(fragmentHeader()->type);
421 artdaq::Fragment::sequence_id_t
422 artdaq::Fragment::sequenceID()
const
424 return fragmentHeader()->sequence_id;
428 artdaq::Fragment::fragment_id_t
429 artdaq::Fragment::fragmentID()
const
431 return fragmentHeader()->fragment_id;
435 artdaq::Fragment::timestamp_t
436 artdaq::Fragment::timestamp()
const
438 return fragmentHeader()->timestamp;
443 artdaq::Fragment::setVersion(version_t version)
445 fragmentHeader()->version = version;
450 artdaq::Fragment::setUserType(type_t type)
452 fragmentHeader()->setUserType(static_cast<uint8_t>(type));
457 artdaq::Fragment::setSystemType(type_t type)
459 fragmentHeader()->setSystemType(static_cast<uint8_t>(type));
464 artdaq::Fragment::setSequenceID(sequence_id_t sequence_id)
466 assert(sequence_id <= detail::RawFragmentHeader::InvalidSequenceID);
467 fragmentHeader()->sequence_id = sequence_id;
472 artdaq::Fragment::setFragmentID(fragment_id_t fragment_id)
474 fragmentHeader()->fragment_id = fragment_id;
479 artdaq::Fragment::setTimestamp(timestamp_t timestamp)
481 fragmentHeader()->timestamp = timestamp;
486 artdaq::Fragment::updateFragmentHeaderWC_()
490 assert(vals_.size() < (1ULL << 32));
491 fragmentHeader()->word_count = vals_.size();
496 artdaq::Fragment::dataSize()
const
498 return vals_.size() - detail::RawFragmentHeader::num_words() -
499 fragmentHeader()->metadata_word_count;
504 artdaq::Fragment::hasMetadata()
const
506 return fragmentHeader()->metadata_word_count != 0;
511 artdaq::Fragment::metadata()
513 if (fragmentHeader()->metadata_word_count == 0) {
514 throw cet::exception(
"InvalidRequest")
515 <<
"No metadata has been stored in this Fragment.";
518 return reinterpret_cast_checked<T *>
519 (&vals_[detail::RawFragmentHeader::num_words()]);
524 artdaq::Fragment::metadata()
const
526 if (fragmentHeader()->metadata_word_count == 0) {
527 throw cet::exception(
"InvalidRequest")
528 <<
"No metadata has been stored in this Fragment.";
530 return reinterpret_cast_checked<T const *>
531 (&vals_[detail::RawFragmentHeader::num_words()]);
536 artdaq::Fragment::setMetadata(
const T & metadata)
538 if (fragmentHeader()->metadata_word_count != 0) {
539 throw cet::exception(
"InvalidRequest")
540 <<
"Metadata has already been stored in this Fragment.";
542 auto const mdSize = validatedMetadataSize_<T>();
543 vals_.insert(dataBegin(), mdSize, 0);
544 updateFragmentHeaderWC_();
545 fragmentHeader()->metadata_word_count = mdSize;
547 memcpy(metadataAddress(), &metadata,
sizeof(T));
552 artdaq::Fragment::updateMetadata(
const T & metadata)
554 if (fragmentHeader()->metadata_word_count == 0) {
555 throw cet::exception(
"InvalidRequest")
556 <<
"No metadata in fragment; please use Fragment::setMetadata instead of Fragment::updateMetadata";
559 auto const mdSize = validatedMetadataSize_<T>();
561 if (fragmentHeader()->metadata_word_count != mdSize) {
562 throw cet::exception(
"InvalidRequest")
563 <<
"Mismatch between type of metadata struct passed to updateMetadata and existing metadata struct";
566 memcpy(metadataAddress(), &metadata,
sizeof(T));
570 artdaq::Fragment::resize(std::size_t sz)
572 vals_.resize(sz + fragmentHeader()->metadata_word_count +
573 detail::RawFragmentHeader::num_words());
574 updateFragmentHeaderWC_();
578 artdaq::Fragment::resize(std::size_t sz, RawDataType v)
580 vals_.resize(sz + fragmentHeader()->metadata_word_count +
581 detail::RawFragmentHeader::num_words(), v);
582 updateFragmentHeaderWC_();
586 artdaq::Fragment::resizeBytes(std::size_t szbytes)
588 RawDataType nwords = ceil(szbytes / static_cast<double>(
sizeof(RawDataType)));
593 artdaq::Fragment::resizeBytes(std::size_t szbytes, byte_t v)
595 RawDataType defaultval;
596 byte_t* ptr = reinterpret_cast_checked<byte_t*>(&defaultval);
598 for (uint8_t i = 0; i <
sizeof(RawDataType); ++i) {
603 RawDataType nwords = ceil(szbytes / static_cast<double>(
sizeof(RawDataType)));
605 resize(nwords, defaultval);
611 artdaq::Fragment::autoResize()
613 vals_.resize(fragmentHeader()->word_count);
614 updateFragmentHeaderWC_();
618 artdaq::Fragment::iterator
619 artdaq::Fragment::dataBegin()
621 return vals_.begin() + detail::RawFragmentHeader::num_words() +
622 fragmentHeader()->metadata_word_count;
626 artdaq::Fragment::iterator
627 artdaq::Fragment::dataEnd()
633 artdaq::Fragment::iterator
634 artdaq::Fragment::headerBegin()
636 return vals_.begin();
640 artdaq::Fragment::const_iterator
641 artdaq::Fragment::dataBegin()
const
643 return vals_.begin() + detail::RawFragmentHeader::num_words() +
644 fragmentHeader()->metadata_word_count;
648 artdaq::Fragment::const_iterator
649 artdaq::Fragment::dataEnd()
const
655 artdaq::Fragment::const_iterator
656 artdaq::Fragment::headerBegin()
const
658 return vals_.begin();
664 artdaq::Fragment::clear()
666 vals_.erase(dataBegin(), dataEnd());
667 updateFragmentHeaderWC_();
672 artdaq::Fragment::empty()
674 return (vals_.size() - detail::RawFragmentHeader::num_words() -
675 fragmentHeader()->metadata_word_count) == 0;
680 artdaq::Fragment::reserve(std::size_t cap)
682 vals_.reserve(cap + detail::RawFragmentHeader::num_words() +
683 fragmentHeader()->metadata_word_count);
688 artdaq::Fragment::swap(Fragment & other)
690 vals_.swap(other.vals_);
694 artdaq::RawDataType *
695 artdaq::Fragment::dataAddress()
697 return &vals_[0] + detail::RawFragmentHeader::num_words() +
698 fragmentHeader()->metadata_word_count;
702 artdaq::RawDataType *
703 artdaq::Fragment::metadataAddress()
705 if (fragmentHeader()->metadata_word_count == 0) {
706 throw cet::exception(
"InvalidRequest")
707 <<
"No metadata has been stored in this Fragment.";
709 return &vals_[0] + detail::RawFragmentHeader::num_words();
713 artdaq::RawDataType *
714 artdaq::Fragment::headerAddress()
720 template <
class InputIterator>
723 dataFrag(sequence_id_t sequenceID,
724 fragment_id_t fragID,
728 Fragment result(sequenceID, fragID);
729 result.vals_.reserve(std::distance(i, e) + detail::RawFragmentHeader::num_words());
730 std::copy(i, e, std::back_inserter(result.vals_));
736 artdaq::Fragment::fragmentHeader()
738 return reinterpret_cast_checked<detail::RawFragmentHeader *>(&vals_[0]);
743 artdaq::Fragment::fragmentHeader()
const
745 return reinterpret_cast_checked<detail::RawFragmentHeader const *>(&vals_[0]);