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 namespace artdaq
00020 {
00021 class ContainerFragmentLoader;
00022 }
00023
00024
00028 class artdaq::ContainerFragmentLoader : public artdaq::ContainerFragment
00029 {
00030 public:
00031
00032
00039 explicit ContainerFragmentLoader(Fragment& f, Fragment::type_t expectedFragmentType);
00040
00041
00046 Metadata* metadata()
00047 {
00048 assert(artdaq_Fragment_.hasMetadata());
00049 return reinterpret_cast<Metadata *>(&*artdaq_Fragment_.metadataAddress());
00050 }
00051
00056 void set_fragment_type(Fragment::type_t type)
00057 {
00058 metadata()->fragment_type = type;
00059 }
00060
00069 void set_missing_data(bool isDataMissing)
00070 {
00071 metadata()->missing_data = isDataMissing;
00072 }
00073
00079 void addFragment(artdaq::Fragment& frag);
00080
00085 void addFragment(artdaq::FragmentPtr& frag);
00086
00091 void addFragments(artdaq::FragmentPtrs& frags);
00092
00093 private:
00094
00095 artdaq::Fragment& artdaq_Fragment_;
00096
00097 static size_t words_to_frag_words_(size_t nWords);
00098
00099 void addSpace_(size_t bytes);
00100
00101 uint8_t* dataBegin_() { return reinterpret_cast<uint8_t*>(&*artdaq_Fragment_.dataBegin()); }
00102 void* dataEnd_() { return reinterpret_cast<void*>(dataBegin_() + lastFragmentIndex()); }
00103 };
00104
00105 inline artdaq::ContainerFragmentLoader::ContainerFragmentLoader(artdaq::Fragment& f, artdaq::Fragment::type_t expectedFragmentType = Fragment::EmptyFragmentType) :
00106 ContainerFragment(f)
00107 , artdaq_Fragment_(f)
00108 {
00109 artdaq_Fragment_.setSystemType(Fragment::ContainerFragmentType);
00110 Metadata m;
00111 m.block_count = 0;
00112 m.fragment_type = expectedFragmentType;
00113 m.missing_data = false;
00114 for (int ii = 0; ii < CONTAINER_FRAGMENT_COUNT_MAX; ++ii)
00115 {
00116 m.index[ii] = 0;
00117 }
00118 artdaq_Fragment_.setMetadata<Metadata>(m);
00119
00120 if (artdaq_Fragment_.size() !=
00121 artdaq::detail::RawFragmentHeader::num_words() +
00122 words_to_frag_words_(Metadata::size_words))
00123 {
00124 TLOG_ERROR("ContainerFragmentLoader") << "ContainerFragmentLoader: Raw artdaq::Fragment object size suggests it does not consist of its own header + the ContainerFragment::Metadata object" << TLOG_ENDL;
00125 TLOG_ERROR("ContainerFragmentLoader") <<"artdaq_Fragment size: " << artdaq_Fragment_.size() << ", Expected size: " << artdaq::detail::RawFragmentHeader::num_words() + words_to_frag_words_(Metadata::size_words) << TLOG_ENDL;
00126
00127 throw cet::exception("InvalidFragment") << "ContainerFragmentLoader: Raw artdaq::Fragment object size suggests it does not consist of its own header + the ContainerFragment::Metadata object";
00128 }
00129 }
00130
00131 inline size_t artdaq::ContainerFragmentLoader::words_to_frag_words_(size_t nWords)
00132 {
00133 size_t mod = nWords % words_per_frag_word_();
00134 return mod ?
00135 nWords / words_per_frag_word_() + 1 :
00136 nWords / words_per_frag_word_();
00137 }
00138
00139 inline void artdaq::ContainerFragmentLoader::addSpace_(size_t bytes)
00140 {
00141 auto currSize = sizeof(artdaq::Fragment::value_type) * artdaq_Fragment_.dataSize();
00142 artdaq_Fragment_.resizeBytes(bytes + currSize);
00143 TRACE(4, "ContainerFragmentLoader::addSpace_: dataEnd_ is now at %p", dataEnd_());
00144 }
00145
00146 inline void artdaq::ContainerFragmentLoader::addFragment(artdaq::Fragment& frag)
00147 {
00148 if (metadata()->block_count >= CONTAINER_FRAGMENT_COUNT_MAX)
00149 {
00150 TLOG_ERROR("ContainerFragmentLoader") << "addFragment: Fragment is full, cannot add more fragments!" << TLOG_ENDL;
00151 throw cet::exception("ContainerFull") << "ContainerFragmentLoader::addFragment: Fragment is full, cannot add more fragments!";
00152 }
00153
00154 TRACE(4, "ContainerFragmentLoader::addFragment: Adding Fragment with payload size %llu to Container", (unsigned long long)frag.dataSizeBytes());
00155 if (metadata()->fragment_type == Fragment::EmptyFragmentType) metadata()->fragment_type = frag.type();
00156 else if (frag.type() != metadata()->fragment_type)
00157 {
00158 TLOG_ERROR("ContainerFragmentLoader") << "addFragment: Trying to add a fragment of different type than what's already been added!" << TLOG_ENDL;
00159 throw cet::exception("WrongFragmentType") << "ContainerFragmentLoader::addFragment: Trying to add a fragment of different type than what's already been added!";
00160 }
00161 TRACE(4, "ContainerFragmentLoader::addFragment: Payload Size is %llu, lastFragmentIndex is %llu, and frag.size is %llu", (unsigned long long)artdaq_Fragment_.dataSizeBytes(), (unsigned long long)lastFragmentIndex(), (unsigned long long)frag.sizeBytes());
00162 if (artdaq_Fragment_.dataSizeBytes() < lastFragmentIndex() + frag.sizeBytes())
00163 {
00164 addSpace_(frag.sizeBytes());
00165 }
00166 frag.setSequenceID(artdaq_Fragment_.sequenceID());
00167 TRACE(4, "ContainerFragmentLoader::addFragment, copying %llu bytes from %p to %p", (long long unsigned int)frag.sizeBytes(), (void*)frag.headerAddress(), dataEnd_());
00168 memcpy(dataEnd_(), frag.headerAddress(), frag.sizeBytes());
00169 metadata()->index[block_count()] = lastFragmentIndex() + frag.sizeBytes();
00170 metadata()->block_count++;
00171 }
00172
00173 inline void artdaq::ContainerFragmentLoader::addFragment(artdaq::FragmentPtr& frag)
00174 {
00175 addFragment(*frag);
00176 }
00177
00178 inline void artdaq::ContainerFragmentLoader::addFragments(artdaq::FragmentPtrs& frags)
00179 {
00180 for (auto& frag : frags)
00181 {
00182 addFragment((*frag));
00183 }
00184 }
00185
00186 #endif