$treeview $search $mathjax $extrastylesheet
artdaq_core
v3_04_20a
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #ifndef artdaq_core_Data_ContainerFragment_hh 00002 #define artdaq_core_Data_ContainerFragment_hh 00003 00004 #include "artdaq-core/Data/Fragment.hh" 00005 #include "cetlib_except/exception.h" 00006 00007 //#include <ostream> 00008 //#include <vector> 00009 00010 // Implementation of "ContainerFragment", an artdaq::Fragment overlay class 00011 00012 namespace artdaq 00013 { 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_alloc_ = true; 00087 Metadata md; 00088 md.block_count = in->block_count; 00089 md.fragment_type = in->fragment_type; 00090 md.has_index = 0; 00091 md.missing_data = in->missing_data; 00092 md.version = 0; 00093 index_ptr_ = in->index; 00094 metadata_ = new Metadata(md); 00095 return metadata_; 00096 } 00097 00104 explicit ContainerFragment(Fragment const& f) : artdaq_Fragment_(f), index_ptr_(nullptr), index_alloc_(false),metadata_(nullptr), metadata_alloc_(false) { } 00105 00106 virtual ~ContainerFragment() 00107 { 00108 if (index_alloc_) 00109 { 00110 delete[] index_ptr_; 00111 } 00112 if (metadata_alloc_) 00113 { 00114 delete metadata_; 00115 } 00116 } 00117 00122 Metadata const* metadata() const 00123 { 00124 if (metadata_alloc_) return metadata_; 00125 00126 if (artdaq_Fragment_.sizeBytes() - artdaq_Fragment_.dataSizeBytes() - sizeof(detail::RawFragmentHeader) == sizeof(MetadataV0)) 00127 { 00128 return UpgradeMetadata(artdaq_Fragment_.metadata<MetadataV0>()); 00129 } 00130 00131 return artdaq_Fragment_.metadata<Metadata>(); 00132 } 00133 00138 Metadata::count_t block_count() const { return metadata()->block_count; } 00143 Fragment::type_t fragment_type() const { return static_cast<Fragment::type_t>(metadata()->fragment_type); } 00148 bool missing_data() const { return static_cast<bool>(metadata()->missing_data); } 00149 00154 void const* dataBegin() const 00155 { 00156 return reinterpret_cast<void const *>(&*artdaq_Fragment_.dataBegin()); 00157 } 00158 00163 void const* dataEnd() const 00164 { 00165 return reinterpret_cast<void const *>(reinterpret_cast<uint8_t const *>(dataBegin()) + lastFragmentIndex()); 00166 } 00167 00174 FragmentPtr at(size_t index) const 00175 { 00176 if (index >= block_count() || block_count() == 0) 00177 { 00178 throw cet::exception("ArgumentOutOfRange") << "Buffer overrun detected! ContainerFragment::at was asked for a non-existent Fragment!"; 00179 } 00180 00181 FragmentPtr frag(nullptr); 00182 auto size = fragSize(index); 00183 if (size < sizeof(RawDataType) * detail::RawFragmentHeader::num_words()) 00184 { 00185 TLOG(TLVL_WARNING, "ContainerFragment") << "Contained Fragment is below minimum size! Reported Data and Metadata sizes will be incorrect!"; 00186 frag.reset(new Fragment()); 00187 } 00188 else 00189 { 00190 // Subtract RawFragmentHeader::num_words here as Fragment consturctor will allocate n + detail::RawFragmentHeader::num_words(), and we want fragSize to be allocated. 00191 frag.reset(new Fragment((fragSize(index)) / sizeof(RawDataType) - detail::RawFragmentHeader::num_words())); 00192 } 00193 memcpy(frag->headerAddress(), reinterpret_cast<uint8_t const*>(dataBegin()) + fragmentIndex(index), fragSize(index)); 00194 return frag; 00195 } 00196 00203 size_t fragSize(size_t index) const 00204 { 00205 if (index >= block_count() || block_count() == 0) 00206 { 00207 throw cet::exception("ArgumentOutOfRange") << "Buffer overrun detected! ContainerFragment::fragSize was asked for a non-existent Fragment!"; 00208 } 00209 auto end = fragmentIndex(index + 1); 00210 if (index == 0) return end; 00211 return end - fragmentIndex(index); 00212 } 00213 00220 FragmentPtr operator[](size_t index) const 00221 { 00222 return this->at(index); 00223 } 00224 00231 size_t fragmentIndex(size_t index) const 00232 { 00233 if (index > block_count()) 00234 { 00235 throw cet::exception("ArgumentOutOfRange") << "Buffer overrun detected! ContainerFragment::fragmentIndex was asked for a non-existent Fragment!"; 00236 } 00237 if (index == 0) { return 0; } 00238 00239 auto index_ptr = get_index_(); 00240 00241 return index_ptr[index - 1]; 00242 } 00243 00248 size_t lastFragmentIndex() const 00249 { 00250 return fragmentIndex(block_count()); 00251 } 00252 00253 protected: 00254 00259 static constexpr size_t words_per_frag_word_() 00260 { 00261 return sizeof(Fragment::value_type) / sizeof(Metadata::data_t); 00262 } 00263 00268 const size_t* create_index_() const 00269 { 00270 TLOG(TLVL_TRACE, "ContainerFragment") << "Creating new index for ContainerFragment"; 00271 auto tmp = new size_t[metadata()->block_count + 1]; 00272 00273 auto current = reinterpret_cast<uint8_t const*>(artdaq_Fragment_.dataBegin()); 00274 size_t offset = 0; 00275 for (int ii = 0; ii < metadata()->block_count; ++ii) 00276 { 00277 auto this_size = reinterpret_cast<const detail::RawFragmentHeader*>(current)->word_count * sizeof(RawDataType); 00278 offset += this_size; 00279 tmp[ii] = offset; 00280 current += this_size; 00281 } 00282 tmp[metadata()->block_count] = CONTAINER_MAGIC; 00283 return tmp; 00284 } 00285 00290 void reset_index_ptr_() const 00291 { 00292 TLOG(TLVL_TRACE, "ContainerFragment") << "Request to reset index_ptr recieved. has_index=" << metadata()->has_index << ", Check word = " << std::hex 00293 << *(reinterpret_cast<size_t const*>(artdaq_Fragment_.dataBeginBytes() + metadata()->index_offset) + metadata()->block_count); 00294 if (metadata()->has_index && *(reinterpret_cast<size_t const*>(artdaq_Fragment_.dataBeginBytes() + metadata()->index_offset) + metadata()->block_count) == CONTAINER_MAGIC) 00295 { 00296 TLOG(TLVL_TRACE, "ContainerFragment") << "Setting index_ptr to found valid index"; 00297 index_ptr_ = reinterpret_cast<size_t const*>(artdaq_Fragment_.dataBeginBytes() + metadata()->index_offset); 00298 } 00299 else 00300 { 00301 TLOG(TLVL_TRACE, "ContainerFragment") << "Index invalid or not found, allocating new index"; 00302 if (index_alloc_) 00303 { 00304 delete[] index_ptr_; 00305 } 00306 00307 index_alloc_ = true; 00308 index_ptr_ = create_index_(); 00309 } 00310 } 00311 00316 const size_t* get_index_() const 00317 { 00318 if (index_ptr_ != nullptr) return index_ptr_; 00319 00320 reset_index_ptr_(); 00321 00322 return index_ptr_; 00323 } 00324 00325 private: 00326 Fragment const& artdaq_Fragment_; 00327 00328 mutable const size_t* index_ptr_; 00329 mutable bool index_alloc_; 00330 mutable const Metadata* metadata_; 00331 mutable bool metadata_alloc_; 00332 }; 00333 00334 #endif /* artdaq_core_Data_ContainerFragment_hh */