CMS 3D CMS Logo

processEDAliases.cc
Go to the documentation of this file.
5 
6 #include "processEDAliases.h"
7 
8 #include <map>
9 
10 namespace edm {
11  namespace {
12  void checkAndInsertAlias(std::string const& friendlyClassName,
13  std::string const& moduleLabel,
14  std::string const& productInstanceName,
15  std::string const& processName,
16  std::string const& alias,
17  std::string const& instanceAlias,
18  ProductRegistry const& preg,
19  std::multimap<BranchKey, BranchKey>& aliasMap,
20  std::map<BranchKey, BranchKey>& aliasKeys) {
21  std::string const star("*");
22 
23  BranchKey key(friendlyClassName, moduleLabel, productInstanceName, processName);
24  if (preg.productList().find(key) == preg.productList().end()) {
25  // No product was found matching the alias.
26  // We throw an exception only if a module with the specified module label was created in this process.
27  for (auto const& product : preg.productList()) {
28  if (moduleLabel == product.first.moduleLabel() && processName == product.first.processName()) {
29  throw Exception(errors::Configuration, "EDAlias does not match data\n")
30  << "There are no products of type '" << friendlyClassName << "'\n"
31  << "with module label '" << moduleLabel << "' and instance name '" << productInstanceName << "'.\n";
32  }
33  }
34  }
35 
36  if (auto iter = aliasMap.find(key); iter != aliasMap.end()) {
37  // If the same EDAlias defines multiple products pointing to the same product, throw
38  if (iter->second.moduleLabel() == alias) {
39  throw Exception(errors::Configuration, "EDAlias conflict\n")
40  << "The module label alias '" << alias << "' is used for multiple products of type '" << friendlyClassName
41  << "' with module label '" << moduleLabel << "' and instance name '" << productInstanceName
42  << "'. One alias has the instance name '" << iter->first.productInstanceName()
43  << "' and the other has the instance name '" << instanceAlias << "'.";
44  }
45  }
46 
47  std::string const& theInstanceAlias(instanceAlias == star ? productInstanceName : instanceAlias);
48  BranchKey aliasKey(friendlyClassName, alias, theInstanceAlias, processName);
49  if (auto it = preg.productList().find(aliasKey); it != preg.productList().end()) {
50  // We might have already inserted an alias that was a chosen case of a SwitchProducer
51  if (not it->second.isAlias()) {
52  throw Exception(errors::Configuration, "EDAlias conflicts with data\n")
53  << "A product of type '" << friendlyClassName << "'\n"
54  << "with module label '" << alias << "' and instance name '" << theInstanceAlias << "'\n"
55  << "already exists.\n";
56  }
57  return;
58  }
59  auto iter = aliasKeys.find(aliasKey);
60  if (iter != aliasKeys.end()) {
61  // The alias matches a previous one. If the same alias is used for different product, throw.
62  if (iter->second != key) {
63  throw Exception(errors::Configuration, "EDAlias conflict\n")
64  << "The module label alias '" << alias << "' and product instance alias '" << theInstanceAlias << "'\n"
65  << "are used for multiple products of type '" << friendlyClassName << "'\n"
66  << "One has module label '" << moduleLabel << "' and product instance name '" << productInstanceName
67  << "',\n"
68  << "the other has module label '" << iter->second.moduleLabel() << "' and product instance name '"
69  << iter->second.productInstanceName() << "'.\n";
70  }
71  } else {
72  auto prodIter = preg.productList().find(key);
73  if (prodIter != preg.productList().end()) {
74  if (!prodIter->second.produced()) {
75  throw Exception(errors::Configuration, "EDAlias\n")
76  << "The module label alias '" << alias << "' and product instance alias '" << theInstanceAlias << "'\n"
77  << "are used for a product of type '" << friendlyClassName << "'\n"
78  << "with module label '" << moduleLabel << "' and product instance name '" << productInstanceName
79  << "',\n"
80  << "An EDAlias can only be used for products produced in the current process. This one is not.\n";
81  }
82  aliasMap.insert(std::make_pair(key, aliasKey));
83  aliasKeys.insert(std::make_pair(aliasKey, key));
84  }
85  }
86  }
87  } // namespace
88 
89  namespace detail {
90  void processEDAliases(std::vector<std::string> const& aliasNamesToProcess,
91  std::unordered_set<std::string> const& aliasModulesToProcess,
92  ParameterSet const& proc_pset,
93  std::string const& processName,
94  ProductRegistry& preg) {
95  if (aliasNamesToProcess.empty()) {
96  return;
97  }
98  std::string const star("*");
99  std::string const empty("");
101  desc.add<std::string>("type");
102  desc.add<std::string>("fromProductInstance", star);
103  desc.add<std::string>("toProductInstance", star);
104 
105  std::multimap<BranchKey, BranchKey> aliasMap;
106 
107  std::map<BranchKey, BranchKey> aliasKeys; // Used to search for duplicates or clashes.
108 
109  // Auxiliary search structure to support wildcard for friendlyClassName
110  std::multimap<std::string, BranchKey> moduleLabelToBranches;
111  for (auto const& prod : preg.productList()) {
112  if (processName == prod.second.processName()) {
113  moduleLabelToBranches.emplace(prod.first.moduleLabel(), prod.first);
114  }
115  }
116 
117  // Now, loop over the alias information and store it in aliasMap.
118  for (std::string const& alias : aliasNamesToProcess) {
119  ParameterSet const& aliasPSet = proc_pset.getParameterSet(alias);
120  std::vector<std::string> vPSetNames = aliasPSet.getParameterNamesForType<VParameterSet>();
121  for (std::string const& moduleLabel : vPSetNames) {
122  if (not aliasModulesToProcess.empty() and
123  aliasModulesToProcess.find(moduleLabel) == aliasModulesToProcess.end()) {
124  continue;
125  }
126 
128  for (ParameterSet& pset : vPSet) {
129  desc.validate(pset);
130  std::string friendlyClassName = pset.getParameter<std::string>("type");
131  std::string productInstanceName = pset.getParameter<std::string>("fromProductInstance");
132  std::string instanceAlias = pset.getParameter<std::string>("toProductInstance");
133 
134  if (friendlyClassName == star) {
135  bool processHasLabel = false;
136  bool match = false;
137  for (auto it = moduleLabelToBranches.lower_bound(moduleLabel);
138  it != moduleLabelToBranches.end() && it->first == moduleLabel;
139  ++it) {
140  processHasLabel = true;
141  if (productInstanceName != star and productInstanceName != it->second.productInstanceName()) {
142  continue;
143  }
144  match = true;
145 
146  checkAndInsertAlias(it->second.friendlyClassName(),
147  moduleLabel,
148  it->second.productInstanceName(),
149  processName,
150  alias,
151  instanceAlias,
152  preg,
153  aliasMap,
154  aliasKeys);
155  }
156  if (not match and processHasLabel) {
157  // No product was found matching the alias.
158  // We throw an exception only if a module with the specified module label was created in this process.
159  // Note that if that condition is ever relatex, it might be best to throw an exception with different
160  // message (omitting productInstanceName) in case 'productInstanceName == start'
161  throw Exception(errors::Configuration, "EDAlias parameter set mismatch\n")
162  << "There are no products with module label '" << moduleLabel << "' and product instance name '"
163  << productInstanceName << "'.\n";
164  }
165  } else if (productInstanceName == star) {
166  bool match = false;
167  BranchKey lowerBound(friendlyClassName, moduleLabel, empty, empty);
168  for (ProductRegistry::ProductList::const_iterator it = preg.productList().lower_bound(lowerBound);
169  it != preg.productList().end() && it->first.friendlyClassName() == friendlyClassName &&
170  it->first.moduleLabel() == moduleLabel;
171  ++it) {
172  if (it->first.processName() != processName) {
173  continue;
174  }
175  match = true;
176 
177  checkAndInsertAlias(friendlyClassName,
178  moduleLabel,
179  it->first.productInstanceName(),
180  processName,
181  alias,
182  instanceAlias,
183  preg,
184  aliasMap,
185  aliasKeys);
186  }
187  if (!match) {
188  // No product was found matching the alias.
189  // We throw an exception only if a module with the specified module label was created in this process.
190  for (auto const& product : preg.productList()) {
191  if (moduleLabel == product.first.moduleLabel() && processName == product.first.processName()) {
192  throw Exception(errors::Configuration, "EDAlias parameter set mismatch\n")
193  << "There are no products of type '" << friendlyClassName << "'\n"
194  << "with module label '" << moduleLabel << "'.\n";
195  }
196  }
197  }
198  } else {
199  checkAndInsertAlias(friendlyClassName,
200  moduleLabel,
201  productInstanceName,
202  processName,
203  alias,
204  instanceAlias,
205  preg,
206  aliasMap,
207  aliasKeys);
208  }
209  }
210  }
211  }
212 
213  // Now add the new alias entries to the product registry.
214  for (auto const& aliasEntry : aliasMap) {
215  // Then check that the alias-for product exists
216  ProductRegistry::ProductList::const_iterator it = preg.productList().find(aliasEntry.first);
217  assert(it != preg.productList().end());
218  preg.addLabelAlias(it->second, aliasEntry.second.moduleLabel(), aliasEntry.second.productInstanceName());
219  }
220  }
221  } // namespace detail
222 } // namespace edm
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
ProductList const & productList() const
std::vector< ParameterSet > VParameterSet
Definition: ParameterSet.h:35
ParameterSet const & getParameterSet(std::string const &) const
assert(be >=bs)
void addLabelAlias(BranchDescription const &productdesc, std::string const &labelAlias, std::string const &instanceAlias)
void processEDAliases(std::vector< std::string > const &aliasNamesToProcess, std::unordered_set< std::string > const &aliasModulesToProcess, ParameterSet const &proc_pset, std::string const &processName, ProductRegistry &preg)
std::vector< std::string > getParameterNamesForType(bool trackiness=true) const
Definition: ParameterSet.h:180
HLT enums.