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 #ifndef CONTAINER_FRAGMENT_CAPACITY 00014 #define CONTAINER_FRAGMENT_CAPACITY 100 00015 #endif 00016 00017 namespace artdaq 00018 { 00019 class ContainerFragment; 00020 00024 static const int CONTAINER_FRAGMENT_COUNT_MAX = CONTAINER_FRAGMENT_CAPACITY; 00025 } 00026 00030 class artdaq::ContainerFragment 00031 { 00032 public: 00033 00037 struct Metadata 00038 { 00039 typedef uint8_t data_t; 00040 typedef uint64_t count_t; 00041 00042 count_t block_count : 55; 00043 count_t fragment_type : 8; 00044 count_t missing_data : 1; 00045 00047 size_t index[CONTAINER_FRAGMENT_COUNT_MAX]; 00048 00050 static size_t const size_words = 8ul + CONTAINER_FRAGMENT_COUNT_MAX * sizeof(size_t) / sizeof(data_t); // Units of Header::data_t 00051 }; 00052 00053 static_assert (sizeof(Metadata) == Metadata::size_words * sizeof(Metadata::data_t), "ContainerFragment::Metadata size changed"); 00054 00061 explicit ContainerFragment(Fragment const& f) : artdaq_Fragment_(f) { } 00062 00067 Metadata const* metadata() const { return artdaq_Fragment_.metadata<Metadata>(); } 00068 00073 Metadata::count_t block_count() const { return metadata()->block_count; } 00078 Fragment::type_t fragment_type() const { return static_cast<Fragment::type_t>(metadata()->fragment_type); } 00083 bool missing_data() const { return static_cast<bool>(metadata()->missing_data); } 00084 00089 void const* dataBegin() const 00090 { 00091 return reinterpret_cast<void const *>(&*artdaq_Fragment_.dataBegin()); 00092 } 00093 00098 void const* dataEnd() const 00099 { 00100 return reinterpret_cast<void const *>(reinterpret_cast<uint8_t const *>(dataBegin()) + lastFragmentIndex()); 00101 } 00102 00109 FragmentPtr at(size_t index) const 00110 { 00111 if (index >= block_count() || block_count() == 0) 00112 { 00113 throw cet::exception("ArgumentOutOfRange") << "Buffer overrun detected! ContainerFragment::at was asked for a non-existent Fragment!"; 00114 } 00115 FragmentPtr frag(new Fragment(fragSize(index) / sizeof(RawDataType) - detail::RawFragmentHeader::num_words())); 00116 memcpy(frag->headerAddress(), reinterpret_cast<uint8_t const *>(dataBegin()) + fragmentIndex(index), fragSize(index)); 00117 return frag; 00118 } 00119 00126 size_t fragSize(size_t index) const 00127 { 00128 if (index >= block_count() || block_count() == 0) 00129 { 00130 throw cet::exception("ArgumentOutOfRange") << "Buffer overrun detected! ContainerFragment::fragSize was asked for a non-existent Fragment!"; 00131 } 00132 auto end = metadata()->index[index]; 00133 if (index == 0) return end; 00134 return end - metadata()->index[index - 1]; 00135 } 00136 00143 FragmentPtr operator[](size_t index) const 00144 { 00145 return this->at(index); 00146 } 00147 00154 size_t fragmentIndex(size_t index) const 00155 { 00156 if (index > block_count()) 00157 { 00158 throw cet::exception("ArgumentOutOfRange") << "Buffer overrun detected! ContainerFragment::fragmentIndex was asked for a non-existent Fragment!"; 00159 } 00160 if (index == 0) { return 0; } 00161 return metadata()->index[index - 1]; 00162 } 00163 00168 size_t lastFragmentIndex() const 00169 { 00170 return fragmentIndex(block_count()); 00171 } 00172 00173 protected: 00174 00179 static constexpr size_t words_per_frag_word_() 00180 { 00181 return sizeof(Fragment::value_type) / sizeof(Metadata::data_t); 00182 } 00183 00184 private: 00185 00186 Fragment const& artdaq_Fragment_; 00187 }; 00188 00189 #endif /* artdaq_core_Data_ContainerFragment_hh */