Public Member Functions | Private Member Functions | Private Attributes | List of all members
art::RootDelayedReader Class Referencefinal

#include <RootDelayedReader.h>

Inheritance diagram for art::RootDelayedReader:
art::DelayedReader

Public Member Functions

 ~RootDelayedReader ()
 
 RootDelayedReader (RootDelayedReader const &)=delete
 
RootDelayedReaderoperator= (RootDelayedReader const &)=delete
 
 RootDelayedReader (RootDelayedReader &&)=delete
 
RootDelayedReaderoperator= (RootDelayedReader &&)=delete
 
 RootDelayedReader (FileFormatVersion, sqlite3 *db, std::vector< input::EntryNumber > const &entrySet, cet::exempt_ptr< input::BranchMap const >, TBranch *provenanceBranch, int64_t saveMemoryObjectThreshold, cet::exempt_ptr< RootInputFile > primaryFile, cet::exempt_ptr< BranchIDLists const > branchIDLists, BranchType branchType, EventID, bool compactSubRunRanges)
 
- Public Member Functions inherited from art::DelayedReader
virtual ~DelayedReader () noexcept
 
 DelayedReader ()
 
std::unique_ptr< EDProductgetProduct (Group const *, ProductID, RangeSet &) const
 
void setPrincipal (cet::exempt_ptr< Principal >)
 
std::vector< ProductProvenancereadProvenance () const
 
bool isAvailableAfterCombine (ProductID) const
 
int openNextSecondaryFile (int idx)
 

Private Member Functions

std::unique_ptr< EDProductgetProduct_ (Group const *, ProductID, RangeSet &) const override
 
void setPrincipal_ (cet::exempt_ptr< Principal >) override
 
std::vector< ProductProvenancereadProvenance_ () const override
 
bool isAvailableAfterCombine_ (ProductID) const override
 
int openNextSecondaryFile_ (int idx) override
 

Private Attributes

FileFormatVersion fileFormatVersion_
 
sqlite3 * db_
 
std::vector< input::EntryNumber > const entrySet_
 
cet::exempt_ptr< input::BranchMap const > branches_
 
TBranch * provenanceBranch_
 
int64_t saveMemoryObjectThreshold_
 
cet::exempt_ptr< Principalprincipal_
 
cet::exempt_ptr< RootInputFileprimaryFile_
 
cet::exempt_ptr< BranchIDLists const > branchIDLists_
 
BranchType branchType_
 
EventID eventID_
 
bool const compactSubRunRanges_
 

Detailed Description

Definition at line 32 of file RootDelayedReader.h.

Constructor & Destructor Documentation

art::RootDelayedReader::~RootDelayedReader ( )
default
art::RootDelayedReader::RootDelayedReader ( RootDelayedReader const &  )
delete
art::RootDelayedReader::RootDelayedReader ( RootDelayedReader &&  )
delete
art::RootDelayedReader::RootDelayedReader ( FileFormatVersion  version,
sqlite3 *  db,
std::vector< input::EntryNumber > const &  entrySet,
cet::exempt_ptr< input::BranchMap const >  branches,
TBranch *  provenanceBranch,
int64_t  saveMemoryObjectThreshold,
cet::exempt_ptr< RootInputFile primaryFile,
cet::exempt_ptr< BranchIDLists const >  branchIDLists,
BranchType  branchType,
EventID  eID,
bool  compactSubRunRanges 
)

Definition at line 34 of file RootDelayedReader.cc.

46  : DelayedReader()
48  , db_{db}
49  , entrySet_{entrySet}
50  , branches_{branches}
51  , provenanceBranch_{provenanceBranch}
52  , saveMemoryObjectThreshold_{saveMemoryObjectThreshold}
53  , primaryFile_{primaryFile}
54  , branchIDLists_{bidLists}
55  , branchType_{branchType}
56  , eventID_{eID}
57  , compactSubRunRanges_{compactSubRunRanges}
58  {}
cet::exempt_ptr< input::BranchMap const > branches_
std::vector< input::EntryNumber > const entrySet_
cet::exempt_ptr< RootInputFile > primaryFile_
cet::exempt_ptr< BranchIDLists const > branchIDLists_
FileFormatVersion fileFormatVersion_

