artdaq  v3_01_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 {
19  TLOG(TLVL_DEBUG) << "Constructor" ;
20  metricMan = &metricMan_;
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 + "." + std::to_string(my_rank));
43  }
44  catch (...)
45  {
46  ExceptionHandler(ExceptionHandlerRethrow::no,
47  "Error loading metrics in DataReceiverCore::initialize()");
48  }
49 
50  fhicl::ParameterSet tmp = pset;
51  tmp.erase("daq");
52 
53  fhicl::ParameterSet data_tmp = data_pset;
54  if (data_pset.has_key("expected_events_per_bunch"))
55  {
56  data_tmp.put<int>("expected_fragments_per_event", data_pset.get<int>("expected_events_per_bunch"));
57  }
58 
59  if (data_pset.has_key("rank"))
60  {
61  if (my_rank >= 0 && data_pset.get<int>("rank") != my_rank) {
62  TLOG(TLVL_WARNING) << "Rank specified at startup is different than rank specified at configure! Using rank received at configure!";
63  }
64  my_rank = data_pset.get<int>("rank");
65  }
66  if (my_rank == -1)
67  {
68  TLOG(TLVL_ERROR) << "Rank not specified at startup or in configuration! Aborting";
69  exit(1);
70  }
71 
72  event_store_ptr_.reset(new SharedMemoryEventManager(data_tmp, tmp));
73 
74  receiver_ptr_.reset(new artdaq::DataReceiverManager(data_tmp, event_store_ptr_));
75 
76  return true;
77 }
78 
80 {
81  logMessage_("Starting run " + boost::lexical_cast<std::string>(id.run()));
82  stop_requested_.store(false);
83  pause_requested_.store(false);
84  run_is_paused_.store(false);
85  metricMan_.do_start();
86  event_store_ptr_->startRun(id.run());
87  receiver_ptr_->start_threads();
88 
89  logMessage_("Completed the Start transition for run " + boost::lexical_cast<std::string>(event_store_ptr_->runID()));
90  return true;
91 }
92 
94 {
95  logMessage_("Stopping run " + boost::lexical_cast<std::string>(event_store_ptr_->runID()) +
96  ", subrun " + boost::lexical_cast<std::string>(event_store_ptr_->subrunID()));
97  bool endSucceeded;
98  int attemptsToEnd;
99  receiver_ptr_->stop_threads();
100 
101  // 21-Jun-2013, KAB - the stop_requested_ variable must be set
102  // before the flush lock so that the processFragments loop will
103  // exit (after the timeout), the lock will be released (in the
104  // processFragments method), and this method can continue.
105  stop_requested_.store(true);
106 
107  if (!run_is_paused_.load())
108  {
109  TLOG(TLVL_DEBUG) << "Ending subrun " << event_store_ptr_->subrunID();
110  endSucceeded = false;
111  attemptsToEnd = 1;
112  endSucceeded = event_store_ptr_->endSubrun();
113  while (!endSucceeded && attemptsToEnd < 3)
114  {
115  ++attemptsToEnd;
116  TLOG(TLVL_DEBUG) << "Retrying EventStore::endSubrun()" ;
117  endSucceeded = event_store_ptr_->endSubrun();
118  }
119  if (!endSucceeded)
120  {
121  TLOG(TLVL_ERROR)
122  << "EventStore::endSubrun in stop method failed after three tries." ;
123  }
124  TLOG(TLVL_DEBUG) << "Done Ending subrun " << event_store_ptr_->subrunID();
125  }
126 
127  TLOG(TLVL_DEBUG) << "Ending run " << event_store_ptr_->runID();
128  endSucceeded = false;
129  attemptsToEnd = 1;
130  endSucceeded = event_store_ptr_->endRun();
131  while (!endSucceeded && attemptsToEnd < 3)
132  {
133  ++attemptsToEnd;
134  TLOG(TLVL_DEBUG) << "Retrying EventStore::endRun()" ;
135  endSucceeded = event_store_ptr_->endRun();
136  }
137  if (!endSucceeded)
138  {
139  TLOG(TLVL_ERROR)
140  << "EventStore::endRun in stop method failed after three tries." ;
141  }
142  TLOG(TLVL_DEBUG) << "Done Ending run " << event_store_ptr_->runID();
143 
144  endSucceeded = false;
145  attemptsToEnd = 1;
146  TLOG(TLVL_DEBUG) << "stop: Calling EventStore::endOfData" ;
147  endSucceeded = event_store_ptr_->endOfData();
148  while (!endSucceeded && attemptsToEnd < 3)
149  {
150  ++attemptsToEnd;
151  TLOG(TLVL_DEBUG) << "Retrying EventStore::endOfData()" ;
152  endSucceeded = event_store_ptr_->endOfData();
153  }
154 
155  run_is_paused_.store(false);
156  logMessage_("Completed the Stop transition for run " + boost::lexical_cast<std::string>(event_store_ptr_->runID()));
157  return true;
158 }
159 
161 {
162  logMessage_("Pausing run " + boost::lexical_cast<std::string>(event_store_ptr_->runID()) +
163  ", subrun " + boost::lexical_cast<std::string>(event_store_ptr_->subrunID()));
164  pause_requested_.store(true);
165 
166  bool endSucceeded = false;
167  int attemptsToEnd = 1;
168  endSucceeded = event_store_ptr_->endSubrun();
169  while (!endSucceeded && attemptsToEnd < 3)
170  {
171  ++attemptsToEnd;
172  TLOG(TLVL_DEBUG) << "Retrying EventStore::endSubrun()" ;
173  endSucceeded = event_store_ptr_->endSubrun();
174  }
175  if (!endSucceeded)
176  {
177  TLOG(TLVL_ERROR)
178  << "EventStore::endSubrun in pause method failed after three tries." ;
179  }
180 
181  run_is_paused_.store(true);
182  logMessage_("Completed the Pause transition for run " + boost::lexical_cast<std::string>(event_store_ptr_->runID()));
183  return true;
184 }
185 
187 {
188  logMessage_("Resuming run " + boost::lexical_cast<std::string>(event_store_ptr_->runID()));
189  pause_requested_.store(false);
190  metricMan_.do_start();
191  event_store_ptr_->startSubrun();
192  run_is_paused_.store(false);
193  logMessage_("Completed the Resume transition for run " + boost::lexical_cast<std::string>(event_store_ptr_->runID()));
194  return true;
195 }
196 
198 {
199  logMessage_("Starting Shutdown transition");
200 
201  /* We don't care about flushing data here. The only way to transition to the
202  shutdown state is from a state where there is no data taking. All we have
203  to do is signal the art input module that we're done taking data so that
204  it can wrap up whatever it needs to do. */
205 
206  TLOG(TLVL_DEBUG) << "shutdown: Shutting down DataReceiverManager" ;
207  receiver_ptr_.reset(nullptr);
208 
209  bool endSucceeded = false;
210  int attemptsToEnd = 1;
211  TLOG(TLVL_DEBUG) << "shutdown: Calling EventStore::endOfData" ;
212  endSucceeded = event_store_ptr_->endOfData();
213  while (!endSucceeded && attemptsToEnd < 3)
214  {
215  ++attemptsToEnd;
216  TLOG(TLVL_DEBUG) << "Retrying EventStore::endOfData()" ;
217  endSucceeded = event_store_ptr_->endOfData();
218  }
219 
220  TLOG(TLVL_DEBUG) << "shutdown: Shutting down SharedMemoryEventManager" ;
221  event_store_ptr_.reset();
222 
223  TLOG(TLVL_DEBUG) << "shutdown: Shutting down MetricManager" ;
224  metricMan_.shutdown();
225 
226  TLOG(TLVL_DEBUG) << "shutdown: Complete" ;
227  logMessage_("Completed Shutdown transition");
228  return endSucceeded;
229 }
230 
231 bool artdaq::DataReceiverCore::soft_initialize(fhicl::ParameterSet const& pset)
232 {
233  TLOG(TLVL_DEBUG) << "soft_initialize method called with DAQ "
234  << "ParameterSet = \"" << pset.to_string()
235  << "\"." ;
236  return true;
237 }
238 
239 bool artdaq::DataReceiverCore::reinitialize(fhicl::ParameterSet const& pset)
240 {
241  TLOG(TLVL_DEBUG) << "reinitialize method called with DAQ "
242  << "ParameterSet = \"" << pset.to_string()
243  << "\"." ;
244  event_store_ptr_ = nullptr;
245  return initialize(pset);
246 }
247 
248 std::string artdaq::DataReceiverCore::report(std::string const& which) const
249 {
250  if (which == "incomplete_event_count")
251  {
252  if (event_store_ptr_ != nullptr)
253  {
254  return boost::lexical_cast<std::string>(event_store_ptr_->GetIncompleteEventCount());
255  }
256  else
257  {
258  return "-1";
259  }
260  }
261  if (which == "event_count")
262  {
263  if (receiver_ptr_ != nullptr)
264  return boost::lexical_cast<std::string>(receiver_ptr_->GetReceivedFragmentCount()->count());
265 
266  return "0";
267  }
268 
269  // lots of cool stuff that we can do here
270  // - report on the number of fragments received and the number
271  // of events built (in the current or previous run
272  // - report on the number of incomplete events in the EventStore
273  // (if running)
274  std::string tmpString;
275  if (event_store_ptr_ != nullptr) tmpString.append(app_name + " run number = " + boost::lexical_cast<std::string>(event_store_ptr_->runID()) + ".\n");
276  tmpString.append("Command \"" + which + "\" is not currently supported.");
277  return tmpString;
278 }
279 
280 void artdaq::DataReceiverCore::logMessage_(std::string const& text)
281 {
282  if (verbose_)
283  {
284  TLOG(TLVL_INFO) << text ;
285  }
286  else
287  {
288  TLOG(TLVL_DEBUG) << text ;
289  }
290 }
MetricManager metricMan_
MetricManager concrete instance (for Globals.hh::metricMan)
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 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.