artdaq  v2_03_03
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Pages
RawEventQueueReader.cc
1 
2 #include "artdaq/DAQdata/Globals.hh"
3 #include "artdaq/ArtModules/detail/RawEventQueueReader.hh"
4 #include "artdaq-core/Data/ContainerFragment.hh"
5 
6 #include "art/Framework/IO/Sources/put_product_in_principal.h"
7 #include "canvas/Persistency/Provenance/FileFormatVersion.h"
8 #include "canvas/Utilities/Exception.h"
9 #include "artdaq-core/Data/Fragment.hh"
10 #include <sys/time.h>
11 #define TRACE_NAME "RawEventQueueReader"
12 #include "trace.h"
13 
14 using std::string;
15 
17  art::ProductRegistryHelper& help,
18  art::SourceHelper const& pm) :
19  pmaker(pm)
20  , incoming_events(getGlobalQueue())
21  , waiting_time(ps.get<double>("waiting_time", 86400.0))
22  , resume_after_timeout(ps.get<bool>("resume_after_timeout", true))
23  , pretend_module_name(ps.get<std::string>("raw_data_label","daq"))
24  , unidentified_instance_name("unidentified")
25  , shutdownMsgReceived(false)
26  , outputFileCloseNeeded(false)
27  , bytesRead(0)
28  , fragment_type_map_(Fragment::MakeSystemTypeMap())
29  , readNext_calls_(0)
30 {
31  help.reconstitutes<Fragments, art::InEvent>(pretend_module_name,
33  help.reconstitutes<Fragments, art::InEvent>(pretend_module_name, "ContainerEmpty");
34  for (auto it = fragment_type_map_.begin(); it != fragment_type_map_.end(); ++it)
35  {
36  help.reconstitutes<Fragments, art::InEvent>(pretend_module_name, it->second);
37  }
38 }
39 
41 
43  art::FileBlock*& fb)
44 {
45  fb = new art::FileBlock(art::FileFormatVersion(1, "RawEvent2011"), "nothing");
46 }
47 
48 bool artdaq::detail::RawEventQueueReader::readNext(art::RunPrincipal* const & inR,
49  art::SubRunPrincipal* const & inSR,
50  art::RunPrincipal*& outR,
51  art::SubRunPrincipal*& outSR,
52  art::EventPrincipal*& outE)
53 {
54  /*if (outputFileCloseNeeded) {
55  outputFileCloseNeeded = false;
56  return false;
57  }*/
58  if (readNext_calls_++ == 0)
59  {
60  incoming_events.setReaderIsReady();
61  TRACE(50, "RawEventQueueReader::readNext after incoming_events.setReaderIsReady()");
62  }
63  // Establish default 'results'
64  outR = 0;
65  outSR = 0;
66  outE = 0;
67  RawEvent_ptr popped_event;
68  // Try to get an event from the queue. We'll continuously loop, either until:
69  // 1) we have read a RawEvent off the queue, or
70  // 2) we have timed out, AND we are told the when we timeout we
71  // should stop.
72  // In any case, if we time out, we emit an informational message.
73  bool keep_looping = true;
74  bool got_event = false;
75  while (keep_looping)
76  {
77  keep_looping = false;
78  got_event = incoming_events.deqTimedWait(popped_event, waiting_time);
79  if (!got_event)
80  {
81  TLOG_INFO("RawEventQueueReader")
82  << "InputFailure: Reading timed out in RawEventQueueReader::readNext()" << TLOG_ENDL;
83  keep_looping = resume_after_timeout;
84  }
85  }
86  // We return false, indicating we're done reading, if:
87  // 1) we did not obtain an event, because we timed out and were
88  // configured NOT to keep trying after a timeout, or
89  // 2) the event we read was the end-of-data marker: a null
90  // pointer
91  if (!got_event || !popped_event)
92  {
93  TLOG_DEBUG("RawEventQueueReader") << "Received shutdown message, returning false" << TLOG_ENDL;
94  shutdownMsgReceived = true;
95  return false;
96  }
97 
98  size_t qsize=incoming_events.size(); // save the qsize at this point
99 
100  // Check the number of fragments in the RawEvent. If we have a single
101  // fragment and that fragment is marked as EndRun or EndSubrun we'll create
102  // the special principals for that.
103  art::Timestamp currentTime = time(0);
104 
105  // make new run if inR is 0 or if the run has changed
106  if (inR == 0 || inR->run() != popped_event->runID())
107  {
108  outR = pmaker.makeRunPrincipal(popped_event->runID(),
109  currentTime);
110  }
111 
112  if (popped_event->numFragments() == 1)
113  {
114  if (popped_event->releaseProduct(Fragment::EndOfRunFragmentType)->size() == 1)
115  {
116  art::EventID const evid(art::EventID::flushEvent());
117  outR = pmaker.makeRunPrincipal(evid.runID(), currentTime);
118  outSR = pmaker.makeSubRunPrincipal(evid.subRunID(), currentTime);
119  outE = pmaker.makeEventPrincipal(evid, currentTime);
120  return true;
121  }
122  else if (popped_event->releaseProduct(Fragment::EndOfSubrunFragmentType)->size() == 1)
123  {
124  // Check if inR == 0 or is a new run
125  if (inR == 0 || inR->run() != popped_event->runID())
126  {
127  outSR = pmaker.makeSubRunPrincipal(popped_event->runID(),
128  popped_event->subrunID(),
129  currentTime);
130 #ifdef ARTDAQ_ART_EVENTID_HAS_EXPLICIT_RUNID /* Old, error-prone interface. */
131  art::EventID const evid(art::EventID::flushEvent(outR->id(), outSR->id()));
132 #else
133  art::EventID const evid(art::EventID::flushEvent(outSR->id()));
134 #endif
135  outE = pmaker.makeEventPrincipal(evid, currentTime);
136  }
137  else
138  {
139  // If the previous subrun was neither 0 nor flush and was identical with the current
140  // subrun, then it must have been associated with a data event. In that case, we need
141  // to generate a flush event with a valid run but flush subrun and event number in order
142  // to end the subrun.
143  if (inSR != 0 && !inSR->id().isFlush() && inSR->subRun() == popped_event->subrunID())
144  {
145  art::EventID const evid(art::EventID::flushEvent(inR->id()));
146  outSR = pmaker.makeSubRunPrincipal(evid.subRunID(), currentTime);
147  outE = pmaker.makeEventPrincipal(evid, currentTime);
148  // If this is either a new or another empty subrun, then generate a flush event with
149  // valid run and subrun numbers but flush event number
150  //} else if(inSR==0 || inSR->id().isFlush()){
151  }
152  else
153  {
154  outSR = pmaker.makeSubRunPrincipal(popped_event->runID(),
155  popped_event->subrunID(),
156  currentTime);
157 #ifdef ARTDAQ_ART_EVENTID_HAS_EXPLICIT_RUNID /* Old, error-prone interface. */
158  art::EventID const evid(art::EventID::flushEvent(inR->id(), outSR->id()));
159 #else
160  art::EventID const evid(art::EventID::flushEvent(outSR->id()));
161 #endif
162  outE = pmaker.makeEventPrincipal(evid, currentTime);
163  // Possible error condition
164  //} else {
165  }
166  outR = 0;
167  }
168  //outputFileCloseNeeded = true;
169  return true;
170  }
171  }
172 
173  // make new subrun if inSR is 0 or if the subrun has changed
174  art::SubRunID subrun_check(popped_event->runID(), popped_event->subrunID());
175  if (inSR == 0 || subrun_check != inSR->id())
176  {
177  outSR = pmaker.makeSubRunPrincipal(popped_event->runID(),
178  popped_event->subrunID(),
179  currentTime);
180  }
181  outE = pmaker.makeEventPrincipal(popped_event->runID(),
182  popped_event->subrunID(),
183  popped_event->sequenceID(),
184  currentTime);
185  // get the list of fragment types that exist in the event
186  std::vector<Fragment::type_t> type_list;
187  popped_event->fragmentTypes(type_list);
188  // insert the Fragments of each type into the EventPrincipal
189  std::map<Fragment::type_t, std::string>::const_iterator iter_end =
190  fragment_type_map_.end();
191  for (size_t idx = 0; idx < type_list.size(); ++idx)
192  {
193  std::map<Fragment::type_t, std::string>::const_iterator iter =
194  fragment_type_map_.find(type_list[idx]);
195  auto product = popped_event->releaseProduct(type_list[idx]);
196  for (auto &frag : *product)
197  bytesRead += frag.sizeBytes();
198  if (iter != iter_end)
199  {
200  if (type_list[idx] == artdaq::Fragment::ContainerFragmentType)
201  {
202  std::unordered_map<std::string, std::unique_ptr<Fragments>> derived_fragments;
203  derived_fragments[iter->second] = std::make_unique<Fragments>();
204 
205  for(size_t ii = 0; ii < product->size(); ++ii)
206  {
207  ContainerFragment cf(product->at(ii));
208  auto contained_type = fragment_type_map_.find(cf.fragment_type());
209  if (contained_type != iter_end)
210  {
211  auto label = iter->second + contained_type->second;
212  if (!derived_fragments.count(label))
213  {
214  derived_fragments[label] = std::make_unique<Fragments>();
215  }
216  derived_fragments[label]->emplace_back(std::move(product->at(ii)));
217  }
218  else
219  {
220  derived_fragments[iter->second]->emplace_back(std::move(product->at(ii)));
221  }
222  }
223 
224  for (auto& type : derived_fragments)
225  {
226  put_product_in_principal(std::move(type.second),
227  *outE,
228  pretend_module_name,
229  type.first);
230  }
231 
232  }
233  else
234  {
235  put_product_in_principal(std::move(product),
236  *outE,
237  pretend_module_name,
238  iter->second);
239  }
240  }
241  else
242  {
243  put_product_in_principal(std::move(product),
244  *outE,
245  pretend_module_name,
246  unidentified_instance_name);
247  TLOG_WARNING("RawEventQueueReader")
248  << "UnknownFragmentType: The product instance name mapping for fragment type \""
249  << ((int)type_list[idx]) << "\" is not known. Fragments of this "
250  << "type will be stored in the event with an instance name of \""
251  << unidentified_instance_name << "\"." << TLOG_ENDL;
252  }
253  }
254  TRACE( 10, "readNext: bytesRead=%lu qsize=%zu cap=%zu metricMan=%p", bytesRead, qsize, incoming_events.capacity(), (void*)metricMan );
255  if (metricMan) {
256  metricMan->sendMetric( "bytesRead", bytesRead>>20, "MB", 5, MetricMode::Accumulate, "", true );
257  metricMan->sendMetric( "queue%Used", static_cast<unsigned long int>(qsize*100/incoming_events.capacity()), "%", 5, MetricMode::LastPoint, "", true );
258  }
259 
260  return true;
261 }
std::string pretend_module_name
The module name to store data under.
bool readNext(art::RunPrincipal *const &inR, art::SubRunPrincipal *const &inSR, art::RunPrincipal *&outR, art::SubRunPrincipal *&outSR, art::EventPrincipal *&outE)
Dequeue a RawEvent and declare its Fragment contents to art, creating Run, SubRun, and EventPrincipal objects as necessary.
RawEventQueueReader(RawEventQueueReader const &)=delete
Copy Constructor is deleted.
std::string unidentified_instance_name
The name to use for unknown Fragment types.
void readFile(std::string const &, art::FileBlock *&fb)
Emulate opening a file.
void closeCurrentFile()
Emulate closing a file. No-Op.
std::map< Fragment::type_t, std::string > fragment_type_map_
The Fragment type names that this RawEventQueueReader knows about.