CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/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/ProcessHistoryRegistry.h"
00007 #include "DataFormats/Provenance/interface/ProductHolderIndexHelper.h"
00008 #include "DataFormats/Provenance/interface/ProductRegistry.h"
00009 #include "FWCore/Framework/interface/DelayedReader.h"
00010 #include "FWCore/Framework/interface/HistoryAppender.h"
00011 #include "FWCore/Framework/interface/ProductDeletedException.h"
00012 #include "FWCore/Utilities/interface/Algorithms.h"
00013 #include "FWCore/Utilities/interface/EDMException.h"
00014 #include "FWCore/Utilities/interface/DictionaryTools.h"
00015 #include "FWCore/Utilities/interface/ProductHolderIndex.h"
00016 #include "FWCore/Utilities/interface/TypeID.h"
00017 #include "FWCore/Utilities/interface/WrappedClassName.h"
00018 
00019 #include <algorithm>
00020 #include <cstring>
00021 #include <limits>
00022 #include <sstream>
00023 #include <stdexcept>
00024 #include <typeinfo>
00025 
00026 namespace edm {
00027 
00028   ProcessHistory const Principal::emptyProcessHistory_;
00029 
00030   static
00031   void
00032   maybeThrowMissingDictionaryException(TypeID const& productType, bool isElement, std::vector<std::string> const& missingDictionaries) {
00033     if(binary_search_all(missingDictionaries, productType.className())) {
00034       checkDictionaries(isElement ? productType.className() : wrappedClassName(productType.className()), false);
00035       throwMissingDictionariesException();
00036     }
00037   }
00038 
00039   static
00040   void
00041   throwProductNotFoundException(char const* where, errors::ErrorCodes error, BranchID const& bid) {
00042     throw Exception(error, "InvalidID")
00043       << "Principal::" << where << ": no product with given branch id: "<< bid << "\n";
00044   }
00045 
00046   static
00047   void
00048   throwCorruptionException(char const* where, std::string const& branchName) {
00049     throw Exception(errors::EventCorruption)
00050        << "Principal::" << where <<": Product on branch " << branchName << " occurs twice in the same event.\n";
00051   }
00052 
00053   static
00054   boost::shared_ptr<cms::Exception>
00055   makeNotFoundException(char const* where, KindOfType kindOfType,
00056                         TypeID const& productType, std::string const& label, std::string const& instance, std::string const& process) {
00057     boost::shared_ptr<cms::Exception> exception(new Exception(errors::ProductNotFound));
00058     if (kindOfType == PRODUCT_TYPE) {
00059       *exception << "Principal::" << where << ": Found zero products matching all criteria\nLooking for type: " << productType << "\n"
00060                  << "Looking for module label: " << label << "\n" << "Looking for productInstanceName: " << instance << "\n"
00061                  << (process.empty() ? "" : "Looking for process: ") << process << "\n";
00062     } else {
00063       *exception << "Principal::" << where << ": Found zero products matching all criteria\nLooking for a container with elements of type: " << productType << "\n"
00064                  << "Looking for module label: " << label << "\n" << "Looking for productInstanceName: " << instance << "\n"
00065                  << (process.empty() ? "" : "Looking for process: ") << process << "\n";
00066     }
00067     return exception;
00068   }
00069 
00070   static
00071   void
00072   throwProductDeletedException(const char* where, TypeID const& productType,std::string const& label, std::string const& instance, std::string const& process) {
00073     ProductDeletedException exception;
00074     exception << "Principal::" << where << ": The product matching all criteria\nLooking for type: " << productType << "\n"
00075       << "Looking for module label: " << label << "\n" << "Looking for productInstanceName: " << instance << "\n"
00076       << (process.empty() ? "" : "Looking for process: ") << process << "\n"
00077       << "Was already deleted. This means there is a configuration error.\n"
00078       << "The module which is asking for this data must be configured to state that it will read this data.";
00079     throw exception;
00080   }
00081 
00082   static
00083   void
00084   throwAmbiguousException(const char* where, TypeID const& productType,std::string const& label, std::string const& instance, std::string const& process) {
00085     cms::Exception exception("AmbiguousProduct");
00086     exception << "Principal::" << where << ": More than 1 product matches all criteria\nLooking for type: " << productType << "\n"
00087     << "Looking for module label: " << label << "\n" << "Looking for productInstanceName: " << instance << "\n"
00088     << (process.empty() ? "" : "Looking for process: ") << process << "\n"
00089     << "This can only occur with get function calls using a Handle<View> argument.\n"
00090     << "Try a get not using a View or change the instance name of one of the products";
00091     throw exception;
00092     
00093   }
00094 
00095   static
00096   void
00097   throwNotFoundException(char const* where, TypeID const& productType, InputTag const& tag) {
00098     boost::shared_ptr<cms::Exception> exception = makeNotFoundException(where, PRODUCT_TYPE, productType, tag.label(), tag.instance(), tag.process());
00099     throw *exception;
00100   }
00101   
00102 
00103   Principal::Principal(boost::shared_ptr<ProductRegistry const> reg,
00104                        boost::shared_ptr<ProductHolderIndexHelper const> productLookup,
00105                        ProcessConfiguration const& pc,
00106                        BranchType bt,
00107                        HistoryAppender* historyAppender) :
00108     EDProductGetter(),
00109     processHistoryPtr_(nullptr),
00110     processHistoryID_(),
00111     processConfiguration_(&pc),
00112     productHolders_(reg->getNextIndexValue(bt), SharedProductPtr()),
00113     preg_(reg),
00114     productLookup_(productLookup),
00115     lookupProcessOrder_(productLookup->lookupProcessNames().size(), 0),
00116     reader_(),
00117     productPtrs_(),
00118     branchType_(bt),
00119     historyAppender_(historyAppender) {
00120 
00121     //Now that these have been set, we can create the list of Branches we need.
00122     std::string const source("source");
00123     ProductRegistry::ProductList const& prodsList = reg->productList();
00124     // The constructor of an alias product holder takes as an argument the product holder for which it is an alias.
00125     // So, the non-alias product holders must be created first.
00126     // Therefore, on this first pass, skip current EDAliases.
00127     bool hasAliases = false;
00128     for(auto const& prod : prodsList) {
00129       BranchDescription const& bd = prod.second;
00130       if(bd.branchType() == branchType_) {
00131         if(bd.isAlias()) {
00132           hasAliases = true;
00133         } else {
00134           boost::shared_ptr<ConstBranchDescription> cbd(new ConstBranchDescription(bd));
00135           if(bd.produced()) {
00136             if(bd.moduleLabel() == source) {
00137               addSourceProduct(cbd);
00138             } else if(bd.onDemand()) {
00139               assert(branchType_ == InEvent);
00140               addUnscheduledProduct(cbd);
00141             } else {
00142               addScheduledProduct(cbd);
00143             }
00144           } else {
00145             addInputProduct(cbd);
00146           }
00147         }
00148       }
00149     }
00150     // Now process any EDAliases
00151     if(hasAliases) {
00152       for(auto const& prod : prodsList) {
00153         BranchDescription const& bd = prod.second;
00154         if(bd.isAlias() && bd.branchType() == branchType_) {
00155           boost::shared_ptr<ConstBranchDescription> cbd(new ConstBranchDescription(bd));
00156           addAliasedProduct(cbd);
00157         }
00158       }
00159     }
00160 
00161     // Now create the ProductHolders that search in reverse process
00162     // order and are used for queries where the process name is the
00163     // empty string
00164     std::vector<std::string> const& lookupProcessNames = productLookup_->lookupProcessNames();
00165     std::vector<ProductHolderIndex> matchingHolders(lookupProcessNames.size(), ProductHolderIndexInvalid);
00166     std::vector<bool> ambiguous(lookupProcessNames.size(), false);
00167     unsigned int beginElements = productLookup_->beginElements();
00168     std::vector<TypeID> const& sortedTypeIDs = productLookup_->sortedTypeIDs();
00169     std::vector<ProductHolderIndexHelper::Range> const& ranges = productLookup_->ranges();
00170     std::vector<ProductHolderIndexHelper::IndexAndNames> const& indexAndNames = productLookup_->indexAndNames();
00171     std::vector<char> const& processNamesCharArray = productLookup_->processNames();
00172 
00173     if (!sortedTypeIDs.empty()) {
00174       ProductHolderIndex productHolderIndex = ProductHolderIndexInvalid;
00175       for(unsigned int k = 0, kEnd = sortedTypeIDs.size(); k < kEnd; ++k) {
00176         ProductHolderIndexHelper::Range const& range = ranges.at(k);
00177         for (unsigned int i = range.begin(); i < range.end(); ++i) {
00178           ProductHolderIndexHelper::IndexAndNames const& product = indexAndNames.at(i);
00179           if (product.startInProcessNames() == 0) {
00180             if (productHolderIndex != ProductHolderIndexInvalid) {
00181               boost::shared_ptr<ProductHolderBase> newHolder(new NoProcessProductHolder(matchingHolders, ambiguous, this));
00182               productHolders_.at(productHolderIndex) = newHolder;
00183               matchingHolders.assign(lookupProcessNames.size(), ProductHolderIndexInvalid);
00184               ambiguous.assign(lookupProcessNames.size(), false);
00185             }
00186             productHolderIndex = product.index();
00187           } else {
00188             std::string process(&processNamesCharArray.at(product.startInProcessNames()));
00189             auto iter = std::find(lookupProcessNames.begin(), lookupProcessNames.end(), process);
00190             assert(iter != lookupProcessNames.end());
00191             ProductHolderIndex iMatchingIndex = product.index();
00192             assert(iMatchingIndex != ProductHolderIndexInvalid);
00193             if (iMatchingIndex == ProductHolderIndexAmbiguous) {
00194               assert(k >= beginElements);
00195               ambiguous.at(iter - lookupProcessNames.begin()) = true;
00196             } else {
00197               matchingHolders.at(iter - lookupProcessNames.begin()) = iMatchingIndex;
00198             }
00199           }
00200         }
00201       }
00202       boost::shared_ptr<ProductHolderBase> newHolder(new NoProcessProductHolder(matchingHolders, ambiguous, this));
00203       productHolders_.at(productHolderIndex) = newHolder;
00204     }
00205   }
00206 
00207   Principal::~Principal() {
00208   }
00209 
00210   // Number of products in the Principal.
00211   // For products in an input file and not yet read in due to delayed read,
00212   // this routine assumes a real product is there.
00213   size_t
00214   Principal::size() const {
00215     size_t size = 0U;
00216     for(auto const& prod : *this) {
00217       if(prod->singleProduct() && // Not a NoProcessProductHolder
00218          !prod->productUnavailable() &&
00219          !prod->onDemand() &&
00220          !prod->branchDescription().dropped()) {
00221         ++size;
00222       }
00223     }
00224     return size;
00225   }
00226 
00227   // adjust provenance for input products after new input file has been merged
00228   bool
00229   Principal::adjustToNewProductRegistry(ProductRegistry const& reg) {
00230     ProductRegistry::ProductList const& prodsList = reg.productList();
00231     for(auto const& prod : prodsList) {
00232       BranchDescription const& bd = prod.second;
00233       if(!bd.produced() && (bd.branchType() == branchType_)) {
00234         boost::shared_ptr<ConstBranchDescription> cbd(new ConstBranchDescription(bd));
00235         ProductHolderBase* phb = getExistingProduct(cbd->branchID());
00236         if(phb == nullptr || phb->branchDescription().branchName() != cbd->branchName()) {
00237             return false;
00238         }
00239         phb->resetBranchDescription(cbd);
00240       }
00241     }
00242     return true;
00243   }
00244 
00245   void
00246   Principal::addScheduledProduct(boost::shared_ptr<ConstBranchDescription> bd) {
00247     std::auto_ptr<ProductHolderBase> phb(new ScheduledProductHolder(bd));
00248     addProductOrThrow(phb);
00249   }
00250 
00251   void
00252   Principal::addSourceProduct(boost::shared_ptr<ConstBranchDescription> bd) {
00253     std::auto_ptr<ProductHolderBase> phb(new SourceProductHolder(bd));
00254     addProductOrThrow(phb);
00255   }
00256 
00257   void
00258   Principal::addInputProduct(boost::shared_ptr<ConstBranchDescription> bd) {
00259     std::auto_ptr<ProductHolderBase> phb(new InputProductHolder(bd, this));
00260     addProductOrThrow(phb);
00261   }
00262 
00263   void
00264   Principal::addUnscheduledProduct(boost::shared_ptr<ConstBranchDescription> bd) {
00265     std::auto_ptr<ProductHolderBase> phb(new UnscheduledProductHolder(bd, this));
00266     addProductOrThrow(phb);
00267   }
00268 
00269   void
00270   Principal::addAliasedProduct(boost::shared_ptr<ConstBranchDescription> bd) {
00271     ProductHolderIndex index = preg_->indexFrom(bd->originalBranchID());
00272     assert(index != ProductHolderIndexInvalid);
00273 
00274     std::auto_ptr<ProductHolderBase> phb(new AliasProductHolder(bd, dynamic_cast<ProducedProductHolder&>(*productHolders_[index])));
00275     addProductOrThrow(phb);
00276   }
00277 
00278   // "Zero" the principal so it can be reused for another Event.
00279   void
00280   Principal::clearPrincipal() {
00281     processHistoryPtr_ = 0;
00282     processHistoryID_ = ProcessHistoryID();
00283     reader_ = 0;
00284     for(auto const& prod : *this) {
00285       prod->resetProductData();
00286     }
00287     productPtrs_.clear();
00288   }
00289 
00290   void
00291   Principal::deleteProduct(BranchID const& id) {
00292     ProductHolderBase* phb = getExistingProduct(id);
00293     assert(nullptr != phb);
00294     auto itFound = productPtrs_.find(phb->product().get());
00295     if(itFound != productPtrs_.end()) {
00296       productPtrs_.erase(itFound);
00297     } 
00298     phb->deleteProduct();
00299   }
00300   
00301   // Set the principal for the Event, Lumi, or Run.
00302   void
00303   Principal::fillPrincipal(ProcessHistoryID const& hist, DelayedReader* reader) {
00304     if(reader) {
00305       reader_ = reader;
00306     }
00307 
00308     ProcessHistory const* inputProcessHistory = 0;
00309     if (historyAppender_ && productRegistry().anyProductProduced()) {
00310       CachedHistory const& cachedHistory = 
00311         historyAppender_->appendToProcessHistory(hist,
00312                                                 *processConfiguration_);
00313       processHistoryPtr_ = cachedHistory.processHistory();
00314       processHistoryID_ = cachedHistory.processHistoryID();
00315       inputProcessHistory = cachedHistory.inputProcessHistory();
00316     }
00317     else {
00318       if (hist.isValid()) {
00319         ProcessHistoryRegistry* registry = ProcessHistoryRegistry::instance();
00320         inputProcessHistory = registry->getMapped(hist);
00321         if (inputProcessHistory == 0) {
00322           throw Exception(errors::LogicError)
00323             << "Principal::fillPrincipal\n"
00324             << "Input ProcessHistory not found in registry\n"
00325             << "Contact a Framework developer\n";
00326         }
00327       } else {
00328         inputProcessHistory = &emptyProcessHistory_;
00329       }
00330       processHistoryID_ = hist;
00331       processHistoryPtr_ = inputProcessHistory;        
00332     }
00333 
00334     if (orderProcessHistoryID_ != processHistoryID_) {
00335       std::vector<std::string> const& lookupProcessNames = productLookup_->lookupProcessNames();
00336       lookupProcessOrder_.assign(lookupProcessNames.size(), 0);
00337       unsigned int k = 0;
00338       for (auto iter = processHistoryPtr_->rbegin(),
00339                 iEnd = processHistoryPtr_->rend();
00340            iter != iEnd; ++iter) {
00341         auto nameIter = std::find(lookupProcessNames.begin(), lookupProcessNames.end(), iter->processName());
00342         if (nameIter == lookupProcessNames.end()) {
00343           continue;
00344         }
00345         lookupProcessOrder_.at(k) = nameIter - lookupProcessNames.begin();
00346         ++k;
00347       }
00348       orderProcessHistoryID_ = processHistoryID_;
00349     }
00350   }
00351 
00352   ProductHolderBase*
00353   Principal::getExistingProduct(BranchID const& branchID) {
00354     ProductHolderIndex index = preg_->indexFrom(branchID);
00355     assert(index != ProductHolderIndexInvalid);
00356     SharedProductPtr ptr = productHolders_.at(index);
00357     return ptr.get();
00358   }
00359 
00360   ProductHolderBase*
00361   Principal::getExistingProduct(ProductHolderBase const& productHolder) {
00362     ProductHolderBase* phb = getExistingProduct(productHolder.branchDescription().branchID());
00363     assert(nullptr == phb || BranchKey(productHolder.branchDescription()) == BranchKey(phb->branchDescription()));
00364     return phb;
00365   }
00366 
00367   void
00368   Principal::addProduct_(std::auto_ptr<ProductHolderBase> productHolder) {
00369     ConstBranchDescription const& bd = productHolder->branchDescription();
00370     assert (!bd.className().empty());
00371     assert (!bd.friendlyClassName().empty());
00372     assert (!bd.moduleLabel().empty());
00373     assert (!bd.processName().empty());
00374     SharedProductPtr phb(productHolder);
00375 
00376     ProductHolderIndex index = preg_->indexFrom(bd.branchID());
00377     assert(index != ProductHolderIndexInvalid);
00378     productHolders_[index] = phb;
00379   }
00380 
00381   void
00382   Principal::addProductOrThrow(std::auto_ptr<ProductHolderBase> productHolder) {
00383     ProductHolderBase const* phb = getExistingProduct(*productHolder);
00384     if(phb != nullptr) {
00385       ConstBranchDescription const& bd = productHolder->branchDescription();
00386       throw Exception(errors::InsertFailure, "AlreadyPresent")
00387           << "addProductOrThrow: Problem found while adding product, "
00388           << "product already exists for ("
00389           << bd.friendlyClassName() << ","
00390           << bd.moduleLabel() << ","
00391           << bd.productInstanceName() << ","
00392           << bd.processName()
00393           << ")\n";
00394     }
00395     addProduct_(productHolder);
00396   }
00397 
00398   Principal::ConstProductPtr
00399   Principal::getProductHolder(BranchID const& bid, bool resolveProd, bool fillOnDemand) const {
00400     ProductHolderIndex index = preg_->indexFrom(bid);
00401     if(index == ProductHolderIndexInvalid){
00402        return ConstProductPtr();
00403     }
00404     return getProductByIndex(index, resolveProd, fillOnDemand);
00405   }
00406 
00407   Principal::ConstProductPtr
00408   Principal::getProductByIndex(ProductHolderIndex const& index, bool resolveProd, bool fillOnDemand) const {
00409 
00410     ConstProductPtr const phb = productHolders_[index].get();
00411     if(nullptr == phb) {
00412       return phb;
00413     }
00414     if(resolveProd && !phb->productUnavailable()) {
00415       this->resolveProduct(*phb, fillOnDemand);
00416     }
00417     return phb;
00418   }
00419 
00420   BasicHandle
00421   Principal::getByLabel(KindOfType kindOfType,
00422                         TypeID const& typeID,
00423                         InputTag const& inputTag) const {
00424 
00425     ProductData const* result = findProductByLabel(kindOfType, typeID, inputTag);
00426     if(result == 0) {
00427       boost::shared_ptr<cms::Exception> whyFailed =
00428         makeNotFoundException("getByLabel", kindOfType, typeID, inputTag.label(), inputTag.instance(), inputTag.process());
00429       return BasicHandle(whyFailed);
00430     }
00431     return BasicHandle(*result);
00432   }
00433 
00434   BasicHandle
00435   Principal::getByLabel(KindOfType kindOfType,
00436                         TypeID const& typeID,
00437                         std::string const& label,
00438                         std::string const& instance,
00439                         std::string const& process) const {
00440 
00441     ProductData const* result = findProductByLabel(kindOfType, typeID, label, instance, process);
00442     if(result == 0) {
00443       boost::shared_ptr<cms::Exception> whyFailed =
00444         makeNotFoundException("getByLabel", kindOfType, typeID, label, instance, process);
00445       return BasicHandle(whyFailed);
00446     }
00447     return BasicHandle(*result);
00448   }
00449 
00450   BasicHandle
00451   Principal::getByToken(KindOfType kindOfType,
00452                         TypeID const& typeID,
00453                         ProductHolderIndex index,
00454                         bool skipCurrentProcess,
00455                         bool& ambiguous) const {
00456     assert(index !=ProductHolderIndexInvalid);
00457     boost::shared_ptr<ProductHolderBase> const& productHolder = productHolders_[index];
00458     assert(0!=productHolder.get());
00459     ProductHolderBase::ResolveStatus resolveStatus;
00460     ProductData const* productData = productHolder->resolveProduct(resolveStatus, skipCurrentProcess);
00461     if(resolveStatus == ProductHolderBase::Ambiguous) {
00462       ambiguous = true;
00463       return BasicHandle();
00464     }
00465     if(productData == 0) {
00466       return BasicHandle();
00467     }
00468     return BasicHandle(*productData);    
00469   }
00470 
00471   void
00472   Principal::getManyByType(TypeID const& typeID,
00473                            BasicHandleVec& results) const {
00474 
00475     assert(results.empty());
00476 
00477     // This finds the indexes to all the ProductHolder's matching the type
00478     ProductHolderIndexHelper::Matches matches =
00479       productLookup().relatedIndexes(PRODUCT_TYPE, typeID);
00480 
00481     if (matches.numberOfMatches() == 0) {
00482       maybeThrowMissingDictionaryException(typeID, false, preg_->missingDictionaries());
00483       return;
00484     }
00485 
00486     results.reserve(matches.numberOfMatches());
00487 
00488     // Loop over the ProductHolders. Add the products that are actually
00489     // present into the results. This will also trigger delayed reading,
00490     // on demand production, and check for deleted products as appropriate.
00491 
00492     // Over the years the code that uses getManyByType has grown to depend
00493     // on the ordering of the results. The order originally was just an
00494     // accident of how previous versions of the code were written, but
00495     // here we have to go through some extra effort to preserve that ordering.
00496 
00497     // We build a list of holders that match a particular label and instance.
00498     // When that list is complete we call findProducts, which loops over
00499     // that list in reverse order of the ProcessHistory (starts with the
00500     // most recent).  Then we clear the list and repeat this until all the
00501     // matching label and instance subsets have been dealt with.
00502 
00503     // Note that the function isFullyResolved returns true for the ProductHolders
00504     // that are associated with an empty process name. Those are the ones that
00505     // know how to search for the most recent process name matching
00506     // a label and instance. We do not need these for getManyByType and
00507     // skip them. In addition to skipping them, we make use of the fact
00508     // that they mark the beginning of each subset of holders with the same
00509     // label and instance. They tell us when to call findProducts. 
00510 
00511     std::vector<ProductHolderBase const*> holders;
00512 
00513     for(unsigned int i = 0; i < matches.numberOfMatches(); ++i) {
00514 
00515       ProductHolderIndex index = matches.index(i);
00516 
00517       if(!matches.isFullyResolved(i)) {
00518         if(!holders.empty()) {
00519           // Process the ones with a particular module label and instance
00520           findProducts(holders, typeID, results);
00521           holders.clear();
00522         }
00523       } else {
00524         ProductHolderBase const* productHolder = productHolders_.at(index).get();
00525         assert(productHolder);
00526         holders.push_back(productHolder);
00527       }
00528     }
00529     // Do not miss the last subset of products
00530     if(!holders.empty()) {
00531       findProducts(holders, typeID, results);
00532     }
00533     return;
00534   }
00535 
00536   void
00537   Principal::findProducts(std::vector<ProductHolderBase const*> const& holders,
00538                           TypeID const& typeID,
00539                           BasicHandleVec& results) const {
00540 
00541     for (auto iter = processHistoryPtr_->rbegin(),
00542               iEnd = processHistoryPtr_->rend();
00543          iter != iEnd; ++iter) {
00544       std::string const& process = iter->processName();
00545       for (auto productHolder : holders) {
00546         ConstBranchDescription const& bd = productHolder->branchDescription();
00547         if (process == bd.processName()) {
00548 
00549           // Ignore aliases to avoid matching the same product multiple times.
00550           if(bd.isAlias()) {
00551             continue;
00552           }
00553 
00554           //NOTE sometimes 'productHolder->productUnavailable()' is true if was already deleted
00555           if(productHolder->productWasDeleted()) {
00556             throwProductDeletedException("findProducts",
00557                                          typeID,
00558                                          bd.moduleLabel(),
00559                                          bd.productInstanceName(),
00560                                          bd.processName());
00561           }
00562 
00563           // Skip product if not available.
00564           if(!productHolder->productUnavailable()) {
00565 
00566             this->resolveProduct(*productHolder, true);
00567             // If the product is a dummy filler, product holder will now be marked unavailable.
00568             // Unscheduled execution can fail to produce the EDProduct so check
00569             if(productHolder->product() && !productHolder->productUnavailable() && !productHolder->onDemand()) {
00570               // Found a good match, save it
00571               BasicHandle bh(productHolder->productData());
00572               results.push_back(bh);
00573             }
00574           }
00575         }
00576       }
00577     }
00578   }
00579 
00580   ProductData const*
00581   Principal::findProductByLabel(KindOfType kindOfType,
00582                                 TypeID const& typeID,
00583                                 InputTag const& inputTag) const {
00584 
00585     bool skipCurrentProcess = inputTag.willSkipCurrentProcess();
00586 
00587     ProductHolderIndex index = inputTag.indexFor(typeID, branchType(), &productRegistry());
00588 
00589     if (index == ProductHolderIndexInvalid) {
00590 
00591       char const* processName = inputTag.process().c_str();
00592       if (skipCurrentProcess) {
00593         processName = "\0";
00594       }
00595 
00596       index = productLookup().index(kindOfType,
00597                                     typeID,
00598                                     inputTag.label().c_str(),
00599                                     inputTag.instance().c_str(),
00600                                     processName);
00601 
00602       if(index == ProductHolderIndexAmbiguous) {
00603         throwAmbiguousException("findProductByLabel", typeID, inputTag.label(), inputTag.instance(), inputTag.process());
00604       } else if (index == ProductHolderIndexInvalid) {
00605         ProductHolderIndexHelper::Matches matches =
00606           productLookup().relatedIndexes(kindOfType, typeID);
00607 
00608         if (matches.numberOfMatches() == 0) {
00609           maybeThrowMissingDictionaryException(typeID, kindOfType == ELEMENT_TYPE, preg_->missingDictionaries());
00610         }
00611         return 0;
00612       }
00613       inputTag.tryToCacheIndex(index, typeID, branchType(), &productRegistry());
00614     }
00615 
00616     boost::shared_ptr<ProductHolderBase> const& productHolder = productHolders_[index];
00617 
00618     ProductHolderBase::ResolveStatus resolveStatus;
00619     ProductData const* productData = productHolder->resolveProduct(resolveStatus, skipCurrentProcess);
00620     if(resolveStatus == ProductHolderBase::Ambiguous) {
00621       throwAmbiguousException("findProductByLabel", typeID, inputTag.label(), inputTag.instance(), inputTag.process());
00622     }
00623     return productData;
00624   }
00625 
00626   ProductData const*
00627   Principal::findProductByLabel(KindOfType kindOfType,
00628                                 TypeID const& typeID,
00629                                 std::string const& label,
00630                                 std::string const& instance,
00631                                 std::string const& process) const {
00632 
00633     ProductHolderIndex index = productLookup().index(kindOfType,
00634                                                      typeID,
00635                                                      label.c_str(),
00636                                                      instance.c_str(),
00637                                                      process.c_str());
00638    
00639     if(index == ProductHolderIndexAmbiguous) {
00640       throwAmbiguousException("findProductByLabel", typeID, label, instance, process);
00641     } else if (index == ProductHolderIndexInvalid) {
00642       ProductHolderIndexHelper::Matches matches =
00643         productLookup().relatedIndexes(kindOfType, typeID);
00644 
00645       if (matches.numberOfMatches() == 0) {
00646         maybeThrowMissingDictionaryException(typeID, kindOfType == ELEMENT_TYPE, preg_->missingDictionaries());
00647       }
00648       return 0;
00649     }
00650     boost::shared_ptr<ProductHolderBase> const& productHolder = productHolders_[index];
00651 
00652     ProductHolderBase::ResolveStatus resolveStatus;
00653     ProductData const* productData = productHolder->resolveProduct(resolveStatus, false);
00654     if(resolveStatus == ProductHolderBase::Ambiguous) {
00655       throwAmbiguousException("findProductByLabel", typeID, label, instance, process);
00656     }
00657     return productData;
00658   }
00659 
00660   ProductData const*
00661   Principal::findProductByTag(TypeID const& typeID, InputTag const& tag) const {
00662     ProductData const* productData =
00663       findProductByLabel(PRODUCT_TYPE,
00664                          typeID,
00665                          tag);
00666     if(productData == nullptr) {
00667       throwNotFoundException("findProductByTag", typeID, tag);
00668     }
00669     return productData;
00670   }
00671 
00672   OutputHandle
00673   Principal::getForOutput(BranchID const& bid, bool getProd) const {
00674     ConstProductPtr const phb = getProductHolder(bid, getProd, true);
00675     if(phb == nullptr) {
00676       throwProductNotFoundException("getForOutput", errors::LogicError, bid);
00677     }
00678     if (phb->productWasDeleted()) {
00679       throwProductDeletedException("getForOutput",phb->productType(),
00680                                    phb->moduleLabel(),
00681                                    phb->productInstanceName(),
00682                                    phb->processName());
00683     }
00684     if(!phb->provenance() || (!phb->product() && !phb->productProvenancePtr())) {
00685       return OutputHandle();
00686     }
00687     return OutputHandle(WrapperHolder(phb->product().get(), phb->productData().getInterface()), &phb->branchDescription(), phb->productProvenancePtr());
00688   }
00689 
00690   Provenance
00691   Principal::getProvenance(BranchID const& bid) const {
00692     ConstProductPtr const phb = getProductHolder(bid, false, true);
00693     if(phb == nullptr) {
00694       throwProductNotFoundException("getProvenance", errors::ProductNotFound, bid);
00695     }
00696 
00697     if(phb->onDemand()) {
00698       unscheduledFill(phb->branchDescription().moduleLabel());
00699     }
00700     // We already tried to produce the unscheduled products above
00701     // If they still are not there, then throw
00702     if(phb->onDemand()) {
00703       throwProductNotFoundException("getProvenance(onDemand)", errors::ProductNotFound, bid);
00704     }
00705 
00706     return *phb->provenance();
00707   }
00708 
00709   // This one is mostly for test printout purposes
00710   // No attempt to trigger on demand execution
00711   // Skips provenance when the EDProduct is not there
00712   void
00713   Principal::getAllProvenance(std::vector<Provenance const*>& provenances) const {
00714     provenances.clear();
00715     for(auto const& productHolder : *this) {
00716       if(productHolder->singleProduct() && productHolder->provenanceAvailable() && !productHolder->branchDescription().isAlias()) {
00717         // We do not attempt to get the event/lumi/run status from the provenance,
00718         // because the per event provenance may have been dropped.
00719         if(productHolder->provenance()->product().present()) {
00720            provenances.push_back(productHolder->provenance());
00721         }
00722       }
00723     }
00724   }
00725 
00726   void
00727   Principal::recombine(Principal& other, std::vector<BranchID> const& bids) {
00728     for(auto const& prod : bids) {
00729       ProductHolderIndex index= preg_->indexFrom(prod);
00730       assert(index!=ProductHolderIndexInvalid);
00731       ProductHolderIndex indexO = other.preg_->indexFrom(prod);
00732       assert(indexO!=ProductHolderIndexInvalid);
00733       productHolders_[index].swap(other.productHolders_[indexO]);
00734       productHolders_[index]->setPrincipal(this);
00735     }
00736     reader_->mergeReaders(other.reader());
00737   }
00738 
00739   WrapperHolder
00740   Principal::getIt(ProductID const&) const {
00741     assert(nullptr);
00742     return WrapperHolder();
00743   }
00744 
00745   void
00746   Principal::checkUniquenessAndType(WrapperOwningHolder const& prod, ProductHolderBase const* phb) const {
00747     if(!prod.isValid()) return;
00748     // These are defensive checks against things that should never happen, but have.
00749     // Checks that the same physical product has not already been put into the event.
00750     bool alreadyPresent = !productPtrs_.insert(prod.wrapper()).second;
00751     if(alreadyPresent) {
00752       phb->checkType(prod);
00753       const_cast<WrapperOwningHolder&>(prod).reset();
00754       throwCorruptionException("checkUniquenessAndType", phb->branchDescription().branchName());
00755     }
00756     // Checks that the real type of the product matches the branch.
00757     phb->checkType(prod);
00758   }
00759 
00760   void
00761   Principal::putOrMerge(WrapperOwningHolder const& prod, ProductHolderBase const* phb) const {
00762     bool willBePut = phb->putOrMergeProduct();
00763     if(willBePut) {
00764       checkUniquenessAndType(prod, phb);
00765       phb->putProduct(prod);
00766     } else {
00767       phb->checkType(prod);
00768       phb->mergeProduct(prod);
00769     }
00770   }
00771 
00772   void
00773   Principal::putOrMerge(WrapperOwningHolder const& prod, ProductProvenance& prov, ProductHolderBase* phb) {
00774     bool willBePut = phb->putOrMergeProduct();
00775     if(willBePut) {
00776       checkUniquenessAndType(prod, phb);
00777       phb->putProduct(prod, prov);
00778     } else {
00779       phb->checkType(prod);
00780       phb->mergeProduct(prod, prov);
00781     }
00782   }
00783 
00784   void
00785   Principal::adjustIndexesAfterProductRegistryAddition() {
00786     if(preg_->getNextIndexValue(branchType_) != productHolders_.size()) {
00787       productHolders_.resize(preg_->getNextIndexValue(branchType_));
00788       for(auto const& prod : preg_->productList()) {
00789         BranchDescription const& bd = prod.second;
00790         if(bd.branchType() == branchType_) {
00791           ProductHolderIndex index = preg_->indexFrom(bd.branchID());
00792           assert(index != ProductHolderIndexInvalid);
00793           if(!productHolders_[index]) {
00794             // no product holder.  Must add one. The new entry must be an input product holder.
00795             assert(!bd.produced());
00796             boost::shared_ptr<ConstBranchDescription> cbd(new ConstBranchDescription(bd));
00797             addInputProduct(cbd);
00798           }
00799         }
00800       }
00801     }
00802     assert(preg_->getNextIndexValue(branchType_) == productHolders_.size());
00803   }
00804 }