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 #include "tracemf.h"
00016
00017 #include <iostream>
00018
00019 #undef TRACE_NAME
00020 #define TRACE_NAME "ContainerFragmentLoader"
00021
00022 namespace artdaq
00023 {
00024 class ContainerFragmentLoader;
00025 }
00026
00027
00031 class artdaq::ContainerFragmentLoader : public artdaq::ContainerFragment
00032 {
00033 public:
00034
00035
00042 explicit ContainerFragmentLoader(Fragment& f, Fragment::type_t expectedFragmentType);
00043
00044
00049 Metadata* metadata()
00050 {
00051 assert(artdaq_Fragment_.hasMetadata());
00052 return reinterpret_cast<Metadata *>(&*artdaq_Fragment_.metadataAddress());
00053 }
00054
00059 void set_fragment_type(Fragment::type_t type)
00060 {
00061 metadata()->fragment_type = type;
00062 }
00063
00072 void set_missing_data(bool isDataMissing)
00073 {
00074 metadata()->missing_data = isDataMissing;
00075 }
00076
00082 void addFragment(artdaq::Fragment& frag);
00083
00088 void addFragment(artdaq::FragmentPtr& frag);
00089
00094 void addFragments(artdaq::FragmentPtrs& frags);
00095
00096 private:
00097
00098 artdaq::Fragment& artdaq_Fragment_;
00099
00100 static size_t words_to_frag_words_(size_t nWords);
00101
00102 void addSpace_(size_t bytes);
00103
00104 uint8_t* dataBegin_() { return reinterpret_cast<uint8_t*>(&*artdaq_Fragment_.dataBegin()); }
00105 void* dataEnd_() { return reinterpret_cast<void*>(dataBegin_() + lastFragmentIndex()); }
00106 };
00107
00108 inline artdaq::ContainerFragmentLoader::ContainerFragmentLoader(artdaq::Fragment& f, artdaq::Fragment::type_t expectedFragmentType = Fragment::EmptyFragmentType) :
00109 ContainerFragment(f)
00110 , artdaq_Fragment_(f)
00111 {
00112 artdaq_Fragment_.setSystemType(Fragment::ContainerFragmentType);
00113 Metadata m;
00114 m.block_count = 0;
00115 m.fragment_type = expectedFragmentType;
00116 m.missing_data = false;
00117 for (int ii = 0; ii < CONTAINER_FRAGMENT_COUNT_MAX; ++ii)
00118 {
00119 m.index[ii] = 0;
00120 }
00121 artdaq_Fragment_.setMetadata<Metadata>(m);
00122
00123 if (artdaq_Fragment_.size() !=
00124 artdaq::detail::RawFragmentHeader::num_words() +
00125 words_to_frag_words_(Metadata::size_words))
00126 {
00127 TLOG(TLVL_ERROR) << "ContainerFragmentLoader: Raw artdaq::Fragment object size suggests it does not consist of its own header + the ContainerFragment::Metadata object" << TLOG_ENDL;
00128 TLOG(TLVL_ERROR) << "artdaq_Fragment size: " << artdaq_Fragment_.size() << ", Expected size: " << artdaq::detail::RawFragmentHeader::num_words() + words_to_frag_words_(Metadata::size_words) << TLOG_ENDL;
00129
00130 throw cet::exception("InvalidFragment") << "ContainerFragmentLoader: Raw artdaq::Fragment object size suggests it does not consist of its own header + the ContainerFragment::Metadata object";
00131 }
00132 }
00133
00134 inline size_t artdaq::ContainerFragmentLoader::words_to_frag_words_(size_t nWords)
00135 {
00136 size_t mod = nWords % words_per_frag_word_();
00137 return mod ?
00138 nWords / words_per_frag_word_() + 1 :
00139 nWords / words_per_frag_word_();
00140 }
00141
00142 inline void artdaq::ContainerFragmentLoader::addSpace_(size_t bytes)
00143 {
00144 auto currSize = sizeof(artdaq::Fragment::value_type) * artdaq_Fragment_.dataSize();
00145 artdaq_Fragment_.resizeBytes(bytes + currSize);
00146 TLOG(4) << "addSpace_: dataEnd_ is now at " << (void*)dataEnd_();
00147 }
00148
00149 inline void artdaq::ContainerFragmentLoader::addFragment(artdaq::Fragment& frag)
00150 {
00151 if (metadata()->block_count >= CONTAINER_FRAGMENT_COUNT_MAX)
00152 {
00153 TLOG(TLVL_ERROR) << "addFragment: Fragment is full, cannot add more fragments!" << TLOG_ENDL;
00154 throw cet::exception("ContainerFull") << "ContainerFragmentLoader::addFragment: Fragment is full, cannot add more fragments!";
00155 }
00156
00157 TLOG(4) << "addFragment: Adding Fragment with payload size " << frag.dataSizeBytes() << " to Container";
00158 if (metadata()->fragment_type == Fragment::EmptyFragmentType) metadata()->fragment_type = frag.type();
00159 else if (frag.type() != metadata()->fragment_type)
00160 {
00161 TLOG(TLVL_ERROR) << "addFragment: Trying to add a fragment of different type than what's already been added!" << TLOG_ENDL;
00162 throw cet::exception("WrongFragmentType") << "ContainerFragmentLoader::addFragment: Trying to add a fragment of different type than what's already been added!";
00163 }
00164 TLOG(4) << "addFragment: Payload Size is " << artdaq_Fragment_.dataSizeBytes() << ", lastFragmentIndex is " << lastFragmentIndex() << ", and frag.size is " << frag.sizeBytes();
00165 if (artdaq_Fragment_.dataSizeBytes() < lastFragmentIndex() + frag.sizeBytes())
00166 {
00167 addSpace_(frag.sizeBytes());
00168 }
00169 frag.setSequenceID(artdaq_Fragment_.sequenceID());
00170 TLOG(4) << "addFragment, copying " << frag.sizeBytes() << " bytes from " << (void*)frag.headerAddress() << " to " << (void*)dataEnd_();
00171 memcpy(dataEnd_(), frag.headerAddress(), frag.sizeBytes());
00172 metadata()->index[block_count()] = lastFragmentIndex() + frag.sizeBytes();
00173 metadata()->block_count++;
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 for (auto& frag : frags)
00184 {
00185 addFragment((*frag));
00186 }
00187 }
00188
00189 #endif