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 for (int ii = 0; ii < CONTAINER_FRAGMENT_COUNT_MAX; ++ii)
00117 {
00118 m.index[ii] = 0;
00119 }
00120 artdaq_Fragment_.setMetadata<Metadata>(m);
00121
00122 if (artdaq_Fragment_.size() !=
00123 artdaq::detail::RawFragmentHeader::num_words() +
00124 words_to_frag_words_(Metadata::size_words))
00125 {
00126 TLOG(TLVL_ERROR,"ContainerFragmentLoader") << "ContainerFragmentLoader: Raw artdaq::Fragment object size suggests it does not consist of its own header + the ContainerFragment::Metadata object" ;
00127 TLOG(TLVL_ERROR,"ContainerFragmentLoader") << "artdaq_Fragment size: " << artdaq_Fragment_.size() << ", Expected size: " << artdaq::detail::RawFragmentHeader::num_words() + words_to_frag_words_(Metadata::size_words) ;
00128
00129 throw cet::exception("InvalidFragment") << "ContainerFragmentLoader: Raw artdaq::Fragment object size suggests it does not consist of its own header + the ContainerFragment::Metadata object";
00130 }
00131 }
00132
00133 inline size_t artdaq::ContainerFragmentLoader::words_to_frag_words_(size_t nWords)
00134 {
00135 size_t mod = nWords % words_per_frag_word_();
00136 return mod ?
00137 nWords / words_per_frag_word_() + 1 :
00138 nWords / words_per_frag_word_();
00139 }
00140
00141 inline void artdaq::ContainerFragmentLoader::addSpace_(size_t bytes)
00142 {
00143 auto currSize = sizeof(artdaq::Fragment::value_type) * artdaq_Fragment_.dataSize();
00144 artdaq_Fragment_.resizeBytes(bytes + currSize);
00145 TLOG(TLVL_TRACE,"ContainerFragmentLoader") << "addSpace_: dataEnd_ is now at " << (void*)dataEnd_();
00146 }
00147
00148 inline void artdaq::ContainerFragmentLoader::addFragment(artdaq::Fragment& frag)
00149 {
00150 if (metadata()->block_count >= CONTAINER_FRAGMENT_COUNT_MAX)
00151 {
00152 TLOG(TLVL_ERROR,"ContainerFragmentLoader") << "addFragment: Fragment is full, cannot add more fragments!" ;
00153 throw cet::exception("ContainerFull") << "ContainerFragmentLoader::addFragment: Fragment is full, cannot add more fragments!";
00154 }
00155
00156 TLOG(TLVL_TRACE,"ContainerFragmentLoader") << "addFragment: Adding Fragment with payload size " << frag.dataSizeBytes() << " to Container";
00157 if (metadata()->fragment_type == Fragment::EmptyFragmentType) metadata()->fragment_type = frag.type();
00158 else if (frag.type() != metadata()->fragment_type)
00159 {
00160 TLOG(TLVL_ERROR,"ContainerFragmentLoader") << "addFragment: Trying to add a fragment of different type than what's already been added!" ;
00161 throw cet::exception("WrongFragmentType") << "ContainerFragmentLoader::addFragment: Trying to add a fragment of different type than what's already been added!";
00162 }
00163 TLOG(TLVL_TRACE,"ContainerFragmentLoader") << "addFragment: Payload Size is " << artdaq_Fragment_.dataSizeBytes() << ", lastFragmentIndex is " << lastFragmentIndex() << ", and frag.size is " << frag.sizeBytes();
00164 if (artdaq_Fragment_.dataSizeBytes() < lastFragmentIndex() + frag.sizeBytes())
00165 {
00166 addSpace_(frag.sizeBytes());
00167 }
00168 frag.setSequenceID(artdaq_Fragment_.sequenceID());
00169 TLOG(TLVL_TRACE,"ContainerFragmentLoader") << "addFragment, copying " << frag.sizeBytes() << " bytes from " << (void*)frag.headerAddress() << " to " << (void*)dataEnd_();
00170 memcpy(dataEnd_(), frag.headerAddress(), frag.sizeBytes());
00171 metadata()->index[block_count()] = lastFragmentIndex() + frag.sizeBytes();
00172 metadata()->block_count++;
00173 }
00174
00175 inline void artdaq::ContainerFragmentLoader::addFragment(artdaq::FragmentPtr& frag)
00176 {
00177 addFragment(*frag);
00178 }
00179
00180 inline void artdaq::ContainerFragmentLoader::addFragments(artdaq::FragmentPtrs& frags)
00181 {
00182 for (auto& frag : frags)
00183 {
00184 addFragment((*frag));
00185 }
00186 }
00187
00188 #endif