artdaq  v2_03_02
 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  size_t qsize=incoming_events.size(); // save the qsize at this point
97 
98  // Check the number of fragments in the RawEvent. If we have a single
99  // fragment and that fragment is marked as EndRun or EndSubrun we'll create
100  // the special principals for that.
101  art::Timestamp currentTime = time(0);
102 
103  // make new run if inR is 0 or if the run has changed
104  if (inR == 0 || inR->run() != popped_event->runID())
105  {
106  outR = pmaker.makeRunPrincipal(popped_event->runID(),
107  currentTime);
108  }
109 
110  if (popped_event->numFragments() == 1)
111  {
112  if (popped_event->releaseProduct(Fragment::EndOfRunFragmentType)->size() == 1)
113  {
114  art::EventID const evid(art::EventID::flushEvent());
115  outR = pmaker.makeRunPrincipal(evid.runID(), currentTime);
116  outSR = pmaker.makeSubRunPrincipal(evid.subRunID(), currentTime);
117  outE = pmaker.makeEventPrincipal(evid, currentTime);
118  return true;
119  }
120  else if (popped_event->releaseProduct(Fragment::EndOfSubrunFragmentType)->size() == 1)
121  {
122  // Check if inR == 0 or is a new run
123  if (inR == 0 || inR->run() != popped_event->runID())
124  {
125  outSR = pmaker.makeSubRunPrincipal(popped_event->runID(),
126  popped_event->subrunID(),
127  currentTime);
128 #ifdef ARTDAQ_ART_EVENTID_HAS_EXPLICIT_RUNID /* Old, error-prone interface. */
129  art::EventID const evid(art::EventID::flushEvent(outR->id(), outSR->id()));
130 #else
131  art::EventID const evid(art::EventID::flushEvent(outSR->id()));
132 #endif
133  outE = pmaker.makeEventPrincipal(evid, currentTime);
134  }
135  else
136  {
137  // If the previous subrun was neither 0 nor flush and was identical with the current
138  // subrun, then it must have been associated with a data event. In that case, we need
139  // to generate a flush event with a valid run but flush subrun and event number in order
140  // to end the subrun.
141  if (inSR != 0 && !inSR->id().isFlush() && inSR->subRun() == popped_event->subrunID())
142  {
143  art::EventID const evid(art::EventID::flushEvent(inR->id()));
144  outSR = pmaker.makeSubRunPrincipal(evid.subRunID(), currentTime);
145  outE = pmaker.makeEventPrincipal(evid, currentTime);
146  // If this is either a new or another empty subrun, then generate a flush event with
147  // valid run and subrun numbers but flush event number
148  //} else if(inSR==0 || inSR->id().isFlush()){
149  }
150  else
151  {
152  outSR = pmaker.makeSubRunPrincipal(popped_event->runID(),
153  popped_event->subrunID(),
154  currentTime);
155 #ifdef ARTDAQ_ART_EVENTID_HAS_EXPLICIT_RUNID /* Old, error-prone interface. */
156  art::EventID const evid(art::EventID::flushEvent(inR->id(), outSR->id()));
157 #else
158  art::EventID const evid(art::EventID::flushEvent(outSR->id()));
159 #endif
160  outE = pmaker.makeEventPrincipal(evid, currentTime);
161  // Possible error condition
162  //} else {
163  }
164  outR = 0;
165  }
166  //outputFileCloseNeeded = true;
167  return true;
168  }
169  }
170 
171  // make new subrun if inSR is 0 or if the subrun has changed
172  art::SubRunID subrun_check(popped_event->runID(), popped_event->subrunID());
173  if (inSR == 0 || subrun_check != inSR->id())
174  {
175  outSR = pmaker.makeSubRunPrincipal(popped_event->runID(),
176  popped_event->subrunID(),
177  currentTime);
178  }
179  outE = pmaker.makeEventPrincipal(popped_event->runID(),
180  popped_event->subrunID(),
181  popped_event->sequenceID(),
182  currentTime);
183  // get the list of fragment types that exist in the event
184  std::vector<Fragment::type_t> type_list;
185  popped_event->fragmentTypes(type_list);
186  // insert the Fragments of each type into the EventPrincipal
187  std::map<Fragment::type_t, std::string>::const_iterator iter_end =
188  fragment_type_map_.end();
189  for (size_t idx = 0; idx < type_list.size(); ++idx)
190  {
191  std::map<Fragment::type_t, std::string>::const_iterator iter =
192  fragment_type_map_.find(type_list[idx]);
193  auto product = popped_event->releaseProduct(type_list[idx]);
194  for (auto &frag : *product)
195  bytesRead += frag.sizeBytes();
196  if (iter != iter_end)
197  {
198  put_product_in_principal(std::move(product),
199  *outE,
200  pretend_module_name,
201  iter->second);
202  }
203  else
204  {
205  put_product_in_principal(std::move(product),
206  *outE,
207  pretend_module_name,
208  unidentified_instance_name);
209  TLOG_WARNING("RawEventQueueReader")
210  << "UnknownFragmentType: The product instance name mapping for fragment type \""
211  << ((int)type_list[idx]) << "\" is not known. Fragments of this "
212  << "type will be stored in the event with an instance name of \""
213  << unidentified_instance_name << "\"." << TLOG_ENDL;
214  }
215  }
216  TRACE( 10, "readNext: bytesRead=%lu qsize=%zu cap=%zu metricMan=%p", bytesRead, qsize, incoming_events.capacity(), (void*)metricMan );
217  if (metricMan) {
218  metricMan->sendMetric( "bytesRead", bytesRead>>20, "MB", 5, false, "", true );
219  metricMan->sendMetric( "queue%Used", static_cast<unsigned long int>(qsize*100/incoming_events.capacity()), "%", 5, false, "", true );
220  }
221 
222  return true;
223 }
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.