Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-04-30 22:24:08

0001 // -*- C++ -*-
0002 //
0003 // Package:     Framework
0004 // Class  :     EventSetupRecordProvider
0005 //
0006 // Implementation:
0007 //     <Notes on implementation>
0008 //
0009 // Author:      Chris Jones
0010 // Created:     Fri Mar 25 19:12:03 EST 2005
0011 //
0012 
0013 // system include files
0014 #include <algorithm>
0015 #include <cassert>
0016 
0017 // user include files
0018 #include "FWCore/Framework/interface/EventSetupRecordProvider.h"
0019 
0020 #include "FWCore/Framework/interface/ComponentDescription.h"
0021 #include "FWCore/Framework/interface/ParameterSetIDHolder.h"
0022 #include "FWCore/Framework/interface/EventSetupImpl.h"
0023 #include "FWCore/Framework/interface/EventSetupProvider.h"
0024 #include "FWCore/Framework/interface/EventSetupRecordIntervalFinder.h"
0025 #include "FWCore/Framework/src/IntersectingIOVRecordIntervalFinder.h"
0026 #include "FWCore/Framework/interface/DependentRecordIntervalFinder.h"
0027 #include "FWCore/Framework/interface/RecordDependencyRegister.h"
0028 #include "FWCore/Framework/interface/ESProductResolverProvider.h"
0029 #include "FWCore/Framework/interface/ESProductResolver.h"
0030 #include "FWCore/Framework/interface/EventSetupRecord.h"
0031 #include "FWCore/Utilities/interface/Algorithms.h"
0032 #include "FWCore/Utilities/interface/Exception.h"
0033 #include "make_shared_noexcept_false.h"
0034 
0035 namespace edm {
0036   namespace eventsetup {
0037 
0038     EventSetupRecordProvider::EventSetupRecordProvider(const EventSetupRecordKey& iKey,
0039                                                        ActivityRegistry const* activityRegistry,
0040                                                        unsigned int nConcurrentIOVs)
0041         : key_(iKey),
0042           validityInterval_(),
0043           finder_(),
0044           providers_(),
0045           multipleFinders_(new std::vector<edm::propagate_const<std::shared_ptr<EventSetupRecordIntervalFinder>>>()),
0046           nConcurrentIOVs_(nConcurrentIOVs) {
0047       recordImpls_.reserve(nConcurrentIOVs);
0048       for (unsigned int i = 0; i < nConcurrentIOVs_; ++i) {
0049         recordImpls_.emplace_back(iKey, activityRegistry, i);
0050       }
0051     }
0052 
0053     EventSetupRecordImpl const& EventSetupRecordProvider::firstRecordImpl() const { return recordImpls_[0]; }
0054 
0055     void EventSetupRecordProvider::add(std::shared_ptr<ESProductResolverProvider> iProvider) {
0056       assert(iProvider->isUsingRecord(key_));
0057       edm::propagate_const<std::shared_ptr<ESProductResolverProvider>> pProvider(iProvider);
0058       assert(!search_all(providers_, pProvider));
0059       providers_.emplace_back(iProvider);
0060     }
0061 
0062     void EventSetupRecordProvider::addFinder(std::shared_ptr<EventSetupRecordIntervalFinder> iFinder) {
0063       auto oldFinder = finder();
0064       finder_ = iFinder;
0065       if (nullptr != multipleFinders_.get()) {
0066         multipleFinders_->emplace_back(iFinder);
0067       } else {
0068         //dependent records set there finders after the multipleFinders_ has been released
0069         // but they also have never had a finder set
0070         if (nullptr != oldFinder.get()) {
0071           cms::Exception("EventSetupMultipleSources")
0072               << "An additional source has been added to the Record " << key_.name() << "'\n"
0073               << "after all the other sources have been dealt with.  This is a logic error, please send email to the "
0074                  "framework group.";
0075         }
0076       }
0077     }
0078     void EventSetupRecordProvider::setValidityInterval_forTesting(const ValidityInterval& iInterval) {
0079       validityInterval_ = iInterval;
0080       initializeForNewSyncValue();
0081     }
0082 
0083     void EventSetupRecordProvider::setDependentProviders(
0084         const std::vector<std::shared_ptr<EventSetupRecordProvider>>& iProviders) {
0085       using std::placeholders::_1;
0086       std::shared_ptr<DependentRecordIntervalFinder> newFinder =
0087           make_shared_noexcept_false<DependentRecordIntervalFinder>(key());
0088 
0089       std::shared_ptr<EventSetupRecordIntervalFinder> old = swapFinder(newFinder);
0090 
0091       for (auto const& p : iProviders) {
0092         newFinder->addProviderWeAreDependentOn(p);
0093       };
0094       //if a finder was already set, add it as a depedency.  This is done to ensure that the IOVs properly change even if the
0095       // old finder does not update each time a dependent record does change
0096       if (old.get() != nullptr) {
0097         newFinder->setAlternateFinder(old);
0098       }
0099     }
0100     void EventSetupRecordProvider::usePreferred(const DataToPreferredProviderMap& iMap) {
0101       using std::placeholders::_1;
0102       for_all(providers_, std::bind(&EventSetupRecordProvider::addResolversToRecordHelper, this, _1, iMap));
0103       if (1 < multipleFinders_->size()) {
0104         std::shared_ptr<IntersectingIOVRecordIntervalFinder> intFinder =
0105             make_shared_noexcept_false<IntersectingIOVRecordIntervalFinder>(key_);
0106         intFinder->swapFinders(*multipleFinders_);
0107         finder_ = intFinder;
0108       }
0109       if (finder_) {
0110         hasNonconcurrentFinder_ = !finder_->concurrentFinder();
0111       }
0112 
0113       //now we get rid of the temporary
0114       multipleFinders_.reset(nullptr);
0115     }
0116 
0117     void EventSetupRecordProvider::addResolversToRecord(
0118         std::shared_ptr<ESProductResolverProvider> iProvider,
0119         const EventSetupRecordProvider::DataToPreferredProviderMap& iMap) {
0120       typedef ESProductResolverProvider::KeyedResolvers ResolverList;
0121       typedef EventSetupRecordProvider::DataToPreferredProviderMap PreferredMap;
0122 
0123       for (auto& record : recordImpls_) {
0124         ResolverList& keyedResolvers(iProvider->keyedResolvers(this->key(), record.iovIndex()));
0125 
0126         for (auto keyedResolver : keyedResolvers) {
0127           PreferredMap::const_iterator itFound = iMap.find(keyedResolver.dataKey_);
0128           if (iMap.end() != itFound) {
0129             if (itFound->second.type_ != keyedResolver.productResolver_->providerDescription()->type_ ||
0130                 itFound->second.label_ != keyedResolver.productResolver_->providerDescription()->label_) {
0131               //this is not the preferred provider
0132               continue;
0133             }
0134           }
0135           record.add(keyedResolver.dataKey_, keyedResolver.productResolver_);
0136         }
0137       }
0138     }
0139 
0140     void EventSetupRecordProvider::initializeForNewIOV(unsigned int iovIndex, unsigned long long cacheIdentifier) {
0141       EventSetupRecordImpl* impl = &recordImpls_[iovIndex];
0142       recordImpl_ = impl;
0143       bool hasFinder = finder_.get() != nullptr;
0144       impl->initializeForNewIOV(cacheIdentifier, validityInterval_, hasFinder);
0145       eventSetupImpl_->addRecordImpl(*recordImpl_);
0146     }
0147 
0148     void EventSetupRecordProvider::continueIOV(bool newEventSetupImpl) {
0149       if (intervalStatus_ == IntervalStatus::UpdateIntervalEnd) {
0150         recordImpl_->setSafely(validityInterval_);
0151       }
0152       if (newEventSetupImpl && intervalStatus_ != IntervalStatus::Invalid) {
0153         eventSetupImpl_->addRecordImpl(*recordImpl_);
0154       }
0155     }
0156 
0157     void EventSetupRecordProvider::endIOV(unsigned int iovIndex) { recordImpls_[iovIndex].invalidateResolvers(); }
0158 
0159     void EventSetupRecordProvider::initializeForNewSyncValue() {
0160       intervalStatus_ = IntervalStatus::NotInitializedForSyncValue;
0161     }
0162 
0163     bool EventSetupRecordProvider::doWeNeedToWaitForIOVsToFinish(IOVSyncValue const& iTime) const {
0164       if (!hasNonconcurrentFinder_) {
0165         return false;
0166       }
0167       if (intervalStatus_ == IntervalStatus::Invalid || !validityInterval_.validFor(iTime)) {
0168         return finder_->nonconcurrentAndIOVNeedsUpdate(key_, iTime);
0169       }
0170       return false;
0171     }
0172 
0173     bool EventSetupRecordProvider::setValidityIntervalFor(const IOVSyncValue& iTime) {
0174       // This function can be called multiple times for the same
0175       // IOVSyncValue because DependentRecordIntervalFinder::setIntervalFor
0176       // can call it in addition to it being called directly. We don't
0177       // need to do the work multiple times for the same IOVSyncValue.
0178       // The next line of code protects against this. Note that it would
0179       // be possible to avoid this check if the calls to setValidityIntervalFor
0180       // were made in the right order, but it would take some development work
0181       // to come up with code to calculate that order (maybe a project for the
0182       // future, but it's not clear it would be worth the effort).
0183       if (intervalStatus_ == IntervalStatus::NotInitializedForSyncValue) {
0184         intervalStatus_ = IntervalStatus::Invalid;
0185 
0186         if (validityInterval_.first() != IOVSyncValue::invalidIOVSyncValue() && validityInterval_.validFor(iTime)) {
0187           intervalStatus_ = IntervalStatus::SameInterval;
0188 
0189         } else if (finder_.get() != nullptr) {
0190           IOVSyncValue oldFirst(validityInterval_.first());
0191           IOVSyncValue oldLast(validityInterval_.last());
0192           validityInterval_ = finder_->findIntervalFor(key_, iTime);
0193 
0194           // An interval is valid if and only if the start of the interval is
0195           // valid. If the start is valid and the end is invalid, it means we
0196           // do not know when the interval ends, but the interval is valid and
0197           // iTime is within the interval.
0198           if (validityInterval_.first() != IOVSyncValue::invalidIOVSyncValue()) {
0199             // An interval is new if the start of the interval changes
0200             if (validityInterval_.first() != oldFirst) {
0201               intervalStatus_ = IntervalStatus::NewInterval;
0202 
0203               // If the start is the same but the end changes, we consider
0204               // this the same interval because we do not want to do the
0205               // work to update the caches of data in this case.
0206             } else if (validityInterval_.last() != oldLast) {
0207               intervalStatus_ = IntervalStatus::UpdateIntervalEnd;
0208             } else {
0209               intervalStatus_ = IntervalStatus::SameInterval;
0210             }
0211           }
0212         }
0213       }
0214       return intervalStatus_ != IntervalStatus::Invalid;
0215     }
0216 
0217     void EventSetupRecordProvider::resetResolvers() {
0218       // Clear out all the ESProductResolver's
0219       for (auto& recordImplIter : recordImpls_) {
0220         recordImplIter.invalidateResolvers();
0221         recordImplIter.resetIfTransientInResolvers();
0222       }
0223       // Force a new IOV to start with a new cacheIdentifier
0224       // on the next eventSetupForInstance call.
0225       validityInterval_ = ValidityInterval{};
0226       if (finder_.get() != nullptr) {
0227         finder_->resetInterval(key_);
0228       }
0229     }
0230 
0231     void EventSetupRecordProvider::getReferencedESProducers(
0232         std::map<EventSetupRecordKey, std::vector<ComponentDescription const*>>& referencedESProducers) const {
0233       firstRecordImpl().getESProducers(referencedESProducers[key_]);
0234     }
0235 
0236     void EventSetupRecordProvider::fillReferencedDataKeys(
0237         std::map<DataKey, ComponentDescription const*>& referencedDataKeys) const {
0238       std::vector<DataKey> const& keys = firstRecordImpl().registeredDataKeys();
0239 
0240       std::vector<ComponentDescription const*> components = firstRecordImpl().componentsForRegisteredDataKeys();
0241       auto itComponents = components.begin();
0242       for (auto const& k : keys) {
0243         referencedDataKeys.emplace(k, *itComponents);
0244         ++itComponents;
0245       }
0246     }
0247 
0248     void EventSetupRecordProvider::resetRecordToResolverPointers(DataToPreferredProviderMap const& iMap) {
0249       for (auto& recordImplIter : recordImpls_) {
0250         recordImplIter.clearResolvers();
0251       }
0252       using std::placeholders::_1;
0253       for_all(providers_, std::bind(&EventSetupRecordProvider::addResolversToRecordHelper, this, _1, iMap));
0254     }
0255 
0256     void EventSetupRecordProvider::fillAllESProductResolverProviders(
0257         std::vector<ESProductResolverProvider const*>& allESProductResolverProviders,
0258         std::unordered_set<unsigned int>& componentIDs) const {
0259       for (auto const& provider : providers_) {
0260         if (componentIDs.insert(provider->description().id_).second) {
0261           allESProductResolverProviders.push_back(provider.get());
0262         }
0263       }
0264     }
0265 
0266     void EventSetupRecordProvider::updateLookup(ESRecordsToProductResolverIndices const& iResolverToIndices) {
0267       for (auto& productResolverProvider : providers_) {
0268         productResolverProvider->updateLookup(iResolverToIndices);
0269       }
0270     }
0271 
0272     std::set<EventSetupRecordKey> EventSetupRecordProvider::dependentRecords() const { return dependencies(key()); }
0273 
0274     std::set<ComponentDescription> EventSetupRecordProvider::resolverProviderDescriptions() const {
0275       using std::placeholders::_1;
0276       std::set<ComponentDescription> descriptions;
0277       std::transform(providers_.begin(),
0278                      providers_.end(),
0279                      std::inserter(descriptions, descriptions.end()),
0280                      std::bind(&ESProductResolverProvider::description, _1));
0281       return descriptions;
0282     }
0283 
0284     std::shared_ptr<ESProductResolverProvider> EventSetupRecordProvider::resolverProvider(
0285         ComponentDescription const& iDesc) {
0286       using std::placeholders::_1;
0287       auto itFound = std::find_if(
0288           providers_.begin(),
0289           providers_.end(),
0290           std::bind(
0291               std::equal_to<ComponentDescription>(), iDesc, std::bind(&ESProductResolverProvider::description, _1)));
0292       if (itFound == providers_.end()) {
0293         return std::shared_ptr<ESProductResolverProvider>();
0294       }
0295       return get_underlying_safe(*itFound);
0296     }
0297 
0298     std::shared_ptr<ESProductResolverProvider> EventSetupRecordProvider::resolverProvider(
0299         ParameterSetIDHolder const& psetID) {
0300       for (auto& productResolverProvider : providers_) {
0301         if (productResolverProvider->description().pid_ == psetID.psetID()) {
0302           return get_underlying_safe(productResolverProvider);
0303         }
0304       }
0305       return std::shared_ptr<ESProductResolverProvider>();
0306     }
0307 
0308     void EventSetupRecordProvider::resetProductResolverProvider(
0309         ParameterSetIDHolder const& psetID,
0310         std::shared_ptr<ESProductResolverProvider> const& sharedESProductResolverProvider) {
0311       for (auto& productResolverProvider : providers_) {
0312         if (productResolverProvider->description().pid_ == psetID.psetID()) {
0313           productResolverProvider = sharedESProductResolverProvider;
0314           productResolverProvider->createKeyedResolvers(key_, nConcurrentIOVs_);
0315         }
0316       }
0317     }
0318 
0319     std::vector<DataKey> const& EventSetupRecordProvider::registeredDataKeys() const {
0320       return firstRecordImpl().registeredDataKeys();
0321     }
0322 
0323     std::vector<ComponentDescription const*> EventSetupRecordProvider::componentsForRegisteredDataKeys() const {
0324       return firstRecordImpl().componentsForRegisteredDataKeys();
0325     }
0326 
0327     std::vector<unsigned int> EventSetupRecordProvider::produceMethodIDsForRegisteredDataKeys() const {
0328       return firstRecordImpl().produceMethodIDsForRegisteredDataKeys();
0329     }
0330 
0331   }  // namespace eventsetup
0332 }  // namespace edm