CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/FWCore/Framework/src/EventSetupsController.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     Framework
00004 // Class  :     EventSetupsController
00005 // 
00006 // Implementation:
00007 //     [Notes on implementation]
00008 //
00009 // Original Author:  Chris Jones, W. David Dagenhart
00010 //         Created:  Wed Jan 12 14:30:44 CST 2011
00011 // $Id: EventSetupsController.cc,v 1.4 2012/06/06 15:51:21 wdd Exp $
00012 //
00013 
00014 #include "FWCore/Framework/src/EventSetupsController.h"
00015 #include "FWCore/Framework/interface/DataKey.h"
00016 #include "FWCore/Framework/interface/DataProxy.h"
00017 #include "FWCore/Framework/interface/EventSetupProviderMaker.h"
00018 #include "FWCore/Framework/interface/EventSetupProvider.h"
00019 #include "FWCore/Framework/interface/ParameterSetIDHolder.h"
00020 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00021 #include "FWCore/Utilities/interface/EDMException.h"
00022 
00023 #include <algorithm>
00024 #include <iostream>
00025 
00026 namespace edm {
00027   namespace eventsetup {
00028 
00029     EventSetupsController::EventSetupsController() : mustFinishConfiguration_(true) {
00030     }
00031 
00032     boost::shared_ptr<EventSetupProvider>
00033     EventSetupsController::makeProvider(ParameterSet& iPSet) {
00034 
00035       // Makes an EventSetupProvider
00036       // Also parses the prefer information from ParameterSets and puts
00037       // it in a map that is stored in the EventSetupProvider
00038       boost::shared_ptr<EventSetupProvider> returnValue(makeEventSetupProvider(iPSet, providers_.size()) );
00039 
00040       // Construct the ESProducers and ESSources
00041       // shared_ptrs to them are temporarily stored in this
00042       // EventSetupsController and in the EventSetupProvider
00043       fillEventSetupProvider(*this, *returnValue, iPSet);
00044    
00045       providers_.push_back(returnValue);
00046       return returnValue;
00047     }
00048 
00049     void
00050     EventSetupsController::eventSetupForInstance(IOVSyncValue const& syncValue) {
00051 
00052       if (mustFinishConfiguration_) {
00053         std::for_each(providers_.begin(), providers_.end(), [](boost::shared_ptr<EventSetupProvider> const& esp) {
00054           esp->finishConfiguration();
00055         });
00056         // When the ESSources and ESProducers were constructed a first pass was
00057         // done which attempts to get component sharing between SubProcesses
00058         // correct, but in this pass only the configuration of the components
00059         // being shared are compared. This is not good enough for ESProducers.
00060         // In the following function, all the other components that contribute 
00061         // to the same record and also the records that record depends on are
00062         // also checked. The component sharing is appropriately fixed as necessary.
00063         checkESProducerSharing();
00064         clearComponents();
00065         mustFinishConfiguration_ = false;
00066       }
00067 
00068       std::for_each(providers_.begin(), providers_.end(), [&syncValue](boost::shared_ptr<EventSetupProvider> const& esp) {
00069         esp->eventSetupForInstance(syncValue);
00070       });
00071     }
00072 
00073     void
00074     EventSetupsController::forceCacheClear() const {
00075       std::for_each(providers_.begin(), providers_.end(), [](boost::shared_ptr<EventSetupProvider> const& esp) {
00076         esp->forceCacheClear();
00077       });
00078     }
00079 
00080     boost::shared_ptr<DataProxyProvider>
00081     EventSetupsController::getESProducerAndRegisterProcess(ParameterSet const& pset, unsigned subProcessIndex) {
00082       // Try to find a DataProxyProvider with a matching ParameterSet
00083       auto elements = esproducers_.equal_range(pset.id());
00084       for (auto it = elements.first; it != elements.second; ++it) {
00085         // Untracked parameters must also match, do complete comparison if IDs match
00086         if (isTransientEqual(pset, *it->second.pset())) {
00087           // Register processes with an exact match
00088           it->second.subProcessIndexes().push_back(subProcessIndex);
00089           // Return the DataProxyProvider
00090           return it->second.provider();
00091         }
00092       }
00093       // Could not find it
00094       return boost::shared_ptr<DataProxyProvider>();
00095     }
00096 
00097     void
00098     EventSetupsController::putESProducer(ParameterSet const& pset, boost::shared_ptr<DataProxyProvider> const& component, unsigned subProcessIndex) {
00099       auto newElement = esproducers_.insert(std::pair<ParameterSetID, ESProducerInfo>(pset.id(), 
00100                                                                                       ESProducerInfo(&pset, component)));
00101       // Register processes with an exact match
00102       newElement->second.subProcessIndexes().push_back(subProcessIndex);
00103     }
00104 
00105     boost::shared_ptr<EventSetupRecordIntervalFinder>
00106     EventSetupsController::getESSourceAndRegisterProcess(ParameterSet const& pset, unsigned subProcessIndex) {
00107       // Try to find a EventSetupRecordIntervalFinder with a matching ParameterSet
00108       auto elements = essources_.equal_range(pset.id());
00109       for (auto it = elements.first; it != elements.second; ++it) {
00110         // Untracked parameters must also match, do complete comparison if IDs match
00111         if (isTransientEqual(pset, *it->second.pset())) {
00112           // Register processes with an exact match
00113           it->second.subProcessIndexes().push_back(subProcessIndex);
00114           // Return the EventSetupRecordIntervalFinder
00115           return it->second.finder();
00116         }
00117       }
00118       // Could not find it
00119       return boost::shared_ptr<EventSetupRecordIntervalFinder>();
00120     }
00121 
00122     void
00123     EventSetupsController::putESSource(ParameterSet const& pset, boost::shared_ptr<EventSetupRecordIntervalFinder> const& component, unsigned subProcessIndex) {
00124       auto newElement = essources_.insert(std::pair<ParameterSetID, ESSourceInfo>(pset.id(), 
00125                                                                                   ESSourceInfo(&pset, component)));
00126       // Register processes with an exact match
00127       newElement->second.subProcessIndexes().push_back(subProcessIndex);
00128     }
00129 
00130     void
00131     EventSetupsController::clearComponents() {
00132       esproducers_.clear();
00133       essources_.clear();
00134     }
00135 
00136     void
00137     EventSetupsController::lookForMatches(ParameterSetID const& psetID,
00138                                           unsigned subProcessIndex,
00139                                           unsigned precedingProcessIndex,
00140                                           bool& firstProcessWithThisPSet,
00141                                           bool& precedingHasMatchingPSet) const {
00142 
00143       auto elements = esproducers_.equal_range(psetID);
00144       for (auto it = elements.first; it != elements.second; ++it) {
00145 
00146         std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
00147 
00148         auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
00149         if (iFound == subProcessIndexes.end()) {
00150           continue;
00151         }
00152 
00153         if (iFound == subProcessIndexes.begin()) {
00154           firstProcessWithThisPSet = true;
00155           precedingHasMatchingPSet = false;      
00156         } else {
00157           auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
00158           if (iFoundPreceding == iFound) {
00159             firstProcessWithThisPSet = false;
00160             precedingHasMatchingPSet = false;
00161           } else {
00162             firstProcessWithThisPSet = false;
00163             precedingHasMatchingPSet = true;    
00164           }
00165         }
00166         return;
00167       }
00168       throw edm::Exception(edm::errors::LogicError)
00169         << "EventSetupsController::lookForMatches\n"
00170         << "Subprocess index not found. This should never happen\n"
00171         << "Please report this to a Framework Developer\n";   
00172     }
00173 
00174     bool
00175     EventSetupsController::isFirstMatch(ParameterSetID const& psetID,
00176                                         unsigned subProcessIndex,
00177                                         unsigned precedingProcessIndex) const {
00178 
00179       auto elements = esproducers_.equal_range(psetID);
00180       for (auto it = elements.first; it != elements.second; ++it) {
00181 
00182         std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
00183 
00184         auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
00185         if (iFound == subProcessIndexes.end()) {
00186           continue;
00187         }
00188 
00189         auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
00190         if (iFoundPreceding == iFound) {
00191           break;
00192         } else {
00193           return iFoundPreceding == subProcessIndexes.begin();
00194         }
00195       }
00196       throw edm::Exception(edm::errors::LogicError)
00197         << "EventSetupsController::isFirstMatch\n"
00198         << "Subprocess index not found. This should never happen\n"
00199         << "Please report this to a Framework Developer\n";
00200       return false;
00201     }
00202 
00203     bool
00204     EventSetupsController::isLastMatch(ParameterSetID const& psetID,
00205                                        unsigned subProcessIndex,
00206                                        unsigned precedingProcessIndex) const {
00207 
00208       auto elements = esproducers_.equal_range(psetID);
00209       for (auto it = elements.first; it != elements.second; ++it) {
00210 
00211         std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
00212 
00213         auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
00214         if (iFound == subProcessIndexes.end()) {
00215           continue;
00216         }
00217 
00218         auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
00219         if (iFoundPreceding == iFound) {
00220           break;
00221         } else {
00222           return (++iFoundPreceding) == iFound;
00223         }
00224       }
00225       throw edm::Exception(edm::errors::LogicError)
00226         << "EventSetupsController::isLastMatch\n"
00227         << "Subprocess index not found. This should never happen\n"
00228         << "Please report this to a Framework Developer\n";
00229       return false;
00230     }
00231 
00232     bool
00233     EventSetupsController::isMatchingESSource(ParameterSetID const& psetID,
00234                                               unsigned subProcessIndex,
00235                                               unsigned precedingProcessIndex) const {
00236       auto elements = essources_.equal_range(psetID);
00237       for (auto it = elements.first; it != elements.second; ++it) {
00238 
00239         std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
00240 
00241         auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
00242         if (iFound == subProcessIndexes.end()) {
00243           continue;
00244         }
00245 
00246         auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
00247         if (iFoundPreceding == iFound) {
00248           return false;
00249         } else {
00250           return true;    
00251         }
00252       }
00253       throw edm::Exception(edm::errors::LogicError)
00254         << "EventSetupsController::lookForMatchingESSource\n"
00255         << "Subprocess index not found. This should never happen\n"
00256         << "Please report this to a Framework Developer\n";
00257       return false;
00258     }
00259 
00260     bool
00261     EventSetupsController::isMatchingESProducer(ParameterSetID const& psetID,
00262                                                 unsigned subProcessIndex,
00263                                                 unsigned precedingProcessIndex) const {
00264       auto elements = esproducers_.equal_range(psetID);
00265       for (auto it = elements.first; it != elements.second; ++it) {
00266 
00267         std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
00268 
00269         auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
00270         if (iFound == subProcessIndexes.end()) {
00271           continue;
00272         }
00273 
00274         auto iFoundPreceding = std::find(subProcessIndexes.begin(), iFound, precedingProcessIndex);
00275         if (iFoundPreceding == iFound) {
00276           return false;
00277         } else {
00278           return true;    
00279         }
00280       }
00281       throw edm::Exception(edm::errors::LogicError)
00282         << "EventSetupsController::lookForMatchingESSource\n"
00283         << "Subprocess index not found. This should never happen\n"
00284         << "Please report this to a Framework Developer\n";
00285       return false;
00286     }
00287 
00288     ParameterSet const*
00289     EventSetupsController::getESProducerPSet(ParameterSetID const& psetID,
00290                                              unsigned subProcessIndex) const {
00291    
00292       auto elements = esproducers_.equal_range(psetID);
00293       for (auto it = elements.first; it != elements.second; ++it) {
00294 
00295         std::vector<unsigned> const& subProcessIndexes = it->second.subProcessIndexes();
00296 
00297         auto iFound = std::find(subProcessIndexes.begin(), subProcessIndexes.end(), subProcessIndex);
00298         if (iFound == subProcessIndexes.end()) {
00299           continue;
00300         }
00301         return it->second.pset();
00302       }
00303       throw edm::Exception(edm::errors::LogicError)
00304         << "EventSetupsController::getESProducerPSet\n"
00305         << "Subprocess index not found. This should never happen\n"
00306         << "Please report this to a Framework Developer\n";
00307       return 0;
00308     }
00309 
00310     void
00311     EventSetupsController::checkESProducerSharing() {
00312 
00313       // Loop over SubProcesses, skip the top level process.
00314       auto esProvider = providers_.begin();
00315       auto esProviderEnd = providers_.end();
00316       if (esProvider != esProviderEnd) ++esProvider;
00317       for ( ; esProvider != esProviderEnd; ++esProvider) {
00318 
00319         // An element is added to this set for each ESProducer
00320         // when we have determined which preceding process
00321         // this process can share that ESProducer with or
00322         // we have determined that it cannot be shared with
00323         // any preceding process.
00324         // Note the earliest possible preceding process
00325         // will be the one selected if there is more than one.
00326         std::set<ParameterSetIDHolder> sharingCheckDone;
00327 
00328         // This will hold an entry for DataProxy's that are
00329         // referenced by an EventSetupRecord in this SubProcess.
00330         // But only for DataProxy's that are associated with
00331         // an ESProducer (not the ones associated with ESSource's
00332         // or EDLooper's)
00333         std::map<EventSetupRecordKey, std::vector<ComponentDescription const*> > referencedESProducers;
00334 
00335         // For each EventSetupProvider from a SubProcess, loop over the
00336         // EventSetupProviders from the preceding processes (the first
00337         // preceding process will be the top level process and the others
00338         // SubProcess's)
00339         for (auto precedingESProvider = providers_.begin();
00340              precedingESProvider != esProvider;
00341              ++precedingESProvider) {
00342 
00343           (*esProvider)->checkESProducerSharing(**precedingESProvider, sharingCheckDone, referencedESProducers, *this);
00344         }
00345 
00346         (*esProvider)->resetRecordToProxyPointers();
00347       }
00348       esProvider = providers_.begin();
00349       for ( ; esProvider != esProviderEnd; ++esProvider) {
00350         (*esProvider)->clearInitializationData();
00351       }
00352     }
00353   }
00354 }