artdaq  v3_07_01
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("art_analyzer_count");
84  agg_pset.put<int>("art_analyzer_count", 0);
85 
86  // initialize the MetricManager and the names of our metrics
87  fhicl::ParameterSet metric_pset;
88 
89  try
90  {
91  metric_pset = daq_pset.get<fhicl::ParameterSet>("metrics");
92  }
93  catch (...)
94  {} // OK if there's no metrics table defined in the FHiCL
95 
96  return initializeDataReceiver(pset, agg_pset, metric_pset);
97 }
98 
99 std::string artdaq::DispatcherCore::register_monitor(fhicl::ParameterSet const& pset)
100 {
101  TLOG(TLVL_DEBUG) << "DispatcherCore::register_monitor called with argument \"" << pset.to_string() << "\"";
102  std::lock_guard<std::mutex> lock(dispatcher_transfers_mutex_);
103  check_filters_();
104 
105  try
106  {
107  TLOG(TLVL_DEBUG) << "Getting unique_label from input ParameterSet";
108  auto label = pset.get<std::string>("unique_label");
109  TLOG(TLVL_DEBUG) << "Unique label is " << label;
110  if (registered_monitors_.count(label))
111  {
112  throw cet::exception("DispatcherCore") << "Unique label already exists!";
113  }
114 
115  registered_monitors_[label] = pset;
116  if (event_store_ptr_ != nullptr)
117  {
118  if (broadcast_mode_)
119  {
120  fhicl::ParameterSet ps = merge_parameter_sets_(pset_, label, pset);
121  TLOG(TLVL_DEBUG) << "Starting art process with received fhicl";
122  registered_monitor_pids_[label] = event_store_ptr_->StartArtProcess(ps);
123  }
124  else
125  {
126  TLOG(TLVL_DEBUG) << "Generating new fhicl and reconfiguring art";
127  event_store_ptr_->ReconfigureArt(generate_filter_fhicl_());
128  }
129  }
130  else
131  {
132  TLOG(TLVL_ERROR) << "Unable to add monitor as there is no SharedMemoryEventManager instance!";
133  }
134  }
135  catch (const cet::exception& e)
136  {
137  std::stringstream errmsg;
138  errmsg << "Unable to create a Transfer plugin with the FHiCL code \"" << pset.to_string() << "\", a new monitor has not been registered" << std::endl;
139  errmsg << "Exception: " << e.what();
140  TLOG(TLVL_ERROR) << errmsg.str();
141  return errmsg.str();
142  }
143  catch (const boost::exception& e)
144  {
145  std::stringstream errmsg;
146  errmsg << "Unable to create a Transfer plugin with the FHiCL code \"" << pset.to_string() << "\", a new monitor has not been registered" << std::endl;
147  errmsg << "Exception: " << boost::diagnostic_information(e);
148  TLOG(TLVL_ERROR) << errmsg.str();
149  return errmsg.str();
150  }
151  catch (const std::exception& e)
152  {
153  std::stringstream errmsg;
154  errmsg << "Unable to create a Transfer plugin with the FHiCL code \"" << pset.to_string() << "\", a new monitor has not been registered" << std::endl;
155  errmsg << "Exception: " << e.what();
156  TLOG(TLVL_ERROR) << errmsg.str();
157  return errmsg.str();
158  }
159  catch (...)
160  {
161  std::stringstream errmsg;
162  errmsg << "Unable to create a Transfer plugin with the FHiCL code \"" << pset.to_string() << "\", a new monitor has not been registered";
163  TLOG(TLVL_ERROR) << errmsg.str();
164  return errmsg.str();
165  }
166 
167  return "Success";
168 }
169 
170 std::string artdaq::DispatcherCore::unregister_monitor(std::string const& label)
171 {
172  TLOG(TLVL_DEBUG) << "DispatcherCore::unregister_monitor called with argument \"" << label << "\"";
173  std::lock_guard<std::mutex> lock(dispatcher_transfers_mutex_);
174  check_filters_();
175 
176  try
177  {
178  if (registered_monitors_.count(label) == 0)
179  {
180  std::stringstream errmsg;
181  errmsg << "Warning in DispatcherCore::unregister_monitor: unable to find requested transfer plugin with "
182  << "label \"" << label << "\"";
183  TLOG(TLVL_WARNING) << errmsg.str();
184  return errmsg.str();
185  }
186 
187  registered_monitors_.erase(label);
188  if (event_store_ptr_ != nullptr)
189  {
190  if (broadcast_mode_)
191  {
192  std::set<pid_t> pids;
193  pids.insert(registered_monitor_pids_[label]);
194  event_store_ptr_->ShutdownArtProcesses(pids);
195  registered_monitor_pids_.erase(label);
196  }
197  else
198  {
199  event_store_ptr_->ReconfigureArt(generate_filter_fhicl_());
200  }
201  }
202  }
203  catch (...)
204  {
205  std::stringstream errmsg;
206  errmsg << "Unable to unregister transfer plugin with label \"" << label << "\"";
207  return errmsg.str();
208  }
209 
210  return "Success";
211 }
212 
213 fhicl::ParameterSet artdaq::DispatcherCore::merge_parameter_sets_(fhicl::ParameterSet skel, std::string label, fhicl::ParameterSet pset)
214 {
215  fhicl::ParameterSet generated_pset = skel;
216  fhicl::ParameterSet generated_outputs;
217  fhicl::ParameterSet generated_physics;
218  fhicl::ParameterSet generated_physics_analyzers;
219  fhicl::ParameterSet generated_physics_producers;
220  fhicl::ParameterSet generated_physics_filters;
221  std::unordered_map<std::string, std::vector<std::string>> generated_physics_filter_paths;
222 
223  TLOG(TLVL_DEBUG) << "merge_parameter_sets_: Generating fhicl for monitor " << label;
224 
225  try
226  {
227  auto path = pset.get<std::vector<std::string>>("path");
228 
229  auto filters = pset.get<std::vector<fhicl::ParameterSet>>("filter_paths", std::vector<fhicl::ParameterSet>());
230  for (auto& filter : filters)
231  {
232  try
233  {
234  auto name = filter.get<std::string>("name");
235  auto path = filter.get<std::vector<std::string>>("path");
236  if (generated_physics_filter_paths.count(name))
237  {
238  bool matched = generated_physics_filter_paths[name].size() == path.size();
239  for (size_t ii = 0; matched && ii < generated_physics_filter_paths[name].size(); ++ii)
240  {
241  matched = matched && path[ii] == generated_physics_filter_paths[name][ii];
242  }
243 
244  if (matched)
245  {
246  // Path is already configured
247  continue;
248  }
249  else
250  {
251  auto newname = label + name;
252  generated_physics_filter_paths[newname] = path;
253  }
254  }
255  else
256  {
257  generated_physics_filter_paths[name] = path;
258  }
259  }
260  catch (...)
261  {
262  }
263  }
264 
265  // outputs section
266  auto outputs = pset.get<fhicl::ParameterSet>("outputs");
267  if (outputs.get_pset_names().size() > 1 || outputs.get_pset_names().size() == 0)
268  {
269  // Only one output allowed per monitor
270  }
271  auto output_name = outputs.get_pset_names()[0];
272  auto output_pset = outputs.get<fhicl::ParameterSet>(output_name);
273  generated_outputs.put(label + output_name, output_pset);
274  bool outputInPath = false;
275  for (size_t ii = 0; ii < path.size(); ++ii)
276  {
277  if (path[ii] == output_name)
278  {
279  path[ii] = label + output_name;
280  outputInPath = true;
281  }
282  }
283  if (!outputInPath)
284  {
285  path.push_back(label + output_name);
286  }
287 
288  //physics section
289  auto physics_pset = pset.get<fhicl::ParameterSet>("physics");
290 
291  if (physics_pset.has_key("analyzers"))
292  {
293  auto analyzers = physics_pset.get<fhicl::ParameterSet>("analyzers");
294  for (auto key : analyzers.get_pset_names())
295  {
296  if (generated_physics_analyzers.has_key(key) && analyzers.get<fhicl::ParameterSet>(key) == generated_physics_analyzers.get<fhicl::ParameterSet>(key))
297  {
298  // Module is already configured
299  continue;
300  }
301  else if (generated_physics_analyzers.has_key(key))
302  {
303  // Module already exists with name, rename
304  auto newkey = label + key;
305  generated_physics_analyzers.put<fhicl::ParameterSet>(newkey, analyzers.get<fhicl::ParameterSet>(key));
306  for (size_t ii = 0; ii < path.size(); ++ii)
307  {
308  if (path[ii] == key)
309  {
310  path[ii] = newkey;
311  }
312  }
313  }
314  else
315  {
316  generated_physics_analyzers.put<fhicl::ParameterSet>(key, analyzers.get<fhicl::ParameterSet>(key));
317  }
318  }
319  }
320  if (physics_pset.has_key("producers"))
321  {
322  auto producers = physics_pset.get<fhicl::ParameterSet>("producers");
323  for (auto key : producers.get_pset_names())
324  {
325  if (generated_physics_producers.has_key(key) && producers.get<fhicl::ParameterSet>(key) == generated_physics_producers.get<fhicl::ParameterSet>(key))
326  {
327  // Module is already configured
328  continue;
329  }
330  else if (generated_physics_producers.has_key(key))
331  {
332  // Module already exists with name, rename
333  auto newkey = label + key;
334  generated_physics_producers.put<fhicl::ParameterSet>(newkey, producers.get<fhicl::ParameterSet>(key));
335  for (size_t ii = 0; ii < path.size(); ++ii)
336  {
337  if (path[ii] == key)
338  {
339  path[ii] = newkey;
340  }
341  }
342  }
343  else
344  {
345  generated_physics_producers.put<fhicl::ParameterSet>(key, producers.get<fhicl::ParameterSet>(key));
346  }
347  }
348  }
349  if (physics_pset.has_key("filters"))
350  {
351  auto filters = physics_pset.get<fhicl::ParameterSet>("filters");
352  for (auto key : filters.get_pset_names())
353  {
354  if (generated_physics_filters.has_key(key) && filters.get<fhicl::ParameterSet>(key) == generated_physics_filters.get<fhicl::ParameterSet>(key))
355  {
356  // Module is already configured
357  continue;
358  }
359  else if (generated_physics_filters.has_key(key))
360  {
361  // Module already exists with name, rename
362  auto newkey = label + key;
363  generated_physics_filters.put<fhicl::ParameterSet>(newkey, filters.get<fhicl::ParameterSet>(key));
364  for (size_t ii = 0; ii < path.size(); ++ii)
365  {
366  if (path[ii] == key)
367  {
368  path[ii] = newkey;
369  }
370  }
371  }
372  else
373  {
374  generated_physics_filters.put<fhicl::ParameterSet>(key, filters.get<fhicl::ParameterSet>(key));
375  }
376  }
377  }
378  generated_physics.put<std::vector<std::string>>(label, path);
379  }
380  catch (cet::exception& e)
381  {
382  // Error in parsing input fhicl
383  TLOG(TLVL_ERROR) << "merge_parameter_sets_: Error processing input fhicl: " << e.what();
384  }
385 
386  TLOG(TLVL_DEBUG) << "merge_parameter_sets_: Building final ParameterSet";
387  generated_pset.put("outputs", generated_outputs);
388 
389  generated_physics.put("analyzers", generated_physics_analyzers);
390  generated_physics.put("producers", generated_physics_producers);
391  generated_physics.put("filters", generated_physics_filters);
392 
393  for (auto& path : generated_physics_filter_paths)
394  {
395  generated_physics.put(path.first, path.second);
396  }
397 
398  generated_pset.put("physics", generated_physics);
399 
400  return generated_pset;
401 }
402 
403 fhicl::ParameterSet artdaq::DispatcherCore::generate_filter_fhicl_()
404 {
405  TLOG(TLVL_DEBUG) << "generate_filter_fhicl_ BEGIN";
406  fhicl::ParameterSet generated_pset = pset_;
407 
408  for (auto& monitor : registered_monitors_)
409  {
410  auto label = monitor.first;
411  auto pset = monitor.second;
412  generated_pset = merge_parameter_sets_(generated_pset, label, pset);
413  }
414 
415  TLOG(TLVL_DEBUG) << "generate_filter_fhicl_ returning ParameterSet: " << generated_pset.to_string();
416  return generated_pset;
417 }
418 
419 void artdaq::DispatcherCore::check_filters_()
420 {
421  auto it = registered_monitors_.begin();
422  while (it != registered_monitors_.end())
423  {
424  if (!event_store_ptr_)
425  {
426  registered_monitor_pids_.erase(it->first);
427  it = registered_monitors_.erase(it);
428  }
429  else
430  {
431  auto pid = registered_monitor_pids_[it->first];
432  auto sts = kill(pid, 0);
433  if (sts < 0)
434  {
435  registered_monitor_pids_.erase(it->first);
436  it = registered_monitors_.erase(it);
437  continue;
438  }
439  }
440  ++it;
441  }
442 }
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.