CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/FWCore/Framework/src/Principal.cc

Go to the documentation of this file.
00001 
00004 #include "FWCore/Framework/interface/Principal.h"
00005 
00006 #include "DataFormats/Provenance/interface/BranchMapper.h"
00007 #include "DataFormats/Provenance/interface/ProcessHistoryRegistry.h"
00008 #include "DataFormats/Provenance/interface/ProductRegistry.h"
00009 #include "FWCore/Framework/interface/DelayedReader.h"
00010 #include "FWCore/Framework/interface/Selector.h"
00011 #include "FWCore/Utilities/interface/Algorithms.h"
00012 #include "FWCore/Utilities/interface/EDMException.h"
00013 #include "FWCore/Utilities/interface/ReflexTools.h"
00014 #include "FWCore/Utilities/interface/WrappedClassName.h"
00015 
00016 #include <algorithm>
00017 #include <cstring>
00018 #include <limits>
00019 #include <sstream>
00020 #include <stdexcept>
00021 
00022 //using boost::lambda::_1;
00023 
00024 namespace edm {
00025   static
00026   void
00027   maybeThrowMissingDictionaryException(TypeID const& productType, bool isElement, std::vector<std::string> const& missingDictionaries) {
00028     if(binary_search_all(missingDictionaries, productType.className())) {
00029       checkDictionaries(isElement ? productType.className() : wrappedClassName(productType.className()), false);
00030       throwMissingDictionariesException();
00031     }
00032   }
00033 
00034   static
00035   void
00036   throwMultiFoundException(char const* where, int nFound, TypeID const& productType) {
00037     throw Exception(errors::ProductNotFound)
00038       << "Principal::" << where << ": Found " << nFound << " products rather than one which match all criteria\n"
00039       << "Looking for type: " << productType << "\n";
00040   }
00041 
00042   static
00043   void
00044   throwGroupNotFoundException(char const* where, errors::ErrorCodes error, BranchID const& bid) {
00045     throw Exception(error, "InvalidID")
00046       << "Principal::" << where << ": no product with given branch id: "<< bid << "\n";
00047   }
00048 
00049   static
00050   void
00051   throwCorruptionException(char const* where, std::string const& branchName) {
00052     throw Exception(errors::EventCorruption)
00053        << "Principal::" << where <<": Product on branch " << branchName << " occurs twice in the same event.\n";
00054   }
00055 
00056   static
00057   boost::shared_ptr<cms::Exception>
00058   makeNotFoundException(char const* where, TypeID const& productType) {
00059     boost::shared_ptr<cms::Exception> exception(new Exception(errors::ProductNotFound));
00060     *exception << "Principal::" << where << ": Found zero products matching all criteria\nLooking for type: " << productType << "\n";
00061     return exception;
00062   }
00063 
00064   static
00065   boost::shared_ptr<cms::Exception>
00066   makeNotFoundException(char const* where, TypeID const& productType, std::string const& label, std::string const& instance, std::string const& process) {
00067     boost::shared_ptr<cms::Exception> exception(new Exception(errors::ProductNotFound));
00068     *exception << "Principal::" << where << ": Found zero products matching all criteria\nLooking for type: " << productType << "\n"
00069                << "Looking for module label: " << label << "\n" << "Looking for productInstanceName: " << instance << "\n"
00070                << (process.empty() ? "" : "Looking for process: ") << process << "\n";
00071     return exception;
00072   }
00073 
00074   static
00075   void
00076   throwNotFoundException(char const* where, TypeID const& productType, InputTag const& tag) {
00077     boost::shared_ptr<cms::Exception> exception = makeNotFoundException(where, productType, tag.label(), tag.instance(), tag.process());
00078     throw *exception;
00079   }
00080 
00081   Principal::Principal(boost::shared_ptr<ProductRegistry const> reg,
00082                        ProcessConfiguration const& pc,
00083                        BranchType bt) :
00084     EDProductGetter(),
00085     processHistoryPtr_(new ProcessHistory),
00086     processHistoryID_(processHistoryPtr_->id()),
00087     processConfiguration_(&pc),
00088     groups_(reg->constProductList().size(), SharedGroupPtr()),
00089     preg_(reg),
00090     branchMapperPtr_(new BranchMapper),
00091     reader_(),
00092     productPtrs_(),
00093     branchType_(bt) {
00094     //Now that these have been set, we can create the list of Branches we need.
00095     std::string const source("source");
00096     ProductRegistry::ProductList const& prodsList = reg->productList();
00097     for(ProductRegistry::ProductList::const_iterator itProdInfo = prodsList.begin(),
00098           itProdInfoEnd = prodsList.end();
00099         itProdInfo != itProdInfoEnd;
00100         ++itProdInfo) {
00101       if(itProdInfo->second.branchType() == branchType_) {
00102         boost::shared_ptr<ConstBranchDescription> bd(new ConstBranchDescription(itProdInfo->second));
00103         if(bd->produced()) {
00104           if(bd->moduleLabel() == source) {
00105             addGroupSource(bd);
00106           } else if(bd->onDemand()) {
00107             assert(bt == InEvent);
00108             addOnDemandGroup(bd);
00109           } else {
00110             addGroupScheduled(bd);
00111           }
00112         } else {
00113           addGroupInput(bd);
00114         }
00115       }
00116     }
00117   }
00118 
00119   Principal::~Principal() {
00120   }
00121 
00122   // Number of products in the Principal.
00123   // For products in an input file and not yet read in due to delayed read,
00124   // this routine assumes a real product is there.
00125   size_t
00126   Principal::size() const {
00127     size_t size = 0U;
00128     for(const_iterator it = this->begin(), itEnd = this->end(); it != itEnd; ++it) {
00129       Group const& g = **it;
00130       if(!g.productUnavailable() && !g.onDemand() && !g.branchDescription().dropped()) {
00131         ++size;
00132       }
00133     }
00134     return size;
00135   }
00136 
00137   //adjust provenance for input groups after new input file has been merged
00138   bool
00139   Principal::adjustToNewProductRegistry(ProductRegistry const& reg) {
00140     if(reg.constProductList().size() > groups_.size()) {
00141       return false;
00142     }
00143     ProductRegistry::ProductList const& prodsList = reg.productList();
00144     for(ProductRegistry::ProductList::const_iterator itProdInfo = prodsList.begin(),
00145           itProdInfoEnd = prodsList.end();
00146         itProdInfo != itProdInfoEnd;
00147         ++itProdInfo) {
00148     if(!itProdInfo->second.produced() && (itProdInfo->second.branchType() == branchType_)) {
00149         boost::shared_ptr<ConstBranchDescription> bd(new ConstBranchDescription(itProdInfo->second));
00150         Group *g = getExistingGroup(itProdInfo->second.branchID());
00151         if(g == 0 || g->branchDescription().branchName() != bd->branchName()) {
00152             return false;
00153         }
00154         g->resetBranchDescription(bd);
00155       }
00156     }
00157     return true;
00158   }
00159 
00160   void
00161   Principal::addGroupScheduled(boost::shared_ptr<ConstBranchDescription> bd) {
00162     std::auto_ptr<Group> g(new ScheduledGroup(bd));
00163     addGroupOrThrow(g);
00164   }
00165 
00166   void
00167   Principal::addGroupSource(boost::shared_ptr<ConstBranchDescription> bd) {
00168     std::auto_ptr<Group> g(new SourceGroup(bd));
00169     addGroupOrThrow(g);
00170   }
00171 
00172   void
00173   Principal::addGroupInput(boost::shared_ptr<ConstBranchDescription> bd) {
00174     std::auto_ptr<Group> g(new InputGroup(bd));
00175     addGroupOrThrow(g);
00176   }
00177 
00178   void
00179   Principal::addOnDemandGroup(boost::shared_ptr<ConstBranchDescription> bd) {
00180     std::auto_ptr<Group> g(new UnscheduledGroup(bd));
00181     addGroupOrThrow(g);
00182   }
00183 
00184   // "Zero" the principal so it can be reused for another Event.
00185   void
00186   Principal::clearPrincipal() {
00187     processHistoryPtr_->clear();
00188     processHistoryID_ = processHistoryPtr_->id();
00189     branchMapperPtr_->reset();
00190     reader_ = 0;
00191     for (Principal::const_iterator i = begin(), iEnd = end(); i != iEnd; ++i) {
00192       (*i)->resetProductData();
00193     }
00194     productPtrs_.clear();
00195   }
00196 
00197   // Set the principal for the Event, Lumi, or Run.
00198   void
00199   Principal::fillPrincipal(ProcessHistoryID const& hist, boost::shared_ptr<BranchMapper> mapper, DelayedReader* reader) {
00200     if(mapper) {
00201       branchMapperPtr_ = mapper;
00202     }
00203     if(reader) {
00204       reader_ = reader;
00205     }
00206     if(hist.isValid()) {
00207       ProcessHistoryRegistry& history(*ProcessHistoryRegistry::instance());
00208       assert(history.notEmpty());
00209       bool found = history.getMapped(hist, *processHistoryPtr_);
00210       assert(found);
00211       processHistoryID_ = processHistoryPtr_->id();
00212     }
00213     preg_->productLookup().reorderIfNecessary(branchType_, *processHistoryPtr_,
00214                                          processConfiguration_->processName());
00215     preg_->elementLookup().reorderIfNecessary(branchType_, *processHistoryPtr_,
00216                                          processConfiguration_->processName());
00217   }
00218 
00219   Group*
00220   Principal::getExistingGroup(BranchID const& branchID) {
00221     ProductTransientIndex index = preg_->indexFrom(branchID);
00222     assert(index != ProductRegistry::kInvalidIndex);
00223     SharedGroupPtr ptr = groups_.at(index);
00224     return ptr.get();
00225   }
00226 
00227   Group*
00228   Principal::getExistingGroup(Group const& group) {
00229     Group* g = getExistingGroup(group.branchDescription().branchID());
00230     assert(0 == g || BranchKey(group.branchDescription()) == BranchKey(g->branchDescription()));
00231     return g;
00232   }
00233 
00234   void
00235   Principal::addGroup_(std::auto_ptr<Group> group) {
00236     ConstBranchDescription const& bd = group->branchDescription();
00237     assert (!bd.className().empty());
00238     assert (!bd.friendlyClassName().empty());
00239     assert (!bd.moduleLabel().empty());
00240     assert (!bd.processName().empty());
00241     SharedGroupPtr g(group);
00242 
00243     ProductTransientIndex index = preg_->indexFrom(bd.branchID());
00244     assert(index != ProductRegistry::kInvalidIndex);
00245     groups_[index] = g;
00246   }
00247 
00248   void
00249   Principal::addGroupOrThrow(std::auto_ptr<Group> group) {
00250     Group const* g = getExistingGroup(*group);
00251     if(g != 0) {
00252       ConstBranchDescription const& bd = group->branchDescription();
00253       throw Exception(errors::InsertFailure, "AlreadyPresent")
00254           << "addGroupOrThrow: Problem found while adding product, "
00255           << "product already exists for ("
00256           << bd.friendlyClassName() << ","
00257           << bd.moduleLabel() << ","
00258           << bd.productInstanceName() << ","
00259           << bd.processName()
00260           << ")\n";
00261     }
00262     addGroup_(group);
00263   }
00264 
00265   void
00266   Principal::setProcessHistory(Principal const& principal) {
00267     *processHistoryPtr_ = *principal.processHistoryPtr_;
00268     processHistoryID_ = processHistoryPtr_->id();
00269   }
00270 
00271   Principal::ConstGroupPtr const
00272   Principal::getGroup(BranchID const& bid, bool resolveProd, bool fillOnDemand) const {
00273     ProductTransientIndex index = preg_->indexFrom(bid);
00274     if(index == ProductRegistry::kInvalidIndex){
00275        return ConstGroupPtr();
00276     }
00277     return getGroupByIndex(index, resolveProd, fillOnDemand);
00278   }
00279 
00280   Principal::ConstGroupPtr const
00281   Principal::getGroupByIndex(ProductTransientIndex const& index, bool resolveProd, bool fillOnDemand) const {
00282 
00283     ConstGroupPtr const g = groups_[index].get();
00284     if(0 == g) {
00285       return g;
00286     }
00287     if(resolveProd && !g->productUnavailable()) {
00288       this->resolveProduct(*g, fillOnDemand);
00289     }
00290     return g;
00291   }
00292 
00293   BasicHandle
00294   Principal::getBySelector(TypeID const& productType,
00295                            SelectorBase const& sel) const {
00296     BasicHandle result;
00297 
00298     int nFound = findGroup(productType,
00299                            preg_->productLookup(),
00300                            sel,
00301                            result);
00302 
00303     if(nFound == 0) {
00304       boost::shared_ptr<cms::Exception> whyFailed = makeNotFoundException("getBySelector", productType);
00305       return BasicHandle(whyFailed);
00306     }
00307     if(nFound > 1) {
00308       throwMultiFoundException("getBySelector", nFound, productType);
00309     }
00310     return result;
00311   }
00312 
00313   BasicHandle
00314   Principal::getByLabel(TypeID const& productType,
00315                         std::string const& label,
00316                         std::string const& productInstanceName,
00317                         std::string const& processName,
00318                         size_t& cachedOffset,
00319                         int& fillCount) const {
00320 
00321     ProductData const* result = findGroupByLabel(productType,
00322                                                  preg_->productLookup(),
00323                                                  label,
00324                                                  productInstanceName,
00325                                                  processName,
00326                                                  cachedOffset,
00327                                                  fillCount);
00328 
00329     if(result == 0) {
00330       boost::shared_ptr<cms::Exception> whyFailed = makeNotFoundException("getByLabel", productType, label, productInstanceName, processName);
00331       return BasicHandle(whyFailed);
00332     }
00333     return BasicHandle(*result);
00334   }
00335 
00336 
00337   void
00338   Principal::getMany(TypeID const& productType,
00339                      SelectorBase const& sel,
00340                      BasicHandleVec& results) const {
00341 
00342     findGroups(productType,
00343                preg_->productLookup(),
00344                sel,
00345                results);
00346 
00347     return;
00348   }
00349 
00350   BasicHandle
00351   Principal::getByType(TypeID const& productType) const {
00352 
00353     BasicHandle result;
00354     MatchAllSelector sel;
00355 
00356     int nFound = findGroup(productType,
00357                            preg_->productLookup(),
00358                            sel,
00359                            result);
00360 
00361     if(nFound == 0) {
00362       boost::shared_ptr<cms::Exception> whyFailed = makeNotFoundException("getByType", productType);
00363       return BasicHandle(whyFailed);
00364     }
00365 
00366     if(nFound > 1) {
00367       throwMultiFoundException("getByType", nFound, productType);
00368     }
00369     return result;
00370   }
00371 
00372   void
00373   Principal::getManyByType(TypeID const& productType,
00374                            BasicHandleVec& results) const {
00375 
00376     MatchAllSelector sel;
00377 
00378     findGroups(productType,
00379                preg_->productLookup(),
00380                sel,
00381                results);
00382     return;
00383   }
00384 
00385   size_t
00386   Principal::getMatchingSequence(TypeID const& typeID,
00387                                  SelectorBase const& selector,
00388                                  BasicHandle& result) const {
00389 
00390     // One new argument is the element lookup container
00391     // Otherwise this just passes through the arguments to findGroup
00392     return findGroup(typeID,
00393                      preg_->elementLookup(),
00394                      selector,
00395                      result);
00396   }
00397 
00398   size_t
00399   Principal::findGroups(TypeID const& typeID,
00400                         TransientProductLookupMap const& typeLookup,
00401                         SelectorBase const& selector,
00402                         BasicHandleVec& results) const {
00403     assert(results.empty());
00404 
00405     typedef TransientProductLookupMap TypeLookup;
00406     // A class without a dictionary cannot be in an Event/Lumi/Run.
00407     // First, we check if the class has a dictionary.  If it does not, we throw an exception.
00408     // The missing dictionary might be for the class itself, the wrapped class, or a component of the class.
00409     std::pair<TypeLookup::const_iterator, TypeLookup::const_iterator> const range = typeLookup.equal_range(TypeInBranchType(typeID, branchType_));
00410     if(range.first == range.second) {
00411       maybeThrowMissingDictionaryException(typeID, &typeLookup == &preg_->elementLookup(), preg_->missingDictionaries());
00412     }
00413 
00414     results.reserve(range.second - range.first);
00415 
00416     for(TypeLookup::const_iterator it = range.first; it != range.second; ++it) {
00417 
00418       if(selector.match(*(it->branchDescription()))) {
00419 
00420         //now see if the data is actually available
00421         ConstGroupPtr const& group = getGroupByIndex(it->index(), false, false);
00422         // Skip product if not available.
00423         if(group && !group->productUnavailable()) {
00424           this->resolveProduct(*group, true);
00425           // If the product is a dummy filler, group will now be marked unavailable.
00426           // Unscheduled execution can fail to produce the EDProduct so check
00427           if(!group->productUnavailable() && !group->onDemand()) {
00428             // Found a good match, save it
00429             BasicHandle bh(group->productData());
00430             results.push_back(bh);
00431           }
00432         }
00433       }
00434     }
00435     return results.size();
00436   }
00437 
00438   size_t
00439   Principal::findGroup(TypeID const& typeID,
00440                        TransientProductLookupMap const& typeLookup,
00441                        SelectorBase const& selector,
00442                        BasicHandle& result) const {
00443     assert(!result.isValid());
00444 
00445     size_t count = 0U;
00446 
00447     typedef TransientProductLookupMap TypeLookup;
00448     // A class without a dictionary cannot be in an Event/Lumi/Run.
00449     // First, we check if the class has a dictionary.  If it does not, we throw an exception.
00450     // The missing dictionary might be for the class itself, the wrapped class, or a component of the class.
00451     std::pair<TypeLookup::const_iterator, TypeLookup::const_iterator> const range = typeLookup.equal_range(TypeInBranchType(typeID, branchType_));
00452     if(range.first == range.second) {
00453       maybeThrowMissingDictionaryException(typeID, &typeLookup == &preg_->elementLookup(), preg_->missingDictionaries());
00454     }
00455 
00456     unsigned int processLevelFound = std::numeric_limits<unsigned int>::max();
00457     for(TypeLookup::const_iterator it = range.first; it != range.second; ++it) {
00458       if(it->processIndex() > processLevelFound) {
00459         //this is for a less recent process and we've already found a match for a more recent process
00460         continue;
00461       }
00462 
00463       if(selector.match(*(it->branchDescription()))) {
00464 
00465         //now see if the data is actually available
00466         ConstGroupPtr const& group = getGroupByIndex(it->index(), false, false);
00467         // Skip product if not available.
00468         if(group && !group->productUnavailable()) {
00469           this->resolveProduct(*group, true);
00470           // If the product is a dummy filler, group will now be marked unavailable.
00471           // Unscheduled execution can fail to produce the EDProduct so check
00472           if(!group->productUnavailable() && !group->onDemand()) {
00473             if(it->processIndex() < processLevelFound) {
00474               processLevelFound = it->processIndex();
00475               count = 0U;
00476             }
00477             if(count == 0U) {
00478               // Found a unique (so far) match, save it
00479               result = BasicHandle(group->productData());
00480             }
00481             ++count;
00482           }
00483         }
00484       }
00485     }
00486     if(count != 1) result = BasicHandle();
00487     return count;
00488   }
00489 
00490   ProductData const*
00491   Principal::findGroupByLabel(TypeID const& typeID,
00492                               TransientProductLookupMap const& typeLookup,
00493                               std::string const& moduleLabel,
00494                               std::string const& productInstanceName,
00495                               std::string const& processName,
00496                               size_t& cachedOffset,
00497                               int& fillCount) const {
00498 
00499     typedef TransientProductLookupMap TypeLookup;
00500     bool isCached = (fillCount > 0 && fillCount == typeLookup.fillCount());
00501     bool toBeCached = (fillCount >= 0 && !isCached);
00502 
00503     std::pair<TypeLookup::const_iterator, TypeLookup::const_iterator> range =
00504         (isCached ? std::make_pair(typeLookup.begin() + cachedOffset, typeLookup.end()) : typeLookup.equal_range(TypeInBranchType(typeID, branchType_), moduleLabel, productInstanceName));
00505 
00506     if(toBeCached) {
00507       cachedOffset = range.first - typeLookup.begin();
00508       fillCount = typeLookup.fillCount();
00509     }
00510 
00511     if(range.first == range.second) {
00512       if(toBeCached) {
00513         cachedOffset = typeLookup.end() - typeLookup.begin();
00514       }
00515       // We check for a missing dictionary.  We do this only in this error leg.
00516       // A class without a dictionary cannot be in an Event/Lumi/Run.
00517       // We check if the class has a dictionary.  If it does not, we throw an exception.
00518       // The missing dictionary might be for the class itself, the wrapped class, or a component of the class.
00519       std::pair<TypeLookup::const_iterator, TypeLookup::const_iterator> const typeRange = typeLookup.equal_range(TypeInBranchType(typeID, branchType_));
00520       if(typeRange.first == typeRange.second) {
00521         maybeThrowMissingDictionaryException(typeID, &typeLookup == &preg_->elementLookup(), preg_->missingDictionaries());
00522       }
00523       return 0;
00524     }
00525 
00526     if(!processName.empty()) {
00527       if(isCached) {
00528         assert(processName == range.first->branchDescription()->processName());
00529         range.second = range.first + 1;
00530       } else if(toBeCached) {
00531         bool processFound = false;
00532         for(TypeLookup::const_iterator it = range.first; it != range.second; ++it) {
00533           if(it->isFirst() && it != range.first) {
00534             break;
00535           }
00536           if(processName == it->branchDescription()->processName()) {
00537             processFound = true;
00538             range.first = it;
00539             cachedOffset = range.first - typeLookup.begin();
00540             range.second = range.first + 1;
00541             break;
00542           }
00543         }
00544         if(!processFound) {
00545           cachedOffset = typeLookup.end() - typeLookup.begin();
00546           return 0;
00547         }
00548       } // end if(toBeCached)
00549     }
00550 
00551     for(TypeLookup::const_iterator it = range.first; it != range.second; ++it) {
00552       if(it->isFirst() && it != range.first) {
00553         return 0;
00554       }
00555       if(!processName.empty() && processName != it->branchDescription()->processName()) {
00556         continue;
00557       }
00558       //now see if the data is actually available
00559       ConstGroupPtr const& group = getGroupByIndex(it->index(), false, false);
00560       // Skip product if not available.
00561       if(group && !group->productUnavailable()) {
00562         this->resolveProduct(*group, true);
00563         // If the product is a dummy filler, group will now be marked unavailable.
00564         // Unscheduled execution can fail to produce the EDProduct so check
00565         if(!group->productUnavailable() && !group->onDemand()) {
00566           // Found the match
00567           return &group->productData();
00568         }
00569       }
00570     }
00571     return 0;
00572   }
00573 
00574   ProductData const*
00575   Principal::findGroupByTag(TypeID const& typeID, InputTag const& tag) const {
00576     ProductData const* productData =
00577         findGroupByLabel(typeID,
00578                          preg_->productLookup(),
00579                          tag.label(),
00580                          tag.instance(),
00581                          tag.process(),
00582                          tag.cachedOffset(),
00583                          tag.fillCount());
00584     if(productData == 0) {
00585       throwNotFoundException("findProductByTag", typeID, tag);
00586     }
00587     return productData;
00588   }
00589 
00590   OutputHandle
00591   Principal::getForOutput(BranchID const& bid, bool getProd) const {
00592     ConstGroupPtr const g = getGroup(bid, getProd, false);
00593     if(g == 0) {
00594       throwGroupNotFoundException("getForOutput", errors::LogicError, bid);
00595     }
00596     if(!g->provenance() || (!g->product() && !g->productProvenancePtr())) {
00597       return OutputHandle();
00598     }
00599     return OutputHandle(WrapperHolder(g->product().get(), g->productData().getInterface()), &g->branchDescription(), g->productProvenancePtr());
00600   }
00601 
00602   Provenance
00603   Principal::getProvenance(BranchID const& bid) const {
00604     ConstGroupPtr const g = getGroup(bid, false, true);
00605     if(g == 0) {
00606       throwGroupNotFoundException("getProvenance", errors::ProductNotFound, bid);
00607     }
00608 
00609     if(g->onDemand()) {
00610       unscheduledFill(g->branchDescription().moduleLabel());
00611     }
00612     // We already tried to produce the unscheduled products above
00613     // If they still are not there, then throw
00614     if(g->onDemand()) {
00615       throwGroupNotFoundException("getProvenance(onDemand)", errors::ProductNotFound, bid);
00616     }
00617 
00618     return *g->provenance();
00619   }
00620 
00621   // This one is mostly for test printout purposes
00622   // No attempt to trigger on demand execution
00623   // Skips provenance when the EDProduct is not there
00624   void
00625   Principal::getAllProvenance(std::vector<Provenance const*>& provenances) const {
00626     provenances.clear();
00627     for (const_iterator i = begin(), iEnd = end(); i != iEnd; ++i) {
00628       if((*i)->provenanceAvailable()) {
00629         // We do not attempt to get the event/lumi/run status from the provenance,
00630         // because the per event provenance may have been dropped.
00631         if((*i)->provenance()->product().present()) {
00632            provenances.push_back((*i)->provenance());
00633         }
00634       }
00635     }
00636   }
00637 
00638   void
00639   Principal::recombine(Principal& other, std::vector<BranchID> const& bids) {
00640     for (std::vector<BranchID>::const_iterator it = bids.begin(), itEnd = bids.end(); it != itEnd; ++it) {
00641       ProductTransientIndex index= preg_->indexFrom(*it);
00642       assert(index!=ProductRegistry::kInvalidIndex);
00643       ProductTransientIndex indexO = other.preg_->indexFrom(*it);
00644       assert(indexO!=ProductRegistry::kInvalidIndex);
00645       groups_[index].swap(other.groups_[indexO]);
00646     }
00647     reader_->mergeReaders(other.reader());
00648     branchMapperPtr_->mergeMappers(other.branchMapperPtr());
00649   }
00650 
00651   WrapperHolder
00652   Principal::getIt(ProductID const&) const {
00653     assert(0);
00654     return WrapperHolder();
00655   }
00656 
00657   void
00658   Principal::maybeFlushCache(TypeID const& tid, InputTag const& tag) const {
00659     if(tag.typeID() != tid ||
00660         tag.branchType() != branchType() ||
00661         tag.productRegistry() != &productRegistry()) {
00662       tag.fillCount() = 0;
00663       tag.cachedOffset() = 0U;
00664       tag.typeID() = tid;
00665       tag.branchType() = branchType();
00666       tag.productRegistry() = &productRegistry();
00667     }
00668   }
00669 
00670   void
00671   Principal::checkUniquenessAndType(WrapperOwningHolder const& prod, Group const* g) const {
00672     if(!prod.isValid()) return;
00673     // These are defensive checks against things that should never happen, but have.
00674     // Checks that the same physical product has not already been put into the event.
00675     bool alreadyPresent = !productPtrs_.insert(prod.wrapper()).second;
00676     if(alreadyPresent) {
00677       g->checkType(prod);
00678       const_cast<WrapperOwningHolder&>(prod).reset();
00679       throwCorruptionException("checkUniquenessAndType", g->branchDescription().branchName());
00680     }
00681     // Checks that the real type of the product matches the branch.
00682     g->checkType(prod);
00683   }
00684 
00685   void
00686   Principal::putOrMerge(WrapperOwningHolder const& prod, Group const* g) const {
00687     bool willBePut = g->putOrMergeProduct();
00688     if(willBePut) {
00689       checkUniquenessAndType(prod, g);
00690       g->putProduct(prod);
00691     } else {
00692       g->checkType(prod);
00693       g->mergeProduct(prod);
00694     }
00695   }
00696 
00697   void
00698   Principal::putOrMerge(WrapperOwningHolder const& prod, ProductProvenance& prov, Group* g) {
00699     bool willBePut = g->putOrMergeProduct();
00700     if(willBePut) {
00701       checkUniquenessAndType(prod, g);
00702       g->putProduct(prod, prov);
00703     } else {
00704       g->checkType(prod);
00705       g->mergeProduct(prod, prov);
00706     }
00707   }
00708 
00709   void
00710   Principal::adjustIndexesAfterProductRegistryAddition() {
00711     if(preg_->constProductList().size() > groups_.size()) {
00712       GroupCollection newGroups(preg_->constProductList().size(), SharedGroupPtr());
00713       for (Principal::const_iterator i = begin(), iEnd = end(); i != iEnd; ++i) {
00714         ProductTransientIndex index = preg_->indexFrom((*i)->branchDescription().branchID());
00715         assert(index != ProductRegistry::kInvalidIndex);
00716         newGroups[index] = *i;
00717       }
00718       groups_.swap(newGroups);
00719       // Now we must add new groups for any new product registry entries.
00720       ProductRegistry::ProductList const& prodsList = preg_->productList();
00721       for(ProductRegistry::ProductList::const_iterator itProdInfo = prodsList.begin(),
00722           itProdInfoEnd = prodsList.end();
00723           itProdInfo != itProdInfoEnd;
00724           ++itProdInfo) {
00725         if(itProdInfo->second.branchType() == branchType_) {
00726           ProductTransientIndex index = preg_->indexFrom(itProdInfo->second.branchID());
00727           assert(index != ProductRegistry::kInvalidIndex);
00728           if(!groups_[index]) {
00729             // no group.  Must add one. The new entry must be an input group.
00730             assert(!itProdInfo->second.produced());
00731             boost::shared_ptr<ConstBranchDescription> bd(new ConstBranchDescription(itProdInfo->second));
00732             addGroupInput(bd);
00733           }
00734         }
00735       }
00736     }
00737   }
00738 }