artdaq_core  v3_04_02
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/Fragment.hh"
14 #include "artdaq-core/Data/ContainerFragment.hh"
15 
16 #include "tracemf.h"
17 
18 #include <iostream>
19 
20 
21 namespace artdaq
22 {
23  class ContainerFragmentLoader;
24 }
25 
26 
31 {
32 public:
33 
34 
41  explicit ContainerFragmentLoader(Fragment& f, Fragment::type_t expectedFragmentType);
42 
43  // ReSharper disable once CppMemberFunctionMayBeConst
49  {
50  assert(artdaq_Fragment_.hasMetadata());
51  return reinterpret_cast<Metadata *>(&*artdaq_Fragment_.metadataAddress());
52  }
53 
59  {
60  metadata()->fragment_type = type;
61  }
62 
71  void set_missing_data(bool isDataMissing)
72  {
73  metadata()->missing_data = isDataMissing;
74  }
75 
81  void addFragment(artdaq::Fragment& frag);
82 
87  void addFragment(artdaq::FragmentPtr& frag);
88 
94 
95 private:
96  // Note that this non-const reference hides the const reference in the base class
97  artdaq::Fragment& artdaq_Fragment_;
98 
99  static size_t words_to_frag_words_(size_t nWords);
100 
101  void addSpace_(size_t bytes);
102 
103  uint8_t* dataBegin_() { return reinterpret_cast<uint8_t*>(&*artdaq_Fragment_.dataBegin()); }
104  void* dataEnd_() { return reinterpret_cast<void*>(dataBegin_() + lastFragmentIndex()); }
105 };
106 
107 inline artdaq::ContainerFragmentLoader::ContainerFragmentLoader(artdaq::Fragment& f, artdaq::Fragment::type_t expectedFragmentType = Fragment::EmptyFragmentType) :
109  , artdaq_Fragment_(f)
110 {
112  Metadata m;
113  m.block_count = 0;
114  m.fragment_type = expectedFragmentType;
115  m.missing_data = false;
116  m.has_index = true;
117  m.version = ContainerFragment::CURRENT_VERSION;
118  m.index_offset = 0;
119  artdaq_Fragment_.setMetadata<Metadata>(m);
120 
121  if (artdaq_Fragment_.size() !=
123  words_to_frag_words_(Metadata::size_words))
124  {
125  TLOG(TLVL_ERROR,"ContainerFragmentLoader") << "ContainerFragmentLoader: Raw artdaq::Fragment object size suggests it does not consist of its own header + the ContainerFragment::Metadata object" ;
126  TLOG(TLVL_ERROR,"ContainerFragmentLoader") << "artdaq_Fragment size: " << artdaq_Fragment_.size() << ", Expected size: " << artdaq::detail::RawFragmentHeader::num_words() + words_to_frag_words_(Metadata::size_words) ;
127 
128  throw cet::exception("InvalidFragment") << "ContainerFragmentLoader: Raw artdaq::Fragment object size suggests it does not consist of its own header + the ContainerFragment::Metadata object";
129  }
130 
131  artdaq_Fragment_.resize(1);
132  *artdaq_Fragment_.dataBegin() = CONTAINER_MAGIC;
133 }
134 
135 inline size_t artdaq::ContainerFragmentLoader::words_to_frag_words_(size_t nWords)
136 {
137  size_t mod = nWords % words_per_frag_word_();
138  return mod ?
139  nWords / words_per_frag_word_() + 1 :
140  nWords / words_per_frag_word_();
141 }
142 
143 inline void artdaq::ContainerFragmentLoader::addSpace_(size_t bytes)
144 {
145  auto currSize = sizeof(artdaq::Fragment::value_type) * artdaq_Fragment_.dataSize(); // Resize takes into account header and metadata size
146  artdaq_Fragment_.resizeBytes(bytes + currSize);
147  reset_index_ptr_(); // Must reset index_ptr after resize operation!
148  TLOG(TLVL_TRACE,"ContainerFragmentLoader") << "addSpace_: dataEnd_ is now at " << (void*)dataEnd_();
149 }
150 
152 {
153  TLOG(TLVL_TRACE,"ContainerFragmentLoader") << "addFragment: Adding Fragment with payload size " << frag.dataSizeBytes() << " to Container";
154  if (metadata()->fragment_type == Fragment::EmptyFragmentType) metadata()->fragment_type = frag.type();
155  else if (frag.type() != metadata()->fragment_type)
156  {
157  TLOG(TLVL_ERROR,"ContainerFragmentLoader") << "addFragment: Trying to add a fragment of different type than what's already been added!" ;
158  throw cet::exception("WrongFragmentType") << "ContainerFragmentLoader::addFragment: Trying to add a fragment of different type than what's already been added!";
159  }
160 
161  TLOG(TLVL_TRACE,"ContainerFragmentLoader") << "addFragment: Payload Size is " << artdaq_Fragment_.dataSizeBytes() << ", lastFragmentIndex is " << lastFragmentIndex() << ", and frag.size is " << frag.sizeBytes();
162  if (artdaq_Fragment_.dataSizeBytes() < (lastFragmentIndex() + frag.sizeBytes() + sizeof(size_t) * (metadata()->block_count + 2)))
163  {
164  addSpace_((lastFragmentIndex() + frag.sizeBytes() + sizeof(size_t) * (metadata()->block_count + 2)) - artdaq_Fragment_.dataSizeBytes());
165  }
166  frag.setSequenceID(artdaq_Fragment_.sequenceID());
167  TLOG(TLVL_TRACE,"ContainerFragmentLoader") << "addFragment, copying " << frag.sizeBytes() << " bytes from " << (void*)frag.headerAddress() << " to " << (void*)dataEnd_();
168  memcpy(dataEnd_(), frag.headerAddress(), frag.sizeBytes());
169  metadata()->has_index = 0;
170 
171  metadata()->block_count++;
172 
173  auto index = create_index_();
174  metadata()->index_offset = index[metadata()->block_count - 1];
175  memcpy(dataBegin_() + metadata()->index_offset, index, sizeof(size_t) * (metadata()->block_count + 1));
176  metadata()->has_index = 1;
177  reset_index_ptr_();
178 }
179 
181 {
182  addFragment(*frag);
183 }
184 
186 {
187  for (auto& frag : frags)
188  {
189  addFragment((*frag));
190  }
191 }
192 
193 #endif /* artdaq_core_Data_ContainerFragmentLoader_hh */
std::unique_ptr< Fragment > FragmentPtr
A std::unique_ptr to a Fragment object.
Definition: Fragment.hh:53
static size_t const size_words
Size of the Metadata object.
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
void setSequenceID(sequence_id_t sequence_id)
Sets the Sequence ID of the Fragment.
Definition: Fragment.hh:862
void setSystemType(type_t stype)
Sets the type of the Fragment, checking that it is a valid system type.
Definition: Fragment.hh:855
std::size_t size() const
Gets the size of the Fragment, from the Fragment header.
Definition: Fragment.hh:799
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:154
std::size_t sizeBytes() const
Size of vals_ vector ( header + (optional) metadata + payload) in bytes.
Definition: Fragment.hh:341
static constexpr std::size_t num_words()
Returns the number of RawDataType words present in the header.
detail::RawFragmentHeader::type_t type_t
typedef for type_t from RawFragmentHeader
Definition: Fragment.hh:136
void resize(std::size_t sz)
Resize the data payload to hold sz RawDataType words.
Definition: Fragment.hh:974
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.
Metadata * metadata()
Get the ContainerFragment metadata (includes information about the location of Fragment objects withi...
void addFragment(artdaq::Fragment &frag)
Add a Fragment to the ContainerFragment by reference.
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:1026
QuickVec< RawDataType >::value_type value_type
Alias value_type type from QuickVec&lt;RawDataType&gt;
Definition: Fragment.hh:184
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:155
ContainerFragmentLoader(Fragment &f, Fragment::type_t expectedFragmentType)
Constructs the ContainerFragmentLoader.
void setMetadata(const T &md)
Set the metadata in the Fragment to the contents of the specified structure. This throws an exception...
Definition: Fragment.hh:937
type_t type() const
Type of the Fragment, from the Fragment header.
Definition: Fragment.hh:813
RawDataType * metadataAddress()
Get the address of the metadata. For internal use only, use metadata() instead.
Definition: Fragment.hh:1110
std::list< FragmentPtr > FragmentPtrs
A std::list of FragmentPtrs.
Definition: Fragment.hh:58
bool hasMetadata() const
Test whether this Fragment has metadata.
Definition: Fragment.hh:903
A Fragment contains the data from one piece of the DAQ system for one event The artdaq::Fragment is t...
Definition: Fragment.hh:84
void set_missing_data(bool isDataMissing)
Sets the missing_data flag.
void addFragments(artdaq::FragmentPtrs &frags)
Add a collection of Fragment objects to the ContainerFragment.
RawDataType * headerAddress()
Gets the address of the header.
Definition: Fragment.hh:1122