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