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  :     EventSetupRecordImpl
0005 //
0006 // Implementation:
0007 //     <Notes on implementation>
0008 //
0009 // Author:      Chris Jones
0010 // Created:     Sat Mar 26 18:06:32 EST 2005
0011 //
0012 
0013 // system include files
0014 #include <algorithm>
0015 #include <cassert>
0016 #include <iterator>
0017 #include <sstream>
0018 #include <utility>
0019 
0020 // user include files
0021 #include "FWCore/Framework/interface/EventSetupRecordImpl.h"
0022 #include "FWCore/Framework/interface/ESProductResolver.h"
0023 #include "FWCore/Framework/interface/ComponentDescription.h"
0024 #include "FWCore/ServiceRegistry/interface/ESParentContext.h"
0025 
0026 #include "FWCore/Utilities/interface/ConvertException.h"
0027 #include "FWCore/Utilities/interface/Exception.h"
0028 
0029 namespace edm {
0030   namespace eventsetup {
0031 
0032     EventSetupRecordImpl::EventSetupRecordImpl(EventSetupRecordKey const& iKey,
0033                                                ActivityRegistry const* activityRegistry,
0034                                                unsigned int iovIndex)
0035         : validity_(),
0036           key_(iKey),
0037           activityRegistry_(activityRegistry),
0038           cacheIdentifier_(1),  // initial value meaningless, gets overwritten before use
0039           iovIndex_(iovIndex),
0040           isAvailable_(true),
0041           validityModificationUnderway_(false) {}
0042 
0043     EventSetupRecordImpl::EventSetupRecordImpl(EventSetupRecordImpl&& source)
0044         : validity_{source.validity_},
0045           key_{source.key_},
0046           keysForResolvers_{std::move(source.keysForResolvers_)},
0047           resolvers_(std::move(source.resolvers_)),
0048           activityRegistry_{source.activityRegistry_},
0049           cacheIdentifier_{source.cacheIdentifier_},
0050           iovIndex_{source.iovIndex_},
0051           isAvailable_{source.isAvailable_.load()},
0052           validityModificationUnderway_{source.validityModificationUnderway_.load()} {}
0053 
0054     EventSetupRecordImpl& EventSetupRecordImpl::operator=(EventSetupRecordImpl&& rhs) {
0055       validity_ = rhs.validity_;
0056       key_ = rhs.key_;
0057       keysForResolvers_ = std::move(rhs.keysForResolvers_);
0058       resolvers_ = std::move(rhs.resolvers_);
0059       activityRegistry_ = rhs.activityRegistry_;
0060       cacheIdentifier_ = rhs.cacheIdentifier_;
0061       iovIndex_ = rhs.iovIndex_;
0062       isAvailable_.store(rhs.isAvailable_.load());
0063       validityModificationUnderway_.store(validityModificationUnderway_.load());
0064       return *this;
0065     }
0066 
0067     ValidityInterval EventSetupRecordImpl::validityInterval() const {
0068       bool expected = false;
0069       while (not validityModificationUnderway_.compare_exchange_strong(expected, true)) {
0070         expected = false;
0071       }
0072       ValidityInterval temp = validity_;
0073       validityModificationUnderway_ = false;
0074       return temp;
0075     }
0076 
0077     void EventSetupRecordImpl::initializeForNewIOV(unsigned long long iCacheIdentifier,
0078                                                    ValidityInterval const& iValidityInterval,
0079                                                    bool hasFinder) {
0080       cacheIdentifier_ = iCacheIdentifier;
0081       validity_ = iValidityInterval;
0082       if (hasFinder) {
0083         for (auto& productResolver : resolvers_) {
0084           productResolver->initializeForNewIOV();
0085         }
0086       }
0087     }
0088 
0089     void EventSetupRecordImpl::setSafely(const ValidityInterval& iInterval) const {
0090       bool expected = false;
0091       while (not validityModificationUnderway_.compare_exchange_strong(expected, true)) {
0092         expected = false;
0093       }
0094       validity_ = iInterval;
0095       validityModificationUnderway_ = false;
0096     }
0097 
0098     void EventSetupRecordImpl::getESProducers(std::vector<ComponentDescription const*>& esproducers) const {
0099       esproducers.clear();
0100       esproducers.reserve(resolvers_.size());
0101       for (auto const& iData : resolvers_) {
0102         ComponentDescription const* componentDescription = iData->providerDescription();
0103         if (!componentDescription->isLooper_ && !componentDescription->isSource_) {
0104           esproducers.push_back(componentDescription);
0105         }
0106       }
0107     }
0108 
0109     std::vector<ComponentDescription const*> EventSetupRecordImpl::componentsForRegisteredDataKeys() const {
0110       std::vector<ComponentDescription const*> ret;
0111       ret.reserve(resolvers_.size());
0112       for (auto const& resolver : resolvers_) {
0113         ret.push_back(resolver->providerDescription());
0114       }
0115       return ret;
0116     }
0117 
0118     std::vector<unsigned int> EventSetupRecordImpl::produceMethodIDsForRegisteredDataKeys() const {
0119       std::vector<unsigned int> ret;
0120       ret.reserve(resolvers_.size());
0121       for (auto const& resolver : resolvers_) {
0122         ret.push_back(resolver->produceMethodID());
0123       }
0124       return ret;
0125     }
0126 
0127     bool EventSetupRecordImpl::add(const DataKey& iKey, ESProductResolver* iResolver) {
0128       const ESProductResolver* resolver = find(iKey);
0129       if (nullptr != resolver) {
0130         //
0131         // we already know the field exist, so do not need to check against end()
0132         //
0133 
0134         // POLICY: If a Producer and a Source both claim to deliver the same data, the
0135         //  Producer 'trumps' the Source. If two modules of the same type claim to deliver the
0136         //  same data, this is an error unless the configuration specifically states which one
0137         //  is to be chosen.  A Looper trumps both a Producer and a Source.
0138 
0139         assert(resolver->providerDescription());
0140         assert(iResolver->providerDescription());
0141         if (iResolver->providerDescription()->isLooper_) {
0142           resolvers_[std::distance(keysForResolvers_.begin(),
0143                                    std::lower_bound(keysForResolvers_.begin(), keysForResolvers_.end(), iKey))] =
0144               iResolver;
0145           return true;
0146         }
0147 
0148         if (resolver->providerDescription()->isSource_ == iResolver->providerDescription()->isSource_) {
0149           //should lookup to see if there is a specified 'chosen' one and only if not, throw the exception
0150           throw cms::Exception("EventSetupConflict")
0151               << "two EventSetup " << (resolver->providerDescription()->isSource_ ? "Sources" : "Producers")
0152               << " want to deliver type=\"" << iKey.type().name() << "\" label=\"" << iKey.name().value() << "\"\n"
0153               << " from record " << key().type().name() << ". The two providers are \n"
0154               << "1) type=\"" << resolver->providerDescription()->type_ << "\" label=\""
0155               << resolver->providerDescription()->label_ << "\"\n"
0156               << "2) type=\"" << iResolver->providerDescription()->type_ << "\" label=\""
0157               << iResolver->providerDescription()->label_ << "\"\n"
0158               << "Please either\n   remove one of these "
0159               << (resolver->providerDescription()->isSource_ ? "Sources" : "Producers")
0160               << "\n   or find a way of configuring one of them so it does not deliver this data"
0161               << "\n   or use an es_prefer statement in the configuration to choose one.";
0162         } else if (resolver->providerDescription()->isSource_) {
0163           resolvers_[std::distance(keysForResolvers_.begin(),
0164                                    std::lower_bound(keysForResolvers_.begin(), keysForResolvers_.end(), iKey))] =
0165               iResolver;
0166         } else {
0167           return false;
0168         }
0169       } else {
0170         auto lb = std::lower_bound(keysForResolvers_.begin(), keysForResolvers_.end(), iKey);
0171         auto index = std::distance(keysForResolvers_.begin(), lb);
0172         keysForResolvers_.insert(lb, iKey);
0173         resolvers_.insert(resolvers_.begin() + index, iResolver);
0174       }
0175       return true;
0176     }
0177 
0178     void EventSetupRecordImpl::clearResolvers() {
0179       keysForResolvers_.clear();
0180       resolvers_.clear();
0181     }
0182 
0183     void EventSetupRecordImpl::invalidateResolvers() {
0184       for (auto& productResolver : resolvers_) {
0185         productResolver->invalidate();
0186       }
0187     }
0188 
0189     void EventSetupRecordImpl::resetIfTransientInResolvers() {
0190       for (auto& productResolver : resolvers_) {
0191         productResolver->resetIfTransient();
0192       }
0193     }
0194 
0195     void const* EventSetupRecordImpl::getFromResolverAfterPrefetch(ESResolverIndex iResolverIndex,
0196                                                                    bool iTransientAccessOnly,
0197                                                                    ComponentDescription const*& iDesc,
0198                                                                    DataKey const*& oGottenKey) const {
0199       const ESProductResolver* resolver = resolvers_[iResolverIndex.value()];
0200       assert(nullptr != resolver);
0201       iDesc = resolver->providerDescription();
0202 
0203       auto const& key = keysForResolvers_[iResolverIndex.value()];
0204       oGottenKey = &key;
0205 
0206       void const* hold = nullptr;
0207       try {
0208         convertException::wrap([&]() { hold = resolver->getAfterPrefetch(*this, key, iTransientAccessOnly); });
0209       } catch (cms::Exception& e) {
0210         addTraceInfoToCmsException(e, key.name().value(), resolver->providerDescription(), key);
0211         throw;
0212       }
0213       return hold;
0214     }
0215 
0216     const ESProductResolver* EventSetupRecordImpl::find(const DataKey& iKey) const {
0217       auto lb = std::lower_bound(keysForResolvers_.begin(), keysForResolvers_.end(), iKey);
0218       if ((lb == keysForResolvers_.end()) or (*lb != iKey)) {
0219         return nullptr;
0220       }
0221       return resolvers_[std::distance(keysForResolvers_.begin(), lb)].get();
0222     }
0223 
0224     void EventSetupRecordImpl::prefetchAsync(WaitingTaskHolder iTask,
0225                                              ESResolverIndex iResolverIndex,
0226                                              EventSetupImpl const* iEventSetupImpl,
0227                                              ServiceToken const& iToken,
0228                                              ESParentContext iParent) const noexcept {
0229       if UNLIKELY (iResolverIndex == ESResolverIndex::moduleLabelDoesNotMatch() ||
0230                    iResolverIndex == ESResolverIndex::noResolverConfigured()) {
0231         return;
0232       }
0233 
0234       const ESProductResolver* resolver = resolvers_[iResolverIndex.value()];
0235       if (nullptr != resolver) {
0236         auto const& key = keysForResolvers_[iResolverIndex.value()];
0237         resolver->prefetchAsync(iTask, *this, key, iEventSetupImpl, iToken, iParent);
0238       }
0239     }
0240 
0241     bool EventSetupRecordImpl::wasGotten(const DataKey& aKey) const {
0242       const ESProductResolver* resolver = find(aKey);
0243       if (nullptr != resolver) {
0244         return resolver->cacheIsValid();
0245       }
0246       return false;
0247     }
0248 
0249     edm::eventsetup::ComponentDescription const* EventSetupRecordImpl::providerDescription(const DataKey& aKey) const {
0250       const ESProductResolver* resolver = find(aKey);
0251       if (nullptr != resolver) {
0252         return resolver->providerDescription();
0253       }
0254       return nullptr;
0255     }
0256 
0257     std::vector<DataKey> const& EventSetupRecordImpl::registeredDataKeys() const { return keysForResolvers_; }
0258 
0259     void EventSetupRecordImpl::addTraceInfoToCmsException(cms::Exception& iException,
0260                                                           const char* iName,
0261                                                           const ComponentDescription* iDescription,
0262                                                           const DataKey& iKey) const {
0263       std::ostringstream ost;
0264       ost << "Using EventSetup component " << iDescription->type_ << "/'" << iDescription->label_ << "' to make data "
0265           << iKey.type().name() << "/'" << iName << "' in record " << this->key().type().name();
0266       iException.addContext(ost.str());
0267     }
0268 
0269   }  // namespace eventsetup
0270 }  // namespace edm