CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/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(typeDemangle(itType->name()));
00152                        LogInfo("Configuration") << "Warning: You have reconfigured service\n"
00153                                  <<  "'" << type << "' in a subprocess.\n"
00154                                  << "This service has already been configured.\n"
00155                                  << "This particular service may not be reconfigured in a subprocess.\n"
00156                                  << "The reconfiguration will be ignored.\n";
00157                        type2Maker_->erase(itFound);
00158                      } else {
00159                        // This is not a process wide service, so the configuration overrides the token.
00160                        type2Service_.erase(type2Service_.find(*itType));
00161                      }
00162                   }
00163                   break;
00164             }
00165             //make sure our signals are propagated to our 'inherited' Services
00166             if (associate) registry_.copySlotsFrom(associatedManager_->registry_);
00167          }
00168          createServices();
00169       }
00170 
00171       // ServicesManager::ServicesManager(ServicesManager const& rhs) {
00172       //    // do actual copying here;
00173       // }
00174 
00175       ServicesManager::~ServicesManager() {
00176          // Force the Service destructors to execute in the reverse order of construction.
00177          // Note that services passed in by a token are not included in this loop and
00178          // do not get destroyed until the ServicesManager object that created them is destroyed
00179          // which occurs after the body of this destructor is executed (the correct order).
00180          // Services directly passed in by a put and not created in the constructor
00181          // may or not be detroyed in the desired order because this class does not control
00182          // their creation (as I'm writing this comment everything in a standard cmsRun
00183          // executable is destroyed in the desired order).
00184          for(std::vector<TypeIDBase>::const_reverse_iterator idIter = actualCreationOrder_.rbegin(),
00185                                                              idEnd = actualCreationOrder_.rend();
00186               idIter != idEnd;
00187               ++idIter) {
00188 
00189             Type2Service::iterator itService = type2Service_.find(*idIter);
00190 
00191             if(itService != type2Service_.end()) {
00192 
00193                // This will cause the Service's destruction if
00194                // there are no other shared pointers around
00195                itService->second.reset();
00196             }
00197          }
00198       }
00199 
00200       //
00201       // assignment operators
00202       //
00203       // ServicesManager const& ServicesManager::operator=(ServicesManager const& rhs) {
00204       //   //An exception safe implementation is
00205       //   ServicesManager temp(rhs);
00206       //   swap(rhs);
00207       //
00208       //   return *this;
00209       // }
00210 
00211       //
00212       // member functions
00213       //
00214       void
00215       ServicesManager::connect(ActivityRegistry& iOther) {
00216          registry_.connect(iOther);
00217       }
00218 
00219       void
00220       ServicesManager::connectTo(ActivityRegistry& iOther) {
00221          iOther.connect(registry_);
00222       }
00223 
00224       void
00225       ServicesManager::copySlotsFrom(ActivityRegistry& iOther) {
00226         registry_.copySlotsFrom(iOther);
00227       }
00228 
00229       void
00230       ServicesManager::copySlotsTo(ActivityRegistry& iOther) {
00231         iOther.copySlotsFrom(registry_);
00232       }
00233 
00234       void
00235       ServicesManager::fillListOfMakers(std::vector<ParameterSet>& iConfiguration) {
00236          for(std::vector<ParameterSet>::iterator itParam = iConfiguration.begin(),
00237               itParamEnd = iConfiguration.end();
00238               itParam != itParamEnd;
00239               ++itParam) {
00240             boost::shared_ptr<ServiceMakerBase> base(ServicePluginFactory::get()->create(itParam->getParameter<std::string>("@service_type")));
00241 
00242             if(0 == base.get()) {
00243                throw Exception(errors::Configuration, "Service")
00244                << "could not find a service named "
00245                << itParam->getParameter<std::string>("@service_type")
00246                << ". Please check spelling.";
00247             }
00248             Type2Maker::iterator itFound = type2Maker_->find(TypeIDBase(base->serviceType()));
00249             if(itFound != type2Maker_->end()) {
00250                throw Exception(errors::Configuration, "Service")
00251                << " the service " << itParam->getParameter<std::string>("@service_type")
00252                << " provides the same service as "
00253                << itFound->second.pset_->getParameter<std::string>("@service_type")
00254                << "\n Please reconfigure job to only use one of these services.";
00255             }
00256             type2Maker_->insert(Type2Maker::value_type(TypeIDBase(base->serviceType()),
00257                                                         MakerHolder(base,
00258                                                                     *itParam,
00259                                                                     registry_)));
00260             requestedCreationOrder_.push_back(TypeIDBase(base->serviceType()));
00261          }
00262       }
00263 
00264       namespace {
00265          struct NoOp {
00266             void operator()(ServicesManager*) {}
00267          };
00268       }
00269 
00270       void
00271       ServicesManager::createServices() {
00272 
00273          //create a shared_ptr of 'this' that will not delete us
00274          boost::shared_ptr<ServicesManager> shareThis(this, NoOp());
00275 
00276          ServiceToken token(shareThis);
00277 
00278          //Now make our services to ones obtained via ServiceRegistry
00279          // when this goes out of scope, it will revert back to the previous Service set
00280          ServiceRegistry::Operate operate(token);
00281 
00282          //Now, make each Service.  If a service depends on a service that has yet to be
00283          // created, that other service will automatically be made
00284 
00285          for(std::vector<TypeIDBase>::const_iterator idIter = requestedCreationOrder_.begin(),
00286                                                      idEnd = requestedCreationOrder_.end();
00287               idIter != idEnd;
00288               ++idIter) {
00289            Type2Maker::iterator itMaker = type2Maker_->find(*idIter);
00290 
00291            // Check to make sure this maker is still there.  They are deleted
00292            // sometimes and that is OK.
00293            if(itMaker != type2Maker_->end()) {
00294 
00295              std::string serviceType = itMaker->second.pset_->getParameter<std::string>("@service_type");
00296              std::auto_ptr<ParameterSetDescriptionFillerBase> filler(
00297                ParameterSetDescriptionFillerPluginFactory::get()->create(serviceType));
00298              ConfigurationDescriptions descriptions(filler->baseType());
00299              filler->fill(descriptions);
00300 
00301              try {
00302                try {
00303                  descriptions.validate(*(itMaker->second.pset_), serviceType);
00304                }
00305                catch (cms::Exception& e) { throw; }
00306                catch(std::bad_alloc& bda) { convertException::badAllocToEDM(); }
00307                catch (std::exception& e) { convertException::stdToEDM(e); }
00308                catch(std::string& s) { convertException::stringToEDM(s); }
00309                catch(char const* c) { convertException::charPtrToEDM(c); }
00310                catch (...) { convertException::unknownToEDM(); }
00311              }
00312              catch (cms::Exception & iException) {
00313                std::ostringstream ost;
00314                ost << "Validating configuration of service of type " << serviceType;
00315                iException.addContext(ost.str());
00316                throw;
00317              }
00318              try {
00319                try {
00320                  // This creates the service
00321                  itMaker->second.add(*this);
00322                }
00323                catch (cms::Exception& e) { throw; }
00324                catch(std::bad_alloc& bda) { convertException::badAllocToEDM(); }
00325                catch (std::exception& e) { convertException::stdToEDM(e); }
00326                catch(std::string& s) { convertException::stringToEDM(s); }
00327                catch(char const* c) { convertException::charPtrToEDM(c); }
00328                catch (...) { convertException::unknownToEDM(); }
00329              }
00330              catch (cms::Exception & iException) {
00331                std::ostringstream ost;
00332                ost << "Constructing service of type " << serviceType;
00333                iException.addContext(ost.str());
00334                throw;
00335              }
00336            }
00337          }
00338          //No longer need the makers
00339          type2Maker_.reset();
00340       }
00341       //
00342       // const member functions
00343       //
00344 
00345       //
00346       // static member functions
00347       //
00348    }
00349 }