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