Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-08-22 04:57:38

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