Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-01-27 00:42:04

0001 // -*- C++ -*-
0002 //
0003 // Package:     Framework
0004 // Module:      EventSetupProvider
0005 //
0006 // Description: <one line class summary>
0007 //
0008 // Implementation:
0009 //     <Notes on implementation>
0010 //
0011 // Author:      Chris Jones
0012 // Created:     Thu Mar 24 16:27:14 EST 2005
0013 //
0014 
0015 // system include files
0016 #include <algorithm>
0017 #include <cassert>
0018 
0019 // user include files
0020 #include "FWCore/Framework/interface/EventSetupProvider.h"
0021 #include "FWCore/Concurrency/interface/WaitingTaskList.h"
0022 #include "FWCore/Framework/interface/EventSetupImpl.h"
0023 #include "FWCore/Framework/interface/EventSetupRecordProvider.h"
0024 #include "FWCore/Framework/interface/EventSetupRecord.h"
0025 #include "FWCore/Framework/interface/DataProxyProvider.h"
0026 #include "FWCore/Framework/interface/EventSetupRecordIntervalFinder.h"
0027 #include "FWCore/Framework/interface/ModuleFactory.h"
0028 #include "FWCore/Framework/interface/ParameterSetIDHolder.h"
0029 #include "FWCore/Framework/interface/ESRecordsToProxyIndices.h"
0030 #include "FWCore/Framework/interface/EventSetupsController.h"
0031 #include "FWCore/Framework/interface/NumberOfConcurrentIOVs.h"
0032 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0033 #include "FWCore/ServiceRegistry/interface/ActivityRegistry.h"
0034 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0035 #include "FWCore/Utilities/interface/Algorithms.h"
0036 #include "FWCore/Utilities/interface/Exception.h"
0037 
0038 namespace edm {
0039   namespace eventsetup {
0040 
0041     EventSetupProvider::EventSetupProvider(ActivityRegistry const* activityRegistry,
0042                                            unsigned subProcessIndex,
0043                                            const PreferredProviderInfo* iInfo)
0044         : activityRegistry_(activityRegistry),
0045           mustFinishConfiguration_(true),
0046           subProcessIndex_(subProcessIndex),
0047           preferredProviderInfo_((nullptr != iInfo) ? (new PreferredProviderInfo(*iInfo)) : nullptr),
0048           finders_(new std::vector<std::shared_ptr<EventSetupRecordIntervalFinder>>()),
0049           dataProviders_(new std::vector<std::shared_ptr<DataProxyProvider>>()),
0050           referencedDataKeys_(new std::map<EventSetupRecordKey, std::map<DataKey, ComponentDescription const*>>),
0051           recordToFinders_(
0052               new std::map<EventSetupRecordKey, std::vector<std::shared_ptr<EventSetupRecordIntervalFinder>>>),
0053           psetIDToRecordKey_(new std::map<ParameterSetIDHolder, std::set<EventSetupRecordKey>>),
0054           recordToPreferred_(new std::map<EventSetupRecordKey, std::map<DataKey, ComponentDescription>>),
0055           recordsWithALooperProxy_(new std::set<EventSetupRecordKey>) {}
0056 
0057     EventSetupProvider::~EventSetupProvider() { forceCacheClear(); }
0058 
0059     std::shared_ptr<EventSetupRecordProvider>& EventSetupProvider::recordProvider(const EventSetupRecordKey& iKey) {
0060       auto lb = std::lower_bound(recordKeys_.begin(), recordKeys_.end(), iKey);
0061       if (lb == recordKeys_.end() || iKey != *lb) {
0062         throw cms::Exception("LogicError") << "EventSetupProvider::recordProvider Could not find key\n"
0063                                            << "Should be impossible. Please contact Framework developer.\n";
0064       }
0065       auto index = std::distance(recordKeys_.begin(), lb);
0066       return recordProviders_[index];
0067     }
0068 
0069     EventSetupRecordProvider* EventSetupProvider::tryToGetRecordProvider(const EventSetupRecordKey& iKey) {
0070       auto lb = std::lower_bound(recordKeys_.begin(), recordKeys_.end(), iKey);
0071       if (lb == recordKeys_.end() || iKey != *lb) {
0072         return nullptr;
0073       }
0074       auto index = std::distance(recordKeys_.begin(), lb);
0075       return recordProviders_[index].get();
0076     }
0077 
0078     void EventSetupProvider::insert(const EventSetupRecordKey& iKey,
0079                                     std::unique_ptr<EventSetupRecordProvider> iProvider) {
0080       auto lb = std::lower_bound(recordKeys_.begin(), recordKeys_.end(), iKey);
0081       auto index = std::distance(recordKeys_.begin(), lb);
0082       if (lb == recordKeys_.end() || iKey != *lb) {
0083         recordKeys_.insert(lb, iKey);
0084         recordProviders_.insert(recordProviders_.begin() + index, std::move(iProvider));
0085       } else {
0086         recordProviders_[index] = std::move(iProvider);
0087       }
0088     }
0089 
0090     void EventSetupProvider::add(std::shared_ptr<DataProxyProvider> iProvider) {
0091       assert(iProvider.get() != nullptr);
0092       dataProviders_->push_back(iProvider);
0093       if (activityRegistry_) {
0094         activityRegistry_->postESModuleRegistrationSignal_(iProvider->description());
0095       }
0096     }
0097 
0098     void EventSetupProvider::replaceExisting(std::shared_ptr<DataProxyProvider> dataProxyProvider) {
0099       ParameterSetIDHolder psetID(dataProxyProvider->description().pid_);
0100       std::set<EventSetupRecordKey> const& keysForPSetID = (*psetIDToRecordKey_)[psetID];
0101       for (auto const& key : keysForPSetID) {
0102         recordProvider(key)->resetProxyProvider(psetID, dataProxyProvider);
0103       }
0104     }
0105 
0106     void EventSetupProvider::add(std::shared_ptr<EventSetupRecordIntervalFinder> iFinder) {
0107       assert(iFinder.get() != nullptr);
0108       finders_->push_back(iFinder);
0109     }
0110 
0111     using RecordProviders = std::vector<std::shared_ptr<EventSetupRecordProvider>>;
0112     using RecordToPreferred = std::map<EventSetupRecordKey, EventSetupRecordProvider::DataToPreferredProviderMap>;
0113     ///find everything made by a DataProxyProvider and add it to the 'preferred' list
0114     static void preferEverything(const ComponentDescription& iComponent,
0115                                  const RecordProviders& iRecordProviders,
0116                                  RecordToPreferred& iReturnValue) {
0117       //need to get our hands on the actual DataProxyProvider
0118       bool foundProxyProvider = false;
0119       for (auto const& recordProvider : iRecordProviders) {
0120         std::set<ComponentDescription> components = recordProvider->proxyProviderDescriptions();
0121         if (components.find(iComponent) != components.end()) {
0122           std::shared_ptr<DataProxyProvider> proxyProv = recordProvider->proxyProvider(*(components.find(iComponent)));
0123           assert(proxyProv.get());
0124 
0125           std::set<EventSetupRecordKey> records = proxyProv->usingRecords();
0126           for (auto const& recordKey : records) {
0127             unsigned int iovIndex = 0;  // Doesn't matter which index is picked, at least 1 should always exist
0128             DataProxyProvider::KeyedProxies& keyedProxies = proxyProv->keyedProxies(recordKey, iovIndex);
0129             if (!keyedProxies.unInitialized()) {
0130               //add them to our output
0131               EventSetupRecordProvider::DataToPreferredProviderMap& dataToProviderMap = iReturnValue[recordKey];
0132 
0133               for (auto keyedProxy : keyedProxies) {
0134                 EventSetupRecordProvider::DataToPreferredProviderMap::iterator itFind =
0135                     dataToProviderMap.find(keyedProxy.dataKey_);
0136                 if (itFind != dataToProviderMap.end()) {
0137                   throw cms::Exception("ESPreferConflict")
0138                       << "Two providers have been set to be preferred for\n"
0139                       << keyedProxy.dataKey_.type().name() << " \"" << keyedProxy.dataKey_.name().value() << "\""
0140                       << "\n the providers are "
0141                       << "\n 1) type=" << itFind->second.type_ << " label=\"" << itFind->second.label_ << "\""
0142                       << "\n 2) type=" << iComponent.type_ << " label=\"" << iComponent.label_ << "\""
0143                       << "\nPlease modify configuration so only one is preferred";
0144                 }
0145                 dataToProviderMap.insert(std::make_pair(keyedProxy.dataKey_, iComponent));
0146               }
0147             }
0148           }
0149           foundProxyProvider = true;
0150           break;
0151         }
0152       }
0153       if (!foundProxyProvider) {
0154         throw cms::Exception("ESPreferNoProvider")
0155             << "Could not make type=\"" << iComponent.type_ << "\" label=\"" << iComponent.label_
0156             << "\" a preferred Provider."
0157             << "\n  Please check spelling of name, or that it was loaded into the job.";
0158       }
0159     }
0160 
0161     void EventSetupProvider::determinePreferred() {
0162       using namespace edm::eventsetup;
0163       if (preferredProviderInfo_) {
0164         for (auto const& itInfo : *preferredProviderInfo_) {
0165           if (itInfo.second.empty()) {
0166             //want everything
0167             preferEverything(itInfo.first, recordProviders_, *recordToPreferred_);
0168           } else {
0169             for (auto const& itRecData : itInfo.second) {
0170               std::string recordName = itRecData.first;
0171               EventSetupRecordKey recordKey(eventsetup::EventSetupRecordKey::TypeTag::findType(recordName));
0172               if (recordKey.type() == eventsetup::EventSetupRecordKey::TypeTag()) {
0173                 throw cms::Exception("ESPreferUnknownRecord")
0174                     << "Unknown record \"" << recordName
0175                     << "\" used in es_prefer statement for type=" << itInfo.first.type_ << " label=\""
0176                     << itInfo.first.label_ << "\"\n Please check spelling.";
0177                 //record not found
0178               }
0179               //See if the ProxyProvider provides something for this Record
0180               EventSetupRecordProvider& recordProviderForKey = *recordProvider(recordKey);
0181 
0182               std::set<ComponentDescription> components = recordProviderForKey.proxyProviderDescriptions();
0183               std::set<ComponentDescription>::iterator itProxyProv = components.find(itInfo.first);
0184               if (itProxyProv == components.end()) {
0185                 throw cms::Exception("ESPreferWrongRecord")
0186                     << "The type=" << itInfo.first.type_ << " label=\"" << itInfo.first.label_
0187                     << "\" does not provide data for the Record " << recordName;
0188               }
0189               //Does it data type exist?
0190               eventsetup::TypeTag datumType = eventsetup::TypeTag::findType(itRecData.second.first);
0191               if (datumType == eventsetup::TypeTag()) {
0192                 //not found
0193                 throw cms::Exception("ESPreferWrongDataType")
0194                     << "The es_prefer statement for type=" << itInfo.first.type_ << " label=\"" << itInfo.first.label_
0195                     << "\" has the unknown data type \"" << itRecData.second.first << "\""
0196                     << "\n Please check spelling";
0197               }
0198               eventsetup::DataKey datumKey(datumType, itRecData.second.second.c_str());
0199 
0200               //Does the proxyprovider make this?
0201               std::shared_ptr<DataProxyProvider> proxyProv = recordProviderForKey.proxyProvider(*itProxyProv);
0202               unsigned int iovIndex = 0;  // Doesn't matter which index is picked, at least 1 should always exist
0203               const DataProxyProvider::KeyedProxies& keyedProxies = proxyProv->keyedProxies(recordKey, iovIndex);
0204               if (!keyedProxies.contains(datumKey)) {
0205                 throw cms::Exception("ESPreferWrongData")
0206                     << "The es_prefer statement for type=" << itInfo.first.type_ << " label=\"" << itInfo.first.label_
0207                     << "\" specifies the data item \n"
0208                     << "  type=\"" << itRecData.second.first << "\" label=\"" << itRecData.second.second << "\""
0209                     << "  which is not provided.  Please check spelling.";
0210               }
0211 
0212               EventSetupRecordProvider::DataToPreferredProviderMap& dataToProviderMap =
0213                   (*recordToPreferred_)[recordKey];
0214               //has another provider already been specified?
0215               if (dataToProviderMap.end() != dataToProviderMap.find(datumKey)) {
0216                 EventSetupRecordProvider::DataToPreferredProviderMap::iterator itFind =
0217                     dataToProviderMap.find(datumKey);
0218                 throw cms::Exception("ESPreferConflict")
0219                     << "Two providers have been set to be preferred for\n"
0220                     << datumKey.type().name() << " \"" << datumKey.name().value() << "\""
0221                     << "\n the providers are "
0222                     << "\n 1) type=" << itFind->second.type_ << " label=\"" << itFind->second.label_ << "\""
0223                     << "\n 2) type=" << itProxyProv->type_ << " label=\"" << itProxyProv->label_ << "\""
0224                     << "\nPlease modify configuration so only one is preferred";
0225               }
0226               dataToProviderMap.insert(std::make_pair(datumKey, *itProxyProv));
0227             }
0228           }
0229         }
0230       }
0231     }
0232 
0233     void EventSetupProvider::finishConfiguration(NumberOfConcurrentIOVs const& numberOfConcurrentIOVs,
0234                                                  bool& hasNonconcurrentFinder) {
0235       //we delayed adding finders to the system till here so that everything would be loaded first
0236       recordToFinders_->clear();
0237       for (auto& finder : *finders_) {
0238         if (!finder->concurrentFinder()) {
0239           hasNonconcurrentFinder = true;
0240         }
0241 
0242         const std::set<EventSetupRecordKey> recordsUsing = finder->findingForRecords();
0243 
0244         for (auto const& key : recordsUsing) {
0245           (*recordToFinders_)[key].push_back(finder);
0246 
0247           EventSetupRecordProvider* recProvider = tryToGetRecordProvider(key);
0248           if (recProvider == nullptr) {
0249             bool printInfoMsg = true;
0250             unsigned int nConcurrentIOVs = numberOfConcurrentIOVs.numberOfConcurrentIOVs(key, printInfoMsg);
0251 
0252             //create a provider for this record
0253             insert(key, std::make_unique<EventSetupRecordProvider>(key, activityRegistry_, nConcurrentIOVs));
0254             recProvider = tryToGetRecordProvider(key);
0255           }
0256           recProvider->addFinder(finder);
0257         }
0258       }
0259       //we've transfered our ownership so this is no longer needed
0260       finders_.reset();
0261 
0262       //Now handle providers since sources can also be finders and the sources can delay registering
0263       // their Records and therefore could delay setting up their Proxies
0264       psetIDToRecordKey_->clear();
0265       for (auto& dataProxyProvider : *dataProviders_) {
0266         ParameterSetIDHolder psetID(dataProxyProvider->description().pid_);
0267 
0268         const std::set<EventSetupRecordKey> recordsUsing = dataProxyProvider->usingRecords();
0269         for (auto const& key : recordsUsing) {
0270           unsigned int nConcurrentIOVs = numberOfConcurrentIOVs.numberOfConcurrentIOVs(key);
0271           dataProxyProvider->createKeyedProxies(key, nConcurrentIOVs);
0272 
0273           if (dataProxyProvider->description().isLooper_) {
0274             recordsWithALooperProxy_->insert(key);
0275           }
0276 
0277           (*psetIDToRecordKey_)[psetID].insert(key);
0278 
0279           EventSetupRecordProvider* recProvider = tryToGetRecordProvider(key);
0280           if (recProvider == nullptr) {
0281             bool printInfoMsg = true;
0282             nConcurrentIOVs = numberOfConcurrentIOVs.numberOfConcurrentIOVs(key, printInfoMsg);
0283             //create a provider for this record
0284             insert(key, std::make_unique<EventSetupRecordProvider>(key, activityRegistry_, nConcurrentIOVs));
0285             recProvider = tryToGetRecordProvider(key);
0286           }
0287           recProvider->add(dataProxyProvider);
0288         }
0289       }
0290 
0291       //used for the case where no preferred Providers have been specified for the Record
0292       static const EventSetupRecordProvider::DataToPreferredProviderMap kEmptyMap;
0293 
0294       determinePreferred();
0295 
0296       //For each Provider, find all the Providers it depends on.  If a dependent Provider
0297       // can not be found pass in an empty list
0298       //CHANGE: now allow for missing Providers
0299       for (auto& itRecordProvider : recordProviders_) {
0300         const EventSetupRecordProvider::DataToPreferredProviderMap* preferredInfo = &kEmptyMap;
0301         RecordToPreferred::const_iterator itRecordFound = recordToPreferred_->find(itRecordProvider->key());
0302         if (itRecordFound != recordToPreferred_->end()) {
0303           preferredInfo = &(itRecordFound->second);
0304         }
0305         //Give it our list of preferred
0306         itRecordProvider->usePreferred(*preferredInfo);
0307 
0308         std::set<EventSetupRecordKey> records = itRecordProvider->dependentRecords();
0309         if (!records.empty()) {
0310           std::string missingRecords;
0311           std::vector<std::shared_ptr<EventSetupRecordProvider>> depProviders;
0312           depProviders.reserve(records.size());
0313           bool foundAllProviders = true;
0314           for (auto const& key : records) {
0315             auto lb = std::lower_bound(recordKeys_.begin(), recordKeys_.end(), key);
0316             if (lb == recordKeys_.end() || key != *lb) {
0317               foundAllProviders = false;
0318               if (missingRecords.empty()) {
0319                 missingRecords = key.name();
0320               } else {
0321                 missingRecords += ", ";
0322                 missingRecords += key.name();
0323               }
0324             } else {
0325               auto index = std::distance(recordKeys_.begin(), lb);
0326               depProviders.push_back(recordProviders_[index]);
0327             }
0328           }
0329 
0330           if (!foundAllProviders) {
0331             edm::LogInfo("EventSetupDependency")
0332                 << "The EventSetup record " << itRecordProvider->key().name() << " depends on at least one Record \n ("
0333                 << missingRecords
0334                 << ") which is not present in the job."
0335                    "\n This may lead to an exception begin thrown during event processing.\n If no exception occurs "
0336                    "during the job than it is usually safe to ignore this message.";
0337 
0338             //depProviders.clear();
0339             //NOTE: should provide a warning
0340           }
0341 
0342           itRecordProvider->setDependentProviders(depProviders);
0343         }
0344       }
0345 
0346       auto indices = recordsToProxyIndices();
0347       for (auto& provider : *dataProviders_) {
0348         provider->updateLookup(indices);
0349       }
0350       dataProviders_.reset();
0351 
0352       mustFinishConfiguration_ = false;
0353     }
0354 
0355     using Itr = RecordProviders::iterator;
0356     static void findDependents(const EventSetupRecordKey& iKey,
0357                                Itr itBegin,
0358                                Itr itEnd,
0359                                std::vector<std::shared_ptr<EventSetupRecordProvider>>& oDependents) {
0360       for (Itr it = itBegin; it != itEnd; ++it) {
0361         //does it depend on the record in question?
0362         const std::set<EventSetupRecordKey>& deps = (*it)->dependentRecords();
0363         if (deps.end() != deps.find(iKey)) {
0364           oDependents.push_back(*it);
0365           //now see who is dependent on this record since they will be indirectly dependent on iKey
0366           findDependents((*it)->key(), itBegin, itEnd, oDependents);
0367         }
0368       }
0369     }
0370 
0371     void EventSetupProvider::resetRecordPlusDependentRecords(const EventSetupRecordKey& iKey) {
0372       EventSetupRecordProvider* recProvider = tryToGetRecordProvider(iKey);
0373       if (recProvider == nullptr) {
0374         return;
0375       }
0376 
0377       std::vector<std::shared_ptr<EventSetupRecordProvider>> dependents;
0378       findDependents(iKey, recordProviders_.begin(), recordProviders_.end(), dependents);
0379 
0380       dependents.erase(std::unique(dependents.begin(), dependents.end()), dependents.end());
0381 
0382       recProvider->resetProxies();
0383       for (auto& d : dependents) {
0384         d->resetProxies();
0385       }
0386     }
0387 
0388     void EventSetupProvider::forceCacheClear() {
0389       for (auto& recProvider : recordProviders_) {
0390         if (recProvider) {
0391           recProvider->resetProxies();
0392         }
0393       }
0394     }
0395 
0396     void EventSetupProvider::checkESProducerSharing(
0397         EventSetupProvider& precedingESProvider,
0398         std::set<ParameterSetIDHolder>& sharingCheckDone,
0399         std::map<EventSetupRecordKey, std::vector<ComponentDescription const*>>& referencedESProducers,
0400         EventSetupsController& esController) {
0401       edm::LogVerbatim("EventSetupSharing")
0402           << "EventSetupProvider::checkESProducerSharing: Checking processes with SubProcess Indexes "
0403           << subProcessIndex() << " and " << precedingESProvider.subProcessIndex();
0404 
0405       if (referencedESProducers.empty()) {
0406         for (auto& recProvider : recordProviders_) {
0407           recProvider->getReferencedESProducers(referencedESProducers);
0408         }
0409       }
0410 
0411       // This records whether the configurations of all the DataProxyProviders
0412       // and finders matches for a particular pair of processes and
0413       // a particular record and also the records it depends on.
0414       std::map<EventSetupRecordKey, bool> allComponentsMatch;
0415 
0416       std::map<ParameterSetID, bool> candidateNotRejectedYet;
0417 
0418       // Loop over all the ESProducers which have a DataProxy
0419       // referenced by any EventSetupRecord in this EventSetupProvider
0420       for (auto const& iRecord : referencedESProducers) {
0421         for (auto const& iComponent : iRecord.second) {
0422           ParameterSetID const& psetID = iComponent->pid_;
0423           ParameterSetIDHolder psetIDHolder(psetID);
0424           if (sharingCheckDone.find(psetIDHolder) != sharingCheckDone.end())
0425             continue;
0426 
0427           bool firstProcessWithThisPSet = false;
0428           bool precedingHasMatchingPSet = false;
0429 
0430           esController.lookForMatches(psetID,
0431                                       subProcessIndex_,
0432                                       precedingESProvider.subProcessIndex_,
0433                                       firstProcessWithThisPSet,
0434                                       precedingHasMatchingPSet);
0435 
0436           if (firstProcessWithThisPSet) {
0437             sharingCheckDone.insert(psetIDHolder);
0438             allComponentsMatch[iRecord.first] = false;
0439             continue;
0440           }
0441 
0442           if (!precedingHasMatchingPSet) {
0443             allComponentsMatch[iRecord.first] = false;
0444             continue;
0445           }
0446 
0447           // An ESProducer that survives to this point is a candidate.
0448           // It was shared with some other process in the first pass where
0449           // ESProducers were constructed and one of three possibilities exists:
0450           //    1) It should not have been shared and a new ESProducer needs
0451           //    to be created and the proper pointers set.
0452           //    2) It should have been shared with a different preceding process
0453           //    in which case some pointers need to be modified.
0454           //    3) It was originally shared which the correct prior process
0455           //    in which case nothing needs to be done, but we do need to
0456           //    do some work to verify that.
0457           // Make an entry in a map for each of these ESProducers. We
0458           // will set the value to false if and when we determine
0459           // the ESProducer cannot be shared between this pair of processes.
0460           auto iCandidateNotRejectedYet = candidateNotRejectedYet.find(psetID);
0461           if (iCandidateNotRejectedYet == candidateNotRejectedYet.end()) {
0462             candidateNotRejectedYet[psetID] = true;
0463             iCandidateNotRejectedYet = candidateNotRejectedYet.find(psetID);
0464           }
0465 
0466           // At this point we know that the two processes both
0467           // have an ESProducer matching the type and label in
0468           // iComponent and also with exactly the same configuration.
0469           // And there was not an earlier preceding process
0470           // where the same instance of the ESProducer could
0471           // have been shared.  And this ESProducer was referenced
0472           // by the later process's EventSetupRecord (preferred or
0473           // or just the only thing that could have made the data).
0474           // To determine if sharing is allowed, now we need to
0475           // check if all the DataProxyProviders and all the
0476           // finders are the same for this record and also for
0477           // all records this record depends on. And even
0478           // if this is true, we have to wait until the loop
0479           // ends because some other DataProxy associated with
0480           // the ESProducer could write to a different record where
0481           // the same determination will need to be repeated. Only if
0482           // all of the the DataProxy's can be shared, can the ESProducer
0483           // instance be shared across processes.
0484 
0485           if (iCandidateNotRejectedYet->second == true) {
0486             auto iAllComponentsMatch = allComponentsMatch.find(iRecord.first);
0487             if (iAllComponentsMatch == allComponentsMatch.end()) {
0488               // We do not know the value in AllComponents yet and
0489               // we need it now so we have to do the difficult calculation
0490               // now.
0491               bool match = doRecordsMatch(precedingESProvider, iRecord.first, allComponentsMatch, esController);
0492               allComponentsMatch[iRecord.first] = match;
0493               iAllComponentsMatch = allComponentsMatch.find(iRecord.first);
0494             }
0495             if (!iAllComponentsMatch->second) {
0496               iCandidateNotRejectedYet->second = false;
0497             }
0498           }
0499         }  // end loop over components used by record
0500       }    // end loop over records
0501 
0502       // Loop over candidates
0503       for (auto const& candidate : candidateNotRejectedYet) {
0504         ParameterSetID const& psetID = candidate.first;
0505         bool canBeShared = candidate.second;
0506         if (canBeShared) {
0507           ParameterSet const& pset = *esController.getESProducerPSet(psetID, subProcessIndex_);
0508           logInfoWhenSharing(pset);
0509           ParameterSetIDHolder psetIDHolder(psetID);
0510           sharingCheckDone.insert(psetIDHolder);
0511           if (esController.isFirstMatch(psetID, subProcessIndex_, precedingESProvider.subProcessIndex_)) {
0512             continue;  // Proper sharing was already done. Nothing more to do.
0513           }
0514 
0515           // Need to reset the pointer from the EventSetupRecordProvider to the
0516           // the DataProxyProvider so these two processes share an ESProducer.
0517 
0518           std::shared_ptr<DataProxyProvider> dataProxyProvider;
0519           std::set<EventSetupRecordKey> const& keysForPSetID1 = (*precedingESProvider.psetIDToRecordKey_)[psetIDHolder];
0520           for (auto const& key : keysForPSetID1) {
0521             dataProxyProvider = precedingESProvider.recordProvider(key)->proxyProvider(psetIDHolder);
0522             assert(dataProxyProvider);
0523             break;
0524           }
0525 
0526           std::set<EventSetupRecordKey> const& keysForPSetID2 = (*psetIDToRecordKey_)[psetIDHolder];
0527           for (auto const& key : keysForPSetID2) {
0528             recordProvider(key)->resetProxyProvider(psetIDHolder, dataProxyProvider);
0529           }
0530         } else {
0531           if (esController.isLastMatch(psetID, subProcessIndex_, precedingESProvider.subProcessIndex_)) {
0532             ParameterSet const& pset = *esController.getESProducerPSet(psetID, subProcessIndex_);
0533             ModuleFactory::get()->addTo(esController, *this, pset, true);
0534           }
0535         }
0536       }
0537     }
0538 
0539     bool EventSetupProvider::doRecordsMatch(EventSetupProvider& precedingESProvider,
0540                                             EventSetupRecordKey const& eventSetupRecordKey,
0541                                             std::map<EventSetupRecordKey, bool>& allComponentsMatch,
0542                                             EventSetupsController const& esController) {
0543       // first check if this record matches. If not just return false
0544 
0545       // then find the directly dependent records and iterate over them
0546       // recursively call this function on them. If they return false
0547       // set allComponentsMatch to false for them and return false.
0548       // if they all return true then set allComponents to true
0549       // and return true.
0550 
0551       if (precedingESProvider.recordsWithALooperProxy_->find(eventSetupRecordKey) !=
0552           precedingESProvider.recordsWithALooperProxy_->end()) {
0553         return false;
0554       }
0555 
0556       if ((*recordToFinders_)[eventSetupRecordKey].size() !=
0557           (*precedingESProvider.recordToFinders_)[eventSetupRecordKey].size()) {
0558         return false;
0559       }
0560 
0561       for (auto const& finder : (*recordToFinders_)[eventSetupRecordKey]) {
0562         ParameterSetID const& psetID = finder->descriptionForFinder().pid_;
0563         bool itMatches =
0564             esController.isMatchingESSource(psetID, subProcessIndex_, precedingESProvider.subProcessIndex_);
0565         if (!itMatches) {
0566           return false;
0567         }
0568       }
0569 
0570       fillReferencedDataKeys(eventSetupRecordKey);
0571       precedingESProvider.fillReferencedDataKeys(eventSetupRecordKey);
0572 
0573       std::map<DataKey, ComponentDescription const*> const& dataItems = (*referencedDataKeys_)[eventSetupRecordKey];
0574 
0575       std::map<DataKey, ComponentDescription const*> const& precedingDataItems =
0576           (*precedingESProvider.referencedDataKeys_)[eventSetupRecordKey];
0577 
0578       if (dataItems.size() != precedingDataItems.size()) {
0579         return false;
0580       }
0581 
0582       for (auto const& dataItem : dataItems) {
0583         auto precedingDataItem = precedingDataItems.find(dataItem.first);
0584         if (precedingDataItem == precedingDataItems.end()) {
0585           return false;
0586         }
0587         if (dataItem.second->pid_ != precedingDataItem->second->pid_) {
0588           return false;
0589         }
0590         // Check that the configurations match exactly for the ESProducers
0591         // (We already checked the ESSources above and there should not be
0592         // any loopers)
0593         if (!dataItem.second->isSource_ && !dataItem.second->isLooper_) {
0594           bool itMatches = esController.isMatchingESProducer(
0595               dataItem.second->pid_, subProcessIndex_, precedingESProvider.subProcessIndex_);
0596           if (!itMatches) {
0597             return false;
0598           }
0599         }
0600       }
0601       EventSetupRecordProvider* recProvider = tryToGetRecordProvider(eventSetupRecordKey);
0602       if (recProvider != nullptr) {
0603         std::set<EventSetupRecordKey> dependentRecords = recProvider->dependentRecords();
0604         for (auto const& dependentRecord : dependentRecords) {
0605           auto iter = allComponentsMatch.find(dependentRecord);
0606           if (iter != allComponentsMatch.end()) {
0607             if (iter->second) {
0608               continue;
0609             } else {
0610               return false;
0611             }
0612           }
0613           bool match = doRecordsMatch(precedingESProvider, dependentRecord, allComponentsMatch, esController);
0614           allComponentsMatch[dependentRecord] = match;
0615           if (!match)
0616             return false;
0617         }
0618       }
0619       return true;
0620     }
0621 
0622     void EventSetupProvider::fillReferencedDataKeys(EventSetupRecordKey const& eventSetupRecordKey) {
0623       if (referencedDataKeys_->find(eventSetupRecordKey) != referencedDataKeys_->end())
0624         return;
0625 
0626       EventSetupRecordProvider* recProvider = tryToGetRecordProvider(eventSetupRecordKey);
0627       if (recProvider == nullptr) {
0628         (*referencedDataKeys_)[eventSetupRecordKey];
0629         return;
0630       }
0631       recProvider->fillReferencedDataKeys((*referencedDataKeys_)[eventSetupRecordKey]);
0632     }
0633 
0634     void EventSetupProvider::resetRecordToProxyPointers() {
0635       for (auto const& recProvider : recordProviders_) {
0636         static const EventSetupRecordProvider::DataToPreferredProviderMap kEmptyMap;
0637         const EventSetupRecordProvider::DataToPreferredProviderMap* preferredInfo = &kEmptyMap;
0638         RecordToPreferred::const_iterator itRecordFound = recordToPreferred_->find(recProvider->key());
0639         if (itRecordFound != recordToPreferred_->end()) {
0640           preferredInfo = &(itRecordFound->second);
0641         }
0642         recProvider->resetRecordToProxyPointers(*preferredInfo);
0643       }
0644     }
0645 
0646     void EventSetupProvider::clearInitializationData() {
0647       preferredProviderInfo_.reset();
0648       referencedDataKeys_.reset();
0649       recordToFinders_.reset();
0650       psetIDToRecordKey_.reset();
0651       recordToPreferred_.reset();
0652       recordsWithALooperProxy_.reset();
0653     }
0654 
0655     void EventSetupProvider::fillRecordsNotAllowingConcurrentIOVs(
0656         std::set<EventSetupRecordKey>& recordsNotAllowingConcurrentIOVs) const {
0657       for (auto const& dataProxyProvider : *dataProviders_) {
0658         dataProxyProvider->fillRecordsNotAllowingConcurrentIOVs(recordsNotAllowingConcurrentIOVs);
0659       }
0660     }
0661 
0662     void EventSetupProvider::setAllValidityIntervals(const IOVSyncValue& iValue) {
0663       // First loop sets a flag that helps us to not duplicate calls to the
0664       // same EventSetupRecordProvider setting the IOVs. Dependent records
0665       // can cause duplicate calls without this protection.
0666       for (auto& recProvider : recordProviders_) {
0667         recProvider->initializeForNewSyncValue();
0668       }
0669 
0670       for (auto& recProvider : recordProviders_) {
0671         recProvider->setValidityIntervalFor(iValue);
0672       }
0673     }
0674 
0675     std::shared_ptr<const EventSetupImpl> EventSetupProvider::eventSetupForInstance(const IOVSyncValue& iValue,
0676                                                                                     bool& newEventSetupImpl) {
0677       using IntervalStatus = EventSetupRecordProvider::IntervalStatus;
0678 
0679       // It is important to understand that eventSetupForInstance is a function
0680       // where only one call is executing at a time (not multiple calls running
0681       // concurrently). These calls are made in the order determined by the
0682       // InputSource. One invocation completes and returns before another starts.
0683 
0684       bool needNewEventSetupImpl = false;
0685       if (eventSetupImpl_.get() == nullptr) {
0686         needNewEventSetupImpl = true;
0687       } else {
0688         for (auto& recProvider : recordProviders_) {
0689           if (recProvider->intervalStatus() == IntervalStatus::Invalid) {
0690             if (eventSetupImpl_->validRecord(recProvider->key())) {
0691               needNewEventSetupImpl = true;
0692             }
0693           } else {
0694             if (recProvider->newIntervalForAnySubProcess()) {
0695               needNewEventSetupImpl = true;
0696             }
0697           }
0698         }
0699       }
0700 
0701       if (needNewEventSetupImpl) {
0702         //cannot use make_shared because constructor is private
0703         eventSetupImpl_ = std::shared_ptr<EventSetupImpl>(new EventSetupImpl());
0704         newEventSetupImpl = true;
0705         eventSetupImpl_->setKeyIters(recordKeys_.begin(), recordKeys_.end());
0706 
0707         for (auto& recProvider : recordProviders_) {
0708           recProvider->setEventSetupImpl(eventSetupImpl_.get());
0709         }
0710       }
0711       return get_underlying_safe(eventSetupImpl_);
0712     }
0713 
0714     bool EventSetupProvider::doWeNeedToWaitForIOVsToFinish(IOVSyncValue const& iValue) const {
0715       for (auto& recProvider : recordProviders_) {
0716         if (recProvider->doWeNeedToWaitForIOVsToFinish(iValue)) {
0717           return true;
0718         }
0719       }
0720       return false;
0721     }
0722 
0723     std::set<ComponentDescription> EventSetupProvider::proxyProviderDescriptions() const {
0724       typedef std::set<ComponentDescription> Set;
0725       Set descriptions;
0726 
0727       for (auto const& recProvider : recordProviders_) {
0728         auto const& d = recProvider->proxyProviderDescriptions();
0729         descriptions.insert(d.begin(), d.end());
0730       }
0731       if (dataProviders_.get()) {
0732         for (auto const& p : *dataProviders_) {
0733           descriptions.insert(p->description());
0734         }
0735       }
0736 
0737       return descriptions;
0738     }
0739 
0740     void EventSetupProvider::addRecord(const EventSetupRecordKey& iKey) {
0741       insert(iKey, std::unique_ptr<EventSetupRecordProvider>());
0742       eventSetupImpl_->setKeyIters(recordKeys_.begin(), recordKeys_.end());
0743     }
0744 
0745     void EventSetupProvider::setPreferredProviderInfo(PreferredProviderInfo const& iInfo) {
0746       preferredProviderInfo_ = std::make_unique<PreferredProviderInfo>(iInfo);
0747     }
0748 
0749     void EventSetupProvider::fillKeys(std::set<EventSetupRecordKey>& keys) const {
0750       for (auto const& recProvider : recordProviders_) {
0751         keys.insert(recProvider->key());
0752       }
0753     }
0754 
0755     ESRecordsToProxyIndices EventSetupProvider::recordsToProxyIndices() const {
0756       ESRecordsToProxyIndices ret(recordKeys_);
0757 
0758       unsigned int index = 0;
0759       for (const auto& provider : recordProviders_) {
0760         index = ret.dataKeysInRecord(
0761             index, provider->key(), provider->registeredDataKeys(), provider->componentsForRegisteredDataKeys());
0762       }
0763 
0764       return ret;
0765     }
0766 
0767     //
0768     // static member functions
0769     //
0770     void EventSetupProvider::logInfoWhenSharing(ParameterSet const& iConfiguration) {
0771       std::string edmtype = iConfiguration.getParameter<std::string>("@module_edm_type");
0772       std::string modtype = iConfiguration.getParameter<std::string>("@module_type");
0773       std::string label = iConfiguration.getParameter<std::string>("@module_label");
0774       edm::LogVerbatim("EventSetupSharing")
0775           << "Sharing " << edmtype << ": class=" << modtype << " label='" << label << "'";
0776     }
0777 
0778   }  // namespace eventsetup
0779 }  // namespace edm