EventProcessorTestOutput_module.cc
Go to the documentation of this file.
1 // ======================================================================
2 //
3 // EventProcessorTestOutput: Allows testing the output-file switching
4 // mechanism. See OUTPUT_COMMENT macro below.
5 //
6 // ======================================================================
7 
17 #include "fhiclcpp/types/TupleAs.h"
18 
19 using namespace art;
20 
21 namespace {
22  class SwitchPoint {
23  public:
24  explicit SwitchPoint() = default;
25 
26  explicit SwitchPoint(std::string const& filename,
27  std::vector<std::uint32_t> const& idNumbers)
28  : filename_{filename}
29  {
30  if (filename_.empty()) {
32  << "Cannot create a valid SwitchPoint object with an empty filename.";
33  }
34 
35  if (idNumbers.empty()) {
36  return;
37  }
38 
39  switch (idNumbers.size()) {
40  // N.B. Rely on fall-through behavior to set all relevant data.
41  case 3ull:
42  e_ = idNumbers[2];
43  [[fallthrough]];
44  case 2ull:
45  sr_ = idNumbers[1];
46  [[fallthrough]];
47  case 1ull:
48  r_ = idNumbers[0];
49  break;
50  default:
52  << "Specified too many id numbers.";
53  }
54  }
55 
56  bool
57  valid() const
58  {
59  return filename_ != "";
60  } // Very weak check, but probably sufficient for this test.
61 
62  bool
63  matches(std::string const& fn) const
64  {
65  return filename_ == fn;
66  }
67 
68  bool
69  matches(std::string const& fn, RunID const& id) const
70  {
71  return matches(fn) && r_ == id.run();
72  }
73 
74  bool
75  matches(std::string const& fn, SubRunID const& id) const
76  {
77  return matches(fn, id.runID()) && sr_ == id.subRun();
78  }
79 
80  bool
81  matches(std::string const& fn, EventID const& id) const
82  {
83  return matches(fn, id.subRunID()) && e_ == id.event();
84  }
85 
86  private:
87  std::string filename_{};
91  };
92 } // namespace
93 
94 #define OUTPUT_COMMENT \
95  "To indicate where an output file should switch, one can\n" \
96  "specify the switch points via:\n\n" \
97  " switchAfter: [\n" \
98  " [\"a.txt\", [1] ], # ==> Switch after Run 1 in file \"a.txt\"\n" \
99  " [\"a.txt\", [] ], # ==> Switch after file \"a.txt\"\n" \
100  " [\"b.txt\", [1,4] ], # ==> Switch after Run 1, SubRun 4 in file " \
101  "\"b.txt\"\n" \
102  " [\"b.txt\", [2,3,7]] # ==> Switch after Run 2, SubRun 3, Event 7 in " \
103  "file \"b.txt\"\n" \
104  " ]\n\n" \
105  "Note that the switching behavior should be put in the order that\n" \
106  "the switching is expected--e.g. it would be an error to\n" \
107  "specify [\"a.txt\", []] as the first item since that would\n" \
108  "tell the module to switch after the first file has been\n" \
109  "processed, and then switch after Run 1 in file \"a.txt\". In\n" \
110  "other words, no sorting is done of the specified switch points."
111 
112 namespace arttest {
113 
114  class EventProcessorTestOutput final : public OutputModule {
115  public:
116  struct Config {
120  switchAfter{fhicl::Name("switchAfter"),
122  std::vector<SwitchPoint>{}};
123  };
124 
125  using Parameters =
128  : OutputModule{ps().omConfig, ps.get_PSet()}
129  , switchPoints_{ps().switchAfter()}
130  {
131  if (!switchPoints_.empty()) {
132  activeSwitchPoint_ = switchPoints_.front();
133  }
134  }
135 
136  private:
137  void
138  respondToOpenInputFile(FileBlock const& fb) override
139  {
140  currentInputFileName_ = fb.fileName();
141  }
142 
143  void
144  write(EventPrincipal& ep) override
145  {
146  requestsFileClose_ =
147  activeSwitchPoint_.matches(currentInputFileName_, ep.eventID());
148  if (requestsFileClose_) {
149  updateSwitchPoints();
150  }
151  }
152 
153  void
155  {
156  requestsFileClose_ =
157  activeSwitchPoint_.matches(currentInputFileName_, srp.subRunID());
158  if (requestsFileClose_) {
159  updateSwitchPoints();
160  }
161  }
162 
163  void
164  writeRun(RunPrincipal& rp) override
165  {
166  requestsFileClose_ =
167  activeSwitchPoint_.matches(currentInputFileName_, rp.runID());
168  if (requestsFileClose_) {
169  updateSwitchPoints();
170  }
171  }
172 
173  void
175  {
176  requestsFileClose_ = activeSwitchPoint_.matches(currentInputFileName_);
177  if (requestsFileClose_) {
178  updateSwitchPoints();
179  }
180  }
181 
182  bool
183  requestsToCloseFile() const override
184  {
185  return requestsFileClose_;
186  }
187 
189  fileGranularity() const override
190  {
191  return Granularity::Event;
192  }
193 
194  void
196  {
197  assert(activeSwitchPoint_.valid());
198  if (switchPoints_.empty()) {
199  // Invalidate the next switch point--matching against a
200  // default-constructed SwitchPoint will always return false.
201  activeSwitchPoint_ = SwitchPoint{};
202  } else {
203  // Pop the front
204  switchPoints_.erase(cbegin(switchPoints_));
205  activeSwitchPoint_ = switchPoints_.front();
206  }
207  }
208 
209  std::vector<SwitchPoint> switchPoints_;
210  SwitchPoint activeSwitchPoint_{};
211  std::string currentInputFileName_{};
212  bool requestsFileClose_{false};
213  };
214 
215 } // namespace arttest
216 #undef OUTPUT_COMMENT
EventID const & eventID() const
Definition: Principal.cc:1064
RunID const & runID() const
Definition: Principal.cc:1052
std::string string
Definition: nybbler.cc:12
auto const & get_PSet() const
ChannelGroupService::Name Name
void writeSubRun(SubRunPrincipal &srp) override
void respondToOpenInputFile(FileBlock const &fb) override
string filename
Definition: train.py:213
QAsciiDict< Entry > fn
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
std::string const & fileName() const
Definition: FileBlock.cc:29
SubRunID subRunID() const
Definition: Principal.cc:1058
IDNumber_t< Level::SubRun > SubRunNumber_t
Definition: IDNumber.h:119
static constexpr double ps
Definition: Units.h:99
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
#define Comment
IDNumber_t< Level::Event > EventNumber_t
Definition: IDNumber.h:118
decltype(auto) constexpr cbegin(T &&obj)
ADL-aware version of std::cbegin.
Definition: StdUtils.h:82
#define OUTPUT_COMMENT
fhicl::TableFragment< OutputModule::Config > omConfig
IDNumber_t< Level::Run > RunNumber_t
Definition: IDNumber.h:120