File indexing completed on 2024-04-06 12:04:10
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <cassert>
0015 #include <iostream>
0016
0017
0018 #include "DataFormats/FWLite/interface/DataGetterHelper.h"
0019 #include "TFile.h"
0020 #include "TTree.h"
0021 #include "TTreeCache.h"
0022
0023 #include "DataFormats/Common/interface/ThinnedAssociation.h"
0024 #include "DataFormats/Common/interface/Wrapper.h"
0025 #include "DataFormats/Common/interface/WrapperBase.h"
0026 #include "DataFormats/Common/interface/getThinned_implementation.h"
0027 #include "DataFormats/Provenance/interface/ThinnedAssociationsHelper.h"
0028
0029 #include "FWCore/FWLite/interface/setRefStreamer.h"
0030
0031 #include "FWCore/Utilities/interface/EDMException.h"
0032 #include "FWCore/Utilities/interface/Exception.h"
0033 #include "FWCore/Reflection/interface/FunctionWithDict.h"
0034 #include "FWCore/Utilities/interface/TypeID.h"
0035 #include "FWCore/Reflection/interface/TypeWithDict.h"
0036 #include "FWCore/Utilities/interface/WrappedClassName.h"
0037
0038 namespace fwlite {
0039
0040
0041
0042
0043
0044
0045
0046
0047 static internal::Data branchNotFound{};
0048 static const char kEmptyString[1] = {0};
0049
0050
0051
0052
0053 DataGetterHelper::DataGetterHelper(TTree* tree,
0054 std::shared_ptr<HistoryGetterBase> historyGetter,
0055 std::shared_ptr<BranchMapReader> branchMap,
0056 std::shared_ptr<edm::EDProductGetter> getter,
0057 bool useCache,
0058 std::function<void(TBranch const&)> baFunc)
0059 : branchMap_(branchMap),
0060 historyGetter_(historyGetter),
0061 getter_(getter),
0062 tcTrained_(false),
0063 tcUse_(useCache),
0064 branchAccessFunc_(baFunc) {
0065 if (nullptr == tree) {
0066 throw cms::Exception("NoTree") << "The TTree pointer passed to the constructor was null";
0067 }
0068 tree_ = tree;
0069 if (tcUse_) {
0070 tree_->SetCacheSize();
0071 }
0072 }
0073
0074
0075
0076
0077
0078
0079 DataGetterHelper::~DataGetterHelper() {}
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105 static TBranch* findBranch(TTree* iTree, std::string const& iMainLabels, std::string const& iProcess) {
0106 std::string branchName(iMainLabels);
0107 branchName += iProcess;
0108
0109 branchName += ".";
0110 return iTree->GetBranch(branchName.c_str());
0111 }
0112
0113 void DataGetterHelper::getBranchData(edm::EDProductGetter const* iGetter,
0114 Long64_t eventEntry,
0115 internal::Data& iData) const {
0116 GetterOperate op(iGetter);
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132 if (tcUse_) {
0133 TTreeCache* tcache = dynamic_cast<TTreeCache*>(branchMap_->getFile()->GetCacheRead());
0134
0135 if (nullptr != tcache) {
0136 if (!tcTrained_) {
0137 tcache->SetLearnEntries(100);
0138 tcache->SetEntryRange(0, tree_->GetEntries());
0139 tcTrained_ = true;
0140 }
0141 tree_->LoadTree(eventEntry);
0142 }
0143 }
0144 branchAccessFunc_(*iData.branch_);
0145 iData.branch_->GetEntry(eventEntry);
0146
0147 iData.lastProduct_ = eventEntry;
0148 }
0149
0150 std::optional<edm::BranchID> DataGetterHelper::getBranchIDFor(std::type_info const& iInfo,
0151 char const* iModuleLabel,
0152 char const* iProductInstanceLabel,
0153 char const* iProcessLabel) const {
0154 auto branchFor = [this](edm::TypeID const& iInfo,
0155 char const* iModuleLabel,
0156 char const* iProductInstanceLabel,
0157 char const* iProcessLabel) -> std::optional<edm::BranchID> {
0158 for (auto const& bd : branchMap_->getBranchDescriptions()) {
0159 if (bd.unwrappedTypeID() == iInfo and bd.moduleLabel() == iModuleLabel and
0160 bd.productInstanceName() == iProductInstanceLabel and bd.processName() == iProcessLabel) {
0161 return bd.branchID();
0162 }
0163 }
0164 return std::nullopt;
0165 };
0166 if (nullptr == iProcessLabel || strlen(iProcessLabel) == 0) {
0167
0168 const edm::ProcessHistory& h = DataGetterHelper::history();
0169 edm::TypeID typeID(iInfo);
0170 for (edm::ProcessHistory::const_reverse_iterator iproc = h.rbegin(), eproc = h.rend(); iproc != eproc; ++iproc) {
0171 auto v = branchFor(typeID, iModuleLabel, iProductInstanceLabel, iproc->processName().c_str());
0172 if (v) {
0173 return v;
0174 }
0175 }
0176 return std::nullopt;
0177 }
0178 return branchFor(edm::TypeID(iInfo), iModuleLabel, iProductInstanceLabel, iProcessLabel);
0179 }
0180
0181 internal::Data& DataGetterHelper::getBranchDataFor(std::type_info const& iInfo,
0182 char const* iModuleLabel,
0183 char const* iProductInstanceLabel,
0184 char const* iProcessLabel) const {
0185 edm::TypeID type(iInfo);
0186 internal::DataKey key(type, iModuleLabel, iProductInstanceLabel, iProcessLabel);
0187
0188 KeyToDataMap::iterator itFind = data_.find(key);
0189 if (itFind == data_.end()) {
0190
0191 std::string const sep("_");
0192
0193 std::string name(type.friendlyClassName());
0194 name += sep + std::string(key.module());
0195 name += sep + std::string(key.product()) + sep;
0196
0197
0198 std::string foundProcessLabel;
0199 TBranch* branch = nullptr;
0200 std::shared_ptr<internal::Data> theData;
0201
0202 if (nullptr == iProcessLabel || iProcessLabel == key.kEmpty() || strlen(iProcessLabel) == 0) {
0203 std::string const* lastLabel = nullptr;
0204
0205 const edm::ProcessHistory& h = DataGetterHelper::history();
0206 for (edm::ProcessHistory::const_reverse_iterator iproc = h.rbegin(), eproc = h.rend(); iproc != eproc;
0207 ++iproc) {
0208 lastLabel = &(iproc->processName());
0209 branch = findBranch(tree_, name, iproc->processName());
0210 if (nullptr != branch) {
0211 break;
0212 }
0213 }
0214 if (nullptr == branch) {
0215 return branchNotFound;
0216 }
0217
0218 if (nullptr != lastLabel) {
0219 internal::DataKey fullKey(type, iModuleLabel, iProductInstanceLabel, lastLabel->c_str());
0220 itFind = data_.find(fullKey);
0221 if (itFind != data_.end()) {
0222
0223 theData = itFind->second;
0224 } else {
0225
0226 foundProcessLabel = *lastLabel;
0227 }
0228 }
0229 } else {
0230
0231 branch = findBranch(tree_, name, key.process());
0232 if (nullptr == branch) {
0233 return branchNotFound;
0234 }
0235 }
0236
0237
0238 size_t moduleLabelLen = strlen(iModuleLabel) + 1;
0239 char* newModule = new char[moduleLabelLen];
0240 std::strncpy(newModule, iModuleLabel, moduleLabelLen);
0241 labels_.push_back(newModule);
0242
0243 char const* newProduct = kEmptyString;
0244 if (key.product()[0] != 0) {
0245 size_t newProductLen = strlen(key.product()) + 1;
0246 auto newProductTmp = new char[newProductLen];
0247 std::strncpy(newProductTmp, key.product(), newProductLen);
0248 newProduct = newProductTmp;
0249 labels_.push_back(newProduct);
0250 }
0251 char const* newProcess = kEmptyString;
0252 if (key.process()[0] != 0) {
0253 size_t newProcessLen = strlen(key.process()) + 1;
0254 auto newProcessTmp = new char[newProcessLen];
0255 std::strncpy(newProcessTmp, key.process(), newProcessLen);
0256 newProcess = newProcessTmp;
0257 labels_.push_back(newProcess);
0258 }
0259 internal::DataKey newKey(edm::TypeID(iInfo), newModule, newProduct, newProcess);
0260
0261 if (nullptr == theData.get()) {
0262
0263
0264
0265 edm::TypeWithDict typeWithDict(iInfo);
0266 if (!bool(typeWithDict)) {
0267 throw cms::Exception("UnknownType") << "No dictionary exists for type " << iInfo.name();
0268 }
0269
0270 edm::ObjectWithDict obj = edm::ObjectWithDict::byType(typeWithDict);
0271
0272 if (obj.address() == nullptr) {
0273 throw cms::Exception("ConstructionFailed") << "failed to construct an instance of " << typeWithDict.name();
0274 }
0275 auto newData = std::make_shared<internal::Data>();
0276 newData->branch_ = branch;
0277 newData->obj_ = obj;
0278 newData->lastProduct_ = -1;
0279 newData->pObj_ = obj.address();
0280 newData->pProd_ = nullptr;
0281 branch->SetAddress(&(newData->pObj_));
0282 theData = newData;
0283 }
0284 itFind = data_.insert(std::make_pair(newKey, theData)).first;
0285
0286 if (!foundProcessLabel.empty()) {
0287
0288 auto newProcessTmp = new char[foundProcessLabel.size() + 1];
0289 std::strcpy(newProcessTmp, foundProcessLabel.c_str());
0290 newProcess = newProcessTmp;
0291 labels_.push_back(newProcess);
0292 internal::DataKey newKeyWithProcess(edm::TypeID(iInfo), newModule, newProduct, newProcess);
0293
0294 data_.insert(std::make_pair(newKeyWithProcess, theData));
0295 }
0296 }
0297 return *(itFind->second);
0298 }
0299
0300 std::string const DataGetterHelper::getBranchNameFor(std::type_info const& iInfo,
0301 char const* iModuleLabel,
0302 char const* iProductInstanceLabel,
0303 char const* iProcessLabel) const {
0304 internal::Data& theData =
0305 DataGetterHelper::getBranchDataFor(iInfo, iModuleLabel, iProductInstanceLabel, iProcessLabel);
0306
0307 if (nullptr != theData.branch_) {
0308 return std::string(theData.branch_->GetName());
0309 }
0310 return std::string("");
0311 }
0312
0313 bool DataGetterHelper::getByLabel(std::type_info const& iInfo,
0314 char const* iModuleLabel,
0315 char const* iProductInstanceLabel,
0316 char const* iProcessLabel,
0317 void* oData,
0318 Long_t eventEntry) const {
0319
0320 void** pOData = reinterpret_cast<void**>(oData);
0321 *pOData = nullptr;
0322
0323 internal::Data& theData =
0324 DataGetterHelper::getBranchDataFor(iInfo, iModuleLabel, iProductInstanceLabel, iProcessLabel);
0325
0326 if (nullptr != theData.branch_) {
0327 if (eventEntry != theData.lastProduct_) {
0328
0329 getBranchData(getter_.get(), eventEntry, theData);
0330 }
0331 *pOData = theData.obj_.address();
0332 }
0333
0334 if (nullptr == *pOData)
0335 return false;
0336 else
0337 return true;
0338 }
0339
0340 bool DataGetterHelper::getByBranchDescription(edm::BranchDescription const& bDesc,
0341 Long_t eventEntry,
0342 KeyToDataMap::iterator& itData) const {
0343 if (!bDesc.branchID().isValid()) {
0344 return false;
0345 }
0346
0347
0348 edm::TypeWithDict typeWD(edm::TypeWithDict::byName(edm::wrappedClassName(bDesc.fullClassName())));
0349 edm::TypeID type(typeWD.typeInfo());
0350 assert(bool(type));
0351
0352
0353 char const* pIL = bDesc.productInstanceName().c_str();
0354 if (pIL[0] == 0) {
0355 pIL = nullptr;
0356 }
0357 internal::DataKey k(type, bDesc.moduleLabel().c_str(), pIL, bDesc.processName().c_str());
0358
0359
0360 itData = data_.find(k);
0361 if (data_.end() == itData) {
0362
0363 edm::WrapperBase const* dummy = nullptr;
0364 getByLabel(type.typeInfo(), k.module(), k.product(), k.process(), &dummy, eventEntry);
0365 if (nullptr == dummy) {
0366 return false;
0367 }
0368 itData = data_.find(k);
0369 assert(itData != data_.end());
0370 assert(dummy == itData->second->obj_.address());
0371 }
0372 return true;
0373 }
0374
0375 edm::WrapperBase const* DataGetterHelper::getByProductID(edm::ProductID const& iID, Long_t eventEntry) const {
0376 typedef std::pair<edm::ProductID, edm::BranchListIndex> IDPair;
0377 IDPair theID = std::make_pair(iID, branchMap_->branchListIndexes()[iID.processIndex() - 1]);
0378 std::map<IDPair, std::shared_ptr<internal::Data>>::const_iterator itFound = idToData_.find(theID);
0379
0380 if (itFound == idToData_.end()) {
0381 edm::BranchDescription const& bDesc = branchMap_->productToBranch(iID);
0382 KeyToDataMap::iterator itData;
0383
0384 if (!getByBranchDescription(bDesc, eventEntry, itData)) {
0385 return nullptr;
0386 }
0387 itFound = idToData_.insert(std::make_pair(theID, itData->second)).first;
0388 }
0389 if (eventEntry != itFound->second->lastProduct_) {
0390
0391 getBranchData(getter_.get(), eventEntry, *(itFound->second));
0392 }
0393 if (nullptr == itFound->second->pProd_) {
0394 itFound->second->pProd_ = wrapperBasePtr(itFound->second->obj_);
0395 if (nullptr == itFound->second->pProd_) {
0396 return nullptr;
0397 }
0398 }
0399 return itFound->second->pProd_;
0400 }
0401
0402 edm::WrapperBase const* DataGetterHelper::getByBranchID(edm::BranchID const& bid, Long_t eventEntry) const {
0403 auto itFound = bidToData_.find(bid);
0404
0405 if (itFound == bidToData_.end()) {
0406 edm::BranchDescription const& bDesc = branchMap_->branchIDToBranch(bid);
0407 KeyToDataMap::iterator itData;
0408
0409 if (!getByBranchDescription(bDesc, eventEntry, itData)) {
0410 return nullptr;
0411 }
0412 itFound = bidToData_.insert(std::make_pair(bid, itData->second)).first;
0413 }
0414 if (eventEntry != itFound->second->lastProduct_) {
0415
0416 getBranchData(getter_.get(), eventEntry, *(itFound->second));
0417 }
0418 if (nullptr == itFound->second->pProd_) {
0419 itFound->second->pProd_ = wrapperBasePtr(itFound->second->obj_);
0420 if (nullptr == itFound->second->pProd_) {
0421 return nullptr;
0422 }
0423 }
0424 return itFound->second->pProd_;
0425 }
0426
0427 edm::WrapperBase const* DataGetterHelper::wrapperBasePtr(edm::ObjectWithDict const& objectWithDict) const {
0428
0429 edm::TypeWithDict wrapperBaseTypeWithDict(typeid(edm::WrapperBase));
0430 return static_cast<edm::WrapperBase const*>(
0431 wrapperBaseTypeWithDict.pointerToBaseType(objectWithDict.address(), objectWithDict.typeOf()));
0432 }
0433
0434 std::optional<std::tuple<edm::WrapperBase const*, unsigned int>> DataGetterHelper::getThinnedProduct(
0435 edm::ProductID const& pid, unsigned int key, Long_t eventEntry) const {
0436 return edm::detail::getThinnedProduct(
0437 pid,
0438 key,
0439 branchMap_->thinnedAssociationsHelper(),
0440 [this](edm::ProductID const& p) { return branchMap_->productToBranchID(p); },
0441 [this, eventEntry](edm::BranchID const& b) { return getThinnedAssociation(b, eventEntry); },
0442 [this, eventEntry](edm::ProductID const& p) { return getByProductID(p, eventEntry); });
0443 }
0444
0445 void DataGetterHelper::getThinnedProducts(edm::ProductID const& pid,
0446 std::vector<edm::WrapperBase const*>& foundContainers,
0447 std::vector<unsigned int>& keys,
0448 Long_t eventEntry) const {
0449 edm::detail::getThinnedProducts(
0450 pid,
0451 branchMap_->thinnedAssociationsHelper(),
0452 [this](edm::ProductID const& p) { return branchMap_->productToBranchID(p); },
0453 [this, eventEntry](edm::BranchID const& b) { return getThinnedAssociation(b, eventEntry); },
0454 [this, eventEntry](edm::ProductID const& p) { return getByProductID(p, eventEntry); },
0455 foundContainers,
0456 keys);
0457 }
0458
0459 edm::OptionalThinnedKey DataGetterHelper::getThinnedKeyFrom(edm::ProductID const& parentID,
0460 unsigned int key,
0461 edm::ProductID const& thinnedID,
0462 Long_t eventEntry) const {
0463 edm::BranchID parent = branchMap_->productToBranchID(parentID);
0464 if (!parent.isValid())
0465 return std::monostate{};
0466 edm::BranchID thinned = branchMap_->productToBranchID(thinnedID);
0467 if (!thinned.isValid())
0468 return std::monostate{};
0469
0470 try {
0471 auto ret = edm::detail::getThinnedKeyFrom_implementation(
0472 parentID,
0473 parent,
0474 key,
0475 thinnedID,
0476 thinned,
0477 branchMap_->thinnedAssociationsHelper(),
0478 [this, eventEntry](edm::BranchID const& branchID) { return getThinnedAssociation(branchID, eventEntry); });
0479 if (auto factory = std::get_if<edm::detail::GetThinnedKeyFromExceptionFactory>(&ret)) {
0480 return [func = *factory]() {
0481 auto ex = func();
0482 ex.addContext("Calling DataGetterHelper::getThinnedKeyFrom()");
0483 return ex;
0484 };
0485 } else {
0486 return ret;
0487 }
0488 } catch (edm::Exception& ex) {
0489 ex.addContext("Calling DataGetterHelper::getThinnedKeyFrom()");
0490 throw ex;
0491 }
0492 }
0493
0494 edm::ThinnedAssociation const* DataGetterHelper::getThinnedAssociation(edm::BranchID const& branchID,
0495 Long_t eventEntry) const {
0496 edm::WrapperBase const* wrapperBase = getByBranchID(branchID, eventEntry);
0497 if (wrapperBase == nullptr) {
0498 throw edm::Exception(edm::errors::LogicError)
0499 << "DataGetterHelper::getThinnedAssociation, product ThinnedAssociation not found.\n";
0500 }
0501 if (!(typeid(edm::ThinnedAssociation) == wrapperBase->dynamicTypeInfo())) {
0502 throw edm::Exception(edm::errors::LogicError)
0503 << "DataGetterHelper::getThinnedAssociation, product has wrong type, not a ThinnedAssociation.\n";
0504 }
0505 edm::Wrapper<edm::ThinnedAssociation> const* wrapper =
0506 static_cast<edm::Wrapper<edm::ThinnedAssociation> const*>(wrapperBase);
0507
0508 edm::ThinnedAssociation const* thinnedAssociation = wrapper->product();
0509 return thinnedAssociation;
0510 }
0511
0512 const edm::ProcessHistory& DataGetterHelper::history() const { return historyGetter_->history(); }
0513
0514
0515
0516
0517 }