CMS 3D CMS Logo

BareRootProductGetter.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: FWLite
4 // Class : BareRootProductGetter
5 //
6 // Implementation:
7 // <Notes on implementation>
8 //
9 // Original Author: Chris Jones
10 // Created: Tue May 23 11:03:31 EDT 2006
11 //
12 
13 // user include files
25 
26 // system include files
27 
28 #include "TROOT.h"
29 #include "TBranch.h"
30 #include "TClass.h"
31 #include "TFile.h"
32 #include "TTree.h"
33 
34 //
35 // constants, enums and typedefs
36 //
37 
38 //
39 // static data member definitions
40 //
41 
42 //
43 // constructors and destructor
44 //
46 
47 // BareRootProductGetter::BareRootProductGetter(BareRootProductGetter const& rhs) {
48 // // do actual copying here;
49 // }
50 
52 
53 //
54 // assignment operators
55 //
56 // BareRootProductGetter const& BareRootProductGetter::operator=(BareRootProductGetter const& rhs) {
57 // //An exception safe implementation is
58 // BareRootProductGetter temp(rhs);
59 // swap(rhs);
60 //
61 // return *this;
62 // }
63 
64 //
65 // member functions
66 //
67 
68 //
69 // const member functions
70 //
72  // std::cout << "getIt called " << pid << std::endl;
73  TFile* currentFile = dynamic_cast<TFile*>(gROOT->GetListOfFiles()->Last());
74  if (nullptr == currentFile) {
75  throw cms::Exception("FileNotFound") << "unable to find the TFile '" << gROOT->GetListOfFiles()->Last() << "'\n"
76  << "retrieved by calling 'gROOT->GetListOfFiles()->Last()'\n"
77  << "Please check the list of files.";
78  }
79  if (branchMap_.updateFile(currentFile)) {
80  idToBuffers_.clear();
81  }
82  TTree* eventTree = branchMap_.getEventTree();
83  // std::cout << "eventTree " << eventTree << std::endl;
84  if (nullptr == eventTree) {
85  throw cms::Exception("NoEventsTree")
86  << "unable to find the TTree '" << edm::poolNames::eventTreeName() << "' in the last open file, \n"
87  << "file: '" << branchMap_.getFile()->GetName()
88  << "'\n Please check that the file is a standard CMS ROOT format.\n"
89  << "If the above is not the file you expect then please open your data file after all other files.";
90  }
91  Long_t eventEntry = eventTree->GetReadEntry();
92  // std::cout << "eventEntry " << eventEntry << std::endl;
93  branchMap_.updateEvent(eventEntry);
94  if (eventEntry < 0) {
95  throw cms::Exception("GetEntryNotCalled")
96  << "please call GetEntry for the 'Events' TTree for each event in order to make edm::Ref's work."
97  << "\n Also be sure to call 'SetAddress' for all Branches after calling the GetEntry.";
98  }
99 
101 
102  return getIt(branchID, eventEntry);
103 }
104 
105 edm::WrapperBase const* BareRootProductGetter::getIt(edm::BranchID const& branchID, Long_t eventEntry) const {
106  Buffer* buffer = nullptr;
107  IdToBuffers::iterator itBuffer = idToBuffers_.find(branchID);
108 
109  // std::cout << "Buffers" << std::endl;
110  if (itBuffer == idToBuffers_.end()) {
111  buffer = createNewBuffer(branchID);
112  // std::cout << "buffer " << buffer << std::endl;
113  if (nullptr == buffer) {
114  return nullptr;
115  }
116  } else {
117  buffer = &(itBuffer->second);
118  }
119  if (nullptr == buffer) {
120  throw cms::Exception("NullBuffer") << "Found a null buffer which is supposed to hold the data item."
121  << "\n Please contact developers since this message should not happen.";
122  }
123  if (nullptr == buffer->branch_) {
124  throw cms::Exception("NullBranch") << "The TBranch which should hold the data item is null."
125  << "\n Please contact the developers since this message should not happen.";
126  }
127  if (buffer->eventEntry_ != eventEntry) {
128  //NOTE: Need to reset address because user could have set the address themselves
129  //std::cout << "new event" << std::endl;
130 
131  //ROOT WORKAROUND: Create new objects so any internal data cache will get cleared
132  void* address = buffer->class_->New();
133 
134  static TClass const* edproductTClass = TClass::GetClass(typeid(edm::WrapperBase));
135  edm::WrapperBase const* prod =
136  static_cast<edm::WrapperBase const*>(buffer->class_->DynamicCast(edproductTClass, address, true));
137 
138  if (nullptr == prod) {
139  cms::Exception("FailedConversion") << "failed to convert a '" << buffer->class_->GetName()
140  << "' to a edm::WrapperBase."
141  << "Please contact developers since something is very wrong.";
142  }
143  buffer->address_ = address;
144  buffer->product_ = std::shared_ptr<edm::WrapperBase const>(prod);
145  //END WORKAROUND
146 
147  address = &(buffer->address_);
148  buffer->branch_->SetAddress(address);
149 
150  buffer->branch_->GetEntry(eventEntry);
151  buffer->eventEntry_ = eventEntry;
152  }
153  if (!buffer->product_) {
154  throw cms::Exception("BranchGetEntryFailed")
155  << "Calling GetEntry with index " << eventEntry << "for branch " << buffer->branch_->GetName() << " failed.";
156  }
157 
158  return buffer->product_.get();
159 }
160 
161 std::optional<std::tuple<edm::WrapperBase const*, unsigned int>> BareRootProductGetter::getThinnedProduct(
162  edm::ProductID const& pid, unsigned int key) const {
163  Long_t eventEntry = branchMap_.getEventTree()->GetReadEntry();
165  pid,
166  key,
168  [this](edm::ProductID const& p) { return branchMap_.productToBranchID(p); },
169  [this, eventEntry](edm::BranchID const& b) { return getThinnedAssociation(b, eventEntry); },
170  [this](edm::ProductID const& p) { return getIt(p); });
171 }
172 
174  std::vector<edm::WrapperBase const*>& foundContainers,
175  std::vector<unsigned int>& keys) const {
176  Long_t eventEntry = branchMap_.getEventTree()->GetReadEntry();
178  pid,
180  [this](edm::ProductID const& p) { return branchMap_.productToBranchID(p); },
181  [this, eventEntry](edm::BranchID const& b) { return getThinnedAssociation(b, eventEntry); },
182  [this](edm::ProductID const& p) { return getIt(p); },
183  foundContainers,
184  keys);
185 }
186 
188  unsigned int key,
189  edm::ProductID const& thinnedID) const {
190  Long_t eventEntry = branchMap_.getEventTree()->GetReadEntry();
192  if (!parent.isValid())
193  return std::monostate{};
194  edm::BranchID thinned = branchMap_.productToBranchID(thinnedID);
195  if (!thinned.isValid())
196  return std::monostate{};
197  try {
199  parentID,
200  parent,
201  key,
202  thinnedID,
203  thinned,
205  [this, eventEntry](edm::BranchID const& branchID) { return getThinnedAssociation(branchID, eventEntry); });
206  if (auto factory = std::get_if<edm::detail::GetThinnedKeyFromExceptionFactory>(&ret)) {
207  return [func = *factory]() {
208  auto ex = func();
209  ex.addContext("Calling BareRootProductGetter::getThinnedKeyFrom()");
210  return ex;
211  };
212  } else {
213  return ret;
214  }
215  } catch (edm::Exception& ex) {
216  ex.addContext("Calling BareRootProductGetter::getThinnedKeyFrom()");
217  throw ex;
218  }
219 }
220 
222  //find the branch
223  edm::BranchDescription const& bdesc = branchMap_.branchIDToBranch(branchID);
224 
225  TBranch* branch = branchMap_.getEventTree()->GetBranch(bdesc.branchName().c_str());
226  if (nullptr == branch) {
227  //we do not thrown on missing branches since 'getIt' should not throw under that condition
228  return nullptr;
229  }
230  //find the class type
233  if (!bool(classType)) {
234  throw cms::Exception("MissingDictionary") << "could not find dictionary for type '" << fullName << "'"
235  << "\n Please make sure all the necessary libraries are available.";
236  return nullptr;
237  }
238 
239  TClass* rootClassType = TClass::GetClass(classType.typeInfo());
240  if (nullptr == rootClassType) {
241  throw cms::Exception("MissingRootDictionary") << "could not find a ROOT dictionary for type '" << fullName << "'"
242  << "\n Please make sure all the necessary libraries are available.";
243  return nullptr;
244  }
245  void* address = rootClassType->New();
246 
247  static TClass const* edproductTClass = TClass::GetClass(typeid(edm::WrapperBase));
248  edm::WrapperBase const* prod =
249  static_cast<edm::WrapperBase const*>(rootClassType->DynamicCast(edproductTClass, address, true));
250  if (nullptr == prod) {
251  throw cms::Exception("FailedConversion") << "failed to convert a '" << fullName << "' to a edm::WrapperBase."
252  << "Please contact developers since something is very wrong.";
253  }
254 
255  //connect the instance to the branch
256  //void* address = wrapperObj.Address();
257  Buffer b(prod, branch, address, rootClassType);
258  idToBuffers_[branchID] = std::move(b);
259 
260  //As of 5.13 ROOT expects the memory address held by the pointer passed to
261  // SetAddress to be valid forever
262  address = &(idToBuffers_[branchID].address_);
263  branch->SetAddress(address);
264 
265  return &(idToBuffers_[branchID]);
266 }
267 
269  Long_t eventEntry) const {
270  edm::WrapperBase const* wrapperBase = getIt(branchID, eventEntry);
271  if (wrapperBase == nullptr) {
273  << "BareRootProductGetter::getThinnedAssociation, product ThinnedAssociation not found.\n";
274  }
275  if (!(typeid(edm::ThinnedAssociation) == wrapperBase->dynamicTypeInfo())) {
277  << "BareRootProductGetter::getThinnedAssociation, product has wrong type, not a ThinnedAssociation.\n";
278  }
280  static_cast<edm::Wrapper<edm::ThinnedAssociation> const*>(wrapperBase);
281 
282  edm::ThinnedAssociation const* thinnedAssociation = wrapper->product();
283  return thinnedAssociation;
284 }
std::variant< unsigned int, detail::GetThinnedKeyFromExceptionFactory, std::monostate > OptionalThinnedKey
ret
prodAgent to be discontinued
std::optional< std::tuple< WrapperBase const *, unsigned int > > getThinnedProduct(ProductID const &pid, unsigned int key, ThinnedAssociationsHelper const &thinnedAssociationsHelper, F1 pidToBid, F2 getThinnedAssociation, F3 getByProductID)
bool updateEvent(Long_t eventEntry)
std::variant< unsigned int, GetThinnedKeyFromExceptionFactory, std::monostate > getThinnedKeyFrom_implementation(ProductID const &parentID, BranchID const &parent, unsigned int key, ProductID const &thinnedID, BranchID thinned, ThinnedAssociationsHelper const &thinnedAssociationsHelper, F &&getThinnedAssociation)
bool updateFile(TFile *file)
TTree const * getEventTree() const
const edm::ThinnedAssociationsHelper & thinnedAssociationsHelper() const
static TypeWithDict byName(std::string const &name)
Definition: TypeWithDict.cc:74
void getThinnedProducts(ProductID const &pid, ThinnedAssociationsHelper const &thinnedAssociationsHelper, F1 pidToBid, F2 getThinnedAssociation, F3 getByProductID, std::vector< WrapperBase const *> &foundContainers, std::vector< unsigned int > &keys)
bool isValid() const
Definition: BranchID.h:22
std::type_info const & dynamicTypeInfo() const
Definition: WrapperBase.h:42
std::string const & className() const
std::string const & branchName() const
const edm::BranchDescription & branchIDToBranch(const edm::BranchID &bid) const
edm::WrapperBase const * getIt(edm::ProductID const &) const override
std::optional< std::tuple< edm::WrapperBase const *, unsigned int > > getThinnedProduct(edm::ProductID const &, unsigned int key) const override
void getThinnedProducts(edm::ProductID const &, std::vector< edm::WrapperBase const *> &foundContainers, std::vector< unsigned int > &keys) const override
edm::OptionalThinnedKey getThinnedKeyFrom(edm::ProductID const &parent, unsigned int key, edm::ProductID const &thinned) const override
Buffer * createNewBuffer(edm::BranchID const &) const
TFile const * getFile() const
std::string wrappedClassName(std::string const &iFullName)
double b
Definition: hdecay.h:120
void addContext(std::string const &context)
Definition: Exception.cc:169
std::string const & eventTreeName()
Definition: BranchType.cc:220
edm::ThinnedAssociation const * getThinnedAssociation(edm::BranchID const &branchID, Long_t eventEntry) const
fwlite::BranchMapReader branchMap_
edm::BranchID productToBranchID(const edm::ProductID &pid)
def move(src, dest)
Definition: eostools.py:511
static HepMC::HEPEVT_Wrapper wrapper