Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-03-23 15:57:47

0001 // -*- C++ -*-
0002 //
0003 // Package:     Modules
0004 // Class  :     ProvenanceCheckerOutputModule
0005 //
0006 // Implementation:
0007 //     Checks the consistency of provenance stored in the framework
0008 //
0009 // Original Author:  Chris Jones
0010 //         Created:  Thu Sep 11 19:24:13 EDT 2008
0011 //
0012 
0013 // system include files
0014 #include "FWCore/Framework/interface/one/OutputModule.h"
0015 #include "FWCore/Framework/interface/MakerMacros.h"
0016 #include "FWCore/Framework/interface/EventForOutput.h"
0017 #include "FWCore/Utilities/interface/Exception.h"
0018 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0019 #include "DataFormats/Provenance/interface/ProductRegistry.h"
0020 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0021 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0022 #include "FWCore/ServiceRegistry/interface/Service.h"
0023 
0024 // user include files
0025 
0026 namespace edm {
0027 
0028   class ModuleCallingContext;
0029   class ParameterSet;
0030 
0031   class ProvenanceCheckerOutputModule : public one::OutputModule<> {
0032   public:
0033     // We do not take ownership of passed stream.
0034     explicit ProvenanceCheckerOutputModule(ParameterSet const& pset);
0035     ~ProvenanceCheckerOutputModule() override;
0036     static void fillDescriptions(ConfigurationDescriptions& descriptions);
0037 
0038   private:
0039     void write(EventForOutput const& e) override;
0040     void writeLuminosityBlock(LuminosityBlockForOutput const&) override {}
0041     void writeRun(RunForOutput const&) override {}
0042   };
0043 
0044   //
0045   // constants, enums and typedefs
0046   //
0047 
0048   //
0049   // static data member definitions
0050   //
0051 
0052   //
0053   // constructors and destructor
0054   //
0055   ProvenanceCheckerOutputModule::ProvenanceCheckerOutputModule(ParameterSet const& pset)
0056       : one::OutputModuleBase(pset), one::OutputModule<>(pset) {}
0057 
0058   // ProvenanceCheckerOutputModule::ProvenanceCheckerOutputModule(ProvenanceCheckerOutputModule const& rhs)
0059   // {
0060   //    // do actual copying here;
0061   // }
0062 
0063   ProvenanceCheckerOutputModule::~ProvenanceCheckerOutputModule() {}
0064 
0065   //
0066   // assignment operators
0067   //
0068   // ProvenanceCheckerOutputModule const& ProvenanceCheckerOutputModule::operator=(ProvenanceCheckerOutputModule const& rhs)
0069   // {
0070   //   //An exception safe implementation is
0071   //   ProvenanceCheckerOutputModule temp(rhs);
0072   //   swap(rhs);
0073   //
0074   //   return *this;
0075   // }
0076 
0077   namespace {
0078     void markAncestors(EventForOutput const& e,
0079                        ProductProvenance const& iInfo,
0080                        std::map<BranchID, bool>& oMap,
0081                        std::set<BranchID>& oMapperMissing) {
0082       for (BranchID const id : iInfo.parentage().parents()) {
0083         //Don't look for parents if we've previously looked at the parents
0084         if (oMap.find(id) == oMap.end()) {
0085           //use side effect of calling operator[] which is if the item isn't there it will add it as 'false'
0086           oMap[id];
0087           ProductProvenance const* pInfo = e.getProvenance(id).productProvenance();
0088           if (pInfo) {
0089             markAncestors(e, *pInfo, oMap, oMapperMissing);
0090           } else {
0091             oMapperMissing.insert(id);
0092           }
0093         }
0094       }
0095     }
0096   }  // namespace
0097 
0098   void ProvenanceCheckerOutputModule::write(EventForOutput const& e) {
0099     //check ProductProvenance's parents to see if they are in the ProductProvenance list
0100 
0101     std::map<BranchID, bool> seenParentInPrincipal;
0102     std::set<BranchID> missingFromMapper;
0103     std::set<BranchID> missingProductProvenance;
0104 
0105     std::map<BranchID, const ProductDescription*> idToProductDescriptions;
0106     for (auto const& product : keptProducts()[InEvent]) {
0107       ProductDescription const* productDescription = product.first;
0108       BranchID branchID = productDescription->branchID();
0109       idToProductDescriptions[branchID] = productDescription;
0110       TypeID const& tid(productDescription->unwrappedTypeID());
0111       EDGetToken const& token = product.second;
0112       BasicHandle bh = e.getByToken(token, tid);
0113       bool cannotFindProductProvenance = false;
0114       if (!(bh.provenance() and bh.provenance()->productProvenance())) {
0115         missingProductProvenance.insert(branchID);
0116         cannotFindProductProvenance = true;
0117       }
0118       ProductProvenance const* pInfo = e.getProvenance(branchID).productProvenance();
0119       if (!pInfo) {
0120         missingFromMapper.insert(branchID);
0121         continue;
0122       }
0123       if (cannotFindProductProvenance) {
0124         continue;
0125       }
0126       markAncestors(e, *(bh.provenance()->productProvenance()), seenParentInPrincipal, missingFromMapper);
0127       seenParentInPrincipal[branchID] = true;
0128     }
0129 
0130     //Determine what BranchIDs are in the product registry
0131     std::set<BranchID> branchesInReg;
0132     for (auto const& product : e.productRegistry().productList()) {
0133       branchesInReg.insert(product.second.branchID());
0134       idToProductDescriptions[product.second.branchID()] = &product.second;
0135     }
0136 
0137     std::set<BranchID> missingFromReg;
0138     for (auto const& item : seenParentInPrincipal) {
0139       if (branchesInReg.find(item.first) == branchesInReg.end()) {
0140         missingFromReg.insert(item.first);
0141       }
0142     }
0143 
0144     if (!missingFromMapper.empty()) {
0145       LogError("ProvenanceChecker") << "Missing the following BranchIDs from ProductProvenanceRetriever\n";
0146       for (std::set<BranchID>::iterator it = missingFromMapper.begin(), itEnd = missingFromMapper.end(); it != itEnd;
0147            ++it) {
0148         LogProblem("ProvenanceChecker") << *it << " " << *(idToProductDescriptions[*it]);
0149       }
0150     }
0151 
0152     if (!missingProductProvenance.empty()) {
0153       LogError("ProvenanceChecker") << "The ProductResolvers for the following BranchIDs have no ProductProvenance\n";
0154       for (std::set<BranchID>::iterator it = missingProductProvenance.begin(), itEnd = missingProductProvenance.end();
0155            it != itEnd;
0156            ++it) {
0157         LogProblem("ProvenanceChecker") << *it << " " << *(idToProductDescriptions[*it]);
0158       }
0159     }
0160 
0161     if (!missingFromReg.empty()) {
0162       LogError("ProvenanceChecker") << "Missing the following BranchIDs from ProductRegistry\n";
0163       for (auto const& item : missingFromReg) {
0164         LogProblem("ProvenanceChecker") << item << " " << *(idToProductDescriptions[item]);
0165       }
0166     }
0167 
0168     if (!missingFromMapper.empty() || !missingProductProvenance.empty() || !missingFromReg.empty()) {
0169       throw cms::Exception("ProvenanceError")
0170           << (!missingFromMapper.empty() ? "Having missing ancestors from ProductProvenanceRetriever.\n" : "")
0171           << (!missingProductProvenance.empty() ? " Have missing ProductProvenance's from ProductResolver in Event.\n"
0172                                                 : "")
0173           << (!missingFromReg.empty() ? " Have missing info from ProductRegistry.\n" : "");
0174     }
0175 
0176     //check consistency with all Intervals
0177     if (e.productRegistry().cacheIdentifier() != e.getRun().productRegistry().cacheIdentifier()) {
0178       throw cms::Exception("ProvenanceError")
0179           << "The registry cache id for Event ( " << e.productRegistry().cacheIdentifier()
0180           << " ) does not match the one for Run ( " << e.getRun().productRegistry().cacheIdentifier() << " )";
0181     }
0182     if (e.productRegistry().cacheIdentifier() != e.getLuminosityBlock().productRegistry().cacheIdentifier()) {
0183       throw cms::Exception("ProvenanceError")
0184           << "The registry cache id for Event ( " << e.productRegistry().cacheIdentifier()
0185           << " ) does not match the one for LuminosityBlock ( "
0186           << e.getLuminosityBlock().productRegistry().cacheIdentifier() << " )";
0187     }
0188   }
0189 
0190   //
0191   // const member functions
0192   //
0193 
0194   //
0195   // static member functions
0196   //
0197   void ProvenanceCheckerOutputModule::fillDescriptions(ConfigurationDescriptions& descriptions) {
0198     ParameterSetDescription desc;
0199     one::OutputModule<>::fillDescription(desc);
0200     descriptions.add("provenanceChecker", desc);
0201   }
0202 }  // namespace edm
0203 using edm::ProvenanceCheckerOutputModule;
0204 DEFINE_FWK_MODULE(ProvenanceCheckerOutputModule);