CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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(0 != 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(0 == 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 
273  //create a shared_ptr of 'this' that will not delete us
274  std::shared_ptr<ServicesManager> shareThis(this, NoOp());
275 
276  ServiceToken token(shareThis);
277 
278  //Now make our services to ones obtained via ServiceRegistry
279  // when this goes out of scope, it will revert back to the previous Service set
281 
282  //Now, make each Service. If a service depends on a service that has yet to be
283  // created, that other service will automatically be made
284 
285  for(std::vector<TypeIDBase>::const_iterator idIter = requestedCreationOrder_.begin(),
286  idEnd = requestedCreationOrder_.end();
287  idIter != idEnd;
288  ++idIter) {
289  Type2Maker::iterator itMaker = type2Maker_->find(*idIter);
290 
291  // Check to make sure this maker is still there. They are deleted
292  // sometimes and that is OK.
293  if(itMaker != type2Maker_->end()) {
294 
295  std::string serviceType = itMaker->second.pset_->getParameter<std::string>("@service_type");
296  std::auto_ptr<ParameterSetDescriptionFillerBase> filler(
298  ConfigurationDescriptions descriptions(filler->baseType());
299  filler->fill(descriptions);
300 
301  try {
302  convertException::wrap([&]() {
303  descriptions.validate(*(itMaker->second.pset_), serviceType);
304  });
305  }
306  catch (cms::Exception & iException) {
307  std::ostringstream ost;
308  ost << "Validating configuration of service of type " << serviceType;
309  iException.addContext(ost.str());
310  throw;
311  }
312  try {
313  convertException::wrap([&]() {
314  // This creates the service
315  itMaker->second.add(*this);
316  });
317  }
318  catch (cms::Exception & iException) {
319  std::ostringstream ost;
320  ost << "Constructing service of type " << serviceType;
321  iException.addContext(ost.str());
322  throw;
323  }
324  }
325  }
326  //No longer need the makers
327  type2Maker_.reset();
328  }
329  //
330  // const member functions
331  //
332 
333  //
334  // static member functions
335  //
336  }
337 }
tuple base
Main Program
Definition: newFWLiteAna.py:92
type
Definition: HCALResponse.h:21
MakerHolder(std::shared_ptr< ServiceMakerBase > iMaker, ParameterSet &iPSet, ActivityRegistry &)
void fillListOfMakers(std::vector< ParameterSet > &)
void copySlotsTo(ActivityRegistry &)
copy our Service&#39;s slots to the argument&#39;s signals
std::map< TypeIDBase, MakerHolder > Type2Maker
void copySlotsFrom(ActivityRegistry &iOther)
std::auto_ptr< Type2Maker > type2Maker_
std::vector< TypeIDBase > actualCreationOrder_
std::set< TypeID > TypeSet
void connectTo(ActivityRegistry &iOther)
causes iOther&#39;s signals to be forward to us
Container::value_type value_type
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:227
ServicesManager(std::vector< ParameterSet > &iConfiguration)
std::shared_ptr< edm::serviceregistry::ServicesManager > manager_
Definition: ServiceToken.h:70
auto wrap(F iFunc) -> decltype(iFunc())
volatile std::atomic< bool > shutdown_flag false
void connect(ActivityRegistry &iOther)
causes our ActivityRegistry&#39;s signals to be forwarded to iOther
SurfaceDeformation * create(int type, const std::vector< double > &params)
std::shared_ptr< ServicesManager > associatedManager_
T get(const Candidate &c)
Definition: component.h:55
void connect(ActivityRegistry &iOther)
forwards our signals to slots connected to iOther