CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_1/src/FWCore/Framework/src/EventSetupProvider.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     Framework
00004 // Module:      EventSetupProvider
00005 // 
00006 // Description: <one line class summary>
00007 //
00008 // Implementation:
00009 //     <Notes on implementation>
00010 //
00011 // Author:      Chris Jones
00012 // Created:     Thu Mar 24 16:27:14 EST 2005
00013 //
00014 
00015 // system include files
00016 #include "boost/bind.hpp"
00017 #include <algorithm>
00018 
00019 // user include files
00020 #include "FWCore/Framework/interface/EventSetupProvider.h"
00021 #include "FWCore/Framework/interface/EventSetupRecordProvider.h"
00022 #include "FWCore/Framework/interface/EventSetupRecordProviderFactoryManager.h"
00023 #include "FWCore/Framework/interface/EventSetupRecord.h"
00024 #include "FWCore/Framework/interface/DataProxyProvider.h"
00025 #include "FWCore/Framework/interface/EventSetupRecordIntervalFinder.h"
00026 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00027 #include "FWCore/Utilities/interface/Algorithms.h"
00028 
00029 namespace edm {
00030    namespace eventsetup {
00031 //
00032 // constants, enums and typedefs
00033 //
00034 
00035 //
00036 // static data member definitions
00037 //
00038 
00039 //
00040 // constructors and destructor
00041 //
00042 EventSetupProvider::EventSetupProvider(const PreferredProviderInfo* iInfo) :
00043 eventSetup_(),
00044 providers_(),
00045 mustFinishConfiguration_(true),
00046 preferredProviderInfo_((0!=iInfo) ? (new PreferredProviderInfo(*iInfo)): 0),
00047 finders_(new std::vector<boost::shared_ptr<EventSetupRecordIntervalFinder> >() ),
00048 dataProviders_(new std::vector<boost::shared_ptr<DataProxyProvider> >() )
00049 {
00050 }
00051 
00052 // EventSetupProvider::EventSetupProvider(const EventSetupProvider& rhs)
00053 // {
00054 //    // do actual copying here;
00055 // }
00056 
00057 EventSetupProvider::~EventSetupProvider()
00058 {
00059 }
00060 
00061 //
00062 // assignment operators
00063 //
00064 // const EventSetupProvider& EventSetupProvider::operator=(const EventSetupProvider& rhs)
00065 // {
00066 //   //An exception safe implementation is
00067 //   EventSetupProvider temp(rhs);
00068 //   swap(rhs);
00069 //
00070 //   return *this;
00071 // }
00072 
00073 //
00074 // member functions
00075 //
00076 void 
00077 EventSetupProvider::insert(const EventSetupRecordKey& iKey, std::auto_ptr<EventSetupRecordProvider> iProvider)
00078 {
00079    boost::shared_ptr<EventSetupRecordProvider> temp(iProvider.release());
00080    providers_[iKey] = temp;
00081    //temp->addRecordTo(*this);
00082 }
00083 
00084 void 
00085 EventSetupProvider::add(boost::shared_ptr<DataProxyProvider> iProvider)
00086 {
00087    mustFinishConfiguration_ = true;
00088    assert(&(*iProvider) != 0);
00089    dataProviders_->push_back(iProvider);
00090 }
00091 
00092 
00093 void 
00094 EventSetupProvider::add(boost::shared_ptr<EventSetupRecordIntervalFinder> iFinder)
00095 {
00096    mustFinishConfiguration_ = true;
00097    assert(&(*iFinder) != 0);
00098    finders_->push_back(iFinder);
00099 }
00100 
00101 typedef std::map<EventSetupRecordKey, boost::shared_ptr<EventSetupRecordProvider> > Providers;
00102 typedef std::map<EventSetupRecordKey, EventSetupRecordProvider::DataToPreferredProviderMap> RecordToPreferred;
00104 static
00105 void 
00106 preferEverything(const ComponentDescription& iComponent,
00107                  const Providers& iProviders,
00108                  RecordToPreferred& iReturnValue)
00109 {
00110    //need to get our hands on the actual DataProxyProvider
00111    bool foundProxyProvider = false;
00112    for(Providers::const_iterator itProvider = iProviders.begin(), itProviderEnd = iProviders.end();
00113        itProvider!= itProviderEnd;
00114        ++itProvider) {
00115       std::set<ComponentDescription> components = itProvider->second->proxyProviderDescriptions();
00116       if(components.find(iComponent)!= components.end()) {
00117          boost::shared_ptr<DataProxyProvider> proxyProv = 
00118          itProvider->second->proxyProvider(*(components.find(iComponent)));
00119          assert(proxyProv.get());
00120          
00121          std::set<EventSetupRecordKey> records = proxyProv->usingRecords();
00122          for(std::set<EventSetupRecordKey>::iterator itRecord = records.begin(),
00123              itRecordEnd = records.end();
00124              itRecord != itRecordEnd;
00125              ++itRecord){
00126             const DataProxyProvider::KeyedProxies& keyedProxies = proxyProv->keyedProxies(*itRecord);
00127             if(!keyedProxies.empty()){
00128                //add them to our output
00129                EventSetupRecordProvider::DataToPreferredProviderMap& dataToProviderMap =
00130                iReturnValue[*itRecord];
00131                
00132                for(DataProxyProvider::KeyedProxies::const_iterator itProxy = keyedProxies.begin(),
00133                    itProxyEnd = keyedProxies.end();
00134                    itProxy != itProxyEnd;
00135                    ++itProxy) {
00136                   EventSetupRecordProvider::DataToPreferredProviderMap::iterator itFind =
00137                   dataToProviderMap.find(itProxy->first);
00138                   if(itFind != dataToProviderMap.end()){
00139                      throw cms::Exception("ESPreferConflict") <<"Two providers have been set to be preferred for\n"
00140                      <<itProxy->first.type().name()<<" \""<<itProxy->first.name().value()<<"\""
00141                      <<"\n the providers are "
00142                      <<"\n 1) type="<<itFind->second.type_<<" label=\""<<itFind->second.label_<<"\""
00143                      <<"\n 2) type="<<iComponent.type_<<" label=\""<<iComponent.label_<<"\""
00144                      <<"\nPlease modify configuration so only one is preferred";
00145                   }
00146                   dataToProviderMap.insert(std::make_pair(itProxy->first,iComponent));
00147                }
00148             }
00149          }
00150          foundProxyProvider=true;
00151          break;
00152       }
00153    }
00154    if(!foundProxyProvider) {
00155       throw cms::Exception("ESPreferNoProvider")<<"Could not make type=\""<<iComponent.type_
00156       <<"\" label=\""<<iComponent.label_<<"\" a preferred Provider."<<
00157       "\n  Please check spelling of name, or that it was loaded into the job.";
00158    }
00159 }
00160 static
00161 RecordToPreferred determinePreferred(const EventSetupProvider::PreferredProviderInfo* iInfo, 
00162                                      const Providers& iProviders)
00163 {
00164    using namespace edm::eventsetup;
00165    RecordToPreferred returnValue;
00166    if(0 != iInfo){
00167       for(EventSetupProvider::PreferredProviderInfo::const_iterator itInfo = iInfo->begin(),
00168           itInfoEnd = iInfo->end();
00169           itInfo != itInfoEnd;
00170           ++itInfo) {
00171          if(itInfo->second.empty()) {
00172             //want everything
00173             preferEverything(itInfo->first, iProviders, returnValue);
00174          } else {
00175             for(EventSetupProvider::RecordToDataMap::const_iterator itRecData = itInfo->second.begin(),
00176                 itRecDataEnd = itInfo->second.end();
00177                 itRecData != itRecDataEnd;
00178                 ++itRecData) {
00179                std::string recordName= itRecData->first;
00180                EventSetupRecordKey recordKey(eventsetup::EventSetupRecordKey::TypeTag::findType(recordName));
00181                if(recordKey.type() == eventsetup::EventSetupRecordKey::TypeTag()) {
00182                   throw cms::Exception("ESPreferUnknownRecord") <<"Unknown record \""<<recordName
00183                   <<"\" used in es_prefer statement for type="
00184                   <<itInfo->first.type_<<" label=\""<<itInfo->first.label_
00185                   <<"\"\n Please check spelling.";
00186                   //record not found
00187                }
00188                //See if the ProxyProvider provides something for this Record
00189                Providers::const_iterator itRecordProvider = iProviders.find(recordKey);
00190                assert(itRecordProvider != iProviders.end());
00191                
00192                std::set<ComponentDescription> components = itRecordProvider->second->proxyProviderDescriptions();
00193                std::set<ComponentDescription>::iterator itProxyProv = components.find(itInfo->first);
00194                if(itProxyProv == components.end()){
00195                   throw cms::Exception("ESPreferWrongRecord")<<"The type="<<itInfo->first.type_<<" label=\""<<
00196                   itInfo->first.label_<<"\" does not provide data for the Record "<<recordName;
00197                }
00198                //Does it data type exist?
00199                eventsetup::TypeTag datumType = eventsetup::TypeTag::findType(itRecData->second.first);
00200                if(datumType == eventsetup::TypeTag()) {
00201                   //not found
00202                   throw cms::Exception("ESPreferWrongDataType")<<"The es_prefer statement for type="<<itInfo->first.type_<<" label=\""<<
00203                   itInfo->first.label_<<"\" has the unknown data type \""<<itRecData->second.first<<"\""
00204                   <<"\n Please check spelling";
00205                }
00206                eventsetup::DataKey datumKey(datumType, itRecData->second.second.c_str());
00207                
00208                //Does the proxyprovider make this?
00209                boost::shared_ptr<DataProxyProvider> proxyProv = 
00210                   itRecordProvider->second->proxyProvider(*itProxyProv);
00211                const DataProxyProvider::KeyedProxies& keyedProxies = proxyProv->keyedProxies(recordKey);
00212                if(std::find_if(keyedProxies.begin(), keyedProxies.end(), 
00213                                 boost::bind(std::equal_to<DataKey>(), datumKey, boost::bind(&DataProxyProvider::KeyedProxies::value_type::first,_1))) ==
00214                    keyedProxies.end()){
00215                   throw cms::Exception("ESPreferWrongData")<<"The es_prefer statement for type="<<itInfo->first.type_<<" label=\""<<
00216                   itInfo->first.label_<<"\" specifies the data item \n"
00217                   <<"  type=\""<<itRecData->second.first<<"\" label=\""<<itRecData->second.second<<"\""
00218                   <<"  which is not provided.  Please check spelling.";
00219                }
00220                
00221                EventSetupRecordProvider::DataToPreferredProviderMap& dataToProviderMap
00222                   =returnValue[recordKey];
00223                //has another provider already been specified?
00224                if(dataToProviderMap.end() != dataToProviderMap.find(datumKey)) {
00225                   EventSetupRecordProvider::DataToPreferredProviderMap::iterator itFind =
00226                   dataToProviderMap.find(datumKey);
00227                   throw cms::Exception("ESPreferConflict") <<"Two providers have been set to be preferred for\n"
00228                   <<datumKey.type().name()<<" \""<<datumKey.name().value()<<"\""
00229                   <<"\n the providers are "
00230                   <<"\n 1) type="<<itFind->second.type_<<" label=\""<<itFind->second.label_<<"\""
00231                   <<"\n 2) type="<<itProxyProv->type_<<" label=\""<<itProxyProv->label_<<"\""
00232                   <<"\nPlease modify configuration so only one is preferred";
00233                }
00234                dataToProviderMap.insert(std::make_pair(datumKey,*itProxyProv));
00235             }
00236          }
00237       }
00238    }
00239    return returnValue;
00240 }
00241 
00242 void
00243 EventSetupProvider::finishConfiguration()
00244 {   
00245    //we delayed adding finders to the system till here so that everything would be loaded first
00246    for(std::vector<boost::shared_ptr<EventSetupRecordIntervalFinder> >::iterator itFinder=finders_->begin(),
00247        itEnd = finders_->end();
00248        itFinder != itEnd;
00249        ++itFinder) {
00250       typedef std::set<EventSetupRecordKey> Keys;
00251       const Keys recordsUsing = (*itFinder)->findingForRecords();
00252       
00253       for(Keys::const_iterator itKey = recordsUsing.begin(), itKeyEnd = recordsUsing.end();
00254           itKey != itKeyEnd;
00255           ++itKey) {
00256          Providers::iterator itFound = providers_.find(*itKey);
00257          if(providers_.end() == itFound) {
00258             //create a provider for this record
00259             insert(*itKey, EventSetupRecordProviderFactoryManager::instance().makeRecordProvider(*itKey));
00260             itFound = providers_.find(*itKey);
00261          }
00262          itFound->second->addFinder(*itFinder);
00263       }      
00264    }
00265    //we've transfered our ownership so this is no longer needed
00266    finders_.reset();
00267    
00268    //Now handle providers since sources can also be finders and the sources can delay registering
00269    // their Records and therefore could delay setting up their Proxies
00270    typedef std::set<EventSetupRecordKey> Keys;
00271    for(std::vector<boost::shared_ptr<DataProxyProvider> >::iterator itProvider=dataProviders_->begin(),
00272        itEnd = dataProviders_->end();
00273        itProvider != itEnd;
00274        ++itProvider) {
00275       
00276       const Keys recordsUsing = (*itProvider)->usingRecords();
00277       
00278       for(Keys::const_iterator itKey = recordsUsing.begin(), itKeyEnd = recordsUsing.end();
00279           itKey != itKeyEnd;
00280           ++itKey) {
00281          Providers::iterator itFound = providers_.find(*itKey);
00282          if(providers_.end() == itFound) {
00283             //create a provider for this record
00284             insert(*itKey, EventSetupRecordProviderFactoryManager::instance().makeRecordProvider(*itKey));
00285             itFound = providers_.find(*itKey);
00286          }
00287          itFound->second->add(*itProvider);
00288       }
00289    }
00290    dataProviders_.reset();
00291    
00292    //used for the case where no preferred Providers have been specified for the Record
00293    static const EventSetupRecordProvider::DataToPreferredProviderMap kEmptyMap;
00294    
00295    RecordToPreferred recordToPreferred = determinePreferred(preferredProviderInfo_.get(),providers_);
00296    //For each Provider, find all the Providers it depends on.  If a dependent Provider
00297    // can not be found pass in an empty list
00298    //CHANGE: now allow for missing Providers
00299    for(Providers::iterator itProvider = providers_.begin(), itProviderEnd = providers_.end();
00300         itProvider != itProviderEnd;
00301         ++itProvider) {
00302       const EventSetupRecordProvider::DataToPreferredProviderMap* preferredInfo = &kEmptyMap;
00303       RecordToPreferred::const_iterator itRecordFound = recordToPreferred.find(itProvider->first);
00304       if(itRecordFound != recordToPreferred.end()) {
00305          preferredInfo = &(itRecordFound->second);
00306       }
00307       //Give it our list of preferred 
00308       itProvider->second->usePreferred(*preferredInfo);
00309       
00310       std::set<EventSetupRecordKey> records = itProvider->second->dependentRecords();
00311       if(records.size() != 0) {
00312          std::string missingRecords;
00313          std::vector<boost::shared_ptr<EventSetupRecordProvider> > depProviders;
00314          depProviders.reserve(records.size());
00315          bool foundAllProviders = true;
00316          for(std::set<EventSetupRecordKey>::iterator itRecord = records.begin(),
00317               itRecordEnd = records.end();
00318               itRecord != itRecordEnd;
00319               ++itRecord) {
00320             Providers::iterator itFound = providers_.find(*itRecord);
00321             if(itFound == providers_.end()) {
00322                foundAllProviders = false;
00323                if(missingRecords.size() == 0) {
00324                  missingRecords = itRecord->name();
00325                } else {
00326                  missingRecords += ", ";
00327                  missingRecords += itRecord->name();
00328                }
00329                //break;
00330             } else {
00331                depProviders.push_back(itFound->second);
00332             }
00333          }
00334          
00335          if(!foundAllProviders) {
00336             edm::LogInfo("EventSetupDependency")<<"The EventSetup record "<<itProvider->second->key().name()
00337             <<" depends on at least one Record \n ("<<missingRecords<<") which is not present in the job."
00338            "\n This may lead to an exception begin thrown during event processing.\n If no exception occurs during the job than it is usually safe to ignore this message.";
00339 
00340             //depProviders.clear();
00341            //NOTE: should provide a warning
00342          }
00343           
00344          itProvider->second->setDependentProviders(depProviders);
00345       }
00346    }
00347    mustFinishConfiguration_ = false;
00348    
00349 }
00350 typedef std::map<EventSetupRecordKey, boost::shared_ptr<EventSetupRecordProvider> > Providers;
00351 typedef Providers::iterator Itr;
00352 static
00353 void
00354 findDependents(const EventSetupRecordKey& iKey,
00355                Itr itBegin,
00356                Itr itEnd,
00357                std::vector<boost::shared_ptr<EventSetupRecordProvider> >& oDependents)
00358 {
00359   
00360   for(Itr it = itBegin; it != itEnd; ++it) {
00361     //does it depend on the record in question?
00362     const std::set<EventSetupRecordKey>& deps = it->second->dependentRecords();
00363     if(deps.end() != deps.find(iKey)) {
00364       oDependents.push_back(it->second);
00365       //now see who is dependent on this record since they will be indirectly dependent on iKey
00366       findDependents(it->first, itBegin, itEnd, oDependents);
00367     }
00368   }
00369 }
00370                
00371 void 
00372 EventSetupProvider::resetRecordPlusDependentRecords(const EventSetupRecordKey& iKey)
00373 {
00374   Providers::iterator itFind = providers_.find(iKey);
00375   if(itFind == providers_.end()) {
00376     return;
00377   }
00378 
00379   
00380   std::vector<boost::shared_ptr<EventSetupRecordProvider> > dependents;
00381   findDependents(iKey, providers_.begin(), providers_.end(), dependents);
00382 
00383   dependents.erase(std::unique(dependents.begin(),dependents.end()), dependents.end());
00384   
00385   itFind->second->resetProxies();
00386   for_all(dependents,
00387                 boost::bind(&EventSetupRecordProvider::resetProxies,
00388                             _1));
00389 }
00390 
00391 void 
00392 EventSetupProvider::forceCacheClear()
00393 {
00394    for(Providers::iterator it=providers_.begin(), itEnd = providers_.end();
00395        it != itEnd;
00396        ++it) {
00397       it->second->resetProxies();
00398    }
00399 }
00400 
00401       
00402 void 
00403 EventSetupProvider::addRecordToEventSetup(EventSetupRecord& iRecord) {
00404    iRecord.setEventSetup(&eventSetup_);
00405    eventSetup_.add(iRecord);
00406 }
00407       
00408 //
00409 // const member functions
00410 //
00411 EventSetup const&
00412 EventSetupProvider::eventSetupForInstance(const IOVSyncValue& iValue)
00413 {
00414    eventSetup_.setIOVSyncValue(iValue);
00415 
00416    eventSetup_.clear();
00417    if(mustFinishConfiguration_) {
00418       const_cast<EventSetupProvider*>(this)->finishConfiguration();
00419    }
00420 
00421    for(Providers::iterator itProvider = providers_.begin(), itProviderEnd = providers_.end();
00422         itProvider != itProviderEnd;
00423         ++itProvider) {
00424       itProvider->second->addRecordToIfValid(*this, iValue);
00425    }
00426    
00427    return eventSetup_;
00428 
00429    
00430 }
00431 namespace {
00432    struct InsertAll : public std::unary_function< const std::set<ComponentDescription>&, void>{
00433       
00434       typedef std::set<ComponentDescription> Set;
00435       Set* container_;
00436       InsertAll(Set& iSet) : container_(&iSet) {}
00437       void operator()(const Set& iSet) {
00438          container_->insert(iSet.begin(), iSet.end());
00439       }
00440    };
00441 }
00442 std::set<ComponentDescription> 
00443 EventSetupProvider::proxyProviderDescriptions() const
00444 {
00445    using boost::bind;
00446    typedef std::set<ComponentDescription> Set;
00447    Set descriptions;
00448 
00449    for_all(providers_,
00450                  bind(InsertAll(descriptions),
00451                       bind(&EventSetupRecordProvider::proxyProviderDescriptions,
00452                            bind(&Providers::value_type::second,_1))));
00453    if(dataProviders_.get()) {
00454       for(std::vector<boost::shared_ptr<DataProxyProvider> >::const_iterator it = dataProviders_->begin(),
00455           itEnd = dataProviders_->end();
00456           it != itEnd;
00457           ++it) {
00458          descriptions.insert((*it)->description());
00459       }
00460          
00461    }
00462                        
00463    return descriptions;
00464 }
00465 
00466 //
00467 // static member functions
00468 //
00469    }
00470 }