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