$treeview $search $mathjax $extrastylesheet
artdaq_core
v3_06_01
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #ifndef artdaq_core_Data_Fragment_hh 00002 #define artdaq_core_Data_Fragment_hh 00003 00004 #include <algorithm> 00005 //#include <cassert> 00006 #include <cmath> 00007 #include <cstddef> 00008 #include <cstdint> 00009 #include <cstring> 00010 #include <iosfwd> 00011 #include <iterator> 00012 #include <list> 00013 #include <map> 00014 #include <memory> 00015 #include <vector> 00016 00017 #include <iostream> 00018 #include "artdaq-core/Core/QuickVec.hh" 00019 #include "artdaq-core/Data/detail/RawFragmentHeader.hh" 00020 #include "artdaq-core/Data/detail/RawFragmentHeaderV0.hh" 00021 #include "artdaq-core/Data/detail/RawFragmentHeaderV1.hh" 00022 #include "artdaq-core/Data/dictionarycontrol.hh" 00023 #if HIDE_FROM_ROOT 00024 #include "trace.h" // TRACE 00025 #endif 00026 00030 namespace artdaq { 00031 #define DATAVEC_T QuickVec<RawDataType> 00032 //#define DATAVEC_T std::vector<RawDataType> 00033 00040 typedef detail::RawFragmentHeader::RawDataType RawDataType; 00041 00042 class Fragment; 00046 typedef std::vector<Fragment> Fragments; 00047 00054 typedef std::unique_ptr<Fragment> FragmentPtr; 00055 00059 typedef std::list<FragmentPtr> FragmentPtrs; 00060 00067 bool fragmentSequenceIDCompare(const Fragment& i, const Fragment& j); 00068 00075 std::ostream& operator<<(std::ostream& os, Fragment const& f); 00076 } // namespace artdaq 00077 00085 class artdaq::Fragment 00086 { 00087 public: 00091 Fragment(); 00092 00100 typedef uint8_t byte_t; 00101 00102 // Hide most things from ROOT. 00103 #if HIDE_FROM_ROOT 00104 00105 // http://stackoverflow.com/questions/33939687 00106 // This should generate an exception if artdaq::Fragment is not move-constructible 00111 Fragment(const Fragment&) = default; 00119 Fragment(Fragment&&) noexcept; 00125 Fragment& operator=(const Fragment&) = default; 00134 Fragment& operator=(Fragment&&) noexcept; 00135 00136 typedef detail::RawFragmentHeader::version_t version_t; 00137 typedef detail::RawFragmentHeader::type_t type_t; 00138 typedef detail::RawFragmentHeader::sequence_id_t sequence_id_t; 00139 typedef detail::RawFragmentHeader::fragment_id_t fragment_id_t; 00140 typedef detail::RawFragmentHeader::timestamp_t timestamp_t; 00141 00142 static constexpr version_t InvalidVersion = detail::RawFragmentHeader::InvalidVersion; 00143 static constexpr sequence_id_t InvalidSequenceID = detail::RawFragmentHeader::InvalidSequenceID; 00144 static constexpr fragment_id_t InvalidFragmentID = detail::RawFragmentHeader::InvalidFragmentID; 00145 static constexpr timestamp_t InvalidTimestamp = detail::RawFragmentHeader::InvalidTimestamp; 00146 00147 static constexpr type_t InvalidFragmentType = detail::RawFragmentHeader::InvalidFragmentType; 00148 static constexpr type_t EndOfDataFragmentType = detail::RawFragmentHeader::EndOfDataFragmentType; 00149 static constexpr type_t DataFragmentType = detail::RawFragmentHeader::DataFragmentType; 00150 static constexpr type_t InitFragmentType = detail::RawFragmentHeader::InitFragmentType; 00151 static constexpr type_t EndOfRunFragmentType = detail::RawFragmentHeader::EndOfRunFragmentType; 00152 static constexpr type_t EndOfSubrunFragmentType = detail::RawFragmentHeader::EndOfSubrunFragmentType; 00153 static constexpr type_t ShutdownFragmentType = detail::RawFragmentHeader::ShutdownFragmentType; 00154 static constexpr type_t FirstUserFragmentType = detail::RawFragmentHeader::FIRST_USER_TYPE; 00155 static constexpr type_t EmptyFragmentType = detail::RawFragmentHeader::EmptyFragmentType; 00156 static constexpr type_t ContainerFragmentType = detail::RawFragmentHeader::ContainerFragmentType; 00157 static constexpr type_t ErrorFragmentType = detail::RawFragmentHeader::ErrorFragmentType; 00158 00164 static constexpr bool isUserFragmentType(type_t fragmentType); 00165 00171 static constexpr bool isSystemFragmentType(type_t fragmentType); 00172 00177 static std::map<type_t, std::string> MakeSystemTypeMap() 00178 { 00179 return detail::RawFragmentHeader::MakeSystemTypeMap(); 00180 } 00181 00182 typedef DATAVEC_T::reference reference; 00183 typedef DATAVEC_T::iterator iterator; 00184 typedef DATAVEC_T::const_iterator const_iterator; 00185 typedef DATAVEC_T::value_type value_type; 00186 typedef DATAVEC_T::difference_type difference_type; 00187 typedef DATAVEC_T::size_type size_type; 00188 00194 explicit Fragment(std::size_t n); 00195 00202 static FragmentPtr FragmentBytes(std::size_t nbytes) 00203 { 00204 RawDataType nwords = ceil(nbytes / static_cast<double>(sizeof(RawDataType))); 00205 return std::make_unique<Fragment>(nwords); 00206 } 00207 00218 template<class T> 00219 Fragment(std::size_t payload_size, sequence_id_t sequence_id, 00220 fragment_id_t fragment_id, type_t type, const T& metadata, 00221 timestamp_t timestamp = Fragment::InvalidTimestamp); 00222 00236 template<class T> 00237 static FragmentPtr FragmentBytes(std::size_t payload_size_in_bytes, 00238 sequence_id_t sequence_id, 00239 fragment_id_t fragment_id, 00240 type_t type, const T& metadata, 00241 timestamp_t timestamp = Fragment::InvalidTimestamp) 00242 { 00243 RawDataType nwords = ceil(payload_size_in_bytes / 00244 static_cast<double>(sizeof(RawDataType))); 00245 return std::make_unique<Fragment>(nwords, sequence_id, fragment_id, type, metadata, timestamp); 00246 } 00247 00255 Fragment(sequence_id_t sequenceID, 00256 fragment_id_t fragID, 00257 type_t type = Fragment::DataFragmentType, 00258 timestamp_t timestamp = Fragment::InvalidTimestamp); 00259 00264 void print(std::ostream& os) const; 00265 00270 std::size_t size() const; 00271 00276 version_t version() const; 00277 00282 type_t type() const; 00283 00288 std::string typeString() const; 00289 00294 sequence_id_t sequenceID() const; 00295 00300 fragment_id_t fragmentID() const; 00301 00306 timestamp_t timestamp() const; 00307 00312 void setUserType(type_t utype); 00313 00318 void setSystemType(type_t stype); 00319 00324 void setSequenceID(sequence_id_t sequence_id); 00325 00330 void setFragmentID(fragment_id_t fragment_id); 00331 00336 void setTimestamp(timestamp_t timestamp); 00337 00341 void touch(); 00342 00347 struct timespec atime() const; 00348 00354 struct timespec getLatency(bool touch); 00355 00360 std::size_t sizeBytes() const { return sizeof(RawDataType) * size(); } 00361 00367 std::size_t dataSize() const; 00368 00374 std::size_t dataSizeBytes() const 00375 { 00376 return sizeof(RawDataType) * dataSize(); 00377 } 00378 00383 bool hasMetadata() const; 00384 00392 template<class T> 00393 T* metadata(); 00394 00402 template<class T> 00403 T const* metadata() const; 00404 00413 template<class T> 00414 void setMetadata(const T& metadata); 00415 00423 template<class T> 00424 void updateMetadata(const T& metadata); 00425 00430 void resize(std::size_t sz); 00431 00437 void resize(std::size_t sz, RawDataType val); 00438 00445 void resizeBytes(std::size_t szbytes); 00446 00455 void resizeBytesWithCushion(std::size_t szbytes, double growthFactor = 1.3); 00456 00464 void resizeBytes(std::size_t szbytes, byte_t val); 00465 00469 void autoResize(); 00470 00475 iterator dataBegin(); 00476 00481 iterator dataEnd(); 00482 00502 template<typename T> 00503 T reinterpret_cast_checked(const RawDataType* in) const 00504 { 00505 T newpointer = reinterpret_cast<T>(in); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) 00506 00507 if (static_cast<const void*>(newpointer) != static_cast<const void*>(in)) 00508 { 00509 throw cet::exception("Error in Fragment.hh: reinterpret_cast failed to return expected address-- please contact John Freeman at jcfree@fnal.gov"); 00510 } 00511 00512 return newpointer; 00513 } 00514 00530 template<typename T> 00531 T reinterpret_cast_checked(RawDataType* in) 00532 { 00533 T newpointer = reinterpret_cast<T>(in); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) 00534 00535 if (static_cast<void*>(newpointer) != static_cast<void*>(in)) 00536 { 00537 throw cet::exception("Error in Fragment.hh: reinterpret_cast failed to return expected address-- please contact John Freeman at jcfree@fnal.gov"); 00538 } 00539 00540 return newpointer; 00541 } 00542 00551 byte_t* dataBeginBytes() { return reinterpret_cast_checked<byte_t*>(&*dataBegin()); } 00552 00561 byte_t* dataEndBytes() { return reinterpret_cast_checked<byte_t*>(&*dataEnd()); } 00562 00568 iterator headerBegin(); 00569 00574 byte_t* headerBeginBytes() { return reinterpret_cast_checked<byte_t*>(&*headerBegin()); } 00575 00580 const_iterator dataBegin() const; 00581 00586 const_iterator dataEnd() const; 00587 00596 const byte_t* dataBeginBytes() const 00597 { 00598 return reinterpret_cast_checked<const byte_t*>(&*dataBegin()); 00599 } 00600 00609 const byte_t* dataEndBytes() const 00610 { 00611 return reinterpret_cast_checked<const byte_t*>(&*dataEnd()); 00612 } 00613 00619 const_iterator headerBegin() const; // See note for non-const, above. 00620 00625 const byte_t* headerBeginBytes() const 00626 { 00627 return reinterpret_cast_checked<const byte_t*>(&*headerBegin()); 00628 } 00629 00634 size_t headerSizeWords() const; 00635 00640 size_t headerSizeBytes() const { return sizeof(RawDataType) * headerSizeWords(); } 00641 00645 void clear(); 00646 00651 bool empty(); 00652 00657 void reserve(std::size_t cap); 00658 00663 void swap(Fragment& other) noexcept; 00664 00671 void swap(DATAVEC_T& other) noexcept { vals_.swap(other); }; 00672 00677 RawDataType* dataAddress(); 00678 00685 RawDataType* metadataAddress(); 00690 RawDataType* headerAddress(); 00691 00697 static FragmentPtr eodFrag(size_t nFragsToExpect); 00698 00710 template<class InputIterator> 00711 static FragmentPtr dataFrag(sequence_id_t sequenceID, 00712 fragment_id_t fragID, 00713 InputIterator i, 00714 InputIterator e) 00715 { 00716 FragmentPtr result(new Fragment(sequenceID, fragID)); 00717 result->vals_.reserve(std::distance(i, e) + detail::RawFragmentHeader::num_words()); 00718 std::copy(i, e, std::back_inserter(result->vals_)); 00719 result->updateFragmentHeaderWC_(); 00720 return result; 00721 } 00722 00732 static FragmentPtr dataFrag(sequence_id_t sequenceID, 00733 fragment_id_t fragID, 00734 RawDataType const* dataPtr, 00735 size_t dataSize, 00736 timestamp_t timestamp = Fragment::InvalidTimestamp); 00737 00742 detail::RawFragmentHeader const fragmentHeader() const; 00743 #endif 00744 00745 private: 00746 template<typename T> 00747 static std::size_t validatedMetadataSize_(); 00748 00749 void updateFragmentHeaderWC_(); 00750 00751 DATAVEC_T vals_; 00752 00753 #if HIDE_FROM_ROOT 00754 00755 detail::RawFragmentHeader* fragmentHeaderPtr(); 00756 00757 #endif 00758 }; 00759 00760 #if HIDE_FROM_ROOT 00761 00762 // http://stackoverflow.com/questions/33939687 00763 // This should generate an exception if artdaq::Fragment is not move-constructible 00764 inline artdaq::Fragment::Fragment(artdaq::Fragment&&) noexcept = default; 00765 inline artdaq::Fragment& artdaq::Fragment::operator=(artdaq::Fragment&&) noexcept = default; 00766 00767 inline bool constexpr artdaq::Fragment:: 00768 isUserFragmentType(type_t fragmentType) 00769 { 00770 return fragmentType >= detail::RawFragmentHeader::FIRST_USER_TYPE && 00771 fragmentType <= detail::RawFragmentHeader::LAST_USER_TYPE; 00772 } 00773 00774 inline bool constexpr artdaq::Fragment:: 00775 isSystemFragmentType(type_t fragmentType) 00776 { 00777 return fragmentType >= detail::RawFragmentHeader::FIRST_SYSTEM_TYPE; 00778 } 00779 00780 template<typename T> 00781 std::size_t 00782 artdaq::Fragment:: 00783 validatedMetadataSize_() 00784 { 00785 // Make sure a size_t is big enough to hold the maximum metadata 00786 // size. This *should* always be true, but it is a compile-time check 00787 // and therefore cheap. 00788 static_assert(sizeof(size_t) >= 00789 sizeof(decltype(std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max())), 00790 "metadata_word_count_t is too big!"); 00791 00792 static size_t constexpr max_md_wc = 00793 std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max(); 00794 size_t requested_md_wc = 00795 std::ceil(sizeof(T) / static_cast<double>(sizeof(artdaq::RawDataType))); 00796 if (requested_md_wc > max_md_wc) 00797 { 00798 throw cet::exception("InvalidRequest") // NOLINT(cert-err60-cpp) 00799 << "The requested metadata structure is too large: " 00800 << "requested word count = " << requested_md_wc 00801 << ", maximum word count = " << max_md_wc; 00802 } 00803 return requested_md_wc; 00804 } 00805 00806 template<class T> 00807 artdaq::Fragment:: 00808 Fragment(std::size_t payload_size, sequence_id_t sequence_id, 00809 fragment_id_t fragment_id, 00810 type_t type, const T& metadata, timestamp_t timestamp) 00811 : vals_((artdaq::detail::RawFragmentHeader::num_words() + // Header 00812 validatedMetadataSize_<T>() + // Metadata 00813 payload_size) // User data 00814 ) 00815 { 00816 TRACEN("Fragment", 50, "Fragment ctor num_word()=%zu MetadataSize_=%zu payload_size=%zu", artdaq::detail::RawFragmentHeader::num_words(), validatedMetadataSize_<T>(), payload_size); // NOLINT 00817 // vals ctor w/o init val is used; make sure header is ALL initialized. 00818 for (iterator ii = vals_.begin(); 00819 ii != (vals_.begin() + detail::RawFragmentHeader::num_words()); ++ii) 00820 { 00821 *ii = -1; 00822 } 00823 fragmentHeaderPtr()->version = detail::RawFragmentHeader::CurrentVersion; 00824 updateFragmentHeaderWC_(); 00825 fragmentHeaderPtr()->sequence_id = sequence_id; 00826 fragmentHeaderPtr()->fragment_id = fragment_id; 00827 fragmentHeaderPtr()->timestamp = timestamp; 00828 fragmentHeaderPtr()->type = type; 00829 00830 fragmentHeaderPtr()->touch(); 00831 00832 fragmentHeaderPtr()->metadata_word_count = 00833 vals_.size() - 00834 (headerSizeWords() + payload_size); 00835 00836 memcpy(metadataAddress(), &metadata, sizeof(T)); 00837 } 00838 00839 inline std::size_t 00840 artdaq::Fragment::size() const 00841 { 00842 return fragmentHeader().word_count; 00843 } 00844 00845 inline artdaq::Fragment::version_t 00846 artdaq::Fragment::version() const 00847 { 00848 auto hdr = reinterpret_cast_checked<detail::RawFragmentHeader const*>(&vals_[0]); 00849 return hdr->version; 00850 } 00851 00852 inline artdaq::Fragment::type_t 00853 artdaq::Fragment::type() const 00854 { 00855 return static_cast<type_t>(fragmentHeader().type); 00856 } 00857 00858 inline std::string 00859 artdaq::Fragment::typeString() const 00860 { 00861 return std::to_string(type()) + (isSystemFragmentType(type()) ? " (" + detail::RawFragmentHeader::SystemTypeToString(type()) + ")" : ""); 00862 } 00863 00864 inline artdaq::Fragment::sequence_id_t 00865 artdaq::Fragment::sequenceID() const 00866 { 00867 return fragmentHeader().sequence_id; 00868 } 00869 00870 inline artdaq::Fragment::fragment_id_t 00871 artdaq::Fragment::fragmentID() const 00872 { 00873 return fragmentHeader().fragment_id; 00874 } 00875 00876 inline artdaq::Fragment::timestamp_t 00877 artdaq::Fragment::timestamp() const 00878 { 00879 return fragmentHeader().timestamp; 00880 } 00881 00882 inline void 00883 artdaq::Fragment::setUserType(type_t type) 00884 { 00885 fragmentHeaderPtr()->setUserType(static_cast<uint8_t>(type)); 00886 } 00887 00888 inline void 00889 artdaq::Fragment::setSystemType(type_t type) 00890 { 00891 fragmentHeaderPtr()->setSystemType(static_cast<uint8_t>(type)); 00892 } 00893 00894 inline void 00895 artdaq::Fragment::setSequenceID(sequence_id_t sequence_id) 00896 { 00897 assert(sequence_id <= detail::RawFragmentHeader::InvalidSequenceID); 00898 fragmentHeaderPtr()->sequence_id = sequence_id; 00899 } 00900 00901 inline void 00902 artdaq::Fragment::setFragmentID(fragment_id_t fragment_id) 00903 { 00904 fragmentHeaderPtr()->fragment_id = fragment_id; 00905 } 00906 00907 inline void 00908 artdaq::Fragment::setTimestamp(timestamp_t timestamp) 00909 { 00910 fragmentHeaderPtr()->timestamp = timestamp; 00911 } 00912 00913 inline void artdaq::Fragment::touch() 00914 { 00915 fragmentHeaderPtr()->touch(); 00916 } 00917 00918 inline struct timespec artdaq::Fragment::atime() const 00919 { 00920 return fragmentHeader().atime(); 00921 } 00922 00923 inline struct timespec artdaq::Fragment::getLatency(bool touch) 00924 { 00925 return fragmentHeaderPtr()->getLatency(touch); 00926 } 00927 00928 inline void 00929 artdaq::Fragment::updateFragmentHeaderWC_() 00930 { 00931 // Make sure vals_.size() fits inside 32 bits. Left-shift here should 00932 // match bitfield size of word_count in RawFragmentHeader. 00933 assert(vals_.size() < (1ULL << 32)); 00934 TRACEN("Fragment", 50, "Fragment::updateFragmentHeaderWC_ adjusting fragmentHeader()->word_count from %u to %zu", (unsigned)(fragmentHeaderPtr()->word_count), vals_.size()); // NOLINT 00935 fragmentHeaderPtr()->word_count = vals_.size(); 00936 } 00937 00938 inline std::size_t 00939 artdaq::Fragment::dataSize() const 00940 { 00941 return vals_.size() - headerSizeWords() - 00942 fragmentHeader().metadata_word_count; 00943 } 00944 00945 inline bool 00946 artdaq::Fragment::hasMetadata() const 00947 { 00948 return fragmentHeader().metadata_word_count != 0; 00949 } 00950 00951 template<class T> 00952 T* artdaq::Fragment::metadata() 00953 { 00954 if (fragmentHeader().metadata_word_count == 0) 00955 { 00956 throw cet::exception("InvalidRequest") // NOLINT(cert-err60-cpp) 00957 << "No metadata has been stored in this Fragment."; 00958 } 00959 00960 return reinterpret_cast_checked<T*>(&vals_[headerSizeWords()]); 00961 } 00962 00963 template<class T> 00964 T const* 00965 artdaq::Fragment::metadata() const 00966 { 00967 if (fragmentHeader().metadata_word_count == 0) 00968 { 00969 throw cet::exception("InvalidRequest") // NOLINT(cert-err60-cpp) 00970 << "No metadata has been stored in this Fragment."; 00971 } 00972 return reinterpret_cast_checked<T const*>(&vals_[headerSizeWords()]); 00973 } 00974 00975 template<class T> 00976 void artdaq::Fragment::setMetadata(const T& metadata) 00977 { 00978 if (fragmentHeader().metadata_word_count != 0) 00979 { 00980 throw cet::exception("InvalidRequest") // NOLINT(cert-err60-cpp) 00981 << "Metadata has already been stored in this Fragment."; 00982 } 00983 auto const mdSize = validatedMetadataSize_<T>(); 00984 vals_.insert(dataBegin(), mdSize, 0); 00985 updateFragmentHeaderWC_(); 00986 fragmentHeaderPtr()->metadata_word_count = mdSize; 00987 00988 memcpy(metadataAddress(), &metadata, sizeof(T)); 00989 } 00990 00991 template<class T> 00992 void artdaq::Fragment::updateMetadata(const T& metadata) 00993 { 00994 if (fragmentHeader().metadata_word_count == 0) 00995 { 00996 throw cet::exception("InvalidRequest") // NOLINT(cert-err60-cpp) 00997 << "No metadata in fragment; please use Fragment::setMetadata instead of Fragment::updateMetadata"; 00998 } 00999 01000 auto const mdSize = validatedMetadataSize_<T>(); 01001 01002 if (fragmentHeader().metadata_word_count != mdSize) 01003 { 01004 throw cet::exception("InvalidRequest") // NOLINT(cert-err60-cpp) 01005 << "Mismatch between type of metadata struct passed to updateMetadata and existing metadata struct"; 01006 } 01007 01008 memcpy(metadataAddress(), &metadata, sizeof(T)); 01009 } 01010 01011 inline void 01012 artdaq::Fragment::resize(std::size_t sz) 01013 { 01014 vals_.resize(sz + fragmentHeaderPtr()->metadata_word_count + 01015 headerSizeWords()); 01016 updateFragmentHeaderWC_(); 01017 } 01018 01019 inline void 01020 artdaq::Fragment::resize(std::size_t sz, RawDataType v) 01021 { 01022 vals_.resize(sz + fragmentHeaderPtr()->metadata_word_count + 01023 headerSizeWords(), 01024 v); 01025 updateFragmentHeaderWC_(); 01026 } 01027 01028 inline void 01029 artdaq::Fragment::resizeBytes(std::size_t szbytes) 01030 { 01031 RawDataType nwords = ceil(szbytes / static_cast<double>(sizeof(RawDataType))); 01032 resize(nwords); 01033 } 01034 01035 inline void 01036 artdaq::Fragment::resizeBytesWithCushion(std::size_t szbytes, double growthFactor) 01037 { 01038 RawDataType nwords = ceil(szbytes / static_cast<double>(sizeof(RawDataType))); 01039 vals_.resizeWithCushion(nwords + fragmentHeaderPtr()->metadata_word_count + 01040 headerSizeWords(), 01041 growthFactor); 01042 updateFragmentHeaderWC_(); 01043 } 01044 01045 inline void 01046 artdaq::Fragment::resizeBytes(std::size_t szbytes, byte_t v) 01047 { 01048 RawDataType defaultval; 01049 auto ptr = reinterpret_cast_checked<byte_t*>(&defaultval); 01050 01051 for (uint8_t i = 0; i < sizeof(RawDataType); ++i) 01052 { 01053 *ptr = v; 01054 ptr++; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) 01055 } 01056 01057 RawDataType nwords = ceil(szbytes / static_cast<double>(sizeof(RawDataType))); 01058 01059 resize(nwords, defaultval); 01060 } 01061 01062 inline void 01063 artdaq::Fragment::autoResize() 01064 { 01065 vals_.resize(fragmentHeaderPtr()->word_count); 01066 updateFragmentHeaderWC_(); 01067 } 01068 01069 inline artdaq::Fragment::iterator 01070 artdaq::Fragment::dataBegin() 01071 { 01072 return vals_.begin() + headerSizeWords() + 01073 fragmentHeader().metadata_word_count; 01074 } 01075 01076 inline artdaq::Fragment::iterator 01077 artdaq::Fragment::dataEnd() 01078 { 01079 return vals_.end(); 01080 } 01081 01082 inline artdaq::Fragment::iterator 01083 artdaq::Fragment::headerBegin() 01084 { 01085 return vals_.begin(); 01086 } 01087 01088 inline artdaq::Fragment::const_iterator 01089 artdaq::Fragment::dataBegin() const 01090 { 01091 return vals_.begin() + headerSizeWords() + 01092 fragmentHeader().metadata_word_count; 01093 } 01094 01095 inline artdaq::Fragment::const_iterator 01096 artdaq::Fragment::dataEnd() const 01097 { 01098 return vals_.end(); 01099 } 01100 01101 inline artdaq::Fragment::const_iterator 01102 artdaq::Fragment::headerBegin() const 01103 { 01104 return vals_.begin(); 01105 } 01106 01107 inline void 01108 artdaq::Fragment::clear() 01109 { 01110 vals_.erase(dataBegin(), dataEnd()); 01111 updateFragmentHeaderWC_(); 01112 } 01113 01114 inline bool 01115 artdaq::Fragment::empty() 01116 { 01117 return (vals_.size() - headerSizeWords() - 01118 fragmentHeader().metadata_word_count) == 0; 01119 } 01120 01121 inline void 01122 artdaq::Fragment::reserve(std::size_t cap) 01123 { 01124 vals_.reserve(cap + headerSizeWords() + 01125 fragmentHeader().metadata_word_count); 01126 } 01127 01128 inline void 01129 artdaq::Fragment::swap(Fragment& other) noexcept 01130 { 01131 vals_.swap(other.vals_); 01132 } 01133 01134 inline artdaq::RawDataType* 01135 artdaq::Fragment::dataAddress() 01136 { 01137 return &vals_[0] + headerSizeWords() + // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) 01138 fragmentHeader().metadata_word_count; 01139 } 01140 01141 inline artdaq::RawDataType* 01142 artdaq::Fragment::metadataAddress() 01143 { 01144 if (fragmentHeader().metadata_word_count == 0) 01145 { 01146 throw cet::exception("InvalidRequest") // NOLINT(cert-err60-cpp) 01147 << "No metadata has been stored in this Fragment."; 01148 } 01149 return &vals_[0] + headerSizeWords(); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) 01150 } 01151 01152 inline artdaq::RawDataType* 01153 artdaq::Fragment::headerAddress() 01154 { 01155 return &vals_[0]; 01156 } 01157 01158 inline size_t 01159 artdaq::Fragment::headerSizeWords() const 01160 { 01161 auto hdr = reinterpret_cast_checked<detail::RawFragmentHeader const*>(&vals_[0]); 01162 if (hdr->version != detail::RawFragmentHeader::CurrentVersion) 01163 { 01164 switch (hdr->version) 01165 { 01166 case 0xFFFF: 01167 TLOG(51, "Fragment") << "Cannot get header size of InvalidVersion Fragment"; 01168 break; 01169 case 0: 01170 { 01171 TLOG(52, "Fragment") << "Getting size of RawFragmentHeaderV0"; 01172 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV0 const*>(&vals_[0]); 01173 return old_hdr->num_words(); 01174 break; 01175 } 01176 case 1: 01177 { 01178 TLOG(52, "Fragment") << "Getting size of RawFragmentHeaderV1"; 01179 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV1 const*>(&vals_[0]); 01180 return old_hdr->num_words(); 01181 break; 01182 } 01183 default: 01184 throw cet::exception("Fragment") << "A Fragment with an unknown version (" << std::to_string(hdr->version) << ") was received!"; // NOLINT(cert-err60-cpp) 01185 break; 01186 } 01187 } 01188 return hdr->num_words(); 01189 } 01190 01191 inline artdaq::detail::RawFragmentHeader* 01192 artdaq::Fragment::fragmentHeaderPtr() 01193 { 01194 auto hdr = reinterpret_cast_checked<detail::RawFragmentHeader*>(&vals_[0]); 01195 if (hdr->version != detail::RawFragmentHeader::CurrentVersion) 01196 { 01197 switch (hdr->version) 01198 { 01199 case 0xFFFF: 01200 TLOG(51, "Fragment") << "Not upgrading InvalidVersion Fragment"; 01201 break; 01202 case 0: 01203 { 01204 TLOG(52, "Fragment") << "Upgrading RawFragmentHeaderV0 (non const)"; 01205 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV0*>(&vals_[0]); 01206 auto new_hdr = old_hdr->upgrade(); 01207 01208 auto szDiff = hdr->num_words() - old_hdr->num_words(); 01209 if (szDiff > 0) 01210 { 01211 vals_.insert(vals_.begin(), szDiff, 0); 01212 new_hdr.word_count = vals_.size(); 01213 } 01214 memcpy(&vals_[0], &new_hdr, hdr->num_words() * sizeof(RawDataType)); 01215 hdr = reinterpret_cast_checked<detail::RawFragmentHeader*>(&vals_[0]); // Update hdr in case vals_->insert call invalidated pointers 01216 break; 01217 } 01218 case 1: 01219 { 01220 TLOG(52, "Fragment") << "Upgrading RawFragmentHeaderV1 (non const)"; 01221 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV1*>(&vals_[0]); 01222 auto new_hdr = old_hdr->upgrade(); 01223 01224 auto szDiff = hdr->num_words() - old_hdr->num_words(); 01225 if (szDiff > 0) 01226 { 01227 vals_.insert(vals_.begin(), szDiff, 0); 01228 new_hdr.word_count = vals_.size(); 01229 } 01230 memcpy(&vals_[0], &new_hdr, hdr->num_words() * sizeof(RawDataType)); 01231 hdr = reinterpret_cast_checked<detail::RawFragmentHeader*>(&vals_[0]); // Update hdr in case vals_->insert call invalidated pointers 01232 break; 01233 } 01234 default: 01235 throw cet::exception("Fragment") << "A Fragment with an unknown version (" << std::to_string(hdr->version) << ") was received!"; // NOLINT(cert-err60-cpp) 01236 break; 01237 } 01238 } 01239 return hdr; 01240 } 01241 01242 inline artdaq::detail::RawFragmentHeader const 01243 artdaq::Fragment::fragmentHeader() const 01244 { 01245 auto hdr = *reinterpret_cast_checked<detail::RawFragmentHeader const*>(&vals_[0]); 01246 if (hdr.version != detail::RawFragmentHeader::CurrentVersion) 01247 { 01248 switch (hdr.version) 01249 { 01250 case 0xFFFF: 01251 TLOG(51, "Fragment") << "Not upgrading InvalidVersion Fragment"; 01252 break; 01253 case 0: 01254 { 01255 TLOG(52, "Fragment") << "Upgrading RawFragmentHeaderV0 (const)"; 01256 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV0 const*>(&vals_[0]); 01257 hdr = old_hdr->upgrade(); 01258 01259 break; 01260 } 01261 case 1: 01262 { 01263 TLOG(52, "Fragment") << "Upgrading RawFragmentHeaderV1 (const)"; 01264 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV1 const*>(&vals_[0]); 01265 hdr = old_hdr->upgrade(); 01266 01267 break; 01268 } 01269 default: 01270 throw cet::exception("Fragment") << "A Fragment with an unknown version (" << std::to_string(hdr.version) << ") was received!"; // NOLINT(cert-err60-cpp) 01271 break; 01272 } 01273 } 01274 return hdr; 01275 } 01276 01277 inline void 01278 swap(artdaq::Fragment& x, artdaq::Fragment& y) noexcept 01279 { 01280 x.swap(y); 01281 } 01282 01283 inline std::ostream& 01284 artdaq::operator<<(std::ostream& os, artdaq::Fragment const& f) 01285 { 01286 f.print(os); 01287 return os; 01288 } 01289 #endif /* HIDE_FROM_ROOT */ 01290 01291 #endif /* artdaq_core_Data_Fragment_hh */