CMS 3D CMS Logo

Principal.cc

Go to the documentation of this file.
00001 
00004 #include <algorithm>
00005 #include <sstream>
00006 #include <stdexcept>
00007 
00008 #include "FWCore/Framework/interface/Principal.h"
00009 #include "DataFormats/Provenance/interface/BranchMapper.h"
00010 #include "DataFormats/Provenance/interface/ProcessHistory.h"
00011 #include "DataFormats/Provenance/interface/ProcessHistoryRegistry.h"
00012 #include "DataFormats/Provenance/interface/ProductRegistry.h"
00013 #include "DataFormats/Provenance/interface/ProductStatus.h"
00014 #include "DataFormats/Common/interface/BasicHandle.h"
00015 #include "FWCore/Utilities/interface/TypeID.h"
00016 #include "FWCore/Utilities/interface/EDMException.h"
00017 #include "FWCore/Utilities/interface/Algorithms.h"
00018 #include "FWCore/Framework/interface/Selector.h"
00019 //using boost::lambda::_1;
00020 
00021 namespace edm {
00022 
00023   Principal::Principal(boost::shared_ptr<ProductRegistry const> reg,
00024                        ProcessConfiguration const& pc,
00025                        ProcessHistoryID const& hist,
00026                        boost::shared_ptr<BranchMapper> mapper,
00027                        boost::shared_ptr<DelayedReader> rtrv) :
00028     EDProductGetter(),
00029     processHistoryID_(hist),
00030     processHistoryPtr_(boost::shared_ptr<ProcessHistory>(new ProcessHistory)),
00031     processConfiguration_(pc),
00032     processHistoryModified_(false),
00033     groups_(),
00034     preg_(reg),
00035     branchMapperPtr_(mapper),
00036     store_(rtrv)
00037   {
00038     if (processHistoryID_.isValid()) {
00039       ProcessHistoryRegistry& history(*ProcessHistoryRegistry::instance());
00040       assert(history.notEmpty());
00041       bool found = history.getMapped(processHistoryID_, *processHistoryPtr_);
00042       assert(found);
00043     }
00044   }
00045 
00046   Principal::~Principal() {
00047   }
00048 
00049   Group*
00050   Principal::getExistingGroup(Group const& group) {
00051     GroupCollection::const_iterator it = groups_.find(group.productDescription().branchID());
00052     if (it == groups_.end()) return 0;
00053     return it->second.get();
00054   }
00055 
00056   void 
00057   Principal::addGroup_(std::auto_ptr<Group> group) {
00058     ConstBranchDescription const& bd = group->productDescription();
00059     assert (!bd.className().empty());
00060     assert (!bd.friendlyClassName().empty());
00061     assert (!bd.moduleLabel().empty());
00062     assert (!bd.processName().empty());
00063     SharedGroupPtr g(group);
00064     groups_.insert(std::make_pair(bd.branchID(), g));
00065   }
00066 
00067   void 
00068   Principal::replaceGroup(std::auto_ptr<Group> group) {
00069     ConstBranchDescription const& bd = group->productDescription();
00070     assert (!bd.className().empty());
00071     assert (!bd.friendlyClassName().empty());
00072     assert (!bd.moduleLabel().empty());
00073     assert (!bd.processName().empty());
00074     SharedGroupPtr g(group);
00075     groups_[bd.branchID()]->replace(*g);
00076   }
00077 
00078   void
00079   Principal::addToProcessHistory() const {
00080     if (processHistoryModified_) return;
00081     ProcessHistory& ph = *processHistoryPtr_;
00082     std::string const& processName = processConfiguration_.processName();
00083     for (ProcessHistory::const_iterator it = ph.begin(), itEnd = ph.end(); it != itEnd; ++it) {
00084       if (processName == it->processName()) {
00085         throw edm::Exception(errors::Configuration, "Duplicate Process")
00086           << "The process name " << processName << " was previously used on these products.\n"
00087           << "Please modify the configuration file to use a distinct process name.\n";
00088       }
00089     }
00090     ph.push_back(processConfiguration_);
00091     //OPTIMIZATION NOTE:  As of 0_9_0_pre3
00092     // For very simple Sources (e.g. EmptySource) this routine takes up nearly 50% of the time per event.
00093     // 96% of the time for this routine is being spent in computing the
00094     // ProcessHistory id which happens because we are reconstructing the ProcessHistory for each event.
00095     // (The process ID is first computed in the call to 'insertMapped(..)' below.)
00096     // It would probably be better to move the ProcessHistory construction out to somewhere
00097     // which persists for longer than one Event
00098     ProcessHistoryRegistry::instance()->insertMapped(ph);
00099     processHistoryID_ = ph.id();
00100     processHistoryModified_ = true;
00101   }
00102 
00103   ProcessHistory const&
00104   Principal::processHistory() const {
00105     return *processHistoryPtr_;
00106   }
00107 
00108   Principal::SharedConstGroupPtr const
00109   Principal::getGroup(BranchID const& bid, bool resolveProd, bool resolveProv, bool fillOnDemand) const {
00110     GroupCollection::const_iterator it = groups_.find(bid);
00111     if (it == groups_.end()) {
00112       return SharedConstGroupPtr();
00113     }
00114     SharedConstGroupPtr const& g = it->second;
00115     if (resolveProv && (g->provenanceAvailable() || g->onDemand())) {
00116       if(g->onDemand()) {
00117          //must execute the unscheduled to get the provenance
00118          this->resolveProduct(*g, true);
00119          //check if this failed (say because of a caught exception)
00120          if( 0 == g->product()) {
00121             //behavior is the same as if the group wasn't there
00122             return SharedConstGroupPtr();
00123          }
00124       }
00125       this->resolveProvenance(*g);
00126     }
00127     if (resolveProd && !g->productUnavailable()) {
00128       this->resolveProduct(*g, fillOnDemand);
00129       if(g->onDemand() && 0 == g->product()) {
00130          //behavior is the same as if the group wasn't there
00131          return SharedConstGroupPtr();
00132       }
00133     }
00134     return g;
00135   }
00136 
00137   BasicHandle
00138   Principal::getBySelector(TypeID const& productType, 
00139                            SelectorBase const& sel) const {
00140 
00141     BasicHandleVec results;
00142 
00143     int nFound = findGroups(productType,
00144                             preg_->productLookup(),
00145                             sel,
00146                             results,
00147                             true);
00148 
00149     if (nFound == 0) {
00150       boost::shared_ptr<cms::Exception> whyFailed( new edm::Exception(edm::errors::ProductNotFound) );
00151       *whyFailed
00152         << "getBySelector: Found zero products matching all criteria\n"
00153         << "Looking for type: " << productType << "\n";
00154       return BasicHandle(whyFailed);
00155     }
00156     if (nFound > 1) {
00157       throw edm::Exception(edm::errors::ProductNotFound)
00158         << "getBySelector: Found "<<nFound<<" products rather than one which match all criteria\n"
00159         << "Looking for type: " << productType << "\n";
00160     }
00161     return results[0];
00162   }
00163 
00164   BasicHandle
00165   Principal::getByLabel(TypeID const& productType, 
00166                         std::string const& label,
00167                         std::string const& productInstanceName) const {
00168     BasicHandleVec results;
00169 
00170     edm::Selector sel(edm::ModuleLabelSelector(label) &&
00171                       edm::ProductInstanceNameSelector(productInstanceName));
00172 
00173     int nFound = findGroups(productType,
00174                             preg_->productLookup(),
00175                             sel,
00176                             results,
00177                             true);
00178 
00179     if (nFound == 0) {
00180       boost::shared_ptr<cms::Exception> whyFailed( new edm::Exception(edm::errors::ProductNotFound) );
00181       *whyFailed
00182         << "getByLabel: Found zero products matching all criteria\n"
00183         << "Looking for type: " << productType << "\n"
00184         << "Looking for module label: " << label << "\n"
00185         << "Looking for productInstanceName: " << productInstanceName << "\n";
00186       return BasicHandle(whyFailed);
00187     }
00188     if (nFound > 1) {
00189       throw edm::Exception(edm::errors::ProductNotFound)
00190         << "getByLabel: Found "<<nFound<<" products rather than one which match all criteria\n"
00191         << "Looking for type: " << productType << "\n"
00192         << "Looking for module label: " << label << "\n"
00193         << "Looking for productInstanceName: " << productInstanceName << "\n";
00194     }
00195     return results[0];
00196   }
00197 
00198   BasicHandle
00199   Principal::getByLabel(TypeID const& productType,
00200                         std::string const& label,
00201                         std::string const& productInstanceName,
00202                         std::string const& processName) const
00203   {
00204 
00205     BasicHandleVec results;
00206 
00207     edm::Selector sel(edm::ModuleLabelSelector(label) &&
00208                       edm::ProductInstanceNameSelector(productInstanceName) &&
00209                       edm::ProcessNameSelector(processName));
00210 
00211     int nFound = findGroups(productType,
00212                             preg_->productLookup(),
00213                             sel,
00214                             results,
00215                             true);
00216 
00217     if (nFound == 0) {
00218       boost::shared_ptr<cms::Exception> whyFailed( new edm::Exception(edm::errors::ProductNotFound) );
00219       *whyFailed
00220         << "getByLabel: Found zero products matching all criteria\n"
00221         << "Looking for type: " << productType << "\n"
00222         << "Looking for module label: " << label << "\n"
00223         << "Looking for productInstanceName: " << productInstanceName << "\n"
00224         << "Looking for process: " << processName << "\n";
00225       return BasicHandle(whyFailed);
00226     }
00227     if (nFound > 1) {
00228       throw edm::Exception(edm::errors::ProductNotFound)
00229         << "getByLabel: Found "<<nFound<<" products rather than one which match all criteria\n"
00230         << "Looking for type: " << productType << "\n"
00231         << "Looking for module label: " << label << "\n"
00232         << "Looking for productInstanceName: " << productInstanceName << "\n"
00233         << "Looking for process: " << processName << "\n";
00234     }
00235     return results[0];
00236   }
00237  
00238 
00239   void 
00240   Principal::getMany(TypeID const& productType, 
00241                      SelectorBase const& sel,
00242                      BasicHandleVec& results) const {
00243 
00244     findGroups(productType,
00245                preg_->productLookup(),
00246                sel,
00247                results,
00248                false);
00249 
00250     return;
00251   }
00252 
00253   BasicHandle
00254   Principal::getByType(TypeID const& productType) const {
00255 
00256     BasicHandleVec results;
00257 
00258     edm::MatchAllSelector sel;
00259 
00260     int nFound = findGroups(productType,
00261                             preg_->productLookup(),
00262                             sel,
00263                             results,
00264                             true);
00265 
00266     if (nFound == 0) {
00267       boost::shared_ptr<cms::Exception> whyFailed( new edm::Exception(edm::errors::ProductNotFound) );
00268       *whyFailed
00269         << "getByType: Found zero products matching all criteria\n"
00270         << "Looking for type: " << productType << "\n";
00271       return BasicHandle(whyFailed);
00272     }
00273     if (nFound > 1) {
00274       throw edm::Exception(edm::errors::ProductNotFound)
00275         << "getByType: Found "<<nFound <<" products rather than one which match all criteria\n"
00276         << "Looking for type: " << productType << "\n";
00277     }
00278     return results[0];
00279   }
00280 
00281   void 
00282   Principal::getManyByType(TypeID const& productType, 
00283                            BasicHandleVec& results) const {
00284 
00285     edm::MatchAllSelector sel;
00286 
00287     findGroups(productType,
00288                preg_->productLookup(),
00289                sel,
00290                results,
00291                false);
00292     return;
00293   }
00294 
00295   size_t
00296   Principal::getMatchingSequence(TypeID const& typeID,
00297                                  SelectorBase const& selector,
00298                                  BasicHandleVec& results,
00299                                  bool stopIfProcessHasMatch) const {
00300 
00301     // One new argument is the element lookup container
00302     // Otherwise this just passes through the arguments to findGroups
00303     return findGroups(typeID,
00304                       preg_->elementLookup(),
00305                       selector,
00306                       results,
00307                       stopIfProcessHasMatch);
00308   }
00309 
00310   void
00311   Principal::readImmediate() const {
00312     for (Principal::const_iterator i = begin(), iEnd = end(); i != iEnd; ++i) {
00313       if (i->second->provenanceAvailable()) {
00314         resolveProvenance(*i->second);
00315       }
00316       if (!i->second->productUnavailable()) {
00317         resolveProduct(*i->second, false);
00318       }
00319     }
00320     branchMapperPtr_->setDelayedRead(false);
00321   }
00322 
00323   size_t
00324   Principal::findGroups(TypeID const& typeID,
00325                         TypeLookup const& typeLookup,
00326                         SelectorBase const& selector,
00327                         BasicHandleVec& results,
00328                         bool stopIfProcessHasMatch) const {
00329     assert(results.empty());
00330 
00331     // A class without a dictionary cannot be in an Event/Lumi/Run.
00332     // First, we check if the class has a dictionary.  If it does not,
00333     // we return immediately.  This is necessary to avoid an exception
00334     // being thrown inside TypeID::friendlyClassName().
00335     if (!typeID.hasDictionary()) {
00336       return 0;
00337     }
00338 
00339     TypeLookup::const_iterator i = typeLookup.find(typeID.friendlyClassName());
00340 
00341     if (i == typeLookup.end()) {
00342       return 0;
00343     }
00344 
00345     const ProcessLookup& processLookup = i->second;
00346 
00347     // Handle groups for current process, note that we need to
00348     // look at the current process even if it is not in the processHistory
00349     // because of potential unscheduled (onDemand) production
00350     findGroupsForProcess(processConfiguration_.processName(),
00351                          processLookup,
00352                          selector,
00353                          results);
00354 
00355     // Loop over processes in reverse time order.  Sometimes we want to stop
00356     // after we find a process with matches so check for that at each step.
00357     for (ProcessHistory::const_reverse_iterator iproc = processHistory().rbegin(),
00358            eproc = processHistory().rend();
00359          iproc != eproc && (results.empty() || !stopIfProcessHasMatch);
00360          ++iproc) {
00361 
00362       // We just dealt with the current process before the loop so skip it
00363       if (iproc->processName() == processConfiguration_.processName()) continue;
00364 
00365       findGroupsForProcess(iproc->processName(),
00366                            processLookup,
00367                            selector,
00368                            results);
00369     }
00370     return results.size();
00371   }
00372 
00373   void 
00374   Principal::findGroupsForProcess(std::string const& processName,
00375                                   ProcessLookup const& processLookup,
00376                                   SelectorBase const& selector,
00377                                   BasicHandleVec& results) const {
00378 
00379     ProcessLookup::const_iterator j = processLookup.find(processName);
00380 
00381     if (j == processLookup.end()) return;
00382 
00383     // This is a vector of indexes into the productID vector
00384     // These indexes point to groups with desired process name (and
00385     // also type when this function is called from findGroups)
00386     std::vector<BranchID> const& vindex = j->second;
00387 
00388     for (std::vector<BranchID>::const_iterator ib(vindex.begin()), ie(vindex.end());
00389          ib != ie;
00390          ++ib) {
00391       SharedConstGroupPtr const& group = getGroup(*ib, false, false, false);
00392       if(group.get() == 0) {
00393         continue;
00394       }
00395 
00396       if (selector.match(group->productDescription())) {
00397 
00398         // Skip product if not available.
00399         if (!group->productUnavailable()) {
00400           this->resolveProduct(*group, true);
00401           // If the product is a dummy filler, group will now be marked unavailable.
00402           // Unscheduled execution can fail to produce the EDProduct so check
00403           if (!group->productUnavailable() && !group->onDemand()) {
00404             // Found a good match, save it
00405             BasicHandle bh(group->product(), group->provenance());
00406             bh.provenance()->setStore(branchMapperPtr_);
00407             results.push_back(bh);
00408           }
00409         }
00410       }
00411     }
00412     return;
00413   }
00414 
00415   void
00416   Principal::resolveProduct(Group const& g, bool fillOnDemand) const {
00417     if (g.productUnavailable()) {
00418       throw edm::Exception(errors::ProductNotFound,"InaccessibleProduct")
00419         << "resolve_: product is not accessible\n"
00420         << g.provenance() << '\n';
00421     }
00422 
00423     if (g.product()) return; // nothing to do.
00424 
00425     // Try unscheduled production.
00426     if (g.onDemand()) {
00427       if (fillOnDemand) unscheduledFill(g.productDescription().moduleLabel());
00428       return;
00429     }
00430 
00431     // must attempt to load from persistent store
00432     BranchKey const bk = BranchKey(g.productDescription());
00433     std::auto_ptr<EDProduct> edp(store_->getProduct(bk, this));
00434 
00435     // Now fix up the Group
00436     g.setProduct(edp);
00437   }
00438 
00439   void
00440   Principal::recombine(Principal & other, std::vector<BranchID> const& bids) {
00441     for (std::vector<BranchID>::const_iterator it = bids.begin(), itEnd = bids.end(); it != itEnd; ++it) {
00442       groups_[*it].swap(other.groups_[*it]);
00443     }
00444     store_->mergeReaders(other.store());
00445     branchMapperPtr_->mergeMappers(other.branchMapperPtr());
00446   }
00447 
00448   EDProduct const*
00449   Principal::getIt(ProductID const& pid) const {
00450     assert(0);
00451     return 0;
00452   }
00453 }

Generated on Tue Jun 9 17:36:11 2009 for CMSSW by  doxygen 1.5.4