CMS 3D CMS Logo

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