File indexing completed on 2025-04-30 22:24:12
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include "DataFormats/Provenance/interface/EventID.h"
0015 #include "FWCore/Framework/interface/DataKey.h"
0016 #include "FWCore/Framework/interface/ESSourceProductResolverConcurrentBase.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
0039 namespace edmtest {
0040
0041 class TestESConcurrentSource;
0042
0043 class TestESConcurrentSourceTestResolver : public edm::eventsetup::ESSourceProductResolverConcurrentBase {
0044 public:
0045 TestESConcurrentSourceTestResolver(TestESConcurrentSource* TestESConcurrentSource);
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 TestESConcurrentSource* testESConcurrentSource_;
0054 };
0055
0056 class TestESConcurrentSource : public edm::eventsetup::ESProductResolverProvider,
0057 public edm::EventSetupRecordIntervalFinder {
0058 public:
0059 using EventSetupRecordKey = edm::eventsetup::EventSetupRecordKey;
0060 explicit TestESConcurrentSource(edm::ParameterSet const&);
0061 ~TestESConcurrentSource() override;
0062
0063 static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0064
0065 void busyWait(char const* msg) const;
0066
0067 void incrementCount() {
0068 auto const v = ++count_;
0069 auto m = maxCount_.load();
0070 while (m < v) {
0071 maxCount_.compare_exchange_strong(m, v);
0072 }
0073 }
0074 std::atomic<unsigned int> count_;
0075 std::atomic<unsigned int> maxCount_;
0076 std::atomic<unsigned int> count_setIntervalFor_;
0077 std::atomic<unsigned int> count_initializeForNewIOV_;
0078
0079 std::vector<edm::eventsetup::ESModuleProducesInfo> producesInfo() const override;
0080
0081 private:
0082 bool isConcurrentFinder() const override { return true; }
0083 void setIntervalFor(EventSetupRecordKey const&, edm::IOVSyncValue const&, edm::ValidityInterval&) override;
0084 KeyedResolversVector registerResolvers(EventSetupRecordKey const&, unsigned int iovIndex) override;
0085 void initConcurrentIOVs(EventSetupRecordKey const&, unsigned int nConcurrentIOVs) override;
0086
0087 std::set<edm::IOVSyncValue> setOfIOV_;
0088 const unsigned int iterations_;
0089 const double pi_;
0090 unsigned int expectedNumberOfConcurrentIOVs_;
0091 unsigned int nConcurrentIOVs_ = 0;
0092 bool checkIOVInitialization_;
0093 };
0094
0095 TestESConcurrentSourceTestResolver::TestESConcurrentSourceTestResolver(TestESConcurrentSource* testESConcurrentSource)
0096 : edm::eventsetup::ESSourceProductResolverConcurrentBase(), testESConcurrentSource_(testESConcurrentSource) {}
0097
0098 void TestESConcurrentSourceTestResolver::prefetch(edm::eventsetup::DataKey const& iKey,
0099 edm::EventSetupRecordDetails iRecord) {
0100 testESConcurrentSource_->incrementCount();
0101 testESConcurrentSource_->busyWait((std::string("getImpl ") + iKey.name().value()).c_str());
0102
0103 edm::ValidityInterval iov = iRecord.validityInterval();
0104 edm::LogAbsolute("TestESConcurrentSourceTestResolver")
0105 << "TestESConcurrentSourceTestResolver::getImpl '" << iKey.name().value()
0106 << "' startIOV = " << iov.first().luminosityBlockNumber() << " endIOV = " << iov.last().luminosityBlockNumber()
0107 << " IOV index = " << iRecord.iovIndex() << " cache identifier = " << iRecord.cacheIdentifier();
0108
0109 iovTestInfo_.iovStartLumi_ = iov.first().luminosityBlockNumber();
0110 iovTestInfo_.iovEndLumi_ = iov.last().luminosityBlockNumber();
0111 iovTestInfo_.iovIndex_ = iRecord.iovIndex();
0112 iovTestInfo_.cacheIdentifier_ = iRecord.cacheIdentifier();
0113
0114 --testESConcurrentSource_->count_;
0115 }
0116
0117 void const* TestESConcurrentSourceTestResolver::getAfterPrefetchImpl() const { return &iovTestInfo_; }
0118
0119 void TestESConcurrentSourceTestResolver::initializeForNewIOV() {
0120 edm::LogAbsolute("TestESConcurrentSourceTestResolver::initializeForNewIOV")
0121 << "TestESConcurrentSourceTestResolver::initializeForNewIOV";
0122 ++testESConcurrentSource_->count_initializeForNewIOV_;
0123 }
0124
0125 TestESConcurrentSource::TestESConcurrentSource(edm::ParameterSet const& pset)
0126 : count_(0),
0127 maxCount_(0),
0128 count_setIntervalFor_(0),
0129 count_initializeForNewIOV_(0),
0130 iterations_(pset.getParameter<unsigned int>("iterations")),
0131 pi_(std::acos(-1)),
0132 expectedNumberOfConcurrentIOVs_(pset.getParameter<unsigned int>("expectedNumberOfConcurrentIOVs")),
0133 checkIOVInitialization_(pset.getParameter<bool>("checkIOVInitialization")) {
0134 std::vector<unsigned int> temp(pset.getParameter<std::vector<unsigned int>>("firstValidLumis"));
0135 for (auto val : temp) {
0136 setOfIOV_.insert(edm::IOVSyncValue(edm::EventID(1, val, 0)));
0137 }
0138
0139 findingRecord<ESTestRecordI>();
0140 usingRecord<ESTestRecordI>();
0141 }
0142
0143 TestESConcurrentSource::~TestESConcurrentSource() {
0144 edm::LogAbsolute("TestESConcurrentSource") << "max concurrency seen " << maxCount_.load();
0145 }
0146
0147 void TestESConcurrentSource::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0148 edm::ParameterSetDescription desc;
0149 std::vector<unsigned int> emptyVector;
0150 desc.add<unsigned int>("iterations", 10 * 1000 * 1000);
0151 desc.add<bool>("checkIOVInitialization", false);
0152 desc.add<unsigned int>("expectedNumberOfConcurrentIOVs", 0);
0153 desc.add<std::vector<unsigned int>>("firstValidLumis", emptyVector);
0154 descriptions.addDefault(desc);
0155 }
0156
0157 void TestESConcurrentSource::setIntervalFor(EventSetupRecordKey const&,
0158 edm::IOVSyncValue const& syncValue,
0159 edm::ValidityInterval& iov) {
0160 if (checkIOVInitialization_) {
0161
0162
0163
0164 if (count_setIntervalFor_ > 0 && count_initializeForNewIOV_ != 2 * (count_setIntervalFor_ - 1)) {
0165 throw cms::Exception("TestFailure") << "TestESConcurrentSource::setIntervalFor,"
0166 << " unexpected number of IOV initializations";
0167 }
0168 }
0169 incrementCount();
0170 ++count_setIntervalFor_;
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
0185 --count_;
0186 return;
0187 }
0188
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> TestESConcurrentSource::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 producesInfo.emplace_back(ESTestRecordI::keyForClass(),
0207 edm::eventsetup::DataKey(edm::eventsetup::DataKey::makeTypeTag<IOVTestInfo>(), "other"),
0208 1);
0209 return producesInfo;
0210 }
0211
0212 edm::eventsetup::ESProductResolverProvider::KeyedResolversVector TestESConcurrentSource::registerResolvers(
0213 EventSetupRecordKey const&, unsigned int iovIndex) {
0214 if (expectedNumberOfConcurrentIOVs_ != 0 && nConcurrentIOVs_ != expectedNumberOfConcurrentIOVs_) {
0215 throw cms::Exception("TestFailure") << "TestESConcurrentSource::registerResolvers,"
0216 << " unexpected number of concurrent IOVs";
0217 }
0218 KeyedResolversVector keyedResolversVector;
0219
0220 {
0221 edm::eventsetup::DataKey dataKey(edm::eventsetup::DataKey::makeTypeTag<IOVTestInfo>(),
0222 edm::eventsetup::IdTags(""));
0223 keyedResolversVector.emplace_back(dataKey, std::make_shared<TestESConcurrentSourceTestResolver>(this));
0224 }
0225 {
0226 edm::eventsetup::DataKey dataKey(edm::eventsetup::DataKey::makeTypeTag<IOVTestInfo>(),
0227 edm::eventsetup::IdTags("other"));
0228 keyedResolversVector.emplace_back(dataKey, std::make_shared<TestESConcurrentSourceTestResolver>(this));
0229 }
0230
0231 return keyedResolversVector;
0232 }
0233
0234 void TestESConcurrentSource::initConcurrentIOVs(EventSetupRecordKey const& key, unsigned int nConcurrentIOVs) {
0235 edm::LogAbsolute("TestESConcurrentSource::initConcurrentIOVs")
0236 << "Start TestESConcurrentSource::initConcurrentIOVs " << nConcurrentIOVs << " " << key.name();
0237 if (EventSetupRecordKey::makeKey<ESTestRecordI>() != key) {
0238 throw cms::Exception("TestFailure") << "TestESConcurrentSource::initConcurrentIOVs,"
0239 << " unexpected EventSetupRecordKey";
0240 }
0241 if (expectedNumberOfConcurrentIOVs_ != 0 && nConcurrentIOVs != expectedNumberOfConcurrentIOVs_) {
0242 throw cms::Exception("TestFailure") << "TestESConcurrentSource::initConcurrentIOVs,"
0243 << " unexpected number of concurrent IOVs";
0244 }
0245 nConcurrentIOVs_ = nConcurrentIOVs;
0246 }
0247
0248 void TestESConcurrentSource::busyWait(char const* msg) const {
0249 edm::LogAbsolute("TestESConcurrentSource::busyWait") << "Start TestESConcurrentSource::busyWait " << msg;
0250 double sum = 0.;
0251 const double stepSize = pi_ / iterations_;
0252 for (unsigned int i = 0; i < iterations_; ++i) {
0253 sum += stepSize * cos(i * stepSize);
0254 }
0255 edm::LogAbsolute("TestESConcurrentSource::busyWait")
0256 << "Stop TestESConcurrentSource::busyWait " << msg << " " << sum;
0257 }
0258 }
0259 using namespace edmtest;
0260 DEFINE_FWK_EVENTSETUP_SOURCE(TestESConcurrentSource);