CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/FWCore/Modules/src/ProvenanceCheckerOutputModule.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     Modules
00004 // Class  :     ProvenanceCheckerOutputModule
00005 //
00006 // Implementation:
00007 //     Checks the consistency of provenance stored in the framework
00008 //
00009 // Original Author:  Chris Jones
00010 //         Created:  Thu Sep 11 19:24:13 EDT 2008
00011 //
00012 
00013 // system include files
00014 #include "FWCore/Framework/interface/OutputModule.h"
00015 #include "FWCore/Framework/interface/MakerMacros.h"
00016 #include "FWCore/Framework/interface/EventPrincipal.h"
00017 #include "FWCore/Utilities/interface/Exception.h"
00018 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00019 #include "DataFormats/Common/interface/OutputHandle.h"
00020 #include "DataFormats/Provenance/interface/ProductRegistry.h"
00021 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
00022 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
00023 
00024 // user include files
00025 
00026 namespace edm {
00027    class ParameterSet;
00028    class ProvenanceCheckerOutputModule : public OutputModule {
00029    public:
00030       // We do not take ownership of passed stream.
00031       explicit ProvenanceCheckerOutputModule(ParameterSet const& pset);
00032       virtual ~ProvenanceCheckerOutputModule();
00033       static void fillDescriptions(ConfigurationDescriptions& descriptions);
00034 
00035    private:
00036       virtual void write(EventPrincipal const& e);
00037       virtual void writeLuminosityBlock(LuminosityBlockPrincipal const&){}
00038       virtual void writeRun(RunPrincipal const&){}
00039    };
00040 
00041 
00042 //
00043 // constants, enums and typedefs
00044 //
00045 
00046 //
00047 // static data member definitions
00048 //
00049 
00050 //
00051 // constructors and destructor
00052 //
00053    ProvenanceCheckerOutputModule::ProvenanceCheckerOutputModule(ParameterSet const& pset) :
00054    OutputModule(pset)
00055    {
00056    }
00057 
00058 // ProvenanceCheckerOutputModule::ProvenanceCheckerOutputModule(ProvenanceCheckerOutputModule const& rhs)
00059 // {
00060 //    // do actual copying here;
00061 // }
00062 
00063    ProvenanceCheckerOutputModule::~ProvenanceCheckerOutputModule()
00064    {
00065    }
00066 
00067 //
00068 // assignment operators
00069 //
00070 // ProvenanceCheckerOutputModule const& ProvenanceCheckerOutputModule::operator=(ProvenanceCheckerOutputModule const& rhs)
00071 // {
00072 //   //An exception safe implementation is
00073 //   ProvenanceCheckerOutputModule temp(rhs);
00074 //   swap(rhs);
00075 //
00076 //   return *this;
00077 // }
00078 
00079    namespace {
00080      void markAncestors(ProductProvenance const& iInfo,
00081                              BranchMapper const& iMapper,
00082                              std::map<BranchID, bool>& oMap,
00083                              std::set<BranchID>& oMapperMissing) {
00084        for(std::vector<BranchID>::const_iterator it = iInfo.parentage().parents().begin(),
00085           itEnd = iInfo.parentage().parents().end();
00086           it != itEnd;
00087           ++it) {
00088          //Don't look for parents if we've previously looked at the parents
00089          if(oMap.find(*it) == oMap.end()) {
00090             //use side effect of calling operator[] which is if the item isn't there it will add it as 'false'
00091             oMap[*it];
00092             ProductProvenance const* pInfo = iMapper.branchIDToProvenance(*it);
00093             if(pInfo) {
00094                markAncestors(*pInfo, iMapper, oMap, oMapperMissing);
00095             } else {
00096                oMapperMissing.insert(*it);
00097             }
00098          }
00099        }
00100      }
00101    }
00102 
00103    void
00104    ProvenanceCheckerOutputModule::write(EventPrincipal const& e) {
00105       //check ProductProvenance's parents to see if they are in the ProductProvenance list
00106       boost::shared_ptr<BranchMapper> mapperPtr = e.branchMapperPtr();
00107 
00108       std::map<BranchID, bool> seenParentInPrincipal;
00109       std::set<BranchID> missingFromMapper;
00110       std::set<BranchID> missingProductProvenance;
00111 
00112       std::map<BranchID, boost::shared_ptr<ProductHolderBase> > idToProductHolder;
00113       for(EventPrincipal::const_iterator it = e.begin(), itEnd = e.end();
00114           it != itEnd;
00115           ++it) {
00116         if(*it && (*it)->singleProduct()) {
00117             BranchID branchID = (*it)->branchDescription().branchID();
00118             idToProductHolder[branchID] = (*it);
00119             if((*it)->productUnavailable()) {
00120                //This call seems to have a side effect of filling the 'ProductProvenance' in the ProductHolder
00121                OutputHandle const oh = e.getForOutput(branchID, false);
00122 
00123                bool cannotFindProductProvenance=false;
00124                if(!(*it)->productProvenancePtr()) {
00125                   missingProductProvenance.insert(branchID);
00126                   cannotFindProductProvenance=true;
00127                }
00128                ProductProvenance const* pInfo = mapperPtr->branchIDToProvenance(branchID);
00129                if(!pInfo) {
00130                   missingFromMapper.insert(branchID);
00131                   continue;
00132                }
00133                if(cannotFindProductProvenance) {
00134                   continue;
00135                }
00136                markAncestors(*((*it)->productProvenancePtr()), *mapperPtr, seenParentInPrincipal, missingFromMapper);
00137             }
00138             seenParentInPrincipal[branchID] = true;
00139          }
00140       }
00141 
00142       //Determine what BranchIDs are in the product registry
00143       ProductRegistry const& reg = e.productRegistry();
00144       ProductRegistry::ProductList const prodList = reg.productList();
00145       std::set<BranchID> branchesInReg;
00146       for(ProductRegistry::ProductList::const_iterator it = prodList.begin(), itEnd = prodList.end();
00147           it != itEnd;
00148           ++it) {
00149          branchesInReg.insert(it->second.branchID());
00150       }
00151 
00152       std::set<BranchID> missingFromPrincipal;
00153       std::set<BranchID> missingFromReg;
00154       for(std::map<BranchID, bool>::iterator it = seenParentInPrincipal.begin(), itEnd = seenParentInPrincipal.end();
00155           it != itEnd;
00156           ++it) {
00157          if(!it->second) {
00158             missingFromPrincipal.insert(it->first);
00159          }
00160          if(branchesInReg.find(it->first) == branchesInReg.end()) {
00161             missingFromReg.insert(it->first);
00162          }
00163       }
00164 
00165       if(missingFromMapper.size()) {
00166          LogError("ProvenanceChecker") << "Missing the following BranchIDs from BranchMapper\n";
00167          for(std::set<BranchID>::iterator it = missingFromMapper.begin(), itEnd = missingFromMapper.end();
00168              it != itEnd;
00169              ++it) {
00170             LogProblem("ProvenanceChecker") << *it<<" "<<idToProductHolder[*it]->branchDescription();
00171          }
00172       }
00173       if(missingFromPrincipal.size()) {
00174          LogError("ProvenanceChecker") << "Missing the following BranchIDs from EventPrincipal\n";
00175          for(std::set<BranchID>::iterator it = missingFromPrincipal.begin(), itEnd = missingFromPrincipal.end();
00176              it != itEnd;
00177              ++it) {
00178             LogProblem("ProvenanceChecker") << *it;
00179          }
00180       }
00181 
00182       if(missingProductProvenance.size()) {
00183          LogError("ProvenanceChecker") << "The ProductHolders for the following BranchIDs have no ProductProvenance\n";
00184          for(std::set<BranchID>::iterator it = missingProductProvenance.begin(), itEnd = missingProductProvenance.end();
00185              it != itEnd;
00186              ++it) {
00187             LogProblem("ProvenanceChecker") << *it<<" "<<idToProductHolder[*it]->branchDescription();
00188          }
00189       }
00190 
00191       if(missingFromReg.size()) {
00192          LogError("ProvenanceChecker") << "Missing the following BranchIDs from ProductRegistry\n";
00193          for(std::set<BranchID>::iterator it = missingFromReg.begin(), itEnd = missingFromReg.end();
00194              it != itEnd;
00195              ++it) {
00196             LogProblem("ProvenanceChecker") << *it;
00197          }
00198       }
00199 
00200       if(missingFromMapper.size() || missingFromPrincipal.size() || missingProductProvenance.size() || missingFromReg.size()) {
00201          throw cms::Exception("ProvenanceError")
00202          << (missingFromMapper.size() || missingFromPrincipal.size() ? "Having missing ancestors" : "")
00203          << (missingFromMapper.size() ? " from BranchMapper" : "")
00204          << (missingFromMapper.size() && missingFromPrincipal.size() ? " and" : "")
00205          << (missingFromPrincipal.size() ? " from EventPrincipal" : "")
00206          << (missingFromMapper.size() || missingFromPrincipal.size() ? ".\n" : "")
00207          << (missingProductProvenance.size() ? " Have missing ProductProvenance's from ProductHolder in EventPrincipal.\n" : "")
00208          << (missingFromReg.size() ? " Have missing info from ProductRegistry.\n" : "");
00209       }
00210    }
00211 
00212 //
00213 // const member functions
00214 //
00215 
00216 //
00217 // static member functions
00218 //
00219   void
00220   ProvenanceCheckerOutputModule::fillDescriptions(ConfigurationDescriptions& descriptions) {
00221     ParameterSetDescription desc;
00222     OutputModule::fillDescription(desc);
00223     descriptions.add("provenanceChecker", desc);
00224   }
00225 }
00226 using edm::ProvenanceCheckerOutputModule;
00227 DEFINE_FWK_MODULE(ProvenanceCheckerOutputModule);