artdaq  v3_02_00
CompositeDriver_generator.cc
1 #define TRACE_NAME "CompositeDriver"
2 
3 #include "artdaq/Application/CompositeDriver.hh"
4 
5 #include "artdaq/Application/GeneratorMacros.hh"
6 #include "artdaq/Application/makeCommandableFragmentGenerator.hh"
7 #include "canvas/Utilities/Exception.h"
8 #include "cetlib_except/exception.h"
9 #include <boost/algorithm/string.hpp>
10 
11 using fhicl::ParameterSet;
12 
15 {
16  std::vector<ParameterSet> psetList =
17  ps.get<std::vector<ParameterSet>>("generator_config_list");
18  for (auto pset : psetList)
19  {
20  if (! makeChildGenerator_(pset))
21  {
22  throw cet::exception("CompositeDriver")
23  << "Unable to create child generator for PSet= \""
24  << pset.to_string() << "\"";
25  }
26  }
27 
28  std::string compositeMetricName;
29  for (auto& generator : generator_list_)
30  {
31  if (compositeMetricName.length() > 0) { compositeMetricName.append(", "); }
32  compositeMetricName.append(generator->metricsReportingInstanceName());
33  }
34  this->metricsReportingInstanceName(compositeMetricName);
35 }
36 
38 {
39  // 15-Feb-2014, KAB - explicitly destruct the generators so that
40  // we can control the order in which they are destructed
41  size_t listSize = generator_list_.size();
42  while (listSize > 0)
43  {
44  --listSize;
45  try
46  {
47  generator_list_.resize(listSize);
48  }
49  catch (...)
50  {
51  TLOG(TLVL_ERROR)
52  << "Unknown exception when destructing the generator at index "
53  << (listSize + 1) ;
54  }
55  }
56 }
57 
59 {
60  for (size_t idx = 0; idx < generator_active_list_.size(); ++idx)
61  {
62  generator_active_list_[idx] = true;
63  }
64  for (auto& generator : generator_list_)
65  {
66  generator->StartCmd(run_number(), timeout(), timestamp());
67  }
68 }
69 
71 {
72  std::vector<std::unique_ptr<CommandableFragmentGenerator>>::reverse_iterator riter;
73  for (riter = generator_list_.rbegin(); riter != generator_list_.rend(); ++riter)
74  {
75  (*riter)->StopCmd(timeout(), timestamp());
76  }
77 }
78 
80 {
81  // 02/17/16 ELF: This logic is now handled in stopNoMutex
82  /*
83  std::vector<std::unique_ptr<CommandableFragmentGenerator>>::reverse_iterator riter;
84  for (riter = generator_list_.rbegin(); riter != generator_list_.rend(); ++riter) {
85  (*riter)->StopCmd( timeout(), timestamp() );
86  }
87  */
88 }
89 
91 {
92  std::vector<std::unique_ptr<CommandableFragmentGenerator>>::reverse_iterator riter;
93  for (riter = generator_list_.rbegin(); riter != generator_list_.rend(); ++riter)
94  {
95  (*riter)->PauseCmd(timeout(), timestamp());
96  }
97 }
98 
100 {
101  for (size_t idx = 0; idx < generator_active_list_.size(); ++idx)
102  {
103  generator_active_list_[idx] = true;
104  }
105  for (auto& generator : generator_list_)
106  {
107  generator->ResumeCmd(timeout(), timestamp());
108  }
109 }
110 
111 std::vector<artdaq::Fragment::fragment_id_t> artdaq::CompositeDriver::fragmentIDs()
112 {
113  std::vector<artdaq::Fragment::fragment_id_t> workList;
114  for (size_t idx = 0; idx < generator_list_.size(); ++idx)
115  {
116  std::vector<artdaq::Fragment::fragment_id_t> tempList =
117  generator_list_[idx]->fragmentIDs();
118  workList.insert(workList.end(), tempList.begin(), tempList.end());
119  }
120  return workList;
121 }
122 
123 bool artdaq::CompositeDriver::getNext_(artdaq::FragmentPtrs& frags)
124 {
125  bool anyGeneratorIsActive = false;
126  for (size_t idx = 0; idx < generator_list_.size(); ++idx)
127  {
128  if (generator_active_list_[idx])
129  {
130  bool status = generator_list_[idx]->getNext(frags);
131 
132  // 08-May-2015, KAB & JCF: if the generator getNext() method returns
133  // false (which indicates that the data flow has stopped) *and* the
134  // reason that it has stopped is because there was an exception that
135  // wasn't handled by the experiment-specific FragmentGenerator class,
136  // we throw an exception so that the process will move to the
137  // InRunError state. We do our best to try to reproduce the original
138  // exception message.
139  if (! status && generator_list_[idx]->exception())
140  {
141  std::string reportString =
142  generator_list_[idx]->ReportCmd("latest_exception");
143  if (std::string::npos !=
144  boost::algorithm::to_lower_copy(reportString).find("exception"))
145  {
146  throw cet::exception("CompositeDriver_generator")
147  << "The FragmentGenerator for "
148  << generator_list_[idx]->metricsReportingInstanceName()
149  << " threw an exception: " << reportString;
150  }
151  else
152  {
153  throw cet::exception("CompositeDriver_generator")
154  << "The FragmentGenerator for "
155  << generator_list_[idx]->metricsReportingInstanceName()
156  << " threw an exception.";
157  }
158  }
159  generator_active_list_[idx] = status;
160  if (status) { anyGeneratorIsActive = true; }
161  }
162  }
163  return anyGeneratorIsActive;
164 }
165 
166 bool artdaq::CompositeDriver::makeChildGenerator_(fhicl::ParameterSet const& pset)
167 {
168  // pull out the relevant parts of the ParameterSet
169  fhicl::ParameterSet daq_pset;
170  try
171  {
172  daq_pset = pset.get<fhicl::ParameterSet>("daq");
173  }
174  catch (...)
175  {
176  TLOG(TLVL_ERROR)
177  << "Unable to find the DAQ parameters in the initialization "
178  << "ParameterSet: \"" + pset.to_string() + "\"." ;
179  return false;
180  }
181  fhicl::ParameterSet fr_pset;
182  try
183  {
184  fr_pset = daq_pset.get<fhicl::ParameterSet>("fragment_receiver");
185  }
186  catch (...)
187  {
188  TLOG(TLVL_ERROR)
189  << "Unable to find the fragment_receiver parameters in the DAQ "
190  << "initialization ParameterSet: \"" + daq_pset.to_string() + "\"." ;
191  return false;
192  }
193 
194  // create the requested FragmentGenerator
195  std::string frag_gen_name = fr_pset.get<std::string>("generator", "");
196  if (frag_gen_name.length() == 0)
197  {
198  TLOG(TLVL_ERROR)
199  << "No fragment generator (parameter name = \"generator\") was "
200  << "specified in the fragment_receiver ParameterSet. The "
201  << "DAQ initialization PSet was \"" << daq_pset.to_string() << "\"." ;
202  return false;
203  }
204 
205  std::unique_ptr<artdaq::CommandableFragmentGenerator> tmp_gen_ptr;
206  try
207  {
208  tmp_gen_ptr = artdaq::makeCommandableFragmentGenerator(frag_gen_name, fr_pset);
209  }
210  catch (art::Exception& excpt)
211  {
212  TLOG(TLVL_ERROR)
213  << "Exception creating a FragmentGenerator of type \""
214  << frag_gen_name << "\" with parameter set \"" << fr_pset.to_string()
215  << "\", exception = " << excpt ;
216  return false;
217  }
218  catch (cet::exception& excpt)
219  {
220  TLOG(TLVL_ERROR)
221  << "Exception creating a FragmentGenerator of type \""
222  << frag_gen_name << "\" with parameter set \"" << fr_pset.to_string()
223  << "\", exception = " << excpt ;
224  return false;
225  }
226  catch (...)
227  {
228  TLOG(TLVL_ERROR)
229  << "Unknown exception creating a FragmentGenerator of type \""
230  << frag_gen_name << "\" with parameter set \"" << fr_pset.to_string()
231  << "\"." ;
232  return false;
233  }
234 
235  std::unique_ptr<CommandableFragmentGenerator> generator_ptr;
236  generator_ptr.reset(nullptr);
237  try
238  {
239  CommandableFragmentGenerator* tmp_cmdablegen_bareptr =
240  dynamic_cast<CommandableFragmentGenerator*>(tmp_gen_ptr.get());
241  if (tmp_cmdablegen_bareptr)
242  {
243  tmp_gen_ptr.release();
244  generator_ptr.reset(tmp_cmdablegen_bareptr);
245  }
246  }
247  catch (...) {}
248  if (! generator_ptr)
249  {
250  TLOG(TLVL_ERROR)
251  << "Error: The requested fragment generator type (" << frag_gen_name
252  << ") is not a CommandableFragmentGenerator, and only "
253  << "CommandableFragmentGenerators are currently supported." ;
254  return false;
255  }
256 
257  generator_list_.push_back(std::move(generator_ptr));
258  generator_active_list_.push_back(true);
259  return true;
260 }
261 
262 DEFINE_ARTDAQ_COMMANDABLE_GENERATOR(artdaq::CompositeDriver)
void start() override
Start all configured CommandableFragmentGenerators.
virtual ~CompositeDriver() noexcept
Destructor. Calls the destructors for each configured CommandableFragmentGenerator.
CompositeDriver handles a set of lower-level generators.
void pause() override
Pause all configured CommandableFragmentGenerators.
std::unique_ptr< CommandableFragmentGenerator > makeCommandableFragmentGenerator(std::string const &generator_plugin_spec, fhicl::ParameterSet const &ps)
Load a CommandableFragmentGenerator plugin.
virtual std::string metricsReportingInstanceName() const
Get the name used when reporting metrics.
void stop() override
Call stop methods for all configured CommandableFragmentGenerators. Currently handled by stopNoMutex...
CommandableFragmentGenerator is a FragmentGenerator-derived abstract class that defines the interface...
CompositeDriver(fhicl::ParameterSet const &ps)
CompositeDriver Constructor.
void resume() override
Resume all configured CommandableFragmentGenerators.
void stopNoMutex() override
Call non-locked stop methods for all configured CommandableFragmentGenerators.