CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_2_9_HLT1_bphpatch4/src/FWCore/ServiceRegistry/src/ServicesManager.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     ServiceRegistry
00004 // Class  :     ServicesManager
00005 //
00006 // Implementation:
00007 //     <Notes on implementation>
00008 //
00009 // Original Author:  Chris Jones
00010 //         Created:  Mon Sep  5 13:33:19 EDT 2005
00011 //
00012 
00013 // user include files
00014 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00015 
00016 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
00017 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00018 #include "FWCore/ParameterSet/interface/ParameterSetDescriptionFillerBase.h"
00019 #include "FWCore/ParameterSet/interface/ParameterSetDescriptionFillerPluginFactory.h"
00020 
00021 #include "FWCore/ServiceRegistry/interface/ServicePluginFactory.h"
00022 #include "FWCore/ServiceRegistry/interface/ServiceRegistry.h"
00023 #include "FWCore/ServiceRegistry/interface/ServiceToken.h"
00024 #include "FWCore/ServiceRegistry/interface/ServicesManager.h"
00025 
00026 #include "FWCore/Utilities/interface/TypeDemangler.h"
00027 
00028 // system include files
00029 #include <set>
00030 #include <string>
00031 
00032 //
00033 // constants, enums and typedefs
00034 //
00035 
00036 namespace edm {
00037    namespace serviceregistry {
00038 
00039       ServicesManager::MakerHolder::MakerHolder(boost::shared_ptr<ServiceMakerBase> iMaker,
00040                                                 ParameterSet& iPSet,
00041                                                 ActivityRegistry& iRegistry) :
00042       maker_(iMaker),
00043       pset_(&iPSet),
00044       registry_(&iRegistry),
00045       wasAdded_(false) {}
00046 
00047       bool
00048       ServicesManager::MakerHolder::add(ServicesManager& oManager) const {
00049          if(!wasAdded_) {
00050             wasAdded_ = maker_->make(*pset_, *registry_, oManager);
00051             if(wasAdded_ && maker_->saveConfiguration()) {
00052                pset_->addUntrackedParameter("@save_config", true);
00053             }
00054          }
00055          return wasAdded_;
00056       }
00057 
00058       //
00059       // static data member definitions
00060       //
00061 
00062       //
00063       // constructors and destructor
00064       //
00065       ServicesManager::ServicesManager(std::vector<ParameterSet>& iConfiguration) :
00066       type2Maker_(new Type2Maker) {
00067          //First create the list of makers
00068          fillListOfMakers(iConfiguration);
00069 
00070          createServices();
00071       }
00072 
00073       ServicesManager::ServicesManager(ServiceToken iToken,
00074                                        ServiceLegacy iLegacy,
00075                                        std::vector<ParameterSet>& iConfiguration,
00076                                        bool associate) :
00077             associatedManager_(associate ? iToken.manager_ : boost::shared_ptr<ServicesManager>()),
00078             type2Maker_(new Type2Maker) {
00079          fillListOfMakers(iConfiguration);
00080 
00081          //find overlaps between services in iToken and iConfiguration
00082          typedef std::set< TypeIDBase> TypeSet;
00083          TypeSet configTypes;
00084          for(Type2Maker::iterator itType = type2Maker_->begin(), itTypeEnd = type2Maker_->end();
00085              itType != itTypeEnd;
00086              ++itType) {
00087             configTypes.insert(itType->first);
00088          }
00089 
00090          TypeSet tokenTypes;
00091          if(0 != iToken.manager_.get()) {
00092             for(Type2Service::iterator itType = iToken.manager_->type2Service_.begin(),
00093                 itTypeEnd = iToken.manager_->type2Service_.end();
00094                 itType != itTypeEnd;
00095                 ++itType) {
00096                tokenTypes.insert(itType->first);
00097             }
00098 
00099             typedef std::set<TypeIDBase> IntersectionType;
00100             IntersectionType intersection;
00101             std::set_intersection(configTypes.begin(), configTypes.end(),
00102                                   tokenTypes.begin(), tokenTypes.end(),
00103                                   inserter(intersection, intersection.end()));
00104 
00105             switch(iLegacy) {
00106                case kOverlapIsError :
00107                   if(!intersection.empty()) {
00108                      throw Exception(errors::Configuration, "Service")
00109                      << "the Service " << (*type2Maker_).find(*(intersection.begin()))->second.pset_->getParameter<std::string>("@service_type")
00110                      << " already has an instance of that type of Service";
00111                   } else {
00112                      //get all the services from Token
00113                      type2Service_ = iToken.manager_->type2Service_;
00114                   }
00115                   break;
00116                case kTokenOverrides :
00117                   //get all the services from Token
00118                   type2Service_ = iToken.manager_->type2Service_;
00119 
00120                   //remove from type2Maker the overlapping services so we never try to make them
00121                   for(IntersectionType::iterator itType = intersection.begin(), itTypeEnd = intersection.end();
00122                       itType != itTypeEnd;
00123                       ++itType) {
00124                      Type2Maker::iterator itFound = type2Maker_->find(*itType);
00125                      //HLT needs it such that even if a service isn't created we store its PSet if needed
00126                      if(itFound->second.maker_->saveConfiguration()) {
00127                         itFound->second.pset_->addUntrackedParameter("@save_config", true);
00128                      }
00129                      type2Maker_->erase(itFound);
00130                   }
00131                   break;
00132                case kConfigurationOverrides:
00133                   //get all the services from the Configuration, except process wide services
00134                   type2Service_ = iToken.manager_->type2Service_;
00135 
00136                   //now remove the ones we do not want
00137                   for(IntersectionType::iterator itType = intersection.begin(), itTypeEnd = intersection.end();
00138                       itType != itTypeEnd;
00139                       ++itType) {
00140                      Type2Maker::iterator itFound = type2Maker_->find(*itType);
00141                      if(itFound->second.maker_->processWideService()) {
00142                        // This is a process wide service, so the token overrides the configuration.
00143                        //HLT needs it such that even if a service isn't created we store its PSet if needed
00144                        if(itFound->second.maker_->saveConfiguration()) {
00145                          itFound->second.pset_->addUntrackedParameter("@save_config", true);
00146                        }
00147                        std::string type;
00148                        typeDemangle(itType->name(), type);
00149                        LogInfo("Configuration") << "Warning: You have reconfigured service\n"
00150                                  <<  "'" << type << "' in a subprocess.\n"
00151                                  << "This service has already been configured.\n"
00152                                  << "This particular service may not be reconfigured in a subprocess.\n"
00153                                  << "The reconfiguration will be ignored.\n";
00154                        type2Maker_->erase(itFound);
00155                      } else {
00156                        // This is not a process wide service, so the configuration overrides the token.
00157                        type2Service_.erase(type2Service_.find(*itType));
00158                      }
00159                   }
00160                   break;
00161             }
00162             //make sure our signals are propagated to our 'inherited' Services
00163             if (associate) registry_.copySlotsFrom(associatedManager_->registry_);
00164          }
00165          createServices();
00166       }
00167 
00168       // ServicesManager::ServicesManager(ServicesManager const& rhs) {
00169       //    // do actual copying here;
00170       // }
00171 
00172       ServicesManager::~ServicesManager() {
00173          // Force the Service destructors to execute in the reverse order of construction.
00174          // Note that services passed in by a token are not included in this loop and
00175          // do not get destroyed until the ServicesManager object that created them is destroyed
00176          // which occurs after the body of this destructor is executed (the correct order).
00177          // Services directly passed in by a put and not created in the constructor
00178          // may or not be detroyed in the desired order because this class does not control
00179          // their creation (as I'm writing this comment everything in a standard cmsRun
00180          // executable is destroyed in the desired order).
00181          for(std::vector<TypeIDBase>::const_reverse_iterator idIter = actualCreationOrder_.rbegin(),
00182                                                              idEnd = actualCreationOrder_.rend();
00183               idIter != idEnd;
00184               ++idIter) {
00185 
00186             Type2Service::iterator itService = type2Service_.find(*idIter);
00187 
00188             if(itService != type2Service_.end()) {
00189 
00190                // This will cause the Service's destruction if
00191                // there are no other shared pointers around
00192                itService->second.reset();
00193             }
00194          }
00195       }
00196 
00197       //
00198       // assignment operators
00199       //
00200       // ServicesManager const& ServicesManager::operator=(ServicesManager const& rhs) {
00201       //   //An exception safe implementation is
00202       //   ServicesManager temp(rhs);
00203       //   swap(rhs);
00204       //
00205       //   return *this;
00206       // }
00207 
00208       //
00209       // member functions
00210       //
00211       void
00212       ServicesManager::connect(ActivityRegistry& iOther) {
00213          registry_.connect(iOther);
00214       }
00215 
00216       void
00217       ServicesManager::connectTo(ActivityRegistry& iOther) {
00218          iOther.connect(registry_);
00219       }
00220 
00221       void
00222       ServicesManager::copySlotsFrom(ActivityRegistry& iOther) {
00223         registry_.copySlotsFrom(iOther);
00224       }
00225 
00226       void
00227       ServicesManager::copySlotsTo(ActivityRegistry& iOther) {
00228         iOther.copySlotsFrom(registry_);
00229       }
00230 
00231       void
00232       ServicesManager::fillListOfMakers(std::vector<ParameterSet>& iConfiguration) {
00233          for(std::vector<ParameterSet>::iterator itParam = iConfiguration.begin(),
00234               itParamEnd = iConfiguration.end();
00235               itParam != itParamEnd;
00236               ++itParam) {
00237             boost::shared_ptr<ServiceMakerBase> base(ServicePluginFactory::get()->create(itParam->getParameter<std::string>("@service_type")));
00238 
00239             if(0 == base.get()) {
00240                throw Exception(errors::Configuration, "Service")
00241                << "could not find a service named "
00242                << itParam->getParameter<std::string>("@service_type")
00243                << ". Please check spelling.";
00244             }
00245             Type2Maker::iterator itFound = type2Maker_->find(TypeIDBase(base->serviceType()));
00246             if(itFound != type2Maker_->end()) {
00247                throw Exception(errors::Configuration, "Service")
00248                << " the service " << itParam->getParameter<std::string>("@service_type")
00249                << " provides the same service as "
00250                << itFound->second.pset_->getParameter<std::string>("@service_type")
00251                << "\n Please reconfigure job to only use one of these services.";
00252             }
00253             type2Maker_->insert(Type2Maker::value_type(TypeIDBase(base->serviceType()),
00254                                                         MakerHolder(base,
00255                                                                     *itParam,
00256                                                                     registry_)));
00257             requestedCreationOrder_.push_back(TypeIDBase(base->serviceType()));
00258          }
00259       }
00260 
00261       namespace {
00262          struct NoOp {
00263             void operator()(ServicesManager*) {}
00264          };
00265       }
00266 
00267       void
00268       ServicesManager::createServices() {
00269 
00270          //create a shared_ptr of 'this' that will not delete us
00271          boost::shared_ptr<ServicesManager> shareThis(this, NoOp());
00272 
00273          ServiceToken token(shareThis);
00274 
00275          //Now make our services to ones obtained via ServiceRegistry
00276          // when this goes out of scope, it will revert back to the previous Service set
00277          ServiceRegistry::Operate operate(token);
00278 
00279          //Now, make each Service.  If a service depends on a service that has yet to be
00280          // created, that other service will automatically be made
00281 
00282          for(std::vector<TypeIDBase>::const_iterator idIter = requestedCreationOrder_.begin(),
00283                                                      idEnd = requestedCreationOrder_.end();
00284               idIter != idEnd;
00285               ++idIter) {
00286            Type2Maker::iterator itMaker = type2Maker_->find(*idIter);
00287 
00288            // Check to make sure this maker is still there.  They are deleted
00289            // sometimes and that is OK.
00290            if(itMaker != type2Maker_->end()) {
00291 
00292              std::string serviceType = itMaker->second.pset_->getParameter<std::string>("@service_type");
00293              std::auto_ptr<ParameterSetDescriptionFillerBase> filler(
00294                ParameterSetDescriptionFillerPluginFactory::get()->create(serviceType));
00295              ConfigurationDescriptions descriptions(filler->baseType());
00296 
00297              try {
00298                filler->fill(descriptions);
00299              }
00300              catch (cms::Exception& iException) {
00301                Exception toThrow(errors::Configuration, "Failed while filling ParameterSetDescriptions.");
00302                toThrow << "\nService plugin name is \"" << serviceType << "\"\n";
00303                toThrow.append(iException);
00304                throw toThrow;
00305              }
00306              try {
00307                descriptions.validate(*(itMaker->second.pset_), serviceType);
00308              }
00309              catch (cms::Exception& iException) {
00310                Exception toThrow(errors::Configuration, "Failed validating service configuration.");
00311                toThrow << "\nService plugin name is \"" << serviceType << "\"\n";
00312                toThrow.append(iException);
00313                throw toThrow;
00314              }
00315              try {
00316                // This creates the service
00317                itMaker->second.add(*this);
00318              }
00319              catch(cms::Exception& iException) {
00320                Exception toThrow(errors::Configuration, "Error occurred while creating ");
00321                toThrow << itMaker->second.pset_->getParameter<std::string>("@service_type") << "\n";
00322                toThrow.append(iException);
00323                throw toThrow;
00324              }
00325            }
00326          }
00327          //No longer need the makers
00328          type2Maker_.reset();
00329       }
00330       //
00331       // const member functions
00332       //
00333 
00334       //
00335       // static member functions
00336       //
00337    }
00338 }