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 : throw cet::exception("CompositeDriver") // NOLINT(cert-err60-cpp)
89 : << "Unable to create child generator for PSet= \""
90 0 : << pset.to_string() << "\"";
91 : }
92 : }
93 :
94 0 : std::string compositeMetricName;
95 0 : for (auto& generator : generator_list_)
96 : {
97 0 : if (compositeMetricName.length() > 0) { compositeMetricName.append(", "); }
98 0 : compositeMetricName.append(generator->metricsReportingInstanceName());
99 : }
100 0 : this->metricsReportingInstanceName(compositeMetricName);
101 0 : }
102 :
103 0 : artdaq::CompositeDriver::~CompositeDriver() noexcept
104 : {
105 : // 15-Feb-2014, KAB - explicitly destruct the generators so that
106 : // we can control the order in which they are destructed
107 0 : size_t listSize = generator_list_.size();
108 0 : while (listSize > 0)
109 : {
110 0 : --listSize;
111 : try
112 : {
113 0 : generator_list_.resize(listSize);
114 : }
115 0 : catch (...)
116 : {
117 0 : TLOG(TLVL_ERROR)
118 0 : << "Unknown exception when destructing the generator at index "
119 0 : << (listSize + 1);
120 0 : }
121 : }
122 0 : }
123 :
124 0 : void artdaq::CompositeDriver::start()
125 : {
126 0 : for (auto&& idx : generator_active_list_)
127 : {
128 0 : idx = true;
129 : }
130 0 : for (auto& generator : generator_list_)
131 : {
132 0 : generator->StartCmd(run_number(), timeout(), timestamp());
133 : }
134 0 : }
135 :
136 0 : void artdaq::CompositeDriver::stopNoMutex()
137 : {
138 0 : std::vector<std::unique_ptr<CommandableFragmentGenerator>>::reverse_iterator riter;
139 0 : for (riter = generator_list_.rbegin(); riter != generator_list_.rend(); ++riter)
140 : {
141 0 : (*riter)->StopCmd(timeout(), timestamp());
142 : }
143 0 : }
144 :
145 0 : void artdaq::CompositeDriver::stop()
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 0 : }
155 :
156 0 : void artdaq::CompositeDriver::pause()
157 : {
158 0 : std::vector<std::unique_ptr<CommandableFragmentGenerator>>::reverse_iterator riter;
159 0 : for (riter = generator_list_.rbegin(); riter != generator_list_.rend(); ++riter)
160 : {
161 0 : (*riter)->PauseCmd(timeout(), timestamp());
162 : }
163 0 : }
164 :
165 0 : void artdaq::CompositeDriver::resume()
166 : {
167 0 : for (auto&& idx : generator_active_list_)
168 : {
169 0 : idx = true;
170 : }
171 0 : for (auto& generator : generator_list_)
172 : {
173 0 : generator->ResumeCmd(timeout(), timestamp());
174 : }
175 0 : }
176 :
177 0 : std::vector<artdaq::Fragment::fragment_id_t> artdaq::CompositeDriver::fragmentIDs()
178 : {
179 0 : std::vector<artdaq::Fragment::fragment_id_t> workList;
180 0 : for (auto& idx : generator_list_)
181 : {
182 : std::vector<artdaq::Fragment::fragment_id_t> tempList =
183 0 : idx->fragmentIDs();
184 0 : workList.insert(workList.end(), tempList.begin(), tempList.end());
185 0 : }
186 0 : return workList;
187 0 : }
188 :
189 0 : bool artdaq::CompositeDriver::getNext_(artdaq::FragmentPtrs& frags)
190 : {
191 0 : bool anyGeneratorIsActive = false;
192 0 : for (size_t idx = 0; idx < generator_list_.size(); ++idx)
193 : {
194 0 : if (generator_active_list_[idx])
195 : {
196 0 : 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 0 : if (!status && generator_list_[idx]->exception())
206 : {
207 : std::string reportString =
208 0 : generator_list_[idx]->ReportCmd("latest_exception");
209 0 : if (std::string::npos !=
210 0 : boost::algorithm::to_lower_copy(reportString).find("exception"))
211 : {
212 0 : throw cet::exception("CompositeDriver_generator") // NOLINT(cert-err60-cpp)
213 : << "The FragmentGenerator for "
214 0 : << generator_list_[idx]->metricsReportingInstanceName()
215 0 : << " threw an exception: " << reportString;
216 : }
217 :
218 0 : throw cet::exception("CompositeDriver_generator") // NOLINT(cert-err60-cpp)
219 : << "The FragmentGenerator for "
220 0 : << generator_list_[idx]->metricsReportingInstanceName()
221 0 : << " threw an exception.";
222 0 : }
223 0 : generator_active_list_[idx] = status;
224 0 : if (status) { anyGeneratorIsActive = true; }
225 : }
226 : }
227 0 : return anyGeneratorIsActive;
228 : }
229 :
230 0 : bool artdaq::CompositeDriver::makeChildGenerator_(fhicl::ParameterSet const& pset)
231 : {
232 : // pull out the relevant parts of the ParameterSet, if needed
233 0 : auto daq_pset = pset.get<fhicl::ParameterSet>("daq", pset);
234 0 : auto fr_pset = daq_pset.get<fhicl::ParameterSet>("fragment_receiver", daq_pset);
235 :
236 : // create the requested FragmentGenerator
237 0 : auto frag_gen_name = fr_pset.get<std::string>("generator", "");
238 0 : if (frag_gen_name.length() == 0)
239 : {
240 0 : TLOG(TLVL_ERROR)
241 0 : << "No fragment generator (parameter name = \"generator\") was "
242 0 : << "specified in the fragment_receiver ParameterSet. The "
243 0 : << "DAQ initialization PSet was \"" << daq_pset.to_string() << "\".";
244 0 : return false;
245 : }
246 :
247 0 : std::unique_ptr<artdaq::CommandableFragmentGenerator> tmp_gen_ptr;
248 : try
249 : {
250 0 : tmp_gen_ptr = artdaq::makeCommandableFragmentGenerator(frag_gen_name, fr_pset);
251 : }
252 0 : catch (art::Exception& excpt)
253 : {
254 0 : TLOG(TLVL_ERROR)
255 0 : << "Exception creating a FragmentGenerator of type \""
256 0 : << frag_gen_name << "\" with parameter set \"" << fr_pset.to_string()
257 0 : << "\", exception = " << excpt;
258 0 : return false;
259 0 : }
260 0 : catch (cet::exception& excpt)
261 : {
262 0 : TLOG(TLVL_ERROR)
263 0 : << "Exception creating a FragmentGenerator of type \""
264 0 : << frag_gen_name << "\" with parameter set \"" << fr_pset.to_string()
265 0 : << "\", exception = " << excpt;
266 0 : return false;
267 0 : }
268 0 : catch (...)
269 : {
270 0 : TLOG(TLVL_ERROR)
271 0 : << "Unknown exception creating a FragmentGenerator of type \""
272 0 : << frag_gen_name << "\" with parameter set \"" << fr_pset.to_string()
273 0 : << "\".";
274 0 : return false;
275 0 : }
276 :
277 0 : std::unique_ptr<CommandableFragmentGenerator> generator_ptr;
278 0 : generator_ptr.reset(nullptr);
279 : try
280 : {
281 0 : auto tmp_cmdablegen_bareptr = tmp_gen_ptr.release();
282 0 : if (tmp_cmdablegen_bareptr != nullptr)
283 : {
284 0 : generator_ptr.reset(tmp_cmdablegen_bareptr);
285 : }
286 : }
287 : catch (...)
288 : {}
289 0 : if (!generator_ptr)
290 : {
291 0 : TLOG(TLVL_ERROR)
292 0 : << "Error: The requested fragment generator type (" << frag_gen_name
293 0 : << ") is not a CommandableFragmentGenerator, and only "
294 0 : << "CommandableFragmentGenerators are currently supported.";
295 0 : return false;
296 : }
297 :
298 0 : generator_list_.push_back(std::move(generator_ptr));
299 0 : generator_active_list_.push_back(true);
300 0 : return true;
301 0 : }
302 :
303 0 : DEFINE_ARTDAQ_COMMANDABLE_GENERATOR(artdaq::CompositeDriver)
|