Back to home page

Project CMSSW displayed by LXR

 
 

    


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

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