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;
94 static size_t words_to_frag_words_(
size_t nWords);
96 void addSpace_(
size_t bytes);
98 uint8_t* dataBegin_() {
return reinterpret_cast<uint8_t*
>(&*artdaq_Fragment_.
dataBegin()); }
99 void* dataEnd_() {
return static_cast<void*
>(dataBegin_() +
lastFragmentIndex()); }
104 , artdaq_Fragment_(f)
116 if (artdaq_Fragment_.
size() !=
120 TLOG(TLVL_ERROR,
"ContainerFragmentLoader") <<
"ContainerFragmentLoader: Raw artdaq::Fragment object size suggests it does not consist of its own header + the ContainerFragment::Metadata object";
123 throw cet::exception(
"InvalidFragment") <<
"ContainerFragmentLoader: Raw artdaq::Fragment object size suggests it does not consist of its own header + the ContainerFragment::Metadata object";
126 artdaq_Fragment_.
resize(1);
130 inline size_t artdaq::ContainerFragmentLoader::words_to_frag_words_(
size_t nWords)
132 size_t mod = nWords % words_per_frag_word_();
133 return mod ? nWords / words_per_frag_word_() + 1 : nWords / words_per_frag_word_();
136 inline void artdaq::ContainerFragmentLoader::addSpace_(
size_t bytes)
139 artdaq_Fragment_.resizeBytesWithCushion(bytes + currSize, 1.3);
142 TLOG(TLVL_DEBUG + 33,
"ContainerFragmentLoader") <<
"addSpace_: dataEnd_ is now at " <<
static_cast<void*
>(dataEnd_()) <<
" (oldSizeBytes/deltaBytes: " << currSize <<
"/" << bytes <<
")";
147 TLOG(TLVL_DEBUG + 33,
"ContainerFragmentLoader") <<
"addFragment: Adding Fragment with payload size " << frag.
dataSizeBytes() <<
" to Container";
149 metadata()->fragment_type = frag.
type();
150 else if (!allowDifferentTypes && frag.
type() != metadata()->fragment_type)
152 TLOG(TLVL_ERROR,
"ContainerFragmentLoader") <<
"addFragment: Trying to add a fragment of different type than what's already been added!";
153 throw cet::exception(
"WrongFragmentType") <<
"ContainerFragmentLoader::addFragment: Trying to add a fragment of different type than what's already been added!";
156 TLOG(TLVL_DEBUG + 33,
"ContainerFragmentLoader") <<
"addFragment: Payload Size is " << artdaq_Fragment_.dataSizeBytes() <<
", lastFragmentIndex is " << lastFragmentIndex() <<
", and frag.size is " << frag.
sizeBytes();
157 if (artdaq_Fragment_.dataSizeBytes() < (lastFragmentIndex() + frag.
sizeBytes() +
sizeof(size_t) * (metadata()->block_count + 2)))
159 addSpace_((lastFragmentIndex() + frag.
sizeBytes() +
sizeof(size_t) * (metadata()->block_count + 2)) - artdaq_Fragment_.dataSizeBytes());
162 TLOG(TLVL_DEBUG + 33,
"ContainerFragmentLoader") <<
"addFragment, copying " << frag.
sizeBytes() <<
" bytes from " <<
static_cast<void*
>(frag.
headerAddress()) <<
" to " << static_cast<void*>(dataEnd_());
164 metadata()->has_index = 0;
166 metadata()->block_count++;
168 auto index = create_index_();
169 metadata()->index_offset = index[metadata()->block_count - 1];
170 memcpy(dataBegin_() + metadata()->index_offset, index,
sizeof(
size_t) * (metadata()->block_count + 1));
172 metadata()->has_index = 1;
178 addFragment(*frag, allowDifferentTypes);
183 TLOG(TLVL_DEBUG + 33,
"ContainerFragmentLoader") <<
"addFragments: Adding " << frags.size() <<
" Fragments to Container";
185 size_t total_size = 0;
186 for (
auto& frag : frags) { total_size += frag->sizeBytes(); }
188 TLOG(TLVL_DEBUG + 33,
"ContainerFragmentLoader") <<
"addFragments: Payload Size is " << artdaq_Fragment_.dataSizeBytes() <<
", lastFragmentIndex is " << lastFragmentIndex() <<
", and size to add is " << total_size;
189 if (artdaq_Fragment_.dataSizeBytes() < (lastFragmentIndex() + total_size +
sizeof(size_t) * (metadata()->block_count + 1 + frags.size())))
191 addSpace_((lastFragmentIndex() + total_size +
sizeof(
size_t) * (metadata()->block_count + 1 + frags.size())) - artdaq_Fragment_.dataSizeBytes());
194 auto data_ptr = dataEnd_();
196 for (
auto& frag : frags)
199 metadata()->fragment_type = frag->type();
200 else if (!allowDifferentTypes && frag->type() != metadata()->fragment_type)
202 TLOG(TLVL_ERROR,
"ContainerFragmentLoader") <<
"addFragments: Trying to add a fragment of different type than what's already been added!";
203 throw cet::exception(
"WrongFragmentType") <<
"ContainerFragmentLoader::addFragments: Trying to add a fragment of different type than what's already been added!";
207 TLOG(TLVL_DEBUG + 33,
"ContainerFragmentLoader") <<
"addFragments, copying " << frag->sizeBytes() <<
" bytes from " <<
static_cast<void*
>(frag->headerAddress()) <<
" to " << static_cast<void*>(dataEnd_());
208 memcpy(data_ptr, frag->headerAddress(), frag->sizeBytes());
209 data_ptr =
static_cast<uint8_t*
>(data_ptr) + frag->sizeBytes();
211 metadata()->has_index = 0;
212 metadata()->block_count += frags.size();
214 auto index = create_index_();
215 metadata()->index_offset = index[metadata()->block_count - 1];
216 memcpy(dataBegin_() + metadata()->index_offset, index,
sizeof(
size_t) * (metadata()->block_count + 1));
218 metadata()->has_index = 1;
std::unique_ptr< Fragment > FragmentPtr
A std::unique_ptr to a Fragment 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...
void setSystemType(type_t stype)
Sets the type of the Fragment, checking that it is a valid system type.
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.
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.
void addFragments(artdaq::FragmentPtrs &frags, bool allowDifferentTypes=false)
Add a collection of Fragment objects to the ContainerFragment.
static constexpr uint8_t CURRENT_VERSION
The current version of the ContainerFragmentHeader.
RawDataType * metadataAddress()
Get the address of the metadata. For internal use only, use metadata() instead.
std::list< FragmentPtr > FragmentPtrs
A std::list of FragmentPtrs.
bool hasMetadata() const
Test whether this Fragment has metadata.
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.