00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "boost/bind.hpp"
00017 #include <algorithm>
00018
00019
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
00032
00033
00034
00035
00036
00037
00038
00039
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 {
00048 }
00049
00050
00051
00052
00053
00054
00055 EventSetupProvider::~EventSetupProvider()
00056 {
00057 }
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 void
00075 EventSetupProvider::insert(const EventSetupRecordKey& iKey, std::auto_ptr<EventSetupRecordProvider> iProvider)
00076 {
00077 boost::shared_ptr<EventSetupRecordProvider> temp(iProvider.release());
00078 providers_[iKey] = temp;
00079
00080 }
00081
00082 void
00083 EventSetupProvider::add(boost::shared_ptr<DataProxyProvider> iProvider)
00084 {
00085 mustFinishConfiguration_ = true;
00086 assert(&(*iProvider) != 0);
00087 typedef std::set<EventSetupRecordKey> Keys;
00088 const Keys recordsUsing = iProvider->usingRecords();
00089
00090 for(Keys::const_iterator itKey = recordsUsing.begin(), itKeyEnd = recordsUsing.end();
00091 itKey != itKeyEnd;
00092 ++itKey) {
00093 Providers::iterator itFound = providers_.find(*itKey);
00094 if(providers_.end() == itFound) {
00095
00096 insert(*itKey, EventSetupRecordProviderFactoryManager::instance().makeRecordProvider(*itKey));
00097 itFound = providers_.find(*itKey);
00098 }
00099 itFound->second->add(iProvider);
00100 }
00101 }
00102
00103
00104 void
00105 EventSetupProvider::add(boost::shared_ptr<EventSetupRecordIntervalFinder> iFinder)
00106 {
00107 mustFinishConfiguration_ = true;
00108 assert(&(*iFinder) != 0);
00109 finders_->push_back(iFinder);
00110 }
00111
00112 typedef std::map<EventSetupRecordKey, boost::shared_ptr<EventSetupRecordProvider> > Providers;
00113 typedef std::map<EventSetupRecordKey, EventSetupRecordProvider::DataToPreferredProviderMap> RecordToPreferred;
00115 static
00116 void
00117 preferEverything(const ComponentDescription& iComponent,
00118 const Providers& iProviders,
00119 RecordToPreferred& iReturnValue)
00120 {
00121
00122 bool foundProxyProvider = false;
00123 for(Providers::const_iterator itProvider = iProviders.begin(), itProviderEnd = iProviders.end();
00124 itProvider!= itProviderEnd;
00125 ++itProvider) {
00126 std::set<ComponentDescription> components = itProvider->second->proxyProviderDescriptions();
00127 if(components.find(iComponent)!= components.end()) {
00128 boost::shared_ptr<DataProxyProvider> proxyProv =
00129 itProvider->second->proxyProvider(*(components.find(iComponent)));
00130 assert(proxyProv.get());
00131
00132 std::set<EventSetupRecordKey> records = proxyProv->usingRecords();
00133 for(std::set<EventSetupRecordKey>::iterator itRecord = records.begin(),
00134 itRecordEnd = records.end();
00135 itRecord != itRecordEnd;
00136 ++itRecord){
00137 const DataProxyProvider::KeyedProxies& keyedProxies = proxyProv->keyedProxies(*itRecord);
00138 if(!keyedProxies.empty()){
00139
00140 EventSetupRecordProvider::DataToPreferredProviderMap& dataToProviderMap =
00141 iReturnValue[*itRecord];
00142
00143 for(DataProxyProvider::KeyedProxies::const_iterator itProxy = keyedProxies.begin(),
00144 itProxyEnd = keyedProxies.end();
00145 itProxy != itProxyEnd;
00146 ++itProxy) {
00147 EventSetupRecordProvider::DataToPreferredProviderMap::iterator itFind =
00148 dataToProviderMap.find(itProxy->first);
00149 if(itFind != dataToProviderMap.end()){
00150 throw cms::Exception("ESPreferConflict") <<"Two providers have been set to be preferred for\n"
00151 <<itProxy->first.type().name()<<" \""<<itProxy->first.name().value()<<"\""
00152 <<"\n the providers are "
00153 <<"\n 1) type="<<itFind->second.type_<<" label=\""<<itFind->second.label_<<"\""
00154 <<"\n 2) type="<<iComponent.type_<<" label=\""<<iComponent.label_<<"\""
00155 <<"\nPlease modify configuration so only one is preferred";
00156 }
00157 dataToProviderMap.insert(std::make_pair(itProxy->first,iComponent));
00158 }
00159 }
00160 }
00161 foundProxyProvider=true;
00162 break;
00163 }
00164 }
00165 if(!foundProxyProvider) {
00166 throw cms::Exception("ESPreferNoProvider")<<"Could not make type=\""<<iComponent.type_
00167 <<"\" label=\""<<iComponent.label_<<"\" a preferred Provider."<<
00168 "\n Please check spelling of name, or that it was loaded into the job.";
00169 }
00170 }
00171 static
00172 RecordToPreferred determinePreferred(const EventSetupProvider::PreferredProviderInfo* iInfo,
00173 const Providers& iProviders)
00174 {
00175 using namespace edm::eventsetup;
00176 RecordToPreferred returnValue;
00177 if(0 != iInfo){
00178 for(EventSetupProvider::PreferredProviderInfo::const_iterator itInfo = iInfo->begin(),
00179 itInfoEnd = iInfo->end();
00180 itInfo != itInfoEnd;
00181 ++itInfo) {
00182 if(itInfo->second.empty()) {
00183
00184 preferEverything(itInfo->first, iProviders, returnValue);
00185 } else {
00186 for(EventSetupProvider::RecordToDataMap::const_iterator itRecData = itInfo->second.begin(),
00187 itRecDataEnd = itInfo->second.end();
00188 itRecData != itRecDataEnd;
00189 ++itRecData) {
00190 std::string recordName= itRecData->first;
00191 EventSetupRecordKey recordKey(eventsetup::EventSetupRecordKey::TypeTag::findType(recordName));
00192 if(recordKey.type() == eventsetup::EventSetupRecordKey::TypeTag()) {
00193 throw cms::Exception("ESPreferUnknownRecord") <<"Unknown record \""<<recordName
00194 <<"\" used in es_prefer statement for type="
00195 <<itInfo->first.type_<<" label=\""<<itInfo->first.label_
00196 <<"\"\n Please check spelling.";
00197
00198 }
00199
00200 Providers::const_iterator itRecordProvider = iProviders.find(recordKey);
00201 assert(itRecordProvider != iProviders.end());
00202
00203 std::set<ComponentDescription> components = itRecordProvider->second->proxyProviderDescriptions();
00204 std::set<ComponentDescription>::iterator itProxyProv = components.find(itInfo->first);
00205 if(itProxyProv == components.end()){
00206 throw cms::Exception("ESPreferWrongRecord")<<"The type="<<itInfo->first.type_<<" label=\""<<
00207 itInfo->first.label_<<"\" does not provide data for the Record "<<recordName;
00208 }
00209
00210 eventsetup::TypeTag datumType = eventsetup::TypeTag::findType(itRecData->second.first);
00211 if(datumType == eventsetup::TypeTag()) {
00212
00213 throw cms::Exception("ESPreferWrongDataType")<<"The es_prefer statement for type="<<itInfo->first.type_<<" label=\""<<
00214 itInfo->first.label_<<"\" has the unknown data type \""<<itRecData->second.first<<"\""
00215 <<"\n Please check spelling";
00216 }
00217 eventsetup::DataKey datumKey(datumType, itRecData->second.second.c_str());
00218
00219
00220 boost::shared_ptr<DataProxyProvider> proxyProv =
00221 itRecordProvider->second->proxyProvider(*itProxyProv);
00222 const DataProxyProvider::KeyedProxies& keyedProxies = proxyProv->keyedProxies(recordKey);
00223 if(std::find_if(keyedProxies.begin(), keyedProxies.end(),
00224 boost::bind(std::equal_to<DataKey>(), datumKey, boost::bind(&DataProxyProvider::KeyedProxies::value_type::first,_1))) ==
00225 keyedProxies.end()){
00226 throw cms::Exception("ESPreferWrongData")<<"The es_prefer statement for type="<<itInfo->first.type_<<" label=\""<<
00227 itInfo->first.label_<<"\" specifies the data item \n"
00228 <<" type=\""<<itRecData->second.first<<"\" label=\""<<itRecData->second.second<<"\""
00229 <<" which is not provided. Please check spelling.";
00230 }
00231
00232 EventSetupRecordProvider::DataToPreferredProviderMap& dataToProviderMap
00233 =returnValue[recordKey];
00234
00235 if(dataToProviderMap.end() != dataToProviderMap.find(datumKey)) {
00236 EventSetupRecordProvider::DataToPreferredProviderMap::iterator itFind =
00237 dataToProviderMap.find(datumKey);
00238 throw cms::Exception("ESPreferConflict") <<"Two providers have been set to be preferred for\n"
00239 <<datumKey.type().name()<<" \""<<datumKey.name().value()<<"\""
00240 <<"\n the providers are "
00241 <<"\n 1) type="<<itFind->second.type_<<" label=\""<<itFind->second.label_<<"\""
00242 <<"\n 2) type="<<itProxyProv->type_<<" label=\""<<itProxyProv->label_<<"\""
00243 <<"\nPlease modify configuration so only one is preferred";
00244 }
00245 dataToProviderMap.insert(std::make_pair(datumKey,*itProxyProv));
00246 }
00247 }
00248 }
00249 }
00250 return returnValue;
00251 }
00252
00253 void
00254 EventSetupProvider::finishConfiguration()
00255 {
00256
00257 for(std::vector<boost::shared_ptr<EventSetupRecordIntervalFinder> >::iterator itFinder=finders_->begin(),
00258 itEnd = finders_->end();
00259 itFinder != itEnd;
00260 ++itFinder) {
00261 typedef std::set<EventSetupRecordKey> Keys;
00262 const Keys recordsUsing = (*itFinder)->findingForRecords();
00263
00264 for(Keys::const_iterator itKey = recordsUsing.begin(), itKeyEnd = recordsUsing.end();
00265 itKey != itKeyEnd;
00266 ++itKey) {
00267 Providers::iterator itFound = providers_.find(*itKey);
00268 if(providers_.end() == itFound) {
00269
00270 insert(*itKey, EventSetupRecordProviderFactoryManager::instance().makeRecordProvider(*itKey));
00271 itFound = providers_.find(*itKey);
00272 }
00273 itFound->second->addFinder(*itFinder);
00274 }
00275 }
00276
00277 finders_.reset();
00278
00279
00280
00281 static const EventSetupRecordProvider::DataToPreferredProviderMap kEmptyMap;
00282
00283 RecordToPreferred recordToPreferred = determinePreferred(preferredProviderInfo_.get(),providers_);
00284
00285
00286
00287 for(Providers::iterator itProvider = providers_.begin(), itProviderEnd = providers_.end();
00288 itProvider != itProviderEnd;
00289 ++itProvider) {
00290 const EventSetupRecordProvider::DataToPreferredProviderMap* preferredInfo = &kEmptyMap;
00291 RecordToPreferred::const_iterator itRecordFound = recordToPreferred.find(itProvider->first);
00292 if(itRecordFound != recordToPreferred.end()) {
00293 preferredInfo = &(itRecordFound->second);
00294 }
00295
00296 itProvider->second->usePreferred(*preferredInfo);
00297
00298 std::set<EventSetupRecordKey> records = itProvider->second->dependentRecords();
00299 if(records.size() != 0) {
00300 std::string missingRecords;
00301 std::vector<boost::shared_ptr<EventSetupRecordProvider> > depProviders;
00302 depProviders.reserve(records.size());
00303 bool foundAllProviders = true;
00304 for(std::set<EventSetupRecordKey>::iterator itRecord = records.begin(),
00305 itRecordEnd = records.end();
00306 itRecord != itRecordEnd;
00307 ++itRecord) {
00308 Providers::iterator itFound = providers_.find(*itRecord);
00309 if(itFound == providers_.end()) {
00310 foundAllProviders = false;
00311 if(missingRecords.size() == 0) {
00312 missingRecords = itRecord->name();
00313 } else {
00314 missingRecords += ", ";
00315 missingRecords += itRecord->name();
00316 }
00317
00318 } else {
00319 depProviders.push_back(itFound->second);
00320 }
00321 }
00322
00323 if(!foundAllProviders) {
00324 edm::LogInfo("EventSetupDependency")<<"The EventSetup record "<<itProvider->second->key().name()
00325 <<" depends on at least one Record \n ("<<missingRecords<<") which is not present in the job."
00326 "\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.";
00327
00328
00329
00330 }
00331
00332 itProvider->second->setDependentProviders(depProviders);
00333 }
00334 }
00335 mustFinishConfiguration_ = false;
00336
00337 }
00338 typedef std::map<EventSetupRecordKey, boost::shared_ptr<EventSetupRecordProvider> > Providers;
00339 typedef Providers::iterator Itr;
00340 static
00341 void
00342 findDependents(const EventSetupRecordKey& iKey,
00343 Itr itBegin,
00344 Itr itEnd,
00345 std::vector<boost::shared_ptr<EventSetupRecordProvider> >& oDependents)
00346 {
00347
00348 for(Itr it = itBegin; it != itEnd; ++it) {
00349
00350 const std::set<EventSetupRecordKey>& deps = it->second->dependentRecords();
00351 if(deps.end() != deps.find(iKey)) {
00352 oDependents.push_back(it->second);
00353
00354 findDependents(it->first, itBegin, itEnd, oDependents);
00355 }
00356 }
00357 }
00358
00359 void
00360 EventSetupProvider::resetRecordPlusDependentRecords(const EventSetupRecordKey& iKey)
00361 {
00362 Providers::iterator itFind = providers_.find(iKey);
00363 if(itFind == providers_.end()) {
00364 return;
00365 }
00366
00367
00368 std::vector<boost::shared_ptr<EventSetupRecordProvider> > dependents;
00369 findDependents(iKey, providers_.begin(), providers_.end(), dependents);
00370
00371 dependents.erase(std::unique(dependents.begin(),dependents.end()), dependents.end());
00372
00373 itFind->second->resetProxies();
00374 for_all(dependents,
00375 boost::bind(&EventSetupRecordProvider::resetProxies,
00376 _1));
00377 }
00378
00379
00380
00381
00382 EventSetup const&
00383 EventSetupProvider::eventSetupForInstance(const IOVSyncValue& iValue)
00384 {
00385 eventSetup_.setIOVSyncValue(iValue);
00386
00387 eventSetup_.clear();
00388 if(mustFinishConfiguration_) {
00389 const_cast<EventSetupProvider*>(this)->finishConfiguration();
00390 }
00391
00392 for(Providers::iterator itProvider = providers_.begin(), itProviderEnd = providers_.end();
00393 itProvider != itProviderEnd;
00394 ++itProvider) {
00395 itProvider->second->addRecordToIfValid(*this, iValue);
00396 }
00397
00398 return eventSetup_;
00399
00400
00401 }
00402 namespace {
00403 struct InsertAll : public std::unary_function< const std::set<ComponentDescription>&, void>{
00404
00405 typedef std::set<ComponentDescription> Set;
00406 Set* container_;
00407 InsertAll(Set& iSet) : container_(&iSet) {}
00408 void operator()(const Set& iSet) {
00409 container_->insert(iSet.begin(), iSet.end());
00410 }
00411 };
00412 }
00413 std::set<ComponentDescription>
00414 EventSetupProvider::proxyProviderDescriptions() const
00415 {
00416 using boost::bind;
00417 typedef std::set<ComponentDescription> Set;
00418 Set descriptions;
00419
00420 for_all(providers_,
00421 bind(InsertAll(descriptions),
00422 bind(&EventSetupRecordProvider::proxyProviderDescriptions,
00423 bind(&Providers::value_type::second,_1))));
00424
00425 return descriptions;
00426 }
00427
00428
00429
00430
00431 }
00432 }