00001 #ifndef artdaq_core_Data_ContainerFragmentLoader_hh
00002 #define artdaq_core_Data_ContainerFragmentLoader_hh
00003
00005
00006
00007
00008
00009
00010
00012
00013 #include "artdaq-core/Data/Fragment.hh"
00014 #include "artdaq-core/Data/ContainerFragment.hh"
00015
00016 #include "tracemf.h"
00017
00018 #include <iostream>
00019
00020
00021 namespace artdaq
00022 {
00023 class ContainerFragmentLoader;
00024 }
00025
00026
00030 class artdaq::ContainerFragmentLoader : public artdaq::ContainerFragment
00031 {
00032 public:
00033
00034
00041 explicit ContainerFragmentLoader(Fragment& f, Fragment::type_t expectedFragmentType);
00042
00043
00048 Metadata* metadata()
00049 {
00050 assert(artdaq_Fragment_.hasMetadata());
00051 return reinterpret_cast<Metadata *>(&*artdaq_Fragment_.metadataAddress());
00052 }
00053
00058 void set_fragment_type(Fragment::type_t type)
00059 {
00060 metadata()->fragment_type = type;
00061 }
00062
00071 void set_missing_data(bool isDataMissing)
00072 {
00073 metadata()->missing_data = isDataMissing;
00074 }
00075
00081 void addFragment(artdaq::Fragment& frag);
00082
00087 void addFragment(artdaq::FragmentPtr& frag);
00088
00093 void addFragments(artdaq::FragmentPtrs& frags);
00094
00095 private:
00096
00097 artdaq::Fragment& artdaq_Fragment_;
00098
00099 static size_t words_to_frag_words_(size_t nWords);
00100
00101 void addSpace_(size_t bytes);
00102
00103 uint8_t* dataBegin_() { return reinterpret_cast<uint8_t*>(&*artdaq_Fragment_.dataBegin()); }
00104 void* dataEnd_() { return reinterpret_cast<void*>(dataBegin_() + lastFragmentIndex()); }
00105 };
00106
00107 inline artdaq::ContainerFragmentLoader::ContainerFragmentLoader(artdaq::Fragment& f, artdaq::Fragment::type_t expectedFragmentType = Fragment::EmptyFragmentType) :
00108 ContainerFragment(f)
00109 , artdaq_Fragment_(f)
00110 {
00111 artdaq_Fragment_.setSystemType(Fragment::ContainerFragmentType);
00112 Metadata m;
00113 m.block_count = 0;
00114 m.fragment_type = expectedFragmentType;
00115 m.missing_data = false;
00116 m.has_index = true;
00117 m.version = ContainerFragment::CURRENT_VERSION;
00118 m.index_offset = 0;
00119 artdaq_Fragment_.setMetadata<Metadata>(m);
00120
00121 if (artdaq_Fragment_.size() !=
00122 artdaq::detail::RawFragmentHeader::num_words() +
00123 words_to_frag_words_(Metadata::size_words))
00124 {
00125 TLOG(TLVL_ERROR,"ContainerFragmentLoader") << "ContainerFragmentLoader: Raw artdaq::Fragment object size suggests it does not consist of its own header + the ContainerFragment::Metadata object" ;
00126 TLOG(TLVL_ERROR,"ContainerFragmentLoader") << "artdaq_Fragment size: " << artdaq_Fragment_.size() << ", Expected size: " << artdaq::detail::RawFragmentHeader::num_words() + words_to_frag_words_(Metadata::size_words) ;
00127
00128 throw cet::exception("InvalidFragment") << "ContainerFragmentLoader: Raw artdaq::Fragment object size suggests it does not consist of its own header + the ContainerFragment::Metadata object";
00129 }
00130
00131 artdaq_Fragment_.resize(1);
00132 *artdaq_Fragment_.dataBegin() = CONTAINER_MAGIC;
00133 }
00134
00135 inline size_t artdaq::ContainerFragmentLoader::words_to_frag_words_(size_t nWords)
00136 {
00137 size_t mod = nWords % words_per_frag_word_();
00138 return mod ?
00139 nWords / words_per_frag_word_() + 1 :
00140 nWords / words_per_frag_word_();
00141 }
00142
00143 inline void artdaq::ContainerFragmentLoader::addSpace_(size_t bytes)
00144 {
00145 auto currSize = sizeof(artdaq::Fragment::value_type) * artdaq_Fragment_.dataSize();
00146 artdaq_Fragment_.resizeBytesWithCushion(bytes + currSize, 1.3);
00147 reset_index_ptr_();
00148 TLOG(TLVL_TRACE,"ContainerFragmentLoader") << "addSpace_: dataEnd_ is now at " << (void*)dataEnd_() << " (oldSizeBytes/deltaBytes: " << currSize << "/" << bytes << ")";
00149 }
00150
00151 inline void artdaq::ContainerFragmentLoader::addFragment(artdaq::Fragment& frag)
00152 {
00153 TLOG(TLVL_TRACE,"ContainerFragmentLoader") << "addFragment: Adding Fragment with payload size " << frag.dataSizeBytes() << " to Container";
00154 if (metadata()->fragment_type == Fragment::EmptyFragmentType) metadata()->fragment_type = frag.type();
00155 else if (frag.type() != metadata()->fragment_type)
00156 {
00157 TLOG(TLVL_ERROR,"ContainerFragmentLoader") << "addFragment: Trying to add a fragment of different type than what's already been added!" ;
00158 throw cet::exception("WrongFragmentType") << "ContainerFragmentLoader::addFragment: Trying to add a fragment of different type than what's already been added!";
00159 }
00160
00161 TLOG(TLVL_TRACE,"ContainerFragmentLoader") << "addFragment: Payload Size is " << artdaq_Fragment_.dataSizeBytes() << ", lastFragmentIndex is " << lastFragmentIndex() << ", and frag.size is " << frag.sizeBytes();
00162 if (artdaq_Fragment_.dataSizeBytes() < (lastFragmentIndex() + frag.sizeBytes() + sizeof(size_t) * (metadata()->block_count + 2)))
00163 {
00164 addSpace_((lastFragmentIndex() + frag.sizeBytes() + sizeof(size_t) * (metadata()->block_count + 2)) - artdaq_Fragment_.dataSizeBytes());
00165 }
00166 frag.setSequenceID(artdaq_Fragment_.sequenceID());
00167 TLOG(TLVL_TRACE,"ContainerFragmentLoader") << "addFragment, copying " << frag.sizeBytes() << " bytes from " << (void*)frag.headerAddress() << " to " << (void*)dataEnd_();
00168 memcpy(dataEnd_(), frag.headerAddress(), frag.sizeBytes());
00169 metadata()->has_index = 0;
00170
00171 metadata()->block_count++;
00172
00173 auto index = create_index_();
00174 metadata()->index_offset = index[metadata()->block_count - 1];
00175 memcpy(dataBegin_() + metadata()->index_offset, index, sizeof(size_t) * (metadata()->block_count + 1));
00176 delete[] index;
00177 metadata()->has_index = 1;
00178 reset_index_ptr_();
00179 }
00180
00181 inline void artdaq::ContainerFragmentLoader::addFragment(artdaq::FragmentPtr& frag)
00182 {
00183 addFragment(*frag);
00184 }
00185
00186 inline void artdaq::ContainerFragmentLoader::addFragments(artdaq::FragmentPtrs& frags)
00187 {
00188 for (auto& frag : frags)
00189 {
00190 addFragment((*frag));
00191 }
00192 }
00193
00194 #endif