Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-24 09:53:05

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 <cassert>
0015 #include <sstream>
0016 
0017 // user include files
0018 #include "FWCore/Framework/interface/EventSetupRecordImpl.h"
0019 #include "FWCore/Framework/interface/DataProxy.h"
0020 #include "FWCore/Framework/interface/ComponentDescription.h"
0021 #include "FWCore/ServiceRegistry/interface/ESParentContext.h"
0022 
0023 #include "FWCore/Concurrency/interface/WaitingTaskHolder.h"
0024 #include "FWCore/Utilities/interface/ConvertException.h"
0025 #include "FWCore/Utilities/interface/Exception.h"
0026 
0027 namespace edm {
0028   namespace eventsetup {
0029 
0030     EventSetupRecordImpl::EventSetupRecordImpl(EventSetupRecordKey const& iKey,
0031                                                ActivityRegistry const* activityRegistry,
0032                                                unsigned int iovIndex)
0033         : validity_(),
0034           key_(iKey),
0035           activityRegistry_(activityRegistry),
0036           cacheIdentifier_(1),  // initial value meaningless, gets overwritten before use
0037           iovIndex_(iovIndex),
0038           isAvailable_(true),
0039           validityModificationUnderway_(false) {}
0040 
0041     EventSetupRecordImpl::EventSetupRecordImpl(EventSetupRecordImpl&& source)
0042         : validity_{source.validity_},
0043           key_{source.key_},
0044           keysForProxies_{std::move(source.keysForProxies_)},
0045           proxies_(std::move(source.proxies_)),
0046           activityRegistry_{source.activityRegistry_},
0047           cacheIdentifier_{source.cacheIdentifier_},
0048           iovIndex_{source.iovIndex_},
0049           isAvailable_{source.isAvailable_.load()},
0050           validityModificationUnderway_{source.validityModificationUnderway_.load()} {}
0051 
0052     EventSetupRecordImpl& EventSetupRecordImpl::operator=(EventSetupRecordImpl&& rhs) {
0053       validity_ = rhs.validity_;
0054       key_ = rhs.key_;
0055       keysForProxies_ = std::move(rhs.keysForProxies_);
0056       proxies_ = std::move(rhs.proxies_);
0057       activityRegistry_ = rhs.activityRegistry_;
0058       cacheIdentifier_ = rhs.cacheIdentifier_;
0059       iovIndex_ = rhs.iovIndex_;
0060       isAvailable_.store(rhs.isAvailable_.load());
0061       validityModificationUnderway_.store(validityModificationUnderway_.load());
0062       return *this;
0063     }
0064 
0065     ValidityInterval EventSetupRecordImpl::validityInterval() const {
0066       bool expected = false;
0067       while (not validityModificationUnderway_.compare_exchange_strong(expected, true)) {
0068         expected = false;
0069       }
0070       ValidityInterval temp = validity_;
0071       validityModificationUnderway_ = false;
0072       return temp;
0073     }
0074 
0075     void EventSetupRecordImpl::initializeForNewIOV(unsigned long long iCacheIdentifier,
0076                                                    ValidityInterval const& iValidityInterval,
0077                                                    bool hasFinder) {
0078       cacheIdentifier_ = iCacheIdentifier;
0079       validity_ = iValidityInterval;
0080       if (hasFinder) {
0081         for (auto& dataProxy : proxies_) {
0082           dataProxy->initializeForNewIOV();
0083         }
0084       }
0085     }
0086 
0087     void EventSetupRecordImpl::setSafely(const ValidityInterval& iInterval) const {
0088       bool expected = false;
0089       while (not validityModificationUnderway_.compare_exchange_strong(expected, true)) {
0090         expected = false;
0091       }
0092       validity_ = iInterval;
0093       validityModificationUnderway_ = false;
0094     }
0095 
0096     void EventSetupRecordImpl::getESProducers(std::vector<ComponentDescription const*>& esproducers) const {
0097       esproducers.clear();
0098       esproducers.reserve(proxies_.size());
0099       for (auto const& iData : proxies_) {
0100         ComponentDescription const* componentDescription = iData->providerDescription();
0101         if (!componentDescription->isLooper_ && !componentDescription->isSource_) {
0102           esproducers.push_back(componentDescription);
0103         }
0104       }
0105     }
0106 
0107     std::vector<ComponentDescription const*> EventSetupRecordImpl::componentsForRegisteredDataKeys() const {
0108       std::vector<ComponentDescription const*> ret;
0109       ret.reserve(proxies_.size());
0110       for (auto const& proxy : proxies_) {
0111         ret.push_back(proxy->providerDescription());
0112       }
0113       return ret;
0114     }
0115 
0116     bool EventSetupRecordImpl::add(const DataKey& iKey, DataProxy* iProxy) {
0117       const DataProxy* proxy = find(iKey);
0118       if (nullptr != proxy) {
0119         //
0120         // we already know the field exist, so do not need to check against end()
0121         //
0122 
0123         // POLICY: If a Producer and a Source both claim to deliver the same data, the
0124         //  Producer 'trumps' the Source. If two modules of the same type claim to deliver the
0125         //  same data, this is an error unless the configuration specifically states which one
0126         //  is to be chosen.  A Looper trumps both a Producer and a Source.
0127 
0128         assert(proxy->providerDescription());
0129         assert(iProxy->providerDescription());
0130         if (iProxy->providerDescription()->isLooper_) {
0131           proxies_[std::distance(keysForProxies_.begin(),
0132                                  std::lower_bound(keysForProxies_.begin(), keysForProxies_.end(), iKey))] = iProxy;
0133           return true;
0134         }
0135 
0136         if (proxy->providerDescription()->isSource_ == iProxy->providerDescription()->isSource_) {
0137           //should lookup to see if there is a specified 'chosen' one and only if not, throw the exception
0138           throw cms::Exception("EventSetupConflict")
0139               << "two EventSetup " << (proxy->providerDescription()->isSource_ ? "Sources" : "Producers")
0140               << " want to deliver type=\"" << iKey.type().name() << "\" label=\"" << iKey.name().value() << "\"\n"
0141               << " from record " << key().type().name() << ". The two providers are \n"
0142               << "1) type=\"" << proxy->providerDescription()->type_ << "\" label=\""
0143               << proxy->providerDescription()->label_ << "\"\n"
0144               << "2) type=\"" << iProxy->providerDescription()->type_ << "\" label=\""
0145               << iProxy->providerDescription()->label_ << "\"\n"
0146               << "Please either\n   remove one of these "
0147               << (proxy->providerDescription()->isSource_ ? "Sources" : "Producers")
0148               << "\n   or find a way of configuring one of them so it does not deliver this data"
0149               << "\n   or use an es_prefer statement in the configuration to choose one.";
0150         } else if (proxy->providerDescription()->isSource_) {
0151           proxies_[std::distance(keysForProxies_.begin(),
0152                                  std::lower_bound(keysForProxies_.begin(), keysForProxies_.end(), iKey))] = iProxy;
0153         } else {
0154           return false;
0155         }
0156       } else {
0157         auto lb = std::lower_bound(keysForProxies_.begin(), keysForProxies_.end(), iKey);
0158         auto index = std::distance(keysForProxies_.begin(), lb);
0159         keysForProxies_.insert(lb, iKey);
0160         proxies_.insert(proxies_.begin() + index, iProxy);
0161       }
0162       return true;
0163     }
0164 
0165     void EventSetupRecordImpl::clearProxies() {
0166       keysForProxies_.clear();
0167       proxies_.clear();
0168     }
0169 
0170     void EventSetupRecordImpl::invalidateProxies() {
0171       for (auto& dataProxy : proxies_) {
0172         dataProxy->invalidate();
0173       }
0174     }
0175 
0176     void EventSetupRecordImpl::resetIfTransientInProxies() {
0177       for (auto& dataProxy : proxies_) {
0178         dataProxy->resetIfTransient();
0179       }
0180     }
0181 
0182     const void* EventSetupRecordImpl::getFromProxy(DataKey const& iKey,
0183                                                    const ComponentDescription*& iDesc,
0184                                                    bool iTransientAccessOnly,
0185                                                    ESParentContext const& iParent,
0186                                                    EventSetupImpl const* iEventSetupImpl) const {
0187       const DataProxy* proxy = this->find(iKey);
0188 
0189       const void* hold = nullptr;
0190 
0191       if (nullptr != proxy) {
0192         try {
0193           convertException::wrap([&]() {
0194             hold = proxy->get(*this, iKey, iTransientAccessOnly, activityRegistry_, iEventSetupImpl, iParent);
0195             iDesc = proxy->providerDescription();
0196           });
0197         } catch (cms::Exception& e) {
0198           addTraceInfoToCmsException(e, iKey.name().value(), proxy->providerDescription(), iKey);
0199           //NOTE: the above function can't do the 'throw' since it causes the C++ class type
0200           // of the throw to be changed, a 'rethrow' does not have that problem
0201           throw;
0202         }
0203       }
0204       return hold;
0205     }
0206 
0207     const void* EventSetupRecordImpl::getFromProxy(ESProxyIndex iProxyIndex,
0208                                                    bool iTransientAccessOnly,
0209                                                    const ComponentDescription*& iDesc,
0210                                                    DataKey const*& oGottenKey,
0211                                                    ESParentContext const& iParent,
0212                                                    EventSetupImpl const* iEventSetupImpl) const {
0213       if (iProxyIndex.value() >= static_cast<ESProxyIndex::Value_t>(proxies_.size())) {
0214         return nullptr;
0215       }
0216 
0217       const DataProxy* proxy = proxies_[iProxyIndex.value()];
0218       assert(nullptr != proxy);
0219       iDesc = proxy->providerDescription();
0220 
0221       const void* hold = nullptr;
0222 
0223       auto const& key = keysForProxies_[iProxyIndex.value()];
0224       oGottenKey = &key;
0225       try {
0226         convertException::wrap([&]() {
0227           hold = proxy->get(*this, key, iTransientAccessOnly, activityRegistry_, iEventSetupImpl, iParent);
0228         });
0229       } catch (cms::Exception& e) {
0230         addTraceInfoToCmsException(e, key.name().value(), proxy->providerDescription(), key);
0231         throw;
0232       }
0233       return hold;
0234     }
0235 
0236     void const* EventSetupRecordImpl::getFromProxyAfterPrefetch(ESProxyIndex iProxyIndex,
0237                                                                 bool iTransientAccessOnly,
0238                                                                 ComponentDescription const*& iDesc,
0239                                                                 DataKey const*& oGottenKey) const {
0240       const DataProxy* proxy = proxies_[iProxyIndex.value()];
0241       assert(nullptr != proxy);
0242       iDesc = proxy->providerDescription();
0243 
0244       auto const& key = keysForProxies_[iProxyIndex.value()];
0245       oGottenKey = &key;
0246 
0247       void const* hold = nullptr;
0248       try {
0249         convertException::wrap([&]() { hold = proxy->getAfterPrefetch(*this, key, iTransientAccessOnly); });
0250       } catch (cms::Exception& e) {
0251         addTraceInfoToCmsException(e, key.name().value(), proxy->providerDescription(), key);
0252         throw;
0253       }
0254       return hold;
0255     }
0256 
0257     const DataProxy* EventSetupRecordImpl::find(const DataKey& iKey) const {
0258       auto lb = std::lower_bound(keysForProxies_.begin(), keysForProxies_.end(), iKey);
0259       if ((lb == keysForProxies_.end()) or (*lb != iKey)) {
0260         return nullptr;
0261       }
0262       return proxies_[std::distance(keysForProxies_.begin(), lb)].get();
0263     }
0264 
0265     void EventSetupRecordImpl::prefetchAsync(WaitingTaskHolder iTask,
0266                                              ESProxyIndex iProxyIndex,
0267                                              EventSetupImpl const* iEventSetupImpl,
0268                                              ServiceToken const& iToken,
0269                                              ESParentContext iParent) const {
0270       if UNLIKELY (iProxyIndex.value() == std::numeric_limits<int>::max()) {
0271         return;
0272       }
0273 
0274       const DataProxy* proxy = proxies_[iProxyIndex.value()];
0275       if (nullptr != proxy) {
0276         auto const& key = keysForProxies_[iProxyIndex.value()];
0277         proxy->prefetchAsync(iTask, *this, key, iEventSetupImpl, iToken, iParent);
0278       }
0279     }
0280 
0281     bool EventSetupRecordImpl::wasGotten(const DataKey& aKey) const {
0282       const DataProxy* proxy = find(aKey);
0283       if (nullptr != proxy) {
0284         return proxy->cacheIsValid();
0285       }
0286       return false;
0287     }
0288 
0289     edm::eventsetup::ComponentDescription const* EventSetupRecordImpl::providerDescription(const DataKey& aKey) const {
0290       const DataProxy* proxy = find(aKey);
0291       if (nullptr != proxy) {
0292         return proxy->providerDescription();
0293       }
0294       return nullptr;
0295     }
0296 
0297     void EventSetupRecordImpl::fillRegisteredDataKeys(std::vector<DataKey>& oToFill) const {
0298       oToFill = keysForProxies_;
0299     }
0300 
0301     void EventSetupRecordImpl::validate(const ComponentDescription* iDesc, const ESInputTag& iTag) const {
0302       if (iDesc && !iTag.module().empty()) {
0303         bool matched = false;
0304         if (iDesc->label_.empty()) {
0305           matched = iDesc->type_ == iTag.module();
0306         } else {
0307           matched = iDesc->label_ == iTag.module();
0308         }
0309         if (!matched) {
0310           throw cms::Exception("EventSetupWrongModule")
0311               << "EventSetup data was retrieved using an ESInputTag with the values\n"
0312               << "  moduleLabel = '" << iTag.module() << "'\n"
0313               << "  dataLabel = '" << iTag.data() << "'\n"
0314               << "but the data matching the C++ class type and dataLabel comes from module type=" << iDesc->type_
0315               << " label='" << iDesc->label_ << "'.\n Please either change the ESInputTag's 'module' label to be "
0316               << (iDesc->label_.empty() ? iDesc->type_ : iDesc->label_) << "\n or add the EventSetup module "
0317               << iTag.module() << " to the configuration.";
0318         }
0319       }
0320     }
0321 
0322     void EventSetupRecordImpl::addTraceInfoToCmsException(cms::Exception& iException,
0323                                                           const char* iName,
0324                                                           const ComponentDescription* iDescription,
0325                                                           const DataKey& iKey) const {
0326       std::ostringstream ost;
0327       ost << "Using EventSetup component " << iDescription->type_ << "/'" << iDescription->label_ << "' to make data "
0328           << iKey.type().name() << "/'" << iName << "' in record " << this->key().type().name();
0329       iException.addContext(ost.str());
0330     }
0331 
0332   }  // namespace eventsetup
0333 }  // namespace edm