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