artdaq  v2_03_02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Pages
genToArt.cc
1 // genToArt
3 //
4 // This application is intended to invoke a configurable set of fragment
5 // generators, and funnel the result to an invocation of art. This is
6 // not an MPI application (see caveat below), so is not intended for
7 // high performance production DAQ scenarios -- for that, see the pmt
8 // application driver and its associated applcations boardreader and
9 // eventbuilder.
11 
12 #include "art/Framework/Art/artapp.h"
13 #include "canvas/Utilities/Exception.h"
14 #include "artdaq/Application/MPI2/MPISentry.hh"
15 #include "artdaq-core/Generators/FragmentGenerator.hh"
16 #include "artdaq-core/Data/Fragment.hh"
17 #include "artdaq/DAQdata/GenericFragmentSimulator.hh"
18 #include "artdaq-core/Generators/makeFragmentGenerator.hh"
19 #include "artdaq/DAQrate/EventStore.hh"
20 #include "artdaq-core/Core/SimpleQueueReader.hh"
21 #include "artdaq-core/Utilities/SimpleLookupPolicy.hh"
22 #include "cetlib/container_algorithms.h"
23 #include "fhiclcpp/ParameterSet.h"
24 #include "fhiclcpp/make_ParameterSet.h"
25 
26 #include <boost/program_options.hpp>
27 
28 #include <deque>
29 #include <iostream>
30 #include <map>
31 #include <memory>
32 #include <string>
33 #include <utility>
34 
35 using namespace std;
36 using namespace fhicl;
37 namespace bpo = boost::program_options;
38 
39 namespace
40 {
48  int process_cmd_line(int argc, char** argv,
49  bpo::variables_map& vm)
50  {
51  std::ostringstream descstr;
52  descstr << argv[0]
53  << " <-c <config-file>> <other-options> [<source-file>]+";
54  bpo::options_description desc(descstr.str());
55  desc.add_options()
56  ("config,c", bpo::value<std::string>(), "Configuration file.")
57  ("help,h", "produce help message");
58  try
59  {
60  bpo::store(bpo::command_line_parser(argc, argv).options(desc).run(), vm);
61  bpo::notify(vm);
62  }
63  catch (bpo::error const& e)
64  {
65  std::cerr << "Exception from command line processing in " << argv[0]
66  << ": " << e.what() << "\n";
67  return -1;
68  }
69  if (vm.count("help"))
70  {
71  std::cout << desc << std::endl;
72  return 1;
73  }
74  if (!vm.count("config"))
75  {
76  std::cerr << "Exception from command line processing in " << argv[0]
77  << ": no configuration file given.\n"
78  << "For usage and an options list, please do '"
79  << argv[0] << " --help"
80  << "'.\n";
81  return 2;
82  }
83  return 0;
84  }
85 
91  {
92  public:
98  ThrottledGenerator(std::string const& generator,
99  fhicl::ParameterSet const& ps);
100 
106  bool getNext(artdaq::FragmentPtrs& newFrags);
107 
112  size_t numFragIDs() const;
113 
114  private:
115  bool generateFragments_();
116 
117  std::unique_ptr<artdaq::FragmentGenerator> generator_;
118  size_t const numFragIDs_;
119  std::map<artdaq::Fragment::fragment_id_t,
120  std::deque<artdaq::FragmentPtr>> frags_;
121  };
122 
123  ThrottledGenerator::
124  ThrottledGenerator(std::string const& generator,
125  fhicl::ParameterSet const& ps)
126  :
127  generator_(artdaq::makeFragmentGenerator(generator, ps))
128  , numFragIDs_(generator_->fragmentIDs().size())
129  , frags_()
130  {
131  assert(generator_);
132  }
133 
134  bool
136  getNext(artdaq::FragmentPtrs& newFrags)
137  {
138  if (frags_.size() && frags_.begin()->second.size())
139  { // Something stored.
140  for (auto& fQp : frags_)
141  {
142  assert(fQp.second.size());
143  newFrags.emplace_back(std::move(fQp.second.front()));
144  fQp.second.pop_front();
145  }
146  }
147  else
148  { // Need fresh fragments.
149  return generateFragments_() && getNext(newFrags);
150  }
151  return true;
152  }
153 
154  bool
155  ThrottledGenerator::
156  generateFragments_()
157  {
158  artdaq::FragmentPtrs incomingFrags;
159  bool result{false};
160  while ((result = generator_->getNext(incomingFrags)) &&
161  incomingFrags.empty()) { }
162  for (auto&& frag : incomingFrags)
163  {
164  frags_[frag->fragmentID()].emplace_back(std::move(frag));
165  }
166  return result;
167  }
168 
169  size_t
171  numFragIDs() const
172  {
173  return numFragIDs_;
174  }
175 
176  // artdaq::FragmentGenerator &
177  // ThrottledGenerator::
178  // generator() const
179  // {
180  // return *generator_;
181  // }
182 
202  int process_data(int argc, char** argv,
203  fhicl::ParameterSet const& pset)
204  {
205  auto const gta_pset = pset.get<ParameterSet>("genToArt");
206 
207  // Make the generators based on the configuration.
208  std::vector<ThrottledGenerator> generators;
209 
210  auto const fr_pset = gta_pset.get<std::vector<ParameterSet>>("fragment_receivers");
211  for (auto const& gen_ps : fr_pset)
212  {
213  generators.emplace_back(gen_ps.get<std::string>("generator"),
214  gen_ps);
215  }
216 
217  artdaq::FragmentPtrs frags;
218  auto const eb_pset = gta_pset.get<ParameterSet>("event_builder", {});
219  size_t expected_frags_per_event = 0;
220  for (auto& gen : generators)
221  {
222  expected_frags_per_event += gen.numFragIDs();
223  }
224 
225  artdaq::EventStore store(eb_pset, expected_frags_per_event,
226  gta_pset.get<artdaq::EventStore::run_id_t>("run_number"),
227  argc,
228  argv,
229  &artapp);
230 
231  auto const events_to_generate =
232  gta_pset.get<artdaq::Fragment::sequence_id_t>("events_to_generate", -1);
233  auto const reset_sequenceID = pset.get<bool>("reset_sequenceID", true);
234  bool done = false;
235  for (artdaq::Fragment::sequence_id_t event_count = 1;
236  (events_to_generate == static_cast<decltype(events_to_generate)>(-1)
237  || event_count <= events_to_generate) && (!done);
238  ++event_count)
239  {
240  for (auto& gen : generators)
241  {
242  done |= !gen.getNext(frags);
243  }
244  artdaq::Fragment::sequence_id_t current_sequence_id = -1;
245  for (auto& val : frags)
246  {
247  if (reset_sequenceID)
248  {
249  val->setSequenceID(event_count);
250  }
251  if (current_sequence_id ==
252  static_cast<artdaq::Fragment::sequence_id_t>(-1))
253  {
254  current_sequence_id = val->sequenceID();
255  }
256  else if (val->sequenceID() != current_sequence_id)
257  {
258  throw art::Exception(art::errors::DataCorruption)
259  << "Data corruption: apparently related fragments have "
260  << " different sequence IDs: "
261  << val->sequenceID()
262  << " and "
263  << current_sequence_id
264  << ".\n";
265  }
266  store.insert(std::move(val));
267  }
268  frags.clear();
269  }
270 
271  int readerReturnValue;
272  bool endSucceeded = store.endOfData(readerReturnValue);
273  if (endSucceeded)
274  {
275  return readerReturnValue;
276  }
277  else
278  {
279  return 15;
280  }
281  }
282 }
283 
284 int main(int argc, char* argv[]) try
285 {
286  // Needed in case plugins use eg MPI timing for performance.
287  artdaq::MPISentry sentry(&argc, &argv);
288  // Command line handling.
289  bpo::variables_map vm;
290  auto result = process_cmd_line(argc, argv, vm);
291  if (result != 0)
292  {
293  return (result);
294  }
295  // Read FHiCL configuration file.
296  ParameterSet pset;
297  if (getenv("FHICL_FILE_PATH") == nullptr)
298  {
299  std::cerr
300  << "INFO: environment variable FHICL_FILE_PATH was not set. Using \".\"\n";
301  setenv("FHICL_FILE_PATH", ".", 0);
302  }
303  artdaq::SimpleLookupPolicy lookup_policy("FHICL_FILE_PATH");
304  make_ParameterSet(vm["config"].as<std::string>(), lookup_policy, pset);
305  return process_data(argc, argv, pset);
306 }
307 catch (std::string& x)
308 {
309  cerr << "Exception (type string) caught in genToArt: " << x << '\n';
310  return 1;
311 }
312 catch (char const* m)
313 {
314  cerr << "Exception (type char const*) caught in genToArt: ";
315  if (m)
316  {
317  cerr << m;
318  }
319  else
320  {
321  cerr << "[the value was a null pointer, so no message is available]";
322  }
323  cerr << '\n';
324 }
void insert(FragmentPtr pfrag, bool printWarningWhenFragmentIsDropped=true)
Give ownership of the Fragment to the EventStore.
Definition: EventStore.cc:98
bool endOfData(int &readerReturnValue)
Indicate that the end of input has been reached to the art thread.
Definition: EventStore.cc:259
The MPISentry class initializes and finalizes the MPI context that the artdaq applciations run in...
Definition: MPISentry.hh:15
int process_cmd_line(int argc, char **argv, bpo::variables_map &vm)
Process the command line.
Definition: genToArt.cc:48
bool getNext(artdaq::FragmentPtrs &newFrags)
Get the next fragment from the generator.
Definition: genToArt.cc:136
The EventStore class collects Fragment objects, until it receives a complete event, at which point the event is handed over to the art thread.
Definition: EventStore.hh:49
size_t numFragIDs() const
Get the number of Fragment IDs handled by this generator.
Definition: genToArt.cc:171
int process_data(int argc, char **argv, fhicl::ParameterSet const &pset)
Run the test, instantiating configured generators and an EventStore.
Definition: genToArt.cc:202
RawEvent::run_id_t run_id_t
Copy RawEvent::run_id_t into local scope.
Definition: EventStore.hh:64
ThrottledGenerator: ensure that we only get one fragment per type at a time from the generator...
Definition: genToArt.cc:90