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