Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:12:11

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