LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
run_art.cc
Go to the documentation of this file.
2 // vim: set sw=2 expandtab :
3 
10 #include "boost/filesystem.hpp"
11 #include "boost/program_options.hpp"
13 #include "cetlib/HorizontalRule.h"
14 #include "cetlib/container_algorithms.h"
15 #include "cetlib/ostream_handle.h"
16 #include "cetlib_except/exception.h"
17 #include "fhiclcpp/ParameterSet.h"
22 #include "fhiclcpp/parse.h"
24 
25 #include <cassert>
26 #include <cstring>
27 #include <exception>
28 #include <iostream>
29 #include <sstream>
30 #include <string>
31 #include <type_traits>
32 #include <vector>
33 
34 namespace bpo = boost::program_options;
35 
36 namespace {
37  cet::ostream_handle
38  make_ostream_handle(std::string const& filename)
39  {
40  if (filename.empty()) {
41  return cet::ostream_handle{std::cerr};
42  } else {
43  auto os = cet::ostream_handle{filename};
44  if (!os) {
46  << "Unable to write post-processed configuration to specified file "
47  << filename << ".\n";
48  }
49  return os;
50  }
51  }
52 
54  get_print_mode(std::string const& mode)
55  {
56  if (mode == "raw") {
58  } else if (mode == "annotate") {
60  } else if (mode == "prefix-annotate") {
62  }
64  << "Unrecognized ParameterSet printing mode: " << mode << '\n';
65  }
66 
67  std::string
68  banner(std::string const& filename)
69  {
70  std::string result = "** Config output ";
71  result +=
72  filename.empty() ? "follows" : std::string("to file '" + filename + "'");
73  result += " **\n";
74  return result;
75  }
76 
77  enum class debug_processing : std::size_t {
78  config_out,
79  debug_config,
80  validate_config,
81  none
82  };
83 
85  maybe_output_config(fhicl::ParameterSet const& main_pset,
86  fhicl::ParameterSet const& scheduler_pset)
87  {
88  std::underlying_type_t<debug_processing> i{};
89  for (auto const debugProcessing :
90  {"configOut", "debugConfig", "validateConfig"}) {
91  auto const j = i++;
92  if (!scheduler_pset.has_key(debugProcessing))
93  continue;
94 
95  // Handle the backwards compatibility case, where "configOut"
96  // was associated with a filename in older configurations.
97  if (scheduler_pset.is_key_to_atom(debugProcessing)) {
98  assert(std::strcmp(debugProcessing, "configOut") == 0);
99  auto const filename = scheduler_pset.get<std::string>("configOut");
100  std::cerr << banner(filename);
101  auto os = make_ostream_handle(filename);
103  return debug_processing::config_out;
104  }
105 
106  auto const& debug_table =
107  scheduler_pset.get<fhicl::ParameterSet>(debugProcessing);
108  auto const filename = debug_table.get<std::string>("fileName");
109  auto const mode = debug_table.get<std::string>("printMode");
110  std::cerr << banner(filename);
111  auto os = make_ostream_handle(filename);
112  os << main_pset.to_indented_string(0, get_print_mode(mode));
113  return static_cast<debug_processing>(j);
114  }
115  return debug_processing::none;
116  }
117 
118 } // namespace
119 
120 namespace art {
121 
122  int
123  run_art(int argc,
124  char** argv,
125  bpo::options_description& in_desc,
126  cet::filepath_maker& lookupPolicy,
127  OptionsHandlers&& handlers)
128  {
129  std::ostringstream descstr;
130  descstr << "\nUsage: "
131  << boost::filesystem::path(argv[0]).filename().native()
132  << " <-c <config-file>> <other-options> [<source-file>]+\n\n"
133  << "Basic options";
134  bpo::options_description all_desc{descstr.str()};
135  all_desc.add(in_desc);
136  // BasicOptionsHandler should always be first in the list!
137  handlers.emplace(handlers.begin(),
138  new BasicOptionsHandler{all_desc, lookupPolicy});
139  // BasicPostProcessor should be last.
140  handlers.emplace_back(new BasicPostProcessor);
141  // This must be added separately: how to deal with any non-option arguments.
142  bpo::positional_options_description pd;
143  // A single non-option argument will be taken to be the source data file.
144  pd.add("source", -1);
145  // Parse the command line.
146  bpo::variables_map vm;
147  try {
148  bpo::store(bpo::command_line_parser(argc, argv)
149  .options(all_desc)
150  .positional(pd)
151  .run(),
152  vm);
153  bpo::notify(vm);
154  }
155  catch (bpo::error const& e) {
156  std::cerr << "Exception from command line processing in " << argv[0]
157  << ": " << e.what() << "\n";
158  return 88;
159  }
160  // Preliminary argument checking.
161  for (auto& handler : handlers) {
162  auto result = handler->checkOptions(vm);
163  if (result != 0) {
164  return result;
165  }
166  }
167  // Processing of arguments and post-processing of config.
168  fhicl::intermediate_table raw_config;
169  for (auto& handler : handlers) {
170  auto result = handler->processOptions(vm, raw_config);
171  if (result != 0) {
172  return result;
173  }
174  }
175  //
176  // Make the parameter set from the intermediate table:
177  //
178  fhicl::ParameterSet main_pset;
179  try {
180  make_ParameterSet(raw_config, main_pset);
181  }
182  catch (cet::exception const& e) {
183  constexpr cet::HorizontalRule rule{36};
184  std::cerr << "ERROR: Failed to create a parameter set from parsed "
185  "configuration with exception "
186  << e.what() << ".\n";
187  std::cerr << " Intermediate configuration state follows:\n"
188  << rule('-') << '\n'
189  << rule('-') << '\n';
190  for (auto const& item : raw_config) {
191  std::cerr << item.first << ": " << item.second.to_string() << '\n';
192  }
193  std::cerr << rule('-') << '\n' << rule('-') << '\n';
194  return 91;
195  }
196 
197  // Main parameter set must be placed in registry manually.
198  try {
200  }
201  catch (...) {
202  std::cerr << "Uncaught exception while inserting main parameter set into "
203  "registry.\n";
204  throw;
205  }
206  return run_art_common_(main_pset);
207  }
208 
209  int
210  run_art_string_config(std::string const& config_string)
211  {
212  //
213  // Make the parameter set from the configuration string:
214  //
215  fhicl::ParameterSet main_pset;
216  try {
217  // create an intermediate table from the input string
218  fhicl::intermediate_table raw_config;
219  parse_document(config_string, raw_config);
220  // run post-processing
221  bpo::variables_map vm;
222  BasicPostProcessor bpp;
223  bpp.processOptions(vm, raw_config);
224  // create the parameter set
225  make_ParameterSet(raw_config, main_pset);
226  }
227  catch (cet::exception& e) {
228  constexpr cet::HorizontalRule rule{36};
229  std::cerr << "ERROR: Failed to create a parameter set from an input "
230  "configuration string with exception "
231  << e.what() << ".\n";
232  std::cerr << " Input configuration string follows:\n"
233  << rule('-') << rule('-') << "\n";
234  std::cerr << config_string << "\n";
235  std::cerr << rule('-') << rule('-') << '\n';
236  return 91;
237  }
238  // Main parameter set must be placed in registry manually.
239  try {
241  }
242  catch (...) {
243  std::cerr << "Uncaught exception while inserting main parameter set into "
244  "registry.\n";
245  throw;
246  }
247  return run_art_common_(main_pset);
248  }
249 
250  int
252  {
253  auto const& services_pset =
254  main_pset.get<fhicl::ParameterSet>("services", {});
255  auto const& scheduler_pset =
256  services_pset.get<fhicl::ParameterSet>("scheduler", {});
257 
258  // Handle early configuration-debugging
259  auto const debug_processing_mode =
260  maybe_output_config(main_pset, scheduler_pset);
261  if (debug_processing_mode == debug_processing::debug_config) {
262  return detail::info_success(); // Bail out early
263  }
264 
265  //
266  // Start the messagefacility
267  //
268  mf::SetIteration("JobSetup");
269  try {
271  services_pset.get<fhicl::ParameterSet>("message", {}));
272  }
273  catch (cet::exception const& e) {
274  std::cerr << e.what() << '\n';
275  return 69;
276  }
277  catch (std::exception const& e) {
278  std::cerr << e.what() << '\n';
279  return 70;
280  }
281  catch (...) {
282  std::cerr << "Caught unknown exception while initializing the message "
283  "facility.\n";
284  return 71;
285  }
286 
287  mf::LogInfo("MF_INIT_OK") << "Messagelogger initialization complete.";
288  //
289  // Initialize:
290  // unix signal facility
291  art::setupSignals(scheduler_pset.get<bool>("enableSigInt", true));
292 
293  int rc{0};
294  try {
295  EventProcessor ep{main_pset};
296  // Behavior of validate_config is to validate FHiCL syntax *and*
297  // user-specified configurations of paths, modules, services, etc.
298  // It is thus possible that an exception thrown during
299  // construction of the EventProcessor object can have nothing to
300  // do with a configuration error.
301  if (debug_processing_mode == debug_processing::validate_config) {
302  return detail::info_success(); // Bail out early
303  }
304  if (scheduler_pset.has_key("dataDependencyGraph")) {
305  return detail::info_success(); // Bail out early
306  }
307  if (ep.runToCompletion() == EventProcessor::epSignal) {
308  std::cerr << "Art has handled signal " << art::shutdown_flag << ".\n";
309  if (scheduler_pset.get<bool>("errorOnSIGINT")) {
310  rc = 128 + art::shutdown_flag;
311  }
312  }
313  }
314  catch (Exception const& e) {
315  rc = e.returnCode();
316  printArtException(e, "art");
317  }
318  catch (cet::exception const& e) {
319  rc = 65;
320  printArtException(e, "art");
321  }
322  catch (std::bad_alloc const& bda) {
323  rc = 68;
324  printBadAllocException("art");
325  }
326  catch (std::exception const& e) {
327  rc = 66;
328  printStdException(e, "art");
329  }
330  catch (...) {
331  rc = 67;
332  printUnknownException("art");
333  }
334  return rc;
335  }
336 }
void SetIteration(string const &val)
static ParameterSetID const & put(ParameterSet const &ps)
int run_art(int argc, char **argv, bpo::options_description &in_desc, cet::filepath_maker &lookupPolicy, OptionsHandlers &&handlers)
Definition: run_art.cc:123
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
std::atomic< int > shutdown_flag
void make_ParameterSet(intermediate_table const &tbl, ParameterSet &ps)
void printStdException(std::exception const &e, char const *prog)
void printUnknownException(char const *prog)
void StartMessageFacility(fhicl::ParameterSet const &pset, string const &applicationName)
int run_art_string_config(std::string const &config_string)
Definition: run_art.cc:210
T get(std::string const &key) const
Definition: ParameterSet.h:231
std::string to_indented_string() const
std::vector< std::unique_ptr< art::OptionsHandler >> OptionsHandlers
bool has_key(std::string const &key) const
void setupSignals(bool want_sigint_enabled)
int processOptions(bpo::variables_map const &vm, fhicl::intermediate_table &raw_config)
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
int run_art_common_(fhicl::ParameterSet const &main_pset)
Definition: run_art.cc:251
debug_processing
Definition: run_art.cc:77
void printArtException(cet::exception const &e, char const *prog)
bool is_key_to_atom(std::string const &key) const
Definition: ParameterSet.h:161
constexpr int info_success()
Definition: info_success.h:9
HLT enums.
void printBadAllocException(char const *prog)
Float_t e
Definition: plot.C:34
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
void parse_document(std::string const &filename, cet::filepath_maker &maker, intermediate_table &result)
Definition: parse.cc:856