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