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 DATAVEC_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();
86 typedef DATAVEC_T::reference reference;
87 typedef DATAVEC_T::iterator iterator;
88 typedef DATAVEC_T::const_iterator const_iterator;
89 typedef DATAVEC_T::value_type value_type;
90 typedef DATAVEC_T::difference_type difference_type;
91 typedef DATAVEC_T::size_type size_type;
101 static std::unique_ptr<Fragment> FragmentBytes(std::size_t nbytes) {
102 RawDataType nwords = ceil(nbytes / static_cast<double>(
sizeof(RawDataType)));
103 return std::unique_ptr<Fragment>(
new Fragment(nwords));
110 Fragment(std::size_t payload_size, sequence_id_t sequence_id,
111 fragment_id_t fragment_id, type_t type,
const T & metadata,
112 timestamp_t timestamp = Fragment::InvalidTimestamp);
119 static std::unique_ptr<Fragment> FragmentBytes(std::size_t payload_size_in_bytes,
120 sequence_id_t sequence_id,
121 fragment_id_t fragment_id,
122 type_t type,
const T & metadata,
123 timestamp_t timestamp = Fragment::InvalidTimestamp) {
124 RawDataType nwords = ceil(payload_size_in_bytes /
125 static_cast<double>(
sizeof(RawDataType)));
126 return std::unique_ptr<Fragment>(
new Fragment(nwords, sequence_id, fragment_id, type, metadata, timestamp));
131 Fragment(sequence_id_t sequenceID,
132 fragment_id_t fragID,
133 type_t type = Fragment::DataFragmentType,
134 timestamp_t timestamp = Fragment::InvalidTimestamp);
137 void print(std::ostream & os)
const;
140 std::size_t size()
const;
141 version_t version()
const;
143 sequence_id_t sequenceID()
const;
144 fragment_id_t fragmentID()
const;
145 timestamp_t timestamp()
const;
148 void setVersion(version_t version);
149 void setUserType(type_t type);
150 void setSystemType(type_t type);
151 void setSequenceID(sequence_id_t sequence_id);
152 void setFragmentID(fragment_id_t fragment_id);
153 void setTimestamp(timestamp_t timestamp);
156 std::size_t sizeBytes()
const {
return sizeof(RawDataType) * size(); }
160 std::size_t dataSize()
const;
163 std::size_t dataSizeBytes()
const {
164 return sizeof(RawDataType) * dataSize();
168 bool hasMetadata()
const;
172 template <
class T> T * metadata();
173 template <
class T> T
const * metadata()
const;
178 template <
class T>
void setMetadata(
const T & md);
181 template <
class T>
void updateMetadata(
const T & md);
184 void resize(std::size_t sz);
185 void resize(std::size_t sz, RawDataType v);
191 void resizeBytes(std::size_t szbytes);
192 void resizeBytes(std::size_t szbytes, byte_t v);
198 iterator dataBegin();
219 template <
typename T>
220 T reinterpret_cast_checked(
const RawDataType* in)
const {
221 T newpointer =
reinterpret_cast<T
>(in);
223 if (static_cast<const void*>(newpointer) !=
static_cast<const void*
>(in)) {
224 throw cet::exception(
"Error in Fragment.hh: reinterpret_cast failed to return expected address-- please contact John Freeman at jcfree@fnal.gov");
231 template <
typename T>
232 T reinterpret_cast_checked(RawDataType* in) {
233 T newpointer =
reinterpret_cast<T
>(in);
235 if (static_cast<void*>(newpointer) !=
static_cast<void*
>(in)) {
236 throw cet::exception(
"Error in Fragment.hh: reinterpret_cast failed to return expected address-- please contact John Freeman at jcfree@fnal.gov");
248 byte_t* dataBeginBytes() {
return reinterpret_cast_checked<byte_t*>(&* dataBegin()); }
249 byte_t* dataEndBytes() {
return reinterpret_cast_checked<byte_t*>(&* dataEnd()); }
253 iterator headerBegin();
256 byte_t* headerBeginBytes() {
return reinterpret_cast_checked<byte_t*>(&* headerBegin()); }
259 const_iterator dataBegin()
const;
260 const_iterator dataEnd()
const;
262 const byte_t* dataBeginBytes()
const {
263 return reinterpret_cast_checked<const byte_t*>(&* dataBegin());
266 const byte_t* dataEndBytes()
const {
267 return reinterpret_cast_checked<const byte_t*>(&* dataEnd());
271 const_iterator headerBegin()
const;
273 const byte_t* headerBeginBytes()
const {
274 return reinterpret_cast_checked<const byte_t*>(&* headerBegin());
280 void reserve(std::size_t cap);
281 void swap(Fragment & other);
282 void swap(DATAVEC_T & other) { vals_.swap(other); };
284 RawDataType * dataAddress();
285 RawDataType * metadataAddress();
286 RawDataType * headerAddress();
288 static std::unique_ptr<Fragment> eodFrag(
size_t nFragsToExpect);
291 template <
class InputIterator>
294 dataFrag(sequence_id_t sequenceID,
295 fragment_id_t fragID,
301 dataFrag(sequence_id_t sequenceID,
302 fragment_id_t fragID,
303 RawDataType
const * dataPtr,
305 timestamp_t timestamp = Fragment::InvalidTimestamp);
309 template <
typename T>
static std::size_t validatedMetadataSize_();
310 void updateFragmentHeaderWC_();
315 detail::RawFragmentHeader * fragmentHeader();
316 detail::RawFragmentHeader
const * fragmentHeader()
const;
325 isUserFragmentType(type_t fragmentType)
327 return fragmentType >= detail::RawFragmentHeader::FIRST_USER_TYPE &&
328 fragmentType <= detail::RawFragmentHeader::LAST_USER_TYPE;
335 isSystemFragmentType(type_t fragmentType)
337 return fragmentType >= detail::RawFragmentHeader::FIRST_SYSTEM_TYPE;
343 validatedMetadataSize_()
348 static_assert(
sizeof(
size_t) >=
349 sizeof(decltype(std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max())),
350 "metadata_word_count_t is too big!");
352 static size_t constexpr max_md_wc =
353 std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max();
354 size_t requested_md_wc =
355 std::ceil(
sizeof(T) / static_cast<double>(
sizeof(artdaq::RawDataType)));
356 if (requested_md_wc > max_md_wc) {
357 throw cet::exception(
"InvalidRequest")
358 <<
"The requested metadata structure is too large: "
359 <<
"requested word count = " << requested_md_wc
360 <<
", maximum word count = " << max_md_wc;
362 return requested_md_wc;
367 Fragment(std::size_t payload_size, sequence_id_t sequence_id,
368 fragment_id_t fragment_id,
369 type_t type,
const T & metadata, timestamp_t timestamp) :
370 vals_((artdaq::detail::RawFragmentHeader::num_words() +
371 validatedMetadataSize_<T>() +
375 updateFragmentHeaderWC_();
376 fragmentHeader()->sequence_id = sequence_id;
377 fragmentHeader()->fragment_id = fragment_id;
378 fragmentHeader()->timestamp = timestamp;
379 fragmentHeader()->type = type;
381 fragmentHeader()->metadata_word_count =
383 (artdaq::detail::RawFragmentHeader::num_words() + payload_size);
385 memcpy(metadataAddress(), &metadata,
sizeof(T));
390 artdaq::Fragment::size()
const
392 return fragmentHeader()->word_count;
396 artdaq::Fragment::version_t
397 artdaq::Fragment::version()
const
399 return fragmentHeader()->version;
403 artdaq::Fragment::type_t
404 artdaq::Fragment::type()
const
406 return static_cast<type_t
>(fragmentHeader()->type);
410 artdaq::Fragment::sequence_id_t
411 artdaq::Fragment::sequenceID()
const
413 return fragmentHeader()->sequence_id;
417 artdaq::Fragment::fragment_id_t
418 artdaq::Fragment::fragmentID()
const
420 return fragmentHeader()->fragment_id;
424 artdaq::Fragment::timestamp_t
425 artdaq::Fragment::timestamp()
const
427 return fragmentHeader()->timestamp;
432 artdaq::Fragment::setVersion(version_t version)
434 fragmentHeader()->version = version;
439 artdaq::Fragment::setUserType(type_t type)
441 fragmentHeader()->setUserType(static_cast<uint8_t>(type));
446 artdaq::Fragment::setSystemType(type_t type)
448 fragmentHeader()->setSystemType(static_cast<uint8_t>(type));
453 artdaq::Fragment::setSequenceID(sequence_id_t sequence_id)
455 assert(sequence_id <= detail::RawFragmentHeader::InvalidSequenceID);
456 fragmentHeader()->sequence_id = sequence_id;
461 artdaq::Fragment::setFragmentID(fragment_id_t fragment_id)
463 fragmentHeader()->fragment_id = fragment_id;
468 artdaq::Fragment::setTimestamp(timestamp_t timestamp)
470 fragmentHeader()->timestamp = timestamp;
475 artdaq::Fragment::updateFragmentHeaderWC_()
479 assert(vals_.size() < (1ULL << 32));
480 fragmentHeader()->word_count = vals_.size();
485 artdaq::Fragment::dataSize()
const
487 return vals_.size() - detail::RawFragmentHeader::num_words() -
488 fragmentHeader()->metadata_word_count;
493 artdaq::Fragment::hasMetadata()
const
495 return fragmentHeader()->metadata_word_count != 0;
500 artdaq::Fragment::metadata()
502 if (fragmentHeader()->metadata_word_count == 0) {
503 throw cet::exception(
"InvalidRequest")
504 <<
"No metadata has been stored in this Fragment.";
507 return reinterpret_cast_checked<T *>
508 (&vals_[detail::RawFragmentHeader::num_words()]);
513 artdaq::Fragment::metadata()
const
515 if (fragmentHeader()->metadata_word_count == 0) {
516 throw cet::exception(
"InvalidRequest")
517 <<
"No metadata has been stored in this Fragment.";
519 return reinterpret_cast_checked<T const *>
520 (&vals_[detail::RawFragmentHeader::num_words()]);
525 artdaq::Fragment::setMetadata(
const T & metadata)
527 if (fragmentHeader()->metadata_word_count != 0) {
528 throw cet::exception(
"InvalidRequest")
529 <<
"Metadata has already been stored in this Fragment.";
531 auto const mdSize = validatedMetadataSize_<T>();
532 vals_.insert(dataBegin(), mdSize, 0);
533 updateFragmentHeaderWC_();
534 fragmentHeader()->metadata_word_count = mdSize;
536 memcpy(metadataAddress(), &metadata,
sizeof(T));
541 artdaq::Fragment::updateMetadata(
const T & metadata)
543 if (fragmentHeader()->metadata_word_count == 0) {
544 throw cet::exception(
"InvalidRequest")
545 <<
"No metadata in fragment; please use Fragment::setMetadata instead of Fragment::updateMetadata";
548 auto const mdSize = validatedMetadataSize_<T>();
550 if (fragmentHeader()->metadata_word_count != mdSize) {
551 throw cet::exception(
"InvalidRequest")
552 <<
"Mismatch between type of metadata struct passed to updateMetadata and existing metadata struct";
555 memcpy(metadataAddress(), &metadata,
sizeof(T));
559 artdaq::Fragment::resize(std::size_t sz)
561 vals_.resize(sz + fragmentHeader()->metadata_word_count +
562 detail::RawFragmentHeader::num_words());
563 updateFragmentHeaderWC_();
567 artdaq::Fragment::resize(std::size_t sz, RawDataType v)
569 vals_.resize(sz + fragmentHeader()->metadata_word_count +
570 detail::RawFragmentHeader::num_words(), v);
571 updateFragmentHeaderWC_();
575 artdaq::Fragment::resizeBytes(std::size_t szbytes)
577 RawDataType nwords = ceil(szbytes / static_cast<double>(
sizeof(RawDataType)));
582 artdaq::Fragment::resizeBytes(std::size_t szbytes, byte_t v)
584 RawDataType defaultval;
585 byte_t* ptr = reinterpret_cast_checked<byte_t*>(&defaultval);
587 for (uint8_t i = 0; i <
sizeof(RawDataType); ++i) {
592 RawDataType nwords = ceil(szbytes / static_cast<double>(
sizeof(RawDataType)));
594 resize(nwords, defaultval);
600 artdaq::Fragment::autoResize()
602 vals_.resize(fragmentHeader()->word_count);
603 updateFragmentHeaderWC_();
607 artdaq::Fragment::iterator
608 artdaq::Fragment::dataBegin()
610 return vals_.begin() + detail::RawFragmentHeader::num_words() +
611 fragmentHeader()->metadata_word_count;
615 artdaq::Fragment::iterator
616 artdaq::Fragment::dataEnd()
622 artdaq::Fragment::iterator
623 artdaq::Fragment::headerBegin()
625 return vals_.begin();
629 artdaq::Fragment::const_iterator
630 artdaq::Fragment::dataBegin()
const
632 return vals_.begin() + detail::RawFragmentHeader::num_words() +
633 fragmentHeader()->metadata_word_count;
637 artdaq::Fragment::const_iterator
638 artdaq::Fragment::dataEnd()
const
644 artdaq::Fragment::const_iterator
645 artdaq::Fragment::headerBegin()
const
647 return vals_.begin();
653 artdaq::Fragment::clear()
655 vals_.erase(dataBegin(), dataEnd());
656 updateFragmentHeaderWC_();
661 artdaq::Fragment::empty()
663 return (vals_.size() - detail::RawFragmentHeader::num_words() -
664 fragmentHeader()->metadata_word_count) == 0;
669 artdaq::Fragment::reserve(std::size_t cap)
671 vals_.reserve(cap + detail::RawFragmentHeader::num_words() +
672 fragmentHeader()->metadata_word_count);
677 artdaq::Fragment::swap(Fragment & other)
679 vals_.swap(other.vals_);
683 artdaq::RawDataType *
684 artdaq::Fragment::dataAddress()
686 return &vals_[0] + detail::RawFragmentHeader::num_words() +
687 fragmentHeader()->metadata_word_count;
691 artdaq::RawDataType *
692 artdaq::Fragment::metadataAddress()
694 if (fragmentHeader()->metadata_word_count == 0) {
695 throw cet::exception(
"InvalidRequest")
696 <<
"No metadata has been stored in this Fragment.";
698 return &vals_[0] + detail::RawFragmentHeader::num_words();
702 artdaq::RawDataType *
703 artdaq::Fragment::headerAddress()
709 template <
class InputIterator>
712 dataFrag(sequence_id_t sequenceID,
713 fragment_id_t fragID,
717 Fragment result(sequenceID, fragID);
718 result.vals_.reserve(std::distance(i, e) + detail::RawFragmentHeader::num_words());
719 std::copy(i, e, std::back_inserter(result.vals_));
725 artdaq::Fragment::fragmentHeader()
727 return reinterpret_cast_checked<detail::RawFragmentHeader *>(&vals_[0]);
732 artdaq::Fragment::fragmentHeader()
const
734 return reinterpret_cast_checked<detail::RawFragmentHeader const *>(&vals_[0]);