Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-09-16 00:05:37

0001 // -*- C++ -*-
0002 //
0003 // Package:     Framework
0004 // Class  :     EventSetupsController
0005 //
0006 // Implementation:
0007 //     [Notes on implementation]
0008 //
0009 // Original Author:  Chris Jones, W. David Dagenhart
0010 //         Created:  Wed Jan 12 14:30:44 CST 2011
0011 //
0012 
0013 #include "FWCore/Framework/interface/EventSetupsController.h"
0014 
0015 #include "FWCore/Concurrency/interface/WaitingTaskHolder.h"
0016 #include "FWCore/Concurrency/interface/WaitingTaskList.h"
0017 #include "FWCore/Concurrency/interface/FinalWaitingTask.h"
0018 #include "FWCore/Framework/interface/DataKey.h"
0019 #include "FWCore/Framework/interface/DataProxy.h"
0020 #include "FWCore/Framework/src/EventSetupProviderMaker.h"
0021 #include "FWCore/Framework/interface/EventSetupProvider.h"
0022 #include "FWCore/Framework/interface/EventSetupRecordKey.h"
0023 #include "FWCore/Framework/interface/ParameterSetIDHolder.h"
0024 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0025 #include "FWCore/Utilities/interface/EDMException.h"
0026 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0027 
0028 #include <algorithm>
0029 #include <iostream>
0030 #include <set>
0031 
0032 namespace edm {
0033   namespace eventsetup {
0034 
0035     EventSetupsController::EventSetupsController() {}
0036     EventSetupsController::EventSetupsController(ModuleTypeResolverBase const* resolver) : typeResolver_(resolver) {}
0037 
0038     void EventSetupsController::endIOVsAsync(edm::WaitingTaskHolder iEndTask) {
0039       for (auto& eventSetupRecordIOVQueue : eventSetupRecordIOVQueues_) {
0040         eventSetupRecordIOVQueue->endIOVAsync(iEndTask);
0041       }
0042     }
0043 
0044     std::shared_ptr<EventSetupProvider> EventSetupsController::makeProvider(ParameterSet& iPSet,
0045                                                                             ActivityRegistry* activityRegistry,
0046                                                                             ParameterSet const* eventSetupPset,
0047                                                                             unsigned int maxConcurrentIOVs,
0048                                                                             bool dumpOptions) {
0049       // Makes an EventSetupProvider
0050       // Also parses the prefer information from ParameterSets and puts
0051       // it in a map that is stored in the EventSetupProvider
0052       std::shared_ptr<EventSetupProvider> returnValue(
0053           makeEventSetupProvider(iPSet, providers_.size(), activityRegistry));
0054 
0055       // Construct the ESProducers and ESSources
0056       // shared_ptrs to them are temporarily stored in this
0057       // EventSetupsController and in the EventSetupProvider
0058       fillEventSetupProvider(typeResolver_, *this, *returnValue, iPSet);
0059 
0060       numberOfConcurrentIOVs_.readConfigurationParameters(eventSetupPset, maxConcurrentIOVs, dumpOptions);
0061 
0062       providers_.push_back(returnValue);
0063       return returnValue;
0064     }
0065 
0066     void EventSetupsController::finishConfiguration() {
0067       if (mustFinishConfiguration_) {
0068         for (auto& eventSetupProvider : providers_) {
0069           numberOfConcurrentIOVs_.fillRecordsNotAllowingConcurrentIOVs(*eventSetupProvider);
0070         }
0071 
0072         for (auto& eventSetupProvider : providers_) {
0073           eventSetupProvider->finishConfiguration(numberOfConcurrentIOVs_, hasNonconcurrentFinder_);
0074         }
0075 
0076         // When the ESSources and ESProducers were constructed a first pass was
0077         // done which attempts to get component sharing between SubProcesses
0078         // correct, but in this pass only the configuration of the components
0079         // being shared are compared. This is not good enough for ESProducers.
0080         // In the following function, all the other components that contribute
0081         // to the same record and also the records that record depends on are
0082         // also checked. The component sharing is appropriately fixed as necessary.
0083         checkESProducerSharing();
0084         clearComponents();
0085 
0086         initializeEventSetupRecordIOVQueues();
0087         numberOfConcurrentIOVs_.clear();
0088         mustFinishConfiguration_ = false;
0089       }
0090     }
0091 
0092     void EventSetupsController::eventSetupForInstanceAsync(
0093         IOVSyncValue const& syncValue,
0094         WaitingTaskHolder const& taskToStartAfterIOVInit,
0095         WaitingTaskList& endIOVWaitingTasks,
0096         std::vector<std::shared_ptr<const EventSetupImpl>>& eventSetupImpls) {
0097       finishConfiguration();
0098 
0099       bool newEventSetupImpl = false;
0100       eventSetupImpls.clear();
0101       eventSetupImpls.reserve(providers_.size());
0102 
0103       // Note that unless there are one or more SubProcesses providers_ will only
0104       // contain one element.
0105 
0106       for (auto& eventSetupProvider : providers_) {
0107         eventSetupProvider->setAllValidityIntervals(syncValue);
0108       }
0109 
0110       for (auto& eventSetupRecordIOVQueue : eventSetupRecordIOVQueues_) {
0111         // For a particular record, if the top level process or any SubProcess requires
0112         // starting a new IOV, then we must start a new IOV for all of them. And we
0113         // need to know whether this is needed at this point in time. This is
0114         // recorded in the EventSetupRecordProviders.
0115         eventSetupRecordIOVQueue->setNewIntervalForAnySubProcess();
0116       }
0117 
0118       for (auto& eventSetupProvider : providers_) {
0119         // Decides whether we can reuse the existing EventSetupImpl and if we can
0120         // returns it. If a new one is needed it will create it, although the pointers
0121         // to the EventSetupRecordImpl's will not be set yet in the returned EventSetupImpl
0122         // object.
0123         eventSetupImpls.push_back(eventSetupProvider->eventSetupForInstance(syncValue, newEventSetupImpl));
0124       }
0125 
0126       for (auto& eventSetupRecordIOVQueue : eventSetupRecordIOVQueues_) {
0127         eventSetupRecordIOVQueue->checkForNewIOVs(taskToStartAfterIOVInit, endIOVWaitingTasks, newEventSetupImpl);
0128       }
0129     }
0130 
0131     bool EventSetupsController::doWeNeedToWaitForIOVsToFinish(IOVSyncValue const& syncValue) const {
0132       if (hasNonconcurrentFinder()) {
0133         for (auto& eventSetupProvider : providers_) {
0134           if (eventSetupProvider->doWeNeedToWaitForIOVsToFinish(syncValue)) {
0135             return true;
0136           }
0137         }
0138       }
0139       return false;
0140     }
0141 
0142     void EventSetupsController::forceCacheClear() {
0143       for (auto& eventSetupProvider : providers_) {
0144         eventSetupProvider->forceCacheClear();
0145       }
0146     }
0147 
0148     std::shared_ptr<DataProxyProvider> EventSetupsController::getESProducerAndRegisterProcess(
0149         ParameterSet const& pset, unsigned subProcessIndex) {
0150       // Try to find a DataProxyProvider with a matching ParameterSet
0151       auto elements = esproducers_.equal_range(pset.id());
0152       for (auto it = elements.first; it != elements.second; ++it) {
0153         // Untracked parameters must also match, do complete comparison if IDs match
0154         if (isTransientEqual(pset, *it->second.pset())) {
0155           // Register processes with an exact match
0156           it->second.subProcessIndexes().push_back(subProcessIndex);
0157           // Return the DataProxyProvider
0158           return it->second.provider();
0159         }
0160       }
0161       // Could not find it
0162       return std::shared_ptr<DataProxyProvider>();
0163     }
0164 
0165     void EventSetupsController::putESProducer(ParameterSet const& pset,
0166                                               std::shared_ptr<DataProxyProvider> const& component,
0167                                               unsigned subProcessIndex) {
0168       auto newElement =
0169           esproducers_.insert(std::pair<ParameterSetID, ESProducerInfo>(pset.id(), ESProducerInfo(&pset, component)));
0170       // Register processes with an exact match
0171       newElement->second.subProcessIndexes().push_back(subProcessIndex);
0172     }
0173 
0174     std::shared_ptr<EventSetupRecordIntervalFinder> EventSetupsController::getESSourceAndRegisterProcess(
0175         ParameterSet const& pset, unsigned subProcessIndex) {
0176       // Try to find a EventSetupRecordIntervalFinder with a matching ParameterSet
0177       auto elements = essources_.equal_range(pset.id());
0178       for (auto it = elements.first; it != elements.second; ++it) {
0179         // Untracked parameters must also match, do complete comparison if IDs match
0180         if (isTransientEqual(pset, *it->second.pset())) {
0181           // Register processes with an exact match
0182           it->second.subProcessIndexes().push_back(subProcessIndex);
0183           // Return the EventSetupRecordIntervalFinder
0184           return it->second.finder();
0185         }
0186       }
0187       // Could not find it
0188       return std::shared_ptr<EventSetupRecordIntervalFinder>();
0189     }
0190 
0191     void EventSetupsController::putESSource(ParameterSet const& pset,
0192                                             std::shared_ptr<EventSetupRecordIntervalFinder> const& component,
0193                                             unsigned subProcessIndex) {
0194       auto newElement =
0195           essources_.insert(std::pair<ParameterSetID, ESSourceInfo>(pset.id(), ESSourceInfo(&pset, component)));
0196       // Register processes with an exact match
0197       newElement->second.subProcessIndexes().push_back(subProcessIndex);
0198     }
0199 
0200     void EventSetupsController::clearComponents() {
0201       esproducers_.clear();
0202       essources_.clear();
0203     }
0204 
0205     void EventSetupsController::lookForMatches(ParameterSetID const& psetID,
0206                                                unsigned subProcessIndex,
0207                                                unsigned precedingProcessIndex,
0208                                                bool& firstProcessWithThisPSet,
0209                                                bool& precedingHasMatchingPSet) const {
0210       auto elements = esproducers_.equal_range(psetID);
0211       for (auto it = elements.first; it != elements.second; ++it) {
0212         std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
0213 
0214         auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
0215         if (iFound == subProcessIndexes.end()) {
0216           continue;
0217         }
0218 
0219         if (iFound == subProcessIndexes.begin()) {
0220           firstProcessWithThisPSet = true;
0221           precedingHasMatchingPSet = false;
0222         } else {
0223           auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
0224           if (iFoundPreceding == iFound) {
0225             firstProcessWithThisPSet = false;
0226             precedingHasMatchingPSet = false;
0227           } else {
0228             firstProcessWithThisPSet = false;
0229             precedingHasMatchingPSet = true;
0230           }
0231         }
0232         return;
0233       }
0234       throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::lookForMatches\n"
0235                                                     << "Subprocess index not found. This should never happen\n"
0236                                                     << "Please report this to a Framework Developer\n";
0237     }
0238 
0239     bool EventSetupsController::isFirstMatch(ParameterSetID const& psetID,
0240                                              unsigned subProcessIndex,
0241                                              unsigned precedingProcessIndex) const {
0242       auto elements = esproducers_.equal_range(psetID);
0243       for (auto it = elements.first; it != elements.second; ++it) {
0244         std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
0245 
0246         auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
0247         if (iFound == subProcessIndexes.end()) {
0248           continue;
0249         }
0250 
0251         auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
0252         if (iFoundPreceding == iFound) {
0253           break;
0254         } else {
0255           return iFoundPreceding == subProcessIndexes.begin();
0256         }
0257       }
0258       throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::isFirstMatch\n"
0259                                                     << "Subprocess index not found. This should never happen\n"
0260                                                     << "Please report this to a Framework Developer\n";
0261       return false;
0262     }
0263 
0264     bool EventSetupsController::isLastMatch(ParameterSetID const& psetID,
0265                                             unsigned subProcessIndex,
0266                                             unsigned precedingProcessIndex) const {
0267       auto elements = esproducers_.equal_range(psetID);
0268       for (auto it = elements.first; it != elements.second; ++it) {
0269         std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
0270 
0271         auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
0272         if (iFound == subProcessIndexes.end()) {
0273           continue;
0274         }
0275 
0276         auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
0277         if (iFoundPreceding == iFound) {
0278           break;
0279         } else {
0280           return (++iFoundPreceding) == iFound;
0281         }
0282       }
0283       throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::isLastMatch\n"
0284                                                     << "Subprocess index not found. This should never happen\n"
0285                                                     << "Please report this to a Framework Developer\n";
0286       return false;
0287     }
0288 
0289     bool EventSetupsController::isMatchingESSource(ParameterSetID const& psetID,
0290                                                    unsigned subProcessIndex,
0291                                                    unsigned precedingProcessIndex) const {
0292       auto elements = essources_.equal_range(psetID);
0293       for (auto it = elements.first; it != elements.second; ++it) {
0294         std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
0295 
0296         auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
0297         if (iFound == subProcessIndexes.end()) {
0298           continue;
0299         }
0300 
0301         auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
0302         if (iFoundPreceding == iFound) {
0303           return false;
0304         } else {
0305           return true;
0306         }
0307       }
0308       throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::lookForMatchingESSource\n"
0309                                                     << "Subprocess index not found. This should never happen\n"
0310                                                     << "Please report this to a Framework Developer\n";
0311       return false;
0312     }
0313 
0314     bool EventSetupsController::isMatchingESProducer(ParameterSetID const& psetID,
0315                                                      unsigned subProcessIndex,
0316                                                      unsigned precedingProcessIndex) const {
0317       auto elements = esproducers_.equal_range(psetID);
0318       for (auto it = elements.first; it != elements.second; ++it) {
0319         std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
0320 
0321         auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
0322         if (iFound == subProcessIndexes.end()) {
0323           continue;
0324         }
0325 
0326         auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
0327         if (iFoundPreceding == iFound) {
0328           return false;
0329         } else {
0330           return true;
0331         }
0332       }
0333       throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::lookForMatchingESSource\n"
0334                                                     << "Subprocess index not found. This should never happen\n"
0335                                                     << "Please report this to a Framework Developer\n";
0336       return false;
0337     }
0338 
0339     ParameterSet const* EventSetupsController::getESProducerPSet(ParameterSetID const& psetID,
0340                                                                  unsigned subProcessIndex) const {
0341       auto elements = esproducers_.equal_range(psetID);
0342       for (auto it = elements.first; it != elements.second; ++it) {
0343         std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
0344 
0345         auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
0346         if (iFound == subProcessIndexes.end()) {
0347           continue;
0348         }
0349         return it->second.pset();
0350       }
0351       throw edm::Exception(edm::errors::LogicError) << "EventSetupsController::getESProducerPSet\n"
0352                                                     << "Subprocess index not found. This should never happen\n"
0353                                                     << "Please report this to a Framework Developer\n";
0354       return nullptr;
0355     }
0356 
0357     void EventSetupsController::checkESProducerSharing() {
0358       // Loop over SubProcesses, skip the top level process.
0359       auto esProvider = providers_.begin();
0360       auto const esProviderEnd = providers_.end();
0361       if (esProvider != esProviderEnd)
0362         ++esProvider;
0363       for (; esProvider != esProviderEnd; ++esProvider) {
0364         // An element is added to this set for each ESProducer
0365         // when we have determined which preceding process
0366         // this process can share that ESProducer with or
0367         // we have determined that it cannot be shared with
0368         // any preceding process.
0369         // Note the earliest possible preceding process
0370         // will be the one selected if there is more than one.
0371         std::set<ParameterSetIDHolder> sharingCheckDone;
0372 
0373         // This will hold an entry for DataProxy's that are
0374         // referenced by an EventSetupRecord in this SubProcess.
0375         // But only for DataProxy's that are associated with
0376         // an ESProducer (not the ones associated with ESSource's
0377         // or EDLooper's)
0378         std::map<EventSetupRecordKey, std::vector<ComponentDescription const*>> referencedESProducers;
0379 
0380         // For each EventSetupProvider from a SubProcess, loop over the
0381         // EventSetupProviders from the preceding processes (the first
0382         // preceding process will be the top level process and the others
0383         // SubProcess's)
0384         for (auto precedingESProvider = providers_.begin(); precedingESProvider != esProvider; ++precedingESProvider) {
0385           (*esProvider)
0386               ->checkESProducerSharing(
0387                   typeResolver_, **precedingESProvider, sharingCheckDone, referencedESProducers, *this);
0388         }
0389 
0390         (*esProvider)->resetRecordToProxyPointers();
0391       }
0392       for (auto& eventSetupProvider : providers_) {
0393         eventSetupProvider->clearInitializationData();
0394       }
0395     }
0396 
0397     void EventSetupsController::initializeEventSetupRecordIOVQueues() {
0398       std::set<EventSetupRecordKey> keys;
0399       for (auto const& provider : providers_) {
0400         provider->fillKeys(keys);
0401       }
0402 
0403       for (auto const& key : keys) {
0404         eventSetupRecordIOVQueues_.push_back(
0405             std::make_unique<EventSetupRecordIOVQueue>(numberOfConcurrentIOVs_.numberOfConcurrentIOVs(key)));
0406         EventSetupRecordIOVQueue& iovQueue = *eventSetupRecordIOVQueues_.back();
0407         for (auto& provider : providers_) {
0408           EventSetupRecordProvider* recProvider = provider->tryToGetRecordProvider(key);
0409           if (recProvider) {
0410             iovQueue.addRecProvider(recProvider);
0411           }
0412         }
0413       }
0414     }
0415 
0416     void synchronousEventSetupForInstance(IOVSyncValue const& syncValue,
0417                                           oneapi::tbb::task_group& iGroup,
0418                                           eventsetup::EventSetupsController& espController) {
0419       FinalWaitingTask waitUntilIOVInitializationCompletes{iGroup};
0420 
0421       // These do nothing ...
0422       WaitingTaskList dummyWaitingTaskList;
0423       std::vector<std::shared_ptr<const EventSetupImpl>> dummyEventSetupImpls;
0424 
0425       {
0426         WaitingTaskHolder waitingTaskHolder(iGroup, &waitUntilIOVInitializationCompletes);
0427         // Caught exception is propagated via WaitingTaskHolder
0428         CMS_SA_ALLOW try {
0429           // All the real work is done here.
0430           espController.eventSetupForInstanceAsync(
0431               syncValue, waitingTaskHolder, dummyWaitingTaskList, dummyEventSetupImpls);
0432           dummyWaitingTaskList.doneWaiting(std::exception_ptr{});
0433         } catch (...) {
0434           dummyWaitingTaskList.doneWaiting(std::exception_ptr{});
0435           waitingTaskHolder.doneWaiting(std::current_exception());
0436         }
0437       }
0438       waitUntilIOVInitializationCompletes.wait();
0439     }
0440   }  // namespace eventsetup
0441 }  // namespace edm