CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_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/BranchIDListHelper.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         boost::shared_ptr<BranchIDListHelper const> branchIDListHelper,
00024         ProcessConfiguration const& pc,
00025         HistoryAppender* historyAppender) :
00026     Base(reg, pc, InEvent, historyAppender),
00027           aux_(),
00028           luminosityBlockPrincipal_(),
00029           branchMapperPtr_(),
00030           unscheduledHandler_(),
00031           moduleLabelsRunning_(),
00032           eventSelectionIDs_(new EventSelectionIDVector),
00033           branchIDListHelper_(branchIDListHelper),
00034           branchListIndexes_(new BranchListIndexes),
00035           branchListIndexToProcessIndex_() {}
00036 
00037   void
00038   EventPrincipal::clearEventPrincipal() {
00039     clearPrincipal();
00040     aux_ = EventAuxiliary();
00041     luminosityBlockPrincipal_.reset();
00042     branchMapperPtr_.reset();
00043     unscheduledHandler_.reset();
00044     moduleLabelsRunning_.clear();
00045     eventSelectionIDs_->clear();
00046     branchListIndexes_->clear();
00047     branchListIndexToProcessIndex_.clear();
00048   }
00049 
00050   void
00051   EventPrincipal::fillEventPrincipal(EventAuxiliary const& aux,
00052         boost::shared_ptr<EventSelectionIDVector> eventSelectionIDs,
00053         boost::shared_ptr<BranchListIndexes> branchListIndexes,
00054         boost::shared_ptr<BranchMapper> mapper,
00055         DelayedReader* reader) {
00056     fillPrincipal(aux.processHistoryID(), reader);
00057     aux_ = aux;
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().originalBranchID()));
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   void
00100   EventPrincipal::put(
00101         ConstBranchDescription const& bd,
00102         WrapperOwningHolder const& edp,
00103         ProductProvenance const& productProvenance) {
00104 
00105     // assert commented out for DaqSource.  When DaqSource no longer uses put(), the assert can be restored.
00106     //assert(produced());
00107     if(!edp.isValid()) {
00108       throw Exception(errors::InsertFailure, "Null Pointer")
00109         << "put: Cannot put because ptr to product is null."
00110         << "\n";
00111     }
00112     branchMapperPtr()->insertIntoSet(productProvenance);
00113     Group* g = getExistingGroup(bd.branchID());
00114     assert(g);
00115     checkUniquenessAndType(edp, g);
00116     // Group assumes ownership
00117     g->putProduct(edp, productProvenance);
00118   }
00119 
00120   void
00121   EventPrincipal::putOnRead(
00122         ConstBranchDescription const& bd,
00123         void const* product,
00124         ProductProvenance const& productProvenance) {
00125 
00126     assert(!bd.produced());
00127     branchMapperPtr()->insertIntoSet(productProvenance);
00128     Group* g = getExistingGroup(bd.branchID());
00129     assert(g);
00130     WrapperOwningHolder const edp(product, g->productData().getInterface());
00131     checkUniquenessAndType(edp, g);
00132     // Group assumes ownership
00133     g->putProduct(edp, productProvenance);
00134   }
00135 
00136   void
00137   EventPrincipal::resolveProduct_(Group const& g, bool fillOnDemand) const {
00138     // Try unscheduled production.
00139     if(g.onDemand()) {
00140       if(fillOnDemand) {
00141         unscheduledFill(g.branchDescription().moduleLabel());
00142       }
00143       return;
00144     }
00145 
00146     if(g.branchDescription().produced()) return; // nothing to do.
00147     if(g.product()) return; // nothing to do.
00148     if(g.productUnavailable()) return; // nothing to do.
00149     if(!reader()) return; // nothing to do.
00150 
00151     // must attempt to load from persistent store
00152     BranchKey const bk = BranchKey(g.branchDescription());
00153     WrapperOwningHolder edp(reader()->getProduct(bk, g.productData().getInterface(), this));
00154 
00155     // Now fix up the Group
00156     checkUniquenessAndType(edp, &g);
00157     g.putProduct(edp);
00158   }
00159 
00160   BranchID
00161   EventPrincipal::pidToBid(ProductID const& pid) const {
00162     if(!pid.isValid()) {
00163       throw Exception(errors::ProductNotFound, "InvalidID")
00164         << "get by product ID: invalid ProductID supplied\n";
00165     }
00166     return productIDToBranchID(pid, branchIDListHelper_->branchIDLists(), *branchListIndexes_);
00167   }
00168 
00169   ProductID
00170   EventPrincipal::branchIDToProductID(BranchID const& bid) const {
00171     if(!bid.isValid()) {
00172       throw Exception(errors::NotFound, "InvalidID")
00173         << "branchIDToProductID: invalid BranchID supplied\n";
00174     }
00175     typedef BranchIDListHelper::BranchIDToIndexMap BIDToIndexMap;
00176     typedef BIDToIndexMap::const_iterator Iter;
00177     typedef std::pair<Iter, Iter> IndexRange;
00178 
00179     IndexRange range = branchIDListHelper_->branchIDToIndexMap().equal_range(bid);
00180     for(Iter it = range.first; it != range.second; ++it) {
00181       BranchListIndex blix = it->second.first;
00182       std::map<BranchListIndex, ProcessIndex>::const_iterator i = branchListIndexToProcessIndex_.find(blix);
00183       if(i != branchListIndexToProcessIndex_.end()) {
00184         ProductIndex productIndex = it->second.second;
00185         ProcessIndex processIndex = i->second;
00186         return ProductID(processIndex+1, productIndex+1);
00187       }
00188     }
00189     // cannot throw, because some products may legitimately not have product ID's (e.g. pile-up).
00190     return ProductID();
00191   }
00192 
00193   static void throwProductDeletedException(ProductID const&pid, edm::EventPrincipal::ConstGroupPtr const g) {
00194     ProductDeletedException exception;
00195     exception<<"get by product ID: The product with given id: "<<pid
00196     <<"\ntype: "<<g->productType()
00197     <<"\nproduct instance name: "<<g->productInstanceName()
00198     <<"\nprocess name: "<<g->processName()
00199     <<"\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.";
00200     throw exception;    
00201   }
00202   
00203   BasicHandle
00204   EventPrincipal::getByProductID(ProductID const& pid) const {
00205     BranchID bid = pidToBid(pid);
00206     ConstGroupPtr const g = getGroup(bid, true, true);
00207     if(g == 0) {
00208       boost::shared_ptr<cms::Exception> whyFailed(new Exception(errors::ProductNotFound, "InvalidID"));
00209       *whyFailed
00210         << "get by product ID: no product with given id: " << pid << "\n";
00211       return BasicHandle(whyFailed);
00212     }
00213 
00214     // Was this already deleted?
00215     if(g->productWasDeleted()) {
00216       throwProductDeletedException(pid,g);
00217     }
00218     // Check for case where we tried on demand production and
00219     // it failed to produce the object
00220     if(g->onDemand()) {
00221       boost::shared_ptr<cms::Exception> whyFailed(new Exception(errors::ProductNotFound, "InvalidID"));
00222       *whyFailed
00223         << "get by product ID: no product with given id: " << pid << "\n"
00224         << "onDemand production failed to produce it.\n";
00225       return BasicHandle(whyFailed);
00226     }
00227     return BasicHandle(g->productData());
00228   }
00229 
00230   WrapperHolder
00231   EventPrincipal::getIt(ProductID const& pid) const {
00232     return getByProductID(pid).wrapperHolder();
00233   }
00234 
00235   Provenance
00236   EventPrincipal::getProvenance(ProductID const& pid) const {
00237     BranchID bid = pidToBid(pid);
00238     return getProvenance(bid);
00239   }
00240 
00241   void
00242   EventPrincipal::setUnscheduledHandler(boost::shared_ptr<UnscheduledHandler> iHandler) {
00243     unscheduledHandler_ = iHandler;
00244   }
00245 
00246   boost::shared_ptr<UnscheduledHandler>
00247   EventPrincipal::unscheduledHandler() const {
00248      return unscheduledHandler_;
00249   }
00250 
00251   EventSelectionIDVector const&
00252   EventPrincipal::eventSelectionIDs() const {
00253     return *eventSelectionIDs_;
00254   }
00255 
00256   BranchListIndexes const&
00257   EventPrincipal::branchListIndexes() const {
00258     return *branchListIndexes_;
00259   }
00260 
00261   bool
00262   EventPrincipal::unscheduledFill(std::string const& moduleLabel) const {
00263 
00264     // If it is a module already currently running in unscheduled
00265     // mode, then there is a circular dependency related to which
00266     // EDProducts modules require and produce.  There is no safe way
00267     // to recover from this.  Here we check for this problem and throw
00268     // an exception.
00269     std::vector<std::string>::const_iterator i =
00270       find_in_all(moduleLabelsRunning_, moduleLabel);
00271 
00272     if(i != moduleLabelsRunning_.end()) {
00273       throw Exception(errors::LogicError)
00274         << "Hit circular dependency while trying to run an unscheduled module.\n"
00275         << "Current implementation of unscheduled execution cannot always determine\n"
00276         << "the proper order for module execution.  It is also possible the modules\n"
00277         << "have a built in circular dependence that will not work with any order.\n"
00278         << "In the first case, scheduling some or all required modules in paths will help.\n"
00279         << "In the second case, the modules themselves will have to be fixed.\n";
00280     }
00281 
00282     moduleLabelsRunning_.push_back(moduleLabel);
00283 
00284     if(unscheduledHandler_) {
00285       unscheduledHandler_->tryToFill(moduleLabel, *const_cast<EventPrincipal*>(this));
00286     }
00287     moduleLabelsRunning_.pop_back();
00288     return true;
00289   }
00290 }