artdaq  v3_03_00
DataReceiverCore.cc
1 #include "canvas/Utilities/Exception.h"
2 #include "art/Framework/Art/artapp.h"
3 
4 #define TRACE_NAME (app_name + "_DataReceiverCore").c_str() // include these 2 first -
5 #include "artdaq/DAQdata/Globals.hh"
6 #include "artdaq-core/Core/SimpleMemoryReader.hh"
7 #include "artdaq-core/Utilities/ExceptionHandler.hh"
8 
9 #include "artdaq/Application/DataReceiverCore.hh"
10 #include "artdaq/TransferPlugins/TransferInterface.hh"
11 
12 #include <iomanip>
13 
15  : stop_requested_(false)
16  , pause_requested_(false)
17  , run_is_paused_(false)
18  , config_archive_entries_()
19 {
20  TLOG(TLVL_DEBUG) << "Constructor" ;
21 }
22 
24 {
25  TLOG(TLVL_DEBUG) << "Destructor" ;
26 }
27 
28 bool artdaq::DataReceiverCore::initializeDataReceiver(fhicl::ParameterSet const& pset, fhicl::ParameterSet const& data_pset, fhicl::ParameterSet const& metric_pset)
29 {
30  // other parameters
31  verbose_ = data_pset.get<bool>("verbose", true);
32 
33  // TRACE here so that mftrace_module and mftrace_iteration are ready by mftrace...should set it for all subsequent traces
34  TLOG(TLVL_INFO) << "Initializing Data Receiver";
35 
36  if (metric_pset.is_empty())
37  {
38  TLOG(TLVL_INFO) << "No metric plugins appear to be defined" ;
39  }
40  try
41  {
42  metricMan->initialize(metric_pset, app_name);
43  }
44  catch (...)
45  {
46  ExceptionHandler(ExceptionHandlerRethrow::no,
47  "Error loading metrics in DataReceiverCore::initialize()");
48  }
49 
50  fhicl::ParameterSet art_pset = pset;
51  if(art_pset.has_key("art"))
52  {
53  art_pset = art_pset.get<fhicl::ParameterSet>("art");
54  }
55  else
56  {
57  art_pset.erase("daq");
58  }
59 
60  fhicl::ParameterSet art_source_pset = art_pset.get<fhicl::ParameterSet>("source");
61  art_source_pset.put<fhicl::ParameterSet>("metrics", metric_pset);
62  art_pset.erase("source");
63  art_pset.put<fhicl::ParameterSet>("source", art_source_pset);
64 
65  fhicl::ParameterSet data_tmp = data_pset;
66  if (data_pset.has_key("expected_events_per_bunch"))
67  {
68  data_tmp.put<int>("expected_fragments_per_event", data_pset.get<int>("expected_events_per_bunch"));
69  }
70 
71  if (data_pset.has_key("rank"))
72  {
73  if (my_rank >= 0 && data_pset.get<int>("rank") != my_rank) {
74  TLOG(TLVL_WARNING) << "Rank specified at startup is different than rank specified at configure! Using rank received at configure!";
75  }
76  my_rank = data_pset.get<int>("rank");
77  }
78  if (my_rank == -1)
79  {
80  TLOG(TLVL_ERROR) << "Rank not specified at startup or in configuration! Aborting";
81  exit(1);
82  }
83 
84  event_store_ptr_.reset(new SharedMemoryEventManager(data_tmp, art_pset));
85  art_pset_ = art_pset;
86 
87  receiver_ptr_.reset(new artdaq::DataReceiverManager(data_tmp, event_store_ptr_));
88 
89  return true;
90 }
91 
93 {
94  logMessage_("Starting run " + boost::lexical_cast<std::string>(id.run()));
95 
96  // 13-Jul-2018, KAB: added code to update the art_pset inside the event store
97  // with configuration archive information
98  // so that the config info will be stored in the output art/ROOT file.
99  // (Note that we don't bother looping over the config_archive_entries if that
100  // map is empty, but we *do* still update the art configuration with art_pset_
101  // at each begin-run because the config archive may be non-empty one time through
102  // and then empty the next time.)
103  fhicl::ParameterSet temp_pset = art_pset_;
104  if (! config_archive_entries_.empty())
105  {
106  fhicl::ParameterSet config_pset;
107  for (auto& entry : config_archive_entries_)
108  {
109  config_pset.put(entry.first, entry.second);
110  }
111  temp_pset.put_or_replace("configuration_documents", config_pset);
112  }
113  event_store_ptr_->UpdateArtConfiguration(temp_pset);
114 
115  stop_requested_.store(false);
116  pause_requested_.store(false);
117  run_is_paused_.store(false);
118  metricMan->do_start();
119  event_store_ptr_->startRun(id.run());
120  receiver_ptr_->start_threads();
121 
122  logMessage_("Completed the Start transition for run " + boost::lexical_cast<std::string>(event_store_ptr_->runID()));
123  return true;
124 }
125 
127 {
128  logMessage_("Stopping run " + boost::lexical_cast<std::string>(event_store_ptr_->runID()) +
129  ", subrun " + boost::lexical_cast<std::string>(event_store_ptr_->subrunID()));
130  bool endSucceeded = false;
131  int attemptsToEnd;
132  receiver_ptr_->stop_threads();
133 
134  // 21-Jun-2013, KAB - the stop_requested_ variable must be set
135  // before the flush lock so that the processFragments loop will
136  // exit (after the timeout), the lock will be released (in the
137  // processFragments method), and this method can continue.
138  stop_requested_.store(true);
139 
140  if (!run_is_paused_.load())
141  {
142  TLOG(TLVL_DEBUG) << "Ending subrun " << event_store_ptr_->subrunID();
143  attemptsToEnd = 1;
144  endSucceeded = event_store_ptr_->endSubrun();
145  while (!endSucceeded && attemptsToEnd < 3)
146  {
147  ++attemptsToEnd;
148  TLOG(TLVL_DEBUG) << "Retrying EventStore::endSubrun()" ;
149  endSucceeded = event_store_ptr_->endSubrun();
150  }
151  if (!endSucceeded)
152  {
153  TLOG(TLVL_ERROR)
154  << "EventStore::endSubrun in stop method failed after three tries." ;
155  }
156  TLOG(TLVL_DEBUG) << "Done Ending subrun " << event_store_ptr_->subrunID();
157  }
158 
159  TLOG(TLVL_DEBUG) << "Ending run " << event_store_ptr_->runID();
160  attemptsToEnd = 1;
161  endSucceeded = event_store_ptr_->endRun();
162  while (!endSucceeded && attemptsToEnd < 3)
163  {
164  ++attemptsToEnd;
165  TLOG(TLVL_DEBUG) << "Retrying EventStore::endRun()" ;
166  endSucceeded = event_store_ptr_->endRun();
167  }
168  if (!endSucceeded)
169  {
170  TLOG(TLVL_ERROR)
171  << "EventStore::endRun in stop method failed after three tries." ;
172  }
173  TLOG(TLVL_DEBUG) << "Done Ending run " << event_store_ptr_->runID();
174 
175  attemptsToEnd = 1;
176  TLOG(TLVL_DEBUG) << "stop: Calling EventStore::endOfData" ;
177  endSucceeded = event_store_ptr_->endOfData();
178  while (!endSucceeded && attemptsToEnd < 3)
179  {
180  ++attemptsToEnd;
181  TLOG(TLVL_DEBUG) << "Retrying EventStore::endOfData()" ;
182  endSucceeded = event_store_ptr_->endOfData();
183  }
184 
185  run_is_paused_.store(false);
186  logMessage_("Completed the Stop transition for run " + boost::lexical_cast<std::string>(event_store_ptr_->runID()));
187  return true;
188 }
189 
191 {
192  logMessage_("Pausing run " + boost::lexical_cast<std::string>(event_store_ptr_->runID()) +
193  ", subrun " + boost::lexical_cast<std::string>(event_store_ptr_->subrunID()));
194  pause_requested_.store(true);
195 
196  bool endSucceeded = false;
197  int attemptsToEnd = 1;
198  endSucceeded = event_store_ptr_->endSubrun();
199  while (!endSucceeded && attemptsToEnd < 3)
200  {
201  ++attemptsToEnd;
202  TLOG(TLVL_DEBUG) << "Retrying EventStore::endSubrun()" ;
203  endSucceeded = event_store_ptr_->endSubrun();
204  }
205  if (!endSucceeded)
206  {
207  TLOG(TLVL_ERROR)
208  << "EventStore::endSubrun in pause method failed after three tries." ;
209  }
210 
211  run_is_paused_.store(true);
212  logMessage_("Completed the Pause transition for run " + boost::lexical_cast<std::string>(event_store_ptr_->runID()));
213  return true;
214 }
215 
217 {
218  logMessage_("Resuming run " + boost::lexical_cast<std::string>(event_store_ptr_->runID()));
219  pause_requested_.store(false);
220  metricMan->do_start();
221  event_store_ptr_->startSubrun();
222  run_is_paused_.store(false);
223  logMessage_("Completed the Resume transition for run " + boost::lexical_cast<std::string>(event_store_ptr_->runID()));
224  return true;
225 }
226 
228 {
229  logMessage_("Starting Shutdown transition");
230 
231  /* We don't care about flushing data here. The only way to transition to the
232  shutdown state is from a state where there is no data taking. All we have
233  to do is signal the art input module that we're done taking data so that
234  it can wrap up whatever it needs to do. */
235 
236  TLOG(TLVL_DEBUG) << "shutdown: Shutting down DataReceiverManager" ;
237  receiver_ptr_.reset(nullptr);
238 
239  bool endSucceeded = false;
240  int attemptsToEnd = 1;
241  TLOG(TLVL_DEBUG) << "shutdown: Calling EventStore::endOfData" ;
242  endSucceeded = event_store_ptr_->endOfData();
243  while (!endSucceeded && attemptsToEnd < 3)
244  {
245  ++attemptsToEnd;
246  TLOG(TLVL_DEBUG) << "Retrying EventStore::endOfData()" ;
247  endSucceeded = event_store_ptr_->endOfData();
248  }
249 
250  TLOG(TLVL_DEBUG) << "shutdown: Shutting down SharedMemoryEventManager" ;
251  event_store_ptr_.reset();
252 
253  TLOG(TLVL_DEBUG) << "shutdown: Shutting down MetricManager" ;
254  metricMan->shutdown();
255 
256  TLOG(TLVL_DEBUG) << "shutdown: Complete" ;
257  logMessage_("Completed Shutdown transition");
258  return endSucceeded;
259 }
260 
261 bool artdaq::DataReceiverCore::soft_initialize(fhicl::ParameterSet const& pset)
262 {
263  TLOG(TLVL_DEBUG) << "soft_initialize method called with DAQ "
264  << "ParameterSet = \"" << pset.to_string()
265  << "\"." ;
266  return true;
267 }
268 
269 bool artdaq::DataReceiverCore::reinitialize(fhicl::ParameterSet const& pset)
270 {
271  TLOG(TLVL_DEBUG) << "reinitialize method called with DAQ "
272  << "ParameterSet = \"" << pset.to_string()
273  << "\"." ;
274  event_store_ptr_ = nullptr;
275  return initialize(pset);
276 }
277 
279 {
280  if (event_store_ptr_)
281  {
282  event_store_ptr_->rolloverSubrun(boundary);
283  return true;
284  }
285  return false;
286 }
287 
288 std::string artdaq::DataReceiverCore::report(std::string const& which) const
289 {
290  if (which == "incomplete_event_count")
291  {
292  if (event_store_ptr_ != nullptr)
293  {
294  return boost::lexical_cast<std::string>(event_store_ptr_->GetIncompleteEventCount());
295  }
296  else
297  {
298  return "-1";
299  }
300  }
301  if (which == "event_count")
302  {
303  if (receiver_ptr_ != nullptr)
304  return boost::lexical_cast<std::string>(receiver_ptr_->GetReceivedFragmentCount()->count());
305 
306  return "0";
307  }
308 
309  // lots of cool stuff that we can do here
310  // - report on the number of fragments received and the number
311  // of events built (in the current or previous run
312  // - report on the number of incomplete events in the EventStore
313  // (if running)
314  std::string tmpString;
315  if (event_store_ptr_ != nullptr) tmpString.append(app_name + " run number = " + boost::lexical_cast<std::string>(event_store_ptr_->runID()) + ".\n");
316  tmpString.append("Command \"" + which + "\" is not currently supported.");
317  return tmpString;
318 }
319 
320 void artdaq::DataReceiverCore::logMessage_(std::string const& text)
321 {
322  if (verbose_)
323  {
324  TLOG(TLVL_INFO) << text ;
325  }
326  else
327  {
328  TLOG(TLVL_DEBUG) << text ;
329  }
330 }
DataReceiverCore()
DataReceiverCore Constructor.
bool soft_initialize(fhicl::ParameterSet const &pset)
Soft-Initializes the DataReceiverCore. No-Op.
The SharedMemoryEventManager is a SharedMemoryManger which tracks events as they are built...
bool resume()
Resumes the DataReceiverCore.
bool shutdown()
Shuts Down the DataReceiverCore.
bool start(art::RunID id)
Start the DataReceiverCore.
void logMessage_(std::string const &text)
Log a message, setting severity based on verbosity flag.
bool stop()
Stops the DataReceiverCore.
std::string report(std::string const &which) const
Send a report on a given run-time quantity.
bool pause()
Pauses the DataReceiverCore.
Receives Fragment objects from one or more DataSenderManager instances using TransferInterface plugin...
bool rollover_subrun(uint64_t eventNum)
Rollover the subrun after the given event.
bool initializeDataReceiver(fhicl::ParameterSet const &pset, fhicl::ParameterSet const &data_pset, fhicl::ParameterSet const &metric_pset)
Initialize the DataReceiverCore (should be called from initialize() overrides.
bool reinitialize(fhicl::ParameterSet const &pset)
Reinitializes the DataReceiverCore.