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
00122 std::string const source("source");
00123 ProductRegistry::ProductList const& prodsList = reg->productList();
00124
00125
00126
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
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
00162
00163
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
00211
00212
00213 size_t
00214 Principal::size() const {
00215 size_t size = 0U;
00216 for(auto const& prod : *this) {
00217 if(prod->singleProduct() &&
00218 !prod->productUnavailable() &&
00219 !prod->onDemand() &&
00220 !prod->branchDescription().dropped()) {
00221 ++size;
00222 }
00223 }
00224 return size;
00225 }
00226
00227
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
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
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
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
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
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
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
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
00550 if(bd.isAlias()) {
00551 continue;
00552 }
00553
00554
00555 if(productHolder->productWasDeleted()) {
00556 throwProductDeletedException("findProducts",
00557 typeID,
00558 bd.moduleLabel(),
00559 bd.productInstanceName(),
00560 bd.processName());
00561 }
00562
00563
00564 if(!productHolder->productUnavailable()) {
00565
00566 this->resolveProduct(*productHolder, true);
00567
00568
00569 if(productHolder->product() && !productHolder->productUnavailable() && !productHolder->onDemand()) {
00570
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
00701
00702 if(phb->onDemand()) {
00703 throwProductNotFoundException("getProvenance(onDemand)", errors::ProductNotFound, bid);
00704 }
00705
00706 return *phb->provenance();
00707 }
00708
00709
00710
00711
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
00718
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
00749
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
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
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 }