Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-01-11 16:27:14

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         ModuleTypeResolverMaker const* resolverMaker,
0398         EventSetupProvider& precedingESProvider,
0399         std::set<ParameterSetIDHolder>& sharingCheckDone,
0400         std::map<EventSetupRecordKey, std::vector<ComponentDescription const*>>& referencedESProducers,
0401         EventSetupsController& esController) {
0402       edm::LogVerbatim("EventSetupSharing")
0403           << "EventSetupProvider::checkESProducerSharing: Checking processes with SubProcess Indexes "
0404           << subProcessIndex() << " and " << precedingESProvider.subProcessIndex();
0405 
0406       if (referencedESProducers.empty()) {
0407         for (auto& recProvider : recordProviders_) {
0408           recProvider->getReferencedESProducers(referencedESProducers);
0409         }
0410       }
0411 
0412       // This records whether the configurations of all the DataProxyProviders
0413       // and finders matches for a particular pair of processes and
0414       // a particular record and also the records it depends on.
0415       std::map<EventSetupRecordKey, bool> allComponentsMatch;
0416 
0417       std::map<ParameterSetID, bool> candidateNotRejectedYet;
0418 
0419       // Loop over all the ESProducers which have a DataProxy
0420       // referenced by any EventSetupRecord in this EventSetupProvider
0421       for (auto const& iRecord : referencedESProducers) {
0422         for (auto const& iComponent : iRecord.second) {
0423           ParameterSetID const& psetID = iComponent->pid_;
0424           ParameterSetIDHolder psetIDHolder(psetID);
0425           if (sharingCheckDone.find(psetIDHolder) != sharingCheckDone.end())
0426             continue;
0427 
0428           bool firstProcessWithThisPSet = false;
0429           bool precedingHasMatchingPSet = false;
0430 
0431           esController.lookForMatches(psetID,
0432                                       subProcessIndex_,
0433                                       precedingESProvider.subProcessIndex_,
0434                                       firstProcessWithThisPSet,
0435                                       precedingHasMatchingPSet);
0436 
0437           if (firstProcessWithThisPSet) {
0438             sharingCheckDone.insert(psetIDHolder);
0439             allComponentsMatch[iRecord.first] = false;
0440             continue;
0441           }
0442 
0443           if (!precedingHasMatchingPSet) {
0444             allComponentsMatch[iRecord.first] = false;
0445             continue;
0446           }
0447 
0448           // An ESProducer that survives to this point is a candidate.
0449           // It was shared with some other process in the first pass where
0450           // ESProducers were constructed and one of three possibilities exists:
0451           //    1) It should not have been shared and a new ESProducer needs
0452           //    to be created and the proper pointers set.
0453           //    2) It should have been shared with a different preceding process
0454           //    in which case some pointers need to be modified.
0455           //    3) It was originally shared which the correct prior process
0456           //    in which case nothing needs to be done, but we do need to
0457           //    do some work to verify that.
0458           // Make an entry in a map for each of these ESProducers. We
0459           // will set the value to false if and when we determine
0460           // the ESProducer cannot be shared between this pair of processes.
0461           auto iCandidateNotRejectedYet = candidateNotRejectedYet.find(psetID);
0462           if (iCandidateNotRejectedYet == candidateNotRejectedYet.end()) {
0463             candidateNotRejectedYet[psetID] = true;
0464             iCandidateNotRejectedYet = candidateNotRejectedYet.find(psetID);
0465           }
0466 
0467           // At this point we know that the two processes both
0468           // have an ESProducer matching the type and label in
0469           // iComponent and also with exactly the same configuration.
0470           // And there was not an earlier preceding process
0471           // where the same instance of the ESProducer could
0472           // have been shared.  And this ESProducer was referenced
0473           // by the later process's EventSetupRecord (preferred or
0474           // or just the only thing that could have made the data).
0475           // To determine if sharing is allowed, now we need to
0476           // check if all the DataProxyProviders and all the
0477           // finders are the same for this record and also for
0478           // all records this record depends on. And even
0479           // if this is true, we have to wait until the loop
0480           // ends because some other DataProxy associated with
0481           // the ESProducer could write to a different record where
0482           // the same determination will need to be repeated. Only if
0483           // all of the the DataProxy's can be shared, can the ESProducer
0484           // instance be shared across processes.
0485 
0486           if (iCandidateNotRejectedYet->second == true) {
0487             auto iAllComponentsMatch = allComponentsMatch.find(iRecord.first);
0488             if (iAllComponentsMatch == allComponentsMatch.end()) {
0489               // We do not know the value in AllComponents yet and
0490               // we need it now so we have to do the difficult calculation
0491               // now.
0492               bool match = doRecordsMatch(precedingESProvider, iRecord.first, allComponentsMatch, esController);
0493               allComponentsMatch[iRecord.first] = match;
0494               iAllComponentsMatch = allComponentsMatch.find(iRecord.first);
0495             }
0496             if (!iAllComponentsMatch->second) {
0497               iCandidateNotRejectedYet->second = false;
0498             }
0499           }
0500         }  // end loop over components used by record
0501       }    // end loop over records
0502 
0503       // Loop over candidates
0504       for (auto const& candidate : candidateNotRejectedYet) {
0505         ParameterSetID const& psetID = candidate.first;
0506         bool canBeShared = candidate.second;
0507         if (canBeShared) {
0508           ParameterSet const& pset = esController.getESProducerPSet(psetID, subProcessIndex_);
0509           logInfoWhenSharing(pset);
0510           ParameterSetIDHolder psetIDHolder(psetID);
0511           sharingCheckDone.insert(psetIDHolder);
0512           if (esController.isFirstMatch(psetID, subProcessIndex_, precedingESProvider.subProcessIndex_)) {
0513             continue;  // Proper sharing was already done. Nothing more to do.
0514           }
0515 
0516           // Need to reset the pointer from the EventSetupRecordProvider to the
0517           // the DataProxyProvider so these two processes share an ESProducer.
0518 
0519           std::shared_ptr<DataProxyProvider> dataProxyProvider;
0520           std::set<EventSetupRecordKey> const& keysForPSetID1 = (*precedingESProvider.psetIDToRecordKey_)[psetIDHolder];
0521           for (auto const& key : keysForPSetID1) {
0522             dataProxyProvider = precedingESProvider.recordProvider(key)->proxyProvider(psetIDHolder);
0523             assert(dataProxyProvider);
0524             break;
0525           }
0526 
0527           std::set<EventSetupRecordKey> const& keysForPSetID2 = (*psetIDToRecordKey_)[psetIDHolder];
0528           for (auto const& key : keysForPSetID2) {
0529             recordProvider(key)->resetProxyProvider(psetIDHolder, dataProxyProvider);
0530           }
0531         } else {
0532           if (esController.isLastMatch(psetID, subProcessIndex_, precedingESProvider.subProcessIndex_)) {
0533             ParameterSet& pset = esController.getESProducerPSet(psetID, subProcessIndex_);
0534             ModuleFactory::get()->addTo(esController, *this, pset, resolverMaker, true);
0535           }
0536         }
0537       }
0538     }
0539 
0540     bool EventSetupProvider::doRecordsMatch(EventSetupProvider& precedingESProvider,
0541                                             EventSetupRecordKey const& eventSetupRecordKey,
0542                                             std::map<EventSetupRecordKey, bool>& allComponentsMatch,
0543                                             EventSetupsController const& esController) {
0544       // first check if this record matches. If not just return false
0545 
0546       // then find the directly dependent records and iterate over them
0547       // recursively call this function on them. If they return false
0548       // set allComponentsMatch to false for them and return false.
0549       // if they all return true then set allComponents to true
0550       // and return true.
0551 
0552       if (precedingESProvider.recordsWithALooperProxy_->find(eventSetupRecordKey) !=
0553           precedingESProvider.recordsWithALooperProxy_->end()) {
0554         return false;
0555       }
0556 
0557       if ((*recordToFinders_)[eventSetupRecordKey].size() !=
0558           (*precedingESProvider.recordToFinders_)[eventSetupRecordKey].size()) {
0559         return false;
0560       }
0561 
0562       for (auto const& finder : (*recordToFinders_)[eventSetupRecordKey]) {
0563         ParameterSetID const& psetID = finder->descriptionForFinder().pid_;
0564         bool itMatches =
0565             esController.isMatchingESSource(psetID, subProcessIndex_, precedingESProvider.subProcessIndex_);
0566         if (!itMatches) {
0567           return false;
0568         }
0569       }
0570 
0571       fillReferencedDataKeys(eventSetupRecordKey);
0572       precedingESProvider.fillReferencedDataKeys(eventSetupRecordKey);
0573 
0574       std::map<DataKey, ComponentDescription const*> const& dataItems = (*referencedDataKeys_)[eventSetupRecordKey];
0575 
0576       std::map<DataKey, ComponentDescription const*> const& precedingDataItems =
0577           (*precedingESProvider.referencedDataKeys_)[eventSetupRecordKey];
0578 
0579       if (dataItems.size() != precedingDataItems.size()) {
0580         return false;
0581       }
0582 
0583       for (auto const& dataItem : dataItems) {
0584         auto precedingDataItem = precedingDataItems.find(dataItem.first);
0585         if (precedingDataItem == precedingDataItems.end()) {
0586           return false;
0587         }
0588         if (dataItem.second->pid_ != precedingDataItem->second->pid_) {
0589           return false;
0590         }
0591         // Check that the configurations match exactly for the ESProducers
0592         // (We already checked the ESSources above and there should not be
0593         // any loopers)
0594         if (!dataItem.second->isSource_ && !dataItem.second->isLooper_) {
0595           bool itMatches = esController.isMatchingESProducer(
0596               dataItem.second->pid_, subProcessIndex_, precedingESProvider.subProcessIndex_);
0597           if (!itMatches) {
0598             return false;
0599           }
0600         }
0601       }
0602       EventSetupRecordProvider* recProvider = tryToGetRecordProvider(eventSetupRecordKey);
0603       if (recProvider != nullptr) {
0604         std::set<EventSetupRecordKey> dependentRecords = recProvider->dependentRecords();
0605         for (auto const& dependentRecord : dependentRecords) {
0606           auto iter = allComponentsMatch.find(dependentRecord);
0607           if (iter != allComponentsMatch.end()) {
0608             if (iter->second) {
0609               continue;
0610             } else {
0611               return false;
0612             }
0613           }
0614           bool match = doRecordsMatch(precedingESProvider, dependentRecord, allComponentsMatch, esController);
0615           allComponentsMatch[dependentRecord] = match;
0616           if (!match)
0617             return false;
0618         }
0619       }
0620       return true;
0621     }
0622 
0623     void EventSetupProvider::fillReferencedDataKeys(EventSetupRecordKey const& eventSetupRecordKey) {
0624       if (referencedDataKeys_->find(eventSetupRecordKey) != referencedDataKeys_->end())
0625         return;
0626 
0627       EventSetupRecordProvider* recProvider = tryToGetRecordProvider(eventSetupRecordKey);
0628       if (recProvider == nullptr) {
0629         (*referencedDataKeys_)[eventSetupRecordKey];
0630         return;
0631       }
0632       recProvider->fillReferencedDataKeys((*referencedDataKeys_)[eventSetupRecordKey]);
0633     }
0634 
0635     void EventSetupProvider::resetRecordToProxyPointers() {
0636       for (auto const& recProvider : recordProviders_) {
0637         static const EventSetupRecordProvider::DataToPreferredProviderMap kEmptyMap;
0638         const EventSetupRecordProvider::DataToPreferredProviderMap* preferredInfo = &kEmptyMap;
0639         RecordToPreferred::const_iterator itRecordFound = recordToPreferred_->find(recProvider->key());
0640         if (itRecordFound != recordToPreferred_->end()) {
0641           preferredInfo = &(itRecordFound->second);
0642         }
0643         recProvider->resetRecordToProxyPointers(*preferredInfo);
0644       }
0645     }
0646 
0647     void EventSetupProvider::clearInitializationData() {
0648       preferredProviderInfo_.reset();
0649       referencedDataKeys_.reset();
0650       recordToFinders_.reset();
0651       psetIDToRecordKey_.reset();
0652       recordToPreferred_.reset();
0653       recordsWithALooperProxy_.reset();
0654     }
0655 
0656     void EventSetupProvider::fillRecordsNotAllowingConcurrentIOVs(
0657         std::set<EventSetupRecordKey>& recordsNotAllowingConcurrentIOVs) const {
0658       for (auto const& dataProxyProvider : *dataProviders_) {
0659         dataProxyProvider->fillRecordsNotAllowingConcurrentIOVs(recordsNotAllowingConcurrentIOVs);
0660       }
0661     }
0662 
0663     void EventSetupProvider::setAllValidityIntervals(const IOVSyncValue& iValue) {
0664       // First loop sets a flag that helps us to not duplicate calls to the
0665       // same EventSetupRecordProvider setting the IOVs. Dependent records
0666       // can cause duplicate calls without this protection.
0667       for (auto& recProvider : recordProviders_) {
0668         recProvider->initializeForNewSyncValue();
0669       }
0670 
0671       for (auto& recProvider : recordProviders_) {
0672         recProvider->setValidityIntervalFor(iValue);
0673       }
0674     }
0675 
0676     std::shared_ptr<const EventSetupImpl> EventSetupProvider::eventSetupForInstance(const IOVSyncValue& iValue,
0677                                                                                     bool& newEventSetupImpl) {
0678       using IntervalStatus = EventSetupRecordProvider::IntervalStatus;
0679 
0680       // It is important to understand that eventSetupForInstance is a function
0681       // where only one call is executing at a time (not multiple calls running
0682       // concurrently). These calls are made in the order determined by the
0683       // InputSource. One invocation completes and returns before another starts.
0684 
0685       bool needNewEventSetupImpl = false;
0686       if (eventSetupImpl_.get() == nullptr) {
0687         needNewEventSetupImpl = true;
0688       } else {
0689         for (auto& recProvider : recordProviders_) {
0690           if (recProvider->intervalStatus() == IntervalStatus::Invalid) {
0691             if (eventSetupImpl_->validRecord(recProvider->key())) {
0692               needNewEventSetupImpl = true;
0693             }
0694           } else {
0695             if (recProvider->newIntervalForAnySubProcess()) {
0696               needNewEventSetupImpl = true;
0697             }
0698           }
0699         }
0700       }
0701 
0702       if (needNewEventSetupImpl) {
0703         //cannot use make_shared because constructor is private
0704         eventSetupImpl_ = std::shared_ptr<EventSetupImpl>(new EventSetupImpl());
0705         newEventSetupImpl = true;
0706         eventSetupImpl_->setKeyIters(recordKeys_.begin(), recordKeys_.end());
0707 
0708         for (auto& recProvider : recordProviders_) {
0709           recProvider->setEventSetupImpl(eventSetupImpl_.get());
0710         }
0711       }
0712       return get_underlying_safe(eventSetupImpl_);
0713     }
0714 
0715     bool EventSetupProvider::doWeNeedToWaitForIOVsToFinish(IOVSyncValue const& iValue) const {
0716       for (auto& recProvider : recordProviders_) {
0717         if (recProvider->doWeNeedToWaitForIOVsToFinish(iValue)) {
0718           return true;
0719         }
0720       }
0721       return false;
0722     }
0723 
0724     std::set<ComponentDescription> EventSetupProvider::proxyProviderDescriptions() const {
0725       typedef std::set<ComponentDescription> Set;
0726       Set descriptions;
0727 
0728       for (auto const& recProvider : recordProviders_) {
0729         auto const& d = recProvider->proxyProviderDescriptions();
0730         descriptions.insert(d.begin(), d.end());
0731       }
0732       if (dataProviders_.get()) {
0733         for (auto const& p : *dataProviders_) {
0734           descriptions.insert(p->description());
0735         }
0736       }
0737 
0738       return descriptions;
0739     }
0740 
0741     void EventSetupProvider::addRecord(const EventSetupRecordKey& iKey) {
0742       insert(iKey, std::unique_ptr<EventSetupRecordProvider>());
0743       eventSetupImpl_->setKeyIters(recordKeys_.begin(), recordKeys_.end());
0744     }
0745 
0746     void EventSetupProvider::setPreferredProviderInfo(PreferredProviderInfo const& iInfo) {
0747       preferredProviderInfo_ = std::make_unique<PreferredProviderInfo>(iInfo);
0748     }
0749 
0750     void EventSetupProvider::fillKeys(std::set<EventSetupRecordKey>& keys) const {
0751       for (auto const& recProvider : recordProviders_) {
0752         keys.insert(recProvider->key());
0753       }
0754     }
0755 
0756     ESRecordsToProxyIndices EventSetupProvider::recordsToProxyIndices() const {
0757       ESRecordsToProxyIndices ret(recordKeys_);
0758 
0759       unsigned int index = 0;
0760       for (const auto& provider : recordProviders_) {
0761         index = ret.dataKeysInRecord(
0762             index, provider->key(), provider->registeredDataKeys(), provider->componentsForRegisteredDataKeys());
0763       }
0764 
0765       return ret;
0766     }
0767 
0768     //
0769     // static member functions
0770     //
0771     void EventSetupProvider::logInfoWhenSharing(ParameterSet const& iConfiguration) {
0772       std::string edmtype = iConfiguration.getParameter<std::string>("@module_edm_type");
0773       std::string modtype = iConfiguration.getParameter<std::string>("@module_type");
0774       std::string label = iConfiguration.getParameter<std::string>("@module_label");
0775       edm::LogVerbatim("EventSetupSharing")
0776           << "Sharing " << edmtype << ": class=" << modtype << " label='" << label << "'";
0777     }
0778 
0779   }  // namespace eventsetup
0780 }  // namespace edm