Member Function Documentation

unique_ptr< EDProduct > art::RootDelayedReader::getProduct_ ( Group const *  grp,
ProductID  pid,
RangeSet rs 
) const
overrideprivatevirtual

Implements art::DelayedReader.

Definition at line 130 of file RootDelayedReader.cc.

133  {
134  auto iter = branches_->find(pid);
135  assert(iter != branches_->end());
136  input::BranchInfo const& branchInfo = iter->second;
137  TBranch* br = branchInfo.productBranch_;
138  assert(br != nullptr);
139  auto const& pd = branchInfo.branchDescription_;
140  // Note: It is not an error to attempt to delay read a produced
141  // run or subrun product because there might be many of them spread
142  // across multiple fragments of the same run or subrun which will
143  // be combined below.
144  if ((branchType_ != InSubRun) && (branchType_ != InRun)) {
145  if (pd.produced()) {
146  throw Exception{errors::LogicError, "RootDelayedReader::getProduct_"}
147  << "Attempt to delay read a produced product!\n";
148  }
149  }
150  // Note: threading: The configure ref core streamer and the related i/o
151  // operations must be done with the source lock held!
152  InputSourceMutexSentry sentry;
153  configureProductIDStreamer(branchIDLists_);
154  configureRefCoreStreamer(principal_.get());
155  TClass* cl = TClass::GetClass(pd.wrappedName().c_str());
156  auto get_product = [this, cl, br](auto entry) {
157  unique_ptr<EDProduct> p{static_cast<EDProduct*>(cl->New())};
158  EDProduct* pp = p.get();
159  br->SetAddress(&pp);
160  unsigned long long ticks = 0;
161  auto const bytesRead = input::getEntry(br, entry, ticks);
162  if ((saveMemoryObjectThreshold_ > -1) &&
163  (bytesRead > saveMemoryObjectThreshold_)) {
164  br->DropBaskets("all");
165  }
166  return p;
167  };
168  // Retrieve first product
169  auto result = get_product(entrySet_[0]);
170  if ((branchType_ != InSubRun) && (branchType_ != InRun)) {
171  // Not a run or subrun product, all done.
172  configureProductIDStreamer();
173  configureRefCoreStreamer();
174  return result;
175  }
176  //
177  // Retrieve and combine multiple Run/SubRun products as needed (this is
178  // aggregation!).
179  //
180  // Products from files that did not support RangeSets are
181  // assigned RangeSets that correspond to the entire run/subrun.
182  if (fileFormatVersion_.value_ < 9) {
183  if (branchType_ == InRun) {
185  } else {
187  }
188  configureProductIDStreamer();
189  configureRefCoreStreamer();
190  return result;
191  }
192  // Fetch the provenance for the first product.
193  vector<ProductProvenance> ppv;
194  unique_ptr<ProductProvenance const> prov;
195  {
196  auto p_ppv = &ppv;
197  provenanceBranch_->SetAddress(&p_ppv);
199  for (auto const& val : ppv) {
200  if (val.productID() == pid) {
201  prov.reset(new ProductProvenance(val));
202  break;
203  }
204  }
205  }
206  // Note: Cannot make this assert here because it can be so that the first
207  // product
208  // is a dummy wrapper with the present flag false, and no provenance
209  // has been written (How???), but the second product is present and
210  // has provenance.
211  // assert((prov.get() != nullptr) && "Could not find provenance for this
212  // Run/SubRun product!");
213  // Unfortunately, we cannot use detail::resolveRangeSetInfo in
214  // this case because products that represent a full (Sub)Run are
215  // allowed to be duplicated in an input file. The behavior in
216  // such a case is a NOP.
217  RangeSet mergedRangeSet = detail::resolveRangeSet(db_,
218  "SomeInput"s,
219  branchType_,
220  result->getRangeSetID(),
222  // Note: If the mergedRangeSet is invalid here that means the first product
223  // was a dummy created
224  // by RootOutputFile to prevent double-counting when combining
225  // products. Or the user is playing games that are going to hurt them
226  // by intentionally created a product with an invalid range set.
227  // Note: Also in that case we have a product status of unknown which we may
228  // have to replace later.
229  for (auto it = entrySet_.cbegin() + 1, e = entrySet_.cend(); it != e;
230  ++it) {
231  auto p = get_product(*it);
232  vector<ProductProvenance> new_ppv;
233  unique_ptr<ProductProvenance const> new_prov;
234  {
235  auto p_ppv = &new_ppv;
236  provenanceBranch_->SetAddress(&p_ppv);
238  for (auto const& val : new_ppv) {
239  if (val.productID() == pid) {
240  new_prov.reset(new ProductProvenance(val));
241  break;
242  }
243  }
244  }
245  // assert((new_prov.get() != nullptr) && "Could not find provenance for
246  // this Run/SubRun product!"); auto const id = p->getRangeSetID();
247  RangeSet const& newRS = detail::resolveRangeSet(db_,
248  "SomeInput"s,
249  branchType_,
250  p->getRangeSetID(),
252  if (!mergedRangeSet.is_valid() && !newRS.is_valid()) {
253  // Both range sets are invalid, do nothing.
254  // RootOutputFile creates this situation to prevent double-counting when
255  // combining products. Possibly can also happen when a produced product
256  // is not produced or when a product is dropped?
257  } else if (mergedRangeSet.is_valid() && !newRS.is_valid()) {
258  // FIXME: Can a neverCreated or dropped product have a valid range set?
259  // assert(prov->productStatus() == productstatus::present());
260  // Our current merged range set is valid and the next one is invalid, do
261  // nothing. RootOutputFile creates this situation to prevent
262  // double-counting when combining products. Possibly can also happen
263  // when a produced product is not produced or when a product is dropped?
264  } else if (!mergedRangeSet.is_valid() && newRS.is_valid()) {
265  // We finally have a valid range set to use.
266  // FIXME: Can a neverCreated or dropped product have a valid range set?
267  // assert(new_prov->productStatus() == productstatus::present());
268  mergedRangeSet = newRS;
269  std::swap(result, p);
270  // Replace the provenance.
271  // Note: We do not worry about productstatus::unknown() here because
272  // newRS is valid.
273  principal_->insert_pp(const_cast<Group*>(grp),
274  make_unique<ProductProvenance const>(*new_prov));
275  prov = move(new_prov);
276  } else if (art::disjoint_ranges(mergedRangeSet, newRS)) {
277  // Old and new range sets can be combined, do it.
278  // FIXME: Can a neverCreated or dropped product have a valid range set?
279  // assert(prov->productStatus() == productstatus::present());
280  // assert(new_prov->productStatus() == productstatus::present());
281  result->combine(p.get());
282  mergedRangeSet.merge(newRS);
283  // FIXME: What do we do about provenance??? What if one product has
284  // status present and the other neverCreated or dropped?
285  // FIXME: Possibly cannot happen because in the case that the new
286  // provenance is not present it would have
287  // FIXME: an invalid range set?
288  // Note: We do not worry about productstatus::unknown() here because
289  // newRS is valid. assert((prov->productStatus() ==
290  // new_prov->productStatus()) && "Unequal product status when merging
291  // range sets!");
292  } else if (art::same_ranges(mergedRangeSet, newRS)) {
293  // The ranges are the same, so the behavior is a NOP. If
294  // the stakeholders decide that products with the same
295  // ranges should be checked for equality, the condition
296  // will be added here.
297  // FIXME: Can a neverCreated or dropped product have a valid range set?
298  // assert(prov->productStatus() == productstatus::present());
299  // assert(new_prov->productStatus() == productstatus::present());
300  // FIXME: What do we do about provenance??? What if one product has
301  // status present and the other neverCreated or dropped?
302  // FIXME: Possibly cannot happen because in the case that the new
303  // provenance is not present it would have
304  // FIXME: an invalid range set?
305  // Note: We do not worry about productstatus::unknown() here because
306  // newRS is valid. assert((prov->productStatus() ==
307  // new_prov->productStatus()) && "Unequal product status when products
308  // have identical range sets!");
309  } else if (art::overlapping_ranges(mergedRangeSet, newRS)) {
311  "RootDelayedReader::getProduct_"}
312  << "\nThe following ranges corresponding to the product:\n"
313  << " '" << branchInfo.branchDescription_ << "'"
314  << "\ncannot be aggregated\n"
315  << mergedRangeSet << " and\n"
316  << newRS << "\nPlease contact artists@fnal.gov.\n";
317  }
318  }
319  // Now transfer the calculated mergedRangeSet to the output argument.
320  std::swap(rs, mergedRangeSet);
321  // And now we are done.
322  configureProductIDStreamer();
323  configureRefCoreStreamer();
324  return result;
325  }
RunID const & runID() const
Definition: EventID.h:93
SubRunID const & subRunID() const
Definition: EventID.h:105
RangeSet resolveRangeSet(RangeSetInfo const &rs)
static RangeSet forSubRun(SubRunID)
Definition: RangeSet.cc:58
const double e
void swap(Handle< T > &a, Handle< T > &b)
cet::exempt_ptr< input::BranchMap const > branches_
std::enable_if_t< detail::are_handles< T, U >::value, bool > disjoint_ranges(T const &a, U const &b)
std::vector< input::EntryNumber > const entrySet_
p
Definition: test.py:228
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
std::enable_if_t< detail::are_handles< T, U >::value, bool > overlapping_ranges(T const &a, U const &b)
std::enable_if_t< detail::are_handles< T, U >::value, bool > same_ranges(T const &a, U const &b)
Int_t getEntry(TBranch *branch, EntryNumber entryNumber)
Definition: getEntry.cc:20
cet::exempt_ptr< Principal > principal_
cet::exempt_ptr< BranchIDLists const > branchIDLists_
static const double s
Definition: Units.h:99
static RangeSet forRun(RunID)
Definition: RangeSet.cc:52
FileFormatVersion fileFormatVersion_
bool art::RootDelayedReader::isAvailableAfterCombine_ ( ProductID  bid) const
overrideprivatevirtual

Reimplemented from art::DelayedReader.

Definition at line 85 of file RootDelayedReader.cc.

86  {
87  if ((branchType_ != InSubRun) && (branchType_ != InRun)) {
88  // We only handle run and subrun products here, tell
89  // the caller he should proceed.
90  return true;
91  }
92  // Products from files that did not support range sets are
93  // worth attempting to read, tell the caller to proceed.
94  if (fileFormatVersion_.value_ < 9) {
95  return true;
96  }
97  {
98  InputSourceMutexSentry sentry;
99  for (auto I = entrySet_.cbegin(), E = entrySet_.cend(); I != E; ++I) {
100  vector<ProductProvenance> ppv;
101  ProductProvenance const* prov = nullptr;
102  {
103  auto p_ppv = &ppv;
104  provenanceBranch_->SetAddress(&p_ppv);
106  for (auto const& val : ppv) {
107  if (val.productID() == bid) {
108  prov = &val;
109  break;
110  }
111  }
112  }
113  // Note: If this is a produced product then it might not be in
114  // any of the fragments, this is not an error.
115  if (prov != nullptr) {
116  if (prov->productStatus() == productstatus::present()) {
117  // We found a usable product in the set of fragments,
118  // tell our caller to proceed.
119  return true;
120  }
121  }
122  }
123  // None of the run or subrun fragments have a usable product,
124  // tell our caller that he can give up now.
125  return false;
126  }
127  }
std::vector< input::EntryNumber > const entrySet_
Int_t getEntry(TBranch *branch, EntryNumber entryNumber)
Definition: getEntry.cc:20
ProductStatus present()
Definition: ProductStatus.h:16
FileFormatVersion fileFormatVersion_
int art::RootDelayedReader::openNextSecondaryFile_ ( int  idx)
overrideprivatevirtual

Reimplemented from art::DelayedReader.

Definition at line 329 of file RootDelayedReader.cc.

330  {
331  // idx being a number we can actually use is a precondition of this
332  // function.
333  assert(!(idx < 0));
334  // Note:
335  //
336  // Return code of -2 means stop, -1 means event-not-found,
337  // otherwise 0 for success.
338  //
339  auto const& sfnm = primaryFile_->secondaryFileNames();
340  assert(!(static_cast<decltype(sfnm.size())>(idx) > sfnm.size()));
341  if (sfnm.empty()) { // No configured secondary files.
342  return -2;
343  }
344  auto const& sf = primaryFile_->secondaryFiles();
345  if (static_cast<decltype(sfnm.size())>(idx) == sfnm.size()) {
346  // We're done.
347  return -2;
348  }
349  if (!sf[idx]) {
350  primaryFile_->openSecondaryFile(idx);
351  }
352  switch (branchType_) {
353  case InEvent: {
354  if (!sf[idx]->readEventForSecondaryFile(eventID_)) {
355  return -1;
356  }
357  } break;
358  case InSubRun: {
359  if (!sf[idx]->readSubRunForSecondaryFile(eventID_.subRunID())) {
360  return -1;
361  }
362  } break;
363  case InRun: {
364  if (!sf[idx]->readRunForSecondaryFile(eventID_.runID())) {
365  return -1;
366  }
367  } break;
368  default: {
369  assert(false && "RootDelayedReader encountered an unknown BranchType!");
370  return -2;
371  }
372  }
373  return 0;
374  }
RunID const & runID() const
Definition: EventID.h:93
SubRunID const & subRunID() const
Definition: EventID.h:105
cet::exempt_ptr< RootInputFile > primaryFile_
RootDelayedReader& art::RootDelayedReader::operator= ( RootDelayedReader const &  )
delete
RootDelayedReader& art::RootDelayedReader::operator= ( RootDelayedReader &&  )
delete
std::vector< ProductProvenance > art::RootDelayedReader::readProvenance_ ( ) const
overrideprivatevirtual

Reimplemented from art::DelayedReader.

Definition at line 67 of file RootDelayedReader.cc.

68  {
69  InputSourceMutexSentry sentry;
70  vector<ProductProvenance> ppv;
71  auto p_ppv = &ppv;
72  provenanceBranch_->SetAddress(&p_ppv);
73  // Note: This provenance may be replaced later for
74  // run and subrun products by the combination
75  // process (agggregation).
77  return ppv;
78  }
std::vector< input::EntryNumber > const entrySet_
Int_t getEntry(TBranch *branch, EntryNumber entryNumber)
Definition: getEntry.cc:20
void art::RootDelayedReader::setPrincipal_ ( cet::exempt_ptr< Principal principal)
overrideprivatevirtual

Reimplemented from art::DelayedReader.

Definition at line 61 of file RootDelayedReader.cc.

62  {
63  principal_ = principal;
64  }
cet::exempt_ptr< Principal > principal_

Member Data Documentation

cet::exempt_ptr<input::BranchMap const> art::RootDelayedReader::branches_
private

Definition at line 64 of file RootDelayedReader.h.

cet::exempt_ptr<BranchIDLists const> art::RootDelayedReader::branchIDLists_
private

Definition at line 69 of file RootDelayedReader.h.

BranchType art::RootDelayedReader::branchType_
private

Definition at line 70 of file RootDelayedReader.h.

bool const art::RootDelayedReader::compactSubRunRanges_
private

Definition at line 72 of file RootDelayedReader.h.

sqlite3* art::RootDelayedReader::db_
private

Definition at line 62 of file RootDelayedReader.h.

std::vector<input::EntryNumber> const art::RootDelayedReader::entrySet_
private

Definition at line 63 of file RootDelayedReader.h.

EventID art::RootDelayedReader::eventID_
private

Definition at line 71 of file RootDelayedReader.h.

FileFormatVersion art::RootDelayedReader::fileFormatVersion_
private

Definition at line 61 of file RootDelayedReader.h.

cet::exempt_ptr<RootInputFile> art::RootDelayedReader::primaryFile_
private

Definition at line 68 of file RootDelayedReader.h.

cet::exempt_ptr<Principal> art::RootDelayedReader::principal_
private

Definition at line 67 of file RootDelayedReader.h.

TBranch* art::RootDelayedReader::provenanceBranch_
private

Definition at line 65 of file RootDelayedReader.h.

int64_t art::RootDelayedReader::saveMemoryObjectThreshold_
private

Definition at line 66 of file RootDelayedReader.h.


The documentation for this class was generated from the following files: