artdaq_core  v3_05_07
Fragment.hh
1 #ifndef artdaq_core_Data_Fragment_hh
2 #define artdaq_core_Data_Fragment_hh
3 
4 #include <algorithm>
5 //#include <cassert>
6 #include <stdint.h>
7 #include <string.h>
8 #include <cmath>
9 #include <cstddef>
10 #include <iosfwd>
11 #include <iterator>
12 #include <list>
13 #include <map>
14 #include <memory>
15 #include <vector>
16 
17 #include <iostream>
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"
23 #if HIDE_FROM_ROOT
24 #include "trace.h" // TRACE
25 #endif
26 
30 namespace artdaq {
31 #define DATAVEC_T QuickVec<RawDataType>
32 //#define DATAVEC_T std::vector<RawDataType>
33 
41 
42 class Fragment;
46 typedef std::vector<Fragment> Fragments;
47 
54 typedef std::unique_ptr<Fragment> FragmentPtr;
55 
59 typedef std::list<FragmentPtr> FragmentPtrs;
60 
68 
75 std::ostream& operator<<(std::ostream& os, Fragment const& f);
76 } // namespace artdaq
77 
86 {
87 public:
91  Fragment();
92 
100  typedef uint8_t byte_t;
101 
102  // Hide most things from ROOT.
103 #if HIDE_FROM_ROOT
104 
105  // http://stackoverflow.com/questions/33939687
106  // This should generate an exception if artdaq::Fragment is not move-constructible
111  Fragment(const Fragment&) = default;
119  Fragment(Fragment&&) noexcept;
125  Fragment& operator=(const Fragment&) = default;
134  Fragment& operator=(Fragment&&) noexcept;
135 
136  typedef detail::RawFragmentHeader::version_t version_t;
137  typedef detail::RawFragmentHeader::type_t type_t;
138  typedef detail::RawFragmentHeader::sequence_id_t sequence_id_t;
139  typedef detail::RawFragmentHeader::fragment_id_t fragment_id_t;
140  typedef detail::RawFragmentHeader::timestamp_t timestamp_t;
141 
142  static constexpr version_t InvalidVersion = detail::RawFragmentHeader::InvalidVersion;
143  static constexpr sequence_id_t InvalidSequenceID = detail::RawFragmentHeader::InvalidSequenceID;
144  static constexpr fragment_id_t InvalidFragmentID = detail::RawFragmentHeader::InvalidFragmentID;
145  static constexpr timestamp_t InvalidTimestamp = detail::RawFragmentHeader::InvalidTimestamp;
146 
147  static constexpr type_t InvalidFragmentType = detail::RawFragmentHeader::InvalidFragmentType;
148  static constexpr type_t EndOfDataFragmentType = detail::RawFragmentHeader::EndOfDataFragmentType;
149  static constexpr type_t DataFragmentType = detail::RawFragmentHeader::DataFragmentType;
150  static constexpr type_t InitFragmentType = detail::RawFragmentHeader::InitFragmentType;
151  static constexpr type_t EndOfRunFragmentType = detail::RawFragmentHeader::EndOfRunFragmentType;
152  static constexpr type_t EndOfSubrunFragmentType = detail::RawFragmentHeader::EndOfSubrunFragmentType;
153  static constexpr type_t ShutdownFragmentType = detail::RawFragmentHeader::ShutdownFragmentType;
154  static constexpr type_t FirstUserFragmentType = detail::RawFragmentHeader::FIRST_USER_TYPE;
155  static constexpr type_t EmptyFragmentType = detail::RawFragmentHeader::EmptyFragmentType;
156  static constexpr type_t ContainerFragmentType = detail::RawFragmentHeader::ContainerFragmentType;
157  static constexpr type_t ErrorFragmentType = detail::RawFragmentHeader::ErrorFragmentType;
158 
164  static constexpr bool isUserFragmentType(type_t fragmentType);
165 
171  static constexpr bool isSystemFragmentType(type_t fragmentType);
172 
177  static std::map<type_t, std::string> MakeSystemTypeMap()
178  {
180  }
181 
182  typedef DATAVEC_T::reference reference;
183  typedef DATAVEC_T::iterator iterator;
184  typedef DATAVEC_T::const_iterator const_iterator;
185  typedef DATAVEC_T::value_type value_type;
186  typedef DATAVEC_T::difference_type difference_type;
187  typedef DATAVEC_T::size_type size_type;
188 
194  explicit Fragment(std::size_t n);
195 
202  static FragmentPtr FragmentBytes(std::size_t nbytes)
203  {
204  RawDataType nwords = ceil(nbytes / static_cast<double>(sizeof(RawDataType)));
205  return FragmentPtr(new Fragment(nwords));
206  }
207 
218  template<class T>
219  Fragment(std::size_t payload_size, sequence_id_t sequence_id,
220  fragment_id_t fragment_id, type_t type, const T& metadata,
222 
236  template<class T>
237  static FragmentPtr FragmentBytes(std::size_t payload_size_in_bytes,
238  sequence_id_t sequence_id,
239  fragment_id_t fragment_id,
240  type_t type, const T& metadata,
242  {
243  RawDataType nwords = ceil(payload_size_in_bytes /
244  static_cast<double>(sizeof(RawDataType)));
245  return FragmentPtr(new Fragment(nwords, sequence_id, fragment_id, type, metadata, timestamp));
246  }
247 
256  fragment_id_t fragID,
259 
264  void print(std::ostream& os) const;
265 
270  std::size_t size() const;
271 
276  version_t version() const;
277 
282  type_t type() const;
283 
288  std::string typeString() const;
289 
294  sequence_id_t sequenceID() const;
295 
300  fragment_id_t fragmentID() const;
301 
306  timestamp_t timestamp() const;
307 
312  void setUserType(type_t utype);
313 
318  void setSystemType(type_t stype);
319 
324  void setSequenceID(sequence_id_t sequence_id);
325 
330  void setFragmentID(fragment_id_t fragment_id);
331 
337 
341  void touch();
342 
347  struct timespec atime() const;
348 
354  struct timespec getLatency(bool touch);
355 
360  std::size_t sizeBytes() const { return sizeof(RawDataType) * size(); }
361 
367  std::size_t dataSize() const;
368 
374  std::size_t dataSizeBytes() const
375  {
376  return sizeof(RawDataType) * dataSize();
377  }
378 
383  bool hasMetadata() const;
384 
392  template<class T>
393  T* metadata();
394 
402  template<class T>
403  T const* metadata() const;
404 
413  template<class T>
414  void setMetadata(const T& md);
415 
423  template<class T>
424  void updateMetadata(const T& md);
425 
430  void resize(std::size_t sz);
431 
437  void resize(std::size_t sz, RawDataType val);
438 
445  void resizeBytes(std::size_t szbytes);
446 
455  void resizeBytesWithCushion(std::size_t szbytes, double growthFactor = 1.3);
456 
464  void resizeBytes(std::size_t szbytes, byte_t val);
465 
469  void autoResize();
470 
476 
481  iterator dataEnd();
482 
502  template<typename T>
504  {
505  T newpointer = reinterpret_cast<T>(in);
506 
507  if (static_cast<const void*>(newpointer) != static_cast<const void*>(in))
508  {
509  throw cet::exception("Error in Fragment.hh: reinterpret_cast failed to return expected address-- please contact John Freeman at jcfree@fnal.gov");
510  }
511 
512  return newpointer;
513  }
514 
530  template<typename T>
532  {
533  T newpointer = reinterpret_cast<T>(in);
534 
535  if (static_cast<void*>(newpointer) != static_cast<void*>(in))
536  {
537  throw cet::exception("Error in Fragment.hh: reinterpret_cast failed to return expected address-- please contact John Freeman at jcfree@fnal.gov");
538  }
539 
540  return newpointer;
541  }
542 
551  byte_t* dataBeginBytes() { return reinterpret_cast_checked<byte_t*>(&*dataBegin()); }
552 
561  byte_t* dataEndBytes() { return reinterpret_cast_checked<byte_t*>(&*dataEnd()); }
562 
569 
574  byte_t* headerBeginBytes() { return reinterpret_cast_checked<byte_t*>(&*headerBegin()); }
575 
580  const_iterator dataBegin() const;
581 
586  const_iterator dataEnd() const;
587 
596  const byte_t* dataBeginBytes() const
597  {
598  return reinterpret_cast_checked<const byte_t*>(&*dataBegin());
599  }
600 
609  const byte_t* dataEndBytes() const
610  {
611  return reinterpret_cast_checked<const byte_t*>(&*dataEnd());
612  }
613 
619  const_iterator headerBegin() const; // See note for non-const, above.
620 
625  const byte_t* headerBeginBytes() const
626  {
627  return reinterpret_cast_checked<const byte_t*>(&*headerBegin());
628  }
629 
630  size_t headerSizeWords() const;
631  size_t headerSizeBytes() const { return sizeof(RawDataType) * headerSizeWords(); }
632 
636  void clear();
637 
642  bool empty();
643 
648  void reserve(std::size_t cap);
649 
654  void swap(Fragment& other) noexcept;
655 
662  void swap(DATAVEC_T& other) noexcept { vals_.swap(other); };
663 
669 
682 
688  static FragmentPtr eodFrag(size_t nFragsToExpect);
689 
701  template<class InputIterator>
703  fragment_id_t fragID,
704  InputIterator i,
705  InputIterator e)
706  {
707  FragmentPtr result(new Fragment(sequenceID, fragID));
708  result->vals_.reserve(std::distance(i, e) + detail::RawFragmentHeader::num_words());
709  std::copy(i, e, std::back_inserter(result->vals_));
710  result->updateFragmentHeaderWC_();
711  return result;
712  }
713 
724  fragment_id_t fragID,
725  RawDataType const* dataPtr,
726  size_t dataSize,
728 #endif
729 
730 private:
731  template<typename T>
732  static std::size_t validatedMetadataSize_();
733 
734  void updateFragmentHeaderWC_();
735 
736  DATAVEC_T vals_;
737 
738 #if HIDE_FROM_ROOT
739 
740  detail::RawFragmentHeader* fragmentHeaderPtr();
741 
742  detail::RawFragmentHeader const fragmentHeader() const;
743 #endif
744 };
745 
746 #if HIDE_FROM_ROOT
747 
748 // http://stackoverflow.com/questions/33939687
749 // This should generate an exception if artdaq::Fragment is not move-constructible
750 inline artdaq::Fragment::Fragment(artdaq::Fragment&&) noexcept = default;
751 inline artdaq::Fragment& artdaq::Fragment::operator=(artdaq::Fragment&&) noexcept = default;
752 
753 inline bool constexpr artdaq::Fragment::
754  isUserFragmentType(type_t fragmentType)
755 {
756  return fragmentType >= detail::RawFragmentHeader::FIRST_USER_TYPE &&
757  fragmentType <= detail::RawFragmentHeader::LAST_USER_TYPE;
758 }
759 
760 inline bool constexpr artdaq::Fragment::
762 {
763  return fragmentType >= detail::RawFragmentHeader::FIRST_SYSTEM_TYPE;
764 }
765 
766 template<typename T>
767 std::size_t
768 artdaq::Fragment::
769  validatedMetadataSize_()
770 {
771  // Make sure a size_t is big enough to hold the maximum metadata
772  // size. This *should* always be true, but it is a compile-time check
773  // and therefore cheap.
774  static_assert(sizeof(size_t) >=
775  sizeof(decltype(std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max())),
776  "metadata_word_count_t is too big!");
777 
778  static size_t constexpr max_md_wc =
779  std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max();
780  size_t requested_md_wc =
781  std::ceil(sizeof(T) / static_cast<double>(sizeof(artdaq::RawDataType)));
782  if (requested_md_wc > max_md_wc)
783  {
784  throw cet::exception("InvalidRequest")
785  << "The requested metadata structure is too large: "
786  << "requested word count = " << requested_md_wc
787  << ", maximum word count = " << max_md_wc;
788  }
789  return requested_md_wc;
790 }
791 
792 template<class T>
794  Fragment(std::size_t payload_size, sequence_id_t sequence_id,
795  fragment_id_t fragment_id,
796  type_t type, const T& metadata, timestamp_t timestamp)
797  : vals_((artdaq::detail::RawFragmentHeader::num_words() + // Header
798  validatedMetadataSize_<T>() + // Metadata
799  payload_size) // User data
800  )
801 {
802  TRACEN("Fragment", 50, "Fragment ctor num_word()=%zu MetadataSize_=%zu payload_size=%zu", artdaq::detail::RawFragmentHeader::num_words(), validatedMetadataSize_<T>(), payload_size);
803  // vals ctor w/o init val is used; make sure header is ALL initialized.
804  for (iterator ii = vals_.begin();
805  ii != (vals_.begin() + detail::RawFragmentHeader::num_words()); ++ii)
806  {
807  *ii = -1;
808  }
809  fragmentHeaderPtr()->version = detail::RawFragmentHeader::CurrentVersion;
810  updateFragmentHeaderWC_();
811  fragmentHeaderPtr()->sequence_id = sequence_id;
812  fragmentHeaderPtr()->fragment_id = fragment_id;
813  fragmentHeaderPtr()->timestamp = timestamp;
814  fragmentHeaderPtr()->type = type;
815 
816  fragmentHeaderPtr()->touch();
817 
818  fragmentHeaderPtr()->metadata_word_count =
819  vals_.size() -
820  (headerSizeWords() + payload_size);
821 
822  memcpy(metadataAddress(), &metadata, sizeof(T));
823 }
824 
825 inline std::size_t
827 {
828  return fragmentHeader().word_count;
829 }
830 
833 {
834  auto hdr = reinterpret_cast_checked<detail::RawFragmentHeader const*>(&vals_[0]);
835  return hdr->version;
836 }
837 
840 {
841  return static_cast<type_t>(fragmentHeader().type);
842 }
843 
844 inline std::string
846 {
847  return std::to_string(type()) + (isSystemFragmentType(type()) ? " (" + detail::RawFragmentHeader::SystemTypeToString(type()) + ")" : "");
848 }
849 
852 {
853  return fragmentHeader().sequence_id;
854 }
855 
858 {
859  return fragmentHeader().fragment_id;
860 }
861 
864 {
865  return fragmentHeader().timestamp;
866 }
867 
868 inline void
870 {
871  fragmentHeaderPtr()->setUserType(static_cast<uint8_t>(type));
872 }
873 
874 inline void
876 {
877  fragmentHeaderPtr()->setSystemType(static_cast<uint8_t>(type));
878 }
879 
880 inline void
882 {
883  assert(sequence_id <= detail::RawFragmentHeader::InvalidSequenceID);
884  fragmentHeaderPtr()->sequence_id = sequence_id;
885 }
886 
887 inline void
889 {
890  fragmentHeaderPtr()->fragment_id = fragment_id;
891 }
892 
893 inline void
895 {
896  fragmentHeaderPtr()->timestamp = timestamp;
897 }
898 
900 {
901  fragmentHeaderPtr()->touch();
902 }
903 
904 inline struct timespec artdaq::Fragment::atime() const
905 {
906  return fragmentHeader().atime();
907 }
908 
909 inline struct timespec artdaq::Fragment::getLatency(bool touch)
910 {
911  return fragmentHeaderPtr()->getLatency(touch);
912 }
913 
914 inline void
915 artdaq::Fragment::updateFragmentHeaderWC_()
916 {
917  // Make sure vals_.size() fits inside 32 bits. Left-shift here should
918  // match bitfield size of word_count in RawFragmentHeader.
919  assert(vals_.size() < (1ULL << 32));
920  TRACEN("Fragment", 50, "Fragment::updateFragmentHeaderWC_ adjusting fragmentHeader()->word_count from %u to %zu", (unsigned)(fragmentHeaderPtr()->word_count), vals_.size());
921  fragmentHeaderPtr()->word_count = vals_.size();
922 }
923 
924 inline std::size_t
926 {
927  return vals_.size() - headerSizeWords() -
928  fragmentHeader().metadata_word_count;
929 }
930 
931 inline bool
933 {
934  return fragmentHeader().metadata_word_count != 0;
935 }
936 
937 template<class T>
939 {
940  if (fragmentHeader().metadata_word_count == 0)
941  {
942  throw cet::exception("InvalidRequest")
943  << "No metadata has been stored in this Fragment.";
944  }
945 
946  return reinterpret_cast_checked<T*>(&vals_[headerSizeWords()]);
947 }
948 
949 template<class T>
950 T const*
952 {
953  if (fragmentHeader().metadata_word_count == 0)
954  {
955  throw cet::exception("InvalidRequest")
956  << "No metadata has been stored in this Fragment.";
957  }
958  return reinterpret_cast_checked<T const*>(&vals_[headerSizeWords()]);
959 }
960 
961 template<class T>
962 void artdaq::Fragment::setMetadata(const T& metadata)
963 {
964  if (fragmentHeader().metadata_word_count != 0)
965  {
966  throw cet::exception("InvalidRequest")
967  << "Metadata has already been stored in this Fragment.";
968  }
969  auto const mdSize = validatedMetadataSize_<T>();
970  vals_.insert(dataBegin(), mdSize, 0);
971  updateFragmentHeaderWC_();
972  fragmentHeaderPtr()->metadata_word_count = mdSize;
973 
974  memcpy(metadataAddress(), &metadata, sizeof(T));
975 }
976 
977 template<class T>
978 void artdaq::Fragment::updateMetadata(const T& metadata)
979 {
980  if (fragmentHeader().metadata_word_count == 0)
981  {
982  throw cet::exception("InvalidRequest")
983  << "No metadata in fragment; please use Fragment::setMetadata instead of Fragment::updateMetadata";
984  }
985 
986  auto const mdSize = validatedMetadataSize_<T>();
987 
988  if (fragmentHeader().metadata_word_count != mdSize)
989  {
990  throw cet::exception("InvalidRequest")
991  << "Mismatch between type of metadata struct passed to updateMetadata and existing metadata struct";
992  }
993 
994  memcpy(metadataAddress(), &metadata, sizeof(T));
995 }
996 
997 inline void
999 {
1000  vals_.resize(sz + fragmentHeaderPtr()->metadata_word_count +
1001  headerSizeWords());
1002  updateFragmentHeaderWC_();
1003 }
1004 
1005 inline void
1007 {
1008  vals_.resize(sz + fragmentHeaderPtr()->metadata_word_count +
1009  headerSizeWords(),
1010  v);
1011  updateFragmentHeaderWC_();
1012 }
1013 
1014 inline void
1015 artdaq::Fragment::resizeBytes(std::size_t szbytes)
1016 {
1017  RawDataType nwords = ceil(szbytes / static_cast<double>(sizeof(RawDataType)));
1018  resize(nwords);
1019 }
1020 
1021 inline void
1022 artdaq::Fragment::resizeBytesWithCushion(std::size_t szbytes, double growthFactor)
1023 {
1024  RawDataType nwords = ceil(szbytes / static_cast<double>(sizeof(RawDataType)));
1025  vals_.resizeWithCushion(nwords + fragmentHeaderPtr()->metadata_word_count +
1026  headerSizeWords(),
1027  growthFactor);
1028  updateFragmentHeaderWC_();
1029 }
1030 
1031 inline void
1032 artdaq::Fragment::resizeBytes(std::size_t szbytes, byte_t v)
1033 {
1034  RawDataType defaultval;
1035  byte_t* ptr = reinterpret_cast_checked<byte_t*>(&defaultval);
1036 
1037  for (uint8_t i = 0; i < sizeof(RawDataType); ++i)
1038  {
1039  *ptr = v;
1040  ptr++;
1041  }
1042 
1043  RawDataType nwords = ceil(szbytes / static_cast<double>(sizeof(RawDataType)));
1044 
1045  resize(nwords, defaultval);
1046 }
1047 
1048 inline void
1050 {
1051  vals_.resize(fragmentHeaderPtr()->word_count);
1052  updateFragmentHeaderWC_();
1053 }
1054 
1057 {
1058  return vals_.begin() + headerSizeWords() +
1059  fragmentHeader().metadata_word_count;
1060 }
1061 
1064 {
1065  return vals_.end();
1066 }
1067 
1070 {
1071  return vals_.begin();
1072 }
1073 
1076 {
1077  return vals_.begin() + headerSizeWords() +
1078  fragmentHeader().metadata_word_count;
1079 }
1080 
1083 {
1084  return vals_.end();
1085 }
1086 
1089 {
1090  return vals_.begin();
1091 }
1092 
1093 inline void
1095 {
1096  vals_.erase(dataBegin(), dataEnd());
1097  updateFragmentHeaderWC_();
1098 }
1099 
1100 inline bool
1102 {
1103  return (vals_.size() - headerSizeWords() -
1104  fragmentHeader().metadata_word_count) == 0;
1105 }
1106 
1107 inline void
1109 {
1110  vals_.reserve(cap + headerSizeWords() +
1111  fragmentHeader().metadata_word_count);
1112 }
1113 
1114 inline void
1116 {
1117  vals_.swap(other.vals_);
1118 }
1119 
1120 inline artdaq::RawDataType*
1122 {
1123  return &vals_[0] + headerSizeWords() +
1124  fragmentHeader().metadata_word_count;
1125 }
1126 
1127 inline artdaq::RawDataType*
1129 {
1130  if (fragmentHeader().metadata_word_count == 0)
1131  {
1132  throw cet::exception("InvalidRequest")
1133  << "No metadata has been stored in this Fragment.";
1134  }
1135  return &vals_[0] + headerSizeWords();
1136 }
1137 
1138 inline artdaq::RawDataType*
1140 {
1141  return &vals_[0];
1142 }
1143 
1144 inline size_t
1145 artdaq::Fragment::headerSizeWords() const
1146 {
1147  auto hdr = reinterpret_cast_checked<detail::RawFragmentHeader const*>(&vals_[0]);
1148  if (hdr->version != detail::RawFragmentHeader::CurrentVersion)
1149  {
1150  switch (hdr->version)
1151  {
1152  case 0xFFFF:
1153  TLOG(51, "Fragment") << "Cannot get header size of InvalidVersion Fragment";
1154  break;
1155  case 0:
1156  {
1157  TLOG(52, "Fragment") << "Getting size of RawFragmentHeaderV0";
1158  auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV0 const*>(&vals_[0]);
1159  return old_hdr->num_words();
1160  break;
1161  }
1162  case 1:
1163  {
1164  TLOG(52, "Fragment") << "Getting size of RawFragmentHeaderV1";
1165  auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV1 const*>(&vals_[0]);
1166  return old_hdr->num_words();
1167  break;
1168  }
1169  default:
1170  throw cet::exception("Fragment") << "A Fragment with an unknown version (" << std::to_string(hdr->version) << ") was received!";
1171  break;
1172  }
1173  }
1174  return hdr->num_words();
1175 }
1176 
1178 artdaq::Fragment::fragmentHeaderPtr()
1179 {
1180  auto hdr = reinterpret_cast_checked<detail::RawFragmentHeader*>(&vals_[0]);
1181  if (hdr->version != detail::RawFragmentHeader::CurrentVersion)
1182  {
1183  switch (hdr->version)
1184  {
1185  case 0xFFFF:
1186  TLOG(51, "Fragment") << "Not upgrading InvalidVersion Fragment";
1187  break;
1188  case 0:
1189  {
1190  TLOG(52, "Fragment") << "Upgrading RawFragmentHeaderV0 (non const)";
1191  auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV0*>(&vals_[0]);
1192  auto new_hdr = old_hdr->upgrade();
1193 
1194  auto szDiff = hdr->num_words() - old_hdr->num_words();
1195  if (szDiff > 0)
1196  {
1197  vals_.insert(vals_.begin(), szDiff, 0);
1198  new_hdr.word_count = vals_.size();
1199  }
1200  memcpy(&vals_[0], &new_hdr, hdr->num_words() * sizeof(RawDataType));
1201  hdr = reinterpret_cast_checked<detail::RawFragmentHeader*>(&vals_[0]); // Update hdr in case vals_->insert call invalidated pointers
1202  break;
1203  }
1204  case 1:
1205  {
1206  TLOG(52, "Fragment") << "Upgrading RawFragmentHeaderV1 (non const)";
1207  auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV1*>(&vals_[0]);
1208  auto new_hdr = old_hdr->upgrade();
1209 
1210  auto szDiff = hdr->num_words() - old_hdr->num_words();
1211  if (szDiff > 0)
1212  {
1213  vals_.insert(vals_.begin(), szDiff, 0);
1214  new_hdr.word_count = vals_.size();
1215  }
1216  memcpy(&vals_[0], &new_hdr, hdr->num_words() * sizeof(RawDataType));
1217  hdr = reinterpret_cast_checked<detail::RawFragmentHeader*>(&vals_[0]); // Update hdr in case vals_->insert call invalidated pointers
1218  break;
1219  }
1220  default:
1221  throw cet::exception("Fragment") << "A Fragment with an unknown version (" << std::to_string(hdr->version) << ") was received!";
1222  break;
1223  }
1224  }
1225  return hdr;
1226 }
1227 
1229 artdaq::Fragment::fragmentHeader() const
1230 {
1231  auto hdr = *reinterpret_cast_checked<detail::RawFragmentHeader const*>(&vals_[0]);
1232  if (hdr.version != detail::RawFragmentHeader::CurrentVersion)
1233  {
1234  switch (hdr.version)
1235  {
1236  case 0xFFFF:
1237  TLOG(51, "Fragment") << "Not upgrading InvalidVersion Fragment";
1238  break;
1239  case 0:
1240  {
1241  TLOG(52, "Fragment") << "Upgrading RawFragmentHeaderV0 (const)";
1242  auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV0 const*>(&vals_[0]);
1243  hdr = old_hdr->upgrade();
1244 
1245  break;
1246  }
1247  case 1:
1248  {
1249  TLOG(52, "Fragment") << "Upgrading RawFragmentHeaderV1 (const)";
1250  auto old_hdr = reinterpret_cast_checked<detail::RawFragmentHeaderV1 const*>(&vals_[0]);
1251  hdr = old_hdr->upgrade();
1252 
1253  break;
1254  }
1255  default:
1256  throw cet::exception("Fragment") << "A Fragment with an unknown version (" << std::to_string(hdr.version) << ") was received!";
1257  break;
1258  }
1259  }
1260  return hdr;
1261 }
1262 
1263 inline void
1264 swap(artdaq::Fragment& x, artdaq::Fragment& y) noexcept
1265 {
1266  x.swap(y);
1267 }
1268 
1269 inline std::ostream&
1270 artdaq::operator<<(std::ostream& os, artdaq::Fragment const& f)
1271 {
1272  f.print(os);
1273  return os;
1274 }
1275 #endif /* HIDE_FROM_ROOT */
1276 
1277 #endif /* artdaq_core_Data_Fragment_hh */
std::unique_ptr< Fragment > FragmentPtr
A std::unique_ptr to a Fragment object.
Definition: Fragment.hh:54
void reserve(std::size_t cap)
Reserves enough memory to hold cap RawDataType words in the Fragment payload.
Definition: Fragment.hh:1108
detail::RawFragmentHeader::timestamp_t timestamp_t
typedef for timestamp_t from RawFragmentHeader
Definition: Fragment.hh:140
RawDataType metadata_word_count
The number of RawDataType words in the user-defined metadata.
static const sequence_id_t InvalidSequenceID
The sequence_id field is currently 48-bits.
static constexpr type_t FIRST_SYSTEM_TYPE
The first system type.
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.
static constexpr type_t InvalidFragmentType
Copy InvalidFragmentType from RawFragmentHeader.
Definition: Fragment.hh:147
T reinterpret_cast_checked(const RawDataType *in) const
Wrapper around reinterpret_cast.
Definition: Fragment.hh:503
QuickVec< RawDataType >::difference_type difference_type
Alias difference_type type from QuickVec&lt;RawDataType&gt;
Definition: Fragment.hh:186
void setSequenceID(sequence_id_t sequence_id)
Sets the Sequence ID of the Fragment.
Definition: Fragment.hh:881
void setSystemType(type_t stype)
Sets the type of the Fragment, checking that it is a valid system type.
Definition: Fragment.hh:875
static std::map< type_t, std::string > MakeSystemTypeMap()
Returns a map of the most-commonly used system types.
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:826
static constexpr type_t EndOfDataFragmentType
Copy EndOfDataFragmentType from RawFragmentHeader.
Definition: Fragment.hh:148
static constexpr timestamp_t InvalidTimestamp
Copy InvalidTimestamp from RawFragmentHeader.
Definition: Fragment.hh:145
void updateMetadata(const T &md)
Updates existing metadata with a new metadata object.
Definition: Fragment.hh:978
static constexpr type_t EmptyFragmentType
Copy EmptyFragmentType from RawFragmentHeader.
Definition: Fragment.hh:155
bool fragmentSequenceIDCompare(Fragment i, Fragment j)
Comparator for Fragment objects, based on their sequence_id.
Definition: Fragment.cc:8
const byte_t * dataEndBytes() const
Return const Fragment::byte_t* pointing at the end of the payload.
Definition: Fragment.hh:609
struct timespec atime() const
Get the last access time of the Fragment.
Definition: Fragment.hh:904
static constexpr bool isUserFragmentType(type_t fragmentType)
Returns whether the given type is in the range of user types.
Definition: Fragment.hh:754
detail::RawFragmentHeader::fragment_id_t fragment_id_t
typedef for fragment_id_t from RawFragmentHeader
Definition: Fragment.hh:139
std::size_t sizeBytes() const
Size of vals_ vector ( header + (optional) metadata + payload) in bytes.
Definition: Fragment.hh:360
byte_t * dataBeginBytes()
Return Fragment::byte_t* pointing at the beginning of the payload.
Definition: Fragment.hh:551
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
void resizeBytes(std::size_t szbytes)
Resize the data payload to hold szbytes bytes (padded by the 8-byte RawDataTypes, so...
Definition: Fragment.hh:1015
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...
Definition: Fragment.hh:702
RawDataType timestamp
The 64-bit timestamp field is the output of a user-defined clock used for building time-correlated ev...
RawDataType sequence_id
The 48-bit sequence_id uniquely identifies events within the artdaq system.
sequence_id_t sequenceID() const
Sequence ID of the Fragment, from the Fragment header.
Definition: Fragment.hh:851
timestamp_t timestamp() const
Timestamp of the Fragment, from the Fragment header.
Definition: Fragment.hh:863
static constexpr type_t DataFragmentType
Copy DataFragmentType from RawFragmentHeader.
Definition: Fragment.hh:149
QuickVec< RawDataType >::const_iterator const_iterator
Alias const_iterator type from QuickVec&lt;RawDataType&gt;
Definition: Fragment.hh:184
uint8_t byte_t
For byte representation.
Definition: Fragment.hh:100
void resize(std::size_t sz)
Resize the data payload to hold sz RawDataType words.
Definition: Fragment.hh:998
RawDataType version
The version of the fragment.
void autoResize()
Resize the fragment to hold the number of words indicated by the header.
Definition: Fragment.hh:1049
static constexpr type_t EndOfRunFragmentType
Copy EndOfRunFragmentType from RawFragmentHeader.
Definition: Fragment.hh:151
static constexpr fragment_id_t InvalidFragmentID
Copy InvalidFragmentID from RawFragmentHeader.
Definition: Fragment.hh:144
RawDataType fragment_id
The fragment_id uniquely identifies a particular piece of hardware within the artdaq system...
size_t size() const
Accesses the current size of the QuickVec.
Definition: QuickVec.hh:387
static constexpr type_t InitFragmentType
Copy InitFragmentType from RawFragmentHeader.
Definition: Fragment.hh:150
QuickVec< RawDataType >::reference reference
Alias reference type from QuickVec&lt;RawDataType&gt;
Definition: Fragment.hh:182
byte_t * headerBeginBytes()
Return a Fragment::byte_t pointer pointing to the beginning of the header.
Definition: Fragment.hh:574
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...
Definition: Fragment.hh:237
static constexpr type_t ErrorFragmentType
Copy ErrorFragmentType from RawFragmentHeader.
Definition: Fragment.hh:157
void touch()
Update the atime fields of the RawFragmentHeader to current time.
struct timespec getLatency(bool touch)
Get the difference between the current time and the last access time of the Fragment.
Definition: Fragment.hh:909
detail::RawFragmentHeader::version_t version_t
typedef for version_t from RawFragmentHeader
Definition: Fragment.hh:136
void setTimestamp(timestamp_t timestamp)
Sets the Timestamp of the Fragment.
Definition: Fragment.hh:894
iterator headerBegin()
Return an iterator to the beginning of the header (should be used for serialization only: use setters...
Definition: Fragment.hh:1069
T reinterpret_cast_checked(RawDataType *in)
Wrapper around reinterpret_cast.
Definition: Fragment.hh:531
byte_t * dataEndBytes()
Return Fragment::byte_t* pointing at the end of the payload.
Definition: Fragment.hh:561
static constexpr version_t InvalidVersion
Copy InvalidVersion from RawFragmentHeader.
Definition: Fragment.hh:142
iterator dataBegin()
Return an iterator to the beginning of the data payload (after header and metadata) ...
Definition: Fragment.hh:1056
bool empty()
Determines if the Fragment contains no data.
Definition: Fragment.hh:1101
static constexpr sequence_id_t InvalidSequenceID
Copy InvalidSequenceID from RawFragmentHeader.
Definition: Fragment.hh:143
QuickVec< RawDataType >::value_type value_type
Alias value_type type from QuickVec&lt;RawDataType&gt;
Definition: Fragment.hh:185
static FragmentPtr eodFrag(size_t nFragsToExpect)
Creates an EndOfData Fragment.
Definition: Fragment.cc:77
void setUserType(type_t utype)
Sets the type of the Fragment, checking that it is a valid user type.
Definition: Fragment.hh:869
void touch()
Update the access time of the Fragment.
Definition: Fragment.hh:899
static constexpr type_t ContainerFragmentType
Copy ContainerFragmentType from RawFragmentHeader.
Definition: Fragment.hh:156
static std::map< type_t, std::string > MakeSystemTypeMap()
Returns a map of the most commonly-used system types.
Definition: Fragment.hh:177
std::ostream & operator<<(std::ostream &os, Fragment const &f)
Prints the given Fragment to the stream.
Definition: Fragment.hh:1270
void swap(QuickVec &other) noexcept
Exchanges references to two QuickVec objects.
Definition: QuickVec.hh:528
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:962
const byte_t * dataBeginBytes() const
Return const Fragment::byte_t* pointing at the beginning of the payload.
Definition: Fragment.hh:596
type_t type() const
Type of the Fragment, from the Fragment header.
Definition: Fragment.hh:839
RawDataType * dataAddress()
Returns a RawDataType pointer to the beginning of the payload.
Definition: Fragment.hh:1121
void print(std::ostream &os) const
Print out summary information for this Fragment to the given stream.
Definition: Fragment.cc:68
unsigned long long RawDataType
The RawDataType (currently a 64-bit integer) is the basic unit of data representation within artdaq ...
T * metadata()
Return a pointer to the metadata. This throws an exception if the Fragment contains no metadata...
Definition: Fragment.hh:938
iterator dataEnd()
Return an iterator to the end of the data payload.
Definition: Fragment.hh:1063
static FragmentPtr FragmentBytes(std::size_t nbytes)
Create a Fragment using a static factory function rather than a constructor to allow for the function...
Definition: Fragment.hh:202
static constexpr type_t ShutdownFragmentType
Copy ShutdownFragmentType from RawFragmentHeader.
Definition: Fragment.hh:153
static constexpr type_t FirstUserFragmentType
Copy FIRST_USER_TYPE from RawFragmentHeader.
Definition: Fragment.hh:154
std::string typeString() const
Print the type of the Fragment.
Definition: Fragment.hh:845
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:1128
std::list< FragmentPtr > FragmentPtrs
A std::list of FragmentPtrs.
Definition: Fragment.hh:59
Fragment()
Create a Fragment with all header values zeroed.
Definition: Fragment.cc:13
void clear()
Removes all elements from the payload section of the Fragment.
Definition: Fragment.hh:1094
static constexpr bool isSystemFragmentType(type_t fragmentType)
Returns whether the given type is in the range of system types.
Definition: Fragment.hh:761
static const version_t CurrentVersion
The CurrentVersion field should be incremented whenever the RawFragmentHeader changes.
QuickVec< RawDataType >::iterator iterator
Alias iterator type from QuickVec&lt;RawDataType&gt;
Definition: Fragment.hh:183
bool hasMetadata() const
Test whether this Fragment has metadata.
Definition: Fragment.hh:932
QuickVec< RawDataType >::size_type size_type
Alias size_type type from QuickVec&lt;RawDataType&gt;
Definition: Fragment.hh:187
const byte_t * headerBeginBytes() const
Return a const Fragment::byte_t pointer pointing to the beginning of the header.
Definition: Fragment.hh:625
static std::string SystemTypeToString(type_t type)
Print a system type&#39;s string name.
void setFragmentID(fragment_id_t fragment_id)
Sets the Fragment ID of the Fragment.
Definition: Fragment.hh:888
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 swap(Fragment &other) noexcept
Swaps two Fragment objects.
Definition: Fragment.hh:1115
static constexpr type_t EndOfSubrunFragmentType
Copy EndOfSubrunFragmentType from RawFragmentHeader.
Definition: Fragment.hh:152
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...
Definition: Fragment.hh:1022
std::size_t dataSize() const
Return the number of RawDataType words in the data payload. This does not include the number of words...
Definition: Fragment.hh:925
iterator begin()
Gets an iterator to the beginning of the QuickVec.
Definition: QuickVec.hh:393
void swap(QuickVec< RawDataType > &other) noexcept
Swaps two Fragment data vectors.
Definition: Fragment.hh:662
detail::RawFragmentHeader::sequence_id_t sequence_id_t
typedef for sequence_id_t from RawFragmentHeader
Definition: Fragment.hh:138
fragment_id_t fragmentID() const
Fragment ID of the Fragment, from the Fragment header.
Definition: Fragment.hh:857
RawDataType * headerAddress()
Gets the address of the header.
Definition: Fragment.hh:1139
version_t version() const
Version of the Fragment, from the Fragment header.
Definition: Fragment.hh:832