Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-12-22 01:53:32

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/ESSourceDataProxyNonConcurrentBase.h"
0017 #include "FWCore/Framework/interface/DataProxyProvider.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/test/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 TestESSourceTestProxy : public edm::eventsetup::ESSourceDataProxyNonConcurrentBase {
0044   public:
0045     TestESSourceTestProxy(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::DataProxyProvider, public edm::EventSetupRecordIntervalFinder {
0057   public:
0058     using EventSetupRecordKey = edm::eventsetup::EventSetupRecordKey;
0059     explicit TestESSource(edm::ParameterSet const&);
0060     ~TestESSource();
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     KeyedProxiesVector registerProxies(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   TestESSourceTestProxy::TestESSourceTestProxy(TestESSource* testESSource)
0087       : edm::eventsetup::ESSourceDataProxyNonConcurrentBase(&testESSource->queue_, &testESSource->mutex_),
0088         testESSource_(testESSource) {}
0089 
0090   void TestESSourceTestProxy::prefetch(edm::eventsetup::DataKey const& iKey, edm::EventSetupRecordDetails iRecord) {
0091     ++testESSource_->count_;
0092     if (testESSource_->count_.load() > 1) {
0093       throw cms::Exception("TestFailure") << "TestESSourceTestProxy::getImpl,"
0094                                           << " functions in mutex should not run concurrently";
0095     }
0096     testESSource_->busyWait("getImpl");
0097 
0098     edm::ValidityInterval iov = iRecord.validityInterval();
0099     edm::LogAbsolute("TestESSourceTestProxy")
0100         << "TestESSoureTestProxy::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* TestESSourceTestProxy::getAfterPrefetchImpl() const { return &iovTestInfo_; }
0113 
0114   void TestESSourceTestProxy::initializeForNewIOV() {
0115     edm::LogAbsolute("TestESSourceTestProxy::initializeForNewIOV") << "TestESSourceTestProxy::initializeForNewIOV";
0116     ++testESSource_->count2_;
0117   }
0118 
0119   TestESSource::TestESSource(edm::ParameterSet const& pset)
0120       : count_(0),
0121         count1_(0),
0122         count2_(0),
0123         iterations_(pset.getParameter<unsigned int>("iterations")),
0124         pi_(std::acos(-1)),
0125         expectedNumberOfConcurrentIOVs_(pset.getParameter<unsigned int>("expectedNumberOfConcurrentIOVs")),
0126         checkIOVInitialization_(pset.getParameter<bool>("checkIOVInitialization")) {
0127     std::vector<unsigned int> temp(pset.getParameter<std::vector<unsigned int>>("firstValidLumis"));
0128     for (auto val : temp) {
0129       setOfIOV_.insert(edm::IOVSyncValue(edm::EventID(1, val, 0)));
0130     }
0131 
0132     findingRecord<ESTestRecordI>();
0133     usingRecord<ESTestRecordI>();
0134   }
0135 
0136   TestESSource::~TestESSource() {}
0137 
0138   void TestESSource::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0139     edm::ParameterSetDescription desc;
0140     std::vector<unsigned int> emptyVector;
0141     desc.add<unsigned int>("iterations", 10 * 1000 * 1000);
0142     desc.add<bool>("checkIOVInitialization", false);
0143     desc.add<unsigned int>("expectedNumberOfConcurrentIOVs", 0);
0144     desc.add<std::vector<unsigned int>>("firstValidLumis", emptyVector);
0145     descriptions.addDefault(desc);
0146   }
0147 
0148   void TestESSource::setIntervalFor(EventSetupRecordKey const&,
0149                                     edm::IOVSyncValue const& syncValue,
0150                                     edm::ValidityInterval& iov) {
0151     std::lock_guard<std::mutex> guard(mutex_);
0152     if (checkIOVInitialization_) {
0153       // Note that this check should pass with the specific configuration where I enable
0154       // the check, but in general it does not have to be true. The counts are offset
0155       // by 1 because the beginRun IOV is invalid (no IOV initialization).
0156       if (count1_ > 0 && count2_ + 1 != count1_) {
0157         throw cms::Exception("TestFailure") << "TestESSource::setIntervalFor,"
0158                                             << " unexpected number of IOV initializations";
0159       }
0160     }
0161     ++count_;
0162     ++count1_;
0163     if (count_.load() > 1) {
0164       throw cms::Exception("TestFailure") << "TestESSource::setIntervalFor,"
0165                                           << " functions in mutex should not run concurrently";
0166     }
0167     busyWait("setIntervalFor");
0168     iov = edm::ValidityInterval::invalidInterval();
0169 
0170     if (setOfIOV_.empty()) {
0171       --count_;
0172       return;
0173     }
0174 
0175     std::pair<std::set<edm::IOVSyncValue>::iterator, std::set<edm::IOVSyncValue>::iterator> itFound =
0176         setOfIOV_.equal_range(syncValue);
0177 
0178     if (itFound.first == itFound.second) {
0179       if (itFound.first == setOfIOV_.begin()) {
0180         //request is before first valid interval, so fail
0181         --count_;
0182         return;
0183       }
0184       //go back one step
0185       --itFound.first;
0186     }
0187 
0188     edm::IOVSyncValue endOfInterval = edm::IOVSyncValue::endOfTime();
0189     if (itFound.second != setOfIOV_.end()) {
0190       endOfInterval = edm::IOVSyncValue(
0191           edm::EventID(1, itFound.second->eventID().luminosityBlock() - 1, edm::EventID::maxEventNumber()));
0192     }
0193     iov = edm::ValidityInterval(*(itFound.first), endOfInterval);
0194     --count_;
0195   }
0196 
0197   edm::eventsetup::DataProxyProvider::KeyedProxiesVector TestESSource::registerProxies(EventSetupRecordKey const&,
0198                                                                                        unsigned int iovIndex) {
0199     if (expectedNumberOfConcurrentIOVs_ != 0 && nConcurrentIOVs_ != expectedNumberOfConcurrentIOVs_) {
0200       throw cms::Exception("TestFailure") << "TestESSource::registerProxies,"
0201                                           << " unexpected number of concurrent IOVs";
0202     }
0203     KeyedProxiesVector keyedProxiesVector;
0204 
0205     edm::eventsetup::DataKey dataKey(edm::eventsetup::DataKey::makeTypeTag<IOVTestInfo>(), edm::eventsetup::IdTags(""));
0206     keyedProxiesVector.emplace_back(dataKey, std::make_shared<TestESSourceTestProxy>(this));
0207 
0208     return keyedProxiesVector;
0209   }
0210 
0211   void TestESSource::initConcurrentIOVs(EventSetupRecordKey const& key, unsigned int nConcurrentIOVs) {
0212     edm::LogAbsolute("TestESSource::initConcurrentIOVs")
0213         << "Start TestESSource::initConcurrentIOVs " << nConcurrentIOVs << " " << key.name();
0214     if (EventSetupRecordKey::makeKey<ESTestRecordI>() != key) {
0215       throw cms::Exception("TestFailure") << "TestESSource::initConcurrentIOVs,"
0216                                           << " unexpected EventSetupRecordKey";
0217     }
0218     if (expectedNumberOfConcurrentIOVs_ != 0 && nConcurrentIOVs != expectedNumberOfConcurrentIOVs_) {
0219       throw cms::Exception("TestFailure") << "TestESSource::initConcurrentIOVs,"
0220                                           << " unexpected number of concurrent IOVs";
0221     }
0222     nConcurrentIOVs_ = nConcurrentIOVs;
0223   }
0224 
0225   void TestESSource::busyWait(char const* msg) const {
0226     edm::LogAbsolute("TestESSource::busyWait") << "Start TestESSource::busyWait " << msg;
0227     double sum = 0.;
0228     const double stepSize = pi_ / iterations_;
0229     for (unsigned int i = 0; i < iterations_; ++i) {
0230       sum += stepSize * cos(i * stepSize);
0231     }
0232     edm::LogAbsolute("TestESSource::busyWait") << "Stop TestESSource::busyWait " << msg << " " << sum;
0233   }
0234 }  // namespace edmtest
0235 using namespace edmtest;
0236 DEFINE_FWK_EVENTSETUP_SOURCE(TestESSource);