CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_1/src/FWCore/Framework/src/EventPrincipal.cc

Go to the documentation of this file.
00001 #include "FWCore/Framework/interface/EventPrincipal.h"
00002 
00003 #include "DataFormats/Common/interface/BasicHandle.h"
00004 #include "DataFormats/Provenance/interface/BranchIDList.h"
00005 #include "DataFormats/Provenance/interface/BranchIDListRegistry.h"
00006 #include "DataFormats/Provenance/interface/BranchListIndex.h"
00007 #include "DataFormats/Provenance/interface/ProductIDToBranchID.h"
00008 #include "DataFormats/Provenance/interface/ProductRegistry.h"
00009 #include "DataFormats/Provenance/interface/Provenance.h"
00010 #include "FWCore/Framework/interface/DelayedReader.h"
00011 #include "FWCore/Framework/interface/Group.h"
00012 #include "FWCore/Framework/interface/LuminosityBlockPrincipal.h"
00013 #include "FWCore/Framework/interface/UnscheduledHandler.h"
00014 #include "FWCore/Framework/interface/ProductDeletedException.h"
00015 #include "FWCore/Utilities/interface/Algorithms.h"
00016 #include "FWCore/Utilities/interface/EDMException.h"
00017 
00018 #include <algorithm>
00019 
00020 namespace edm {
00021   EventPrincipal::EventPrincipal(
00022         boost::shared_ptr<ProductRegistry const> reg,
00023         ProcessConfiguration const& pc,
00024         HistoryAppender* historyAppender) :
00025     Base(reg, pc, InEvent, historyAppender),
00026           aux_(),
00027           luminosityBlockPrincipal_(),
00028           branchMapperPtr_(),
00029           unscheduledHandler_(),
00030           moduleLabelsRunning_(),
00031           eventSelectionIDs_(new EventSelectionIDVector),
00032           branchListIndexes_(new BranchListIndexes),
00033           branchListIndexToProcessIndex_() {}
00034 
00035   void
00036   EventPrincipal::clearEventPrincipal() {
00037     clearPrincipal();
00038     aux_ = EventAuxiliary();
00039     luminosityBlockPrincipal_.reset();
00040     branchMapperPtr_.reset();
00041     unscheduledHandler_.reset();
00042     moduleLabelsRunning_.clear();
00043     eventSelectionIDs_->clear();
00044     branchListIndexes_->clear();
00045     branchListIndexToProcessIndex_.clear();
00046   }
00047 
00048   void
00049   EventPrincipal::fillEventPrincipal(EventAuxiliary const& aux,
00050         boost::shared_ptr<LuminosityBlockPrincipal> lbp,
00051         boost::shared_ptr<EventSelectionIDVector> eventSelectionIDs,
00052         boost::shared_ptr<BranchListIndexes> branchListIndexes,
00053         boost::shared_ptr<BranchMapper> mapper,
00054         DelayedReader* reader) {
00055     fillPrincipal(aux.processHistoryID(), reader);
00056     aux_ = aux;
00057     luminosityBlockPrincipal_ = lbp;
00058     if(eventSelectionIDs) {
00059       eventSelectionIDs_ = eventSelectionIDs;
00060     }
00061     aux_.setProcessHistoryID(processHistoryID());
00062 
00063     branchMapperPtr_ = mapper;
00064 
00065     if(branchListIndexes) {
00066       branchListIndexes_ = branchListIndexes;
00067     }
00068 
00069     if(productRegistry().productProduced(InEvent)) {
00070       // Add index into BranchIDListRegistry for products produced this process
00071       branchListIndexes_->push_back(productRegistry().producedBranchListIndex());
00072     }
00073 
00074     // Fill in helper map for Branch to ProductID mapping
00075     for(BranchListIndexes::const_iterator
00076         it = branchListIndexes_->begin(),
00077         itEnd = branchListIndexes_->end();
00078         it != itEnd; ++it) {
00079       ProcessIndex pix = it - branchListIndexes_->begin();
00080       branchListIndexToProcessIndex_.insert(std::make_pair(*it, pix));
00081     }
00082 
00083     // Fill in the product ID's in the groups.
00084     for(const_iterator it = this->begin(), itEnd = this->end(); it != itEnd; ++it) {
00085       (*it)->setProvenance(branchMapperPtr(), processHistoryID(), branchIDToProductID((*it)->branchDescription().branchID()));
00086     }
00087   }
00088 
00089   void
00090   EventPrincipal::setLuminosityBlockPrincipal(boost::shared_ptr<LuminosityBlockPrincipal> const& lbp) {
00091     luminosityBlockPrincipal_ = lbp;
00092   }
00093 
00094   RunPrincipal const&
00095   EventPrincipal::runPrincipal() const {
00096     return luminosityBlockPrincipal().runPrincipal();
00097   }
00098 
00099   RunPrincipal &
00100   EventPrincipal::runPrincipal() {
00101     return luminosityBlockPrincipal().runPrincipal();
00102   }
00103 
00104   void
00105   EventPrincipal::put(
00106         ConstBranchDescription const& bd,
00107         WrapperOwningHolder const& edp,
00108         ProductProvenance const& productProvenance) {
00109 
00110     // assert commented out for DaqSource.  When DaqSource no longer uses put(), the assert can be restored.
00111     //assert(produced());
00112     if(!edp.isValid()) {
00113       throw Exception(errors::InsertFailure, "Null Pointer")
00114         << "put: Cannot put because ptr to product is null."
00115         << "\n";
00116     }
00117     branchMapperPtr()->insertIntoSet(productProvenance);
00118     Group* g = getExistingGroup(bd.branchID());
00119     assert(g);
00120     checkUniquenessAndType(edp, g);
00121     // Group assumes ownership
00122     g->putProduct(edp, productProvenance);
00123   }
00124 
00125   void
00126   EventPrincipal::putOnRead(
00127         ConstBranchDescription const& bd,
00128         void const* product,
00129         ProductProvenance const& productProvenance) {
00130 
00131     assert(!bd.produced());
00132     branchMapperPtr()->insertIntoSet(productProvenance);
00133     Group* g = getExistingGroup(bd.branchID());
00134     assert(g);
00135     WrapperOwningHolder const edp(product, g->productData().getInterface());
00136     checkUniquenessAndType(edp, g);
00137     // Group assumes ownership
00138     g->putProduct(edp, productProvenance);
00139   }
00140 
00141   void
00142   EventPrincipal::resolveProduct_(Group const& g, bool fillOnDemand) const {
00143     // Try unscheduled production.
00144     if(g.onDemand()) {
00145       if(fillOnDemand) {
00146         unscheduledFill(g.branchDescription().moduleLabel());
00147       }
00148       return;
00149     }
00150 
00151     if(g.branchDescription().produced()) return; // nothing to do.
00152     if(g.product()) return; // nothing to do.
00153     if(g.productUnavailable()) return; // nothing to do.
00154     if(!reader()) return; // nothing to do.
00155 
00156     // must attempt to load from persistent store
00157     BranchKey const bk = BranchKey(g.branchDescription());
00158     WrapperOwningHolder edp(reader()->getProduct(bk, g.productData().getInterface(), this));
00159 
00160     // Now fix up the Group
00161     checkUniquenessAndType(edp, &g);
00162     g.putProduct(edp);
00163   }
00164 
00165   BranchID
00166   EventPrincipal::pidToBid(ProductID const& pid) const {
00167     if(!pid.isValid()) {
00168       throw Exception(errors::ProductNotFound, "InvalidID")
00169         << "get by product ID: invalid ProductID supplied\n";
00170     }
00171     return productIDToBranchID(pid, BranchIDListRegistry::instance()->data(), *branchListIndexes_);
00172   }
00173 
00174   ProductID
00175   EventPrincipal::branchIDToProductID(BranchID const& bid) const {
00176     if(!bid.isValid()) {
00177       throw Exception(errors::NotFound, "InvalidID")
00178         << "branchIDToProductID: invalid BranchID supplied\n";
00179     }
00180     typedef BranchIDListHelper::BranchIDToIndexMap BIDToIndexMap;
00181     typedef BIDToIndexMap::const_iterator Iter;
00182     typedef std::pair<Iter, Iter> IndexRange;
00183 
00184     BIDToIndexMap const& branchIDToIndexMap = BranchIDListRegistry::instance()->extra().branchIDToIndexMap();
00185     IndexRange range = branchIDToIndexMap.equal_range(bid);
00186     for(Iter it = range.first; it != range.second; ++it) {
00187       BranchListIndex blix = it->second.first;
00188       std::map<BranchListIndex, ProcessIndex>::const_iterator i = branchListIndexToProcessIndex_.find(blix);
00189       if(i != branchListIndexToProcessIndex_.end()) {
00190         ProductIndex productIndex = it->second.second;
00191         ProcessIndex processIndex = i->second;
00192         return ProductID(processIndex+1, productIndex+1);
00193       }
00194     }
00195     // cannot throw, because some products may legitimately not have product ID's (e.g. pile-up).
00196     return ProductID();
00197   }
00198 
00199   static void throwProductDeletedException(ProductID const&pid, edm::EventPrincipal::ConstGroupPtr const g) {
00200     ProductDeletedException exception;
00201     exception<<"get by product ID: The product with given id: "<<pid
00202     <<"\ntype: "<<g->productType()
00203     <<"\nproduct instance name: "<<g->productInstanceName()
00204     <<"\nprocess name: "<<g->processName()
00205     <<"\nwas already deleted. This is a configuration error. Please change the configuration of the module which caused this exception to state it reads this data.";
00206     throw exception;    
00207   }
00208   
00209   BasicHandle
00210   EventPrincipal::getByProductID(ProductID const& pid) const {
00211     BranchID bid = pidToBid(pid);
00212     ConstGroupPtr const g = getGroup(bid, true, true);
00213     if(g == 0) {
00214       boost::shared_ptr<cms::Exception> whyFailed(new Exception(errors::ProductNotFound, "InvalidID"));
00215       *whyFailed
00216         << "get by product ID: no product with given id: " << pid << "\n";
00217       return BasicHandle(whyFailed);
00218     }
00219 
00220     // Was this already deleted?
00221     if(g->productWasDeleted()) {
00222       throwProductDeletedException(pid,g);
00223     }
00224     // Check for case where we tried on demand production and
00225     // it failed to produce the object
00226     if(g->onDemand()) {
00227       boost::shared_ptr<cms::Exception> whyFailed(new Exception(errors::ProductNotFound, "InvalidID"));
00228       *whyFailed
00229         << "get by product ID: no product with given id: " << pid << "\n"
00230         << "onDemand production failed to produce it.\n";
00231       return BasicHandle(whyFailed);
00232     }
00233     return BasicHandle(g->productData());
00234   }
00235 
00236   WrapperHolder
00237   EventPrincipal::getIt(ProductID const& pid) const {
00238     return getByProductID(pid).wrapperHolder();
00239   }
00240 
00241   Provenance
00242   EventPrincipal::getProvenance(ProductID const& pid) const {
00243     BranchID bid = pidToBid(pid);
00244     return getProvenance(bid);
00245   }
00246 
00247   void
00248   EventPrincipal::setUnscheduledHandler(boost::shared_ptr<UnscheduledHandler> iHandler) {
00249     unscheduledHandler_ = iHandler;
00250   }
00251 
00252   boost::shared_ptr<UnscheduledHandler>
00253   EventPrincipal::unscheduledHandler() const {
00254      return unscheduledHandler_;
00255   }
00256 
00257   EventSelectionIDVector const&
00258   EventPrincipal::eventSelectionIDs() const {
00259     return *eventSelectionIDs_;
00260   }
00261 
00262   BranchListIndexes const&
00263   EventPrincipal::branchListIndexes() const {
00264     return *branchListIndexes_;
00265   }
00266 
00267   bool
00268   EventPrincipal::unscheduledFill(std::string const& moduleLabel) const {
00269 
00270     // If it is a module already currently running in unscheduled
00271     // mode, then there is a circular dependency related to which
00272     // EDProducts modules require and produce.  There is no safe way
00273     // to recover from this.  Here we check for this problem and throw
00274     // an exception.
00275     std::vector<std::string>::const_iterator i =
00276       find_in_all(moduleLabelsRunning_, moduleLabel);
00277 
00278     if(i != moduleLabelsRunning_.end()) {
00279       throw Exception(errors::LogicError)
00280         << "Hit circular dependency while trying to run an unscheduled module.\n"
00281         << "Current implementation of unscheduled execution cannot always determine\n"
00282         << "the proper order for module execution.  It is also possible the modules\n"
00283         << "have a built in circular dependence that will not work with any order.\n"
00284         << "In the first case, scheduling some or all required modules in paths will help.\n"
00285         << "In the second case, the modules themselves will have to be fixed.\n";
00286     }
00287 
00288     moduleLabelsRunning_.push_back(moduleLabel);
00289 
00290     if(unscheduledHandler_) {
00291       unscheduledHandler_->tryToFill(moduleLabel, *const_cast<EventPrincipal*>(this));
00292     }
00293     moduleLabelsRunning_.pop_back();
00294     return true;
00295   }
00296 }