Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:12:35

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