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),
47  pset_(&iPSet),
48  registry_(&iRegistry),
49  wasAdded_(false) {}
50 
51  bool
53  if(!wasAdded_) {
54  wasAdded_ = maker_->make(*pset_, *registry_, oManager);
55  if(wasAdded_ && maker_->saveConfiguration()) {
56  pset_->addUntrackedParameter("@save_config", true);
57  }
58  }
59  return wasAdded_;
60  }
61 
62  //
63  // static data member definitions
64  //
65 
66  //
67  // constructors and destructor
68  //
69  ServicesManager::ServicesManager(std::vector<ParameterSet>& iConfiguration) :
70  type2Maker_(new Type2Maker) {
71  //First create the list of makers
72  fillListOfMakers(iConfiguration);
73 
75  }
76 
78  ServiceLegacy iLegacy,
79  std::vector<ParameterSet>& iConfiguration,
80  bool associate) :
81  associatedManager_(associate ? iToken.manager_ : std::shared_ptr<ServicesManager>()),
82  type2Maker_(new Type2Maker) {
83  fillListOfMakers(iConfiguration);
84 
85  //find overlaps between services in iToken and iConfiguration
86  typedef std::set< TypeIDBase> TypeSet;
87  TypeSet configTypes;
88  for(Type2Maker::iterator itType = type2Maker_->begin(), itTypeEnd = type2Maker_->end();
89  itType != itTypeEnd;
90  ++itType) {
91  configTypes.insert(itType->first);
92  }
93 
94  TypeSet tokenTypes;
95  if(nullptr != iToken.manager_.get()) {
96  for(Type2Service::iterator itType = iToken.manager_->type2Service_.begin(),
97  itTypeEnd = iToken.manager_->type2Service_.end();
98  itType != itTypeEnd;
99  ++itType) {
100  tokenTypes.insert(itType->first);
101  }
102 
103  typedef std::set<TypeIDBase> IntersectionType;
104  IntersectionType intersection;
105  std::set_intersection(configTypes.begin(), configTypes.end(),
106  tokenTypes.begin(), tokenTypes.end(),
107  inserter(intersection, intersection.end()));
108 
109  switch(iLegacy) {
110  case kOverlapIsError :
111  if(!intersection.empty()) {
112  throw Exception(errors::Configuration, "Service")
113  << "the Service " << (*type2Maker_).find(*(intersection.begin()))->second.pset_->getParameter<std::string>("@service_type")
114  << " already has an instance of that type of Service";
115  } else {
116  //get all the services from Token
117  type2Service_ = iToken.manager_->type2Service_;
118  }
119  break;
120  case kTokenOverrides :
121  //get all the services from Token
122  type2Service_ = iToken.manager_->type2Service_;
123 
124  //remove from type2Maker the overlapping services so we never try to make them
125  for(IntersectionType::iterator itType = intersection.begin(), itTypeEnd = intersection.end();
126  itType != itTypeEnd;
127  ++itType) {
128  Type2Maker::iterator itFound = type2Maker_->find(*itType);
129  //HLT needs it such that even if a service isn't created we store its PSet if needed
130  if(itFound->second.maker_->saveConfiguration()) {
131  itFound->second.pset_->addUntrackedParameter("@save_config", true);
132  }
133  type2Maker_->erase(itFound);
134  }
135  break;
137  //get all the services from the Configuration, except process wide services
138  type2Service_ = iToken.manager_->type2Service_;
139 
140  //now remove the ones we do not want
141  for(IntersectionType::iterator itType = intersection.begin(), itTypeEnd = intersection.end();
142  itType != itTypeEnd;
143  ++itType) {
144  Type2Maker::iterator itFound = type2Maker_->find(*itType);
145  if(itFound->second.maker_->processWideService()) {
146  // This is a process wide service, so the token overrides the configuration.
147  //HLT needs it such that even if a service isn't created we store its PSet if needed
148  if(itFound->second.maker_->saveConfiguration()) {
149  itFound->second.pset_->addUntrackedParameter("@save_config", true);
150  }
151  std::string type(typeDemangle(itType->name()));
152  LogInfo("Configuration") << "Warning: You have reconfigured service\n"
153  << "'" << type << "' in a subprocess.\n"
154  << "This service has already been configured.\n"
155  << "This particular service may not be reconfigured in a subprocess.\n"
156  << "The reconfiguration will be ignored.\n";
157  type2Maker_->erase(itFound);
158  } else {
159  // This is not a process wide service, so the configuration overrides the token.
160  type2Service_.erase(type2Service_.find(*itType));
161  }
162  }
163  break;
164  }
165  //make sure our signals are propagated to our 'inherited' Services
166  if (associate) registry_.copySlotsFrom(associatedManager_->registry_);
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 
189  Type2Service::iterator itService = type2Service_.find(*idIter);
190 
191  if(itService != type2Service_.end()) {
192 
193  // This will cause the Service's destruction if
194  // there are no other shared pointers around
195  itService->second.reset();
196  }
197  }
198  }
199 
200  //
201  // assignment operators
202  //
203  // ServicesManager const& ServicesManager::operator=(ServicesManager const& rhs) {
204  // //An exception safe implementation is
205  // ServicesManager temp(rhs);
206  // swap(rhs);
207  //
208  // return *this;
209  // }
210 
211  //
212  // member functions
213  //
214  void
216  registry_.connect(iOther);
217  }
218 
219  void
221  iOther.connect(registry_);
222  }
223 
224  void
226  registry_.copySlotsFrom(iOther);
227  }
228 
229  void
231  iOther.copySlotsFrom(registry_);
232  }
233 
234  void
235  ServicesManager::fillListOfMakers(std::vector<ParameterSet>& iConfiguration) {
236  for(std::vector<ParameterSet>::iterator itParam = iConfiguration.begin(),
237  itParamEnd = iConfiguration.end();
238  itParam != itParamEnd;
239  ++itParam) {
240  std::shared_ptr<ServiceMakerBase> base(ServicePluginFactory::get()->create(itParam->getParameter<std::string>("@service_type")));
241 
242  if(nullptr == base.get()) {
243  throw Exception(errors::Configuration, "Service")
244  << "could not find a service named "
245  << itParam->getParameter<std::string>("@service_type")
246  << ". Please check spelling.";
247  }
248  Type2Maker::iterator itFound = type2Maker_->find(TypeIDBase(base->serviceType()));
249  if(itFound != type2Maker_->end()) {
250  throw Exception(errors::Configuration, "Service")
251  << " the service " << itParam->getParameter<std::string>("@service_type")
252  << " provides the same service as "
253  << itFound->second.pset_->getParameter<std::string>("@service_type")
254  << "\n Please reconfigure job to only use one of these services.";
255  }
256  type2Maker_->insert(Type2Maker::value_type(TypeIDBase(base->serviceType()),
257  MakerHolder(base,
258  *itParam,
259  registry_)));
260  requestedCreationOrder_.push_back(TypeIDBase(base->serviceType()));
261  }
262  }
263 
264  namespace {
265  struct NoOp {
266  void operator()(ServicesManager*) {}
267  };
268  }
269 
270  void
272  std::string serviceType = iMaker.pset_->getParameter<std::string>("@service_type");
273  std::unique_ptr<ParameterSetDescriptionFillerBase> filler(
275  ConfigurationDescriptions descriptions(filler->baseType(), serviceType);
276  filler->fill(descriptions);
277 
278  try {
279  convertException::wrap([&]() {
280  descriptions.validate(*(iMaker.pset_), serviceType);
281  });
282  }
283  catch (cms::Exception & iException) {
284  std::ostringstream ost;
285  ost << "Validating configuration of service of type " << serviceType;
286  iException.addContext(ost.str());
287  throw;
288  }
289  try {
290  convertException::wrap([&]() {
291  // This creates the service
292  iMaker.add(*this);
293  });
294  }
295  catch (cms::Exception & iException) {
296  std::ostringstream ost;
297  ost << "Constructing service of type " << serviceType;
298  iException.addContext(ost.str());
299  throw;
300  }
301  }
302 
303  void
305 
306  //create a shared_ptr of 'this' that will not delete us
307  std::shared_ptr<ServicesManager> shareThis(this, NoOp());
308 
309  ServiceToken token(shareThis);
310 
311  //Now make our services to ones obtained via ServiceRegistry
312  // when this goes out of scope, it will revert back to the previous Service set
314 
315  //Now, make each Service. If a service depends on a service that has yet to be
316  // created, that other service will automatically be made
317 
318  for(std::vector<TypeIDBase>::const_iterator idIter = requestedCreationOrder_.begin(),
319  idEnd = requestedCreationOrder_.end();
320  idIter != idEnd;
321  ++idIter) {
322  Type2Maker::iterator itMaker = type2Maker_->find(*idIter);
323 
324  // Check to make sure this maker is still there. They are deleted
325  // sometimes and that is OK.
326  if(itMaker != type2Maker_->end()) {
327  createServiceFor(itMaker->second);
328  }
329  }
330  //No longer need the makers
331  type2Maker_ = nullptr; // propagate_const<T> has no reset() function
332  }
333  //
334  // const member functions
335  //
336 
337  //
338  // static member functions
339  //
340  }
341 }
type
Definition: HCALResponse.h:21
T getParameter(std::string const &) const
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
std::map< TypeIDBase, MakerHolder > Type2Maker
void copySlotsFrom(ActivityRegistry &iOther)
edm::propagate_const< std::shared_ptr< ServiceMakerBase > > maker_
std::vector< TypeIDBase > actualCreationOrder_
void connectTo(ActivityRegistry &iOther)
causes iOther&#39;s signals to be forward to us
base
Make Sure CMSSW is Setup ##.
void copySlotsFrom(ActivityRegistry &)
the copy the argument&#39;s slots to the our signals
std::vector< TypeIDBase > requestedCreationOrder_
void addUntrackedParameter(std::string const &name, T const &value)
Definition: ParameterSet.h:207
std::string typeDemangle(char const *mangledName)
void addContext(std::string const &context)
Definition: Exception.cc:227
edm::propagate_const< std::unique_ptr< Type2Maker > > type2Maker_
ServicesManager(std::vector< ParameterSet > &iConfiguration)
std::shared_ptr< edm::serviceregistry::ServicesManager > manager_
Definition: ServiceToken.h:77
HLT enums.
edm::propagate_const< std::shared_ptr< ServicesManager > > associatedManager_
auto wrap(F iFunc) -> decltype(iFunc())
void connect(ActivityRegistry &iOther)
causes our ActivityRegistry&#39;s signals to be forwarded to iOther
T get(const Candidate &c)
Definition: component.h:55
def operate(timelog, memlog, json_f, num)
void connect(ActivityRegistry &iOther)
forwards our signals to slots connected to iOther