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