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