ServicesManager.cc
Go to the documentation of this file.
2 // vim: set sw=2 expandtab :
3 
11 #include "cetlib/LibraryManager.h"
12 #include "cetlib_except/demangle.h"
13 #include "fhiclcpp/ParameterSet.h"
15 
16 #include <map>
17 #include <memory>
18 #include <stack>
19 #include <string>
20 #include <utility>
21 #include <vector>
22 
23 using namespace std;
26 
27 namespace {
28 
29  void
30  addService(string const& name, vector<ParameterSet>& service_set)
31  {
33  tmp.put("service_type", name);
34  ParameterSetRegistry::put(tmp);
35  service_set.emplace_back(move(tmp));
36  }
37 
38  void
39  addService(string const& name,
40  ParameterSet const& source,
41  vector<ParameterSet>& service_set)
42  {
44  if (source.get_if_present(name, tmp)) {
45  service_set.emplace_back(move(tmp));
46  return;
47  }
48  addService(name, service_set);
49  }
50 
51 } // unnamed namespace
52 
53 namespace art {
54 
55  ServicesManager::~ServicesManager()
56  {
57  // Force the Service destructors to execute in the reverse order
58  // of construction. We first clear the the services cache, which
59  // is safe to do as the services owned by it are co-owned by the
60  // actualCreationOrder_ data member.
61  services_.clear();
62  while (!actualCreationOrder_.empty()) {
63  actualCreationOrder_.pop();
64  }
65  }
66 
67  std::vector<std::string>
68  ServicesManager::registerProducts(ProductDescriptions& productsToProduce,
69  ProducingServiceSignals& signals,
70  ProcessConfiguration const& pc)
71  {
72  std::vector<std::string> producing_services;
73  for (auto& pr : services_) {
74  auto& serviceEntry = pr.second;
75 
76  // Service interfaces cannot be used for product insertion.
77  if (serviceEntry.is_interface())
78  continue;
79 
80  // The value of service_type becomes the "module name/label" for
81  // the ModuleDescription object.
82  auto const& pset = serviceEntry.getParameterSet();
83  std::string moduleLabel{};
84  if (!pset.get_if_present("service_type", moduleLabel)) {
85  // System services do not insert products.
86  continue;
87  }
88 
89  auto const before = productsToProduce.size();
90  ModuleDescription const md{
91  pset.id(), moduleLabel, moduleLabel, ModuleThreadingType::shared, pc};
92  serviceEntry.registerProducts(productsToProduce, signals, md);
93  if (productsToProduce.size() != before) {
94  // Registering the products for this service has changed the
95  // size of productsToProduce. We make the reasonable
96  // assumption that productsToProduce has increased in size.
97  producing_services.push_back(moduleLabel);
98  }
99  }
100  return producing_services;
101  }
102 
103  ServicesManager::ServicesManager(ParameterSet&& servicesPSet,
104  ActivityRegistry& actReg,
105  detail::SharedResources& resources)
106  : actReg_{actReg}, resources_{resources}
107  {
108  vector<ParameterSet> psets;
109  {
110  // Force presence of FileCatalogMetadata service.
111  addService("FileCatalogMetadata", servicesPSet, psets);
112  servicesPSet.erase("FileCatalogMetadata");
113  // Force presence of DatabaseConnection service.
114  addService("DatabaseConnection", servicesPSet, psets);
115  servicesPSet.erase("DatabaseConnection");
116  // Extract all
117  for (auto const& key : servicesPSet.get_pset_names()) {
118  addService(key, servicesPSet, psets);
119  }
120  }
121  using SHBCREATOR_t = std::unique_ptr<detail::ServiceHelperBase> (*)();
122  for (auto const& ps : psets) {
123  auto const service_name = ps.get<string>("service_type");
124  auto const service_provider =
125  ps.get<string>("service_provider", service_name);
126  // Get the helper from the library.
127  unique_ptr<detail::ServiceHelperBase> service_helper{
128  lm_.getSymbolByLibspec<SHBCREATOR_t>(service_provider,
129  "create_service_helper")()};
130  if (service_helper->is_interface()) {
132  << "Service " << service_name << " (of type "
133  << service_helper->get_typeid().className()
134  << ")\nhas been registered as an interface in its header using\n"
135  << "DECLARE_ART_SERVICE_INTERFACE.\n"
136  << "Use DECLARE_ART_SERVICE OR DECLARE_ART_SERVICE_INTERFACE_IMPL\n"
137  << "as appropriate. A true service interface should *not* be\n"
138  << "compiled into a _service.so plugin library.\n";
139  }
140  unique_ptr<detail::ServiceInterfaceHelper> iface_helper;
141  if (service_helper->is_interface_impl()) { // Expect an interface helper
142  iface_helper.reset(dynamic_cast<detail::ServiceInterfaceHelper*>(
143  lm_
144  .getSymbolByLibspec<SHBCREATOR_t>(service_provider,
145  "create_iface_helper")()
146  .release()));
147  if (dynamic_cast<detail::ServiceInterfaceImplHelper*>(
148  service_helper.get())
149  ->get_interface_typeid() != iface_helper->get_typeid()) {
151  << "Service registration for " << service_provider
152  << " is internally inconsistent: " << iface_helper->get_typeid()
153  << " (" << iface_helper->get_typeid().className() << ") != "
154  << dynamic_cast<detail::ServiceInterfaceImplHelper*>(
155  service_helper.get())
156  ->get_interface_typeid()
157  << " ("
158  << dynamic_cast<detail::ServiceInterfaceImplHelper*>(
159  service_helper.get())
160  ->get_interface_typeid()
161  .className()
162  << ").\n"
163  << "Contact the art developers <artists@fnal.gov>.\n";
164  }
165  if (service_provider == service_name) {
166  string iface_name{
167  cet::demangle_symbol(iface_helper->get_typeid().name())};
168  // Remove any namespace qualification if necessary
169  auto const colon_pos = iface_name.find_last_of(":");
170  if (colon_pos != std::string::npos) {
171  iface_name.erase(0, colon_pos + 1);
172  }
174  << "Illegal use of service interface implementation as service "
175  "name in configuration.\n"
176  << "Correct use: services." << iface_name
177  << ": { service_provider: \"" << service_provider << "\" }\n";
178  }
179  }
180  // Insert the cache entry for the main service implementation. Note
181  // we save the typeid of the implementation because we're about to
182  // give away the helper.
183  TypeID service_typeid{service_helper->get_typeid()};
184 
185  // Need temporary because we can't guarantee the order of evaluation
186  // of the arguments to make_pair() below.
187  TypeID const sType{service_helper->get_typeid()};
188  auto svc = services_.emplace(
189  sType, detail::ServiceCacheEntry(ps, move(service_helper)));
190 
191  if (iface_helper) {
192  // Need temporary because we can't guarantee the order of evaluation
193  // of the arguments to make_pair() below.
194  TypeID const iType{iface_helper->get_typeid()};
195  services_.emplace(
196  iType,
197  detail::ServiceCacheEntry(ps, move(iface_helper), svc.first->second));
198  }
199  requestedCreationOrder_.emplace_back(move(service_typeid));
200  }
202  }
203 
204  void
205  ServicesManager::getParameterSets(std::vector<fhicl::ParameterSet>& out) const
206  {
207  std::vector<fhicl::ParameterSet> tmp;
208  for (auto const& typeID_and_ServiceCacheEntry : services_) {
209  auto const& sce = typeID_and_ServiceCacheEntry.second;
210  tmp.push_back(sce.getParameterSet());
211  }
212  tmp.swap(out);
213  }
214 
215  void
217  {
218  for (auto const& typeID : requestedCreationOrder_) {
219  if (auto it = services_.find(typeID); it != services_.end()) {
220  auto const& sce = it->second;
221  sce.forceCreation(actReg_, resources_);
222  }
223  }
224  }
225 
226 } // namespace art
static QCString name
Definition: declinfo.cpp:673
ActivityRegistry & actReg_
std::string string
Definition: nybbler.cc:12
std::vector< TypeID > requestedCreationOrder_
STL namespace.
std::vector< BranchDescription > ProductDescriptions
static ServiceRegistry & instance() noexcept
T getSymbolByLibspec(std::string const &libspec, std::string const &sym_name) const
detail::SharedResources & resources_
def key(type, name=None)
Definition: graph.py:13
def move(depos, offset)
Definition: depos.py:107
void setManager(ServicesManager *)
void getParameterSets(std::vector< fhicl::ParameterSet > &out) const
string tmp
Definition: languages.py:63
static constexpr double ps
Definition: Units.h:99
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
string release
Definition: conf.py:24
std::map< TypeID, detail::ServiceCacheEntry > services_
std::optional< T > get_if_present(std::string const &key) const
Definition: ParameterSet.h:224
void put(std::string const &key)
cet::LibraryManager lm_