1 #ifndef artdaq_core_Data_Fragment_hh
2 #define artdaq_core_Data_Fragment_hh
18 #include "artdaq-core/Core/QuickVec.hh"
19 #include "artdaq-core/Data/detail/RawFragmentHeader.hh"
20 #include "artdaq-core/Data/detail/RawFragmentHeaderV0.hh"
21 #include "artdaq-core/Data/detail/RawFragmentHeaderV1.hh"
22 #include "artdaq-core/Data/dictionarycontrol.hh"
31 #define DATAVEC_T QuickVec<RawDataType>
205 return std::make_unique<Fragment>(nwords);
264 void print(std::ostream& os)
const;
270 std::size_t
size()
const;
347 struct timespec
atime() const;
430 void resize(std::size_t sz);
505 T newpointer =
reinterpret_cast<T
>(in);
507 if (static_cast<const void*>(newpointer) !=
static_cast<const void*
>(in))
509 throw cet::exception(
"Error in Fragment.hh: reinterpret_cast failed to return expected address-- please contact John Freeman at jcfree@fnal.gov");
533 T newpointer =
reinterpret_cast<T
>(in);
535 if (static_cast<void*>(newpointer) !=
static_cast<void*
>(in))
537 throw cet::exception(
"Error in Fragment.hh: reinterpret_cast failed to return expected address-- please contact John Freeman at jcfree@fnal.gov");
598 return reinterpret_cast_checked<const byte_t*>(&*
dataBegin());
611 return reinterpret_cast_checked<const byte_t*>(&*
dataEnd());
627 return reinterpret_cast_checked<const byte_t*>(&*
headerBegin());
671 void swap(DATAVEC_T& other) noexcept { vals_.
swap(other); };
710 template<
class InputIterator>
718 std::copy(i, e, std::back_inserter(result->vals_));
719 result->updateFragmentHeaderWC_();
747 static std::size_t validatedMetadataSize_();
749 void updateFragmentHeaderWC_();
765 inline artdaq::Fragment& artdaq::Fragment::operator=(artdaq::Fragment&&) noexcept = default;
767 inline
bool constexpr artdaq::Fragment::
770 return fragmentType >= detail::RawFragmentHeader::FIRST_USER_TYPE &&
771 fragmentType <= detail::RawFragmentHeader::LAST_USER_TYPE;
783 validatedMetadataSize_()
788 static_assert(
sizeof(
size_t) >=
789 sizeof(decltype(std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max())),
790 "metadata_word_count_t is too big!");
792 static size_t constexpr max_md_wc =
793 std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max();
794 size_t requested_md_wc =
796 if (requested_md_wc > max_md_wc)
798 throw cet::exception(
"InvalidRequest")
799 <<
"The requested metadata structure is too large: "
800 <<
"requested word count = " << requested_md_wc
801 <<
", maximum word count = " << max_md_wc;
803 return requested_md_wc;
811 : vals_((artdaq::detail::RawFragmentHeader::num_words() +
812 validatedMetadataSize_<T>() +
824 updateFragmentHeaderWC_();
830 fragmentHeaderPtr()->
touch();
842 return fragmentHeader().word_count;
848 auto hdr = reinterpret_cast_checked<detail::RawFragmentHeader const*>(&vals_[0]);
855 return static_cast<type_t>(fragmentHeader().type);
867 return fragmentHeader().sequence_id;
873 return fragmentHeader().fragment_id;
879 return fragmentHeader().timestamp;
885 fragmentHeaderPtr()->setUserType(static_cast<uint8_t>(type));
891 fragmentHeaderPtr()->setSystemType(static_cast<uint8_t>(type));
898 fragmentHeaderPtr()->sequence_id = sequence_id;
904 fragmentHeaderPtr()->fragment_id = fragment_id;
910 fragmentHeaderPtr()->timestamp = timestamp;
915 fragmentHeaderPtr()->touch();
920 return fragmentHeader().atime();
925 return fragmentHeaderPtr()->getLatency(touch);
929 artdaq::Fragment::updateFragmentHeaderWC_()
933 assert(vals_.size() < (1ULL << 32));
934 TRACEN(
"Fragment", 50,
"Fragment::updateFragmentHeaderWC_ adjusting fragmentHeader()->word_count from %u to %zu", (
unsigned)(fragmentHeaderPtr()->word_count), vals_.size());
935 fragmentHeaderPtr()->word_count = vals_.size();
941 return vals_.size() - headerSizeWords() -
942 fragmentHeader().metadata_word_count;
948 return fragmentHeader().metadata_word_count != 0;
954 if (fragmentHeader().metadata_word_count == 0)
956 throw cet::exception(
"InvalidRequest")
957 <<
"No metadata has been stored in this Fragment.";
960 return reinterpret_cast_checked<T*>(&vals_[headerSizeWords()]);
967 if (fragmentHeader().metadata_word_count == 0)
969 throw cet::exception(
"InvalidRequest")
970 <<
"No metadata has been stored in this Fragment.";
972 return reinterpret_cast_checked<T const*>(&vals_[headerSizeWords()]);
978 if (fragmentHeader().metadata_word_count != 0)
980 throw cet::exception(
"InvalidRequest")
981 <<
"Metadata has already been stored in this Fragment.";
983 auto const mdSize = validatedMetadataSize_<T>();
984 vals_.insert(dataBegin(), mdSize, 0);
985 updateFragmentHeaderWC_();
986 fragmentHeaderPtr()->metadata_word_count = mdSize;
988 memcpy(metadataAddress(), &metadata,
sizeof(T));
994 if (fragmentHeader().metadata_word_count == 0)
996 throw cet::exception(
"InvalidRequest")
997 <<
"No metadata in fragment; please use Fragment::setMetadata instead of Fragment::updateMetadata";
1000 auto const mdSize = validatedMetadataSize_<T>();
1002 if (fragmentHeader().metadata_word_count != mdSize)
1004 throw cet::exception(
"InvalidRequest")
1005 <<
"Mismatch between type of metadata struct passed to updateMetadata and existing metadata struct";
1008 memcpy(metadataAddress(), &metadata,
sizeof(T));
1014 vals_.resize(sz + fragmentHeaderPtr()->metadata_word_count +
1016 updateFragmentHeaderWC_();
1022 vals_.resize(sz + fragmentHeaderPtr()->metadata_word_count +
1025 updateFragmentHeaderWC_();
1039 vals_.resizeWithCushion(nwords + fragmentHeaderPtr()->metadata_word_count +
1042 updateFragmentHeaderWC_();
1049 auto ptr = reinterpret_cast_checked<byte_t*>(&defaultval);
1059 resize(nwords, defaultval);
1065 vals_.resize(fragmentHeaderPtr()->word_count);
1066 updateFragmentHeaderWC_();
1072 return vals_.begin() + headerSizeWords() +
1073 fragmentHeader().metadata_word_count;
1085 return vals_.begin();
1091 return vals_.begin() + headerSizeWords() +
1092 fragmentHeader().metadata_word_count;
1104 return vals_.begin();
1110 vals_.erase(dataBegin(), dataEnd());
1111 updateFragmentHeaderWC_();
1117 return (vals_.size() - headerSizeWords() -
1118 fragmentHeader().metadata_word_count) == 0;
1124 vals_.reserve(cap + headerSizeWords() +
1125 fragmentHeader().metadata_word_count);
1131 vals_.swap(other.vals_);
1137 return &vals_[0] + headerSizeWords() +
1138 fragmentHeader().metadata_word_count;
1144 if (fragmentHeader().metadata_word_count == 0)
1146 throw cet::exception(
"InvalidRequest")
1147 <<
"No metadata has been stored in this Fragment.";
1149 return &vals_[0] + headerSizeWords();
1161 auto hdr = reinterpret_cast_checked<detail::RawFragmentHeader const*>(&vals_[0]);
1164 switch (hdr->version)
1167 TLOG(51,
"Fragment") <<
"Cannot get header size of InvalidVersion Fragment";
1171 TLOG(52,
"Fragment") <<
"Getting size of RawFragmentHeaderV0";
1172 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV0 const*>(&vals_[0]);
1173 return old_hdr->num_words();
1178 TLOG(52,
"Fragment") <<
"Getting size of RawFragmentHeaderV1";
1179 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV1 const*>(&vals_[0]);
1180 return old_hdr->num_words();
1184 throw cet::exception(
"Fragment") <<
"A Fragment with an unknown version (" << std::to_string(hdr->version) <<
") was received!";
1188 return hdr->num_words();
1192 artdaq::Fragment::fragmentHeaderPtr()
1194 auto hdr = reinterpret_cast_checked<detail::RawFragmentHeader*>(&vals_[0]);
1197 switch (hdr->version)
1200 TLOG(51,
"Fragment") <<
"Not upgrading InvalidVersion Fragment";
1204 TLOG(52,
"Fragment") <<
"Upgrading RawFragmentHeaderV0 (non const)";
1205 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV0*>(&vals_[0]);
1206 auto new_hdr = old_hdr->upgrade();
1208 auto szDiff = hdr->
num_words() - old_hdr->num_words();
1211 vals_.insert(vals_.begin(), szDiff, 0);
1212 new_hdr.word_count = vals_.size();
1214 memcpy(&vals_[0], &new_hdr, hdr->num_words() *
sizeof(
RawDataType));
1215 hdr = reinterpret_cast_checked<detail::RawFragmentHeader*>(&vals_[0]);
1220 TLOG(52,
"Fragment") <<
"Upgrading RawFragmentHeaderV1 (non const)";
1221 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV1*>(&vals_[0]);
1222 auto new_hdr = old_hdr->upgrade();
1224 auto szDiff = hdr->num_words() - old_hdr->num_words();
1227 vals_.insert(vals_.begin(), szDiff, 0);
1228 new_hdr.word_count = vals_.size();
1230 memcpy(&vals_[0], &new_hdr, hdr->num_words() *
sizeof(
RawDataType));
1231 hdr = reinterpret_cast_checked<detail::RawFragmentHeader*>(&vals_[0]);
1235 throw cet::exception(
"Fragment") <<
"A Fragment with an unknown version (" << std::to_string(hdr->version) <<
") was received!";
1245 auto hdr = *reinterpret_cast_checked<detail::RawFragmentHeader const*>(&vals_[0]);
1248 switch (hdr.version)
1251 TLOG(51,
"Fragment") <<
"Not upgrading InvalidVersion Fragment";
1255 TLOG(52,
"Fragment") <<
"Upgrading RawFragmentHeaderV0 (const)";
1256 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV0 const*>(&vals_[0]);
1257 hdr = old_hdr->upgrade();
1263 TLOG(52,
"Fragment") <<
"Upgrading RawFragmentHeaderV1 (const)";
1264 auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV1 const*>(&vals_[0]);
1265 hdr = old_hdr->upgrade();
1270 throw cet::exception(
"Fragment") <<
"A Fragment with an unknown version (" << std::to_string(hdr.version) <<
") was received!";
1283 inline std::ostream&
std::unique_ptr< Fragment > FragmentPtr
A std::unique_ptr to a Fragment object.
void reserve(std::size_t cap)
Reserves enough memory to hold cap RawDataType words in the Fragment payload.
detail::RawFragmentHeader::timestamp_t timestamp_t
typedef for timestamp_t from RawFragmentHeader
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...
static constexpr type_t InvalidFragmentType
Copy InvalidFragmentType from RawFragmentHeader.
T reinterpret_cast_checked(const RawDataType *in) const
Wrapper around reinterpret_cast.
QuickVec< RawDataType >::difference_type difference_type
Alias difference_type type from QuickVec<RawDataType>
void setSequenceID(sequence_id_t sequence_id)
Sets the Sequence ID of the Fragment.
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.
static constexpr type_t EndOfDataFragmentType
Copy EndOfDataFragmentType from RawFragmentHeader.
static constexpr timestamp_t InvalidTimestamp
Copy InvalidTimestamp from RawFragmentHeader.
static constexpr type_t EmptyFragmentType
Copy EmptyFragmentType from RawFragmentHeader.
const byte_t * dataEndBytes() const
Return const Fragment::byte_t* pointing at the end of the payload.
struct timespec atime() const
Get the last access time of the Fragment.
static constexpr bool isUserFragmentType(type_t fragmentType)
Returns whether the given type is in the range of user types.
detail::RawFragmentHeader::fragment_id_t fragment_id_t
typedef for fragment_id_t from RawFragmentHeader
std::size_t sizeBytes() const
Size of vals_ vector ( header + (optional) metadata + payload) in bytes.
byte_t * dataBeginBytes()
Return Fragment::byte_t* pointing at the beginning of the payload.
detail::RawFragmentHeader::type_t type_t
typedef for type_t from RawFragmentHeader
void resizeBytes(std::size_t szbytes)
Resize the data payload to hold szbytes bytes (padded by the 8-byte RawDataTypes, so...
static FragmentPtr dataFrag(sequence_id_t sequenceID, fragment_id_t fragID, InputIterator i, InputIterator e)
Creates a Fragment, copying data from given location. 12-Apr-2013, KAB - this method is deprecated...
sequence_id_t sequenceID() const
Sequence ID of the Fragment, from the Fragment header.
timestamp_t timestamp() const
Timestamp of the Fragment, from the Fragment header.
static constexpr type_t DataFragmentType
Copy DataFragmentType from RawFragmentHeader.
QuickVec< RawDataType >::const_iterator const_iterator
Alias const_iterator type from QuickVec<RawDataType>
uint8_t byte_t
For byte representation.
void resize(std::size_t sz)
Resize the data payload to hold sz RawDataType words.
void autoResize()
Resize the fragment to hold the number of words indicated by the header.
static constexpr type_t EndOfRunFragmentType
Copy EndOfRunFragmentType from RawFragmentHeader.
static constexpr fragment_id_t InvalidFragmentID
Copy InvalidFragmentID from RawFragmentHeader.
size_t size() const
Accesses the current size of the QuickVec.
static constexpr type_t InitFragmentType
Copy InitFragmentType from RawFragmentHeader.
QuickVec< RawDataType >::reference reference
Alias reference type from QuickVec<RawDataType>
byte_t * headerBeginBytes()
Return a Fragment::byte_t pointer pointing to the beginning of the header.
void setMetadata(const T &metadata)
Set the metadata in the Fragment to the contents of the specified structure. This throws an exception...
static FragmentPtr FragmentBytes(std::size_t payload_size_in_bytes, sequence_id_t sequence_id, fragment_id_t fragment_id, type_t type, const T &metadata, timestamp_t timestamp=Fragment::InvalidTimestamp)
Create a Fragment with the given header values. Uses static factory function instead of constructor t...
static constexpr type_t ErrorFragmentType
Copy ErrorFragmentType from RawFragmentHeader.
struct timespec getLatency(bool touch)
Get the difference between the current time and the last access time of the Fragment.
detail::RawFragmentHeader::version_t version_t
typedef for version_t from RawFragmentHeader
void setTimestamp(timestamp_t timestamp)
Sets the Timestamp of the Fragment.
iterator headerBegin()
Return an iterator to the beginning of the header (should be used for serialization only: use setters...
T reinterpret_cast_checked(RawDataType *in)
Wrapper around reinterpret_cast.
byte_t * dataEndBytes()
Return Fragment::byte_t* pointing at the end of the payload.
static constexpr version_t InvalidVersion
Copy InvalidVersion from RawFragmentHeader.
iterator dataBegin()
Return an iterator to the beginning of the data payload (after header and metadata) ...
bool empty()
Determines if the Fragment contains no data.
static constexpr sequence_id_t InvalidSequenceID
Copy InvalidSequenceID from RawFragmentHeader.
QuickVec< RawDataType >::value_type value_type
Alias value_type type from QuickVec<RawDataType>
static FragmentPtr eodFrag(size_t nFragsToExpect)
Creates an EndOfData Fragment.
void setUserType(type_t utype)
Sets the type of the Fragment, checking that it is a valid user type.
void touch()
Update the access time of the Fragment.
static constexpr type_t ContainerFragmentType
Copy ContainerFragmentType from RawFragmentHeader.
static std::map< type_t, std::string > MakeSystemTypeMap()
Returns a map of the most commonly-used system types.
void updateMetadata(const T &metadata)
Updates existing metadata with a new metadata object.
std::ostream & operator<<(std::ostream &os, Fragment const &f)
Prints the given Fragment to the stream.
void swap(QuickVec &other) noexcept
Exchanges references to two QuickVec objects.
const byte_t * dataBeginBytes() const
Return const Fragment::byte_t* pointing at the beginning of the payload.
type_t type() const
Type of the Fragment, from the Fragment header.
RawDataType * dataAddress()
Returns a RawDataType pointer to the beginning of the payload.
void print(std::ostream &os) const
Print out summary information for this Fragment to the given stream.
T * metadata()
Return a pointer to the metadata. This throws an exception if the Fragment contains no metadata...
iterator dataEnd()
Return an iterator to the end of the data payload.
static FragmentPtr FragmentBytes(std::size_t nbytes)
Create a Fragment using a static factory function rather than a constructor to allow for the function...
static constexpr type_t ShutdownFragmentType
Copy ShutdownFragmentType from RawFragmentHeader.
static constexpr type_t FirstUserFragmentType
Copy FIRST_USER_TYPE from RawFragmentHeader.
std::string typeString() const
Print the type of the Fragment.
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.
size_t headerSizeBytes() const
Get the size of this Fragment's header, in bytes.
std::list< FragmentPtr > FragmentPtrs
A std::list of FragmentPtrs.
Fragment()
Create a Fragment with all header values zeroed.
size_t headerSizeWords() const
Get the size of this Fragment's header, in RawDataType words.
void clear()
Removes all elements from the payload section of the Fragment.
static constexpr bool isSystemFragmentType(type_t fragmentType)
Returns whether the given type is in the range of system types.
QuickVec< RawDataType >::iterator iterator
Alias iterator type from QuickVec<RawDataType>
bool hasMetadata() const
Test whether this Fragment has metadata.
QuickVec< RawDataType >::size_type size_type
Alias size_type type from QuickVec<RawDataType>
const byte_t * headerBeginBytes() const
Return a const Fragment::byte_t pointer pointing to the beginning of the header.
void setFragmentID(fragment_id_t fragment_id)
Sets the Fragment ID of the Fragment.
A Fragment contains the data from one piece of the DAQ system for one event The artdaq::Fragment is t...
void swap(Fragment &other) noexcept
Swaps two Fragment objects.
static constexpr type_t EndOfSubrunFragmentType
Copy EndOfSubrunFragmentType from RawFragmentHeader.
bool fragmentSequenceIDCompare(const Fragment &i, const Fragment &j)
Comparator for Fragment objects, based on their sequence_id.
detail::RawFragmentHeader const fragmentHeader() const
Get a copy of the RawFragmentHeader from this Fragment.
void resizeBytesWithCushion(std::size_t szbytes, double growthFactor=1.3)
Resize the data payload to hold szbytes bytes (padded by the 8-byte RawDataTypes, so...
std::size_t dataSize() const
Return the number of RawDataType words in the data payload. This does not include the number of words...
iterator begin()
Gets an iterator to the beginning of the QuickVec.
void swap(QuickVec< RawDataType > &other) noexcept
Swaps two Fragment data vectors.
detail::RawFragmentHeader::sequence_id_t sequence_id_t
typedef for sequence_id_t from RawFragmentHeader
fragment_id_t fragmentID() const
Fragment ID of the Fragment, from the Fragment header.
RawDataType * headerAddress()
Gets the address of the header.
version_t version() const
Version of the Fragment, from the Fragment header.