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