$treeview $search $mathjax $extrastylesheet
artdaq_core
v3_06_01
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #ifndef artdaq_core_Data_ContainerFragment_hh 00002 #define artdaq_core_Data_ContainerFragment_hh 00003 00004 #include <memory> 00005 #include "artdaq-core/Data/Fragment.hh" 00006 #include "cetlib_except/exception.h" 00007 00008 //#include <ostream> 00009 //#include <vector> 00010 00011 // Implementation of "ContainerFragment", an artdaq::Fragment overlay class 00012 00013 namespace artdaq { 00014 class ContainerFragment; 00015 } 00016 00020 class artdaq::ContainerFragment 00021 { 00022 public: 00024 static constexpr uint8_t CURRENT_VERSION = 1; 00026 static constexpr size_t CONTAINER_MAGIC = 0x00BADDEED5B1BEE5; 00027 00031 struct MetadataV0 00032 { 00036 static constexpr int CONTAINER_FRAGMENT_COUNT_MAX = 100; 00037 00038 typedef uint8_t data_t; 00039 typedef uint64_t count_t; 00040 00041 count_t block_count : 55; 00042 count_t fragment_type : 8; 00043 count_t missing_data : 1; 00044 00046 size_t index[CONTAINER_FRAGMENT_COUNT_MAX]; 00047 00049 static size_t const size_words = 8ul + CONTAINER_FRAGMENT_COUNT_MAX * sizeof(size_t) / sizeof(data_t); // Units of Header::data_t 00050 }; 00051 static_assert(sizeof(MetadataV0) == MetadataV0::size_words * sizeof(MetadataV0::data_t), "ContainerFragment::MetadataV0 size changed"); 00052 00056 struct Metadata 00057 { 00058 typedef uint8_t data_t; 00059 typedef uint64_t count_t; 00060 00061 count_t block_count : 16; 00062 count_t fragment_type : 8; 00063 count_t version : 4; 00064 count_t missing_data : 1; 00065 count_t has_index : 1; 00066 count_t unused_flag1 : 1; 00067 count_t unused_flag2 : 1; 00068 count_t unused : 32; 00069 00070 uint64_t index_offset; 00071 00073 static size_t const size_words = 16ul; // Units of Header::data_t 00074 }; 00075 static_assert(sizeof(Metadata) == Metadata::size_words * sizeof(Metadata::data_t), "ContainerFragment::Metadata size changed"); 00076 00082 Metadata const* UpgradeMetadata(MetadataV0 const* in) const 00083 { 00084 TLOG(TLVL_DEBUG, "ContainerFragment") << "Upgrading ContainerFragment::MetadataV0 into new ContainerFragment::Metadata"; 00085 assert(in->block_count < std::numeric_limits<Metadata::count_t>::max()); 00086 Metadata md; 00087 md.block_count = in->block_count; 00088 md.fragment_type = in->fragment_type; 00089 md.has_index = 0; 00090 md.missing_data = in->missing_data; 00091 md.version = 0; 00092 index_ptr_ = in->index; 00093 metadata_ = std::make_unique<Metadata>(md); 00094 return metadata_.get(); 00095 } 00096 00103 explicit ContainerFragment(Fragment const& f) 00104 : artdaq_Fragment_(f), index_ptr_(nullptr), index_ptr_owner_(nullptr), metadata_(nullptr) {} 00105 00106 virtual ~ContainerFragment() 00107 { 00108 } 00109 00114 Metadata const* metadata() const 00115 { 00116 if (metadata_) return metadata_.get(); 00117 00118 if (artdaq_Fragment_.sizeBytes() - artdaq_Fragment_.dataSizeBytes() - artdaq_Fragment_.headerSizeBytes() == sizeof(MetadataV0)) 00119 { 00120 return UpgradeMetadata(artdaq_Fragment_.metadata<MetadataV0>()); 00121 } 00122 00123 return artdaq_Fragment_.metadata<Metadata>(); 00124 } 00125 00130 Metadata::count_t block_count() const { return metadata()->block_count; } 00135 Fragment::type_t fragment_type() const { return static_cast<Fragment::type_t>(metadata()->fragment_type); } 00140 bool missing_data() const { return static_cast<bool>(metadata()->missing_data); } 00141 00146 void const* dataBegin() const 00147 { 00148 return reinterpret_cast<void const*>(&*artdaq_Fragment_.dataBegin()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) 00149 } 00150 00155 void const* dataEnd() const 00156 { 00157 return reinterpret_cast<void const*>(reinterpret_cast<uint8_t const*>(dataBegin()) + lastFragmentIndex()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-bounds-pointer-arithmetic) 00158 } 00159 00166 FragmentPtr at(size_t index) const 00167 { 00168 if (index >= block_count() || block_count() == 0) 00169 { 00170 throw cet::exception("ArgumentOutOfRange") << "Buffer overrun detected! ContainerFragment::at was asked for a non-existent Fragment!"; // NOLINT(cert-err60-cpp) 00171 } 00172 00173 FragmentPtr frag(nullptr); 00174 auto size = fragSize(index); 00175 if (size < sizeof(RawDataType) * detail::RawFragmentHeader::num_words()) 00176 { 00177 TLOG(TLVL_WARNING, "ContainerFragment") << "Contained Fragment is below minimum size! Reported Data and Metadata sizes will be incorrect!"; 00178 frag = std::make_unique<Fragment>(); 00179 } 00180 else 00181 { 00182 // Subtract RawFragmentHeader::num_words here as Fragment consturctor will allocate n + detail::RawFragmentHeader::num_words(), and we want fragSize to be allocated. 00183 frag = std::make_unique<Fragment>((fragSize(index)) / sizeof(RawDataType) - detail::RawFragmentHeader::num_words()); 00184 } 00185 memcpy(frag->headerAddress(), reinterpret_cast<uint8_t const*>(dataBegin()) + fragmentIndex(index), fragSize(index)); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-bounds-pointer-arithmetic) 00186 return frag; 00187 } 00188 00195 size_t fragSize(size_t index) const 00196 { 00197 if (index >= block_count() || block_count() == 0) 00198 { 00199 throw cet::exception("ArgumentOutOfRange") << "Buffer overrun detected! ContainerFragment::fragSize was asked for a non-existent Fragment!"; // NOLINT(cert-err60-cpp) 00200 } 00201 auto end = fragmentIndex(index + 1); 00202 if (index == 0) return end; 00203 return end - fragmentIndex(index); 00204 } 00205 00212 FragmentPtr operator[](size_t index) const 00213 { 00214 return this->at(index); 00215 } 00216 00223 size_t fragmentIndex(size_t index) const 00224 { 00225 if (index > block_count()) 00226 { 00227 throw cet::exception("ArgumentOutOfRange") << "Buffer overrun detected! ContainerFragment::fragmentIndex was asked for a non-existent Fragment!"; // NOLINT(cert-err60-cpp) 00228 } 00229 if (index == 0) { return 0; } 00230 00231 auto index_ptr = get_index_(); 00232 00233 return index_ptr[index - 1]; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) 00234 } 00235 00240 size_t lastFragmentIndex() const 00241 { 00242 return fragmentIndex(block_count()); 00243 } 00244 00245 protected: 00250 static constexpr size_t words_per_frag_word_() 00251 { 00252 return sizeof(Fragment::value_type) / sizeof(Metadata::data_t); 00253 } 00254 00259 const size_t* create_index_() const 00260 { 00261 TLOG(TLVL_TRACE, "ContainerFragment") << "Creating new index for ContainerFragment"; 00262 index_ptr_owner_ = std::make_unique<std::vector<size_t>>(metadata()->block_count + 1); 00263 00264 auto current = reinterpret_cast<uint8_t const*>(artdaq_Fragment_.dataBegin()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) 00265 size_t offset = 0; 00266 for (int ii = 0; ii < metadata()->block_count; ++ii) 00267 { 00268 auto this_size = reinterpret_cast<const detail::RawFragmentHeader*>(current)->word_count * sizeof(RawDataType); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) 00269 offset += this_size; 00270 index_ptr_owner_->at(ii) = offset; 00271 current += this_size; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) 00272 } 00273 index_ptr_owner_->at(metadata()->block_count) = CONTAINER_MAGIC; 00274 return &index_ptr_owner_->at(0); 00275 } 00276 00281 void reset_index_ptr_() const 00282 { 00283 TLOG(TLVL_TRACE, "ContainerFragment") << "Request to reset index_ptr recieved. has_index=" << metadata()->has_index << ", Check word = " << std::hex 00284 << *(reinterpret_cast<size_t const*>(artdaq_Fragment_.dataBeginBytes() + metadata()->index_offset) + metadata()->block_count); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-bounds-pointer-arithmetic) 00285 if (metadata()->has_index && *(reinterpret_cast<size_t const*>(artdaq_Fragment_.dataBeginBytes() + metadata()->index_offset) + metadata()->block_count) == CONTAINER_MAGIC) // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-bounds-pointer-arithmetic) 00286 { 00287 TLOG(TLVL_TRACE, "ContainerFragment") << "Setting index_ptr to found valid index"; 00288 index_ptr_ = reinterpret_cast<size_t const*>(artdaq_Fragment_.dataBeginBytes() + metadata()->index_offset); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-bounds-pointer-arithmetic) 00289 } 00290 else 00291 { 00292 TLOG(TLVL_TRACE, "ContainerFragment") << "Index invalid or not found, allocating new index"; 00293 index_ptr_owner_.reset(nullptr); 00294 index_ptr_ = create_index_(); 00295 } 00296 } 00297 00302 const size_t* get_index_() const 00303 { 00304 if (index_ptr_ != nullptr) return index_ptr_; 00305 00306 reset_index_ptr_(); 00307 00308 return index_ptr_; 00309 } 00310 00311 private: 00312 ContainerFragment(ContainerFragment const&) = delete; // ContainerFragments should definitely not be copied 00313 ContainerFragment(ContainerFragment&&) = delete; // ContainerFragments should not be moved, only the underlying Fragment 00314 ContainerFragment& operator=(ContainerFragment const&) = delete; // ContainerFragments should definitely not be copied 00315 ContainerFragment& operator=(ContainerFragment&&) = delete; // ContainerFragments should not be moved, only the underlying Fragment 00316 00317 Fragment const& artdaq_Fragment_; 00318 00319 mutable const size_t* index_ptr_; 00320 mutable std::unique_ptr<std::vector<size_t>> index_ptr_owner_; 00321 mutable std::unique_ptr<Metadata> metadata_; 00322 }; 00323 00324 #endif /* artdaq_core_Data_ContainerFragment_hh */