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