CMS 3D CMS Logo

ServicesManager.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: ServiceRegistry
4 // Class : ServicesManager
5 //
6 // Implementation:
7 // <Notes on implementation>
8 //
9 // Original Author: Chris Jones
10 // Created: Mon Sep 5 13:33:19 EDT 2005
11 //
12 
13 // user include files
15 
20 
25 
29 
30 // system include files
31 #include <set>
32 #include <string>
33 #include <exception>
34 #include <sstream>
35 
36 //
37 // constants, enums and typedefs
38 //
39 
40 namespace edm {
41  namespace serviceregistry {
42 
43  ServicesManager::MakerHolder::MakerHolder(std::shared_ptr<ServiceMakerBase> iMaker,
44  ParameterSet& iPSet,
45  ActivityRegistry& iRegistry)
46  : maker_(iMaker), pset_(&iPSet), registry_(&iRegistry), wasAdded_(false) {}
47 
49  if (!wasAdded_) {
50  wasAdded_ = maker_->make(*pset_, *registry_, oManager);
51  if (wasAdded_ && maker_->saveConfiguration()) {
52  pset_->addUntrackedParameter("@save_config", true);
53  }
54  }
55  return wasAdded_;
56  }
57 
58  //
59  // static data member definitions
60  //
61 
62  //
63  // constructors and destructor
64  //
65  ServicesManager::ServicesManager(std::vector<ParameterSet>& iConfiguration) : type2Maker_(new Type2Maker) {
66  //First create the list of makers
67  fillListOfMakers(iConfiguration);
68 
70  }
71 
73  ServiceLegacy iLegacy,
74  std::vector<ParameterSet>& iConfiguration,
75  bool associate)
76  : associatedManager_(associate ? iToken.manager_ : std::shared_ptr<ServicesManager>()),
77  type2Maker_(new Type2Maker) {
78  fillListOfMakers(iConfiguration);
79 
80  //find overlaps between services in iToken and iConfiguration
81  typedef std::set<TypeIDBase> TypeSet;
82  TypeSet configTypes;
83  for (Type2Maker::iterator itType = type2Maker_->begin(), itTypeEnd = type2Maker_->end(); itType != itTypeEnd;
84  ++itType) {
85  configTypes.insert(itType->first);
86  }
87 
88  TypeSet tokenTypes;
89  if (nullptr != iToken.manager_.get()) {
90  for (Type2Service::iterator itType = iToken.manager_->type2Service_.begin(),
91  itTypeEnd = iToken.manager_->type2Service_.end();
92  itType != itTypeEnd;
93  ++itType) {
94  tokenTypes.insert(itType->first);
95  }
96 
97  typedef std::set<TypeIDBase> IntersectionType;
98  IntersectionType intersection;
99  std::set_intersection(configTypes.begin(),
100  configTypes.end(),
101  tokenTypes.begin(),
102  tokenTypes.end(),
103  inserter(intersection, intersection.end()));
104 
105  switch (iLegacy) {
106  case kOverlapIsError:
107  if (!intersection.empty()) {
108  throw Exception(errors::Configuration, "Service")
109  << "the Service "
110  << (*type2Maker_)
111  .find(*(intersection.begin()))
112  ->second.pset_->getParameter<std::string>("@service_type")
113  << " already has an instance of that type of Service";
114  } else {
115  //get all the services from Token
116  type2Service_ = iToken.manager_->type2Service_;
117  }
118  break;
119  case kTokenOverrides:
120  //get all the services from Token
121  type2Service_ = iToken.manager_->type2Service_;
122 
123  //remove from type2Maker the overlapping services so we never try to make them
124  for (IntersectionType::iterator itType = intersection.begin(), itTypeEnd = intersection.end();
125  itType != itTypeEnd;
126  ++itType) {
127  Type2Maker::iterator itFound = type2Maker_->find(*itType);
128  //HLT needs it such that even if a service isn't created we store its PSet if needed
129  if (itFound->second.maker_->saveConfiguration()) {
130  itFound->second.pset_->addUntrackedParameter("@save_config", true);
131  }
132  type2Maker_->erase(itFound);
133  }
134  break;
136  //get all the services from the Configuration, except process wide services
137  type2Service_ = iToken.manager_->type2Service_;
138 
139  //now remove the ones we do not want
140  for (IntersectionType::iterator itType = intersection.begin(), itTypeEnd = intersection.end();
141  itType != itTypeEnd;
142  ++itType) {
143  Type2Maker::iterator itFound = type2Maker_->find(*itType);
144  if (itFound->second.maker_->processWideService()) {
145  // This is a process wide service, so the token overrides the configuration.
146  //HLT needs it such that even if a service isn't created we store its PSet if needed
147  if (itFound->second.maker_->saveConfiguration()) {
148  itFound->second.pset_->addUntrackedParameter("@save_config", true);
149  }
150  std::string type(typeDemangle(itType->name()));
151  LogInfo("Configuration") << "Warning: You have reconfigured service\n"
152  << "'" << type << "' in a subprocess.\n"
153  << "This service has already been configured.\n"
154  << "This particular service may not be reconfigured in a subprocess.\n"
155  << "The reconfiguration will be ignored.\n";
156  type2Maker_->erase(itFound);
157  } else {
158  // This is not a process wide service, so the configuration overrides the token.
159  type2Service_.erase(type2Service_.find(*itType));
160  }
161  }
162  break;
163  }
164  //make sure our signals are propagated to our 'inherited' Services
165  if (associate)
167  }
168  createServices();
169  }
170 
171  // ServicesManager::ServicesManager(ServicesManager const& rhs) {
172  // // do actual copying here;
173  // }
174 
176  // Force the Service destructors to execute in the reverse order of construction.
177  // Note that services passed in by a token are not included in this loop and
178  // do not get destroyed until the ServicesManager object that created them is destroyed
179  // which occurs after the body of this destructor is executed (the correct order).
180  // Services directly passed in by a put and not created in the constructor
181  // may or not be detroyed in the desired order because this class does not control
182  // their creation (as I'm writing this comment everything in a standard cmsRun
183  // executable is destroyed in the desired order).
184  for (std::vector<TypeIDBase>::const_reverse_iterator idIter = actualCreationOrder_.rbegin(),
185  idEnd = actualCreationOrder_.rend();
186  idIter != idEnd;
187  ++idIter) {
188  Type2Service::iterator itService = type2Service_.find(*idIter);
189 
190  if (itService != type2Service_.end()) {
191  // This will cause the Service's destruction if
192  // there are no other shared pointers around
193  itService->second.reset();
194  }
195  }
196  }
197 
198  //
199  // assignment operators
200  //
201  // ServicesManager const& ServicesManager::operator=(ServicesManager const& rhs) {
202  // //An exception safe implementation is
203  // ServicesManager temp(rhs);
204  // swap(rhs);
205  //
206  // return *this;
207  // }
208 
209  //
210  // member functions
211  //
213 
215 
217 
219 
220  void ServicesManager::fillListOfMakers(std::vector<ParameterSet>& iConfiguration) {
221  for (std::vector<ParameterSet>::iterator itParam = iConfiguration.begin(), itParamEnd = iConfiguration.end();
222  itParam != itParamEnd;
223  ++itParam) {
224  std::shared_ptr<ServiceMakerBase> base(
225  ServicePluginFactory::get()->create(itParam->getParameter<std::string>("@service_type")));
226 
227  if (nullptr == base.get()) {
228  throw Exception(errors::Configuration, "Service")
229  << "could not find a service named " << itParam->getParameter<std::string>("@service_type")
230  << ". Please check spelling.";
231  }
232  Type2Maker::iterator itFound = type2Maker_->find(TypeIDBase(base->serviceType()));
233  if (itFound != type2Maker_->end()) {
234  throw Exception(errors::Configuration, "Service")
235  << " the service " << itParam->getParameter<std::string>("@service_type")
236  << " provides the same service as " << itFound->second.pset_->getParameter<std::string>("@service_type")
237  << "\n Please reconfigure job to only use one of these services.";
238  }
239  type2Maker_->insert(
240  Type2Maker::value_type(TypeIDBase(base->serviceType()), MakerHolder(base, *itParam, registry_)));
241  requestedCreationOrder_.push_back(TypeIDBase(base->serviceType()));
242  }
243  }
244 
245  namespace {
246  struct NoOp {
247  void operator()(ServicesManager*) {}
248  };
249  } // namespace
250 
252  std::string serviceType = iMaker.pset_->getParameter<std::string>("@service_type");
253  std::unique_ptr<ParameterSetDescriptionFillerBase> filler(
255  ConfigurationDescriptions descriptions(filler->baseType(), serviceType);
256  filler->fill(descriptions);
257 
258  try {
259  convertException::wrap([&]() { descriptions.validate(*(iMaker.pset_), serviceType); });
260  } catch (cms::Exception& iException) {
261  std::ostringstream ost;
262  ost << "Validating configuration of service of type " << serviceType;
263  iException.addContext(ost.str());
264  throw;
265  }
266  try {
267  convertException::wrap([&]() {
268  // This creates the service
269  iMaker.add(*this);
270  });
271  } catch (cms::Exception& iException) {
272  std::ostringstream ost;
273  ost << "Constructing service of type " << serviceType;
274  iException.addContext(ost.str());
275  throw;
276  }
277  }
278 
280  //create a shared_ptr of 'this' that will not delete us
281  std::shared_ptr<ServicesManager> shareThis(this, NoOp());
282 
283  ServiceToken token(shareThis);
284 
285  //Now make our services to ones obtained via ServiceRegistry
286  // when this goes out of scope, it will revert back to the previous Service set
288 
289  //Now, make each Service. If a service depends on a service that has yet to be
290  // created, that other service will automatically be made
291 
292  for (std::vector<TypeIDBase>::const_iterator idIter = requestedCreationOrder_.begin(),
293  idEnd = requestedCreationOrder_.end();
294  idIter != idEnd;
295  ++idIter) {
296  Type2Maker::iterator itMaker = type2Maker_->find(*idIter);
297 
298  // Check to make sure this maker is still there. They are deleted
299  // sometimes and that is OK.
300  if (itMaker != type2Maker_->end()) {
301  createServiceFor(itMaker->second);
302  }
303  }
304  //No longer need the makers
305  type2Maker_ = nullptr; // propagate_const<T> has no reset() function
306  }
307  //
308  // const member functions
309  //
310 
311  //
312  // static member functions
313  //
314  } // namespace serviceregistry
315 } // namespace edm
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
MakerHolder(std::shared_ptr< ServiceMakerBase > iMaker, ParameterSet &iPSet, ActivityRegistry &)
void fillListOfMakers(std::vector< ParameterSet > &)
def create(alignables, pedeDump, additionalData, outputFile, config)
void createServiceFor(MakerHolder const &)
void copySlotsTo(ActivityRegistry &)
copy our Service&#39;s slots to the argument&#39;s signals
base
Main Program
Definition: newFWLiteAna.py:92
std::map< TypeIDBase, MakerHolder > Type2Maker
void copySlotsFrom(ActivityRegistry &iOther)
std::vector< TypeIDBase > actualCreationOrder_
void connectTo(ActivityRegistry &iOther)
causes iOther&#39;s signals to be forward to us
Log< level::Info, false > LogInfo
void copySlotsFrom(ActivityRegistry &)
the copy the argument&#39;s slots to the our signals
std::vector< TypeIDBase > requestedCreationOrder_
std::string typeDemangle(char const *mangledName)
void addContext(std::string const &context)
Definition: Exception.cc:165
edm::propagate_const< std::unique_ptr< Type2Maker > > type2Maker_
ServicesManager(std::vector< ParameterSet > &iConfiguration)
std::shared_ptr< edm::serviceregistry::ServicesManager > manager_
Definition: ServiceToken.h:83
HLT enums.
edm::propagate_const< std::shared_ptr< ServicesManager > > associatedManager_
auto wrap(F iFunc) -> decltype(iFunc())
#define get
void connect(ActivityRegistry &iOther)
causes our ActivityRegistry&#39;s signals to be forwarded to iOther
std::vector< std::string > set_intersection(std::vector< std::string > const &v1, std::vector< std::string > const &v2)
void connect(ActivityRegistry &iOther)
forwards our signals to slots connected to iOther