$treeview $search $mathjax $extrastylesheet
artdaq_core
v3_05_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 <cstddef> 00007 #include <iosfwd> 00008 #include <iterator> 00009 #include <vector> 00010 #include <list> 00011 #include <memory> 00012 #include <map> 00013 #include <cmath> 00014 #include <stdint.h> 00015 #include <string.h> 00016 00017 #include "artdaq-core/Data/detail/RawFragmentHeader.hh" 00018 #include "artdaq-core/Data/detail/RawFragmentHeaderV0.hh" 00019 #include "artdaq-core/Data/detail/RawFragmentHeaderV1.hh" 00020 #include "artdaq-core/Data/dictionarycontrol.hh" 00021 #include "artdaq-core/Core/QuickVec.hh" 00022 #include <iostream> 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 } 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(); 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 00369 00375 std::size_t dataSizeBytes() const 00376 { 00377 return sizeof(RawDataType) * dataSize(); 00378 } 00379 00384 bool hasMetadata() const; 00385 00393 template <class T> 00394 T* metadata(); 00395 00403 template <class T> 00404 T const* metadata() const; 00405 00414 template <class T> 00415 void setMetadata(const T& md); 00416 00424 template <class T> 00425 void updateMetadata(const T& md); 00426 00431 void resize(std::size_t sz); 00432 00438 void resize(std::size_t sz, RawDataType val); 00439 00446 void resizeBytes(std::size_t szbytes); 00447 00456 void resizeBytesWithCushion(std::size_t szbytes, double growthFactor=1.3); 00457 00465 void resizeBytes(std::size_t szbytes, byte_t val); 00466 00470 void autoResize(); 00471 00476 iterator dataBegin(); 00477 00482 iterator dataEnd(); 00483 00503 template <typename T> 00504 T reinterpret_cast_checked(const RawDataType* in) const 00505 { 00506 T newpointer = reinterpret_cast<T>(in); 00507 00508 if (static_cast<const void*>(newpointer) != static_cast<const void*>(in)) 00509 { 00510 throw cet::exception("Error in Fragment.hh: reinterpret_cast failed to return expected address-- please contact John Freeman at jcfree@fnal.gov"); 00511 } 00512 00513 return newpointer; 00514 } 00515 00531 template <typename T> 00532 T reinterpret_cast_checked(RawDataType* in) 00533 { 00534 T newpointer = reinterpret_cast<T>(in); 00535 00536 if (static_cast<void*>(newpointer) != static_cast<void*>(in)) 00537 { 00538 throw cet::exception("Error in Fragment.hh: reinterpret_cast failed to return expected address-- please contact John Freeman at jcfree@fnal.gov"); 00539 } 00540 00541 return newpointer; 00542 } 00543 00552 byte_t* dataBeginBytes() { return reinterpret_cast_checked<byte_t*>(&* dataBegin()); } 00553 00562 byte_t* dataEndBytes() { return reinterpret_cast_checked<byte_t*>(&* dataEnd()); } 00563 00569 iterator headerBegin(); 00570 00575 byte_t* headerBeginBytes() { return reinterpret_cast_checked<byte_t*>(&* headerBegin()); } 00576 00581 const_iterator dataBegin() const; 00582 00587 const_iterator dataEnd() const; 00588 00597 const byte_t* dataBeginBytes() const 00598 { 00599 return reinterpret_cast_checked<const byte_t*>(&* dataBegin()); 00600 } 00601 00610 const byte_t* dataEndBytes() const 00611 { 00612 return reinterpret_cast_checked<const byte_t*>(&* dataEnd()); 00613 } 00614 00620 const_iterator headerBegin() const; // See note for non-const, above. 00621 00626 const byte_t* headerBeginBytes() const 00627 { 00628 return reinterpret_cast_checked<const byte_t*>(&* headerBegin()); 00629 } 00630 00634 void clear(); 00635 00640 bool empty(); 00641 00646 void reserve(std::size_t cap); 00647 00652 void swap(Fragment& other) noexcept; 00653 00660 void swap(DATAVEC_T& other) noexcept { vals_.swap(other); }; 00661 00666 RawDataType* dataAddress(); 00667 00674 RawDataType* metadataAddress(); 00679 RawDataType* headerAddress(); 00680 00686 static FragmentPtr eodFrag(size_t nFragsToExpect); 00687 00699 template<class InputIterator> static FragmentPtr dataFrag(sequence_id_t sequenceID, 00700 fragment_id_t fragID, 00701 InputIterator i, 00702 InputIterator e) 00703 { 00704 FragmentPtr result(new Fragment(sequenceID, fragID)); 00705 result->vals_.reserve(std::distance(i, e) + detail::RawFragmentHeader::num_words()); 00706 std::copy(i, e, std::back_inserter(result->vals_)); 00707 result->updateFragmentHeaderWC_(); 00708 return result; 00709 } 00710 00720 static FragmentPtr dataFrag(sequence_id_t sequenceID, 00721 fragment_id_t fragID, 00722 RawDataType const* dataPtr, 00723 size_t dataSize, 00724 timestamp_t timestamp = Fragment::InvalidTimestamp); 00725 #endif 00726 00727 private: 00728 template <typename T> 00729 static std::size_t validatedMetadataSize_(); 00730 00731 void updateFragmentHeaderWC_(); 00732 00733 DATAVEC_T vals_; 00734 00735 #if HIDE_FROM_ROOT 00736 detail::RawFragmentHeader* fragmentHeader(); 00737 00738 detail::RawFragmentHeader const* fragmentHeader() const; 00739 #endif 00740 }; 00741 00742 #if HIDE_FROM_ROOT 00743 00744 00745 // http://stackoverflow.com/questions/33939687 00746 // This should generate an exception if artdaq::Fragment is not move-constructible 00747 inline artdaq::Fragment::Fragment(artdaq::Fragment&&) noexcept = default; 00748 inline artdaq::Fragment& artdaq::Fragment::operator=(artdaq::Fragment&&) noexcept = default; 00749 00750 inline 00751 bool 00752 constexpr 00753 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 00761 bool 00762 constexpr 00763 artdaq::Fragment:: 00764 isSystemFragmentType(type_t fragmentType) 00765 { 00766 return fragmentType >= detail::RawFragmentHeader::FIRST_SYSTEM_TYPE; 00767 } 00768 00769 template <typename T> 00770 std::size_t 00771 artdaq::Fragment:: 00772 validatedMetadataSize_() 00773 { 00774 // Make sure a size_t is big enough to hold the maximum metadata 00775 // size. This *should* always be true, but it is a compile-time check 00776 // and therefore cheap. 00777 static_assert(sizeof(size_t) >= 00778 sizeof(decltype(std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max())), 00779 "metadata_word_count_t is too big!"); 00780 00781 static size_t constexpr max_md_wc = 00782 std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max(); 00783 size_t requested_md_wc = 00784 std::ceil(sizeof(T) / static_cast<double>(sizeof(artdaq::RawDataType))); 00785 if (requested_md_wc > max_md_wc) 00786 { 00787 throw cet::exception("InvalidRequest") 00788 << "The requested metadata structure is too large: " 00789 << "requested word count = " << requested_md_wc 00790 << ", maximum word count = " << max_md_wc; 00791 } 00792 return requested_md_wc; 00793 } 00794 00795 template <class T> 00796 artdaq::Fragment:: 00797 Fragment(std::size_t payload_size, sequence_id_t sequence_id, 00798 fragment_id_t fragment_id, 00799 type_t type, const T& metadata, timestamp_t timestamp) : 00800 vals_((artdaq::detail::RawFragmentHeader::num_words() + // Header 00801 validatedMetadataSize_<T>() + // Metadata 00802 payload_size) // User data 00803 ) 00804 { 00805 TRACEN( "Fragment", 50, "Fragment ctor num_word()=%zu MetadataSize_=%zu payload_size=%zu" 00806 ,artdaq::detail::RawFragmentHeader::num_words(), validatedMetadataSize_<T>(), payload_size ); 00807 // vals ctor w/o init val is used; make sure header is ALL initialized. 00808 for (iterator ii = vals_.begin(); 00809 ii != (vals_.begin() + detail::RawFragmentHeader::num_words()); ++ii) { 00810 *ii = -1; 00811 } 00812 fragmentHeader()->version = detail::RawFragmentHeader::CurrentVersion; 00813 updateFragmentHeaderWC_(); 00814 fragmentHeader()->sequence_id = sequence_id; 00815 fragmentHeader()->fragment_id = fragment_id; 00816 fragmentHeader()->timestamp = timestamp; 00817 fragmentHeader()->type = type; 00818 00819 fragmentHeader()->touch(); 00820 00821 fragmentHeader()->metadata_word_count = 00822 vals_.size() - 00823 (fragmentHeader()->num_words() + payload_size); 00824 00825 memcpy(metadataAddress(), &metadata, sizeof(T)); 00826 } 00827 00828 inline 00829 std::size_t 00830 artdaq::Fragment::size() const 00831 { 00832 return fragmentHeader()->word_count; 00833 } 00834 00835 inline 00836 artdaq::Fragment::version_t 00837 artdaq::Fragment::version() const 00838 { 00839 return fragmentHeader()->version; 00840 } 00841 00842 inline 00843 artdaq::Fragment::type_t 00844 artdaq::Fragment::type() const 00845 { 00846 return static_cast<type_t>(fragmentHeader()->type); 00847 } 00848 00849 inline 00850 std::string 00851 artdaq::Fragment::typeString() const 00852 { 00853 return std::to_string(type()) + (isSystemFragmentType(type()) ? " (" + detail::RawFragmentHeader::SystemTypeToString(type()) + ")" : ""); 00854 } 00855 00856 inline 00857 artdaq::Fragment::sequence_id_t 00858 artdaq::Fragment::sequenceID() const 00859 { 00860 return fragmentHeader()->sequence_id; 00861 } 00862 00863 inline 00864 artdaq::Fragment::fragment_id_t 00865 artdaq::Fragment::fragmentID() const 00866 { 00867 return fragmentHeader()->fragment_id; 00868 } 00869 00870 inline 00871 artdaq::Fragment::timestamp_t 00872 artdaq::Fragment::timestamp() const 00873 { 00874 return fragmentHeader()->timestamp; 00875 } 00876 00877 inline 00878 void 00879 artdaq::Fragment::setUserType(type_t type) 00880 { 00881 fragmentHeader()->setUserType(static_cast<uint8_t>(type)); 00882 } 00883 00884 inline 00885 void 00886 artdaq::Fragment::setSystemType(type_t type) 00887 { 00888 fragmentHeader()->setSystemType(static_cast<uint8_t>(type)); 00889 } 00890 00891 inline 00892 void 00893 artdaq::Fragment::setSequenceID(sequence_id_t sequence_id) 00894 { 00895 assert(sequence_id <= detail::RawFragmentHeader::InvalidSequenceID); 00896 fragmentHeader()->sequence_id = sequence_id; 00897 } 00898 00899 inline 00900 void 00901 artdaq::Fragment::setFragmentID(fragment_id_t fragment_id) 00902 { 00903 fragmentHeader()->fragment_id = fragment_id; 00904 } 00905 00906 inline 00907 void 00908 artdaq::Fragment::setTimestamp(timestamp_t timestamp) 00909 { 00910 fragmentHeader()->timestamp = timestamp; 00911 } 00912 00913 00914 inline void artdaq::Fragment::touch() 00915 { 00916 fragmentHeader()->touch(); 00917 } 00918 00919 inline struct timespec artdaq::Fragment::atime() 00920 { 00921 return fragmentHeader()->atime(); 00922 } 00923 00924 inline struct timespec artdaq::Fragment::getLatency(bool touch) { 00925 return fragmentHeader()->getLatency(touch); 00926 } 00927 00928 inline 00929 void 00930 artdaq::Fragment::updateFragmentHeaderWC_() 00931 { 00932 // Make sure vals_.size() fits inside 32 bits. Left-shift here should 00933 // match bitfield size of word_count in RawFragmentHeader. 00934 assert(vals_.size() < (1ULL << 32)); 00935 TRACEN( "Fragment", 50, "Fragment::updateFragmentHeaderWC_ adjusting fragmentHeader()->word_count from %u to %zu", (unsigned)(fragmentHeader()->word_count), vals_.size() ); 00936 fragmentHeader()->word_count = vals_.size(); 00937 } 00938 00939 inline 00940 std::size_t 00941 artdaq::Fragment::dataSize() const 00942 { 00943 return vals_.size() - fragmentHeader()->num_words() - 00944 fragmentHeader()->metadata_word_count; 00945 } 00946 00947 inline 00948 bool 00949 artdaq::Fragment::hasMetadata() const 00950 { 00951 return fragmentHeader()->metadata_word_count != 0; 00952 } 00953 00954 template <class T> 00955 T* 00956 artdaq::Fragment::metadata() 00957 { 00958 if (fragmentHeader()->metadata_word_count == 0) 00959 { 00960 throw cet::exception("InvalidRequest") 00961 << "No metadata has been stored in this Fragment."; 00962 } 00963 00964 return reinterpret_cast_checked<T *> 00965 (&vals_[fragmentHeader()->num_words()]); 00966 } 00967 00968 template <class T> 00969 T const* 00970 artdaq::Fragment::metadata() const 00971 { 00972 if (fragmentHeader()->metadata_word_count == 0) 00973 { 00974 throw cet::exception("InvalidRequest") 00975 << "No metadata has been stored in this Fragment."; 00976 } 00977 return reinterpret_cast_checked<T const *> 00978 (&vals_[fragmentHeader()->num_words()]); 00979 } 00980 00981 template <class T> 00982 void 00983 artdaq::Fragment::setMetadata(const T& metadata) 00984 { 00985 if (fragmentHeader()->metadata_word_count != 0) 00986 { 00987 throw cet::exception("InvalidRequest") 00988 << "Metadata has already been stored in this Fragment."; 00989 } 00990 auto const mdSize = validatedMetadataSize_<T>(); 00991 vals_.insert(dataBegin(), mdSize, 0); 00992 updateFragmentHeaderWC_(); 00993 fragmentHeader()->metadata_word_count = mdSize; 00994 00995 memcpy(metadataAddress(), &metadata, sizeof(T)); 00996 } 00997 00998 template <class T> 00999 void 01000 artdaq::Fragment::updateMetadata(const T& metadata) 01001 { 01002 if (fragmentHeader()->metadata_word_count == 0) 01003 { 01004 throw cet::exception("InvalidRequest") 01005 << "No metadata in fragment; please use Fragment::setMetadata instead of Fragment::updateMetadata"; 01006 } 01007 01008 auto const mdSize = validatedMetadataSize_<T>(); 01009 01010 if (fragmentHeader()->metadata_word_count != mdSize) 01011 { 01012 throw cet::exception("InvalidRequest") 01013 << "Mismatch between type of metadata struct passed to updateMetadata and existing metadata struct"; 01014 } 01015 01016 memcpy(metadataAddress(), &metadata, sizeof(T)); 01017 } 01018 01019 inline void 01020 artdaq::Fragment::resize(std::size_t sz) 01021 { 01022 vals_.resize(sz + fragmentHeader()->metadata_word_count + 01023 fragmentHeader()->num_words()); 01024 updateFragmentHeaderWC_(); 01025 } 01026 01027 inline 01028 void 01029 artdaq::Fragment::resize(std::size_t sz, RawDataType v) 01030 { 01031 vals_.resize(sz + fragmentHeader()->metadata_word_count + 01032 fragmentHeader()->num_words(), v); 01033 updateFragmentHeaderWC_(); 01034 } 01035 01036 inline void 01037 artdaq::Fragment::resizeBytes(std::size_t szbytes) 01038 { 01039 RawDataType nwords = ceil(szbytes / static_cast<double>(sizeof(RawDataType))); 01040 resize(nwords); 01041 } 01042 01043 inline void 01044 artdaq::Fragment::resizeBytesWithCushion(std::size_t szbytes, double growthFactor) 01045 { 01046 RawDataType nwords = ceil(szbytes / static_cast<double>(sizeof(RawDataType))); 01047 vals_.resizeWithCushion(nwords + fragmentHeader()->metadata_word_count + 01048 fragmentHeader()->num_words(), growthFactor); 01049 updateFragmentHeaderWC_(); 01050 } 01051 01052 inline 01053 void 01054 artdaq::Fragment::resizeBytes(std::size_t szbytes, byte_t v) 01055 { 01056 RawDataType defaultval; 01057 byte_t* ptr = reinterpret_cast_checked<byte_t*>(&defaultval); 01058 01059 for (uint8_t i = 0; i < sizeof(RawDataType); ++i) 01060 { 01061 *ptr = v; 01062 ptr++; 01063 } 01064 01065 RawDataType nwords = ceil(szbytes / static_cast<double>(sizeof(RawDataType))); 01066 01067 resize(nwords, defaultval); 01068 } 01069 01070 01071 inline 01072 void 01073 artdaq::Fragment::autoResize() 01074 { 01075 vals_.resize(fragmentHeader()->word_count); 01076 updateFragmentHeaderWC_(); 01077 } 01078 01079 inline 01080 artdaq::Fragment::iterator 01081 artdaq::Fragment::dataBegin() 01082 { 01083 return vals_.begin() + fragmentHeader()->num_words() + 01084 fragmentHeader()->metadata_word_count; 01085 } 01086 01087 inline 01088 artdaq::Fragment::iterator 01089 artdaq::Fragment::dataEnd() 01090 { 01091 return vals_.end(); 01092 } 01093 01094 inline 01095 artdaq::Fragment::iterator 01096 artdaq::Fragment::headerBegin() 01097 { 01098 return vals_.begin(); 01099 } 01100 01101 inline 01102 artdaq::Fragment::const_iterator 01103 artdaq::Fragment::dataBegin() const 01104 { 01105 return vals_.begin() + fragmentHeader()->num_words() + 01106 fragmentHeader()->metadata_word_count; 01107 } 01108 01109 inline 01110 artdaq::Fragment::const_iterator 01111 artdaq::Fragment::dataEnd() const 01112 { 01113 return vals_.end(); 01114 } 01115 01116 inline 01117 artdaq::Fragment::const_iterator 01118 artdaq::Fragment::headerBegin() const 01119 { 01120 return vals_.begin(); 01121 } 01122 01123 01124 inline 01125 void 01126 artdaq::Fragment::clear() 01127 { 01128 vals_.erase(dataBegin(), dataEnd()); 01129 updateFragmentHeaderWC_(); 01130 } 01131 01132 inline 01133 bool 01134 artdaq::Fragment::empty() 01135 { 01136 return (vals_.size() - fragmentHeader()->num_words() - 01137 fragmentHeader()->metadata_word_count) == 0; 01138 } 01139 01140 inline 01141 void 01142 artdaq::Fragment::reserve(std::size_t cap) 01143 { 01144 vals_.reserve(cap + fragmentHeader()->num_words() + 01145 fragmentHeader()->metadata_word_count); 01146 } 01147 01148 inline 01149 void 01150 artdaq::Fragment::swap(Fragment& other) noexcept 01151 { 01152 vals_.swap(other.vals_); 01153 } 01154 01155 inline 01156 artdaq::RawDataType* 01157 artdaq::Fragment::dataAddress() 01158 { 01159 return &vals_[0] + fragmentHeader()->num_words() + 01160 fragmentHeader()->metadata_word_count; 01161 } 01162 01163 inline 01164 artdaq::RawDataType* 01165 artdaq::Fragment::metadataAddress() 01166 { 01167 if (fragmentHeader()->metadata_word_count == 0) 01168 { 01169 throw cet::exception("InvalidRequest") 01170 << "No metadata has been stored in this Fragment."; 01171 } 01172 return &vals_[0] + fragmentHeader()->num_words(); 01173 } 01174 01175 inline 01176 artdaq::RawDataType* 01177 artdaq::Fragment::headerAddress() 01178 { 01179 return &vals_[0]; 01180 } 01181 01182 inline 01183 artdaq::detail::RawFragmentHeader* 01184 artdaq::Fragment::fragmentHeader() 01185 { 01186 auto hdr = reinterpret_cast_checked<detail::RawFragmentHeader *>(&vals_[0]); 01187 if (hdr->version != detail::RawFragmentHeader::CurrentVersion) 01188 { 01189 switch (hdr->version) 01190 { 01191 case 0xFFFF: 01192 //std::cout << "Not upgrading InvalidVersion Fragment" << std::endl; 01193 break; 01194 case 0: 01195 { 01196 std::cout << "Upgrading RawFragmentHeaderV0 (non const)" << std::endl; 01197 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV0 *>(&vals_[0]); 01198 auto new_hdr = old_hdr->upgrade(); 01199 01200 auto szDiff = hdr->num_words() - old_hdr->num_words(); 01201 if (szDiff > 0) vals_.insert(vals_.begin(), szDiff, 0); 01202 memcpy(&vals_[0], &new_hdr, hdr->num_words() * sizeof(RawDataType)); 01203 break; 01204 } 01205 case 1: 01206 { 01207 std::cout << "Upgrading RawFragmentHeaderV1 (non const)" << std::endl; 01208 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV1 *>(&vals_[0]); 01209 auto new_hdr = old_hdr->upgrade(); 01210 01211 auto szDiff = hdr->num_words() - old_hdr->num_words(); 01212 if (szDiff > 0) vals_.insert(vals_.begin(), szDiff, 0); 01213 memcpy(&vals_[0], &new_hdr, hdr->num_words() * sizeof(RawDataType)); 01214 break; 01215 } 01216 default: 01217 throw cet::exception("Fragment") << "A Fragment with an unknown version (" << std::to_string(hdr->version) << ") was received!"; 01218 break; 01219 } 01220 } 01221 return hdr; 01222 } 01223 01224 inline 01225 artdaq::detail::RawFragmentHeader const* 01226 artdaq::Fragment::fragmentHeader() const 01227 { 01228 auto hdr = reinterpret_cast_checked<detail::RawFragmentHeader const*>(&vals_[0]); 01229 if (hdr->version != detail::RawFragmentHeader::CurrentVersion) 01230 { 01231 switch (hdr->version) 01232 { 01233 case 0xFFFF: 01234 //std::cout << "Not upgrading InvalidVersion Fragment" << std::endl; 01235 break; 01236 case 0: 01237 { 01238 std::cout << "Upgrading RawFragmentHeaderV0 (const)" << std::endl; 01239 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV0 const*>(&vals_[0]); 01240 auto new_hdr = old_hdr->upgrade(); 01241 01242 auto szDiff = hdr->num_words() - old_hdr->num_words(); 01243 auto vals_nc = const_cast<DATAVEC_T*>(&vals_); 01244 if (szDiff > 0) vals_nc->insert(vals_nc->begin(), szDiff, 0); 01245 memcpy(&(*vals_nc)[0], &new_hdr, hdr->num_words() * sizeof(RawDataType)); 01246 break; 01247 } 01248 case 1: 01249 { 01250 std::cout << "Upgrading RawFragmentHeaderV1 (const)" << std::endl; 01251 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV1 const*>(&vals_[0]); 01252 auto new_hdr = old_hdr->upgrade(); 01253 01254 auto szDiff = hdr->num_words() - old_hdr->num_words(); 01255 auto vals_nc = const_cast<DATAVEC_T*>(&vals_); 01256 if (szDiff > 0) vals_nc->insert(vals_nc->begin(), szDiff, 0); 01257 memcpy(&(*vals_nc)[0], &new_hdr, hdr->num_words() * sizeof(RawDataType)); 01258 break; 01259 } 01260 default: 01261 throw cet::exception("Fragment") << "A Fragment with an unknown version (" << std::to_string(hdr->version) << ") was received!"; 01262 break; 01263 } 01264 } 01265 return hdr; 01266 } 01267 01268 inline 01269 void 01270 swap(artdaq::Fragment& x, artdaq::Fragment& y) noexcept 01271 { 01272 x.swap(y); 01273 } 01274 01275 inline 01276 std::ostream& 01277 artdaq::operator<<(std::ostream& os, artdaq::Fragment const& f) 01278 { 01279 f.print(os); 01280 return os; 01281 } 01282 #endif/* HIDE_FROM_ROOT */ 01283 01284 #endif /* artdaq_core_Data_Fragment_hh */