$treeview $search $mathjax $extrastylesheet
artdaq_core
v3_06_01
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #ifndef artdaq_core_Data_ContainerFragmentLoader_hh 00002 #define artdaq_core_Data_ContainerFragmentLoader_hh 00003 00005 // ContainerFragmentLoader 00006 // 00007 // This class gives write access to a ContainerFragment. It should be 00008 // used when multiple fragments are generated by one BoardReader for a 00009 // single event. 00010 // 00012 00013 #include "artdaq-core/Data/ContainerFragment.hh" 00014 #include "artdaq-core/Data/Fragment.hh" 00015 00016 #include "tracemf.h" 00017 00018 #include <iostream> 00019 00020 namespace artdaq { 00021 class ContainerFragmentLoader; 00022 } 00023 00027 class artdaq::ContainerFragmentLoader : public artdaq::ContainerFragment 00028 { 00029 public: 00036 explicit ContainerFragmentLoader(Fragment& f, Fragment::type_t expectedFragmentType); 00037 00038 // ReSharper disable once CppMemberFunctionMayBeConst 00043 Metadata* metadata() 00044 { 00045 assert(artdaq_Fragment_.hasMetadata()); 00046 return reinterpret_cast<Metadata*>(&*artdaq_Fragment_.metadataAddress()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) 00047 } 00048 00053 void set_fragment_type(Fragment::type_t type) 00054 { 00055 metadata()->fragment_type = type; 00056 } 00057 00066 void set_missing_data(bool isDataMissing) 00067 { 00068 metadata()->missing_data = isDataMissing; 00069 } 00070 00076 void addFragment(artdaq::Fragment& frag); 00077 00082 void addFragment(artdaq::FragmentPtr& frag); 00083 00088 void addFragments(artdaq::FragmentPtrs& frags); 00089 00090 private: 00091 // Note that this non-const reference hides the const reference in the base class 00092 artdaq::Fragment& artdaq_Fragment_; 00093 00094 static size_t words_to_frag_words_(size_t nWords); 00095 00096 void addSpace_(size_t bytes); 00097 00098 uint8_t* dataBegin_() { return reinterpret_cast<uint8_t*>(&*artdaq_Fragment_.dataBegin()); } // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) 00099 void* dataEnd_() { return static_cast<void*>(dataBegin_() + lastFragmentIndex()); } // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) 00100 }; 00101 00102 inline artdaq::ContainerFragmentLoader::ContainerFragmentLoader(artdaq::Fragment& f, artdaq::Fragment::type_t expectedFragmentType = Fragment::EmptyFragmentType) 00103 : ContainerFragment(f) 00104 , artdaq_Fragment_(f) 00105 { 00106 artdaq_Fragment_.setSystemType(Fragment::ContainerFragmentType); 00107 Metadata m; 00108 m.block_count = 0; 00109 m.fragment_type = expectedFragmentType; 00110 m.missing_data = false; 00111 m.has_index = true; 00112 m.version = ContainerFragment::CURRENT_VERSION; 00113 m.index_offset = 0; 00114 artdaq_Fragment_.setMetadata<Metadata>(m); 00115 00116 if (artdaq_Fragment_.size() != 00117 artdaq::detail::RawFragmentHeader::num_words() + 00118 words_to_frag_words_(Metadata::size_words)) 00119 { 00120 TLOG(TLVL_ERROR, "ContainerFragmentLoader") << "ContainerFragmentLoader: Raw artdaq::Fragment object size suggests it does not consist of its own header + the ContainerFragment::Metadata object"; 00121 TLOG(TLVL_ERROR, "ContainerFragmentLoader") << "artdaq_Fragment size: " << artdaq_Fragment_.size() << ", Expected size: " << artdaq::detail::RawFragmentHeader::num_words() + words_to_frag_words_(Metadata::size_words); 00122 00123 throw cet::exception("InvalidFragment") << "ContainerFragmentLoader: Raw artdaq::Fragment object size suggests it does not consist of its own header + the ContainerFragment::Metadata object"; // NOLINT(cert-err60-cpp) 00124 } 00125 00126 artdaq_Fragment_.resize(1); 00127 *artdaq_Fragment_.dataBegin() = CONTAINER_MAGIC; 00128 } 00129 00130 inline size_t artdaq::ContainerFragmentLoader::words_to_frag_words_(size_t nWords) 00131 { 00132 size_t mod = nWords % words_per_frag_word_(); 00133 return mod ? nWords / words_per_frag_word_() + 1 : nWords / words_per_frag_word_(); 00134 } 00135 00136 inline void artdaq::ContainerFragmentLoader::addSpace_(size_t bytes) 00137 { 00138 auto currSize = sizeof(artdaq::Fragment::value_type) * artdaq_Fragment_.dataSize(); // Resize takes into account header and metadata size 00139 artdaq_Fragment_.resizeBytesWithCushion(bytes + currSize, 1.3); 00140 reset_index_ptr_(); // Must reset index_ptr after resize operation! 00141 00142 TLOG(TLVL_TRACE, "ContainerFragmentLoader") << "addSpace_: dataEnd_ is now at " << static_cast<void*>(dataEnd_()) << " (oldSizeBytes/deltaBytes: " << currSize << "/" << bytes << ")"; 00143 } 00144 00145 inline void artdaq::ContainerFragmentLoader::addFragment(artdaq::Fragment& frag) 00146 { 00147 TLOG(TLVL_TRACE, "ContainerFragmentLoader") << "addFragment: Adding Fragment with payload size " << frag.dataSizeBytes() << " to Container"; 00148 if (metadata()->fragment_type == Fragment::EmptyFragmentType) 00149 metadata()->fragment_type = frag.type(); 00150 else if (frag.type() != metadata()->fragment_type) 00151 { 00152 TLOG(TLVL_ERROR, "ContainerFragmentLoader") << "addFragment: Trying to add a fragment of different type than what's already been added!"; 00153 throw cet::exception("WrongFragmentType") << "ContainerFragmentLoader::addFragment: Trying to add a fragment of different type than what's already been added!"; // NOLINT(cert-err60-cpp) 00154 } 00155 00156 TLOG(TLVL_TRACE, "ContainerFragmentLoader") << "addFragment: Payload Size is " << artdaq_Fragment_.dataSizeBytes() << ", lastFragmentIndex is " << lastFragmentIndex() << ", and frag.size is " << frag.sizeBytes(); 00157 if (artdaq_Fragment_.dataSizeBytes() < (lastFragmentIndex() + frag.sizeBytes() + sizeof(size_t) * (metadata()->block_count + 2))) 00158 { 00159 addSpace_((lastFragmentIndex() + frag.sizeBytes() + sizeof(size_t) * (metadata()->block_count + 2)) - artdaq_Fragment_.dataSizeBytes()); 00160 } 00161 frag.setSequenceID(artdaq_Fragment_.sequenceID()); 00162 TLOG(TLVL_TRACE, "ContainerFragmentLoader") << "addFragment, copying " << frag.sizeBytes() << " bytes from " << static_cast<void*>(frag.headerAddress()) << " to " << static_cast<void*>(dataEnd_()); 00163 memcpy(dataEnd_(), frag.headerAddress(), frag.sizeBytes()); 00164 metadata()->has_index = 0; 00165 00166 metadata()->block_count++; 00167 00168 auto index = create_index_(); 00169 metadata()->index_offset = index[metadata()->block_count - 1]; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) 00170 memcpy(dataBegin_() + metadata()->index_offset, index, sizeof(size_t) * (metadata()->block_count + 1)); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) 00171 00172 metadata()->has_index = 1; 00173 reset_index_ptr_(); 00174 } 00175 00176 inline void artdaq::ContainerFragmentLoader::addFragment(artdaq::FragmentPtr& frag) 00177 { 00178 addFragment(*frag); 00179 } 00180 00181 inline void artdaq::ContainerFragmentLoader::addFragments(artdaq::FragmentPtrs& frags) 00182 { 00183 TLOG(TLVL_TRACE, "ContainerFragmentLoader") << "addFragments: Adding " << frags.size() << " Fragments to Container"; 00184 00185 size_t total_size = 0; 00186 for (auto& frag : frags) { total_size += frag->sizeBytes(); } 00187 00188 TLOG(TLVL_TRACE, "ContainerFragmentLoader") << "addFragments: Payload Size is " << artdaq_Fragment_.dataSizeBytes() << ", lastFragmentIndex is " << lastFragmentIndex() << ", and size to add is " << total_size; 00189 if (artdaq_Fragment_.dataSizeBytes() < (lastFragmentIndex() + total_size + sizeof(size_t) * (metadata()->block_count + 1 + frags.size()))) 00190 { 00191 addSpace_((lastFragmentIndex() + total_size + sizeof(size_t) * (metadata()->block_count + 1 + frags.size())) - artdaq_Fragment_.dataSizeBytes()); 00192 } 00193 00194 auto data_ptr = dataEnd_(); 00195 00196 for (auto& frag : frags) 00197 { 00198 if (metadata()->fragment_type == Fragment::EmptyFragmentType) 00199 metadata()->fragment_type = frag->type(); 00200 else if (frag->type() != metadata()->fragment_type) 00201 { 00202 TLOG(TLVL_ERROR, "ContainerFragmentLoader") << "addFragments: Trying to add a fragment of different type than what's already been added!"; 00203 throw cet::exception("WrongFragmentType") << "ContainerFragmentLoader::addFragments: Trying to add a fragment of different type than what's already been added!"; // NOLINT(cert-err60-cpp) 00204 } 00205 00206 frag->setSequenceID(artdaq_Fragment_.sequenceID()); 00207 TLOG(TLVL_TRACE, "ContainerFragmentLoader") << "addFragments, copying " << frag->sizeBytes() << " bytes from " << static_cast<void*>(frag->headerAddress()) << " to " << static_cast<void*>(dataEnd_()); 00208 memcpy(data_ptr, frag->headerAddress(), frag->sizeBytes()); 00209 data_ptr = static_cast<uint8_t*>(data_ptr) + frag->sizeBytes(); 00210 } 00211 metadata()->has_index = 0; 00212 metadata()->block_count += frags.size(); 00213 00214 auto index = create_index_(); 00215 metadata()->index_offset = index[metadata()->block_count - 1]; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) 00216 memcpy(dataBegin_() + metadata()->index_offset, index, sizeof(size_t) * (metadata()->block_count + 1)); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) 00217 00218 metadata()->has_index = 1; 00219 reset_index_ptr_(); 00220 } 00221 00222 #endif /* artdaq_core_Data_ContainerFragmentLoader_hh */