ProcessingOptionsHandler.cc
Go to the documentation of this file.
2 
7 #include "tbb/task_arena.h"
8 
9 #include <string>
10 
11 using namespace std::string_literals;
13 
14 namespace {
15 
17 
18  // For 'fillTable' the behavior is as follows:
19  //
20  // (1) If the program option is specified at the command line, the
21  // corresponding FHiCL parameter is added to the intermediate
22  // table (if it doesn't already exist), or the corresponding
23  // value is overwritten (if the parameter does already exist).
24  //
25  // (2) If the program option is not specified AND the FHiCL file
26  // does not have the corresponding parameter, then a default
27  // value of 'true' is added to the FHiCL configuration.
28  //
29  // This function could be made more general, but there is currently
30  // no need.
31 
32  void
33  fillTable(std::string const& bpo_key,
34  std::string const& fhicl_key,
35  bpo::variables_map const& vm,
37  bool const default_value)
38  {
39  if (vm.count(bpo_key)) {
40  config.put(fhicl_key, vm[bpo_key].as<bool>());
41  } else if (!exists_outside_prolog(config, fhicl_key)) {
42  config.put(fhicl_key, default_value);
43  }
44  }
45 
46 } // namespace
47 
49  bpo::options_description& desc)
50 {
51  bpo::options_description processing_options{"Processing options"};
52  // clang-format off
53  processing_options.add_options()
54  ("parallelism,j",
55  bpo::value<int>(),
56  "Number of threads AND schedules to use for event processing "
57  "(default = 1, 0 = all cores).")
58  ("nschedules",
59  bpo::value<int>(),
60  "Number of schedules to use for event processing (default = 1)")
61  // Note: tbb wants nthreads to be an int!
62  ("nthreads",
63  bpo::value<int>(),
64  "Number of threads to use for event processing (default = 1, 0 = all "
65  "cores)")
66  ("default-exceptions",
67  "Some exceptions may be handled differently by default (e.g. "
68  "ProductNotFound).")
69  ("rethrow-default", "All exceptions default to rethrow.")
70  ("rethrow-all",
71  "All exceptions overridden to rethrow (cf rethrow-default).")
72  ("errorOnMissingConsumes",
73  bpo::value<bool>()->implicit_value(true, "true"),
74  "If 'true', then an exception will be thrown if any module attempts "
75  "to retrieve a product via the 'getBy*' interface without specifying "
76  "the appropriate 'consumes<T>(...)' statement in the module constructor.")
77  ("errorOnSIGINT",
78  bpo::value<bool>()->implicit_value(true, "true"),
79  "If 'true', a signal received from the user yields an art return code "
80  "corresponding to an error; otherwise return 0.");
81  // clang-format on
82  desc.add(processing_options);
83 }
84 
85 int
86 art::ProcessingOptionsHandler::doCheckOptions(bpo::variables_map const& vm)
87 {
88  if ((vm.count("rethrow-all") + vm.count("rethrow-default") +
89  vm.count("no-rethrow-default")) > 1) {
91  << "Options --default-exceptions, --rethrow-all, and --rethrow-default "
92  "\n"
93  << "are mutually incompatible.\n";
94  }
95 
96  // 'parallelism' is incompatible with either 'nthreads' or
97  // 'nschedules'.
98  if (vm.count("parallelism")) {
99  if (vm.count("nthreads") or vm.count("nschedules")) {
100  throw Exception(errors::Configuration) << "The -j/--parallelism option "
101  "cannot be used with either "
102  "--nthreads or --nschedules.\n";
103  }
104  }
105 
106  if (vm.count("nthreads") and vm["nthreads"].as<int>() < 0) {
108  << "Option --nthreads must greater than or equal to 0.";
109  }
110  if (vm.count("nschedules") and vm["nschedules"].as<int>() < 1) {
112  << "Option --nschedules must be at least 1.\n";
113  }
114  return 0;
115 }
116 
117 int
119  bpo::variables_map const& vm,
120  fhicl::intermediate_table& raw_config)
121 {
122  auto const scheduler_key = fhicl_key("services", "scheduler");
123 
124  if (vm.count("rethrow-all") == 1 || vm.count("rethrow-default") == 1) {
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("errorOnMissingConsumes",
135  fhicl_key(scheduler_key, "errorOnMissingConsumes"),
136  vm,
137  raw_config,
138  false);
139  fillTable("errorOnSIGINT",
140  fhicl_key(scheduler_key, "errorOnSIGINT"),
141  vm,
142  raw_config,
143  true);
144 
145  auto const num_schedules_key = fhicl_key(scheduler_key, "num_schedules");
146  auto const num_threads_key = fhicl_key(scheduler_key, "num_threads");
147  if (vm.count("parallelism")) {
148  // 'nthreads' and 'nschedules' are set to the same value.
149  auto const j = vm["parallelism"].as<int>();
150  auto const nthreads =
151  (j == 0) ? tbb::this_task_arena::max_concurrency() : j;
152  raw_config.put(num_schedules_key, nthreads);
153  raw_config.put(num_threads_key, nthreads);
154  return 0;
155  }
156 
157  if (vm.count("nschedules")) {
158  raw_config.put(num_schedules_key, vm["nschedules"].as<int>());
159  }
160  if (vm.count("nthreads")) {
161  auto const nt = vm["nthreads"].as<int>();
162  auto const nthreads =
163  (nt == 0) ? tbb::this_task_arena::max_concurrency() : nt;
164  raw_config.put(num_threads_key, nthreads);
165  }
166 
167  // If 'nschedules' or 'nthreads' does not exist in configuration,
168  // assign the default value of 1.
169  if (not exists_outside_prolog(raw_config, num_schedules_key)) {
170  raw_config.put(num_schedules_key, 1);
171  }
172  if (not exists_outside_prolog(raw_config, num_threads_key)) {
173  raw_config.put(num_threads_key, 1);
174  }
175 
176  return 0;
177 }
int doCheckOptions(bpo::variables_map const &vm) override
ProcessingOptionsHandler(bpo::options_description &desc)
bool exists_outside_prolog(fhicl::intermediate_table const &config, std::string const &key)
std::string string
Definition: nybbler.cc:12
bool putEmptySequence(std::string const &name, bool in_prolog=false)
static Config * config
Definition: config.cpp:1054
std::enable_if_t< std::is_convertible_v< T, std::string >, std::string > fhicl_key(T const &name)
Definition: fhicl_key.h:12
bool put(std::string const &name, std::string const &value, bool in_prolog=false)
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