CMS 3D CMS Logo

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