artdaq  v3_09_04
DispatcherCore.cc
1 #include <bitset>
2 #include <cerrno>
3 #include <iomanip>
4 #include <sstream>
5 
6 #include <csignal>
7 
8 #include <boost/algorithm/string.hpp>
9 #include <boost/exception/all.hpp>
10 #include <boost/filesystem.hpp>
11 #include <boost/throw_exception.hpp>
12 #include <boost/tokenizer.hpp>
13 #include <utility>
14 
15 #include "fhiclcpp/ParameterSet.h"
16 
17 #include "artdaq/DAQdata/Globals.hh" // include these 2 first -
18 #define TRACE_NAME (app_name + "_DispatcherCore").c_str()
19 
20 #include "artdaq-core/Data/RawEvent.hh"
21 
22 #include "artdaq/Application/DispatcherCore.hh"
23 #include "artdaq/TransferPlugins/MakeTransferPlugin.hh"
24 
25 bool artdaq::DispatcherCore::initialize(fhicl::ParameterSet const& pset)
26 {
27  TLOG(TLVL_DEBUG) << "initialize method called with DAQ "
28  << "ParameterSet = \"" << pset.to_string() << "\".";
29 
30  pset_ = pset;
31  // 04-Apr-2019, KAB: added support for art config params to be in an "art" block
32  if (pset_.has_key("art"))
33  {
34  pset_ = pset_.get<fhicl::ParameterSet>("art");
35  }
36  pset_.erase("outputs");
37  pset_.erase("physics");
38  pset_.erase("daq");
39 
40  TLOG(TLVL_DEBUG) << "Pieces of the input pset that are saved for later: \"" << pset_.to_string() << "\".";
41 
42  // pull out the relevant parts of the ParameterSet
43  fhicl::ParameterSet daq_pset;
44  try
45  {
46  daq_pset = pset.get<fhicl::ParameterSet>("daq");
47  }
48  catch (...)
49  {
50  TLOG(TLVL_ERROR)
51  << "Unable to find the DAQ parameters in the initialization "
52  << "ParameterSet: \"" + pset.to_string() + "\".";
53  return false;
54  }
55  fhicl::ParameterSet agg_pset;
56  try
57  {
58  agg_pset = daq_pset.get<fhicl::ParameterSet>("dispatcher", daq_pset.get<fhicl::ParameterSet>("aggregator"));
59  }
60  catch (...)
61  {
62  TLOG(TLVL_ERROR)
63  << "Unable to find the Dispatcher parameters in the DAQ "
64  << "initialization ParameterSet: \"" + daq_pset.to_string() + "\".";
65  return false;
66  }
67 
68  broadcast_mode_ = agg_pset.get<bool>("broadcast_mode", true);
69  if (broadcast_mode_ && !agg_pset.has_key("broadcast_mode"))
70  {
71  agg_pset.put<bool>("broadcast_mode", true);
72  if (!agg_pset.has_key("non_reliable_mode"))
73  {
74  agg_pset.put<bool>("non_reliable_mode", true);
75  }
76  if (!agg_pset.has_key("non_reliable_mode_retry_count"))
77  {
78  agg_pset.put<int>("non_reliable_mode_retry_count", 2);
79  }
80  }
81 
82  agg_pset.erase("restart_crashed_art_processes");
83  agg_pset.put<bool>("restart_crashed_art_processes", false);
84 
85  agg_pset.erase("art_analyzer_count");
86  agg_pset.put<int>("art_analyzer_count", 0);
87 
88  // initialize the MetricManager and the names of our metrics
89  fhicl::ParameterSet metric_pset;
90 
91  try
92  {
93  metric_pset = daq_pset.get<fhicl::ParameterSet>("metrics");
94  }
95  catch (...)
96  {} // OK if there's no metrics table defined in the FHiCL
97 
98  return initializeDataReceiver(pset, agg_pset, metric_pset);
99 }
100 
101 std::string artdaq::DispatcherCore::register_monitor(fhicl::ParameterSet const& pset)
102 {
103  TLOG(TLVL_DEBUG) << "DispatcherCore::register_monitor called with argument \"" << pset.to_string() << "\"";
104  check_filters_();
105 
106  try
107  {
108  TLOG(TLVL_DEBUG) << "Getting unique_label from input ParameterSet";
109  auto const& label = pset.get<std::string>("unique_label");
110  TLOG(TLVL_DEBUG) << "Unique label is " << label;
111  {
112  std::lock_guard<std::mutex> lock(dispatcher_transfers_mutex_);
113  if (registered_monitors_.count(label) != 0u)
114  {
115  throw cet::exception("DispatcherCore") << "Unique label already exists!"; // NOLINT(cert-err60-cpp)
116  }
117 
118  registered_monitors_[label] = pset;
119  }
120 
121  // ELF, Jul 21, 2020: This can take a long time, and we don't want to block the XMLRPC thread
122  boost::thread thread([=] { start_art_process_(label); });
123  thread.detach();
124  }
125  catch (const cet::exception& e)
126  {
127  std::stringstream errmsg;
128  errmsg << "Unable to create a Transfer plugin with the FHiCL code \"" << pset.to_string() << "\", a new monitor has not been registered" << std::endl;
129  errmsg << "Exception: " << e.what();
130  TLOG(TLVL_ERROR) << errmsg.str();
131  return errmsg.str();
132  }
133  catch (const boost::exception& e)
134  {
135  std::stringstream errmsg;
136  errmsg << "Unable to create a Transfer plugin with the FHiCL code \"" << pset.to_string() << "\", a new monitor has not been registered" << std::endl;
137  errmsg << "Exception: " << boost::diagnostic_information(e);
138  TLOG(TLVL_ERROR) << errmsg.str();
139  return errmsg.str();
140  }
141  catch (const std::exception& e)
142  {
143  std::stringstream errmsg;
144  errmsg << "Unable to create a Transfer plugin with the FHiCL code \"" << pset.to_string() << "\", a new monitor has not been registered" << std::endl;
145  errmsg << "Exception: " << e.what();
146  TLOG(TLVL_ERROR) << errmsg.str();
147  return errmsg.str();
148  }
149  catch (...)
150  {
151  std::stringstream errmsg;
152  errmsg << "Unable to create a Transfer plugin with the FHiCL code \"" << pset.to_string() << "\", a new monitor has not been registered";
153  TLOG(TLVL_ERROR) << errmsg.str();
154  return errmsg.str();
155  }
156 
157  TLOG(TLVL_DEBUG) << "Successfully registered monitor";
158  return "Success";
159 }
160 
161 std::string artdaq::DispatcherCore::unregister_monitor(std::string const& label)
162 {
163  TLOG(TLVL_DEBUG) << "DispatcherCore::unregister_monitor called with argument \"" << label << "\"";
164  check_filters_();
165 
166  try
167  {
168  {
169  std::lock_guard<std::mutex> lock(dispatcher_transfers_mutex_);
170  if (registered_monitors_.count(label) == 0)
171  {
172  std::stringstream errmsg;
173  errmsg << "Warning in DispatcherCore::unregister_monitor: unable to find requested transfer plugin with "
174  << "label \"" << label << "\"";
175  TLOG(TLVL_WARNING) << errmsg.str();
176  return errmsg.str();
177  }
178 
179  registered_monitors_.erase(label);
180  }
181 
182  // ELF, Jul 21, 2020: This can take a long time, and we don't want to block the XMLRPC thread
183  boost::thread thread([=] { stop_art_process_(label); });
184  thread.detach();
185  }
186  catch (...)
187  {
188  std::stringstream errmsg;
189  errmsg << "Unable to unregister transfer plugin with label \"" << label << "\"";
190  TLOG(TLVL_ERROR) << errmsg.str();
191  return errmsg.str();
192  }
193 
194  TLOG(TLVL_DEBUG) << "unregister_monitor completed successfully";
195  return "Success";
196 }
197 
198 fhicl::ParameterSet artdaq::DispatcherCore::merge_parameter_sets_(fhicl::ParameterSet const& skel, const std::string& label, const fhicl::ParameterSet& pset)
199 {
200  fhicl::ParameterSet generated_pset(skel);
201  fhicl::ParameterSet generated_outputs;
202  fhicl::ParameterSet generated_physics;
203  fhicl::ParameterSet generated_physics_analyzers;
204  fhicl::ParameterSet generated_physics_producers;
205  fhicl::ParameterSet generated_physics_filters;
206  std::unordered_map<std::string, std::vector<std::string>> generated_physics_filter_paths;
207 
208  TLOG(TLVL_DEBUG) << "merge_parameter_sets_: Generating fhicl for monitor " << label;
209 
210  try
211  {
212  auto path = pset.get<std::vector<std::string>>("path");
213 
214  auto filters = pset.get<std::vector<fhicl::ParameterSet>>("filter_paths", std::vector<fhicl::ParameterSet>());
215  for (auto& filter : filters)
216  {
217  try
218  {
219  auto name = filter.get<std::string>("name");
220  auto path = filter.get<std::vector<std::string>>("path");
221  if (generated_physics_filter_paths.count(name) != 0u)
222  {
223  bool matched = generated_physics_filter_paths[name].size() == path.size();
224  for (size_t ii = 0; matched && ii < generated_physics_filter_paths[name].size(); ++ii)
225  {
226  matched = matched && path[ii] == generated_physics_filter_paths[name][ii];
227  }
228 
229  if (matched)
230  {
231  // Path is already configured
232  continue;
233  }
234 
235  auto newname = label + name;
236  generated_physics_filter_paths[newname] = path;
237  }
238  else
239  {
240  generated_physics_filter_paths[name] = path;
241  }
242  }
243  catch (...)
244  {
245  }
246  }
247 
248  // outputs section
249  auto outputs = pset.get<fhicl::ParameterSet>("outputs");
250  if (outputs.get_pset_names().size() > 1 || outputs.get_pset_names().empty())
251  {
252  // Only one output allowed per monitor
253  }
254  auto output_name = outputs.get_pset_names()[0];
255  auto output_pset = outputs.get<fhicl::ParameterSet>(output_name);
256  generated_outputs.put(label + output_name, output_pset);
257  bool outputInPath = false;
258  for (auto& ii : path)
259  {
260  if (ii == output_name)
261  {
262  ii = label + output_name;
263  outputInPath = true;
264  }
265  }
266  if (!outputInPath)
267  {
268  path.push_back(label + output_name);
269  }
270 
271  //physics section
272  auto physics_pset = pset.get<fhicl::ParameterSet>("physics");
273 
274  if (physics_pset.has_key("analyzers"))
275  {
276  auto analyzers = physics_pset.get<fhicl::ParameterSet>("analyzers");
277  for (const auto& key : analyzers.get_pset_names())
278  {
279  if (generated_physics_analyzers.has_key(key) && analyzers.get<fhicl::ParameterSet>(key) == generated_physics_analyzers.get<fhicl::ParameterSet>(key))
280  {
281  // Module is already configured
282  continue;
283  }
284  if (generated_physics_analyzers.has_key(key))
285  {
286  // Module already exists with name, rename
287  auto newkey = label + key;
288  generated_physics_analyzers.put<fhicl::ParameterSet>(newkey, analyzers.get<fhicl::ParameterSet>(key));
289  for (auto& ii : path)
290  {
291  if (ii == key)
292  {
293  ii = newkey;
294  }
295  }
296  }
297  else
298  {
299  generated_physics_analyzers.put<fhicl::ParameterSet>(key, analyzers.get<fhicl::ParameterSet>(key));
300  }
301  }
302  }
303  if (physics_pset.has_key("producers"))
304  {
305  auto producers = physics_pset.get<fhicl::ParameterSet>("producers");
306  for (const auto& key : producers.get_pset_names())
307  {
308  if (generated_physics_producers.has_key(key) && producers.get<fhicl::ParameterSet>(key) == generated_physics_producers.get<fhicl::ParameterSet>(key))
309  {
310  // Module is already configured
311  continue;
312  }
313  if (generated_physics_producers.has_key(key))
314  {
315  // Module already exists with name, rename
316  auto newkey = label + key;
317  generated_physics_producers.put<fhicl::ParameterSet>(newkey, producers.get<fhicl::ParameterSet>(key));
318  for (auto& ii : path)
319  {
320  if (ii == key)
321  {
322  ii = newkey;
323  }
324  }
325  }
326  else
327  {
328  generated_physics_producers.put<fhicl::ParameterSet>(key, producers.get<fhicl::ParameterSet>(key));
329  }
330  }
331  }
332  if (physics_pset.has_key("filters"))
333  {
334  auto filters = physics_pset.get<fhicl::ParameterSet>("filters");
335  for (const auto& key : filters.get_pset_names())
336  {
337  if (generated_physics_filters.has_key(key) && filters.get<fhicl::ParameterSet>(key) == generated_physics_filters.get<fhicl::ParameterSet>(key))
338  {
339  // Module is already configured
340  continue;
341  }
342  if (generated_physics_filters.has_key(key))
343  {
344  // Module already exists with name, rename
345  auto newkey = label + key;
346  generated_physics_filters.put<fhicl::ParameterSet>(newkey, filters.get<fhicl::ParameterSet>(key));
347  for (auto& ii : path)
348  {
349  if (ii == key)
350  {
351  ii = newkey;
352  }
353  }
354  }
355  else
356  {
357  generated_physics_filters.put<fhicl::ParameterSet>(key, filters.get<fhicl::ParameterSet>(key));
358  }
359  }
360  }
361  generated_physics.put<std::vector<std::string>>(label, path);
362  }
363  catch (cet::exception& e)
364  {
365  // Error in parsing input fhicl
366  TLOG(TLVL_ERROR) << "merge_parameter_sets_: Error processing input fhicl: " << e.what();
367  }
368 
369  TLOG(TLVL_DEBUG) << "merge_parameter_sets_: Building final ParameterSet";
370  generated_pset.put("outputs", generated_outputs);
371 
372  generated_physics.put("analyzers", generated_physics_analyzers);
373  generated_physics.put("producers", generated_physics_producers);
374  generated_physics.put("filters", generated_physics_filters);
375 
376  for (auto& path : generated_physics_filter_paths)
377  {
378  generated_physics.put(path.first, path.second);
379  }
380 
381  generated_pset.put("physics", generated_physics);
382 
383  return generated_pset;
384 }
385 
386 fhicl::ParameterSet artdaq::DispatcherCore::generate_filter_fhicl_()
387 {
388  TLOG(TLVL_DEBUG) << "generate_filter_fhicl_ BEGIN";
389  std::lock_guard<std::mutex> lock(dispatcher_transfers_mutex_);
390  fhicl::ParameterSet generated_pset = pset_;
391 
392  for (auto& monitor : registered_monitors_)
393  {
394  auto label = monitor.first;
395  auto pset = monitor.second;
396  generated_pset = merge_parameter_sets_(generated_pset, label, pset);
397  }
398 
399  TLOG(TLVL_DEBUG) << "generate_filter_fhicl_ returning ParameterSet: " << generated_pset.to_string();
400  return generated_pset;
401 }
402 
403 void artdaq::DispatcherCore::check_filters_()
404 {
405  std::lock_guard<std::mutex> lock(dispatcher_transfers_mutex_);
406  auto it = registered_monitors_.begin();
407  while (it != registered_monitors_.end())
408  {
409  if (registered_monitor_pids_.count(it->first) != 0u)
410  {
411  if (!event_store_ptr_)
412  {
413  registered_monitor_pids_.erase(it->first);
414  }
415  else
416  {
417  auto pid = registered_monitor_pids_[it->first];
418  auto sts = kill(pid, 0);
419  if (sts < 0)
420  {
421  registered_monitor_pids_.erase(it->first);
422  }
423  }
424  }
425  ++it;
426  }
427 }
428 
429 void artdaq::DispatcherCore::start_art_process_(std::string const& label)
430 {
431  if (event_store_ptr_ != nullptr)
432  {
433  if (broadcast_mode_)
434  {
435  fhicl::ParameterSet pset;
436  {
437  std::lock_guard<std::mutex> lock(dispatcher_transfers_mutex_);
438  pset = registered_monitors_[label];
439  }
440  fhicl::ParameterSet ps = merge_parameter_sets_(pset_, label, pset);
441  TLOG(TLVL_DEBUG) << "Starting art process with received fhicl";
442  auto pid = event_store_ptr_->StartArtProcess(ps);
443  {
444  std::lock_guard<std::mutex> lock(dispatcher_transfers_mutex_);
445  registered_monitor_pids_[label] = pid;
446  }
447  }
448  else
449  {
450  TLOG(TLVL_DEBUG) << "Calling ReconfigureArt";
451  fhicl::ParameterSet generated_fhicl;
452  {
453  std::lock_guard<std::mutex> lock(dispatcher_transfers_mutex_);
454  generated_fhicl = generate_filter_fhicl_();
455  }
456  event_store_ptr_->ReconfigureArt(generated_fhicl);
457  TLOG(TLVL_DEBUG) << "Done with ReconfigureArt";
458  }
459  }
460  else
461  {
462  TLOG(TLVL_ERROR) << "Unable to add monitor as there is no SharedMemoryEventManager instance!";
463  }
464 }
465 
466 void artdaq::DispatcherCore::stop_art_process_(std::string const& label)
467 {
468  if (event_store_ptr_ != nullptr)
469  {
470  if (broadcast_mode_)
471  {
472  if (registered_monitor_pids_.count(label) != 0u)
473  {
474  std::set<pid_t> pids;
475  {
476  std::lock_guard<std::mutex> lock(dispatcher_transfers_mutex_);
477  pids.insert(registered_monitor_pids_[label]);
478  registered_monitor_pids_.erase(label);
479  }
480  TLOG(TLVL_DEBUG) << "Calling ShutdownArtProcesses";
481  event_store_ptr_->ShutdownArtProcesses(pids);
482  TLOG(TLVL_DEBUG) << "Done with ShutdownArtProcesses";
483  }
484  }
485  else
486  {
487  TLOG(TLVL_DEBUG) << "Calling ReconfigureArt";
488  fhicl::ParameterSet generated_fhicl;
489  {
490  std::lock_guard<std::mutex> lock(dispatcher_transfers_mutex_);
491  generated_fhicl = generate_filter_fhicl_();
492  }
493  event_store_ptr_->ReconfigureArt(generated_fhicl);
494  TLOG(TLVL_DEBUG) << "Done with ReconfigureArt";
495  }
496  }
497 }
std::string unregister_monitor(std::string const &label)
Delete the TransferInterface having the given unique label.
std::string register_monitor(fhicl::ParameterSet const &pset)
Create a new TransferInterface instance using the given configuration.
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 initialize(fhicl::ParameterSet const &pset) override
Processes the initialize request.