artdaq_core  v3_06_00
ContainerFragment.hh
1 #ifndef artdaq_core_Data_ContainerFragment_hh
2 #define artdaq_core_Data_ContainerFragment_hh
3 
4 #include <memory>
5 #include "artdaq-core/Data/Fragment.hh"
6 #include "cetlib_except/exception.h"
7 
8 //#include <ostream>
9 //#include <vector>
10 
11 // Implementation of "ContainerFragment", an artdaq::Fragment overlay class
12 
13 namespace artdaq {
14 class ContainerFragment;
15 }
16 
21 {
22 public:
24  static constexpr uint8_t CURRENT_VERSION = 1;
26  static constexpr size_t CONTAINER_MAGIC = 0x00BADDEED5B1BEE5;
27 
31  struct MetadataV0
32  {
36  static constexpr int CONTAINER_FRAGMENT_COUNT_MAX = 100;
37 
38  typedef uint8_t data_t;
39  typedef uint64_t count_t;
40 
44 
47 
49  static size_t const size_words = 8ul + CONTAINER_FRAGMENT_COUNT_MAX * sizeof(size_t) / sizeof(data_t); // Units of Header::data_t
50  };
51  static_assert(sizeof(MetadataV0) == MetadataV0::size_words * sizeof(MetadataV0::data_t), "ContainerFragment::MetadataV0 size changed");
52 
56  struct Metadata
57  {
58  typedef uint8_t data_t;
59  typedef uint64_t count_t;
60 
68  count_t unused : 32;
69 
70  uint64_t index_offset;
71 
73  static size_t const size_words = 16ul; // Units of Header::data_t
74  };
75  static_assert(sizeof(Metadata) == Metadata::size_words * sizeof(Metadata::data_t), "ContainerFragment::Metadata size changed");
76 
82  Metadata const* UpgradeMetadata(MetadataV0 const* in) const
83  {
84  TLOG(TLVL_DEBUG, "ContainerFragment") << "Upgrading ContainerFragment::MetadataV0 into new ContainerFragment::Metadata";
85  assert(in->block_count < std::numeric_limits<Metadata::count_t>::max());
86  Metadata md;
87  md.block_count = in->block_count;
89  md.has_index = 0;
90  md.missing_data = in->missing_data;
91  md.version = 0;
92  index_ptr_ = in->index;
93  metadata_ = std::make_unique<Metadata>(md);
94  return metadata_.get();
95  }
96 
103  explicit ContainerFragment(Fragment const& f)
104  : artdaq_Fragment_(f), index_ptr_(nullptr), index_ptr_owner_(nullptr), metadata_(nullptr) {}
105 
106  virtual ~ContainerFragment()
107  {
108  }
109 
114  Metadata const* metadata() const
115  {
116  if (metadata_) return metadata_.get();
117 
118  if (artdaq_Fragment_.sizeBytes() - artdaq_Fragment_.dataSizeBytes() - artdaq_Fragment_.headerSizeBytes() == sizeof(MetadataV0))
119  {
120  return UpgradeMetadata(artdaq_Fragment_.metadata<MetadataV0>());
121  }
122 
123  return artdaq_Fragment_.metadata<Metadata>();
124  }
125 
140  bool missing_data() const { return static_cast<bool>(metadata()->missing_data); }
141 
146  void const* dataBegin() const
147  {
148  return reinterpret_cast<void const*>(&*artdaq_Fragment_.dataBegin()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
149  }
150 
155  void const* dataEnd() const
156  {
157  return reinterpret_cast<void const*>(reinterpret_cast<uint8_t const*>(dataBegin()) + lastFragmentIndex()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-bounds-pointer-arithmetic)
158  }
159 
166  FragmentPtr at(size_t index) const
167  {
168  if (index >= block_count() || block_count() == 0)
169  {
170  throw cet::exception("ArgumentOutOfRange") << "Buffer overrun detected! ContainerFragment::at was asked for a non-existent Fragment!"; // NOLINT(cert-err60-cpp)
171  }
172 
173  FragmentPtr frag(nullptr);
174  auto size = fragSize(index);
175  if (size < sizeof(RawDataType) * detail::RawFragmentHeader::num_words())
176  {
177  TLOG(TLVL_WARNING, "ContainerFragment") << "Contained Fragment is below minimum size! Reported Data and Metadata sizes will be incorrect!";
178  frag = std::make_unique<Fragment>();
179  }
180  else
181  {
182  // Subtract RawFragmentHeader::num_words here as Fragment consturctor will allocate n + detail::RawFragmentHeader::num_words(), and we want fragSize to be allocated.
183  frag = std::make_unique<Fragment>((fragSize(index)) / sizeof(RawDataType) - detail::RawFragmentHeader::num_words());
184  }
185  memcpy(frag->headerAddress(), reinterpret_cast<uint8_t const*>(dataBegin()) + fragmentIndex(index), fragSize(index)); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-bounds-pointer-arithmetic)
186  return frag;
187  }
188 
195  size_t fragSize(size_t index) const
196  {
197  if (index >= block_count() || block_count() == 0)
198  {
199  throw cet::exception("ArgumentOutOfRange") << "Buffer overrun detected! ContainerFragment::fragSize was asked for a non-existent Fragment!"; // NOLINT(cert-err60-cpp)
200  }
201  auto end = fragmentIndex(index + 1);
202  if (index == 0) return end;
203  return end - fragmentIndex(index);
204  }
205 
212  FragmentPtr operator[](size_t index) const
213  {
214  return this->at(index);
215  }
216 
223  size_t fragmentIndex(size_t index) const
224  {
225  if (index > block_count())
226  {
227  throw cet::exception("ArgumentOutOfRange") << "Buffer overrun detected! ContainerFragment::fragmentIndex was asked for a non-existent Fragment!"; // NOLINT(cert-err60-cpp)
228  }
229  if (index == 0) { return 0; }
230 
231  auto index_ptr = get_index_();
232 
233  return index_ptr[index - 1]; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
234  }
235 
240  size_t lastFragmentIndex() const
241  {
242  return fragmentIndex(block_count());
243  }
244 
245 protected:
250  static constexpr size_t words_per_frag_word_()
251  {
252  return sizeof(Fragment::value_type) / sizeof(Metadata::data_t);
253  }
254 
259  const size_t* create_index_() const
260  {
261  TLOG(TLVL_TRACE, "ContainerFragment") << "Creating new index for ContainerFragment";
262  index_ptr_owner_ = std::make_unique<std::vector<size_t>>(metadata()->block_count + 1);
263 
264  auto current = reinterpret_cast<uint8_t const*>(artdaq_Fragment_.dataBegin()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
265  size_t offset = 0;
266  for (int ii = 0; ii < metadata()->block_count; ++ii)
267  {
268  auto this_size = reinterpret_cast<const detail::RawFragmentHeader*>(current)->word_count * sizeof(RawDataType); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
269  offset += this_size;
270  index_ptr_owner_->at(ii) = offset;
271  current += this_size; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
272  }
273  index_ptr_owner_->at(metadata()->block_count) = CONTAINER_MAGIC;
274  return &index_ptr_owner_->at(0);
275  }
276 
281  void reset_index_ptr_() const
282  {
283  TLOG(TLVL_TRACE, "ContainerFragment") << "Request to reset index_ptr recieved. has_index=" << metadata()->has_index << ", Check word = " << std::hex
284  << *(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)
285  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)
286  {
287  TLOG(TLVL_TRACE, "ContainerFragment") << "Setting index_ptr to found valid index";
288  index_ptr_ = reinterpret_cast<size_t const*>(artdaq_Fragment_.dataBeginBytes() + metadata()->index_offset); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-bounds-pointer-arithmetic)
289  }
290  else
291  {
292  TLOG(TLVL_TRACE, "ContainerFragment") << "Index invalid or not found, allocating new index";
293  index_ptr_owner_.reset(nullptr);
294  index_ptr_ = create_index_();
295  }
296  }
297 
302  const size_t* get_index_() const
303  {
304  if (index_ptr_ != nullptr) return index_ptr_;
305 
307 
308  return index_ptr_;
309  }
310 
311 private:
312  ContainerFragment(ContainerFragment const&) = delete; // ContainerFragments should definitely not be copied
313  ContainerFragment(ContainerFragment&&) = delete; // ContainerFragments should not be moved, only the underlying Fragment
314  ContainerFragment& operator=(ContainerFragment const&) = delete; // ContainerFragments should definitely not be copied
315  ContainerFragment& operator=(ContainerFragment&&) = delete; // ContainerFragments should not be moved, only the underlying Fragment
316 
317  Fragment const& artdaq_Fragment_;
318 
319  mutable const size_t* index_ptr_;
320  mutable std::unique_ptr<std::vector<size_t>> index_ptr_owner_;
321  mutable std::unique_ptr<Metadata> metadata_;
322 };
323 
324 #endif /* artdaq_core_Data_ContainerFragment_hh */
std::unique_ptr< Fragment > FragmentPtr
A std::unique_ptr to a Fragment object.
Definition: Fragment.hh:54
static constexpr size_t words_per_frag_word_()
Gets the ratio between the fundamental data storage type and the representation within the Fragment...
uint8_t data_t
Basic unit of data-retrieval.
static size_t const size_words
Size of the Metadata object.
size_t fragmentIndex(size_t index) const
Get the offset of a Fragment within the ContainerFragment.
The artdaq::ContainerFragment class represents a Fragment which contains other Fragments.
std::size_t dataSizeBytes() const
Return the number of bytes in the data payload. This does not include the number of bytes in the head...
Definition: Fragment.hh:374
uint64_t count_t
Size of block_count variables.
void reset_index_ptr_() const
Reset the index pointer, creating a new index if necessary. ContainerFragmentLoader uses this functio...
std::size_t sizeBytes() const
Size of vals_ vector ( header + (optional) metadata + payload) in bytes.
Definition: Fragment.hh:360
byte_t * dataBeginBytes()
Return Fragment::byte_t* pointing at the beginning of the payload.
Definition: Fragment.hh:551
static constexpr std::size_t num_words()
Returns the number of RawDataType words present in the header.
The RawFragmentHeader class contains the basic fields used by artdaq for routing Fragment objects thr...
detail::RawFragmentHeader::type_t type_t
typedef for type_t from RawFragmentHeader
Definition: Fragment.hh:137
bool missing_data() const
Gets the flag if the ContainerFragment knows that it is missing data.
Metadata const * UpgradeMetadata(MetadataV0 const *in) const
Upgrade the Metadata of a fixed-size ContainerFragment to the new standard.
count_t has_index
Whether the ContainerFragment has an index at the end of the payload.
Fragment::type_t fragment_type() const
Get the Fragment::type_t of stored Fragment objects.
static constexpr size_t CONTAINER_MAGIC
Marker word used in index.
size_t index[CONTAINER_FRAGMENT_COUNT_MAX]
Offset of each Fragment within the ContainerFragment.
count_t fragment_type
The Fragment::type_t of stored Fragment objects.
count_t fragment_type
The Fragment::type_t of stored Fragment objects.
size_t lastFragmentIndex() const
Returns the offset of the last Fragment in the ContainerFragment.
count_t block_count
The number of Fragment objects stored in the ContainerFragment.
iterator dataBegin()
Return an iterator to the beginning of the data payload (after header and metadata) ...
Definition: Fragment.hh:1070
QuickVec< RawDataType >::value_type value_type
Alias value_type type from QuickVec&lt;RawDataType&gt;
Definition: Fragment.hh:185
const size_t * get_index_() const
Get a pointer to the index.
void const * dataBegin() const
Gets the start of the data.
Contains the information necessary for retrieving Fragment objects from the ContainerFragment.
void const * dataEnd() const
Gets the last Fragment in the ContainerFragment.
count_t missing_data
Flag if the ContainerFragment knows that it is missing data.
ContainerFragment(Fragment const &f)
const size_t * create_index_() const
Create an index for the currently-contained Fragments.
Contains the information necessary for retrieving Fragment objects from the ContainerFragment.
count_t missing_data
Flag if the ContainerFragment knows that it is missing data.
Metadata::count_t block_count() const
Gets the number of fragments stored in the ContainerFragment.
T * metadata()
Return a pointer to the metadata. This throws an exception if the Fragment contains no metadata...
Definition: Fragment.hh:952
static constexpr uint8_t CURRENT_VERSION
The current version of the ContainerFragmentHeader.
Metadata const * metadata() const
const getter function for the Metadata
detail::RawFragmentHeader::RawDataType RawDataType
The RawDataType (currently a 64-bit integer) is the basic unit of data representation within artdaq ...
Definition: Fragment.hh:40
count_t block_count
The number of Fragment objects stored in the ContainerFragment.
size_t headerSizeBytes() const
Get the size of this Fragment&#39;s header, in bytes.
Definition: Fragment.hh:640
FragmentPtr operator[](size_t index) const
Alias to ContainerFragment::at()
count_t version
Version number of ContainerFragment.
uint64_t count_t
Size of block_count variables.
A Fragment contains the data from one piece of the DAQ system for one event The artdaq::Fragment is t...
Definition: Fragment.hh:85
FragmentPtr at(size_t index) const
Gets a specific Fragment from the ContainerFragment.
static size_t const size_words
Size of the Metadata object.
static constexpr int CONTAINER_FRAGMENT_COUNT_MAX
The maximum capacity of the ContainerFragment (in fragments)
size_t fragSize(size_t index) const
Gets the size of the Fragment at the specified location in the ContainerFragment, in bytes...
uint64_t index_offset
Index starts this many bytes after the beginning of the payload (is also the total size of contained ...
uint8_t data_t
Basic unit of data-retrieval.