artdaq  v2_03_00
 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 
5 #include "art/Framework/IO/Sources/put_product_in_principal.h"
6 #include "canvas/Persistency/Provenance/FileFormatVersion.h"
7 #include "canvas/Utilities/Exception.h"
8 #include "artdaq-core/Data/Fragment.hh"
9 #include <sys/time.h>
10 #define TRACE_NAME "RawEventQueueReader"
11 #include "trace.h"
12 
13 using std::string;
14 
16  art::ProductRegistryHelper& help,
17  art::SourceHelper const& pm) :
18  pmaker(pm)
19  , incoming_events(getGlobalQueue())
20  , waiting_time(ps.get<double>("waiting_time", 86400.0))
21  , resume_after_timeout(ps.get<bool>("resume_after_timeout", true))
22  , pretend_module_name(ps.get<std::string>("raw_data_label","daq"))
23  , unidentified_instance_name("unidentified")
24  , shutdownMsgReceived(false)
25  , outputFileCloseNeeded(false)
26  , bytesRead(0)
27  , fragment_type_map_(Fragment::MakeSystemTypeMap())
28  , readNext_calls_(0)
29 {
30  help.reconstitutes<Fragments, art::InEvent>(pretend_module_name,
32  for (auto it = fragment_type_map_.begin(); it != fragment_type_map_.end(); ++it)
33  {
34  help.reconstitutes<Fragments, art::InEvent>(pretend_module_name, it->second);
35  }
36 }
37 
39 
41  art::FileBlock*& fb)
42 {
43  fb = new art::FileBlock(art::FileFormatVersion(1, "RawEvent2011"), "nothing");
44 }
45 
46 bool artdaq::detail::RawEventQueueReader::readNext(art::RunPrincipal* const & inR,
47  art::SubRunPrincipal* const & inSR,
48  art::RunPrincipal*& outR,
49  art::SubRunPrincipal*& outSR,
50  art::EventPrincipal*& outE)
51 {
52  /*if (outputFileCloseNeeded) {
53  outputFileCloseNeeded = false;
54  return false;
55  }*/
56  if (readNext_calls_++ == 0)
57  {
58  incoming_events.setReaderIsReady();
59  TRACE(50, "RawEventQueueReader::readNext after incoming_events.setReaderIsReady()");
60  }
61  // Establish default 'results'
62  outR = 0;
63  outSR = 0;
64  outE = 0;
65  RawEvent_ptr popped_event;
66  // Try to get an event from the queue. We'll continuously loop, either until:
67  // 1) we have read a RawEvent off the queue, or
68  // 2) we have timed out, AND we are told the when we timeout we
69  // should stop.
70  // In any case, if we time out, we emit an informational message.
71  bool keep_looping = true;
72  bool got_event = false;
73  while (keep_looping)
74  {
75  keep_looping = false;
76  got_event = incoming_events.deqTimedWait(popped_event, waiting_time);
77  if (!got_event)
78  {
79  TLOG_INFO("RawEventQueueReader")
80  << "InputFailure: Reading timed out in RawEventQueueReader::readNext()" << TLOG_ENDL;
81  keep_looping = resume_after_timeout;
82  }
83  }
84  // We return false, indicating we're done reading, if:
85  // 1) we did not obtain an event, because we timed out and were
86  // configured NOT to keep trying after a timeout, or
87  // 2) the event we read was the end-of-data marker: a null
88  // pointer
89  if (!got_event || !popped_event)
90  {
91  TLOG_DEBUG("RawEventQueueReader") << "Received shutdown message, returning false" << TLOG_ENDL;
92  shutdownMsgReceived = true;
93  return false;
94  }
95 
96  // Check the number of fragments in the RawEvent. If we have a single
97  // fragment and that fragment is marked as EndRun or EndSubrun we'll create
98  // the special principals for that.
99  art::Timestamp currentTime = time(0);
100 
101  // make new run if inR is 0 or if the run has changed
102  if (inR == 0 || inR->run() != popped_event->runID())
103  {
104  outR = pmaker.makeRunPrincipal(popped_event->runID(),
105  currentTime);
106  }
107 
108  if (popped_event->numFragments() == 1)
109  {
110  if (popped_event->releaseProduct(Fragment::EndOfRunFragmentType)->size() == 1)
111  {
112  art::EventID const evid(art::EventID::flushEvent());
113  outR = pmaker.makeRunPrincipal(evid.runID(), currentTime);
114  outSR = pmaker.makeSubRunPrincipal(evid.subRunID(), currentTime);
115  outE = pmaker.makeEventPrincipal(evid, currentTime);
116  return true;
117  }
118  else if (popped_event->releaseProduct(Fragment::EndOfSubrunFragmentType)->size() == 1)
119  {
120  // Check if inR == 0 or is a new run
121  if (inR == 0 || inR->run() != popped_event->runID())
122  {
123  outSR = pmaker.makeSubRunPrincipal(popped_event->runID(),
124  popped_event->subrunID(),
125  currentTime);
126 #ifdef ARTDAQ_ART_EVENTID_HAS_EXPLICIT_RUNID /* Old, error-prone interface. */
127  art::EventID const evid(art::EventID::flushEvent(outR->id(), outSR->id()));
128 #else
129  art::EventID const evid(art::EventID::flushEvent(outSR->id()));
130 #endif
131  outE = pmaker.makeEventPrincipal(evid, currentTime);
132  }
133  else
134  {
135  // If the previous subrun was neither 0 nor flush and was identical with the current
136  // subrun, then it must have been associated with a data event. In that case, we need
137  // to generate a flush event with a valid run but flush subrun and event number in order
138  // to end the subrun.
139  if (inSR != 0 && !inSR->id().isFlush() && inSR->subRun() == popped_event->subrunID())
140  {
141  art::EventID const evid(art::EventID::flushEvent(inR->id()));
142  outSR = pmaker.makeSubRunPrincipal(evid.subRunID(), currentTime);
143  outE = pmaker.makeEventPrincipal(evid, currentTime);
144  // If this is either a new or another empty subrun, then generate a flush event with
145  // valid run and subrun numbers but flush event number
146  //} else if(inSR==0 || inSR->id().isFlush()){
147  }
148  else
149  {
150  outSR = pmaker.makeSubRunPrincipal(popped_event->runID(),
151  popped_event->subrunID(),
152  currentTime);
153 #ifdef ARTDAQ_ART_EVENTID_HAS_EXPLICIT_RUNID /* Old, error-prone interface. */
154  art::EventID const evid(art::EventID::flushEvent(inR->id(), outSR->id()));
155 #else
156  art::EventID const evid(art::EventID::flushEvent(outSR->id()));
157 #endif
158  outE = pmaker.makeEventPrincipal(evid, currentTime);
159  // Possible error condition
160  //} else {
161  }
162  outR = 0;
163  }
164  //outputFileCloseNeeded = true;
165  return true;
166  }
167  }
168 
169  // make new subrun if inSR is 0 or if the subrun has changed
170  art::SubRunID subrun_check(popped_event->runID(), popped_event->subrunID());
171  if (inSR == 0 || subrun_check != inSR->id())
172  {
173  outSR = pmaker.makeSubRunPrincipal(popped_event->runID(),
174  popped_event->subrunID(),
175  currentTime);
176  }
177  outE = pmaker.makeEventPrincipal(popped_event->runID(),
178  popped_event->subrunID(),
179  popped_event->sequenceID(),
180  currentTime);
181  // get the list of fragment types that exist in the event
182  std::vector<Fragment::type_t> type_list;
183  popped_event->fragmentTypes(type_list);
184  // insert the Fragments of each type into the EventPrincipal
185  std::map<Fragment::type_t, std::string>::const_iterator iter_end =
186  fragment_type_map_.end();
187  for (size_t idx = 0; idx < type_list.size(); ++idx)
188  {
189  std::map<Fragment::type_t, std::string>::const_iterator iter =
190  fragment_type_map_.find(type_list[idx]);
191  auto product = popped_event->releaseProduct(type_list[idx]);
192  for (auto &frag : *product)
193  bytesRead += frag.sizeBytes();
194  if (iter != iter_end)
195  {
196  put_product_in_principal(std::move(product),
197  *outE,
198  pretend_module_name,
199  iter->second);
200  }
201  else
202  {
203  put_product_in_principal(std::move(product),
204  *outE,
205  pretend_module_name,
206  unidentified_instance_name);
207  TLOG_WARNING("RawEventQueueReader")
208  << "UnknownFragmentType: The product instance name mapping for fragment type \""
209  << ((int)type_list[idx]) << "\" is not known. Fragments of this "
210  << "type will be stored in the event with an instance name of \""
211  << unidentified_instance_name << "\"." << TLOG_ENDL;
212  }
213  }
214  TRACE( 10, "readNext: bytesRead=%lu metricMan=%p", bytesRead, (void*)metricMan );
215  if (metricMan)
216  metricMan->sendMetric( "bytesRead", bytesRead>>20, "MB", 5, false, "", true );
217 
218  return true;
219 }
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.