$treeview $search $mathjax $extrastylesheet
artdaq_core
v3_05_08a
$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 <stdint.h> 00007 #include <string.h> 00008 #include <cmath> 00009 #include <cstddef> 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(Fragment i, 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 FragmentPtr(new 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 FragmentPtr(new 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& md); 00415 00423 template<class T> 00424 void updateMetadata(const T& md); 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); 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); 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 #endif 00738 00739 private: 00740 template<typename T> 00741 static std::size_t validatedMetadataSize_(); 00742 00743 void updateFragmentHeaderWC_(); 00744 00745 DATAVEC_T vals_; 00746 00747 #if HIDE_FROM_ROOT 00748 00749 detail::RawFragmentHeader* fragmentHeaderPtr(); 00750 00751 detail::RawFragmentHeader const fragmentHeader() const; 00752 #endif 00753 }; 00754 00755 #if HIDE_FROM_ROOT 00756 00757 // http://stackoverflow.com/questions/33939687 00758 // This should generate an exception if artdaq::Fragment is not move-constructible 00759 inline artdaq::Fragment::Fragment(artdaq::Fragment&&) noexcept = default; 00760 inline artdaq::Fragment& artdaq::Fragment::operator=(artdaq::Fragment&&) noexcept = default; 00761 00762 inline bool constexpr artdaq::Fragment:: 00763 isUserFragmentType(type_t fragmentType) 00764 { 00765 return fragmentType >= detail::RawFragmentHeader::FIRST_USER_TYPE && 00766 fragmentType <= detail::RawFragmentHeader::LAST_USER_TYPE; 00767 } 00768 00769 inline bool constexpr artdaq::Fragment:: 00770 isSystemFragmentType(type_t fragmentType) 00771 { 00772 return fragmentType >= detail::RawFragmentHeader::FIRST_SYSTEM_TYPE; 00773 } 00774 00775 template<typename T> 00776 std::size_t 00777 artdaq::Fragment:: 00778 validatedMetadataSize_() 00779 { 00780 // Make sure a size_t is big enough to hold the maximum metadata 00781 // size. This *should* always be true, but it is a compile-time check 00782 // and therefore cheap. 00783 static_assert(sizeof(size_t) >= 00784 sizeof(decltype(std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max())), 00785 "metadata_word_count_t is too big!"); 00786 00787 static size_t constexpr max_md_wc = 00788 std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max(); 00789 size_t requested_md_wc = 00790 std::ceil(sizeof(T) / static_cast<double>(sizeof(artdaq::RawDataType))); 00791 if (requested_md_wc > max_md_wc) 00792 { 00793 throw cet::exception("InvalidRequest") 00794 << "The requested metadata structure is too large: " 00795 << "requested word count = " << requested_md_wc 00796 << ", maximum word count = " << max_md_wc; 00797 } 00798 return requested_md_wc; 00799 } 00800 00801 template<class T> 00802 artdaq::Fragment:: 00803 Fragment(std::size_t payload_size, sequence_id_t sequence_id, 00804 fragment_id_t fragment_id, 00805 type_t type, const T& metadata, timestamp_t timestamp) 00806 : vals_((artdaq::detail::RawFragmentHeader::num_words() + // Header 00807 validatedMetadataSize_<T>() + // Metadata 00808 payload_size) // User data 00809 ) 00810 { 00811 TRACEN("Fragment", 50, "Fragment ctor num_word()=%zu MetadataSize_=%zu payload_size=%zu", artdaq::detail::RawFragmentHeader::num_words(), validatedMetadataSize_<T>(), payload_size); 00812 // vals ctor w/o init val is used; make sure header is ALL initialized. 00813 for (iterator ii = vals_.begin(); 00814 ii != (vals_.begin() + detail::RawFragmentHeader::num_words()); ++ii) 00815 { 00816 *ii = -1; 00817 } 00818 fragmentHeaderPtr()->version = detail::RawFragmentHeader::CurrentVersion; 00819 updateFragmentHeaderWC_(); 00820 fragmentHeaderPtr()->sequence_id = sequence_id; 00821 fragmentHeaderPtr()->fragment_id = fragment_id; 00822 fragmentHeaderPtr()->timestamp = timestamp; 00823 fragmentHeaderPtr()->type = type; 00824 00825 fragmentHeaderPtr()->touch(); 00826 00827 fragmentHeaderPtr()->metadata_word_count = 00828 vals_.size() - 00829 (headerSizeWords() + payload_size); 00830 00831 memcpy(metadataAddress(), &metadata, sizeof(T)); 00832 } 00833 00834 inline std::size_t 00835 artdaq::Fragment::size() const 00836 { 00837 return fragmentHeader().word_count; 00838 } 00839 00840 inline artdaq::Fragment::version_t 00841 artdaq::Fragment::version() const 00842 { 00843 auto hdr = reinterpret_cast_checked<detail::RawFragmentHeader const*>(&vals_[0]); 00844 return hdr->version; 00845 } 00846 00847 inline artdaq::Fragment::type_t 00848 artdaq::Fragment::type() const 00849 { 00850 return static_cast<type_t>(fragmentHeader().type); 00851 } 00852 00853 inline std::string 00854 artdaq::Fragment::typeString() const 00855 { 00856 return std::to_string(type()) + (isSystemFragmentType(type()) ? " (" + detail::RawFragmentHeader::SystemTypeToString(type()) + ")" : ""); 00857 } 00858 00859 inline artdaq::Fragment::sequence_id_t 00860 artdaq::Fragment::sequenceID() const 00861 { 00862 return fragmentHeader().sequence_id; 00863 } 00864 00865 inline artdaq::Fragment::fragment_id_t 00866 artdaq::Fragment::fragmentID() const 00867 { 00868 return fragmentHeader().fragment_id; 00869 } 00870 00871 inline artdaq::Fragment::timestamp_t 00872 artdaq::Fragment::timestamp() const 00873 { 00874 return fragmentHeader().timestamp; 00875 } 00876 00877 inline void 00878 artdaq::Fragment::setUserType(type_t type) 00879 { 00880 fragmentHeaderPtr()->setUserType(static_cast<uint8_t>(type)); 00881 } 00882 00883 inline void 00884 artdaq::Fragment::setSystemType(type_t type) 00885 { 00886 fragmentHeaderPtr()->setSystemType(static_cast<uint8_t>(type)); 00887 } 00888 00889 inline void 00890 artdaq::Fragment::setSequenceID(sequence_id_t sequence_id) 00891 { 00892 assert(sequence_id <= detail::RawFragmentHeader::InvalidSequenceID); 00893 fragmentHeaderPtr()->sequence_id = sequence_id; 00894 } 00895 00896 inline void 00897 artdaq::Fragment::setFragmentID(fragment_id_t fragment_id) 00898 { 00899 fragmentHeaderPtr()->fragment_id = fragment_id; 00900 } 00901 00902 inline void 00903 artdaq::Fragment::setTimestamp(timestamp_t timestamp) 00904 { 00905 fragmentHeaderPtr()->timestamp = timestamp; 00906 } 00907 00908 inline void artdaq::Fragment::touch() 00909 { 00910 fragmentHeaderPtr()->touch(); 00911 } 00912 00913 inline struct timespec artdaq::Fragment::atime() const 00914 { 00915 return fragmentHeader().atime(); 00916 } 00917 00918 inline struct timespec artdaq::Fragment::getLatency(bool touch) 00919 { 00920 return fragmentHeaderPtr()->getLatency(touch); 00921 } 00922 00923 inline void 00924 artdaq::Fragment::updateFragmentHeaderWC_() 00925 { 00926 // Make sure vals_.size() fits inside 32 bits. Left-shift here should 00927 // match bitfield size of word_count in RawFragmentHeader. 00928 assert(vals_.size() < (1ULL << 32)); 00929 TRACEN("Fragment", 50, "Fragment::updateFragmentHeaderWC_ adjusting fragmentHeader()->word_count from %u to %zu", (unsigned)(fragmentHeaderPtr()->word_count), vals_.size()); 00930 fragmentHeaderPtr()->word_count = vals_.size(); 00931 } 00932 00933 inline std::size_t 00934 artdaq::Fragment::dataSize() const 00935 { 00936 return vals_.size() - headerSizeWords() - 00937 fragmentHeader().metadata_word_count; 00938 } 00939 00940 inline bool 00941 artdaq::Fragment::hasMetadata() const 00942 { 00943 return fragmentHeader().metadata_word_count != 0; 00944 } 00945 00946 template<class T> 00947 T* artdaq::Fragment::metadata() 00948 { 00949 if (fragmentHeader().metadata_word_count == 0) 00950 { 00951 throw cet::exception("InvalidRequest") 00952 << "No metadata has been stored in this Fragment."; 00953 } 00954 00955 return reinterpret_cast_checked<T*>(&vals_[headerSizeWords()]); 00956 } 00957 00958 template<class T> 00959 T const* 00960 artdaq::Fragment::metadata() const 00961 { 00962 if (fragmentHeader().metadata_word_count == 0) 00963 { 00964 throw cet::exception("InvalidRequest") 00965 << "No metadata has been stored in this Fragment."; 00966 } 00967 return reinterpret_cast_checked<T const*>(&vals_[headerSizeWords()]); 00968 } 00969 00970 template<class T> 00971 void artdaq::Fragment::setMetadata(const T& metadata) 00972 { 00973 if (fragmentHeader().metadata_word_count != 0) 00974 { 00975 throw cet::exception("InvalidRequest") 00976 << "Metadata has already been stored in this Fragment."; 00977 } 00978 auto const mdSize = validatedMetadataSize_<T>(); 00979 vals_.insert(dataBegin(), mdSize, 0); 00980 updateFragmentHeaderWC_(); 00981 fragmentHeaderPtr()->metadata_word_count = mdSize; 00982 00983 memcpy(metadataAddress(), &metadata, sizeof(T)); 00984 } 00985 00986 template<class T> 00987 void artdaq::Fragment::updateMetadata(const T& metadata) 00988 { 00989 if (fragmentHeader().metadata_word_count == 0) 00990 { 00991 throw cet::exception("InvalidRequest") 00992 << "No metadata in fragment; please use Fragment::setMetadata instead of Fragment::updateMetadata"; 00993 } 00994 00995 auto const mdSize = validatedMetadataSize_<T>(); 00996 00997 if (fragmentHeader().metadata_word_count != mdSize) 00998 { 00999 throw cet::exception("InvalidRequest") 01000 << "Mismatch between type of metadata struct passed to updateMetadata and existing metadata struct"; 01001 } 01002 01003 memcpy(metadataAddress(), &metadata, sizeof(T)); 01004 } 01005 01006 inline void 01007 artdaq::Fragment::resize(std::size_t sz) 01008 { 01009 vals_.resize(sz + fragmentHeaderPtr()->metadata_word_count + 01010 headerSizeWords()); 01011 updateFragmentHeaderWC_(); 01012 } 01013 01014 inline void 01015 artdaq::Fragment::resize(std::size_t sz, RawDataType v) 01016 { 01017 vals_.resize(sz + fragmentHeaderPtr()->metadata_word_count + 01018 headerSizeWords(), 01019 v); 01020 updateFragmentHeaderWC_(); 01021 } 01022 01023 inline void 01024 artdaq::Fragment::resizeBytes(std::size_t szbytes) 01025 { 01026 RawDataType nwords = ceil(szbytes / static_cast<double>(sizeof(RawDataType))); 01027 resize(nwords); 01028 } 01029 01030 inline void 01031 artdaq::Fragment::resizeBytesWithCushion(std::size_t szbytes, double growthFactor) 01032 { 01033 RawDataType nwords = ceil(szbytes / static_cast<double>(sizeof(RawDataType))); 01034 vals_.resizeWithCushion(nwords + fragmentHeaderPtr()->metadata_word_count + 01035 headerSizeWords(), 01036 growthFactor); 01037 updateFragmentHeaderWC_(); 01038 } 01039 01040 inline void 01041 artdaq::Fragment::resizeBytes(std::size_t szbytes, byte_t v) 01042 { 01043 RawDataType defaultval; 01044 byte_t* ptr = reinterpret_cast_checked<byte_t*>(&defaultval); 01045 01046 for (uint8_t i = 0; i < sizeof(RawDataType); ++i) 01047 { 01048 *ptr = v; 01049 ptr++; 01050 } 01051 01052 RawDataType nwords = ceil(szbytes / static_cast<double>(sizeof(RawDataType))); 01053 01054 resize(nwords, defaultval); 01055 } 01056 01057 inline void 01058 artdaq::Fragment::autoResize() 01059 { 01060 vals_.resize(fragmentHeaderPtr()->word_count); 01061 updateFragmentHeaderWC_(); 01062 } 01063 01064 inline artdaq::Fragment::iterator 01065 artdaq::Fragment::dataBegin() 01066 { 01067 return vals_.begin() + headerSizeWords() + 01068 fragmentHeader().metadata_word_count; 01069 } 01070 01071 inline artdaq::Fragment::iterator 01072 artdaq::Fragment::dataEnd() 01073 { 01074 return vals_.end(); 01075 } 01076 01077 inline artdaq::Fragment::iterator 01078 artdaq::Fragment::headerBegin() 01079 { 01080 return vals_.begin(); 01081 } 01082 01083 inline artdaq::Fragment::const_iterator 01084 artdaq::Fragment::dataBegin() const 01085 { 01086 return vals_.begin() + headerSizeWords() + 01087 fragmentHeader().metadata_word_count; 01088 } 01089 01090 inline artdaq::Fragment::const_iterator 01091 artdaq::Fragment::dataEnd() const 01092 { 01093 return vals_.end(); 01094 } 01095 01096 inline artdaq::Fragment::const_iterator 01097 artdaq::Fragment::headerBegin() const 01098 { 01099 return vals_.begin(); 01100 } 01101 01102 inline void 01103 artdaq::Fragment::clear() 01104 { 01105 vals_.erase(dataBegin(), dataEnd()); 01106 updateFragmentHeaderWC_(); 01107 } 01108 01109 inline bool 01110 artdaq::Fragment::empty() 01111 { 01112 return (vals_.size() - headerSizeWords() - 01113 fragmentHeader().metadata_word_count) == 0; 01114 } 01115 01116 inline void 01117 artdaq::Fragment::reserve(std::size_t cap) 01118 { 01119 vals_.reserve(cap + headerSizeWords() + 01120 fragmentHeader().metadata_word_count); 01121 } 01122 01123 inline void 01124 artdaq::Fragment::swap(Fragment& other) noexcept 01125 { 01126 vals_.swap(other.vals_); 01127 } 01128 01129 inline artdaq::RawDataType* 01130 artdaq::Fragment::dataAddress() 01131 { 01132 return &vals_[0] + headerSizeWords() + 01133 fragmentHeader().metadata_word_count; 01134 } 01135 01136 inline artdaq::RawDataType* 01137 artdaq::Fragment::metadataAddress() 01138 { 01139 if (fragmentHeader().metadata_word_count == 0) 01140 { 01141 throw cet::exception("InvalidRequest") 01142 << "No metadata has been stored in this Fragment."; 01143 } 01144 return &vals_[0] + headerSizeWords(); 01145 } 01146 01147 inline artdaq::RawDataType* 01148 artdaq::Fragment::headerAddress() 01149 { 01150 return &vals_[0]; 01151 } 01152 01153 inline size_t 01154 artdaq::Fragment::headerSizeWords() const 01155 { 01156 auto hdr = reinterpret_cast_checked<detail::RawFragmentHeader const*>(&vals_[0]); 01157 if (hdr->version != detail::RawFragmentHeader::CurrentVersion) 01158 { 01159 switch (hdr->version) 01160 { 01161 case 0xFFFF: 01162 TLOG(51, "Fragment") << "Cannot get header size of InvalidVersion Fragment"; 01163 break; 01164 case 0: 01165 { 01166 TLOG(52, "Fragment") << "Getting size of RawFragmentHeaderV0"; 01167 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV0 const*>(&vals_[0]); 01168 return old_hdr->num_words(); 01169 break; 01170 } 01171 case 1: 01172 { 01173 TLOG(52, "Fragment") << "Getting size of RawFragmentHeaderV1"; 01174 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV1 const*>(&vals_[0]); 01175 return old_hdr->num_words(); 01176 break; 01177 } 01178 default: 01179 throw cet::exception("Fragment") << "A Fragment with an unknown version (" << std::to_string(hdr->version) << ") was received!"; 01180 break; 01181 } 01182 } 01183 return hdr->num_words(); 01184 } 01185 01186 inline artdaq::detail::RawFragmentHeader* 01187 artdaq::Fragment::fragmentHeaderPtr() 01188 { 01189 auto hdr = reinterpret_cast_checked<detail::RawFragmentHeader*>(&vals_[0]); 01190 if (hdr->version != detail::RawFragmentHeader::CurrentVersion) 01191 { 01192 switch (hdr->version) 01193 { 01194 case 0xFFFF: 01195 TLOG(51, "Fragment") << "Not upgrading InvalidVersion Fragment"; 01196 break; 01197 case 0: 01198 { 01199 TLOG(52, "Fragment") << "Upgrading RawFragmentHeaderV0 (non const)"; 01200 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV0*>(&vals_[0]); 01201 auto new_hdr = old_hdr->upgrade(); 01202 01203 auto szDiff = hdr->num_words() - old_hdr->num_words(); 01204 if (szDiff > 0) 01205 { 01206 vals_.insert(vals_.begin(), szDiff, 0); 01207 new_hdr.word_count = vals_.size(); 01208 } 01209 memcpy(&vals_[0], &new_hdr, hdr->num_words() * sizeof(RawDataType)); 01210 hdr = reinterpret_cast_checked<detail::RawFragmentHeader*>(&vals_[0]); // Update hdr in case vals_->insert call invalidated pointers 01211 break; 01212 } 01213 case 1: 01214 { 01215 TLOG(52, "Fragment") << "Upgrading RawFragmentHeaderV1 (non const)"; 01216 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV1*>(&vals_[0]); 01217 auto new_hdr = old_hdr->upgrade(); 01218 01219 auto szDiff = hdr->num_words() - old_hdr->num_words(); 01220 if (szDiff > 0) 01221 { 01222 vals_.insert(vals_.begin(), szDiff, 0); 01223 new_hdr.word_count = vals_.size(); 01224 } 01225 memcpy(&vals_[0], &new_hdr, hdr->num_words() * sizeof(RawDataType)); 01226 hdr = reinterpret_cast_checked<detail::RawFragmentHeader*>(&vals_[0]); // Update hdr in case vals_->insert call invalidated pointers 01227 break; 01228 } 01229 default: 01230 throw cet::exception("Fragment") << "A Fragment with an unknown version (" << std::to_string(hdr->version) << ") was received!"; 01231 break; 01232 } 01233 } 01234 return hdr; 01235 } 01236 01237 inline artdaq::detail::RawFragmentHeader const 01238 artdaq::Fragment::fragmentHeader() const 01239 { 01240 auto hdr = *reinterpret_cast_checked<detail::RawFragmentHeader const*>(&vals_[0]); 01241 if (hdr.version != detail::RawFragmentHeader::CurrentVersion) 01242 { 01243 switch (hdr.version) 01244 { 01245 case 0xFFFF: 01246 TLOG(51, "Fragment") << "Not upgrading InvalidVersion Fragment"; 01247 break; 01248 case 0: 01249 { 01250 TLOG(52, "Fragment") << "Upgrading RawFragmentHeaderV0 (const)"; 01251 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV0 const*>(&vals_[0]); 01252 hdr = old_hdr->upgrade(); 01253 01254 break; 01255 } 01256 case 1: 01257 { 01258 TLOG(52, "Fragment") << "Upgrading RawFragmentHeaderV1 (const)"; 01259 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV1 const*>(&vals_[0]); 01260 hdr = old_hdr->upgrade(); 01261 01262 break; 01263 } 01264 default: 01265 throw cet::exception("Fragment") << "A Fragment with an unknown version (" << std::to_string(hdr.version) << ") was received!"; 01266 break; 01267 } 01268 } 01269 return hdr; 01270 } 01271 01272 inline void 01273 swap(artdaq::Fragment& x, artdaq::Fragment& y) noexcept 01274 { 01275 x.swap(y); 01276 } 01277 01278 inline std::ostream& 01279 artdaq::operator<<(std::ostream& os, artdaq::Fragment const& f) 01280 { 01281 f.print(os); 01282 return os; 01283 } 01284 #endif /* HIDE_FROM_ROOT */ 01285 01286 #endif /* artdaq_core_Data_Fragment_hh */