artdaq_core  v1_05_07
 All Classes Namespaces Functions
ContainerFragmentLoader.hh
1 #ifndef artdaq_core_Data_ContainerFragmentLoader_hh
2 #define artdaq_core_Data_ContainerFragmentLoader_hh
3 
5 // ContainerFragmentLoader
6 //
7 // This class gives write access to a ContainerFragment. It should be
8 // used when multiple fragments are generated by one BoardReader for a
9 // single event.
10 //
12 
13 #include "artdaq-core/Data/Fragment.hh"
14 #include "artdaq-core/Data/Fragments.hh"
15 #include "artdaq-core/Data/ContainerFragment.hh"
16 #include "trace.h"
17 
18 #include <iostream>
19 
20 namespace artdaq {
21  class ContainerFragmentLoader;
22 }
23 
24 
26 public:
27 
28 
30 
31  Metadata * metadata() {
32  assert(artdaq_Fragment_.hasMetadata());
33  return reinterpret_cast<Metadata *>(&*artdaq_Fragment_.metadataAddress());
34  }
35 
36  void set_fragment_type(Fragment::type_t type) {
37  metadata()->fragment_type = type;
38  }
39 
40  void set_missing_data(bool isDataMissing) {
41  metadata()->missing_data = isDataMissing;
42  }
43 
44  void addFragment(artdaq::Fragment & frag);
45  void addFragment(artdaq::FragmentPtr& frag);
46  void addFragments(artdaq::FragmentPtrs & frags);
47 
48 private:
49  // Note that this non-const reference hides the const reference in the base class
50  artdaq::Fragment & artdaq_Fragment_;
51  static size_t words_to_frag_words_(size_t nWords);
52  void addSpace_(size_t bytes);
53  uint8_t* dataBegin_() { return reinterpret_cast<uint8_t*>(&*artdaq_Fragment_.dataBegin()); }
54  void* dataEnd_() { return reinterpret_cast<void*>(dataBegin_() + lastFragmentIndex()); }
55 };
56 
57 // The constructor will expect the artdaq::Fragment object it's been
58 // passed to contain the artdaq::Fragment header + the
59 // DTCFragment::Metadata object, otherwise it throws
60 
61 artdaq::ContainerFragmentLoader::ContainerFragmentLoader(artdaq::Fragment& f) :
62  ContainerFragment(f), artdaq_Fragment_(f) {
63  artdaq_Fragment_.setSystemType(Fragment::ContainerFragmentType);
64  Metadata m;
65  m.block_count = 0;
66  m.fragment_type = Fragment::EmptyFragmentType;
67  m.missing_data = false;
68  for (int ii = 0; ii < FRAGMENT_COUNT_MAX; ++ii) {
69  m.index[ii] = 0;
70  }
71  artdaq_Fragment_.setMetadata<Metadata>(m);
72 
73  if (artdaq_Fragment_.size() !=
74  artdaq::detail::RawFragmentHeader::num_words() +
75  words_to_frag_words_(Metadata::size_words))
76  {
77  std::cerr << "artdaq_Fragment size: " << artdaq_Fragment_.size() << std::endl;
78  std::cerr << "Expected size: " << artdaq::detail::RawFragmentHeader::num_words() +
79  words_to_frag_words_(Metadata::size_words) << std::endl;
80 
81  throw cet::exception("ContainerFragmentLoader: Raw artdaq::Fragment object size suggests it does not consist of its own header + the ContainerFragment::Metadata object");
82  }
83 }
84 
85 inline size_t artdaq::ContainerFragmentLoader::words_to_frag_words_(size_t nWords)
86 {
87  size_t mod = nWords % words_per_frag_word_();
88  return mod ?
89  nWords / words_per_frag_word_() + 1 :
90  nWords / words_per_frag_word_();
91 }
92 
93 void artdaq::ContainerFragmentLoader::addSpace_(size_t bytes)
94 {
95  auto currSize = sizeof(artdaq::Fragment::value_type) * artdaq_Fragment_.dataSize(); // Resize takes into account header and metadata size
96  artdaq_Fragment_.resizeBytes(bytes + currSize);
97  TRACE(4, "ContainerFragmentLoader::addSpace_: dataEnd_ is now at %p", dataEnd_());
98 }
99 
100 void artdaq::ContainerFragmentLoader::addFragment(artdaq::Fragment & frag)
101 {
102  TRACE(4, "ContainerFragmentLoader::addFragment: Adding Fragment with payload size %llu to Container", (unsigned long long)frag.dataSizeBytes());
103  if (metadata()->fragment_type == Fragment::EmptyFragmentType) metadata()->fragment_type = frag.type();
104  else if (frag.type() != metadata()->fragment_type) {
105  throw cet::exception("ContainerFragmentLoader::addFragment: Trying to add a fragment of different type than what's already been added!");
106  }
107  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());
108  if (artdaq_Fragment_.dataSizeBytes() < lastFragmentIndex() + frag.sizeBytes()) {
109  addSpace_(frag.sizeBytes());
110  }
111  frag.setSequenceID(artdaq_Fragment_.sequenceID());
112  TRACE(4, "ContainerFragmentLoader::addFragment, copying %llu bytes from %p to %p", (long long unsigned int)frag.sizeBytes(), (void*)frag.headerAddress(), dataEnd_());
113  memcpy(dataEnd_(), frag.headerAddress(), frag.sizeBytes());
114  metadata()->index[block_count()] = lastFragmentIndex() + frag.sizeBytes();
115  metadata()->block_count++;
116 }
117 
118 void artdaq::ContainerFragmentLoader::addFragment(artdaq::FragmentPtr & frag)
119 {
120  addFragment(*frag);
121 }
122 
123 void artdaq::ContainerFragmentLoader::addFragments(artdaq::FragmentPtrs & frags)
124 {
125  for (auto & frag : frags)
126  {
127  addFragment((*frag));
128  }
129 }
130 
131 #endif /* artdaq_core_Data_ContainerFragmentLoader_hh */