Line data Source code
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 {
12 : /**
13 : * \brief CompositeDriver handles a set of lower-level generators
14 : *
15 : * When multiple CommandableFragmentGenerators are needed by a single BoardReader, CompositeDriver may be used to provide
16 : * a single interface to all of them.
17 : */
18 : class CompositeDriver : public CommandableFragmentGenerator
19 : {
20 : public:
21 : /**
22 : * \brief CompositeDriver Constructor
23 : * \param ps ParameterSet used to configure CompositeDriver
24 : *
25 : * \verbatim
26 : * CompositeDriver accepts the following Parameters:
27 : * "generator_config_list" (REQUIRED): A FHiCL sequence of FHiCL tables, each one configuring
28 : * a CommandableFragmentGenerator instance.
29 : * \endverbatim
30 : */
31 : explicit CompositeDriver(fhicl::ParameterSet const& ps);
32 :
33 : /**
34 : * \brief Destructor. Calls the destructors for each configured CommandableFragmentGenerator
35 : */
36 : virtual ~CompositeDriver() noexcept;
37 :
38 : /**
39 : * \brief Start all configured CommandableFragmentGenerators
40 : */
41 : void start() override;
42 :
43 : /**
44 : * \brief Call non-locked stop methods for all configured CommandableFragmentGenerators
45 : */
46 : void stopNoMutex() override;
47 :
48 : /**
49 : * \brief Call stop methods for all configured CommandableFragmentGenerators. Currently handled by stopNoMutex
50 : */
51 : void stop() override;
52 :
53 : /**
54 : * \brief Pause all configured CommandableFragmentGenerators
55 : */
56 : void pause() override;
57 :
58 : /**
59 : * \brief Resume all configured CommandableFragmentGenerators
60 : */
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 0 : artdaq::CompositeDriver::CompositeDriver(const fhicl::ParameterSet& ps)
80 0 : : CommandableFragmentGenerator(ps)
81 : {
82 : auto psetList =
83 0 : ps.get<std::vector<fhicl::ParameterSet>>("generator_config_list");
84 0 : for (const auto& pset : psetList)
85 : {
86 0 : if (!makeChildGenerator_(pset))
87 : {
88 0 : TLOG(TLVL_ERROR) << "Unable to create child generator for PSet= \"" << pset.to_string() << "\"";
89 0 : throw cet::exception("CompositeDriver") // NOLINT(cert-err60-cpp)
90 : << "Unable to create child generator for PSet= \""
91 0 : << pset.to_string() << "\"";
92 : }
93 : }
94 :
95 0 : std::string compositeMetricName;
96 0 : for (auto& generator : generator_list_)
97 : {
98 0 : if (compositeMetricName.length() > 0) { compositeMetricName.append(", "); }
99 0 : compositeMetricName.append(generator->metricsReportingInstanceName());
100 : }
101 0 : this->metricsReportingInstanceName(compositeMetricName);
102 0 : }
103 :
104 0 : artdaq::CompositeDriver::~CompositeDriver() noexcept
105 : {
106 : // 15-Feb-2014, KAB - explicitly destruct the generators so that
107 : // we can control the order in which they are destructed
108 0 : size_t listSize = generator_list_.size();
109 0 : while (listSize > 0)
110 : {
111 0 : --listSize;
112 : try
113 : {
114 0 : generator_list_.resize(listSize);
115 : }
116 0 : catch (...)
117 : {
118 0 : TLOG(TLVL_ERROR)
119 0 : << "Unknown exception when destructing the generator at index "
120 0 : << (listSize + 1);
121 0 : }
122 : }
123 0 : }
124 :
125 0 : void artdaq::CompositeDriver::start()
126 : {
127 0 : for (auto&& idx : generator_active_list_)
128 : {
129 0 : idx = true;
130 : }
131 0 : for (auto& generator : generator_list_)
132 : {
133 0 : generator->StartCmd(run_number(), timeout(), timestamp());
134 : }
135 0 : }
136 :
137 0 : void artdaq::CompositeDriver::stopNoMutex()
138 : {
139 0 : std::vector<std::unique_ptr<CommandableFragmentGenerator>>::reverse_iterator riter;
140 0 : for (riter = generator_list_.rbegin(); riter != generator_list_.rend(); ++riter)
141 : {
142 0 : (*riter)->StopCmd(timeout(), timestamp());
143 : }
144 0 : }
145 :
146 0 : void artdaq::CompositeDriver::stop()
147 : {
148 : // 02/17/16 ELF: This logic is now handled in stopNoMutex
149 : /*
150 : std::vector<std::unique_ptr<CommandableFragmentGenerator>>::reverse_iterator riter;
151 : for (riter = generator_list_.rbegin(); riter != generator_list_.rend(); ++riter) {
152 : (*riter)->StopCmd( timeout(), timestamp() );
153 : }
154 : */
155 0 : }
156 :
157 0 : void artdaq::CompositeDriver::pause()
158 : {
159 0 : std::vector<std::unique_ptr<CommandableFragmentGenerator>>::reverse_iterator riter;
160 0 : for (riter = generator_list_.rbegin(); riter != generator_list_.rend(); ++riter)
161 : {
162 0 : (*riter)->PauseCmd(timeout(), timestamp());
163 : }
164 0 : }
165 :
166 0 : void artdaq::CompositeDriver::resume()
167 : {
168 0 : for (auto&& idx : generator_active_list_)
169 : {
170 0 : idx = true;
171 : }
172 0 : for (auto& generator : generator_list_)
173 : {
174 0 : generator->ResumeCmd(timeout(), timestamp());
175 : }
176 0 : }
177 :
178 0 : std::vector<artdaq::Fragment::fragment_id_t> artdaq::CompositeDriver::fragmentIDs()
179 : {
180 0 : std::vector<artdaq::Fragment::fragment_id_t> workList;
181 0 : for (auto& idx : generator_list_)
182 : {
183 : std::vector<artdaq::Fragment::fragment_id_t> tempList =
184 0 : idx->fragmentIDs();
185 0 : workList.insert(workList.end(), tempList.begin(), tempList.end());
186 0 : }
187 0 : return workList;
188 0 : }
189 :
190 0 : bool artdaq::CompositeDriver::getNext_(artdaq::FragmentPtrs& frags)
191 : {
192 0 : bool anyGeneratorIsActive = false;
193 0 : for (size_t idx = 0; idx < generator_list_.size(); ++idx)
194 : {
195 0 : if (generator_active_list_[idx])
196 : {
197 0 : bool status = generator_list_[idx]->getNext(frags);
198 :
199 : // 08-May-2015, KAB & JCF: if the generator getNext() method returns
200 : // false (which indicates that the data flow has stopped) *and* the
201 : // reason that it has stopped is because there was an exception that
202 : // wasn't handled by the experiment-specific FragmentGenerator class,
203 : // we throw an exception so that the process will move to the
204 : // InRunError state. We do our best to try to reproduce the original
205 : // exception message.
206 0 : if (!status && generator_list_[idx]->exception())
207 : {
208 : std::string reportString =
209 0 : generator_list_[idx]->ReportCmd("latest_exception");
210 0 : if (std::string::npos !=
211 0 : boost::algorithm::to_lower_copy(reportString).find("exception"))
212 : {
213 0 : TLOG(TLVL_ERROR) << "The FragmentGenerator for " << generator_list_[idx]->metricsReportingInstanceName() << " threw an exception: " << reportString;
214 0 : throw cet::exception("CompositeDriver_generator") // NOLINT(cert-err60-cpp)
215 : << "The FragmentGenerator for "
216 0 : << generator_list_[idx]->metricsReportingInstanceName()
217 0 : << " threw an exception: " << reportString;
218 : }
219 :
220 0 : TLOG(TLVL_ERROR) << "The FragmentGenerator for " << generator_list_[idx]->metricsReportingInstanceName() << " threw an exception.";
221 0 : throw cet::exception("CompositeDriver_generator") // NOLINT(cert-err60-cpp)
222 : << "The FragmentGenerator for "
223 0 : << generator_list_[idx]->metricsReportingInstanceName()
224 0 : << " threw an exception.";
225 0 : }
226 0 : generator_active_list_[idx] = status;
227 0 : if (status) { anyGeneratorIsActive = true; }
228 : }
229 : }
230 0 : return anyGeneratorIsActive;
231 : }
232 :
233 0 : bool artdaq::CompositeDriver::makeChildGenerator_(fhicl::ParameterSet const& pset)
234 : {
235 : // pull out the relevant parts of the ParameterSet, if needed
236 0 : auto daq_pset = pset.get<fhicl::ParameterSet>("daq", pset);
237 0 : auto fr_pset = daq_pset.get<fhicl::ParameterSet>("fragment_receiver", daq_pset);
238 :
239 : // create the requested FragmentGenerator
240 0 : auto frag_gen_name = fr_pset.get<std::string>("generator", "");
241 0 : if (frag_gen_name.length() == 0)
242 : {
243 0 : TLOG(TLVL_ERROR)
244 0 : << "No fragment generator (parameter name = \"generator\") was "
245 0 : << "specified in the fragment_receiver ParameterSet. The "
246 0 : << "DAQ initialization PSet was \"" << daq_pset.to_string() << "\".";
247 0 : return false;
248 : }
249 :
250 0 : std::unique_ptr<artdaq::CommandableFragmentGenerator> tmp_gen_ptr;
251 : try
252 : {
253 0 : tmp_gen_ptr = artdaq::makeCommandableFragmentGenerator(frag_gen_name, fr_pset);
254 : }
255 0 : catch (art::Exception& excpt)
256 : {
257 0 : TLOG(TLVL_ERROR)
258 0 : << "Exception creating a FragmentGenerator of type \""
259 0 : << frag_gen_name << "\" with parameter set \"" << fr_pset.to_string()
260 0 : << "\", exception = " << excpt;
261 0 : return false;
262 0 : }
263 0 : catch (cet::exception& excpt)
264 : {
265 0 : TLOG(TLVL_ERROR)
266 0 : << "Exception creating a FragmentGenerator of type \""
267 0 : << frag_gen_name << "\" with parameter set \"" << fr_pset.to_string()
268 0 : << "\", exception = " << excpt;
269 0 : return false;
270 0 : }
271 0 : catch (...)
272 : {
273 0 : TLOG(TLVL_ERROR)
274 0 : << "Unknown exception creating a FragmentGenerator of type \""
275 0 : << frag_gen_name << "\" with parameter set \"" << fr_pset.to_string()
276 0 : << "\".";
277 0 : return false;
278 0 : }
279 :
280 0 : std::unique_ptr<CommandableFragmentGenerator> generator_ptr;
281 0 : generator_ptr.reset(nullptr);
282 : try
283 : {
284 0 : auto tmp_cmdablegen_bareptr = tmp_gen_ptr.release();
285 0 : if (tmp_cmdablegen_bareptr != nullptr)
286 : {
287 0 : generator_ptr.reset(tmp_cmdablegen_bareptr);
288 : }
289 : }
290 : catch (...)
291 : {}
292 0 : if (!generator_ptr)
293 : {
294 0 : TLOG(TLVL_ERROR)
295 0 : << "Error: The requested fragment generator type (" << frag_gen_name
296 0 : << ") is not a CommandableFragmentGenerator, and only "
297 0 : << "CommandableFragmentGenerators are currently supported.";
298 0 : return false;
299 : }
300 :
301 0 : generator_list_.push_back(std::move(generator_ptr));
302 0 : generator_active_list_.push_back(true);
303 0 : return true;
304 0 : }
305 :
306 0 : DEFINE_ARTDAQ_COMMANDABLE_GENERATOR(artdaq::CompositeDriver)
|