00001 #ifndef artdaq_core_Data_Fragment_hh
00002 #define artdaq_core_Data_Fragment_hh
00003
00004 #include <algorithm>
00005 #include <cassert>
00006 #include <cstddef>
00007 #include <iosfwd>
00008 #include <iterator>
00009 #include <vector>
00010 #include <memory>
00011 #include <map>
00012 #include <stdint.h>
00013 #include <string.h>
00014
00015 #include "artdaq-core/Data/detail/RawFragmentHeader.hh"
00016 #include "artdaq-core/Data/dictionarycontrol.hh"
00017
00018 namespace artdaq {
00019 # include "QuickVec.hh"
00020 # define QUICKVEC_T QuickVec<RawDataType>
00021 # define DO_STDVEC 0
00022 typedef detail::RawFragmentHeader::RawDataType RawDataType;
00023
00024 class Fragment;
00025 bool fragmentSequenceIDCompare(Fragment i, Fragment j);
00026
00027 std::ostream & operator<<(std::ostream & os, Fragment const & f);
00028 }
00029
00030 class artdaq::Fragment {
00031 public:
00032
00033 Fragment();
00034
00035
00036
00037
00038
00039 typedef uint8_t byte_t;
00040
00041
00042 #if HIDE_FROM_ROOT
00043 typedef detail::RawFragmentHeader::version_t version_t;
00044 typedef detail::RawFragmentHeader::type_t type_t;
00045 typedef detail::RawFragmentHeader::sequence_id_t sequence_id_t;
00046 typedef detail::RawFragmentHeader::fragment_id_t fragment_id_t;
00047 typedef detail::RawFragmentHeader::timestamp_t timestamp_t;
00048
00049 static constexpr version_t InvalidVersion =
00050 detail::RawFragmentHeader::InvalidVersion;
00051 static constexpr sequence_id_t InvalidSequenceID =
00052 detail::RawFragmentHeader::InvalidSequenceID;
00053 static constexpr fragment_id_t InvalidFragmentID =
00054 detail::RawFragmentHeader::InvalidFragmentID;
00055 static constexpr timestamp_t InvalidTimestamp =
00056 detail::RawFragmentHeader::InvalidTimestamp;
00057
00058 static constexpr type_t InvalidFragmentType =
00059 detail::RawFragmentHeader::InvalidFragmentType;
00060 static constexpr type_t EndOfDataFragmentType =
00061 detail::RawFragmentHeader::EndOfDataFragmentType;
00062 static constexpr type_t DataFragmentType =
00063 detail::RawFragmentHeader::DataFragmentType;
00064 static constexpr type_t InitFragmentType =
00065 detail::RawFragmentHeader::InitFragmentType;
00066 static constexpr type_t EndOfRunFragmentType =
00067 detail::RawFragmentHeader::EndOfRunFragmentType;
00068 static constexpr type_t EndOfSubrunFragmentType =
00069 detail::RawFragmentHeader::EndOfSubrunFragmentType;
00070 static constexpr type_t ShutdownFragmentType =
00071 detail::RawFragmentHeader::ShutdownFragmentType;
00072 static constexpr type_t FirstUserFragmentType =
00073 detail::RawFragmentHeader::FIRST_USER_TYPE;
00074 static constexpr type_t EmptyFragmentType =
00075 detail::RawFragmentHeader::EmptyFragmentType;
00076 static constexpr type_t ContainerFragmentType =
00077 detail::RawFragmentHeader::ContainerFragmentType;
00078
00079 static constexpr bool isUserFragmentType(type_t fragmentType);
00080 static constexpr bool isSystemFragmentType(type_t fragmentType);
00081 static std::map<type_t, std::string> MakeSystemTypeMap()
00082 {
00083 return detail::RawFragmentHeader::MakeSystemTypeMap();
00084 }
00085
00086 #if DO_STDVEC == 1
00087 typedef std::vector<RawDataType>::reference reference;
00088 typedef std::vector<RawDataType>::iterator iterator;
00089 typedef std::vector<RawDataType>::const_iterator const_iterator;
00090 typedef std::vector<RawDataType>::value_type value_type;
00091 typedef std::vector<RawDataType>::difference_type difference_type;
00092 typedef std::vector<RawDataType>::size_type size_type;
00093 #else
00094 typedef QUICKVEC_T::reference reference;
00095 typedef QUICKVEC_T::iterator iterator;
00096 typedef QUICKVEC_T::const_iterator const_iterator;
00097 typedef QUICKVEC_T::value_type value_type;
00098 typedef QUICKVEC_T::difference_type difference_type;
00099 typedef QUICKVEC_T::size_type size_type;
00100 #endif
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
00292 RawDataType * dataAddress();
00293 RawDataType * metadataAddress();
00294 RawDataType * headerAddress();
00295
00296 static std::unique_ptr<Fragment> eodFrag(size_t nFragsToExpect);
00297
00298
00299 template <class InputIterator>
00300 static
00301 Fragment
00302 dataFrag(sequence_id_t sequenceID,
00303 fragment_id_t fragID,
00304 InputIterator i,
00305 InputIterator e);
00306
00307 static
00308 Fragment
00309 dataFrag(sequence_id_t sequenceID,
00310 fragment_id_t fragID,
00311 RawDataType const * dataPtr,
00312 size_t dataSize,
00313 timestamp_t timestamp = Fragment::InvalidTimestamp);
00314 #endif
00315
00316 private:
00317 template <typename T> static std::size_t validatedMetadataSize_();
00318 void updateFragmentHeaderWC_();
00319 #if DO_STDVEC == 1
00320 std::vector<RawDataType> vals_;
00321 #else
00322 QUICKVEC_T vals_;
00323 #endif
00324
00325 #if HIDE_FROM_ROOT
00326 detail::RawFragmentHeader * fragmentHeader();
00327 detail::RawFragmentHeader const * fragmentHeader() const;
00328 #endif
00329 };
00330
00331 #if HIDE_FROM_ROOT
00332 inline
00333 bool
00334 constexpr
00335 artdaq::Fragment::
00336 isUserFragmentType(type_t fragmentType)
00337 {
00338 return fragmentType >= detail::RawFragmentHeader::FIRST_USER_TYPE &&
00339 fragmentType <= detail::RawFragmentHeader::LAST_USER_TYPE;
00340 }
00341
00342 inline
00343 bool
00344 constexpr
00345 artdaq::Fragment::
00346 isSystemFragmentType(type_t fragmentType)
00347 {
00348 return fragmentType >= detail::RawFragmentHeader::FIRST_SYSTEM_TYPE;
00349 }
00350
00351 template<typename T>
00352 std::size_t
00353 artdaq::Fragment::
00354 validatedMetadataSize_()
00355 {
00356
00357
00358
00359 static_assert(sizeof(size_t) >=
00360 sizeof(decltype(std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max())),
00361 "metadata_word_count_t is too big!");
00362
00363 static size_t constexpr max_md_wc =
00364 std::numeric_limits<detail::RawFragmentHeader::metadata_word_count_t>::max();
00365 size_t requested_md_wc =
00366 std::ceil(sizeof(T) / static_cast<double>(sizeof(artdaq::RawDataType)));
00367 if (requested_md_wc > max_md_wc) {
00368 throw cet::exception("InvalidRequest")
00369 << "The requested metadata structure is too large: "
00370 << "requested word count = " << requested_md_wc
00371 << ", maximum word count = " << max_md_wc;
00372 }
00373 return requested_md_wc;
00374 }
00375
00376 template <class T>
00377 artdaq::Fragment::
00378 Fragment(std::size_t payload_size, sequence_id_t sequence_id,
00379 fragment_id_t fragment_id,
00380 type_t type, const T & metadata, timestamp_t timestamp) :
00381 vals_((artdaq::detail::RawFragmentHeader::num_words() +
00382 validatedMetadataSize_<T>() +
00383 payload_size),
00384 0)
00385 {
00386 updateFragmentHeaderWC_();
00387 fragmentHeader()->sequence_id = sequence_id;
00388 fragmentHeader()->fragment_id = fragment_id;
00389 fragmentHeader()->timestamp = timestamp;
00390 fragmentHeader()->type = type;
00391
00392 fragmentHeader()->metadata_word_count =
00393 vals_.size() -
00394 (artdaq::detail::RawFragmentHeader::num_words() + payload_size);
00395
00396 memcpy(metadataAddress(), &metadata, sizeof(T));
00397 }
00398
00399 inline
00400 std::size_t
00401 artdaq::Fragment::size() const
00402 {
00403 return fragmentHeader()->word_count;
00404 }
00405
00406 inline
00407 artdaq::Fragment::version_t
00408 artdaq::Fragment::version() const
00409 {
00410 return fragmentHeader()->version;
00411 }
00412
00413 inline
00414 artdaq::Fragment::type_t
00415 artdaq::Fragment::type() const
00416 {
00417 return static_cast<type_t>(fragmentHeader()->type);
00418 }
00419
00420 inline
00421 artdaq::Fragment::sequence_id_t
00422 artdaq::Fragment::sequenceID() const
00423 {
00424 return fragmentHeader()->sequence_id;
00425 }
00426
00427 inline
00428 artdaq::Fragment::fragment_id_t
00429 artdaq::Fragment::fragmentID() const
00430 {
00431 return fragmentHeader()->fragment_id;
00432 }
00433
00434 inline
00435 artdaq::Fragment::timestamp_t
00436 artdaq::Fragment::timestamp() const
00437 {
00438 return fragmentHeader()->timestamp;
00439 }
00440
00441 inline
00442 void
00443 artdaq::Fragment::setVersion(version_t version)
00444 {
00445 fragmentHeader()->version = version;
00446 }
00447
00448 inline
00449 void
00450 artdaq::Fragment::setUserType(type_t type)
00451 {
00452 fragmentHeader()->setUserType(static_cast<uint8_t>(type));
00453 }
00454
00455 inline
00456 void
00457 artdaq::Fragment::setSystemType(type_t type)
00458 {
00459 fragmentHeader()->setSystemType(static_cast<uint8_t>(type));
00460 }
00461
00462 inline
00463 void
00464 artdaq::Fragment::setSequenceID(sequence_id_t sequence_id)
00465 {
00466 assert(sequence_id <= detail::RawFragmentHeader::InvalidSequenceID);
00467 fragmentHeader()->sequence_id = sequence_id;
00468 }
00469
00470 inline
00471 void
00472 artdaq::Fragment::setFragmentID(fragment_id_t fragment_id)
00473 {
00474 fragmentHeader()->fragment_id = fragment_id;
00475 }
00476
00477 inline
00478 void
00479 artdaq::Fragment::setTimestamp(timestamp_t timestamp)
00480 {
00481 fragmentHeader()->timestamp = timestamp;
00482 }
00483
00484 inline
00485 void
00486 artdaq::Fragment::updateFragmentHeaderWC_()
00487 {
00488
00489
00490 assert(vals_.size() < (1ULL << 32));
00491 fragmentHeader()->word_count = vals_.size();
00492 }
00493
00494 inline
00495 std::size_t
00496 artdaq::Fragment::dataSize() const
00497 {
00498 return vals_.size() - detail::RawFragmentHeader::num_words() -
00499 fragmentHeader()->metadata_word_count;
00500 }
00501
00502 inline
00503 bool
00504 artdaq::Fragment::hasMetadata() const
00505 {
00506 return fragmentHeader()->metadata_word_count != 0;
00507 }
00508
00509 template <class T>
00510 T *
00511 artdaq::Fragment::metadata()
00512 {
00513 if (fragmentHeader()->metadata_word_count == 0) {
00514 throw cet::exception("InvalidRequest")
00515 << "No metadata has been stored in this Fragment.";
00516 }
00517
00518 return reinterpret_cast_checked<T *>
00519 (&vals_[detail::RawFragmentHeader::num_words()]);
00520 }
00521
00522 template <class T>
00523 T const *
00524 artdaq::Fragment::metadata() const
00525 {
00526 if (fragmentHeader()->metadata_word_count == 0) {
00527 throw cet::exception("InvalidRequest")
00528 << "No metadata has been stored in this Fragment.";
00529 }
00530 return reinterpret_cast_checked<T const *>
00531 (&vals_[detail::RawFragmentHeader::num_words()]);
00532 }
00533
00534 template <class T>
00535 void
00536 artdaq::Fragment::setMetadata(const T & metadata)
00537 {
00538 if (fragmentHeader()->metadata_word_count != 0) {
00539 throw cet::exception("InvalidRequest")
00540 << "Metadata has already been stored in this Fragment.";
00541 }
00542 auto const mdSize = validatedMetadataSize_<T>();
00543 vals_.insert(dataBegin(), mdSize, 0);
00544 updateFragmentHeaderWC_();
00545 fragmentHeader()->metadata_word_count = mdSize;
00546
00547 memcpy(metadataAddress(), &metadata, sizeof(T));
00548 }
00549
00550 template <class T>
00551 void
00552 artdaq::Fragment::updateMetadata(const T & metadata)
00553 {
00554 if (fragmentHeader()->metadata_word_count == 0) {
00555 throw cet::exception("InvalidRequest")
00556 << "No metadata in fragment; please use Fragment::setMetadata instead of Fragment::updateMetadata";
00557 }
00558
00559 auto const mdSize = validatedMetadataSize_<T>();
00560
00561 if (fragmentHeader()->metadata_word_count != mdSize) {
00562 throw cet::exception("InvalidRequest")
00563 << "Mismatch between type of metadata struct passed to updateMetadata and existing metadata struct";
00564 }
00565
00566 memcpy(metadataAddress(), &metadata, sizeof(T));
00567 }
00568
00569 inline void
00570 artdaq::Fragment::resize(std::size_t sz)
00571 {
00572 vals_.resize(sz + fragmentHeader()->metadata_word_count +
00573 detail::RawFragmentHeader::num_words());
00574 updateFragmentHeaderWC_();
00575 }
00576 inline
00577 void
00578 artdaq::Fragment::resize(std::size_t sz, RawDataType v)
00579 {
00580 vals_.resize(sz + fragmentHeader()->metadata_word_count +
00581 detail::RawFragmentHeader::num_words(), v);
00582 updateFragmentHeaderWC_();
00583 }
00584
00585 inline void
00586 artdaq::Fragment::resizeBytes(std::size_t szbytes)
00587 {
00588 RawDataType nwords = ceil(szbytes / static_cast<double>(sizeof(RawDataType)));
00589 resize(nwords);
00590 }
00591 inline
00592 void
00593 artdaq::Fragment::resizeBytes(std::size_t szbytes, byte_t v)
00594 {
00595 RawDataType defaultval;
00596 byte_t* ptr = reinterpret_cast_checked<byte_t*>(&defaultval);
00597
00598 for (uint8_t i = 0; i < sizeof(RawDataType); ++i) {
00599 *ptr = v;
00600 ptr++;
00601 }
00602
00603 RawDataType nwords = ceil(szbytes / static_cast<double>(sizeof(RawDataType)));
00604
00605 resize(nwords, defaultval);
00606 }
00607
00608
00609 inline
00610 void
00611 artdaq::Fragment::autoResize()
00612 {
00613 vals_.resize(fragmentHeader()->word_count);
00614 updateFragmentHeaderWC_();
00615 }
00616
00617 inline
00618 artdaq::Fragment::iterator
00619 artdaq::Fragment::dataBegin()
00620 {
00621 return vals_.begin() + detail::RawFragmentHeader::num_words() +
00622 fragmentHeader()->metadata_word_count;
00623 }
00624
00625 inline
00626 artdaq::Fragment::iterator
00627 artdaq::Fragment::dataEnd()
00628 {
00629 return vals_.end();
00630 }
00631
00632 inline
00633 artdaq::Fragment::iterator
00634 artdaq::Fragment::headerBegin()
00635 {
00636 return vals_.begin();
00637 }
00638
00639 inline
00640 artdaq::Fragment::const_iterator
00641 artdaq::Fragment::dataBegin() const
00642 {
00643 return vals_.begin() + detail::RawFragmentHeader::num_words() +
00644 fragmentHeader()->metadata_word_count;
00645 }
00646
00647 inline
00648 artdaq::Fragment::const_iterator
00649 artdaq::Fragment::dataEnd() const
00650 {
00651 return vals_.end();
00652 }
00653
00654 inline
00655 artdaq::Fragment::const_iterator
00656 artdaq::Fragment::headerBegin() const
00657 {
00658 return vals_.begin();
00659 }
00660
00661
00662 inline
00663 void
00664 artdaq::Fragment::clear()
00665 {
00666 vals_.erase(dataBegin(), dataEnd());
00667 updateFragmentHeaderWC_();
00668 }
00669
00670 inline
00671 bool
00672 artdaq::Fragment::empty()
00673 {
00674 return (vals_.size() - detail::RawFragmentHeader::num_words() -
00675 fragmentHeader()->metadata_word_count) == 0;
00676 }
00677
00678 inline
00679 void
00680 artdaq::Fragment::reserve(std::size_t cap)
00681 {
00682 vals_.reserve(cap + detail::RawFragmentHeader::num_words() +
00683 fragmentHeader()->metadata_word_count);
00684 }
00685
00686 inline
00687 void
00688 artdaq::Fragment::swap(Fragment & other)
00689 {
00690 vals_.swap(other.vals_);
00691 }
00692
00693 inline
00694 artdaq::RawDataType *
00695 artdaq::Fragment::dataAddress()
00696 {
00697 return &vals_[0] + detail::RawFragmentHeader::num_words() +
00698 fragmentHeader()->metadata_word_count;
00699 }
00700
00701 inline
00702 artdaq::RawDataType *
00703 artdaq::Fragment::metadataAddress()
00704 {
00705 if (fragmentHeader()->metadata_word_count == 0) {
00706 throw cet::exception("InvalidRequest")
00707 << "No metadata has been stored in this Fragment.";
00708 }
00709 return &vals_[0] + detail::RawFragmentHeader::num_words();
00710 }
00711
00712 inline
00713 artdaq::RawDataType *
00714 artdaq::Fragment::headerAddress()
00715 {
00716 return &vals_[0];
00717 }
00718
00719
00720 template <class InputIterator>
00721 artdaq::Fragment
00722 artdaq::Fragment::
00723 dataFrag(sequence_id_t sequenceID,
00724 fragment_id_t fragID,
00725 InputIterator i,
00726 InputIterator e)
00727 {
00728 Fragment result(sequenceID, fragID);
00729 result.vals_.reserve(std::distance(i, e) + detail::RawFragmentHeader::num_words());
00730 std::copy(i, e, std::back_inserter(result.vals_));
00731 return result;
00732 }
00733
00734 inline
00735 artdaq::detail::RawFragmentHeader *
00736 artdaq::Fragment::fragmentHeader()
00737 {
00738 return reinterpret_cast_checked<detail::RawFragmentHeader *>(&vals_[0]);
00739 }
00740
00741 inline
00742 artdaq::detail::RawFragmentHeader const *
00743 artdaq::Fragment::fragmentHeader() const
00744 {
00745 return reinterpret_cast_checked<detail::RawFragmentHeader const *>(&vals_[0]);
00746 }
00747
00748 inline
00749 void
00750 swap(artdaq::Fragment & x, artdaq::Fragment & y)
00751 {
00752 x.swap(y);
00753 }
00754
00755 inline
00756 std::ostream &
00757 artdaq::operator<<(std::ostream & os, artdaq::Fragment const & f)
00758 {
00759 f.print(os);
00760 return os;
00761 }
00762 #endif
00763
00764 #endif
00765