artdaq  v3_00_03
driver.cc
1 //
2 // artdaqDriver is a program for testing the behavior of the generic
3 // RawInput source. Run 'artdaqDriver --help' to get a description of the
4 // expected command-line parameters.
5 //
6 //
7 // The current version generates simple data fragments, for testing
8 // that data are transmitted without corruption from the
9 // artdaq::EventStore through to the artdaq::RawInput source.
10 //
11 
12 #include "art/Framework/Art/artapp.h"
13 #include "artdaq-core/Generators/FragmentGenerator.hh"
14 #include "artdaq-core/Data/Fragment.hh"
15 #include "artdaq-core/Utilities/ExceptionHandler.hh"
16 #include "artdaq/DAQdata/GenericFragmentSimulator.hh"
17 
18 #include "artdaq/DAQdata/Globals.hh"
19 #include "artdaq-core/Generators/makeFragmentGenerator.hh"
20 #include "artdaq/Application/makeCommandableFragmentGenerator.hh"
21 #include "artdaq-utilities/Plugins/MetricManager.hh"
22 #include "artdaq-core/Core/SimpleMemoryReader.hh"
23 #include "cetlib/filepath_maker.h"
24 #include "fhiclcpp/ParameterSet.h"
25 #include "fhiclcpp/make_ParameterSet.h"
26 #include <boost/program_options.hpp>
27 
28 #include <signal.h>
29 #include <iostream>
30 #include <memory>
31 #include <utility>
32 #include "artdaq/DAQrate/SharedMemoryEventManager.hh"
33 #include "artdaq/Application/LoadParameterSet.hh"
34 
35 namespace bpo = boost::program_options;
36 
37 volatile int events_to_generate;
38 void sig_handler(int) { events_to_generate = -1; }
39 
40 template<typename B, typename D>
41 std::unique_ptr<D>
42 dynamic_unique_ptr_cast(std::unique_ptr<B>& p);
43 
44 int main(int argc, char * argv[]) try
45 {
46  auto pset = LoadParameterSet(argc, argv);
47 
48  int run = pset.get<int>("run_number", 1);
49  bool debug = pset.get<bool>("debug_cout", false);
50  uint64_t timeout = pset.get<uint64_t>("transition_timeout", 30);
51  uint64_t timestamp = 0;
52 
53  artdaq::configureMessageFacility("artdaqDriver",true,debug);
54 
55  fhicl::ParameterSet fragment_receiver_pset = pset.get<fhicl::ParameterSet>("fragment_receiver");
56 
57  std::unique_ptr<artdaq::FragmentGenerator>
58  gen(artdaq::makeFragmentGenerator(fragment_receiver_pset.get<std::string>("generator"),
59  fragment_receiver_pset));
60 
61  std::unique_ptr<artdaq::CommandableFragmentGenerator> commandable_gen =
62  dynamic_unique_ptr_cast<artdaq::FragmentGenerator, artdaq::CommandableFragmentGenerator>(gen);
63 
64  artdaq::MetricManager metricMan_;
65  metricMan = &metricMan_;
66  my_rank = 0;
67  // pull out the Metric part of the ParameterSet
68  fhicl::ParameterSet metric_pset;
69  try {
70  metric_pset = pset.get<fhicl::ParameterSet>("metrics");
71  }
72  catch (...) {} // OK if there's no metrics table defined in the FHiCL
73 
74  if (metric_pset.is_empty()) {
75  TLOG_INFO("artdaqDriver") << "No metric plugins appear to be defined" << TLOG_ENDL;
76  }
77  try {
78  metricMan_.initialize(metric_pset, "artdaqDriver");
79  metricMan_.do_start();
80  }
81  catch (...) {
82  }
83  artdaq::FragmentPtrs frags;
85  // Note: we are constrained to doing all this here rather than
86  // encapsulated neatly in a function due to the lieftime issues
87  // associated with async threads and std::string::c_str().
88  fhicl::ParameterSet event_builder_pset = pset.get<fhicl::ParameterSet>("event_builder");
89 
90  artdaq::SharedMemoryEventManager store(event_builder_pset, pset);
92 
93  int events_to_generate = pset.get<int>("events_to_generate", 0);
94  int event_count = 0;
95  artdaq::Fragment::sequence_id_t previous_sequence_id = -1;
96 
97  if (commandable_gen) {
98  commandable_gen->StartCmd(run, timeout, timestamp);
99  }
100 
101  TLOG_ARB(50, "artdaqDriver") << "driver main before store.startRun" << TLOG_ENDL;
102  store.startRun(run);
103 
104  // Read or generate fragments as rapidly as possible, and feed them
105  // into the EventStore. The throughput resulting from this design
106  // choice is likely to have the fragment reading (or generation)
107  // speed as the limiting factor
108  while ((commandable_gen && commandable_gen->getNext(frags)) ||
109  (gen && gen->getNext(frags))) {
110  TLOG_ARB(50, "artdaqDriver") << "driver main: getNext returned frags.size()=" << std::to_string(frags.size()) << " current event_count=" << event_count << TLOG_ENDL;
111  for (auto & val : frags) {
112  if (val->sequenceID() != previous_sequence_id) {
113  ++event_count;
114  previous_sequence_id = val->sequenceID();
115  }
116  if (events_to_generate != 0 && event_count > events_to_generate) {
117  if (commandable_gen) {
118  commandable_gen->StopCmd(timeout, timestamp);
119  }
120  break;
121  }
122  artdaq::FragmentPtr tempFrag;
123  auto sts = store.AddFragment(std::move(val), 1000000, tempFrag);
124  if (!sts)
125  {
126  TLOG_ERROR("artdaqDriver") << "Fragment was not added after 1s. Check art thread status!" << TLOG_ENDL;
127  exit(1);
128  }
129  }
130  frags.clear();
131 
132  if (events_to_generate != 0 && event_count >= events_to_generate) {
133  if (commandable_gen) {
134  commandable_gen->StopCmd(timeout, timestamp);
135  }
136  break;
137  }
138  }
139 
140  if (commandable_gen) {
141  commandable_gen->joinThreads();
142  }
143 
144  bool endSucceeded = false;
145  int attemptsToEnd = 1;
146  endSucceeded = store.endOfData();
147  while (!endSucceeded && attemptsToEnd < 3) {
148  ++attemptsToEnd;
149  endSucceeded = store.endOfData();
150  }
151  if (!endSucceeded) {
152  std::cerr << "Failed to shut down the reader and the event store "
153  << "because the endOfData marker could not be pushed "
154  << "onto the queue." << std::endl;
155  }
156 
157  metricMan_.do_stop();
158  return 0;
159 }
160 catch (std::string & x)
161 {
162  std::cerr << "Exception (type string) caught in artdaqDriver: " << x << '\n';
163  return 1;
164 }
165 catch (char const * m)
166 {
167  std::cerr << "Exception (type char const*) caught in artdaqDriver: ";
168  if (m)
169  {
170  std::cerr << m;
171  }
172  else
173  {
174  std::cerr << "[the value was a null pointer, so no message is available]";
175  }
176  std::cerr << '\n';
177 }
178 catch (...) {
179  artdaq::ExceptionHandler(artdaq::ExceptionHandlerRethrow::no,
180  "Exception caught in artdaqDriver");
181 }
182 
183 
184 template<typename B, typename D>
185 std::unique_ptr<D>
186 dynamic_unique_ptr_cast(std::unique_ptr<B>& p)
187 {
188  D* result = dynamic_cast<D*>(p.get());
189 
190  if (result) {
191  p.release();
192  return std::unique_ptr<D>(result);
193  }
194  return nullptr;
195 }
The SharedMemoryEventManager is a SharedMemoryManger which tracks events as they are built...
void StopCmd(uint64_t timeout, uint64_t timestamp)
Stop the CommandableFragmentGenerator.
void StartCmd(int run, uint64_t timeout, uint64_t timestamp)
Start the CommandableFragmentGenerator.
bool getNext(FragmentPtrs &output) overridefinal
getNext calls either applyRequests or getNext_ to get any data that is ready to be sent to the EventB...
CommandableFragmentGenerator is a FragmentGenerator-derived abstract class that defines the interface...
void joinThreads()
Join any data-taking threads. Should be called when destructing CommandableFragmentGenerator.