Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:12:13

0001 #include "DataFormats/Provenance/interface/BranchDescription.h"
0002 #include "DataFormats/Provenance/interface/BranchKey.h"
0003 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0004 #include "FWCore/Utilities/interface/EDMException.h"
0005 
0006 #include "processEDAliases.h"
0007 
0008 #include <map>
0009 
0010 namespace edm {
0011   namespace {
0012     void checkAndInsertAlias(std::string const& friendlyClassName,
0013                              std::string const& moduleLabel,
0014                              std::string const& productInstanceName,
0015                              std::string const& processName,
0016                              std::string const& alias,
0017                              std::string const& instanceAlias,
0018                              ProductRegistry const& preg,
0019                              std::multimap<BranchKey, BranchKey>& aliasMap,
0020                              std::map<BranchKey, BranchKey>& aliasKeys) {
0021       std::string const star("*");
0022 
0023       BranchKey key(friendlyClassName, moduleLabel, productInstanceName, processName);
0024       if (preg.productList().find(key) == preg.productList().end()) {
0025         // No product was found matching the alias.
0026         // We throw an exception only if a module with the specified module label was created in this process.
0027         for (auto const& product : preg.productList()) {
0028           if (moduleLabel == product.first.moduleLabel() && processName == product.first.processName()) {
0029             throw Exception(errors::Configuration, "EDAlias does not match data\n")
0030                 << "There are no products of type '" << friendlyClassName << "'\n"
0031                 << "with module label '" << moduleLabel << "' and instance name '" << productInstanceName << "'.\n";
0032           }
0033         }
0034       }
0035 
0036       if (auto iter = aliasMap.find(key); iter != aliasMap.end()) {
0037         // If the same EDAlias defines multiple products pointing to the same product, throw
0038         if (iter->second.moduleLabel() == alias) {
0039           throw Exception(errors::Configuration, "EDAlias conflict\n")
0040               << "The module label alias '" << alias << "' is used for multiple products of type '" << friendlyClassName
0041               << "' with module label '" << moduleLabel << "' and instance name '" << productInstanceName
0042               << "'. One alias has the instance name '" << iter->first.productInstanceName()
0043               << "' and the other has the instance name '" << instanceAlias << "'.";
0044         }
0045       }
0046 
0047       std::string const& theInstanceAlias(instanceAlias == star ? productInstanceName : instanceAlias);
0048       BranchKey aliasKey(friendlyClassName, alias, theInstanceAlias, processName);
0049       if (auto it = preg.productList().find(aliasKey); it != preg.productList().end()) {
0050         // We might have already inserted an alias that was a chosen case of a SwitchProducer
0051         if (not it->second.isAlias()) {
0052           throw Exception(errors::Configuration, "EDAlias conflicts with data\n")
0053               << "A product of type '" << friendlyClassName << "'\n"
0054               << "with module label '" << alias << "' and instance name '" << theInstanceAlias << "'\n"
0055               << "already exists.\n";
0056         }
0057         return;
0058       }
0059       auto iter = aliasKeys.find(aliasKey);
0060       if (iter != aliasKeys.end()) {
0061         // The alias matches a previous one.  If the same alias is used for different product, throw.
0062         if (iter->second != key) {
0063           throw Exception(errors::Configuration, "EDAlias conflict\n")
0064               << "The module label alias '" << alias << "' and product instance alias '" << theInstanceAlias << "'\n"
0065               << "are used for multiple products of type '" << friendlyClassName << "'\n"
0066               << "One has module label '" << moduleLabel << "' and product instance name '" << productInstanceName
0067               << "',\n"
0068               << "the other has module label '" << iter->second.moduleLabel() << "' and product instance name '"
0069               << iter->second.productInstanceName() << "'.\n";
0070         }
0071       } else {
0072         auto prodIter = preg.productList().find(key);
0073         if (prodIter != preg.productList().end()) {
0074           if (!prodIter->second.produced()) {
0075             throw Exception(errors::Configuration, "EDAlias\n")
0076                 << "The module label alias '" << alias << "' and product instance alias '" << theInstanceAlias << "'\n"
0077                 << "are used for a product of type '" << friendlyClassName << "'\n"
0078                 << "with module label '" << moduleLabel << "' and product instance name '" << productInstanceName
0079                 << "',\n"
0080                 << "An EDAlias can only be used for products produced in the current process. This one is not.\n";
0081           }
0082           aliasMap.insert(std::make_pair(key, aliasKey));
0083           aliasKeys.insert(std::make_pair(aliasKey, key));
0084         }
0085       }
0086     }
0087   }  // namespace
0088 
0089   namespace detail {
0090     void processEDAliases(std::vector<std::string> const& aliasNamesToProcess,
0091                           std::unordered_set<std::string> const& aliasModulesToProcess,
0092                           ParameterSet const& proc_pset,
0093                           std::string const& processName,
0094                           ProductRegistry& preg) {
0095       if (aliasNamesToProcess.empty()) {
0096         return;
0097       }
0098       std::string const star("*");
0099       std::string const empty("");
0100       ParameterSetDescription desc;
0101       desc.add<std::string>("type");
0102       desc.add<std::string>("fromProductInstance", star);
0103       desc.add<std::string>("toProductInstance", star);
0104 
0105       std::multimap<BranchKey, BranchKey> aliasMap;
0106 
0107       std::map<BranchKey, BranchKey> aliasKeys;  // Used to search for duplicates or clashes.
0108 
0109       // Auxiliary search structure to support wildcard for friendlyClassName
0110       std::multimap<std::string, BranchKey> moduleLabelToBranches;
0111       for (auto const& prod : preg.productList()) {
0112         if (processName == prod.second.processName()) {
0113           moduleLabelToBranches.emplace(prod.first.moduleLabel(), prod.first);
0114         }
0115       }
0116 
0117       // Now, loop over the alias information and store it in aliasMap.
0118       for (std::string const& alias : aliasNamesToProcess) {
0119         ParameterSet const& aliasPSet = proc_pset.getParameterSet(alias);
0120         std::vector<std::string> vPSetNames = aliasPSet.getParameterNamesForType<VParameterSet>();
0121         for (std::string const& moduleLabel : vPSetNames) {
0122           if (not aliasModulesToProcess.empty() and
0123               aliasModulesToProcess.find(moduleLabel) == aliasModulesToProcess.end()) {
0124             continue;
0125           }
0126 
0127           VParameterSet vPSet = aliasPSet.getParameter<VParameterSet>(moduleLabel);
0128           for (ParameterSet& pset : vPSet) {
0129             desc.validate(pset);
0130             std::string friendlyClassName = pset.getParameter<std::string>("type");
0131             std::string productInstanceName = pset.getParameter<std::string>("fromProductInstance");
0132             std::string instanceAlias = pset.getParameter<std::string>("toProductInstance");
0133 
0134             if (friendlyClassName == star) {
0135               bool processHasLabel = false;
0136               bool match = false;
0137               for (auto it = moduleLabelToBranches.lower_bound(moduleLabel);
0138                    it != moduleLabelToBranches.end() && it->first == moduleLabel;
0139                    ++it) {
0140                 processHasLabel = true;
0141                 if (productInstanceName != star and productInstanceName != it->second.productInstanceName()) {
0142                   continue;
0143                 }
0144                 match = true;
0145 
0146                 checkAndInsertAlias(it->second.friendlyClassName(),
0147                                     moduleLabel,
0148                                     it->second.productInstanceName(),
0149                                     processName,
0150                                     alias,
0151                                     instanceAlias,
0152                                     preg,
0153                                     aliasMap,
0154                                     aliasKeys);
0155               }
0156               if (not match and processHasLabel) {
0157                 // No product was found matching the alias.
0158                 // We throw an exception only if a module with the specified module label was created in this process.
0159                 // Note that if that condition is ever relatex, it  might be best to throw an exception with different
0160                 // message (omitting productInstanceName) in case 'productInstanceName == start'
0161                 throw Exception(errors::Configuration, "EDAlias parameter set mismatch\n")
0162                     << "There are no products with module label '" << moduleLabel << "' and product instance name '"
0163                     << productInstanceName << "'.\n";
0164               }
0165             } else if (productInstanceName == star) {
0166               bool match = false;
0167               BranchKey lowerBound(friendlyClassName, moduleLabel, empty, empty);
0168               for (ProductRegistry::ProductList::const_iterator it = preg.productList().lower_bound(lowerBound);
0169                    it != preg.productList().end() && it->first.friendlyClassName() == friendlyClassName &&
0170                    it->first.moduleLabel() == moduleLabel;
0171                    ++it) {
0172                 if (it->first.processName() != processName) {
0173                   continue;
0174                 }
0175                 match = true;
0176 
0177                 checkAndInsertAlias(friendlyClassName,
0178                                     moduleLabel,
0179                                     it->first.productInstanceName(),
0180                                     processName,
0181                                     alias,
0182                                     instanceAlias,
0183                                     preg,
0184                                     aliasMap,
0185                                     aliasKeys);
0186               }
0187               if (!match) {
0188                 // No product was found matching the alias.
0189                 // We throw an exception only if a module with the specified module label was created in this process.
0190                 for (auto const& product : preg.productList()) {
0191                   if (moduleLabel == product.first.moduleLabel() && processName == product.first.processName()) {
0192                     throw Exception(errors::Configuration, "EDAlias parameter set mismatch\n")
0193                         << "There are no products of type '" << friendlyClassName << "'\n"
0194                         << "with module label '" << moduleLabel << "'.\n";
0195                   }
0196                 }
0197               }
0198             } else {
0199               checkAndInsertAlias(friendlyClassName,
0200                                   moduleLabel,
0201                                   productInstanceName,
0202                                   processName,
0203                                   alias,
0204                                   instanceAlias,
0205                                   preg,
0206                                   aliasMap,
0207                                   aliasKeys);
0208             }
0209           }
0210         }
0211       }
0212 
0213       // Now add the new alias entries to the product registry.
0214       for (auto const& aliasEntry : aliasMap) {
0215         // Then check that the alias-for product exists
0216         ProductRegistry::ProductList::const_iterator it = preg.productList().find(aliasEntry.first);
0217         assert(it != preg.productList().end());
0218         preg.addLabelAlias(it->second, aliasEntry.second.moduleLabel(), aliasEntry.second.productInstanceName());
0219       }
0220     }
0221   }  // namespace detail
0222 }  // namespace edm