Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 11:02:15

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/DataProxy.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           keysForProxies_{std::move(source.keysForProxies_)},
0047           proxies_(std::move(source.proxies_)),
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       keysForProxies_ = std::move(rhs.keysForProxies_);
0058       proxies_ = std::move(rhs.proxies_);
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& dataProxy : proxies_) {
0084           dataProxy->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(proxies_.size());
0101       for (auto const& iData : proxies_) {
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(proxies_.size());
0112       for (auto const& proxy : proxies_) {
0113         ret.push_back(proxy->providerDescription());
0114       }
0115       return ret;
0116     }
0117 
0118     bool EventSetupRecordImpl::add(const DataKey& iKey, DataProxy* iProxy) {
0119       const DataProxy* proxy = find(iKey);
0120       if (nullptr != proxy) {
0121         //
0122         // we already know the field exist, so do not need to check against end()
0123         //
0124 
0125         // POLICY: If a Producer and a Source both claim to deliver the same data, the
0126         //  Producer 'trumps' the Source. If two modules of the same type claim to deliver the
0127         //  same data, this is an error unless the configuration specifically states which one
0128         //  is to be chosen.  A Looper trumps both a Producer and a Source.
0129 
0130         assert(proxy->providerDescription());
0131         assert(iProxy->providerDescription());
0132         if (iProxy->providerDescription()->isLooper_) {
0133           proxies_[std::distance(keysForProxies_.begin(),
0134                                  std::lower_bound(keysForProxies_.begin(), keysForProxies_.end(), iKey))] = iProxy;
0135           return true;
0136         }
0137 
0138         if (proxy->providerDescription()->isSource_ == iProxy->providerDescription()->isSource_) {
0139           //should lookup to see if there is a specified 'chosen' one and only if not, throw the exception
0140           throw cms::Exception("EventSetupConflict")
0141               << "two EventSetup " << (proxy->providerDescription()->isSource_ ? "Sources" : "Producers")
0142               << " want to deliver type=\"" << iKey.type().name() << "\" label=\"" << iKey.name().value() << "\"\n"
0143               << " from record " << key().type().name() << ". The two providers are \n"
0144               << "1) type=\"" << proxy->providerDescription()->type_ << "\" label=\""
0145               << proxy->providerDescription()->label_ << "\"\n"
0146               << "2) type=\"" << iProxy->providerDescription()->type_ << "\" label=\""
0147               << iProxy->providerDescription()->label_ << "\"\n"
0148               << "Please either\n   remove one of these "
0149               << (proxy->providerDescription()->isSource_ ? "Sources" : "Producers")
0150               << "\n   or find a way of configuring one of them so it does not deliver this data"
0151               << "\n   or use an es_prefer statement in the configuration to choose one.";
0152         } else if (proxy->providerDescription()->isSource_) {
0153           proxies_[std::distance(keysForProxies_.begin(),
0154                                  std::lower_bound(keysForProxies_.begin(), keysForProxies_.end(), iKey))] = iProxy;
0155         } else {
0156           return false;
0157         }
0158       } else {
0159         auto lb = std::lower_bound(keysForProxies_.begin(), keysForProxies_.end(), iKey);
0160         auto index = std::distance(keysForProxies_.begin(), lb);
0161         keysForProxies_.insert(lb, iKey);
0162         proxies_.insert(proxies_.begin() + index, iProxy);
0163       }
0164       return true;
0165     }
0166 
0167     void EventSetupRecordImpl::clearProxies() {
0168       keysForProxies_.clear();
0169       proxies_.clear();
0170     }
0171 
0172     void EventSetupRecordImpl::invalidateProxies() {
0173       for (auto& dataProxy : proxies_) {
0174         dataProxy->invalidate();
0175       }
0176     }
0177 
0178     void EventSetupRecordImpl::resetIfTransientInProxies() {
0179       for (auto& dataProxy : proxies_) {
0180         dataProxy->resetIfTransient();
0181       }
0182     }
0183 
0184     void const* EventSetupRecordImpl::getFromProxyAfterPrefetch(ESProxyIndex iProxyIndex,
0185                                                                 bool iTransientAccessOnly,
0186                                                                 ComponentDescription const*& iDesc,
0187                                                                 DataKey const*& oGottenKey) const {
0188       const DataProxy* proxy = proxies_[iProxyIndex.value()];
0189       assert(nullptr != proxy);
0190       iDesc = proxy->providerDescription();
0191 
0192       auto const& key = keysForProxies_[iProxyIndex.value()];
0193       oGottenKey = &key;
0194 
0195       void const* hold = nullptr;
0196       try {
0197         convertException::wrap([&]() { hold = proxy->getAfterPrefetch(*this, key, iTransientAccessOnly); });
0198       } catch (cms::Exception& e) {
0199         addTraceInfoToCmsException(e, key.name().value(), proxy->providerDescription(), key);
0200         throw;
0201       }
0202       return hold;
0203     }
0204 
0205     const DataProxy* EventSetupRecordImpl::find(const DataKey& iKey) const {
0206       auto lb = std::lower_bound(keysForProxies_.begin(), keysForProxies_.end(), iKey);
0207       if ((lb == keysForProxies_.end()) or (*lb != iKey)) {
0208         return nullptr;
0209       }
0210       return proxies_[std::distance(keysForProxies_.begin(), lb)].get();
0211     }
0212 
0213     void EventSetupRecordImpl::prefetchAsync(WaitingTaskHolder iTask,
0214                                              ESProxyIndex iProxyIndex,
0215                                              EventSetupImpl const* iEventSetupImpl,
0216                                              ServiceToken const& iToken,
0217                                              ESParentContext iParent) const {
0218       if UNLIKELY (iProxyIndex.value() == std::numeric_limits<int>::max()) {
0219         return;
0220       }
0221 
0222       const DataProxy* proxy = proxies_[iProxyIndex.value()];
0223       if (nullptr != proxy) {
0224         auto const& key = keysForProxies_[iProxyIndex.value()];
0225         proxy->prefetchAsync(iTask, *this, key, iEventSetupImpl, iToken, iParent);
0226       }
0227     }
0228 
0229     bool EventSetupRecordImpl::wasGotten(const DataKey& aKey) const {
0230       const DataProxy* proxy = find(aKey);
0231       if (nullptr != proxy) {
0232         return proxy->cacheIsValid();
0233       }
0234       return false;
0235     }
0236 
0237     edm::eventsetup::ComponentDescription const* EventSetupRecordImpl::providerDescription(const DataKey& aKey) const {
0238       const DataProxy* proxy = find(aKey);
0239       if (nullptr != proxy) {
0240         return proxy->providerDescription();
0241       }
0242       return nullptr;
0243     }
0244 
0245     void EventSetupRecordImpl::fillRegisteredDataKeys(std::vector<DataKey>& oToFill) const {
0246       oToFill = keysForProxies_;
0247     }
0248 
0249     void EventSetupRecordImpl::addTraceInfoToCmsException(cms::Exception& iException,
0250                                                           const char* iName,
0251                                                           const ComponentDescription* iDescription,
0252                                                           const DataKey& iKey) const {
0253       std::ostringstream ost;
0254       ost << "Using EventSetup component " << iDescription->type_ << "/'" << iDescription->label_ << "' to make data "
0255           << iKey.type().name() << "/'" << iName << "' in record " << this->key().type().name();
0256       iException.addContext(ost.str());
0257     }
0258 
0259   }  // namespace eventsetup
0260 }  // namespace edm