1 #ifndef artdaq_core_Data_ContainerFragmentLoader_hh
2 #define artdaq_core_Data_ContainerFragmentLoader_hh
13 #include "artdaq-core/Data/ContainerFragment.hh"
14 #include "artdaq-core/Data/Fragment.hh"
16 #include "TRACE/tracemf.h"
21 class ContainerFragmentLoader;
115 static size_t words_to_frag_words_(
size_t nWords);
117 void addSpace_(
size_t bytes);
119 uint8_t* dataBegin_() {
return reinterpret_cast<uint8_t*
>(&*artdaq_Fragment_.
dataBegin()); }
120 void* dataEnd_() {
return static_cast<void*
>(dataBegin_() +
lastFragmentIndex()); }
125 , artdaq_Fragment_(f)
137 if (artdaq_Fragment_.
size() !=
141 TLOG(TLVL_ERROR,
"ContainerFragmentLoader") <<
"ContainerFragmentLoader: Raw artdaq::Fragment object size suggests it does not consist of its own header + the ContainerFragment::Metadata object";
144 throw cet::exception(
"InvalidFragment") <<
"ContainerFragmentLoader: Raw artdaq::Fragment object size suggests it does not consist of its own header + the ContainerFragment::Metadata object";
147 artdaq_Fragment_.
resize(1);
151 inline size_t artdaq::ContainerFragmentLoader::words_to_frag_words_(
size_t nWords)
153 size_t mod = nWords % words_per_frag_word_();
154 return mod ? nWords / words_per_frag_word_() + 1 : nWords / words_per_frag_word_();
157 inline void artdaq::ContainerFragmentLoader::addSpace_(
size_t bytes)
160 artdaq_Fragment_.resizeBytesWithCushion(bytes + currSize, 1.3);
163 TLOG(TLVL_DEBUG + 33,
"ContainerFragmentLoader") <<
"addSpace_: dataEnd_ is now at " <<
static_cast<void*
>(dataEnd_()) <<
" (oldSizeBytes/deltaBytes: " << currSize <<
"/" << bytes <<
")";
168 TLOG(TLVL_DEBUG + 33,
"ContainerFragmentLoader") <<
"addFragment: Adding Fragment with payload size " << frag.
dataSizeBytes() <<
" to Container";
170 metadata()->fragment_type = frag.
type();
171 else if (!allowDifferentTypes && frag.
type() != metadata()->fragment_type)
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!";
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)))
180 addSpace_((lastFragmentIndex() + frag.
sizeBytes() +
sizeof(size_t) * (metadata()->block_count + 2)) - artdaq_Fragment_.dataSizeBytes());
183 TLOG(TLVL_DEBUG + 33,
"ContainerFragmentLoader") <<
"addFragment, copying " << frag.
sizeBytes() <<
" bytes from " <<
static_cast<void*
>(frag.
headerAddress()) <<
" to " << static_cast<void*>(dataEnd_());
185 metadata()->has_index = 0;
187 metadata()->block_count++;
189 auto index = create_index_();
190 metadata()->index_offset = index[metadata()->block_count - 1];
191 memcpy(dataBegin_() + metadata()->index_offset, index,
sizeof(
size_t) * (metadata()->block_count + 1));
193 metadata()->has_index = 1;
200 TLOG(TLVL_DEBUG + 33,
"ContainerFragmentLoader") <<
"addFragments: Adding " << frags.size() <<
" Fragments to Container";
202 size_t total_size = 0;
203 for (
auto& frag : frags) { total_size += frag.sizeBytes(); }
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())))
208 addSpace_((lastFragmentIndex() + total_size +
sizeof(
size_t) * (metadata()->block_count + 1 + frags.size())) - artdaq_Fragment_.dataSizeBytes());
211 auto data_ptr = dataEnd_();
213 for (
auto& frag : frags)
216 metadata()->fragment_type = frag.type();
217 else if (!allowDifferentTypes && frag.type() != metadata()->fragment_type)
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!";
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();
228 metadata()->has_index = 0;
229 metadata()->block_count += frags.size();
231 auto index = create_index_();
232 metadata()->index_offset = index[metadata()->block_count - 1];
233 memcpy(dataBegin_() + metadata()->index_offset, index,
sizeof(
size_t) * (metadata()->block_count + 1));
235 metadata()->has_index = 1;
241 TLOG(TLVL_TRACE,
"ContainerFragmentLoader") <<
"addFragment: Allocating Fragment with payload size " << nwords <<
" in Container";
244 TLOG(TLVL_TRACE,
"ContainerFragmentLoader") <<
"addFragment: Payload Size is " << artdaq_Fragment_.dataSizeBytes() <<
", lastFragmentIndex is " << lastFragmentIndex() <<
", and frag.size is "
246 if (artdaq_Fragment_.dataSizeBytes() < (lastFragmentIndex() + fragSizeBytes +
sizeof(size_t) * (metadata()->block_count + 2)))
248 addSpace_((lastFragmentIndex() + fragSizeBytes +
sizeof(
size_t) * (metadata()->block_count + 2)) - artdaq_Fragment_.dataSizeBytes());
253 hdr.
type = metadata()->fragment_type;
258 auto ptr = dataEnd_();
261 metadata()->has_index = 0;
263 metadata()->block_count++;
265 auto index = create_index_();
266 metadata()->index_offset = index[metadata()->block_count - 1];
267 memcpy(dataBegin_() + metadata()->index_offset, index,
sizeof(
size_t) * (metadata()->block_count + 1));
269 metadata()->has_index = 1;
272 return lastFragmentHeader();
277 auto hdr = lastFragmentHeader();
282 if (curFragSize < nwords)
286 metadata()->has_index = 0;
288 auto index = create_index_();
289 metadata()->index_offset = index[metadata()->block_count - 1];
290 memcpy(dataBegin_() + metadata()->index_offset, index,
sizeof(
size_t) * (metadata()->block_count + 1));
292 metadata()->has_index = 1;
298 addFragment(*frag, allowDifferentTypes);
303 TLOG(TLVL_DEBUG + 33,
"ContainerFragmentLoader") <<
"addFragments: Adding " << frags.size() <<
" Fragments to Container";
305 size_t total_size = 0;
306 for (
auto& frag : frags) { total_size += frag->sizeBytes(); }
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())))
311 addSpace_((lastFragmentIndex() + total_size +
sizeof(
size_t) * (metadata()->block_count + 1 + frags.size())) - artdaq_Fragment_.dataSizeBytes());
314 auto data_ptr = dataEnd_();
316 for (
auto& frag : frags)
319 metadata()->fragment_type = frag->type();
320 else if (!allowDifferentTypes && frag->type() != metadata()->fragment_type)
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!";
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();
331 metadata()->has_index = 0;
332 metadata()->block_count += frags.size();
334 auto index = create_index_();
335 metadata()->index_offset = index[metadata()->block_count - 1];
336 memcpy(dataBegin_() + metadata()->index_offset, index,
sizeof(
size_t) * (metadata()->block_count + 1));
338 metadata()->has_index = 1;
std::unique_ptr< Fragment > FragmentPtr
A std::unique_ptr to a Fragment 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...
void setSystemType(type_t stype)
Sets the type of the Fragment, checking that it is a valid system type.
std::vector< Fragment > Fragments
A std::vector of Fragment objects.
std::size_t size() const
Gets the size of the Fragment, from the Fragment header.
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.
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.
detail::RawFragmentHeader::type_t type_t
typedef for type_t from RawFragmentHeader
void resize(std::size_t sz)
Resize the data payload to hold sz RawDataType words.
static constexpr size_t CONTAINER_MAGIC
Marker word used in index.
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...
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...
iterator dataBegin()
Return an iterator to the beginning of the data payload (after header and metadata) ...
QuickVec< RawDataType >::value_type value_type
Alias value_type type from QuickVec<RawDataType>
static constexpr type_t ContainerFragmentType
Copy ContainerFragmentType from RawFragmentHeader.
ContainerFragmentLoader(Fragment &f, Fragment::type_t expectedFragmentType)
Constructs the ContainerFragmentLoader.
type_t type() const
Type of the Fragment, from the Fragment header.
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 ...
RawDataType * metadataAddress()
Get the address of the metadata. For internal use only, use metadata() instead.
std::list< FragmentPtr > FragmentPtrs
A std::list of FragmentPtrs.
void addFragments(artdaq::Fragments &frags, bool allowDifferentTypes=false)
Add a collection of Fragment objects to the ContainerFragment.
bool hasMetadata() const
Test whether this Fragment has metadata.
detail::RawFragmentHeader * appendFragment(size_t nwords)
Create a Fragment at the end of the ContainerFragment with the given size nwords Size (in RawDataTyp...
A Fragment contains the data from one piece of the DAQ system for one event The artdaq::Fragment is t...
void set_missing_data(bool isDataMissing)
Sets the missing_data flag.
RawDataType * headerAddress()
Gets the address of the header.