00001 #ifndef artdaq_core_Data_Fragment_hh
00002 #define artdaq_core_Data_Fragment_hh
00003
00004 #include <algorithm>
00005
00006 #include <cstddef>
00007 #include <iosfwd>
00008 #include <iterator>
00009 #include <vector>
00010 #include <memory>
00011 #include <map>
00012 #include <cmath>
00013 #include <stdint.h>
00014 #include <string.h>
00015
00016 #include "artdaq-core/Data/detail/RawFragmentHeader.hh"
00017 #include "artdaq-core/Data/dictionarycontrol.hh"
00018
00019 namespace artdaq {
00020 # include "QuickVec.hh"
00021 # define DATAVEC_T QuickVec<RawDataType>
00022
00023 typedef detail::RawFragmentHeader::RawDataType RawDataType;
00024
00025 class Fragment;
00026 bool fragmentSequenceIDCompare(Fragment i, Fragment j);
00027
00028 std::ostream & operator<<(std::ostream & os, Fragment const & f);
00029 }
00030
00031 class artdaq::Fragment {
00032 public:
00033
00034 Fragment();
00035
00036
00037
00038
00039
00040 typedef uint8_t byte_t;
00041
00042
00043 #if HIDE_FROM_ROOT
00044
00045
00046
00047 Fragment(const Fragment&) = default;
00048 Fragment(Fragment&&) noexcept;
00049 Fragment& operator=(const Fragment&) = default;
00050 Fragment& operator=(Fragment&&) noexcept;
00051
00052 typedef detail::RawFragmentHeader::version_t version_t;
00053 typedef detail::RawFragmentHeader::type_t type_t;
00054 typedef detail::RawFragmentHeader::sequence_id_t sequence_id_t;
00055 typedef detail::RawFragmentHeader::fragment_id_t fragment_id_t;
00056 typedef detail::RawFragmentHeader::timestamp_t timestamp_t;
00057
00058 static constexpr version_t InvalidVersion =
00059 detail::RawFragmentHeader::InvalidVersion;
00060 static constexpr sequence_id_t InvalidSequenceID =
00061 detail::RawFragmentHeader::InvalidSequenceID;
00062 static constexpr fragment_id_t InvalidFragmentID =
00063 detail::RawFragmentHeader::InvalidFragmentID;
00064 static constexpr timestamp_t InvalidTimestamp =
00065 detail::RawFragmentHeader::InvalidTimestamp;
00066
00067 static constexpr type_t InvalidFragmentType =
00068 detail::RawFragmentHeader::InvalidFragmentType;
00069 static constexpr type_t EndOfDataFragmentType =
00070 detail::RawFragmentHeader::EndOfDataFragmentType;
00071 static constexpr type_t DataFragmentType =
00072 detail::RawFragmentHeader::DataFragmentType;
00073 static constexpr type_t InitFragmentType =
00074 detail::RawFragmentHeader::InitFragmentType;
00075 static constexpr type_t EndOfRunFragmentType =
00076 detail::RawFragmentHeader::EndOfRunFragmentType;
00077 static constexpr type_t EndOfSubrunFragmentType =
00078 detail::RawFragmentHeader::EndOfSubrunFragmentType;
00079 static constexpr type_t ShutdownFragmentType =
00080 detail::RawFragmentHeader::ShutdownFragmentType;
00081 static constexpr type_t FirstUserFragmentType =
00082 detail::RawFragmentHeader::FIRST_USER_TYPE;
00083 static constexpr type_t EmptyFragmentType =
00084 detail::RawFragmentHeader::EmptyFragmentType;
00085 static constexpr type_t ContainerFragmentType =
00086 detail::RawFragmentHeader::ContainerFragmentType;
00087
00088 static constexpr bool isUserFragmentType(type_t fragmentType);
00089 static constexpr bool isSystemFragmentType(type_t fragmentType);
00090 static std::map<type_t, std::string> MakeSystemTypeMap()
00091 {
00092 return detail::RawFragmentHeader::MakeSystemTypeMap();
00093 }
00094
00095 typedef DATAVEC_T::reference reference;
00096 typedef DATAVEC_T::iterator iterator;
00097 typedef DATAVEC_T::const_iterator const_iterator;
00098 typedef DATAVEC_T::value_type value_type;
00099 typedef DATAVEC_T::difference_type difference_type;
00100 typedef DATAVEC_T::size_type size_type;
00101
00102
00103
00104 explicit Fragment(std::size_t n);
00105
00106
00107
00108
00109
00110 static std::unique_ptr<Fragment> FragmentBytes(std::size_t nbytes) {
00111 RawDataType nwords = ceil(nbytes / static_cast<double>(sizeof(RawDataType)));
00112 return std::unique_ptr<Fragment>(new Fragment(nwords));
00113 }
00114
00115
00116
00117
00118 template <class T>
00119 Fragment(std::size_t payload_size, sequence_id_t sequence_id,
00120 fragment_id_t fragment_id, type_t type, const T & metadata,
00121 timestamp_t timestamp = Fragment::InvalidTimestamp);
00122
00123
00124
00125
00126
00127 template <class T>
00128 static std::unique_ptr<Fragment> FragmentBytes(std::size_t payload_size_in_bytes,
00129 sequence_id_t sequence_id,
00130 fragment_id_t fragment_id,
00131 type_t type, const T & metadata,
00132 timestamp_t timestamp = Fragment::InvalidTimestamp) {
00133 RawDataType nwords = ceil(payload_size_in_bytes /
00134 static_cast<double>(sizeof(RawDataType)));
00135 return std::unique_ptr<Fragment>(new Fragment(nwords, sequence_id, fragment_id, type, metadata, timestamp));
00136 }
00137
00138
00139
00140 Fragment(sequence_id_t sequenceID,
00141 fragment_id_t fragID,
00142 type_t type = Fragment::DataFragmentType,
00143 timestamp_t timestamp = Fragment::InvalidTimestamp);
00144
00145
00146 void print(std::ostream & os) const;
00147
00148
00149 std::size_t size() const;
00150 version_t version() const;
00151 type_t type() const;
00152 sequence_id_t sequenceID() const;
00153 fragment_id_t fragmentID() const;
00154 timestamp_t timestamp() const;
00155
00156
00157 void setVersion(version_t version);
00158 void setUserType(type_t type);
00159 void setSystemType(type_t type);
00160 void setSequenceID(sequence_id_t sequence_id);
00161 void setFragmentID(fragment_id_t fragment_id);
00162 void setTimestamp(timestamp_t timestamp);
00163
00164
00165 std::size_t sizeBytes() const { return sizeof(RawDataType) * size(); }
00166
00167
00168
00169 std::size_t dataSize() const;
00170
00171
00172 std::size_t dataSizeBytes() const {
00173 return sizeof(RawDataType) * dataSize();
00174 }
00175
00176
00177 bool hasMetadata() const;
00178
00179
00180
00181 template <class T> T * metadata();
00182 template <class T> T const * metadata() const;
00183
00184
00185
00186
00187 template <class T> void setMetadata(const T & md);
00188
00189
00190 template <class T> void updateMetadata(const T & md);
00191
00192
00193 void resize(std::size_t sz);
00194 void resize(std::size_t sz, RawDataType v);
00195
00196
00197
00198
00199
00200 void resizeBytes(std::size_t szbytes);
00201 void resizeBytes(std::size_t szbytes, byte_t v);
00202
00203
00204 void autoResize();
00205
00206
00207 iterator dataBegin();
00208
00209 iterator dataEnd();
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 template <typename T>
00229 T reinterpret_cast_checked(const RawDataType* in) const {
00230 T newpointer = reinterpret_cast<T>(in);
00231
00232 if (static_cast<const void*>(newpointer) != static_cast<const void*>(in)) {
00233 throw cet::exception("Error in Fragment.hh: reinterpret_cast failed to return expected address-- please contact John Freeman at jcfree@fnal.gov");
00234 }
00235
00236 return newpointer;
00237 }
00238
00239
00240 template <typename T>
00241 T reinterpret_cast_checked(RawDataType* in) {
00242 T newpointer = reinterpret_cast<T>(in);
00243
00244 if (static_cast<void*>(newpointer) != static_cast<void*>(in)) {
00245 throw cet::exception("Error in Fragment.hh: reinterpret_cast failed to return expected address-- please contact John Freeman at jcfree@fnal.gov");
00246 }
00247
00248 return newpointer;
00249 }
00250
00251
00252
00253
00254
00255
00256
00257 byte_t* dataBeginBytes() { return reinterpret_cast_checked<byte_t*>(&* dataBegin()); }
00258 byte_t* dataEndBytes() { return reinterpret_cast_checked<byte_t*>(&* dataEnd()); }
00259
00260
00261
00262 iterator headerBegin();
00263
00264
00265 byte_t* headerBeginBytes() { return reinterpret_cast_checked<byte_t*>(&* headerBegin()); }
00266
00267
00268 const_iterator dataBegin() const;
00269 const_iterator dataEnd() const;
00270
00271 const byte_t* dataBeginBytes() const {
00272 return reinterpret_cast_checked<const byte_t*>(&* dataBegin());
00273 }
00274
00275 const byte_t* dataEndBytes() const {
00276 return reinterpret_cast_checked<const byte_t*>(&* dataEnd());
00277 }
00278
00279
00280 const_iterator headerBegin() const;
00281
00282 const byte_t* headerBeginBytes() const {
00283 return reinterpret_cast_checked<const byte_t*>(&* headerBegin());
00284 }
00285
00286
00287 void clear();
00288 bool empty();
00289 void reserve(std::size_t cap);
00290 void swap(Fragment & other);
00291 void swap(DATAVEC_T & other) { vals_.swap(other); };
00292
00293 RawDataType * dataAddress();
00294 RawDataType * metadataAddress();
00295 RawDataType * headerAddress();
00296
00297 static std::unique_ptr<Fragment> eodFrag(size_t nFragsToExpect);
00298
00299
00300 template <class InputIterator>
00301 static
00302 Fragment
00303 dataFrag(sequence_id_t sequenceID,
00304 fragment_id_t fragID,
00305 InputIterator i,
00306 InputIterator e);
00307
00308 static
00309 Fragment
00310 dataFrag(sequence_id_t sequenceID,
00311 fragment_id_t fragID,
00312 RawDataType const * dataPtr,
00313 size_t dataSize,
00314 timestamp_t timestamp = Fragment::InvalidTimestamp);
00315 #endif
00316
00317 private:
00318 template <typename T> static std::size_t validatedMetadataSize_();
00319 void updateFragmentHeaderWC_();
00320
00321 DATAVEC_T vals_;
00322
00323 #if HIDE_FROM_ROOT
00324 detail::RawFragmentHeader * fragmentHeader();
00325 detail::RawFragmentHeader const * fragmentHeader() const;
00326 #endif
00327 };
00328
00329 #if HIDE_FROM_ROOT
00330
00331
00332
00333
00334 inline artdaq::Fragment::Fragment(artdaq::Fragment&&) noexcept = default;
00335 inline artdaq::Fragment& artdaq::Fragment::operator=(artdaq::Fragment&&) noexcept = default;
00336
00337 inline
00338 bool
00339 constexpr
00340 artdaq::Fragment::
00341 isUserFragmentType(type_t fragmentType)
00342 {
00343 return fragmentType >= detail::RawFragmentHeader::FIRST_USER_TYPE &&
00344 fragmentType <= detail::RawFragmentHeader::LAST_USER_TYPE;
00345 }
00346
00347 inline
00348 bool
00349 constexpr
00350 artdaq::Fragment::
00351 isSystemFragmentType(type_t fragmentType)
00352 {
00353 return fragmentType >= detail::RawFragmentHeader::FIRST_SYSTEM_TYPE;
00354 }
00355
00356 template<typename T>
00357 std::size_t
00358 artdaq::Fragment::
00359 validatedMetadataSize_()
00360 {
00361
00362
00363
00364 static_assert(sizeof(size_t) >=
00365 sizeof(decltype(std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max())),
00366 "metadata_word_count_t is too big!");
00367
00368 static size_t constexpr max_md_wc =
00369 std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max();
00370 size_t requested_md_wc =
00371 std::ceil(sizeof(T) / static_cast<double>(sizeof(artdaq::RawDataType)));
00372 if (requested_md_wc > max_md_wc) {
00373 throw cet::exception("InvalidRequest")
00374 << "The requested metadata structure is too large: "
00375 << "requested word count = " << requested_md_wc
00376 << ", maximum word count = " << max_md_wc;
00377 }
00378 return requested_md_wc;
00379 }
00380
00381 template <class T>
00382 artdaq::Fragment::
00383 Fragment(std::size_t payload_size, sequence_id_t sequence_id,
00384 fragment_id_t fragment_id,
00385 type_t type, const T & metadata, timestamp_t timestamp) :
00386 vals_((artdaq::detail::RawFragmentHeader::num_words() +
00387 validatedMetadataSize_<T>() +
00388 payload_size),
00389 0)
00390 {
00391 updateFragmentHeaderWC_();
00392 fragmentHeader()->sequence_id = sequence_id;
00393 fragmentHeader()->fragment_id = fragment_id;
00394 fragmentHeader()->timestamp = timestamp;
00395 fragmentHeader()->type = type;
00396
00397 fragmentHeader()->metadata_word_count =
00398 vals_.size() -
00399 (artdaq::detail::RawFragmentHeader::num_words() + payload_size);
00400
00401 memcpy(metadataAddress(), &metadata, sizeof(T));
00402 }
00403
00404 inline
00405 std::size_t
00406 artdaq::Fragment::size() const
00407 {
00408 return fragmentHeader()->word_count;
00409 }
00410
00411 inline
00412 artdaq::Fragment::version_t
00413 artdaq::Fragment::version() const
00414 {
00415 return fragmentHeader()->version;
00416 }
00417
00418 inline
00419 artdaq::Fragment::type_t
00420 artdaq::Fragment::type() const
00421 {
00422 return static_cast<type_t>(fragmentHeader()->type);
00423 }
00424
00425 inline
00426 artdaq::Fragment::sequence_id_t
00427 artdaq::Fragment::sequenceID() const
00428 {
00429 return fragmentHeader()->sequence_id;
00430 }
00431
00432 inline
00433 artdaq::Fragment::fragment_id_t
00434 artdaq::Fragment::fragmentID() const
00435 {
00436 return fragmentHeader()->fragment_id;
00437 }
00438
00439 inline
00440 artdaq::Fragment::timestamp_t
00441 artdaq::Fragment::timestamp() const
00442 {
00443 return fragmentHeader()->timestamp;
00444 }
00445
00446 inline
00447 void
00448 artdaq::Fragment::setVersion(version_t version)
00449 {
00450 fragmentHeader()->version = version;
00451 }
00452
00453 inline
00454 void
00455 artdaq::Fragment::setUserType(type_t type)
00456 {
00457 fragmentHeader()->setUserType(static_cast<uint8_t>(type));
00458 }
00459
00460 inline
00461 void
00462 artdaq::Fragment::setSystemType(type_t type)
00463 {
00464 fragmentHeader()->setSystemType(static_cast<uint8_t>(type));
00465 }
00466
00467 inline
00468 void
00469 artdaq::Fragment::setSequenceID(sequence_id_t sequence_id)
00470 {
00471 assert(sequence_id <= detail::RawFragmentHeader::InvalidSequenceID);
00472 fragmentHeader()->sequence_id = sequence_id;
00473 }
00474
00475 inline
00476 void
00477 artdaq::Fragment::setFragmentID(fragment_id_t fragment_id)
00478 {
00479 fragmentHeader()->fragment_id = fragment_id;
00480 }
00481
00482 inline
00483 void
00484 artdaq::Fragment::setTimestamp(timestamp_t timestamp)
00485 {
00486 fragmentHeader()->timestamp = timestamp;
00487 }
00488
00489 inline
00490 void
00491 artdaq::Fragment::updateFragmentHeaderWC_()
00492 {
00493
00494
00495 assert(vals_.size() < (1ULL << 32));
00496 fragmentHeader()->word_count = vals_.size();
00497 }
00498
00499 inline
00500 std::size_t
00501 artdaq::Fragment::dataSize() const
00502 {
00503 return vals_.size() - detail::RawFragmentHeader::num_words() -
00504 fragmentHeader()->metadata_word_count;
00505 }
00506
00507 inline
00508 bool
00509 artdaq::Fragment::hasMetadata() const
00510 {
00511 return fragmentHeader()->metadata_word_count != 0;
00512 }
00513
00514 template <class T>
00515 T *
00516 artdaq::Fragment::metadata()
00517 {
00518 if (fragmentHeader()->metadata_word_count == 0) {
00519 throw cet::exception("InvalidRequest")
00520 << "No metadata has been stored in this Fragment.";
00521 }
00522
00523 return reinterpret_cast_checked<T *>
00524 (&vals_[detail::RawFragmentHeader::num_words()]);
00525 }
00526
00527 template <class T>
00528 T const *
00529 artdaq::Fragment::metadata() const
00530 {
00531 if (fragmentHeader()->metadata_word_count == 0) {
00532 throw cet::exception("InvalidRequest")
00533 << "No metadata has been stored in this Fragment.";
00534 }
00535 return reinterpret_cast_checked<T const *>
00536 (&vals_[detail::RawFragmentHeader::num_words()]);
00537 }
00538
00539 template <class T>
00540 void
00541 artdaq::Fragment::setMetadata(const T & metadata)
00542 {
00543 if (fragmentHeader()->metadata_word_count != 0) {
00544 throw cet::exception("InvalidRequest")
00545 << "Metadata has already been stored in this Fragment.";
00546 }
00547 auto const mdSize = validatedMetadataSize_<T>();
00548 vals_.insert(dataBegin(), mdSize, 0);
00549 updateFragmentHeaderWC_();
00550 fragmentHeader()->metadata_word_count = mdSize;
00551
00552 memcpy(metadataAddress(), &metadata, sizeof(T));
00553 }
00554
00555 template <class T>
00556 void
00557 artdaq::Fragment::updateMetadata(const T & metadata)
00558 {
00559 if (fragmentHeader()->metadata_word_count == 0) {
00560 throw cet::exception("InvalidRequest")
00561 << "No metadata in fragment; please use Fragment::setMetadata instead of Fragment::updateMetadata";
00562 }
00563
00564 auto const mdSize = validatedMetadataSize_<T>();
00565
00566 if (fragmentHeader()->metadata_word_count != mdSize) {
00567 throw cet::exception("InvalidRequest")
00568 << "Mismatch between type of metadata struct passed to updateMetadata and existing metadata struct";
00569 }
00570
00571 memcpy(metadataAddress(), &metadata, sizeof(T));
00572 }
00573
00574 inline void
00575 artdaq::Fragment::resize(std::size_t sz)
00576 {
00577 vals_.resize(sz + fragmentHeader()->metadata_word_count +
00578 detail::RawFragmentHeader::num_words());
00579 updateFragmentHeaderWC_();
00580 }
00581 inline
00582 void
00583 artdaq::Fragment::resize(std::size_t sz, RawDataType v)
00584 {
00585 vals_.resize(sz + fragmentHeader()->metadata_word_count +
00586 detail::RawFragmentHeader::num_words(), v);
00587 updateFragmentHeaderWC_();
00588 }
00589
00590 inline void
00591 artdaq::Fragment::resizeBytes(std::size_t szbytes)
00592 {
00593 RawDataType nwords = ceil(szbytes / static_cast<double>(sizeof(RawDataType)));
00594 resize(nwords);
00595 }
00596 inline
00597 void
00598 artdaq::Fragment::resizeBytes(std::size_t szbytes, byte_t v)
00599 {
00600 RawDataType defaultval;
00601 byte_t* ptr = reinterpret_cast_checked<byte_t*>(&defaultval);
00602
00603 for (uint8_t i = 0; i < sizeof(RawDataType); ++i) {
00604 *ptr = v;
00605 ptr++;
00606 }
00607
00608 RawDataType nwords = ceil(szbytes / static_cast<double>(sizeof(RawDataType)));
00609
00610 resize(nwords, defaultval);
00611 }
00612
00613
00614 inline
00615 void
00616 artdaq::Fragment::autoResize()
00617 {
00618 vals_.resize(fragmentHeader()->word_count);
00619 updateFragmentHeaderWC_();
00620 }
00621
00622 inline
00623 artdaq::Fragment::iterator
00624 artdaq::Fragment::dataBegin()
00625 {
00626 return vals_.begin() + detail::RawFragmentHeader::num_words() +
00627 fragmentHeader()->metadata_word_count;
00628 }
00629
00630 inline
00631 artdaq::Fragment::iterator
00632 artdaq::Fragment::dataEnd()
00633 {
00634 return vals_.end();
00635 }
00636
00637 inline
00638 artdaq::Fragment::iterator
00639 artdaq::Fragment::headerBegin()
00640 {
00641 return vals_.begin();
00642 }
00643
00644 inline
00645 artdaq::Fragment::const_iterator
00646 artdaq::Fragment::dataBegin() const
00647 {
00648 return vals_.begin() + detail::RawFragmentHeader::num_words() +
00649 fragmentHeader()->metadata_word_count;
00650 }
00651
00652 inline
00653 artdaq::Fragment::const_iterator
00654 artdaq::Fragment::dataEnd() const
00655 {
00656 return vals_.end();
00657 }
00658
00659 inline
00660 artdaq::Fragment::const_iterator
00661 artdaq::Fragment::headerBegin() const
00662 {
00663 return vals_.begin();
00664 }
00665
00666
00667 inline
00668 void
00669 artdaq::Fragment::clear()
00670 {
00671 vals_.erase(dataBegin(), dataEnd());
00672 updateFragmentHeaderWC_();
00673 }
00674
00675 inline
00676 bool
00677 artdaq::Fragment::empty()
00678 {
00679 return (vals_.size() - detail::RawFragmentHeader::num_words() -
00680 fragmentHeader()->metadata_word_count) == 0;
00681 }
00682
00683 inline
00684 void
00685 artdaq::Fragment::reserve(std::size_t cap)
00686 {
00687 vals_.reserve(cap + detail::RawFragmentHeader::num_words() +
00688 fragmentHeader()->metadata_word_count);
00689 }
00690
00691 inline
00692 void
00693 artdaq::Fragment::swap(Fragment & other)
00694 {
00695 vals_.swap(other.vals_);
00696 }
00697
00698 inline
00699 artdaq::RawDataType *
00700 artdaq::Fragment::dataAddress()
00701 {
00702 return &vals_[0] + detail::RawFragmentHeader::num_words() +
00703 fragmentHeader()->metadata_word_count;
00704 }
00705
00706 inline
00707 artdaq::RawDataType *
00708 artdaq::Fragment::metadataAddress()
00709 {
00710 if (fragmentHeader()->metadata_word_count == 0) {
00711 throw cet::exception("InvalidRequest")
00712 << "No metadata has been stored in this Fragment.";
00713 }
00714 return &vals_[0] + detail::RawFragmentHeader::num_words();
00715 }
00716
00717 inline
00718 artdaq::RawDataType *
00719 artdaq::Fragment::headerAddress()
00720 {
00721 return &vals_[0];
00722 }
00723
00724
00725 template <class InputIterator>
00726 artdaq::Fragment
00727 artdaq::Fragment::
00728 dataFrag(sequence_id_t sequenceID,
00729 fragment_id_t fragID,
00730 InputIterator i,
00731 InputIterator e)
00732 {
00733 Fragment result(sequenceID, fragID);
00734 result.vals_.reserve(std::distance(i, e) + detail::RawFragmentHeader::num_words());
00735 std::copy(i, e, std::back_inserter(result.vals_));
00736 return result;
00737 }
00738
00739 inline
00740 artdaq::detail::RawFragmentHeader *
00741 artdaq::Fragment::fragmentHeader()
00742 {
00743 return reinterpret_cast_checked<detail::RawFragmentHeader *>(&vals_[0]);
00744 }
00745
00746 inline
00747 artdaq::detail::RawFragmentHeader const *
00748 artdaq::Fragment::fragmentHeader() const
00749 {
00750 return reinterpret_cast_checked<detail::RawFragmentHeader const *>(&vals_[0]);
00751 }
00752
00753 inline
00754 void
00755 swap(artdaq::Fragment & x, artdaq::Fragment & y)
00756 {
00757 x.swap(y);
00758 }
00759
00760 inline
00761 std::ostream &
00762 artdaq::operator<<(std::ostream & os, artdaq::Fragment const & f)
00763 {
00764 f.print(os);
00765 return os;
00766 }
00767 #endif
00768
00769 #endif
00770