Back to home page

Project CMSSW displayed by LXR

 
 

    


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

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