Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 #ifndef FWCore_Framework_EventSetupRecordImpl_h
0002 #define FWCore_Framework_EventSetupRecordImpl_h
0003 // -*- C++ -*-
0004 //
0005 // Package:     Framework
0006 // Class  :     EventSetupRecordImpl
0007 //
0008 /**\class edm::eventsetup::EventSetupRecordImpl
0009 
0010  Description: Base class for all Records in an EventSetup.  Holds data with the same lifetime.
0011 
0012  Usage:
0013 This class contains the Proxies that make up a given Record.  It
0014 is designed to be reused time after time, rather than it being
0015 destroyed and a new one created every time a new Record is
0016 required.  Proxies can only be added by the EventSetupRecordProvider class which
0017 uses the 'add' function to do this.
0018 
0019 When the set of  Proxies for a Records changes, i.e. a
0020 DataProxyProvider is added of removed from the system, then the
0021 Proxies in a Record need to be changed as appropriate.
0022 In this design it was decided the easiest way to achieve this was
0023 to erase all Proxies in a Record.
0024 
0025 It is important for the management of the Records that each Record
0026 know the ValidityInterval that represents the time over which its data is valid.
0027 The ValidityInterval is set by its EventSetupRecordProvider using the
0028 'set' function.  This quantity can be recovered
0029 through the 'validityInterval' method.
0030 
0031 */
0032 //
0033 // Author:      Chris Jones
0034 // Created:     Fri Mar 25 14:38:35 EST 2005
0035 //
0036 
0037 // user include files
0038 #include "FWCore/Framework/interface/FunctorESHandleExceptionFactory.h"
0039 #include "FWCore/Framework/interface/DataKey.h"
0040 #include "FWCore/Framework/interface/NoProxyException.h"
0041 #include "FWCore/Framework/interface/ValidityInterval.h"
0042 #include "FWCore/Framework/interface/EventSetupRecordKey.h"
0043 #include "FWCore/Concurrency/interface/WaitingTaskHolder.h"
0044 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0045 #include "FWCore/ServiceRegistry/interface/ESParentContext.h"
0046 #include "FWCore/Utilities/interface/propagate_const.h"
0047 #include "FWCore/Utilities/interface/ESInputTag.h"
0048 #include "FWCore/Utilities/interface/ESIndices.h"
0049 
0050 // system include files
0051 #include <exception>
0052 #include <map>
0053 #include <memory>
0054 #include <utility>
0055 #include <vector>
0056 #include <atomic>
0057 #include <cassert>
0058 
0059 // forward declarations
0060 namespace cms {
0061   class Exception;
0062 }  // namespace cms
0063 
0064 namespace edm {
0065 
0066   class ActivityRegistry;
0067   class ESHandleExceptionFactory;
0068   class ESInputTag;
0069   class EventSetupImpl;
0070   class ServiceToken;
0071   class ESParentContext;
0072 
0073   namespace eventsetup {
0074     struct ComponentDescription;
0075     class DataProxy;
0076 
0077     class EventSetupRecordImpl {
0078       friend class EventSetupRecord;
0079 
0080     public:
0081       EventSetupRecordImpl(const EventSetupRecordKey& iKey, ActivityRegistry const*, unsigned int iovIndex = 0);
0082       EventSetupRecordImpl(EventSetupRecordImpl const&) = delete;
0083       EventSetupRecordImpl const& operator=(EventSetupRecordImpl const&) = delete;
0084       EventSetupRecordImpl(EventSetupRecordImpl&&);
0085       EventSetupRecordImpl& operator=(EventSetupRecordImpl&&);
0086 
0087       ValidityInterval validityInterval() const;
0088 
0089       ///prefetch the data to setup for subsequent calls to getImplementation
0090       void prefetchAsync(WaitingTaskHolder iTask,
0091                          ESProxyIndex iProxyIndex,
0092                          EventSetupImpl const*,
0093                          ServiceToken const&,
0094                          ESParentContext) const;
0095 
0096       /**returns true only if someone has already requested data for this key
0097           and the data was retrieved
0098           */
0099       bool wasGotten(DataKey const& aKey) const;
0100 
0101       /**returns the ComponentDescription for the module which creates the data or 0
0102           if no module has been registered for the data. This does not cause the data to
0103           actually be constructed.
0104           */
0105       ComponentDescription const* providerDescription(DataKey const& aKey) const;
0106 
0107       EventSetupRecordKey const& key() const { return key_; }
0108 
0109       /**If you are caching data from the Record, you should also keep
0110           this number.  If this number changes then you know that
0111           the data you have cached is invalid. This is NOT true if
0112           if the validityInterval() hasn't changed since it is possible that
0113           the job has gone to a new Record and then come back to the
0114           previous SyncValue and your algorithm didn't see the intervening
0115           Record.
0116           The value of '0' will never be returned so you can use that to
0117           denote that you have not yet checked the value.
0118           */
0119       unsigned long long cacheIdentifier() const { return cacheIdentifier_; }
0120 
0121       unsigned int iovIndex() const { return iovIndex_; }
0122 
0123       ///clears the oToFill vector and then fills it with the keys for all registered data keys
0124       void fillRegisteredDataKeys(std::vector<DataKey>& oToFill) const;
0125       ///there is a 1-to-1 correspondence between elements returned and the elements returned from fillRegisteredDataKey.
0126       std::vector<ComponentDescription const*> componentsForRegisteredDataKeys() const;
0127 
0128       // The following member functions should only be used by EventSetupRecordProvider
0129       bool add(DataKey const& iKey, DataProxy* iProxy);
0130       void clearProxies();
0131 
0132       ///Set the cache identifier and validity interval when starting a new IOV
0133       ///In addition, also notify the DataProxy's a new IOV is starting.
0134       ///(As a performance optimization, we only notify the DataProxy's if hasFinder
0135       ///is true. At the current time, the CondDBESSource DataProxy's are the only
0136       ///ones who need to know about this and they always have finders).
0137       void initializeForNewIOV(unsigned long long iCacheIdentifier, ValidityInterval const&, bool hasFinder);
0138 
0139       /**Set the validity interval in a thread safe way. This is used when the
0140          IOV is already in use and the end of the IOV needs to be updated but
0141          the start time stays the same. In this case a new IOV does not need
0142          to be started.
0143           */
0144       void setSafely(ValidityInterval const&) const;
0145 
0146       void getESProducers(std::vector<ComponentDescription const*>& esproducers) const;
0147 
0148       DataProxy const* find(DataKey const& aKey) const;
0149 
0150       void validate(ComponentDescription const*, ESInputTag const&) const;
0151 
0152       ActivityRegistry const* activityRegistry() const noexcept { return activityRegistry_; }
0153 
0154       void addTraceInfoToCmsException(cms::Exception& iException,
0155                                       char const* iName,
0156                                       ComponentDescription const*,
0157                                       DataKey const&) const;
0158 
0159       void invalidateProxies();
0160       void resetIfTransientInProxies();
0161 
0162     private:
0163       void const* getFromProxy(DataKey const& iKey,
0164                                ComponentDescription const*& iDesc,
0165                                bool iTransientAccessOnly,
0166                                ESParentContext const&,
0167                                EventSetupImpl const* = nullptr) const;
0168 
0169       void const* getFromProxy(ESProxyIndex iProxyIndex,
0170                                bool iTransientAccessOnly,
0171                                ComponentDescription const*& iDesc,
0172                                DataKey const*& oGottenKey,
0173                                ESParentContext const&,
0174                                EventSetupImpl const* = nullptr) const;
0175 
0176       void const* getFromProxyAfterPrefetch(ESProxyIndex iProxyIndex,
0177                                             bool iTransientAccessOnly,
0178                                             ComponentDescription const*& iDesc,
0179                                             DataKey const*& oGottenKey) const;
0180 
0181       template <typename DataT>
0182       void getImplementation(DataT const*& iData,
0183                              char const* iName,
0184                              ComponentDescription const*& iDesc,
0185                              bool iTransientAccessOnly,
0186                              std::shared_ptr<ESHandleExceptionFactory>& whyFailedFactory,
0187                              ESParentContext const& iParent,
0188                              EventSetupImpl const* iEventSetupImpl) const {
0189         DataKey dataKey(DataKey::makeTypeTag<DataT>(), iName, DataKey::kDoNotCopyMemory);
0190 
0191         void const* pValue = this->getFromProxy(dataKey, iDesc, iTransientAccessOnly, iParent, iEventSetupImpl);
0192         if (nullptr == pValue) {
0193           whyFailedFactory = makeESHandleExceptionFactory([=] {
0194             NoProxyException<DataT> ex(this->key(), dataKey);
0195             return std::make_exception_ptr(ex);
0196           });
0197         }
0198         iData = reinterpret_cast<DataT const*>(pValue);
0199       }
0200 
0201       template <typename DataT>
0202       void getImplementation(DataT const*& iData,
0203                              ESProxyIndex iProxyIndex,
0204                              bool iTransientAccessOnly,
0205                              ComponentDescription const*& oDesc,
0206                              std::shared_ptr<ESHandleExceptionFactory>& whyFailedFactory,
0207                              EventSetupImpl const* iEventSetupImpl) const {
0208         DataKey const* dataKey = nullptr;
0209         if (iProxyIndex.value() == std::numeric_limits<int>::max()) {
0210           whyFailedFactory = makeESHandleExceptionFactory([=] {
0211             NoProxyException<DataT> ex(this->key(), {});
0212             return std::make_exception_ptr(ex);
0213           });
0214           iData = nullptr;
0215           return;
0216         }
0217         assert(iProxyIndex.value() > -1 and
0218                iProxyIndex.value() < static_cast<ESProxyIndex::Value_t>(keysForProxies_.size()));
0219         void const* pValue = this->getFromProxyAfterPrefetch(iProxyIndex, iTransientAccessOnly, oDesc, dataKey);
0220         if (nullptr == pValue) {
0221           whyFailedFactory = makeESHandleExceptionFactory([=] {
0222             NoProxyException<DataT> ex(this->key(), *dataKey);
0223             return std::make_exception_ptr(ex);
0224           });
0225         }
0226         iData = reinterpret_cast<DataT const*>(pValue);
0227       }
0228 
0229       // ---------- member data --------------------------------
0230 
0231       // We allow the validity to be modified while it is being used in
0232       // the case where a new sync value is being initialized and the
0233       // first part of the new validity range is the same,
0234       // but the last part of the validity range changes. In this case,
0235       // we do not want to start a new IOV, all the cached data should
0236       // remain valid. The atomic bool validityModificationUnderway_
0237       // protects access to validity_ while this change is made.
0238       CMS_THREAD_SAFE mutable ValidityInterval validity_;
0239 
0240       EventSetupRecordKey key_;
0241       std::vector<DataKey> keysForProxies_;
0242       std::vector<edm::propagate_const<DataProxy*>> proxies_;
0243       ActivityRegistry const* activityRegistry_;
0244       unsigned long long cacheIdentifier_;
0245       unsigned int iovIndex_;
0246       std::atomic<bool> isAvailable_;
0247       mutable std::atomic<bool> validityModificationUnderway_;
0248     };
0249   }  // namespace eventsetup
0250 }  // namespace edm
0251 #endif