Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:28:25

0001 // -*- C++ -*-
0002 //
0003 // Package:     FWLite
0004 // Class  :     BareRootProductGetter
0005 //
0006 // Implementation:
0007 //     <Notes on implementation>
0008 //
0009 // Original Author:  Chris Jones
0010 //         Created:  Tue May 23 11:03:31 EDT 2006
0011 //
0012 
0013 // user include files
0014 #include "FWCore/FWLite/src/BareRootProductGetter.h"
0015 #include "DataFormats/Common/interface/ThinnedAssociation.h"
0016 #include "DataFormats/Common/interface/Wrapper.h"
0017 #include "DataFormats/Common/interface/getThinned_implementation.h"
0018 #include "DataFormats/Provenance/interface/BranchDescription.h"
0019 #include "DataFormats/Provenance/interface/BranchID.h"
0020 #include "DataFormats/Provenance/interface/BranchType.h"
0021 #include "DataFormats/Provenance/interface/ThinnedAssociationsHelper.h"
0022 #include "FWCore/Utilities/interface/Exception.h"
0023 #include "FWCore/Reflection/interface/TypeWithDict.h"
0024 #include "FWCore/Utilities/interface/WrappedClassName.h"
0025 
0026 // system include files
0027 
0028 #include "TROOT.h"
0029 #include "TBranch.h"
0030 #include "TClass.h"
0031 #include "TFile.h"
0032 #include "TTree.h"
0033 
0034 //
0035 // constants, enums and typedefs
0036 //
0037 
0038 //
0039 // static data member definitions
0040 //
0041 
0042 //
0043 // constructors and destructor
0044 //
0045 BareRootProductGetter::BareRootProductGetter() {}
0046 
0047 // BareRootProductGetter::BareRootProductGetter(BareRootProductGetter const& rhs) {
0048 //    // do actual copying here;
0049 // }
0050 
0051 BareRootProductGetter::~BareRootProductGetter() {}
0052 
0053 //
0054 // assignment operators
0055 //
0056 // BareRootProductGetter const& BareRootProductGetter::operator=(BareRootProductGetter const& rhs) {
0057 //   //An exception safe implementation is
0058 //   BareRootProductGetter temp(rhs);
0059 //   swap(rhs);
0060 //
0061 //   return *this;
0062 // }
0063 
0064 //
0065 // member functions
0066 //
0067 
0068 //
0069 // const member functions
0070 //
0071 edm::WrapperBase const* BareRootProductGetter::getIt(edm::ProductID const& pid) const {
0072   // std::cout << "getIt called " << pid << std::endl;
0073   TFile* currentFile = dynamic_cast<TFile*>(gROOT->GetListOfFiles()->Last());
0074   if (nullptr == currentFile) {
0075     throw cms::Exception("FileNotFound") << "unable to find the TFile '" << gROOT->GetListOfFiles()->Last() << "'\n"
0076                                          << "retrieved by calling 'gROOT->GetListOfFiles()->Last()'\n"
0077                                          << "Please check the list of files.";
0078   }
0079   if (branchMap_.updateFile(currentFile)) {
0080     idToBuffers_.clear();
0081   }
0082   TTree* eventTree = branchMap_.getEventTree();
0083   // std::cout << "eventTree " << eventTree << std::endl;
0084   if (nullptr == eventTree) {
0085     throw cms::Exception("NoEventsTree")
0086         << "unable to find the TTree '" << edm::poolNames::eventTreeName() << "' in the last open file, \n"
0087         << "file: '" << branchMap_.getFile()->GetName()
0088         << "'\n Please check that the file is a standard CMS ROOT format.\n"
0089         << "If the above is not the file you expect then please open your data file after all other files.";
0090   }
0091   Long_t eventEntry = eventTree->GetReadEntry();
0092   // std::cout << "eventEntry " << eventEntry << std::endl;
0093   branchMap_.updateEvent(eventEntry);
0094   if (eventEntry < 0) {
0095     throw cms::Exception("GetEntryNotCalled")
0096         << "please call GetEntry for the 'Events' TTree for each event in order to make edm::Ref's work."
0097         << "\n Also be sure to call 'SetAddress' for all Branches after calling the GetEntry.";
0098   }
0099 
0100   edm::BranchID branchID = branchMap_.productToBranchID(pid);
0101 
0102   return getIt(branchID, eventEntry);
0103 }
0104 
0105 edm::WrapperBase const* BareRootProductGetter::getIt(edm::BranchID const& branchID, Long_t eventEntry) const {
0106   Buffer* buffer = nullptr;
0107   IdToBuffers::iterator itBuffer = idToBuffers_.find(branchID);
0108 
0109   // std::cout << "Buffers" << std::endl;
0110   if (itBuffer == idToBuffers_.end()) {
0111     buffer = createNewBuffer(branchID);
0112     // std::cout << "buffer " << buffer << std::endl;
0113     if (nullptr == buffer) {
0114       return nullptr;
0115     }
0116   } else {
0117     buffer = &(itBuffer->second);
0118   }
0119   if (nullptr == buffer) {
0120     throw cms::Exception("NullBuffer") << "Found a null buffer which is supposed to hold the data item."
0121                                        << "\n Please contact developers since this message should not happen.";
0122   }
0123   if (nullptr == buffer->branch_) {
0124     throw cms::Exception("NullBranch") << "The TBranch which should hold the data item is null."
0125                                        << "\n Please contact the developers since this message should not happen.";
0126   }
0127   if (buffer->eventEntry_ != eventEntry) {
0128     //NOTE: Need to reset address because user could have set the address themselves
0129     //std::cout << "new event" << std::endl;
0130 
0131     //ROOT WORKAROUND: Create new objects so any internal data cache will get cleared
0132     void* address = buffer->class_->New();
0133 
0134     static TClass const* edproductTClass = TClass::GetClass(typeid(edm::WrapperBase));
0135     edm::WrapperBase const* prod =
0136         static_cast<edm::WrapperBase const*>(buffer->class_->DynamicCast(edproductTClass, address, true));
0137 
0138     if (nullptr == prod) {
0139       cms::Exception("FailedConversion") << "failed to convert a '" << buffer->class_->GetName()
0140                                          << "' to a edm::WrapperBase."
0141                                          << "Please contact developers since something is very wrong.";
0142     }
0143     buffer->address_ = address;
0144     buffer->product_ = std::shared_ptr<edm::WrapperBase const>(prod);
0145     //END WORKAROUND
0146 
0147     address = &(buffer->address_);
0148     buffer->branch_->SetAddress(address);
0149 
0150     buffer->branch_->GetEntry(eventEntry);
0151     buffer->eventEntry_ = eventEntry;
0152   }
0153   if (!buffer->product_) {
0154     throw cms::Exception("BranchGetEntryFailed")
0155         << "Calling GetEntry with index " << eventEntry << "for branch " << buffer->branch_->GetName() << " failed.";
0156   }
0157 
0158   return buffer->product_.get();
0159 }
0160 
0161 std::optional<std::tuple<edm::WrapperBase const*, unsigned int>> BareRootProductGetter::getThinnedProduct(
0162     edm::ProductID const& pid, unsigned int key) const {
0163   Long_t eventEntry = branchMap_.getEventTree()->GetReadEntry();
0164   return edm::detail::getThinnedProduct(
0165       pid,
0166       key,
0167       branchMap_.thinnedAssociationsHelper(),
0168       [this](edm::ProductID const& p) { return branchMap_.productToBranchID(p); },
0169       [this, eventEntry](edm::BranchID const& b) { return getThinnedAssociation(b, eventEntry); },
0170       [this](edm::ProductID const& p) { return getIt(p); });
0171 }
0172 
0173 void BareRootProductGetter::getThinnedProducts(edm::ProductID const& pid,
0174                                                std::vector<edm::WrapperBase const*>& foundContainers,
0175                                                std::vector<unsigned int>& keys) const {
0176   Long_t eventEntry = branchMap_.getEventTree()->GetReadEntry();
0177   edm::detail::getThinnedProducts(
0178       pid,
0179       branchMap_.thinnedAssociationsHelper(),
0180       [this](edm::ProductID const& p) { return branchMap_.productToBranchID(p); },
0181       [this, eventEntry](edm::BranchID const& b) { return getThinnedAssociation(b, eventEntry); },
0182       [this](edm::ProductID const& p) { return getIt(p); },
0183       foundContainers,
0184       keys);
0185 }
0186 
0187 edm::OptionalThinnedKey BareRootProductGetter::getThinnedKeyFrom(edm::ProductID const& parentID,
0188                                                                  unsigned int key,
0189                                                                  edm::ProductID const& thinnedID) const {
0190   Long_t eventEntry = branchMap_.getEventTree()->GetReadEntry();
0191   edm::BranchID parent = branchMap_.productToBranchID(parentID);
0192   if (!parent.isValid())
0193     return std::monostate{};
0194   edm::BranchID thinned = branchMap_.productToBranchID(thinnedID);
0195   if (!thinned.isValid())
0196     return std::monostate{};
0197   try {
0198     auto ret = edm::detail::getThinnedKeyFrom_implementation(
0199         parentID,
0200         parent,
0201         key,
0202         thinnedID,
0203         thinned,
0204         branchMap_.thinnedAssociationsHelper(),
0205         [this, eventEntry](edm::BranchID const& branchID) { return getThinnedAssociation(branchID, eventEntry); });
0206     if (auto factory = std::get_if<edm::detail::GetThinnedKeyFromExceptionFactory>(&ret)) {
0207       return [func = *factory]() {
0208         auto ex = func();
0209         ex.addContext("Calling BareRootProductGetter::getThinnedKeyFrom()");
0210         return ex;
0211       };
0212     } else {
0213       return ret;
0214     }
0215   } catch (edm::Exception& ex) {
0216     ex.addContext("Calling BareRootProductGetter::getThinnedKeyFrom()");
0217     throw ex;
0218   }
0219 }
0220 
0221 BareRootProductGetter::Buffer* BareRootProductGetter::createNewBuffer(edm::BranchID const& branchID) const {
0222   //find the branch
0223   edm::BranchDescription const& bdesc = branchMap_.branchIDToBranch(branchID);
0224 
0225   TBranch* branch = branchMap_.getEventTree()->GetBranch(bdesc.branchName().c_str());
0226   if (nullptr == branch) {
0227     //we do not thrown on missing branches since 'getIt' should not throw under that condition
0228     return nullptr;
0229   }
0230   //find the class type
0231   std::string const fullName = edm::wrappedClassName(bdesc.className());
0232   edm::TypeWithDict classType(edm::TypeWithDict::byName(fullName));
0233   if (!bool(classType)) {
0234     throw cms::Exception("MissingDictionary") << "could not find dictionary for type '" << fullName << "'"
0235                                               << "\n Please make sure all the necessary libraries are available.";
0236     return nullptr;
0237   }
0238 
0239   TClass* rootClassType = TClass::GetClass(classType.typeInfo());
0240   if (nullptr == rootClassType) {
0241     throw cms::Exception("MissingRootDictionary") << "could not find a ROOT dictionary for type '" << fullName << "'"
0242                                                   << "\n Please make sure all the necessary libraries are available.";
0243     return nullptr;
0244   }
0245   void* address = rootClassType->New();
0246 
0247   static TClass const* edproductTClass = TClass::GetClass(typeid(edm::WrapperBase));
0248   edm::WrapperBase const* prod =
0249       static_cast<edm::WrapperBase const*>(rootClassType->DynamicCast(edproductTClass, address, true));
0250   if (nullptr == prod) {
0251     throw cms::Exception("FailedConversion") << "failed to convert a '" << fullName << "' to a edm::WrapperBase."
0252                                              << "Please contact developers since something is very wrong.";
0253   }
0254 
0255   //connect the instance to the branch
0256   //void* address  = wrapperObj.Address();
0257   Buffer b(prod, branch, address, rootClassType);
0258   idToBuffers_[branchID] = std::move(b);
0259 
0260   //As of 5.13 ROOT expects the memory address held by the pointer passed to
0261   // SetAddress to be valid forever
0262   address = &(idToBuffers_[branchID].address_);
0263   branch->SetAddress(address);
0264 
0265   return &(idToBuffers_[branchID]);
0266 }
0267 
0268 edm::ThinnedAssociation const* BareRootProductGetter::getThinnedAssociation(edm::BranchID const& branchID,
0269                                                                             Long_t eventEntry) const {
0270   edm::WrapperBase const* wrapperBase = getIt(branchID, eventEntry);
0271   if (wrapperBase == nullptr) {
0272     throw edm::Exception(edm::errors::LogicError)
0273         << "BareRootProductGetter::getThinnedAssociation, product ThinnedAssociation not found.\n";
0274   }
0275   if (!(typeid(edm::ThinnedAssociation) == wrapperBase->dynamicTypeInfo())) {
0276     throw edm::Exception(edm::errors::LogicError)
0277         << "BareRootProductGetter::getThinnedAssociation, product has wrong type, not a ThinnedAssociation.\n";
0278   }
0279   edm::Wrapper<edm::ThinnedAssociation> const* wrapper =
0280       static_cast<edm::Wrapper<edm::ThinnedAssociation> const*>(wrapperBase);
0281 
0282   edm::ThinnedAssociation const* thinnedAssociation = wrapper->product();
0283   return thinnedAssociation;
0284 }