Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 // -*- C++ -*-
0002 //
0003 // Package:     FWCore/Integration
0004 // Class  :     ConcurrentIOVESSource
0005 //
0006 // Implementation:
0007 //     ESSource used for tests of Framework support for
0008 //     concurrent IOVs in the EventSetup system
0009 //
0010 // Original Author:  W. David Dagenhart
0011 //         Created:  21 March 2019
0012 
0013 #include "DataFormats/Provenance/interface/EventID.h"
0014 #include "DataFormats/Provenance/interface/Timestamp.h"
0015 #include "FWCore/Framework/interface/EventSetupRecordIntervalFinder.h"
0016 #include "FWCore/Framework/interface/ESProducer.h"
0017 #include "FWCore/Framework/interface/IOVSyncValue.h"
0018 #include "FWCore/Framework/interface/SourceFactory.h"
0019 #include "FWCore/Framework/interface/ValidityInterval.h"
0020 #include "FWCore/Integration/interface/ESTestData.h"
0021 #include "FWCore/Integration/interface/ESTestRecords.h"
0022 #include "FWCore/Integration/interface/IOVTestInfo.h"
0023 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0024 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0025 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0026 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0027 #include "FWCore/Utilities/interface/Exception.h"
0028 #include "FWCore/Utilities/interface/WallclockTimer.h"
0029 
0030 #include <memory>
0031 #include <vector>
0032 
0033 namespace edmtest {
0034 
0035   class ConcurrentIOVESSource : public edm::EventSetupRecordIntervalFinder, public edm::ESProducer {
0036   public:
0037     ConcurrentIOVESSource(edm::ParameterSet const&);
0038 
0039     std::unique_ptr<IOVTestInfo> produce(ESTestRecordI const&);
0040     std::unique_ptr<ESTestDataA> produceA(ESTestRecordA const&);
0041 
0042     static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0043 
0044   private:
0045     void setIntervalFor(edm::eventsetup::EventSetupRecordKey const&,
0046                         edm::IOVSyncValue const&,
0047                         edm::ValidityInterval&) override;
0048 
0049     bool isConcurrentFinder() const override { return concurrentFinder_; }
0050 
0051     // These are thread safe because after the constructor we do not
0052     // modify their state.
0053     const bool iovIsTime_;
0054     std::set<edm::IOVSyncValue> setOfIOV_;
0055     std::set<edm::IOVSyncValue> setOfInvalidIOV_;
0056     const bool concurrentFinder_;
0057     const bool testForceESSourceMode_;
0058     const bool findForRecordA_;
0059     edm::WallclockTimer wallclockTimer_;
0060 
0061     // Be careful with this. It is modified in setIntervalFor
0062     // and the setIntervalFor function is called serially (nonconcurrent
0063     // with itself). But it is not thread safe to use this data member
0064     // in the produce methods unless concurrentFinder_ is false.
0065     edm::ValidityInterval validityInterval_;
0066   };
0067 
0068   ConcurrentIOVESSource::ConcurrentIOVESSource(edm::ParameterSet const& pset)
0069       : iovIsTime_(!pset.getParameter<bool>("iovIsRunNotTime")),
0070         concurrentFinder_(pset.getParameter<bool>("concurrentFinder")),
0071         testForceESSourceMode_(pset.getParameter<bool>("testForceESSourceMode")),
0072         findForRecordA_(pset.getParameter<bool>("findForRecordA")) {
0073     wallclockTimer_.start();
0074 
0075     std::vector<unsigned int> temp(pset.getParameter<std::vector<unsigned int>>("firstValidLumis"));
0076     for (auto val : temp) {
0077       if (iovIsTime_) {
0078         setOfIOV_.insert(edm::IOVSyncValue(edm::Timestamp(val)));
0079       } else {
0080         setOfIOV_.insert(edm::IOVSyncValue(edm::EventID(1, val, 0)));
0081       }
0082     }
0083 
0084     std::vector<unsigned int> tempInvalid(pset.getParameter<std::vector<unsigned int>>("invalidLumis"));
0085     for (auto val : tempInvalid) {
0086       if (iovIsTime_) {
0087         setOfInvalidIOV_.insert(edm::IOVSyncValue(edm::Timestamp(val)));
0088       } else {
0089         setOfInvalidIOV_.insert(edm::IOVSyncValue(edm::EventID(1, val, 0)));
0090       }
0091     }
0092     this->findingRecord<ESTestRecordI>();
0093     setWhatProduced(this);
0094     if (findForRecordA_) {
0095       this->findingRecord<ESTestRecordA>();
0096       setWhatProduced(this, &ConcurrentIOVESSource::produceA);
0097     }
0098   }
0099 
0100   std::unique_ptr<IOVTestInfo> ConcurrentIOVESSource::produce(ESTestRecordI const& record) {
0101     auto data = std::make_unique<IOVTestInfo>();
0102 
0103     edm::ValidityInterval iov = record.validityInterval();
0104     edm::LogAbsolute("ConcurrentIOVESSource")
0105         << "ConcurrentIOVESSource::produce startIOV = " << iov.first().luminosityBlockNumber()
0106         << " endIOV = " << iov.last().luminosityBlockNumber() << " IOV index = " << record.iovIndex()
0107         << " cache identifier = " << record.cacheIdentifier() << " time = " << wallclockTimer_.realTime();
0108 
0109     if (!concurrentFinder_) {
0110       if (validityInterval_ != iov) {
0111         throw cms::Exception("TestError")
0112             << "ConcurrentIOVESSource::produce, testing as nonconcurrent finder and IOV changed!";
0113       }
0114     }
0115 
0116     data->iovStartRun_ = iov.first().eventID().run();
0117     data->iovEndRun_ = iov.last().eventID().run();
0118     data->iovStartLumi_ = iov.first().luminosityBlockNumber();
0119     data->iovEndLumi_ = iov.last().luminosityBlockNumber();
0120     data->iovIndex_ = record.iovIndex();
0121     data->cacheIdentifier_ = record.cacheIdentifier();
0122     return data;
0123   }
0124 
0125   std::unique_ptr<ESTestDataA> ConcurrentIOVESSource::produceA(ESTestRecordA const& record) {
0126     edm::ValidityInterval iov = record.validityInterval();
0127     if (!testForceESSourceMode_ && record.iovIndex() != 0) {
0128       // This criteria should never fail because the EventSetupRecord class
0129       // is hard coded to allow only one IOV at a time.
0130       throw cms::Exception("TestError")
0131           << "ConcurrentIOVESSource::produce, more than one concurrent IOV for type ESTestRecordA!";
0132     }
0133     edm::LogAbsolute("ConcurrentIOVESSource")
0134         << "ConcurrentIOVESSource::produceA startIOV = " << iov.first().luminosityBlockNumber()
0135         << " endIOV = " << iov.last().luminosityBlockNumber() << " IOV index = " << record.iovIndex()
0136         << " cache identifier = " << record.cacheIdentifier() << " time = " << wallclockTimer_.realTime();
0137     return std::make_unique<ESTestDataA>(0);
0138   }
0139 
0140   void ConcurrentIOVESSource::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0141     edm::ParameterSetDescription desc;
0142     std::vector<unsigned int> emptyVector;
0143     desc.add<bool>("iovIsRunNotTime", true);
0144     desc.add<bool>("concurrentFinder", true);
0145     desc.add<bool>("testForceESSourceMode", false);
0146     desc.add<bool>("findForRecordA", false);
0147     desc.add<std::vector<unsigned int>>("firstValidLumis", emptyVector);
0148     desc.add<std::vector<unsigned int>>("invalidLumis", emptyVector);
0149     descriptions.addDefault(desc);
0150   }
0151 
0152   void ConcurrentIOVESSource::setIntervalFor(edm::eventsetup::EventSetupRecordKey const& key,
0153                                              edm::IOVSyncValue const& syncValue,
0154                                              edm::ValidityInterval& interval) {
0155     interval = edm::ValidityInterval::invalidInterval();
0156     validityInterval_ = interval;
0157 
0158     for (auto const& invalidSyncValue : setOfInvalidIOV_) {
0159       if (syncValue == invalidSyncValue) {
0160         return;
0161       }
0162     }
0163 
0164     //if no intervals given, fail immediately
0165     if (setOfIOV_.empty()) {
0166       return;
0167     }
0168 
0169     std::pair<std::set<edm::IOVSyncValue>::iterator, std::set<edm::IOVSyncValue>::iterator> itFound =
0170         setOfIOV_.equal_range(syncValue);
0171 
0172     if (itFound.first == itFound.second) {
0173       if (itFound.first == setOfIOV_.begin()) {
0174         //request is before first valid interval, so fail
0175         return;
0176       }
0177       //go back one step
0178       --itFound.first;
0179     }
0180     edm::IOVSyncValue endOfInterval = edm::IOVSyncValue::endOfTime();
0181 
0182     if (itFound.second != setOfIOV_.end()) {
0183       if (iovIsTime_) {
0184         endOfInterval = edm::IOVSyncValue(edm::Timestamp(itFound.second->time().value() - 1));
0185       } else {
0186         endOfInterval = edm::IOVSyncValue(
0187             edm::EventID(1, itFound.second->eventID().luminosityBlock() - 1, edm::EventID::maxEventNumber()));
0188       }
0189     }
0190     interval = edm::ValidityInterval(*(itFound.first), endOfInterval);
0191     validityInterval_ = interval;
0192   }
0193 }  // namespace edmtest
0194 using namespace edmtest;
0195 DEFINE_FWK_EVENTSETUP_SOURCE(ConcurrentIOVESSource);