File indexing completed on 2021-02-14 12:53:25
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 internal::Data& DataGetterHelper::getBranchDataFor(std::type_info const& iInfo,
0151 char const* iModuleLabel,
0152 char const* iProductInstanceLabel,
0153 char const* iProcessLabel) const {
0154 edm::TypeID type(iInfo);
0155 internal::DataKey key(type, iModuleLabel, iProductInstanceLabel, iProcessLabel);
0156
0157 KeyToDataMap::iterator itFind = data_.find(key);
0158 if (itFind == data_.end()) {
0159
0160 std::string const sep("_");
0161
0162 std::string name(type.friendlyClassName());
0163 name += sep + std::string(key.module());
0164 name += sep + std::string(key.product()) + sep;
0165
0166
0167 std::string foundProcessLabel;
0168 TBranch* branch = nullptr;
0169 std::shared_ptr<internal::Data> theData;
0170
0171 if (nullptr == iProcessLabel || iProcessLabel == key.kEmpty() || strlen(iProcessLabel) == 0) {
0172 std::string const* lastLabel = nullptr;
0173
0174 const edm::ProcessHistory& h = DataGetterHelper::history();
0175 for (edm::ProcessHistory::const_reverse_iterator iproc = h.rbegin(), eproc = h.rend(); iproc != eproc;
0176 ++iproc) {
0177 lastLabel = &(iproc->processName());
0178 branch = findBranch(tree_, name, iproc->processName());
0179 if (nullptr != branch) {
0180 break;
0181 }
0182 }
0183 if (nullptr == branch) {
0184 return branchNotFound;
0185 }
0186
0187 if (nullptr != lastLabel) {
0188 internal::DataKey fullKey(type, iModuleLabel, iProductInstanceLabel, lastLabel->c_str());
0189 itFind = data_.find(fullKey);
0190 if (itFind != data_.end()) {
0191
0192 theData = itFind->second;
0193 } else {
0194
0195 foundProcessLabel = *lastLabel;
0196 }
0197 }
0198 } else {
0199
0200 branch = findBranch(tree_, name, key.process());
0201 if (nullptr == branch) {
0202 return branchNotFound;
0203 }
0204 }
0205
0206
0207 size_t moduleLabelLen = strlen(iModuleLabel) + 1;
0208 char* newModule = new char[moduleLabelLen];
0209 std::strncpy(newModule, iModuleLabel, moduleLabelLen);
0210 labels_.push_back(newModule);
0211
0212 char const* newProduct = kEmptyString;
0213 if (key.product()[0] != 0) {
0214 size_t newProductLen = strlen(key.product()) + 1;
0215 auto newProductTmp = new char[newProductLen];
0216 std::strncpy(newProductTmp, key.product(), newProductLen);
0217 newProduct = newProductTmp;
0218 labels_.push_back(newProduct);
0219 }
0220 char const* newProcess = kEmptyString;
0221 if (key.process()[0] != 0) {
0222 size_t newProcessLen = strlen(key.process()) + 1;
0223 auto newProcessTmp = new char[newProcessLen];
0224 std::strncpy(newProcessTmp, key.process(), newProcessLen);
0225 newProcess = newProcessTmp;
0226 labels_.push_back(newProcess);
0227 }
0228 internal::DataKey newKey(edm::TypeID(iInfo), newModule, newProduct, newProcess);
0229
0230 if (nullptr == theData.get()) {
0231
0232
0233
0234 edm::TypeWithDict typeWithDict(iInfo);
0235 if (!bool(typeWithDict)) {
0236 throw cms::Exception("UnknownType") << "No dictionary exists for type " << iInfo.name();
0237 }
0238
0239 edm::ObjectWithDict obj = edm::ObjectWithDict::byType(typeWithDict);
0240
0241 if (obj.address() == nullptr) {
0242 throw cms::Exception("ConstructionFailed") << "failed to construct an instance of " << typeWithDict.name();
0243 }
0244 auto newData = std::make_shared<internal::Data>();
0245 newData->branch_ = branch;
0246 newData->obj_ = obj;
0247 newData->lastProduct_ = -1;
0248 newData->pObj_ = obj.address();
0249 newData->pProd_ = nullptr;
0250 branch->SetAddress(&(newData->pObj_));
0251 theData = newData;
0252 }
0253 itFind = data_.insert(std::make_pair(newKey, theData)).first;
0254
0255 if (!foundProcessLabel.empty()) {
0256
0257 auto newProcessTmp = new char[foundProcessLabel.size() + 1];
0258 std::strcpy(newProcessTmp, foundProcessLabel.c_str());
0259 newProcess = newProcessTmp;
0260 labels_.push_back(newProcess);
0261 internal::DataKey newKeyWithProcess(edm::TypeID(iInfo), newModule, newProduct, newProcess);
0262
0263 data_.insert(std::make_pair(newKeyWithProcess, theData));
0264 }
0265 }
0266 return *(itFind->second);
0267 }
0268
0269 std::string const DataGetterHelper::getBranchNameFor(std::type_info const& iInfo,
0270 char const* iModuleLabel,
0271 char const* iProductInstanceLabel,
0272 char const* iProcessLabel) const {
0273 internal::Data& theData =
0274 DataGetterHelper::getBranchDataFor(iInfo, iModuleLabel, iProductInstanceLabel, iProcessLabel);
0275
0276 if (nullptr != theData.branch_) {
0277 return std::string(theData.branch_->GetName());
0278 }
0279 return std::string("");
0280 }
0281
0282 bool DataGetterHelper::getByLabel(std::type_info const& iInfo,
0283 char const* iModuleLabel,
0284 char const* iProductInstanceLabel,
0285 char const* iProcessLabel,
0286 void* oData,
0287 Long_t eventEntry) const {
0288
0289 void** pOData = reinterpret_cast<void**>(oData);
0290 *pOData = nullptr;
0291
0292 internal::Data& theData =
0293 DataGetterHelper::getBranchDataFor(iInfo, iModuleLabel, iProductInstanceLabel, iProcessLabel);
0294
0295 if (nullptr != theData.branch_) {
0296 if (eventEntry != theData.lastProduct_) {
0297
0298 getBranchData(getter_.get(), eventEntry, theData);
0299 }
0300 *pOData = theData.obj_.address();
0301 }
0302
0303 if (nullptr == *pOData)
0304 return false;
0305 else
0306 return true;
0307 }
0308
0309 bool DataGetterHelper::getByBranchDescription(edm::BranchDescription const& bDesc,
0310 Long_t eventEntry,
0311 KeyToDataMap::iterator& itData) const {
0312 if (!bDesc.branchID().isValid()) {
0313 return false;
0314 }
0315
0316
0317 edm::TypeWithDict typeWD(edm::TypeWithDict::byName(edm::wrappedClassName(bDesc.fullClassName())));
0318 edm::TypeID type(typeWD.typeInfo());
0319 assert(bool(type));
0320
0321
0322 char const* pIL = bDesc.productInstanceName().c_str();
0323 if (pIL[0] == 0) {
0324 pIL = nullptr;
0325 }
0326 internal::DataKey k(type, bDesc.moduleLabel().c_str(), pIL, bDesc.processName().c_str());
0327
0328
0329 itData = data_.find(k);
0330 if (data_.end() == itData) {
0331
0332 edm::WrapperBase const* dummy = nullptr;
0333 getByLabel(type.typeInfo(), k.module(), k.product(), k.process(), &dummy, eventEntry);
0334 if (nullptr == dummy) {
0335 return false;
0336 }
0337 itData = data_.find(k);
0338 assert(itData != data_.end());
0339 assert(dummy == itData->second->obj_.address());
0340 }
0341 return true;
0342 }
0343
0344 edm::WrapperBase const* DataGetterHelper::getByProductID(edm::ProductID const& iID, Long_t eventEntry) const {
0345 typedef std::pair<edm::ProductID, edm::BranchListIndex> IDPair;
0346 IDPair theID = std::make_pair(iID, branchMap_->branchListIndexes()[iID.processIndex() - 1]);
0347 std::map<IDPair, std::shared_ptr<internal::Data>>::const_iterator itFound = idToData_.find(theID);
0348
0349 if (itFound == idToData_.end()) {
0350 edm::BranchDescription const& bDesc = branchMap_->productToBranch(iID);
0351 KeyToDataMap::iterator itData;
0352
0353 if (!getByBranchDescription(bDesc, eventEntry, itData)) {
0354 return nullptr;
0355 }
0356 itFound = idToData_.insert(std::make_pair(theID, itData->second)).first;
0357 }
0358 if (eventEntry != itFound->second->lastProduct_) {
0359
0360 getBranchData(getter_.get(), eventEntry, *(itFound->second));
0361 }
0362 if (nullptr == itFound->second->pProd_) {
0363 itFound->second->pProd_ = wrapperBasePtr(itFound->second->obj_);
0364 if (nullptr == itFound->second->pProd_) {
0365 return nullptr;
0366 }
0367 }
0368 return itFound->second->pProd_;
0369 }
0370
0371 edm::WrapperBase const* DataGetterHelper::getByBranchID(edm::BranchID const& bid, Long_t eventEntry) const {
0372 auto itFound = bidToData_.find(bid);
0373
0374 if (itFound == bidToData_.end()) {
0375 edm::BranchDescription const& bDesc = branchMap_->branchIDToBranch(bid);
0376 KeyToDataMap::iterator itData;
0377
0378 if (!getByBranchDescription(bDesc, eventEntry, itData)) {
0379 return nullptr;
0380 }
0381 itFound = bidToData_.insert(std::make_pair(bid, itData->second)).first;
0382 }
0383 if (eventEntry != itFound->second->lastProduct_) {
0384
0385 getBranchData(getter_.get(), eventEntry, *(itFound->second));
0386 }
0387 if (nullptr == itFound->second->pProd_) {
0388 itFound->second->pProd_ = wrapperBasePtr(itFound->second->obj_);
0389 if (nullptr == itFound->second->pProd_) {
0390 return nullptr;
0391 }
0392 }
0393 return itFound->second->pProd_;
0394 }
0395
0396 edm::WrapperBase const* DataGetterHelper::wrapperBasePtr(edm::ObjectWithDict const& objectWithDict) const {
0397
0398 edm::TypeWithDict wrapperBaseTypeWithDict(typeid(edm::WrapperBase));
0399 return static_cast<edm::WrapperBase const*>(
0400 wrapperBaseTypeWithDict.pointerToBaseType(objectWithDict.address(), objectWithDict.typeOf()));
0401 }
0402
0403 std::optional<std::tuple<edm::WrapperBase const*, unsigned int>> DataGetterHelper::getThinnedProduct(
0404 edm::ProductID const& pid, unsigned int key, Long_t eventEntry) const {
0405 return edm::detail::getThinnedProduct(
0406 pid,
0407 key,
0408 branchMap_->thinnedAssociationsHelper(),
0409 [this](edm::ProductID const& p) { return branchMap_->productToBranchID(p); },
0410 [this, eventEntry](edm::BranchID const& b) { return getThinnedAssociation(b, eventEntry); },
0411 [this, eventEntry](edm::ProductID const& p) { return getByProductID(p, eventEntry); });
0412 }
0413
0414 void DataGetterHelper::getThinnedProducts(edm::ProductID const& pid,
0415 std::vector<edm::WrapperBase const*>& foundContainers,
0416 std::vector<unsigned int>& keys,
0417 Long_t eventEntry) const {
0418 edm::detail::getThinnedProducts(
0419 pid,
0420 branchMap_->thinnedAssociationsHelper(),
0421 [this](edm::ProductID const& p) { return branchMap_->productToBranchID(p); },
0422 [this, eventEntry](edm::BranchID const& b) { return getThinnedAssociation(b, eventEntry); },
0423 [this, eventEntry](edm::ProductID const& p) { return getByProductID(p, eventEntry); },
0424 foundContainers,
0425 keys);
0426 }
0427
0428 edm::OptionalThinnedKey DataGetterHelper::getThinnedKeyFrom(edm::ProductID const& parentID,
0429 unsigned int key,
0430 edm::ProductID const& thinnedID,
0431 Long_t eventEntry) const {
0432 edm::BranchID parent = branchMap_->productToBranchID(parentID);
0433 if (!parent.isValid())
0434 return std::monostate{};
0435 edm::BranchID thinned = branchMap_->productToBranchID(thinnedID);
0436 if (!thinned.isValid())
0437 return std::monostate{};
0438
0439 try {
0440 auto ret = edm::detail::getThinnedKeyFrom_implementation(
0441 parentID,
0442 parent,
0443 key,
0444 thinnedID,
0445 thinned,
0446 branchMap_->thinnedAssociationsHelper(),
0447 [this, eventEntry](edm::BranchID const& branchID) { return getThinnedAssociation(branchID, eventEntry); });
0448 if (auto factory = std::get_if<edm::detail::GetThinnedKeyFromExceptionFactory>(&ret)) {
0449 return [func = *factory]() {
0450 auto ex = func();
0451 ex.addContext("Calling DataGetterHelper::getThinnedKeyFrom()");
0452 return ex;
0453 };
0454 } else {
0455 return ret;
0456 }
0457 } catch (edm::Exception& ex) {
0458 ex.addContext("Calling DataGetterHelper::getThinnedKeyFrom()");
0459 throw ex;
0460 }
0461 }
0462
0463 edm::ThinnedAssociation const* DataGetterHelper::getThinnedAssociation(edm::BranchID const& branchID,
0464 Long_t eventEntry) const {
0465 edm::WrapperBase const* wrapperBase = getByBranchID(branchID, eventEntry);
0466 if (wrapperBase == nullptr) {
0467 throw edm::Exception(edm::errors::LogicError)
0468 << "DataGetterHelper::getThinnedAssociation, product ThinnedAssociation not found.\n";
0469 }
0470 if (!(typeid(edm::ThinnedAssociation) == wrapperBase->dynamicTypeInfo())) {
0471 throw edm::Exception(edm::errors::LogicError)
0472 << "DataGetterHelper::getThinnedAssociation, product has wrong type, not a ThinnedAssociation.\n";
0473 }
0474 edm::Wrapper<edm::ThinnedAssociation> const* wrapper =
0475 static_cast<edm::Wrapper<edm::ThinnedAssociation> const*>(wrapperBase);
0476
0477 edm::ThinnedAssociation const* thinnedAssociation = wrapper->product();
0478 return thinnedAssociation;
0479 }
0480
0481 const edm::ProcessHistory& DataGetterHelper::history() const { return historyGetter_->history(); }
0482
0483
0484
0485
0486 }