artdaq  v3_12_02
CompositeDriver_generator.cc
1 #define TRACE_NAME "CompositeDriver"
2 
3 #include "artdaq/Generators/CommandableFragmentGenerator.hh"
4 #include "artdaq/Generators/GeneratorMacros.hh"
5 #include "artdaq/Generators/makeCommandableFragmentGenerator.hh"
6 #include "canvas/Utilities/Exception.h"
7 #include "cetlib_except/exception.h"
8 
9 #include <boost/algorithm/string.hpp>
10 
11 namespace artdaq {
18 class CompositeDriver : public CommandableFragmentGenerator
19 {
20 public:
31  explicit CompositeDriver(fhicl::ParameterSet const& ps);
32 
36  virtual ~CompositeDriver() noexcept;
37 
41  void start() override;
42 
46  void stopNoMutex() override;
47 
51  void stop() override;
52 
56  void pause() override;
57 
61  void resume() override;
62 
63 private:
64  CompositeDriver(CompositeDriver const&) = delete;
65  CompositeDriver(CompositeDriver&&) = delete;
66  CompositeDriver& operator=(CompositeDriver const&) = delete;
67  CompositeDriver& operator=(CompositeDriver&&) = delete;
68 
69  std::vector<artdaq::Fragment::fragment_id_t> fragmentIDs() override;
70 
71  bool getNext_(artdaq::FragmentPtrs& frags) override;
72 
73  bool makeChildGenerator_(fhicl::ParameterSet const&);
74 
75  std::vector<std::unique_ptr<CommandableFragmentGenerator>> generator_list_;
76  std::vector<bool> generator_active_list_;
77 };
78 } // namespace artdaq
79 artdaq::CompositeDriver::CompositeDriver(const fhicl::ParameterSet& ps)
81 {
82  auto psetList =
83  ps.get<std::vector<fhicl::ParameterSet>>("generator_config_list");
84  for (const auto& pset : psetList)
85  {
86  if (!makeChildGenerator_(pset))
87  {
88  throw cet::exception("CompositeDriver") // NOLINT(cert-err60-cpp)
89  << "Unable to create child generator for PSet= \""
90  << pset.to_string() << "\"";
91  }
92  }
93 
94  std::string compositeMetricName;
95  for (auto& generator : generator_list_)
96  {
97  if (compositeMetricName.length() > 0) { compositeMetricName.append(", "); }
98  compositeMetricName.append(generator->metricsReportingInstanceName());
99  }
100  this->metricsReportingInstanceName(compositeMetricName);
101 }
102 
104 {
105  // 15-Feb-2014, KAB - explicitly destruct the generators so that
106  // we can control the order in which they are destructed
107  size_t listSize = generator_list_.size();
108  while (listSize > 0)
109  {
110  --listSize;
111  try
112  {
113  generator_list_.resize(listSize);
114  }
115  catch (...)
116  {
117  TLOG(TLVL_ERROR)
118  << "Unknown exception when destructing the generator at index "
119  << (listSize + 1);
120  }
121  }
122 }
123 
125 {
126  for (auto&& idx : generator_active_list_)
127  {
128  idx = true;
129  }
130  for (auto& generator : generator_list_)
131  {
132  generator->StartCmd(run_number(), timeout(), timestamp());
133  }
134 }
135 
137 {
138  std::vector<std::unique_ptr<CommandableFragmentGenerator>>::reverse_iterator riter;
139  for (riter = generator_list_.rbegin(); riter != generator_list_.rend(); ++riter)
140  {
141  (*riter)->StopCmd(timeout(), timestamp());
142  }
143 }
144 
146 {
147  // 02/17/16 ELF: This logic is now handled in stopNoMutex
148  /*
149  std::vector<std::unique_ptr<CommandableFragmentGenerator>>::reverse_iterator riter;
150  for (riter = generator_list_.rbegin(); riter != generator_list_.rend(); ++riter) {
151  (*riter)->StopCmd( timeout(), timestamp() );
152  }
153  */
154 }
155 
157 {
158  std::vector<std::unique_ptr<CommandableFragmentGenerator>>::reverse_iterator riter;
159  for (riter = generator_list_.rbegin(); riter != generator_list_.rend(); ++riter)
160  {
161  (*riter)->PauseCmd(timeout(), timestamp());
162  }
163 }
164 
166 {
167  for (auto&& idx : generator_active_list_)
168  {
169  idx = true;
170  }
171  for (auto& generator : generator_list_)
172  {
173  generator->ResumeCmd(timeout(), timestamp());
174  }
175 }
176 
177 std::vector<artdaq::Fragment::fragment_id_t> artdaq::CompositeDriver::fragmentIDs()
178 {
179  std::vector<artdaq::Fragment::fragment_id_t> workList;
180  for (auto& idx : generator_list_)
181  {
182  std::vector<artdaq::Fragment::fragment_id_t> tempList =
183  idx->fragmentIDs();
184  workList.insert(workList.end(), tempList.begin(), tempList.end());
185  }
186  return workList;
187 }
188 
189 bool artdaq::CompositeDriver::getNext_(artdaq::FragmentPtrs& frags)
190 {
191  bool anyGeneratorIsActive = false;
192  for (size_t idx = 0; idx < generator_list_.size(); ++idx)
193  {
194  if (generator_active_list_[idx])
195  {
196  bool status = generator_list_[idx]->getNext(frags);
197 
198  // 08-May-2015, KAB & JCF: if the generator getNext() method returns
199  // false (which indicates that the data flow has stopped) *and* the
200  // reason that it has stopped is because there was an exception that
201  // wasn't handled by the experiment-specific FragmentGenerator class,
202  // we throw an exception so that the process will move to the
203  // InRunError state. We do our best to try to reproduce the original
204  // exception message.
205  if (!status && generator_list_[idx]->exception())
206  {
207  std::string reportString =
208  generator_list_[idx]->ReportCmd("latest_exception");
209  if (std::string::npos !=
210  boost::algorithm::to_lower_copy(reportString).find("exception"))
211  {
212  throw cet::exception("CompositeDriver_generator") // NOLINT(cert-err60-cpp)
213  << "The FragmentGenerator for "
214  << generator_list_[idx]->metricsReportingInstanceName()
215  << " threw an exception: " << reportString;
216  }
217 
218  throw cet::exception("CompositeDriver_generator") // NOLINT(cert-err60-cpp)
219  << "The FragmentGenerator for "
220  << generator_list_[idx]->metricsReportingInstanceName()
221  << " threw an exception.";
222  }
223  generator_active_list_[idx] = status;
224  if (status) { anyGeneratorIsActive = true; }
225  }
226  }
227  return anyGeneratorIsActive;
228 }
229 
230 bool artdaq::CompositeDriver::makeChildGenerator_(fhicl::ParameterSet const& pset)
231 {
232  // pull out the relevant parts of the ParameterSet, if needed
233  auto daq_pset = pset.get<fhicl::ParameterSet>("daq", pset);
234  auto fr_pset = daq_pset.get<fhicl::ParameterSet>("fragment_receiver", daq_pset);
235 
236  // create the requested FragmentGenerator
237  auto frag_gen_name = fr_pset.get<std::string>("generator", "");
238  if (frag_gen_name.length() == 0)
239  {
240  TLOG(TLVL_ERROR)
241  << "No fragment generator (parameter name = \"generator\") was "
242  << "specified in the fragment_receiver ParameterSet. The "
243  << "DAQ initialization PSet was \"" << daq_pset.to_string() << "\".";
244  return false;
245  }
246 
247  std::unique_ptr<artdaq::CommandableFragmentGenerator> tmp_gen_ptr;
248  try
249  {
250  tmp_gen_ptr = artdaq::makeCommandableFragmentGenerator(frag_gen_name, fr_pset);
251  }
252  catch (art::Exception& excpt)
253  {
254  TLOG(TLVL_ERROR)
255  << "Exception creating a FragmentGenerator of type \""
256  << frag_gen_name << "\" with parameter set \"" << fr_pset.to_string()
257  << "\", exception = " << excpt;
258  return false;
259  }
260  catch (cet::exception& excpt)
261  {
262  TLOG(TLVL_ERROR)
263  << "Exception creating a FragmentGenerator of type \""
264  << frag_gen_name << "\" with parameter set \"" << fr_pset.to_string()
265  << "\", exception = " << excpt;
266  return false;
267  }
268  catch (...)
269  {
270  TLOG(TLVL_ERROR)
271  << "Unknown exception creating a FragmentGenerator of type \""
272  << frag_gen_name << "\" with parameter set \"" << fr_pset.to_string()
273  << "\".";
274  return false;
275  }
276 
277  std::unique_ptr<CommandableFragmentGenerator> generator_ptr;
278  generator_ptr.reset(nullptr);
279  try
280  {
281  auto tmp_cmdablegen_bareptr = tmp_gen_ptr.release();
282  if (tmp_cmdablegen_bareptr != nullptr)
283  {
284  generator_ptr.reset(tmp_cmdablegen_bareptr);
285  }
286  }
287  catch (...)
288  {}
289  if (!generator_ptr)
290  {
291  TLOG(TLVL_ERROR)
292  << "Error: The requested fragment generator type (" << frag_gen_name
293  << ") is not a CommandableFragmentGenerator, and only "
294  << "CommandableFragmentGenerators are currently supported.";
295  return false;
296  }
297 
298  generator_list_.push_back(std::move(generator_ptr));
299  generator_active_list_.push_back(true);
300  return true;
301 }
302 
303 DEFINE_ARTDAQ_COMMANDABLE_GENERATOR(artdaq::CompositeDriver)
void start() override
Start all configured CommandableFragmentGenerators.
CommandableFragmentGenerator(const fhicl::ParameterSet &ps)
CommandableFragmentGenerator Constructor.
bool exception() const
Get the current value of the exception flag.
virtual ~CompositeDriver() noexcept
Destructor. Calls the destructors for each configured CommandableFragmentGenerator.
uint64_t timeout() const
Timeout of last command.
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.
uint64_t timestamp() const
Timestamp of last command.
void stopNoMutex() override
Call non-locked stop methods for all configured CommandableFragmentGenerators.
int run_number() const
Get the current Run number.