artdaq_core  3.10.01
ContainerFragmentLoader.hh
1 #ifndef artdaq_core_Data_ContainerFragmentLoader_hh
2 #define artdaq_core_Data_ContainerFragmentLoader_hh
3 
5 // ContainerFragmentLoader
6 //
7 // This class gives write access to a ContainerFragment. It should be
8 // used when multiple fragments are generated by one BoardReader for a
9 // single event.
10 //
12 
13 #include "artdaq-core/Data/ContainerFragment.hh"
14 #include "artdaq-core/Data/Fragment.hh"
15 
16 #include "TRACE/tracemf.h"
17 
18 #include <iostream>
19 
20 namespace artdaq {
21 class ContainerFragmentLoader;
22 }
23 
28 {
29 public:
36  explicit ContainerFragmentLoader(Fragment& f, Fragment::type_t expectedFragmentType);
37 
38  // ReSharper disable once CppMemberFunctionMayBeConst
44  {
45  assert(artdaq_Fragment_.hasMetadata());
46  return reinterpret_cast<Metadata*>(&*artdaq_Fragment_.metadataAddress()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
47  }
48 
54  {
55  metadata()->fragment_type = type;
56  }
57 
66  void set_missing_data(bool isDataMissing)
67  {
68  metadata()->missing_data = isDataMissing;
69  }
70 
76  void addFragment(artdaq::Fragment& frag, bool allowDifferentTypes = false);
77 
82  void addFragment(artdaq::FragmentPtr& frag, bool allowDifferentTypes = false);
83 
88  void addFragments(artdaq::Fragments& frags, bool allowDifferentTypes = false);
89 
94  void addFragments(artdaq::FragmentPtrs& frags, bool allowDifferentTypes = false);
95 
102 
107  void resizeLastFragment(size_t nwords);
108 
109  detail::RawFragmentHeader* lastFragmentHeader() { return reinterpret_cast<detail::RawFragmentHeader*>(dataBegin_() + fragmentIndex(block_count() - 1)); }
110 
111 private:
112  // Note that this non-const reference hides the const reference in the base class
113  artdaq::Fragment& artdaq_Fragment_;
114 
115  static size_t words_to_frag_words_(size_t nWords);
116 
117  void addSpace_(size_t bytes);
118 
119  uint8_t* dataBegin_() { return reinterpret_cast<uint8_t*>(&*artdaq_Fragment_.dataBegin()); } // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
120  void* dataEnd_() { return static_cast<void*>(dataBegin_() + lastFragmentIndex()); } // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
121 };
122 
123 inline artdaq::ContainerFragmentLoader::ContainerFragmentLoader(artdaq::Fragment& f, artdaq::Fragment::type_t expectedFragmentType = Fragment::EmptyFragmentType)
124  : ContainerFragment(f)
125  , artdaq_Fragment_(f)
126 {
128  Metadata m;
129  m.block_count = 0;
130  m.fragment_type = expectedFragmentType;
131  m.missing_data = false;
132  m.has_index = true;
134  m.index_offset = 0;
135  artdaq_Fragment_.setMetadata<Metadata>(m);
136 
137  if (artdaq_Fragment_.size() !=
139  words_to_frag_words_(Metadata::size_words))
140  {
141  TLOG(TLVL_ERROR, "ContainerFragmentLoader") << "ContainerFragmentLoader: Raw artdaq::Fragment object size suggests it does not consist of its own header + the ContainerFragment::Metadata object";
142  TLOG(TLVL_ERROR, "ContainerFragmentLoader") << "artdaq_Fragment size: " << artdaq_Fragment_.size() << ", Expected size: " << artdaq::detail::RawFragmentHeader::num_words() + words_to_frag_words_(Metadata::size_words);
143 
144  throw cet::exception("InvalidFragment") << "ContainerFragmentLoader: Raw artdaq::Fragment object size suggests it does not consist of its own header + the ContainerFragment::Metadata object"; // NOLINT(cert-err60-cpp)
145  }
146 
147  artdaq_Fragment_.resize(1);
148  *artdaq_Fragment_.dataBegin() = CONTAINER_MAGIC;
149 }
150 
151 inline size_t artdaq::ContainerFragmentLoader::words_to_frag_words_(size_t nWords)
152 {
153  size_t mod = nWords % words_per_frag_word_();
154  return mod ? nWords / words_per_frag_word_() + 1 : nWords / words_per_frag_word_();
155 }
156 
157 inline void artdaq::ContainerFragmentLoader::addSpace_(size_t bytes)
158 {
159  auto currSize = sizeof(artdaq::Fragment::value_type) * artdaq_Fragment_.dataSize(); // Resize takes into account header and metadata size
160  artdaq_Fragment_.resizeBytesWithCushion(bytes + currSize, 1.3);
161  reset_index_ptr_(); // Must reset index_ptr after resize operation!
162 
163  TLOG(TLVL_DEBUG + 33, "ContainerFragmentLoader") << "addSpace_: dataEnd_ is now at " << static_cast<void*>(dataEnd_()) << " (oldSizeBytes/deltaBytes: " << currSize << "/" << bytes << ")";
164 }
165 
166 inline void artdaq::ContainerFragmentLoader::addFragment(artdaq::Fragment& frag, bool allowDifferentTypes)
167 {
168  TLOG(TLVL_DEBUG + 33, "ContainerFragmentLoader") << "addFragment: Adding Fragment with payload size " << frag.dataSizeBytes() << " to Container";
169  if (metadata()->fragment_type == Fragment::EmptyFragmentType)
170  metadata()->fragment_type = frag.type();
171  else if (!allowDifferentTypes && frag.type() != metadata()->fragment_type)
172  {
173  TLOG(TLVL_ERROR, "ContainerFragmentLoader") << "addFragment: Trying to add a fragment of different type than what's already been added!";
174  throw cet::exception("WrongFragmentType") << "ContainerFragmentLoader::addFragment: Trying to add a fragment of different type than what's already been added!"; // NOLINT(cert-err60-cpp)
175  }
176 
177  TLOG(TLVL_DEBUG + 33, "ContainerFragmentLoader") << "addFragment: Payload Size is " << artdaq_Fragment_.dataSizeBytes() << ", lastFragmentIndex is " << lastFragmentIndex() << ", and frag.size is " << frag.sizeBytes();
178  if (artdaq_Fragment_.dataSizeBytes() < (lastFragmentIndex() + frag.sizeBytes() + sizeof(size_t) * (metadata()->block_count + 2)))
179  {
180  addSpace_((lastFragmentIndex() + frag.sizeBytes() + sizeof(size_t) * (metadata()->block_count + 2)) - artdaq_Fragment_.dataSizeBytes());
181  }
182  // frag.setSequenceID(artdaq_Fragment_.sequenceID());
183  TLOG(TLVL_DEBUG + 33, "ContainerFragmentLoader") << "addFragment, copying " << frag.sizeBytes() << " bytes from " << static_cast<void*>(frag.headerAddress()) << " to " << static_cast<void*>(dataEnd_());
184  memcpy(dataEnd_(), frag.headerAddress(), frag.sizeBytes());
185  metadata()->has_index = 0;
186 
187  metadata()->block_count++;
188 
189  auto index = create_index_();
190  metadata()->index_offset = index[metadata()->block_count - 1]; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
191  memcpy(dataBegin_() + metadata()->index_offset, index, sizeof(size_t) * (metadata()->block_count + 1)); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
192 
193  metadata()->has_index = 1;
194  reset_index_ptr_();
195 }
196 
197 
198 inline void artdaq::ContainerFragmentLoader::addFragments(artdaq::Fragments& frags, bool allowDifferentTypes)
199 {
200  TLOG(TLVL_DEBUG + 33, "ContainerFragmentLoader") << "addFragments: Adding " << frags.size() << " Fragments to Container";
201 
202  size_t total_size = 0;
203  for (auto& frag : frags) { total_size += frag.sizeBytes(); }
204 
205  TLOG(TLVL_DEBUG + 33, "ContainerFragmentLoader") << "addFragments: Payload Size is " << artdaq_Fragment_.dataSizeBytes() << ", lastFragmentIndex is " << lastFragmentIndex() << ", and size to add is " << total_size;
206  if (artdaq_Fragment_.dataSizeBytes() < (lastFragmentIndex() + total_size + sizeof(size_t) * (metadata()->block_count + 1 + frags.size())))
207  {
208  addSpace_((lastFragmentIndex() + total_size + sizeof(size_t) * (metadata()->block_count + 1 + frags.size())) - artdaq_Fragment_.dataSizeBytes());
209  }
210 
211  auto data_ptr = dataEnd_();
212 
213  for (auto& frag : frags)
214  {
215  if (metadata()->fragment_type == Fragment::EmptyFragmentType)
216  metadata()->fragment_type = frag.type();
217  else if (!allowDifferentTypes && frag.type() != metadata()->fragment_type)
218  {
219  TLOG(TLVL_ERROR, "ContainerFragmentLoader") << "addFragments: Trying to add a fragment of different type than what's already been added!";
220  throw cet::exception("WrongFragmentType") << "ContainerFragmentLoader::addFragments: Trying to add a fragment of different type than what's already been added!"; // NOLINT(cert-err60-cpp)
221  }
222 
223  // frag->setSequenceID(artdaq_Fragment_.sequenceID());
224  TLOG(TLVL_DEBUG + 33, "ContainerFragmentLoader") << "addFragments, copying " << frag.sizeBytes() << " bytes from " << static_cast<void*>(frag.headerAddress()) << " to " << static_cast<void*>(dataEnd_());
225  memcpy(data_ptr, frag.headerAddress(), frag.sizeBytes());
226  data_ptr = static_cast<uint8_t*>(data_ptr) + frag.sizeBytes();
227  }
228  metadata()->has_index = 0;
229  metadata()->block_count += frags.size();
230 
231  auto index = create_index_();
232  metadata()->index_offset = index[metadata()->block_count - 1]; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
233  memcpy(dataBegin_() + metadata()->index_offset, index, sizeof(size_t) * (metadata()->block_count + 1)); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
234 
235  metadata()->has_index = 1;
236  reset_index_ptr_();
237 }
238 
240 {
241  TLOG(TLVL_TRACE, "ContainerFragmentLoader") << "addFragment: Allocating Fragment with payload size " << nwords << " in Container";
242 
243  auto fragSizeBytes = (nwords + detail::RawFragmentHeader::num_words()) * sizeof(RawDataType);
244  TLOG(TLVL_TRACE, "ContainerFragmentLoader") << "addFragment: Payload Size is " << artdaq_Fragment_.dataSizeBytes() << ", lastFragmentIndex is " << lastFragmentIndex() << ", and frag.size is "
245  << fragSizeBytes;
246  if (artdaq_Fragment_.dataSizeBytes() < (lastFragmentIndex() + fragSizeBytes + sizeof(size_t) * (metadata()->block_count + 2)))
247  {
248  addSpace_((lastFragmentIndex() + fragSizeBytes + sizeof(size_t) * (metadata()->block_count + 2)) - artdaq_Fragment_.dataSizeBytes());
249  }
250 
252  hdr.sequence_id = artdaq_Fragment_.sequenceID();
253  hdr.type = metadata()->fragment_type;
255  hdr.fragment_id = artdaq_Fragment_.fragmentID();
257 
258  auto ptr = dataEnd_();
259  memcpy(ptr, &hdr, sizeof(detail::RawFragmentHeader));
260 
261  metadata()->has_index = 0;
262 
263  metadata()->block_count++;
264 
265  auto index = create_index_();
266  metadata()->index_offset = index[metadata()->block_count - 1]; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
267  memcpy(dataBegin_() + metadata()->index_offset, index, sizeof(size_t) * (metadata()->block_count + 1)); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
268 
269  metadata()->has_index = 1;
270  reset_index_ptr_();
271 
272  return lastFragmentHeader();
273 }
274 
276 {
277  auto hdr = lastFragmentHeader();
278  auto curFragSize = hdr->word_count - detail::RawFragmentHeader::num_words();
279 
280  hdr->word_count = nwords + detail::RawFragmentHeader::num_words();
281  // New size is larger than current
282  if (curFragSize < nwords)
283  {
284  addSpace_((nwords - curFragSize) * sizeof(artdaq::RawDataType));
285  }
286  metadata()->has_index = 0;
287 
288  auto index = create_index_();
289  metadata()->index_offset = index[metadata()->block_count - 1]; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
290  memcpy(dataBegin_() + metadata()->index_offset, index, sizeof(size_t) * (metadata()->block_count + 1)); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
291 
292  metadata()->has_index = 1;
293  reset_index_ptr_();
294 }
295 
296 inline void artdaq::ContainerFragmentLoader::addFragment(artdaq::FragmentPtr& frag, bool allowDifferentTypes)
297 {
298  addFragment(*frag, allowDifferentTypes);
299 }
300 
301 inline void artdaq::ContainerFragmentLoader::addFragments(artdaq::FragmentPtrs& frags, bool allowDifferentTypes)
302 {
303  TLOG(TLVL_DEBUG + 33, "ContainerFragmentLoader") << "addFragments: Adding " << frags.size() << " Fragments to Container";
304 
305  size_t total_size = 0;
306  for (auto& frag : frags) { total_size += frag->sizeBytes(); }
307 
308  TLOG(TLVL_DEBUG + 33, "ContainerFragmentLoader") << "addFragments: Payload Size is " << artdaq_Fragment_.dataSizeBytes() << ", lastFragmentIndex is " << lastFragmentIndex() << ", and size to add is " << total_size;
309  if (artdaq_Fragment_.dataSizeBytes() < (lastFragmentIndex() + total_size + sizeof(size_t) * (metadata()->block_count + 1 + frags.size())))
310  {
311  addSpace_((lastFragmentIndex() + total_size + sizeof(size_t) * (metadata()->block_count + 1 + frags.size())) - artdaq_Fragment_.dataSizeBytes());
312  }
313 
314  auto data_ptr = dataEnd_();
315 
316  for (auto& frag : frags)
317  {
318  if (metadata()->fragment_type == Fragment::EmptyFragmentType)
319  metadata()->fragment_type = frag->type();
320  else if (!allowDifferentTypes && frag->type() != metadata()->fragment_type)
321  {
322  TLOG(TLVL_ERROR, "ContainerFragmentLoader") << "addFragments: Trying to add a fragment of different type than what's already been added!";
323  throw cet::exception("WrongFragmentType") << "ContainerFragmentLoader::addFragments: Trying to add a fragment of different type than what's already been added!"; // NOLINT(cert-err60-cpp)
324  }
325 
326  // frag->setSequenceID(artdaq_Fragment_.sequenceID());
327  TLOG(TLVL_DEBUG + 33, "ContainerFragmentLoader") << "addFragments, copying " << frag->sizeBytes() << " bytes from " << static_cast<void*>(frag->headerAddress()) << " to " << static_cast<void*>(dataEnd_());
328  memcpy(data_ptr, frag->headerAddress(), frag->sizeBytes());
329  data_ptr = static_cast<uint8_t*>(data_ptr) + frag->sizeBytes();
330  }
331  metadata()->has_index = 0;
332  metadata()->block_count += frags.size();
333 
334  auto index = create_index_();
335  metadata()->index_offset = index[metadata()->block_count - 1]; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
336  memcpy(dataBegin_() + metadata()->index_offset, index, sizeof(size_t) * (metadata()->block_count + 1)); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
337 
338  metadata()->has_index = 1;
339  reset_index_ptr_();
340 }
341 
342 #endif /* artdaq_core_Data_ContainerFragmentLoader_hh */
std::unique_ptr< Fragment > FragmentPtr
A std::unique_ptr to a Fragment object.
Definition: Fragment.hh:54
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.
RawDataType word_count
number of RawDataType words in this Fragment
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
RawDataType type
The type of the fragment, either system or user-defined.
void setSystemType(type_t stype)
Sets the type of the Fragment, checking that it is a valid system type.
Definition: Fragment.hh:912
std::vector< Fragment > Fragments
A std::vector of Fragment objects.
Definition: Fragment.hh:42
std::size_t size() const
Gets the size of the Fragment, from the Fragment header.
Definition: Fragment.hh:863
void set_fragment_type(Fragment::type_t type)
Sets the type of Fragment which this ContainerFragment should contain.
A Read-Write version of the ContainerFragment, used for filling ContainerFragment objects with other ...
static constexpr type_t EmptyFragmentType
Copy EmptyFragmentType from RawFragmentHeader.
Definition: Fragment.hh:155
void resizeLastFragment(size_t nwords)
Resize the last Fragment in the container.
std::size_t sizeBytes() const
Size of vals_ vector ( header + (optional) metadata + payload) in bytes.
Definition: Fragment.hh:360
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
RawDataType sequence_id
The 48-bit sequence_id uniquely identifies events within the artdaq system.
count_t has_index
Whether the ContainerFragment has an index at the end of the payload.
void resize(std::size_t sz)
Resize the data payload to hold sz RawDataType words.
Definition: Fragment.hh:1035
RawDataType version
The version of the fragment.
RawDataType fragment_id
The fragment_id uniquely identifies a particular piece of hardware within the artdaq system...
static constexpr size_t CONTAINER_MAGIC
Marker word used in index.
count_t fragment_type
The Fragment::type_t of stored Fragment objects.
void addFragment(artdaq::Fragment &frag, bool allowDifferentTypes=false)
Add a Fragment to the ContainerFragment by reference.
void setMetadata(const T &metadata)
Set the metadata in the Fragment to the contents of the specified structure. This throws an exception...
Definition: Fragment.hh:999
size_t lastFragmentIndex() const
Returns the offset of the last Fragment in the ContainerFragment.
Metadata * metadata()
Get the ContainerFragment metadata (includes information about the location of Fragment objects withi...
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:1093
QuickVec< RawDataType >::value_type value_type
Alias value_type type from QuickVec&lt;RawDataType&gt;
Definition: Fragment.hh:185
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.
static constexpr type_t ContainerFragmentType
Copy ContainerFragmentType from RawFragmentHeader.
Definition: Fragment.hh:156
ContainerFragmentLoader(Fragment &f, Fragment::type_t expectedFragmentType)
Constructs the ContainerFragmentLoader.
type_t type() const
Type of the Fragment, from the Fragment header.
Definition: Fragment.hh:876
Metadata::count_t block_count() const
Gets the number of fragments stored in the ContainerFragment.
static constexpr uint8_t CURRENT_VERSION
The current version of the ContainerFragmentHeader.
detail::RawFragmentHeader::RawDataType RawDataType
The RawDataType (currently a 64-bit integer) is the basic unit of data representation within artdaq ...
Definition: Fragment.hh:40
RawDataType * metadataAddress()
Get the address of the metadata. For internal use only, use metadata() instead.
Definition: Fragment.hh:1165
std::list< FragmentPtr > FragmentPtrs
A std::list of FragmentPtrs.
Definition: Fragment.hh:59
void addFragments(artdaq::Fragments &frags, bool allowDifferentTypes=false)
Add a collection of Fragment objects to the ContainerFragment.
static const version_t CurrentVersion
The CurrentVersion field should be incremented whenever the RawFragmentHeader changes.
bool hasMetadata() const
Test whether this Fragment has metadata.
Definition: Fragment.hh:969
detail::RawFragmentHeader * appendFragment(size_t nwords)
Create a Fragment at the end of the ContainerFragment with the given size nwords Size (in RawDataTyp...
count_t version
Version number of ContainerFragment.
A Fragment contains the data from one piece of the DAQ system for one event The artdaq::Fragment is t...
Definition: Fragment.hh:85
void set_missing_data(bool isDataMissing)
Sets the missing_data flag.
uint64_t index_offset
Index starts this many bytes after the beginning of the payload (is also the total size of contained ...
RawDataType * headerAddress()
Gets the address of the header.
Definition: Fragment.hh:1176