artdaq  v3_08_00
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 
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  {
75  TLOG(TLVL_WARNING) << "Rank specified at startup is different than rank specified at configure! Using rank received at configure!";
76  }
77  my_rank = data_pset.get<int>("rank");
78  }
79  if (my_rank == -1)
80  {
81  TLOG(TLVL_ERROR) << "Rank not specified at startup or in configuration! Aborting";
82  exit(1);
83  }
84 
85  event_store_ptr_.reset(new SharedMemoryEventManager(data_tmp, art_pset));
86  art_pset_ = art_pset;
87  TLOG(TLVL_DEBUG) << "Resulting art_pset_: \"" << art_pset_.to_string() << "\".";
88 
89  receiver_ptr_.reset(new artdaq::DataReceiverManager(data_tmp, event_store_ptr_));
90 
91  return true;
92 }
93 
95 {
96  TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) << "Starting run " << id.run();
97 
98  // 13-Jul-2018, KAB: added code to update the art_pset inside the event store
99  // with configuration archive information
100  // so that the config info will be stored in the output art/ROOT file.
101  // (Note that we don't bother looping over the config_archive_entries if that
102  // map is empty, but we *do* still update the art configuration with art_pset_
103  // at each begin-run because the config archive may be non-empty one time through
104  // and then empty the next time.)
105  fhicl::ParameterSet temp_pset = art_pset_;
106  if (!config_archive_entries_.empty())
107  {
108  fhicl::ParameterSet config_pset;
109  for (auto& entry : config_archive_entries_)
110  {
111  config_pset.put(entry.first, entry.second);
112  }
113  temp_pset.put_or_replace("configuration_documents", config_pset);
114  }
115  event_store_ptr_->UpdateArtConfiguration(temp_pset);
116 
117  stop_requested_.store(false);
118  pause_requested_.store(false);
119  run_is_paused_.store(false);
120  metricMan->do_start();
121  event_store_ptr_->startRun(id.run());
122  receiver_ptr_->start_threads();
123 
124  TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) << "Completed the Start transition for run " << event_store_ptr_->runID();
125  return true;
126 }
127 
129 {
130  TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) << "Stopping run " << event_store_ptr_->runID();
131  bool endSucceeded = false;
132  int attemptsToEnd;
133  receiver_ptr_->stop_threads();
134 
135  // 21-Jun-2013, KAB - the stop_requested_ variable must be set
136  // before the flush lock so that the processFragments loop will
137  // exit (after the timeout), the lock will be released (in the
138  // processFragments method), and this method can continue.
139  stop_requested_.store(true);
140 
141  TLOG(TLVL_DEBUG) << "Ending run " << event_store_ptr_->runID();
142  attemptsToEnd = 1;
143  endSucceeded = event_store_ptr_->endRun();
144  while (!endSucceeded && attemptsToEnd < 3)
145  {
146  ++attemptsToEnd;
147  TLOG(TLVL_DEBUG) << "Retrying EventStore::endRun()";
148  endSucceeded = event_store_ptr_->endRun();
149  }
150  if (!endSucceeded)
151  {
152  TLOG(TLVL_ERROR)
153  << "EventStore::endRun in stop method failed after three tries.";
154  }
155  TLOG(TLVL_DEBUG) << "Done Ending run " << event_store_ptr_->runID();
156 
157  attemptsToEnd = 1;
158  TLOG(TLVL_DEBUG) << "stop: Calling EventStore::endOfData";
159  endSucceeded = event_store_ptr_->endOfData();
160  while (!endSucceeded && attemptsToEnd < 3)
161  {
162  ++attemptsToEnd;
163  TLOG(TLVL_DEBUG) << "Retrying EventStore::endOfData()";
164  endSucceeded = event_store_ptr_->endOfData();
165  }
166 
167  run_is_paused_.store(false);
168  TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) << "Completed the Stop transition for run " << event_store_ptr_->runID();
169  return true;
170 }
171 
173 {
174  TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) << "Pausing run " << event_store_ptr_->runID();
175  pause_requested_.store(true);
176  run_is_paused_.store(true);
177  TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) << "Completed the Pause transition for run " << event_store_ptr_->runID();
178  return true;
179 }
180 
182 {
183  TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) << "Resuming run " << event_store_ptr_->runID();
184  pause_requested_.store(false);
185  metricMan->do_start();
186  event_store_ptr_->rolloverSubrun();
187  run_is_paused_.store(false);
188  TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) << "Completed the Resume transition for run " << event_store_ptr_->runID();
189  return true;
190 }
191 
193 {
194  TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) << "Starting Shutdown transition";
195 
196  /* We don't care about flushing data here. The only way to transition to the
197  shutdown state is from a state where there is no data taking. All we have
198  to do is signal the art input module that we're done taking data so that
199  it can wrap up whatever it needs to do. */
200 
201  TLOG(TLVL_DEBUG) << "shutdown: Shutting down DataReceiverManager";
202  receiver_ptr_.reset(nullptr);
203 
204  bool endSucceeded = false;
205  int attemptsToEnd = 1;
206  TLOG(TLVL_DEBUG) << "shutdown: Calling EventStore::endOfData";
207  endSucceeded = event_store_ptr_->endOfData();
208  while (!endSucceeded && attemptsToEnd < 3)
209  {
210  ++attemptsToEnd;
211  TLOG(TLVL_DEBUG) << "Retrying EventStore::endOfData()";
212  endSucceeded = event_store_ptr_->endOfData();
213  }
214 
215  TLOG(TLVL_DEBUG) << "shutdown: Shutting down SharedMemoryEventManager";
216  event_store_ptr_.reset();
217 
218  TLOG(TLVL_DEBUG) << "shutdown: Shutting down MetricManager";
219  metricMan->shutdown();
220 
221  TLOG(TLVL_DEBUG) << "shutdown: Complete";
222  TLOG((verbose_ ? TLVL_INFO : TLVL_DEBUG)) << "Completed Shutdown transition";
223  return endSucceeded;
224 }
225 
226 bool artdaq::DataReceiverCore::soft_initialize(fhicl::ParameterSet const& pset)
227 {
228  TLOG(TLVL_DEBUG) << "soft_initialize method called with DAQ "
229  << "ParameterSet = \"" << pset.to_string()
230  << "\".";
231  return true;
232 }
233 
234 bool artdaq::DataReceiverCore::reinitialize(fhicl::ParameterSet const& pset)
235 {
236  TLOG(TLVL_DEBUG) << "reinitialize method called with DAQ "
237  << "ParameterSet = \"" << pset.to_string()
238  << "\".";
239  event_store_ptr_ = nullptr;
240  return initialize(pset);
241 }
242 
243 bool artdaq::DataReceiverCore::rollover_subrun(uint64_t boundary, uint32_t subrun)
244 {
245  if (event_store_ptr_)
246  {
247  event_store_ptr_->rolloverSubrun(boundary, subrun);
248  return true;
249  }
250  return false;
251 }
252 
253 std::string artdaq::DataReceiverCore::report(std::string const& which) const
254 {
255  if (which == "incomplete_event_count")
256  {
257  if (event_store_ptr_ != nullptr)
258  {
259  return std::to_string(event_store_ptr_->GetIncompleteEventCount());
260  }
261  else
262  {
263  return "-1";
264  }
265  }
266  if (which == "event_count")
267  {
268  if (receiver_ptr_ != nullptr)
269  return std::to_string(receiver_ptr_->GetReceivedFragmentCount()->count());
270 
271  return "0";
272  }
273 
274  // lots of cool stuff that we can do here
275  // - report on the number of fragments received and the number
276  // of events built (in the current or previous run
277  // - report on the number of incomplete events in the EventStore
278  // (if running)
279  std::string tmpString;
280  if (event_store_ptr_ != nullptr) tmpString.append(app_name + " run number = " + std::to_string(event_store_ptr_->runID()) + ".\n");
281  tmpString.append("Command \"" + which + "\" is not currently supported.");
282  return tmpString;
283 }
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.
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 rollover_subrun(uint64_t eventNum, uint32_t subrun)
Rollover the subrun after the given event.
Receives Fragment objects from one or more DataSenderManager instances using TransferInterface plugin...
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.