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