LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
FileIndex.cc
Go to the documentation of this file.
2 // vim: set sw=2 expandtab :
3 
6 #include "cetlib/container_algorithms.h"
8 
9 #include <cassert>
10 #include <iomanip>
11 #include <ostream>
12 
13 using namespace cet;
14 using namespace std;
15 
16 namespace {
17 
18  bool
19  subRunUnspecified(art::EventID const& eID)
20  {
21  // This is nasty, principally because we don't want to be
22  // encouraging too many people to do this. Basically, we're
23  // checking whether the only reason an EventID is invalid is
24  // because its subRun number is invalid.
25  return (!eID.isValid()) && eID.runID().isValid() &&
26  art::EventID(art::SubRunID::firstSubRun(), eID.event()).isValid();
27  }
28 
29 } // unnamed namespace
30 
31 namespace art {
32 
33  FileIndex::EntryNumber_t constexpr FileIndex::Element::invalid;
34 
35  FileIndex::Element::Element(EventID const& eID) : Element(eID, invalid) {}
36 
38  EntryNumber_t const entryNumber)
39  : eventID{eID}, entry{entryNumber}
40  {}
41 
44  {
45  return eventID.isValid() ? kEvent :
47  }
48 
51  {
52  return entries_.begin();
53  }
54 
57  {
58  return entries_.begin();
59  }
60 
63  {
64  return entries_.begin();
65  }
66 
69  {
70  return entries_.end();
71  }
72 
75  {
76  return entries_.end();
77  }
78 
81  {
82  return entries_.end();
83  }
84 
85  std::vector<FileIndex::Element>::size_type
87  {
88  return entries_.size();
89  }
90 
91  bool
93  {
94  return entries_.empty();
95  }
96 
97  bool&
99  {
100  return transients_.get().allInEntryOrder;
101  }
102 
103  bool&
105  {
106  return transients_.get().resultCached;
107  }
108 
111  {
112  return transients_.get().sortState;
113  }
114 
115  bool
116  FileIndex::contains(EventID const& id, bool exact) const
117  {
118  return findPosition(id, exact) != entries_.end();
119  }
120 
121  bool
122  FileIndex::contains(SubRunID const& id, bool exact) const
123  {
124  return findPosition(id, exact) != entries_.end();
125  }
126 
127  bool
128  FileIndex::contains(RunID const& id, bool exact) const
129  {
130  return findPosition(id, exact) != entries_.end();
131  }
132 
133  void
135  {
136  entries_.emplace_back(eID, entry);
137  resultCached() = false;
138  sortState() = kNotSorted;
139  }
140 
141  void
143  {
144  entries_.emplace_back(eID, entry);
145  resultCached() = false;
146  }
147 
148  void
150  {
151  stable_sort_all(entries_);
152  resultCached() = false;
154  }
155 
156  void
158  {
159  stable_sort_all(entries_, Compare_Run_SubRun_EventEntry());
160  resultCached() = false;
162  }
163 
164  bool
166  {
167  if (!resultCached()) {
168  resultCached() = true;
170  for (auto const& e : entries_) {
171  if (e.getEntryType() == kEvent) {
172  if (e.entry < maxEntry) {
173  allInEntryOrder() = false;
174  return false;
175  }
176  maxEntry = e.entry;
177  }
178  }
179  allInEntryOrder() = true;
180  return true;
181  }
182  return allInEntryOrder();
183  }
184 
185  bool
187  {
188  auto it = cbegin();
189  auto itEnd = cend();
190  // Set up the iterators to point to first two events
191  // (In the trivial case where there is zero or one event,
192  // the set is unique and ordered by construction).
193  if (it == itEnd) {
194  return true;
195  }
196  // Step to first event
197  while (it->getEntryType() != kEvent) {
198  ++it;
199  if (it == itEnd) {
200  return true;
201  }
202  }
203  auto itPrevious = it;
204  // Step to second event
205  ++it;
206  if (it == itEnd) {
207  return true;
208  }
209  while (it->getEntryType() != kEvent) {
210  ++it;
211  if (it == itEnd) {
212  return true;
213  }
214  }
215  for (; it != itEnd; ++it) {
216  if (it->getEntryType() == kEvent) {
217  if (it->eventID <= itPrevious->eventID) {
218  return false;
219  }
220  itPrevious = it;
221  }
222  }
223  return true; // finished and found no duplicates
224  }
225 
228  {
229  assert(sortState() == kSorted_Run_SubRun_Event);
230  Element el{eID};
231  return lower_bound_all(entries_, el);
232  }
233 
235  FileIndex::findPosition(EventID const& eID, bool exact) const
236  {
237  assert(sortState() == kSorted_Run_SubRun_Event);
238  if (subRunUnspecified(eID)) {
239  return findEventForUnspecifiedSubRun(eID, exact);
240  }
241  const_iterator it = findPosition(eID);
242  const_iterator itEnd = entries_.end();
243  while (it != itEnd && it->getEntryType() != FileIndex::kEvent) {
244  ++it;
245  }
246  if (it == itEnd) {
247  return itEnd;
248  }
249  if (exact && (*it != eID)) {
250  return itEnd;
251  }
252  return it;
253  }
254 
256  FileIndex::findPosition(SubRunID const& srID, bool exact) const
257  {
258  assert(sortState() != kNotSorted);
259  const_iterator it;
260  auto const invID = EventID::invalidEvent(srID);
262  Element const el{invID};
263  it = lower_bound_all(entries_, el, Compare_Run_SubRun_EventEntry());
264  } else {
265  it = findPosition(invID);
266  }
267  auto const itEnd = entries_.cend();
268  while (it != itEnd && it->getEntryType() != FileIndex::kSubRun) {
269  ++it;
270  }
271  if (it == itEnd) {
272  return itEnd;
273  }
274  if (exact && (it->eventID.subRunID() != srID)) {
275  return itEnd;
276  }
277  return it;
278  }
279 
281  FileIndex::findPosition(RunID const& rID, bool exact) const
282  {
283  assert(sortState() != kNotSorted);
284  const_iterator it;
285  auto const invID = EventID::invalidEvent(rID);
287  Element const el{invID};
288  it = lower_bound_all(entries_, el, Compare_Run_SubRun_EventEntry());
289  } else {
290  it = findPosition(invID);
291  }
292  auto const itEnd = entries_.cend();
293  while (it != itEnd && it->getEntryType() != FileIndex::kRun) {
294  ++it;
295  }
296  if (it == itEnd) {
297  return itEnd;
298  }
299  if (exact && (it->eventID.runID() != rID)) {
300  return itEnd;
301  }
302  return it;
303  }
304 
307  {
308  assert(sortState() != kNotSorted);
309  const_iterator it;
311  Element el{EventID::invalidEvent(srID)};
312  it = lower_bound_all(entries_, el, Compare_Run_SubRun_EventEntry());
313  } else {
315  }
316  auto const itEnd = entries_.cend();
317  while (it != itEnd && it->getEntryType() != FileIndex::kSubRun &&
318  it->getEntryType() != FileIndex::kRun) {
319  ++it;
320  }
321  return it;
322  }
323 
324  void
325  FileIndex::print_event_list(ostream& os) const
326  {
327  os << "\nPrinting the list of Runs, SubRuns, and Events stored in the root "
328  "file.\n\n";
329  os << setw(15) << "Run" << setw(15) << "SubRun" << setw(15) << "Event"
330  << "\n";
331  for (auto const& e : entries_) {
332  if (e.getEntryType() == FileIndex::kEvent) {
333  os << setw(15) << e.eventID.run() << setw(15) << e.eventID.subRun()
334  << setw(15) << e.eventID.event() << "\n";
335  } else if (e.getEntryType() == FileIndex::kSubRun) {
336  os << setw(15) << e.eventID.run() << setw(15) << e.eventID.subRun()
337  << setw(15) << " "
338  << "\n";
339  } else if (e.getEntryType() == FileIndex::kRun) {
340  os << setw(15) << e.eventID.run() << setw(15) << " " << setw(15) << " "
341  << "\n";
342  }
343  }
344  }
345 
347  FileIndex::findEventForUnspecifiedSubRun(EventID const& eID, bool exact) const
348  {
349  RunID const& runID = eID.runID();
350  EventNumber_t event = eID.event();
351  SubRunID last_subRunID;
352  // Try to find the event.
353  auto const firstEvent =
355  const_iterator it = firstEvent;
356  const_iterator const itEnd = entries_.end();
357  if (it == itEnd) {
358  return it;
359  }
360 
361  // Starting with it, jump to the first event of each subrun until
362  // we find either:
363  //
364  // 1. The next run.
365  // 2. An event number higher than we want.
366  // 3. The end of the file index.
367  while ((it != itEnd) && (it->eventID.runID() == runID) &&
368  (it->eventID.event() < event)) {
369  last_subRunID = it->eventID.subRunID();
370  // Get the first event in the next subrun.
371  it =
372  findPosition(EventID::firstEvent(it->eventID.subRunID().next()), false);
373  }
374  const_iterator result = itEnd;
375  if ((it != itEnd) && (it->eventID.runID() == runID) &&
376  (it->eventID.event() == event)) {
377  // We started on the correct event.
378  result = it;
379  } else if (last_subRunID.isValid()) {
380  // Find the event in the last subrun.
381  result = findPosition(EventID(last_subRunID, event), exact);
382  }
383  if (result == itEnd) {
384  // Did not find anything.
385  mf::LogWarning("FileIndex")
386  << "Could not find incompletely specified event " << eID
387  << " with smart algorithm:\n"
388  << "Assuming pathological file structure (event selection?) and\n"
389  << "trying again (inefficient).\n"
390  << "NOTE: this will find only the event with matching event number "
391  << "and the\n"
392  << " lowest subrun number: any others are inaccessible via this "
393  << "method.";
394  SubRunID trySubRun{SubRunID::firstSubRun(runID)};
395  // Try to find the highest subrun number in this run.
396  const_iterator findIt(firstEvent);
397  SubRunID lastSubRunInRun{trySubRun};
398  for (; findIt != itEnd && findIt->eventID.runID() == runID;
399  findIt =
400  findPosition(EventID::firstEvent(lastSubRunInRun.next()), false)) {
401  lastSubRunInRun = findIt->eventID.subRunID();
402  }
403  // Now loop through each subrun looking for an exact match to our event.
404  while ((findIt = findPosition(EventID(trySubRun, event), true)) ==
405  itEnd &&
406  trySubRun < lastSubRunInRun) {
407  trySubRun = trySubRun.next();
408  }
409  result = findIt;
410  }
411  return result;
412  }
413 
414  bool
416  {
417  return lh.eventID < rh.eventID;
418  }
419 
420  bool
422  {
423  return rh < lh;
424  }
425 
426  bool
428  {
429  return !(lh < rh);
430  }
431 
432  bool
434  {
435  return !(rh < lh);
436  }
437 
438  bool
440  {
441  return !(lh < rh || rh < lh);
442  }
443 
444  bool
446  {
447  return !(lh == rh);
448  }
449 
450  bool
451  operator==(FileIndex const& lh, FileIndex const& rh)
452  {
453  return lh.entries_ == rh.entries_;
454  }
455 
456  bool
457  operator!=(FileIndex const& lh, FileIndex const& rh)
458  {
459  return !(lh == rh);
460  }
461 
462  bool
464  FileIndex::Element const& rh)
465  {
466  if (lh.eventID.subRunID() == rh.eventID.subRunID()) {
467  if ((!lh.eventID.isValid()) && (!rh.eventID.isValid())) {
468  return false;
469  } else if (!lh.eventID.isValid()) {
470  return true;
471  } else if (!rh.eventID.isValid()) {
472  return false;
473  }
474  return lh.entry < rh.entry;
475  }
476  return lh.eventID.subRunID() < rh.eventID.subRunID();
477  }
478 
479  ostream&
480  operator<<(ostream& os, FileIndex::Element const& el)
481  {
482  os << el.eventID << ": entry# " << el.entry;
483  return os;
484  }
485 
486  ostream&
487  operator<<(ostream& os, FileIndex const& fileIndex)
488  {
489  os << "\nPrinting FileIndex contents. This includes a list of all Runs, "
490  "SubRuns\n"
491  << "and Events stored in the root file.\n\n";
492  os << setw(15) << "Run" << setw(15) << "SubRun" << setw(15) << "Event"
493  << setw(15) << "TTree Entry"
494  << "\n";
495  for (auto const& e : fileIndex) {
496  if (e.getEntryType() == FileIndex::kEvent) {
497  os << setw(15) << e.eventID.run() << setw(15) << e.eventID.subRun()
498  << setw(15) << e.eventID.event() << setw(15) << e.entry << "\n";
499  } else if (e.getEntryType() == FileIndex::kSubRun) {
500  os << setw(15) << e.eventID.run() << setw(15) << e.eventID.subRun()
501  << setw(15) << " " << setw(15) << e.entry << " (SubRun)"
502  << "\n";
503  } else if (e.getEntryType() == FileIndex::kRun) {
504  os << setw(15) << e.eventID.run() << setw(15) << " " << setw(15) << " "
505  << setw(15) << e.entry << " (Run)"
506  << "\n";
507  }
508  }
509  return os;
510  }
511 
512 } // namespace art
bool isValid() const
Definition: EventID.h:122
RunID const & runID() const
Definition: EventID.h:92
SubRunID const & subRunID() const
Definition: EventID.h:104
void addEntryOnLoad(EventID const &eID, EntryNumber_t entry)
Definition: FileIndex.cc:142
Transient< Transients > transients_
Definition: FileIndex.h:127
std::vector< Element >::iterator iterator
Definition: FileIndex.h:64
iterator begin()
Definition: FileIndex.cc:50
bool operator>(ScheduleID const left, ScheduleID const right) noexcept
Definition: ScheduleID.cc:53
const_iterator findSubRunOrRunPosition(SubRunID const &srID) const
Definition: FileIndex.cc:306
art::FileIndex::EntryNumber_t EntryNumber_t
friend bool operator==(FileIndex const &, FileIndex const &)
Definition: FileIndex.cc:451
bool allEventsInEntryOrder() const
Definition: FileIndex.cc:165
STL namespace.
SortState & sortState() const
Definition: FileIndex.cc:110
bool operator()(FileIndex::Element const &lh, FileIndex::Element const &rh)
Definition: FileIndex.cc:463
void sortBy_Run_SubRun_EventEntry()
Definition: FileIndex.cc:157
bool & allInEntryOrder() const
Definition: FileIndex.cc:98
bool operator!=(ScheduleID const left, ScheduleID const right) noexcept
Definition: ScheduleID.cc:41
long long EntryNumber_t
Definition: FileIndex.h:41
bool empty() const
Definition: FileIndex.cc:92
bool isValid() const
Definition: SubRunID.h:97
std::vector< Element >::size_type size() const
Definition: FileIndex.cc:86
std::ostream & operator<<(std::ostream &os, const GroupSelector &gs)
bool operator<(ProductInfo const &a, ProductInfo const &b)
Definition: ProductInfo.cc:51
SubRunID next() const
Definition: SubRunID.h:111
bool operator<=(ScheduleID const left, ScheduleID const right) noexcept
Definition: ScheduleID.cc:47
void print_event_list(std::ostream &os) const
Definition: FileIndex.cc:325
const_iterator findEventForUnspecifiedSubRun(EventID const &eID, bool exact) const
Definition: FileIndex.cc:347
const_iterator cbegin() const
Definition: FileIndex.cc:62
void sortBy_Run_SubRun_Event()
Definition: FileIndex.cc:149
const_iterator findPosition(EventID const &eID) const
Definition: FileIndex.cc:227
void addEntry(EventID const &eID, EntryNumber_t entry)
Definition: FileIndex.cc:134
static SubRunID firstSubRun()
Definition: SubRunID.h:153
bool eventsUniqueAndOrdered() const
Definition: FileIndex.cc:186
EntryType getEntryType() const
Definition: FileIndex.cc:43
iterator end()
Definition: FileIndex.cc:68
std::vector< Element >::const_iterator const_iterator
Definition: FileIndex.h:63
bool contains(EventID const &id, bool exact) const
Definition: FileIndex.cc:116
static constexpr EntryNumber_t invalid
Definition: FileIndex.h:51
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
static constexpr EventID invalidEvent() noexcept
Definition: EventID.h:202
IDNumber_t< Level::Event > EventNumber_t
Definition: IDNumber.h:118
bool isValid() const
Definition: RunID.h:70
Definition: MVAAlg.h:12
EventNumber_t event() const
Definition: EventID.h:116
bool operator>=(ScheduleID const left, ScheduleID const right) noexcept
Definition: ScheduleID.cc:59
const_iterator cend() const
Definition: FileIndex.cc:80
Float_t e
Definition: plot.C:35
static EventID firstEvent()
Definition: EventID.h:190
std::vector< Element > entries_
Definition: FileIndex.h:126
EntryNumber_t entry
Definition: FileIndex.h:60
Event finding and building.
bool & resultCached() const
Definition: FileIndex.cc:104