artdaq_core  v3_04_20a
ContainerFragment.hh
1 #ifndef artdaq_core_Data_ContainerFragment_hh
2 #define artdaq_core_Data_ContainerFragment_hh
3 
4 #include "artdaq-core/Data/Fragment.hh"
5 #include "cetlib_except/exception.h"
6 
7 //#include <ostream>
8 //#include <vector>
9 
10 // Implementation of "ContainerFragment", an artdaq::Fragment overlay class
11 
12 namespace artdaq
13 {
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_alloc_ = true;
87  Metadata md;
88  md.block_count = in->block_count;
90  md.has_index = 0;
91  md.missing_data = in->missing_data;
92  md.version = 0;
93  index_ptr_ = in->index;
94  metadata_ = new Metadata(md);
95  return metadata_;
96  }
97 
104  explicit ContainerFragment(Fragment const& f) : artdaq_Fragment_(f), index_ptr_(nullptr), index_alloc_(false),metadata_(nullptr), metadata_alloc_(false) { }
105 
106  virtual ~ContainerFragment()
107  {
108  if (index_alloc_)
109  {
110  delete[] index_ptr_;
111  }
112  if (metadata_alloc_)
113  {
114  delete metadata_;
115  }
116  }
117 
122  Metadata const* metadata() const
123  {
124  if (metadata_alloc_) return metadata_;
125 
126  if (artdaq_Fragment_.sizeBytes() - artdaq_Fragment_.dataSizeBytes() - sizeof(detail::RawFragmentHeader) == sizeof(MetadataV0))
127  {
128  return UpgradeMetadata(artdaq_Fragment_.metadata<MetadataV0>());
129  }
130 
131  return artdaq_Fragment_.metadata<Metadata>();
132  }
133 
148  bool missing_data() const { return static_cast<bool>(metadata()->missing_data); }
149 
154  void const* dataBegin() const
155  {
156  return reinterpret_cast<void const *>(&*artdaq_Fragment_.dataBegin());
157  }
158 
163  void const* dataEnd() const
164  {
165  return reinterpret_cast<void const *>(reinterpret_cast<uint8_t const *>(dataBegin()) + lastFragmentIndex());
166  }
167 
174  FragmentPtr at(size_t index) const
175  {
176  if (index >= block_count() || block_count() == 0)
177  {
178  throw cet::exception("ArgumentOutOfRange") << "Buffer overrun detected! ContainerFragment::at was asked for a non-existent Fragment!";
179  }
180 
181  FragmentPtr frag(nullptr);
182  auto size = fragSize(index);
183  if (size < sizeof(RawDataType) * detail::RawFragmentHeader::num_words())
184  {
185  TLOG(TLVL_WARNING, "ContainerFragment") << "Contained Fragment is below minimum size! Reported Data and Metadata sizes will be incorrect!";
186  frag.reset(new Fragment());
187  }
188  else
189  {
190  // Subtract RawFragmentHeader::num_words here as Fragment consturctor will allocate n + detail::RawFragmentHeader::num_words(), and we want fragSize to be allocated.
191  frag.reset(new Fragment((fragSize(index)) / sizeof(RawDataType) - detail::RawFragmentHeader::num_words()));
192  }
193  memcpy(frag->headerAddress(), reinterpret_cast<uint8_t const*>(dataBegin()) + fragmentIndex(index), fragSize(index));
194  return frag;
195  }
196 
203  size_t fragSize(size_t index) const
204  {
205  if (index >= block_count() || block_count() == 0)
206  {
207  throw cet::exception("ArgumentOutOfRange") << "Buffer overrun detected! ContainerFragment::fragSize was asked for a non-existent Fragment!";
208  }
209  auto end = fragmentIndex(index + 1);
210  if (index == 0) return end;
211  return end - fragmentIndex(index);
212  }
213 
220  FragmentPtr operator[](size_t index) const
221  {
222  return this->at(index);
223  }
224 
231  size_t fragmentIndex(size_t index) const
232  {
233  if (index > block_count())
234  {
235  throw cet::exception("ArgumentOutOfRange") << "Buffer overrun detected! ContainerFragment::fragmentIndex was asked for a non-existent Fragment!";
236  }
237  if (index == 0) { return 0; }
238 
239  auto index_ptr = get_index_();
240 
241  return index_ptr[index - 1];
242  }
243 
248  size_t lastFragmentIndex() const
249  {
250  return fragmentIndex(block_count());
251  }
252 
253 protected:
254 
259  static constexpr size_t words_per_frag_word_()
260  {
261  return sizeof(Fragment::value_type) / sizeof(Metadata::data_t);
262  }
263 
268  const size_t* create_index_() const
269  {
270  TLOG(TLVL_TRACE, "ContainerFragment") << "Creating new index for ContainerFragment";
271  auto tmp = new size_t[metadata()->block_count + 1];
272 
273  auto current = reinterpret_cast<uint8_t const*>(artdaq_Fragment_.dataBegin());
274  size_t offset = 0;
275  for (int ii = 0; ii < metadata()->block_count; ++ii)
276  {
277  auto this_size = reinterpret_cast<const detail::RawFragmentHeader*>(current)->word_count * sizeof(RawDataType);
278  offset += this_size;
279  tmp[ii] = offset;
280  current += this_size;
281  }
283  return tmp;
284  }
285 
290  void reset_index_ptr_() const
291  {
292  TLOG(TLVL_TRACE, "ContainerFragment") << "Request to reset index_ptr recieved. has_index=" << metadata()->has_index << ", Check word = " << std::hex
293  << *(reinterpret_cast<size_t const*>(artdaq_Fragment_.dataBeginBytes() + metadata()->index_offset) + metadata()->block_count);
294  if (metadata()->has_index && *(reinterpret_cast<size_t const*>(artdaq_Fragment_.dataBeginBytes() + metadata()->index_offset) + metadata()->block_count) == CONTAINER_MAGIC)
295  {
296  TLOG(TLVL_TRACE, "ContainerFragment") << "Setting index_ptr to found valid index";
297  index_ptr_ = reinterpret_cast<size_t const*>(artdaq_Fragment_.dataBeginBytes() + metadata()->index_offset);
298  }
299  else
300  {
301  TLOG(TLVL_TRACE, "ContainerFragment") << "Index invalid or not found, allocating new index";
302  if (index_alloc_)
303  {
304  delete[] index_ptr_;
305  }
306 
307  index_alloc_ = true;
308  index_ptr_ = create_index_();
309  }
310  }
311 
316  const size_t* get_index_() const
317  {
318  if (index_ptr_ != nullptr) return index_ptr_;
319 
321 
322  return index_ptr_;
323  }
324 
325 private:
326  Fragment const& artdaq_Fragment_;
327 
328  mutable const size_t* index_ptr_;
329  mutable bool index_alloc_;
330  mutable const Metadata* metadata_;
331  mutable bool metadata_alloc_;
332 };
333 
334 #endif /* artdaq_core_Data_ContainerFragment_hh */
std::unique_ptr< Fragment > FragmentPtr
A std::unique_ptr to a Fragment object.
Definition: Fragment.hh:53
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:356
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:341
byte_t * dataBeginBytes()
Return Fragment::byte_t* pointing at the beginning of the payload.
Definition: Fragment.hh:533
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:136
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:1045
QuickVec< RawDataType >::value_type value_type
Alias value_type type from QuickVec&lt;RawDataType&gt;
Definition: Fragment.hh:184
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:920
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:39
count_t block_count
The number of Fragment objects stored in the ContainerFragment.
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:84
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.