LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
ProcessingOptionsHandler.cc
Go to the documentation of this file.
2 
6 #include "fhiclcpp/coding.h"
9 #include "fhiclcpp/parse.h"
10 #include "tbb/task_scheduler_init.h"
11 
12 #include <string>
13 
14 using namespace std::string_literals;
16 
17 namespace {
18 
20 
21  // For 'fillTable' the behavior is as follows:
22  //
23  // (1) If the program option is specified at the command line, the
24  // corresponding FHiCL parameter is added to the intermediate
25  // table (if it doesn't already exist), or the corresponding
26  // value is overwritten (if the parameter does already exist).
27  //
28  // (2) If the program option is not specified AND the FHiCL file
29  // does not have the corresponding parameter, then a default
30  // value of 'true' is added to the FHiCL configuration.
31  //
32  // This function could be made more general, but there is currently
33  // no need.
34 
35  void
36  fillTable(std::string const& bpo_key,
37  std::string const& fhicl_key,
38  bpo::variables_map const& vm,
40  bool const flag_value)
41  {
42  if (vm.count(bpo_key)) {
43  config.put(fhicl_key, vm[bpo_key].as<bool>());
44  } else if (!exists_outside_prolog(config, fhicl_key)) {
45  config.put(fhicl_key, flag_value);
46  }
47  }
48 
49 } // namespace
50 
52  bpo::options_description& desc,
53  bool const rethrowDefault)
54  : rethrowDefault_{rethrowDefault}
55 {
56 
57  bpo::options_description processing_options{"Processing options"};
58  auto options = processing_options.add_options();
59  // Note: tbb wants nthreads to be an int!
60  add_opt(options,
61  "nthreads",
62  bpo::value<int>()->default_value(1),
63  "Number of threads to use for event processing (default = 1, 0 = all "
64  "cores)");
65  add_opt(options,
66  "default-exceptions",
67  "Some exceptions may be handled differently by default (e.g. "
68  "ProductNotFound).");
69  add_opt(options, "rethrow-default", "All exceptions default to rethrow.");
70  add_opt(options,
71  "rethrow-all",
72  "All exceptions overridden to rethrow (cf rethrow-default).");
73  add_opt(
74  options,
75  "errorOnFailureToPut",
76  bpo::value<bool>()->implicit_value(true, "true"),
77  "Global flag that controls the behavior upon failure to 'put' a "
78  "product (declared by 'produces') onto the Event. If 'true', per-module "
79  "flags can override the value of the global flag.");
80  add_opt(
81  options,
82  "errorOnMissingConsumes",
83  bpo::value<bool>()->implicit_value(true, "true"),
84  "If 'true', then an exception will be thrown if any module attempts "
85  "to retrieve a product via the 'getBy*' interface without specifying "
86  "the appropriate 'consumes<T>(...)' statement in the module constructor.");
87  add_opt(
88  options,
89  "errorOnSIGINT",
90  bpo::value<bool>()->implicit_value(true, "true"),
91  "If 'true', a signal received from the user yields an art return code "
92  "corresponding to an error; otherwise return 0.");
93  desc.add(processing_options);
94 }
95 
96 int
97 art::ProcessingOptionsHandler::doCheckOptions(bpo::variables_map const& vm)
98 {
99  if ((vm.count("rethrow-all") + vm.count("rethrow-default") +
100  vm.count("no-rethrow-default")) > 1) {
102  << "Options --default-exceptions, --rethrow-all, and --rethrow-default "
103  "\n"
104  << "are mutually incompatible.\n";
105  }
106 
107  // No need to check for presence of 'nthreads' since it has a
108  // default value.
109  if (vm["nthreads"].as<int>() < 0) {
111  << "Option --nthreads must greater than or equal to 0.";
112  }
113  return 0;
114 }
115 
116 int
118  bpo::variables_map const& vm,
119  fhicl::intermediate_table& raw_config)
120 {
121  std::string const scheduler_key{"services.scheduler"};
122 
123  if (vm.count("rethrow-all") == 1 || vm.count("rethrow-default") == 1 ||
124  (rethrowDefault_ && vm.count("default-exceptions") == 0)) {
125  raw_config.put(fhicl_key(scheduler_key, "defaultExceptions"), false);
126  if (vm.count("rethrow-all") == 1) {
127  raw_config.putEmptySequence(fhicl_key(scheduler_key, "IgnoreCompletely"));
128  raw_config.putEmptySequence(fhicl_key(scheduler_key, "SkipEvent"));
129  raw_config.putEmptySequence(fhicl_key(scheduler_key, "FailModule"));
130  raw_config.putEmptySequence(fhicl_key(scheduler_key, "FailPath"));
131  }
132  }
133 
134  fillTable("errorOnFailureToPut",
135  fhicl_key(scheduler_key, "errorOnFailureToPut"),
136  vm,
137  raw_config,
138  true);
139  fillTable("errorOnMissingConsumes",
140  fhicl_key(scheduler_key, "errorOnMissingConsumes"),
141  vm,
142  raw_config,
143  false);
144  fillTable("errorOnSIGINT",
145  fhicl_key(scheduler_key, "errorOnSIGINT"),
146  vm,
147  raw_config,
148  true);
149 
150  auto const nt = vm["nthreads"].as<int>();
151  auto const nthreads =
152  (nt == 0) ? tbb::task_scheduler_init::default_num_threads() : nt;
153  raw_config.put(fhicl_key(scheduler_key, "num_threads"), nthreads);
154  return 0;
155 }
int doCheckOptions(bpo::variables_map const &vm) override
bool exists_outside_prolog(fhicl::intermediate_table const &config, std::string const &key)
void add_opt(T &t, Args &&...args)
bool putEmptySequence(std::string const &name, bool in_prolog=false)
bool put(std::string const &name, std::string const &value, bool in_prolog=false)
std::enable_if_t< std::is_convertible< T, std::string >::value, std::string > fhicl_key(T const &name)
Definition: fhicl_key.h:13
ProcessingOptionsHandler(bpo::options_description &desc, bool rethrowDefault)
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
int doProcessOptions(bpo::variables_map const &vm, fhicl::intermediate_table &raw_config) override