Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-04-30 22:24:08

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