Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-06-17 01:30:26

0001 // -*- C++ -*-
0002 //
0003 // Package:     ServiceRegistry
0004 // Class  :     ServicesManager
0005 //
0006 // Implementation:
0007 //     <Notes on implementation>
0008 //
0009 // Original Author:  Chris Jones
0010 //         Created:  Mon Sep  5 13:33:19 EDT 2005
0011 //
0012 
0013 // user include files
0014 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0015 
0016 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0017 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0018 #include "FWCore/ParameterSet/interface/ParameterSetDescriptionFillerBase.h"
0019 #include "FWCore/ParameterSet/interface/ParameterSetDescriptionFillerPluginFactory.h"
0020 
0021 #include "FWCore/ServiceRegistry/interface/ServicePluginFactory.h"
0022 #include "FWCore/ServiceRegistry/interface/ServiceRegistry.h"
0023 #include "FWCore/ServiceRegistry/interface/ServiceToken.h"
0024 #include "FWCore/ServiceRegistry/interface/ServicesManager.h"
0025 
0026 #include "FWCore/Utilities/interface/ConvertException.h"
0027 #include "FWCore/Utilities/interface/Exception.h"
0028 #include "FWCore/Utilities/interface/TypeDemangler.h"
0029 
0030 // system include files
0031 #include <set>
0032 #include <string>
0033 #include <exception>
0034 #include <sstream>
0035 
0036 //
0037 // constants, enums and typedefs
0038 //
0039 
0040 namespace edm {
0041   namespace serviceregistry {
0042 
0043     ServicesManager::MakerHolder::MakerHolder(std::shared_ptr<ServiceMakerBase> iMaker,
0044                                               ParameterSet& iPSet,
0045                                               ActivityRegistry& iRegistry)
0046         : maker_(iMaker), pset_(&iPSet), registry_(&iRegistry), wasAdded_(false) {}
0047 
0048     bool ServicesManager::MakerHolder::add(ServicesManager& oManager) const {
0049       if (!wasAdded_) {
0050         wasAdded_ = maker_->make(*pset_, *registry_, oManager);
0051         if (wasAdded_ && maker_->saveConfiguration()) {
0052           pset_->addUntrackedParameter("@save_config", true);
0053         }
0054       }
0055       return wasAdded_;
0056     }
0057 
0058     //
0059     // static data member definitions
0060     //
0061 
0062     //
0063     // constructors and destructor
0064     //
0065     ServicesManager::ServicesManager(std::vector<ParameterSet>& iConfiguration) : type2Maker_(new Type2Maker) {
0066       //First create the list of makers
0067       fillListOfMakers(iConfiguration);
0068 
0069       createServices();
0070     }
0071 
0072     ServicesManager::ServicesManager(ServiceToken iToken,
0073                                      ServiceLegacy iLegacy,
0074                                      std::vector<ParameterSet>& iConfiguration)
0075         : associatedManager_(iToken.manager_), type2Maker_(new Type2Maker) {
0076       fillListOfMakers(iConfiguration);
0077 
0078       //find overlaps between services in iToken and iConfiguration
0079       typedef std::set<TypeIDBase> TypeSet;
0080       TypeSet configTypes;
0081       for (Type2Maker::iterator itType = type2Maker_->begin(), itTypeEnd = type2Maker_->end(); itType != itTypeEnd;
0082            ++itType) {
0083         configTypes.insert(itType->first);
0084       }
0085 
0086       TypeSet tokenTypes;
0087       if (nullptr != iToken.manager_.get()) {
0088         for (Type2Service::iterator itType = iToken.manager_->type2Service_.begin(),
0089                                     itTypeEnd = iToken.manager_->type2Service_.end();
0090              itType != itTypeEnd;
0091              ++itType) {
0092           tokenTypes.insert(itType->first);
0093         }
0094 
0095         typedef std::set<TypeIDBase> IntersectionType;
0096         IntersectionType intersection;
0097         std::set_intersection(configTypes.begin(),
0098                               configTypes.end(),
0099                               tokenTypes.begin(),
0100                               tokenTypes.end(),
0101                               inserter(intersection, intersection.end()));
0102 
0103         switch (iLegacy) {
0104           case kOverlapIsError:
0105             if (!intersection.empty()) {
0106               throw Exception(errors::Configuration, "Service")
0107                   << "the Service "
0108                   << (*type2Maker_)
0109                          .find(*(intersection.begin()))
0110                          ->second.pset_->getParameter<std::string>("@service_type")
0111                   << " already has an instance of that type of Service";
0112             } else {
0113               //get all the services from Token
0114               type2Service_ = iToken.manager_->type2Service_;
0115             }
0116             break;
0117           case kTokenOverrides:
0118             //get all the services from Token
0119             type2Service_ = iToken.manager_->type2Service_;
0120 
0121             //remove from type2Maker the overlapping services so we never try to make them
0122             for (IntersectionType::iterator itType = intersection.begin(), itTypeEnd = intersection.end();
0123                  itType != itTypeEnd;
0124                  ++itType) {
0125               Type2Maker::iterator itFound = type2Maker_->find(*itType);
0126               //HLT needs it such that even if a service isn't created we store its PSet if needed
0127               if (itFound->second.maker_->saveConfiguration()) {
0128                 itFound->second.pset_->addUntrackedParameter("@save_config", true);
0129               }
0130               type2Maker_->erase(itFound);
0131             }
0132             break;
0133         }
0134         //make sure our signals are propagated to our 'inherited' Services
0135         registry_.copySlotsFrom(associatedManager_->registry_);
0136       }
0137       createServices();
0138     }
0139 
0140     // ServicesManager::ServicesManager(ServicesManager const& rhs) {
0141     //    // do actual copying here;
0142     // }
0143 
0144     ServicesManager::~ServicesManager() {
0145       // Force the Service destructors to execute in the reverse order of construction.
0146       // Note that services passed in by a token are not included in this loop and
0147       // do not get destroyed until the ServicesManager object that created them is destroyed
0148       // which occurs after the body of this destructor is executed (the correct order).
0149       // Services directly passed in by a put and not created in the constructor
0150       // may or not be detroyed in the desired order because this class does not control
0151       // their creation (as I'm writing this comment everything in a standard cmsRun
0152       // executable is destroyed in the desired order).
0153       for (std::vector<TypeIDBase>::const_reverse_iterator idIter = actualCreationOrder_.rbegin(),
0154                                                            idEnd = actualCreationOrder_.rend();
0155            idIter != idEnd;
0156            ++idIter) {
0157         Type2Service::iterator itService = type2Service_.find(*idIter);
0158 
0159         if (itService != type2Service_.end()) {
0160           // This will cause the Service's destruction if
0161           // there are no other shared pointers around
0162           itService->second.reset();
0163         }
0164       }
0165     }
0166 
0167     //
0168     // assignment operators
0169     //
0170     // ServicesManager const& ServicesManager::operator=(ServicesManager const& rhs) {
0171     //   //An exception safe implementation is
0172     //   ServicesManager temp(rhs);
0173     //   swap(rhs);
0174     //
0175     //   return *this;
0176     // }
0177 
0178     //
0179     // member functions
0180     //
0181     void ServicesManager::connect(ActivityRegistry& iOther) { registry_.connect(iOther); }
0182 
0183     void ServicesManager::connectTo(ActivityRegistry& iOther) { iOther.connect(registry_); }
0184 
0185     void ServicesManager::copySlotsFrom(ActivityRegistry& iOther) { registry_.copySlotsFrom(iOther); }
0186 
0187     void ServicesManager::copySlotsTo(ActivityRegistry& iOther) { iOther.copySlotsFrom(registry_); }
0188 
0189     void ServicesManager::fillListOfMakers(std::vector<ParameterSet>& iConfiguration) {
0190       for (std::vector<ParameterSet>::iterator itParam = iConfiguration.begin(), itParamEnd = iConfiguration.end();
0191            itParam != itParamEnd;
0192            ++itParam) {
0193         std::shared_ptr<ServiceMakerBase> base(
0194             ServicePluginFactory::get()->create(itParam->getParameter<std::string>("@service_type")));
0195 
0196         if (nullptr == base.get()) {
0197           throw Exception(errors::Configuration, "Service")
0198               << "could not find a service named " << itParam->getParameter<std::string>("@service_type")
0199               << ". Please check spelling.";
0200         }
0201         Type2Maker::iterator itFound = type2Maker_->find(TypeIDBase(base->serviceType()));
0202         if (itFound != type2Maker_->end()) {
0203           throw Exception(errors::Configuration, "Service")
0204               << " the service " << itParam->getParameter<std::string>("@service_type")
0205               << " provides the same service as " << itFound->second.pset_->getParameter<std::string>("@service_type")
0206               << "\n Please reconfigure job to only use one of these services.";
0207         }
0208         type2Maker_->insert(
0209             Type2Maker::value_type(TypeIDBase(base->serviceType()), MakerHolder(base, *itParam, registry_)));
0210         requestedCreationOrder_.push_back(TypeIDBase(base->serviceType()));
0211       }
0212     }
0213 
0214     namespace {
0215       struct NoOp {
0216         void operator()(ServicesManager*) {}
0217       };
0218     }  // namespace
0219 
0220     void ServicesManager::createServiceFor(MakerHolder const& iMaker) {
0221       std::string serviceType = iMaker.pset_->getParameter<std::string>("@service_type");
0222       std::unique_ptr<ParameterSetDescriptionFillerBase> filler(
0223           ParameterSetDescriptionFillerPluginFactory::get()->create(serviceType));
0224       ConfigurationDescriptions descriptions(filler->baseType(), serviceType);
0225       filler->fill(descriptions);
0226 
0227       try {
0228         convertException::wrap([&]() { descriptions.validate(*(iMaker.pset_), serviceType); });
0229       } catch (cms::Exception& iException) {
0230         std::ostringstream ost;
0231         ost << "Validating configuration of service of type " << serviceType;
0232         iException.addContext(ost.str());
0233         throw;
0234       }
0235       try {
0236         convertException::wrap([&]() {
0237           // This creates the service
0238           iMaker.add(*this);
0239         });
0240       } catch (cms::Exception& iException) {
0241         std::ostringstream ost;
0242         ost << "Constructing service of type " << serviceType;
0243         iException.addContext(ost.str());
0244         throw;
0245       }
0246     }
0247 
0248     void ServicesManager::createServices() {
0249       //create a shared_ptr of 'this' that will not delete us
0250       std::shared_ptr<ServicesManager> shareThis(this, NoOp());
0251 
0252       ServiceToken token(shareThis);
0253 
0254       //Now make our services to ones obtained via ServiceRegistry
0255       // when this goes out of scope, it will revert back to the previous Service set
0256       ServiceRegistry::Operate operate(token);
0257 
0258       //Now, make each Service.  If a service depends on a service that has yet to be
0259       // created, that other service will automatically be made
0260 
0261       for (std::vector<TypeIDBase>::const_iterator idIter = requestedCreationOrder_.begin(),
0262                                                    idEnd = requestedCreationOrder_.end();
0263            idIter != idEnd;
0264            ++idIter) {
0265         Type2Maker::iterator itMaker = type2Maker_->find(*idIter);
0266 
0267         // Check to make sure this maker is still there.  They are deleted
0268         // sometimes and that is OK.
0269         if (itMaker != type2Maker_->end()) {
0270           createServiceFor(itMaker->second);
0271         }
0272       }
0273       //No longer need the makers
0274       type2Maker_ = nullptr;  // propagate_const<T> has no reset() function
0275     }
0276     //
0277     // const member functions
0278     //
0279 
0280     //
0281     // static member functions
0282     //
0283   }  // namespace serviceregistry
0284 }  // namespace edm