Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-04-30 22:24:12

0001 // -*- C++ -*-
0002 //
0003 // Package:     FWCore/Integration
0004 // Class  :     TestESSource
0005 //
0006 // Implementation:
0007 //     ESSource used for tests of Framework support for
0008 //     ESSources and ESProducers. This is primarily focused
0009 //     on the infrastructure used by CondDBESSource.
0010 //
0011 // Original Author:  W. David Dagenhart
0012 //         Created:  15 August 2019
0013 
0014 #include "DataFormats/Provenance/interface/EventID.h"
0015 #include "FWCore/Framework/interface/DataKey.h"
0016 #include "FWCore/Framework/interface/ESSourceProductResolverNonConcurrentBase.h"
0017 #include "FWCore/Framework/interface/ESProductResolverProvider.h"
0018 #include "FWCore/Framework/interface/EventSetupRecordIntervalFinder.h"
0019 #include "FWCore/Framework/interface/EventSetupRecordKey.h"
0020 #include "FWCore/Framework/interface/IOVSyncValue.h"
0021 #include "FWCore/Framework/interface/SourceFactory.h"
0022 #include "FWCore/Framework/interface/ValidityInterval.h"
0023 #include "FWCore/Framework/interface/ESModuleProducesInfo.h"
0024 #include "FWCore/Integration/interface/ESTestRecords.h"
0025 #include "FWCore/Integration/interface/IOVTestInfo.h"
0026 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0027 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0028 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0029 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0030 #include "FWCore/Utilities/interface/Exception.h"
0031 
0032 #include <atomic>
0033 #include <cmath>
0034 #include <limits>
0035 #include <set>
0036 #include <utility>
0037 #include <vector>
0038 #include <mutex>
0039 
0040 namespace edmtest {
0041 
0042   class TestESSource;
0043 
0044   class TestESSourceTestResolver : public edm::eventsetup::ESSourceProductResolverNonConcurrentBase {
0045   public:
0046     TestESSourceTestResolver(TestESSource* testESSource);
0047 
0048   private:
0049     void prefetch(edm::eventsetup::DataKey const&, edm::EventSetupRecordDetails) override;
0050     void initializeForNewIOV() override;
0051     void const* getAfterPrefetchImpl() const override;
0052 
0053     IOVTestInfo iovTestInfo_;
0054     TestESSource* testESSource_;
0055   };
0056 
0057   class TestESSource : public edm::eventsetup::ESProductResolverProvider, public edm::EventSetupRecordIntervalFinder {
0058   public:
0059     using EventSetupRecordKey = edm::eventsetup::EventSetupRecordKey;
0060     explicit TestESSource(edm::ParameterSet const&);
0061     ~TestESSource() override;
0062 
0063     static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0064 
0065     void busyWait(char const* msg) const;
0066 
0067     std::atomic<unsigned int> count_;
0068     std::atomic<unsigned int> count1_;
0069     std::atomic<unsigned int> count2_;
0070     edm::SerialTaskQueue queue_;
0071     std::mutex mutex_;
0072 
0073     std::vector<edm::eventsetup::ESModuleProducesInfo> producesInfo() const override;
0074 
0075   private:
0076     bool isConcurrentFinder() const override { return true; }
0077     void setIntervalFor(EventSetupRecordKey const&, edm::IOVSyncValue const&, edm::ValidityInterval&) override;
0078     KeyedResolversVector registerResolvers(EventSetupRecordKey const&, unsigned int iovIndex) override;
0079     void initConcurrentIOVs(EventSetupRecordKey const&, unsigned int nConcurrentIOVs) override;
0080 
0081     std::set<edm::IOVSyncValue> setOfIOV_;
0082     const unsigned int iterations_;
0083     const double pi_;
0084     unsigned int expectedNumberOfConcurrentIOVs_;
0085     unsigned int nConcurrentIOVs_ = 0;
0086     bool checkIOVInitialization_;
0087   };
0088 
0089   TestESSourceTestResolver::TestESSourceTestResolver(TestESSource* testESSource)
0090       : edm::eventsetup::ESSourceProductResolverNonConcurrentBase(&testESSource->queue_, &testESSource->mutex_),
0091         testESSource_(testESSource) {}
0092 
0093   void TestESSourceTestResolver::prefetch(edm::eventsetup::DataKey const& iKey, edm::EventSetupRecordDetails iRecord) {
0094     ++testESSource_->count_;
0095     if (testESSource_->count_.load() > 1) {
0096       throw cms::Exception("TestFailure") << "TestESSourceTestResolver::getImpl,"
0097                                           << " functions in mutex should not run concurrently";
0098     }
0099     testESSource_->busyWait("getImpl");
0100 
0101     edm::ValidityInterval iov = iRecord.validityInterval();
0102     edm::LogAbsolute("TestESSourceTestResolver")
0103         << "TestESSoureTestResolver::getImpl startIOV = " << iov.first().luminosityBlockNumber()
0104         << " endIOV = " << iov.last().luminosityBlockNumber() << " IOV index = " << iRecord.iovIndex()
0105         << " cache identifier = " << iRecord.cacheIdentifier();
0106 
0107     iovTestInfo_.iovStartLumi_ = iov.first().luminosityBlockNumber();
0108     iovTestInfo_.iovEndLumi_ = iov.last().luminosityBlockNumber();
0109     iovTestInfo_.iovIndex_ = iRecord.iovIndex();
0110     iovTestInfo_.cacheIdentifier_ = iRecord.cacheIdentifier();
0111 
0112     --testESSource_->count_;
0113   }
0114 
0115   void const* TestESSourceTestResolver::getAfterPrefetchImpl() const { return &iovTestInfo_; }
0116 
0117   void TestESSourceTestResolver::initializeForNewIOV() {
0118     edm::LogAbsolute("TestESSourceTestResolver::initializeForNewIOV")
0119         << "TestESSourceTestResolver::initializeForNewIOV";
0120     ++testESSource_->count2_;
0121   }
0122 
0123   TestESSource::TestESSource(edm::ParameterSet const& pset)
0124       : count_(0),
0125         count1_(0),
0126         count2_(0),
0127         iterations_(pset.getParameter<unsigned int>("iterations")),
0128         pi_(std::acos(-1)),
0129         expectedNumberOfConcurrentIOVs_(pset.getParameter<unsigned int>("expectedNumberOfConcurrentIOVs")),
0130         checkIOVInitialization_(pset.getParameter<bool>("checkIOVInitialization")) {
0131     std::vector<unsigned int> temp(pset.getParameter<std::vector<unsigned int>>("firstValidLumis"));
0132     for (auto val : temp) {
0133       setOfIOV_.insert(edm::IOVSyncValue(edm::EventID(1, val, 0)));
0134     }
0135 
0136     findingRecord<ESTestRecordI>();
0137     usingRecord<ESTestRecordI>();
0138   }
0139 
0140   TestESSource::~TestESSource() {}
0141 
0142   void TestESSource::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0143     edm::ParameterSetDescription desc;
0144     std::vector<unsigned int> emptyVector;
0145     desc.add<unsigned int>("iterations", 10 * 1000 * 1000);
0146     desc.add<bool>("checkIOVInitialization", false);
0147     desc.add<unsigned int>("expectedNumberOfConcurrentIOVs", 0);
0148     desc.add<std::vector<unsigned int>>("firstValidLumis", emptyVector);
0149     descriptions.addDefault(desc);
0150   }
0151 
0152   void TestESSource::setIntervalFor(EventSetupRecordKey const&,
0153                                     edm::IOVSyncValue const& syncValue,
0154                                     edm::ValidityInterval& iov) {
0155     std::lock_guard<std::mutex> guard(mutex_);
0156     if (checkIOVInitialization_) {
0157       // Note that this check should pass with the specific configuration where I enable
0158       // the check, but in general it does not have to be true. The counts are offset
0159       // by 1 because the beginRun IOV is invalid (no IOV initialization).
0160       if (count1_ > 0 && count2_ + 1 != count1_) {
0161         throw cms::Exception("TestFailure") << "TestESSource::setIntervalFor,"
0162                                             << " unexpected number of IOV initializations";
0163       }
0164     }
0165     ++count_;
0166     ++count1_;
0167     if (count_.load() > 1) {
0168       throw cms::Exception("TestFailure") << "TestESSource::setIntervalFor,"
0169                                           << " functions in mutex should not run concurrently";
0170     }
0171     busyWait("setIntervalFor");
0172     iov = edm::ValidityInterval::invalidInterval();
0173 
0174     if (setOfIOV_.empty()) {
0175       --count_;
0176       return;
0177     }
0178 
0179     std::pair<std::set<edm::IOVSyncValue>::iterator, std::set<edm::IOVSyncValue>::iterator> itFound =
0180         setOfIOV_.equal_range(syncValue);
0181 
0182     if (itFound.first == itFound.second) {
0183       if (itFound.first == setOfIOV_.begin()) {
0184         //request is before first valid interval, so fail
0185         --count_;
0186         return;
0187       }
0188       //go back one step
0189       --itFound.first;
0190     }
0191 
0192     edm::IOVSyncValue endOfInterval = edm::IOVSyncValue::endOfTime();
0193     if (itFound.second != setOfIOV_.end()) {
0194       endOfInterval = edm::IOVSyncValue(
0195           edm::EventID(1, itFound.second->eventID().luminosityBlock() - 1, edm::EventID::maxEventNumber()));
0196     }
0197     iov = edm::ValidityInterval(*(itFound.first), endOfInterval);
0198     --count_;
0199   }
0200 
0201   std::vector<edm::eventsetup::ESModuleProducesInfo> TestESSource::producesInfo() const {
0202     std::vector<edm::eventsetup::ESModuleProducesInfo> producesInfo;
0203     producesInfo.emplace_back(ESTestRecordI::keyForClass(),
0204                               edm::eventsetup::DataKey(edm::eventsetup::DataKey::makeTypeTag<IOVTestInfo>(), ""),
0205                               0);
0206     return producesInfo;
0207   }
0208 
0209   edm::eventsetup::ESProductResolverProvider::KeyedResolversVector TestESSource::registerResolvers(
0210       EventSetupRecordKey const&, unsigned int iovIndex) {
0211     if (expectedNumberOfConcurrentIOVs_ != 0 && nConcurrentIOVs_ != expectedNumberOfConcurrentIOVs_) {
0212       throw cms::Exception("TestFailure") << "TestESSource::registerResolvers,"
0213                                           << " unexpected number of concurrent IOVs";
0214     }
0215     KeyedResolversVector keyedResolversVector;
0216 
0217     edm::eventsetup::DataKey dataKey(edm::eventsetup::DataKey::makeTypeTag<IOVTestInfo>(), edm::eventsetup::IdTags(""));
0218     keyedResolversVector.emplace_back(dataKey, std::make_shared<TestESSourceTestResolver>(this));
0219 
0220     return keyedResolversVector;
0221   }
0222 
0223   void TestESSource::initConcurrentIOVs(EventSetupRecordKey const& key, unsigned int nConcurrentIOVs) {
0224     edm::LogAbsolute("TestESSource::initConcurrentIOVs")
0225         << "Start TestESSource::initConcurrentIOVs " << nConcurrentIOVs << " " << key.name();
0226     if (EventSetupRecordKey::makeKey<ESTestRecordI>() != key) {
0227       throw cms::Exception("TestFailure") << "TestESSource::initConcurrentIOVs,"
0228                                           << " unexpected EventSetupRecordKey";
0229     }
0230     if (expectedNumberOfConcurrentIOVs_ != 0 && nConcurrentIOVs != expectedNumberOfConcurrentIOVs_) {
0231       throw cms::Exception("TestFailure") << "TestESSource::initConcurrentIOVs,"
0232                                           << " unexpected number of concurrent IOVs";
0233     }
0234     nConcurrentIOVs_ = nConcurrentIOVs;
0235   }
0236 
0237   void TestESSource::busyWait(char const* msg) const {
0238     edm::LogAbsolute("TestESSource::busyWait") << "Start TestESSource::busyWait " << msg;
0239     double sum = 0.;
0240     const double stepSize = pi_ / iterations_;
0241     for (unsigned int i = 0; i < iterations_; ++i) {
0242       sum += stepSize * cos(i * stepSize);
0243     }
0244     edm::LogAbsolute("TestESSource::busyWait") << "Stop TestESSource::busyWait " << msg << " " << sum;
0245   }
0246 }  // namespace edmtest
0247 using namespace edmtest;
0248 DEFINE_FWK_EVENTSETUP_SOURCE(TestESSource);