CMS 3D CMS Logo

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