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