artdaq_demo  v3_04_00
demo_driver.cc
1 //
2 // Based off of "ds50driver", a program for testing DarkSide-50 input
3 // sources, "driver" is an executable designed to make it simple to
4 // test a fragment generator under development
5 
6 // Run 'driver --help' to get a description of the
7 // expected command-line parameters.
8 //
9 //
10 // The current version generates data fragments and passes them
11 // to an EventStore instance and then to art, if desired.
12 //
13 
14 #include "art/Framework/Art/artapp.h"
15 #include "artdaq-core/Data/Fragment.hh"
16 #include "artdaq/Application/CommandableFragmentGenerator.hh"
17 #include "artdaq/Application/makeCommandableFragmentGenerator.hh"
18 #include "artdaq/DAQrate/EventStore.hh"
19 #include "artdaq-core/Core/SimpleMemoryReader.hh"
20 #include "artdaq-core/Utilities/SimpleLookupPolicy.hh"
21 #include "cetlib/container_algorithms.h"
22 #include "cetlib/filepath_maker.h"
23 #include "fhiclcpp/ParameterSet.h"
24 #include "fhiclcpp/make_ParameterSet.h"
25 
26 #include <boost/program_options.hpp>
27 
28 #include <signal.h>
29 #include <iostream>
30 #include <memory>
31 #include <utility>
32 #include <limits>
33 
34 using namespace fhicl;
35 namespace bpo = boost::program_options;
36 
37 
38 int main(int argc, char* argv[]) try
39 {
40  // 15-Dec-2016, KAB: by consensus, we want people to use the "artdaqDriver"
41  // program (which corresponds to "artdaq/proto/driver.cc").
42  if (true)
43  {
44  std::cout << "****************************************" << std::endl;
45  std::cout << "*** \"demo_driver\" has been deprecated (15-Dec-2016)." << std::endl;
46  std::cout << "*** Please use the \"artdaqDriver\" application that is available from" << std::endl
47  << "*** the artdaq software package instead of \"demo_driver\"." << std::endl;
48  exit(1);
49  }
50 
51  // Get the input parameters via the boost::program_options library,
52  // designed to make it relatively simple to define arguments and
53  // issue errors if argument list is supplied incorrectly
54 
55  std::ostringstream descstr;
56  descstr << argv[0] << " <-c <config-file>> <other-options>";
57 
58  bpo::options_description desc = descstr.str();
59 
60  desc.add_options()
61  ("config,c", bpo::value<std::string>(), "Configuration file.")
62  ("help,h", "produce help message");
63 
64  bpo::variables_map vm;
65 
66  try
67  {
68  bpo::store(bpo::command_line_parser(argc, argv).options(desc).run(), vm);
69  bpo::notify(vm);
70  }
71  catch (bpo::error const& e)
72  {
73  std::cerr << "Exception from command line processing in " << argv[0]
74  << ": " << e.what() << "\n";
75  return -1;
76  }
77 
78  if (vm.count("help"))
79  {
80  std::cout << desc << std::endl;
81  return 1;
82  }
83  if (!vm.count("config"))
84  {
85  std::cerr << "Exception from command line processing in " << argv[0]
86  << ": no configuration file given.\n"
87  << "For usage and an options list, please do '"
88  << argv[0] << " --help"
89  << "'.\n";
90  return 2;
91  }
92 
93  // Check the directories defined by the FHICL_FILE_PATH
94  // environmental variable for the *.fcl file whose name was passed to
95  // the command line. If not defined, look in the current directory.
96 
97  ParameterSet complete_pset;
98 
99  if (getenv("FHICL_FILE_PATH") == nullptr)
100  {
101  std::cerr
102  << "INFO: environment variable FHICL_FILE_PATH was not set. Using \".\"\n";
103  setenv("FHICL_FILE_PATH", ".", 0);
104  }
105 
106  artdaq::SimpleLookupPolicy lookup_policy("FHICL_FILE_PATH");
107 
108  make_ParameterSet(vm["config"].as<std::string>(), lookup_policy, complete_pset);
109 
110  ParameterSet fragment_receiver_pset = complete_pset.get<ParameterSet>("fragment_receiver");
111  ParameterSet event_builder_pset = complete_pset.get<ParameterSet>("event_builder");
112 
113  // Use the "generator" parameter from the user-supplied *.fcl
114  // configuration file to define our fragment generator
115 
116  std::unique_ptr<artdaq::CommandableFragmentGenerator> const
117  gen(artdaq::makeCommandableFragmentGenerator(fragment_receiver_pset.get<std::string>("generator"),
118  fragment_receiver_pset));
119 
120  // The instance of the artdaq::EventStore object can either pass
121  // events to a thread running Art, or to a small executable called
122  // "SimpleMemoryReader"
123 
124  bool const want_artapp = event_builder_pset.get<bool>("use_art", false);
125 
126  std::ostringstream os;
127  if (!want_artapp)
128  {
129  os << event_builder_pset.get<int>("events_expected_in_SimpleMemoryReader");
130  }
131  std::string oss = os.str();
132 
133  const char* args[2]{"SimpleMemoryReader", const_cast<char *>(oss.c_str())};
134 
135  int es_argc(want_artapp ? argc : 2);
136  char** es_argv(want_artapp ? argv : const_cast<char**>(args));
137 
138  artdaq::EventStore::ART_CMDLINE_FCN*
139  es_fcn(want_artapp ? &artapp : &artdaq::SimpleMemoryReaderApp);
140 
141  artdaq::EventStore store(event_builder_pset, event_builder_pset.get<size_t>("expected_fragments_per_event"),
142  complete_pset.get<artdaq::EventStore::run_id_t>("run_number"),
143  es_argc,
144  es_argv,
145  es_fcn);
146 
147  int events_to_generate = complete_pset.get<int>("events_to_generate", 0);
148  int event_count = 0;
149  artdaq::Fragment::sequence_id_t previous_sequence_id = 0;
150 
151  uint64_t timeout = 45;
152  uint64_t timestamp = std::numeric_limits<uint64_t>::max();
153 
154  gen.get()->StartCmd(complete_pset.get<artdaq::EventStore::run_id_t>("run_number"), timeout, timestamp);
155 
156  artdaq::FragmentPtrs frags;
157 
158  while (events_to_generate >= 0 && gen->getNext(frags))
159  {
160  for (auto& val : frags)
161  {
162  std::cout << "Fragment: Seq ID: " << val->sequenceID() << ", Frag ID: " << val->fragmentID() << ", total size in bytes: " << val->size() * sizeof(artdaq::RawDataType) << std::endl;
163 
164  if (val->sequenceID() != previous_sequence_id)
165  {
166  ++event_count;
167  previous_sequence_id = val->sequenceID();
168  }
169  if (events_to_generate != 0 && event_count > events_to_generate)
170  gen.get()->StopCmd(timeout, timestamp);
171 
172  store.insert(std::move(val));
173  }
174  frags.clear();
175 
176  if (events_to_generate != 0 && event_count >= events_to_generate)
177  gen.get()->StopCmd(timeout, timestamp);
178  }
179 
180  int readerReturnValue;
181  bool endSucceeded = false;
182  int attemptsToEnd = 1;
183  endSucceeded = store.endOfData(readerReturnValue);
184  while (! endSucceeded && attemptsToEnd < 3)
185  {
186  ++attemptsToEnd;
187  endSucceeded = store.endOfData(readerReturnValue);
188  }
189  if (! endSucceeded)
190  {
191  std::cerr << "Failed to shut down the reader and the event store "
192  << "because the endOfData marker could not be pushed "
193  << "onto the queue." << std::endl;
194  }
195  return readerReturnValue;
196 }
197 
198 catch (std::string& x)
199 {
200  std::cerr << "Exception (type string) caught in driver: " << x << "\n";
201  return 1;
202 }
203 
204 catch (char const* m)
205 {
206  std::cerr << "Exception (type char const*) caught in driver: " << std::endl;
207  if (m)
208  {
209  std::cerr << m;
210  }
211  else
212  {
213  std::cerr << "[the value was a null pointer, so no message is available]";
214  }
215  std::cerr << '\n';
216 }
detail::RawFragmentHeader::RawDataType RawDataType
std::list< FragmentPtr > FragmentPtrs
int SimpleMemoryReaderApp(int argc, char **argv)
detail::RawFragmentHeader::sequence_id_t sequence_id_t