CMS 3D CMS Logo

Principal.cc
Go to the documentation of this file.
1 
5 
15 #include "ProductResolvers.h"
21 
23 
24 #include <algorithm>
25 #include <cstring>
26 #include <limits>
27 #include <sstream>
28 #include <stdexcept>
29 #include <typeinfo>
30 #include <atomic>
31 
32 namespace edm {
33 
35 
36  static std::string appendCurrentProcessIfAlias(std::string const& processFromInputTag,
37  std::string const& currentProcess) {
38  if (processFromInputTag == InputTag::kCurrentProcess) {
39  std::string returnValue = processFromInputTag;
40  returnValue += " (";
41  returnValue += currentProcess;
42  returnValue += ")";
43  return returnValue;
44  }
45  return processFromInputTag;
46  }
47 
48  static void throwProductNotFoundException(char const* where, errors::ErrorCodes error, BranchID const& bid) {
49  throw Exception(error, "InvalidID") << "Principal::" << where << ": no product with given branch id: " << bid
50  << "\n";
51  }
52 
53  static std::shared_ptr<cms::Exception> makeNotFoundException(char const* where,
54  KindOfType kindOfType,
55  TypeID const& productType,
56  std::string const& label,
57  std::string const& instance,
58  std::string const& process) {
59  std::shared_ptr<cms::Exception> exception = std::make_shared<Exception>(errors::ProductNotFound);
60  if (kindOfType == PRODUCT_TYPE) {
61  *exception << "Principal::" << where
62  << ": Found zero products matching all criteria\nLooking for type: " << productType << "\n"
63  << "Looking for module label: " << label << "\n"
64  << "Looking for productInstanceName: " << instance << "\n"
65  << (process.empty() ? "" : "Looking for process: ") << process << "\n";
66  } else {
67  *exception << "Principal::" << where
68  << ": Found zero products matching all criteria\nLooking for a container with elements of type: "
69  << productType << "\n"
70  << "Looking for module label: " << label << "\n"
71  << "Looking for productInstanceName: " << instance << "\n"
72  << (process.empty() ? "" : "Looking for process: ") << process << "\n";
73  }
74  return exception;
75  }
76 
77  static void throwAmbiguousException(const char* where,
78  TypeID const& productType,
79  std::string const& label,
80  std::string const& instance,
81  std::string const& process) {
82  cms::Exception exception("AmbiguousProduct");
83  exception << "Principal::" << where
84  << ": More than 1 product matches all criteria\nLooking for type: " << productType << "\n"
85  << "Looking for module label: " << label << "\n"
86  << "Looking for productInstanceName: " << instance << "\n"
87  << (process.empty() ? "" : "Looking for process: ") << process << "\n"
88  << "This can only occur with get function calls using a Handle<View> argument.\n"
89  << "Try a get not using a View or change the instance name of one of the products";
90  throw exception;
91  }
92 
93  namespace {
94  void failedToRegisterConsumesMany(edm::TypeID const& iType) {
95  cms::Exception exception("GetManyWithoutRegistration");
96  exception << "::getManyByType called for " << iType
97  << " without a corresponding consumesMany being called for this module. \n";
98  throw exception;
99  }
100 
101  void failedToRegisterConsumes(KindOfType kindOfType,
102  TypeID const& productType,
103  std::string const& moduleLabel,
104  std::string const& productInstanceName,
105  std::string const& processName) {
106  cms::Exception exception("GetByLabelWithoutRegistration");
107  exception << "::getByLabel without corresponding call to consumes or mayConsumes for this module.\n"
108  << (kindOfType == PRODUCT_TYPE ? " type: " : " type: edm::View<") << productType
109  << (kindOfType == PRODUCT_TYPE ? "\n module label: " : ">\n module label: ") << moduleLabel
110  << "\n product instance name: '" << productInstanceName << "'\n process name: '" << processName
111  << "'\n";
112  throw exception;
113  }
114  } // namespace
115 
116  //0 means unset
117  static std::atomic<Principal::CacheIdentifier_t> s_nextIdentifier{1};
119  return s_nextIdentifier.fetch_add(1, std::memory_order_acq_rel);
120  }
121 
122  Principal::Principal(std::shared_ptr<ProductRegistry const> reg,
123  std::shared_ptr<ProductResolverIndexHelper const> productLookup,
124  ProcessConfiguration const& pc,
125  BranchType bt,
126  HistoryAppender* historyAppender,
127  bool isForPrimaryProcess)
128  : EDProductGetter(),
129  processHistoryPtr_(),
130  processHistoryID_(),
131  processHistoryIDBeforeConfig_(),
132  processConfiguration_(&pc),
133  productResolvers_(),
134  preg_(reg),
135  productLookup_(productLookup),
136  lookupProcessOrder_(productLookup->lookupProcessNames().size(), 0),
137  reader_(),
138  branchType_(bt),
139  historyAppender_(historyAppender),
140  cacheIdentifier_(nextIdentifier()) {
141  productResolvers_.resize(reg->getNextIndexValue(bt));
142  //Now that these have been set, we can create the list of Branches we need.
143  std::string const source("source");
144  ProductRegistry::ProductList const& prodsList = reg->productList();
145  // The constructor of an alias product holder takes as an argument the product holder for which it is an alias.
146  // So, the non-alias product holders must be created first.
147  // Therefore, on this first pass, skip current EDAliases.
148  bool hasAliases = false;
149  bool hasSwitchAliases = false;
150  for (auto const& prod : prodsList) {
151  BranchDescription const& bd = prod.second;
152  if (bd.branchType() == branchType_) {
153  if (isForPrimaryProcess or bd.processName() == pc.processName()) {
154  if (bd.isAlias()) {
155  hasAliases = true;
156  } else if (bd.isSwitchAlias()) {
157  hasSwitchAliases = true;
158  } else {
159  auto cbd = std::make_shared<BranchDescription const>(bd);
160  if (bd.produced()) {
161  if (bd.moduleLabel() == source) {
162  addSourceProduct(cbd);
163  } else if (bd.onDemand()) {
166  } else {
167  addScheduledProduct(cbd);
168  }
169  } else {
170  if (bd.onDemand()) {
172  } else {
174  }
175  }
176  }
177  } else {
178  //We are in a SubProcess and this branch is from the parent
179  auto cbd = std::make_shared<BranchDescription const>(bd);
181  }
182  }
183  }
184  // Now process any EDAliases
185  if (hasAliases) {
186  for (auto const& prod : prodsList) {
187  BranchDescription const& bd = prod.second;
188  if (bd.isAlias() && bd.branchType() == branchType_) {
189  addAliasedProduct(std::make_shared<BranchDescription const>(bd));
190  }
191  }
192  }
193  // Finally process any SwitchProducer aliases
194  if (hasSwitchAliases) {
195  for (auto const& prod : prodsList) {
196  BranchDescription const& bd = prod.second;
197  if (bd.isSwitchAlias() && bd.branchType() == branchType_) {
199  auto cbd = std::make_shared<BranchDescription const>(bd);
200  // Need different implementation for SwitchProducers not
201  // in any Path (onDemand) and for those in a Path in order
202  // to prevent the switch-aliased-for EDProducers from
203  // being run when the SwitchProducer is in a Path after a
204  // failing EDFilter.
205  if (bd.onDemand()) {
207  } else {
209  }
210  }
211  }
212  }
213 
214  // Now create the ProductResolvers that search in reverse process
215  // order and are used for queries where the process name is the
216  // empty string
217  std::vector<std::string> const& lookupProcessNames = productLookup_->lookupProcessNames();
218  std::vector<ProductResolverIndex> matchingHolders(lookupProcessNames.size(), ProductResolverIndexInvalid);
219  std::vector<bool> ambiguous(lookupProcessNames.size(), false);
220  unsigned int beginElements = productLookup_->beginElements();
221  std::vector<TypeID> const& sortedTypeIDs = productLookup_->sortedTypeIDs();
222  std::vector<ProductResolverIndexHelper::Range> const& ranges = productLookup_->ranges();
223  std::vector<ProductResolverIndexHelper::IndexAndNames> const& indexAndNames = productLookup_->indexAndNames();
224  std::vector<char> const& processNamesCharArray = productLookup_->processNames();
225 
226  unsigned int numberOfMatches = 0;
228  if (!sortedTypeIDs.empty()) {
229  ProductResolverIndex productResolverIndex = ProductResolverIndexInvalid;
230  for (unsigned int k = 0, kEnd = sortedTypeIDs.size(); k < kEnd; ++k) {
232  for (unsigned int i = range.begin(); i < range.end(); ++i) {
233  ProductResolverIndexHelper::IndexAndNames const& product = indexAndNames.at(i);
234  if (product.startInProcessNames() == 0) {
235  if (productResolverIndex != ProductResolverIndexInvalid) {
236  if ((numberOfMatches == 1) and (lastMatchIndex != ProductResolverIndexAmbiguous)) {
237  //only one choice so use a special resolver
238  productResolvers_.at(productResolverIndex) =
239  std::make_shared<SingleChoiceNoProcessProductResolver>(lastMatchIndex);
240  } else {
241  bool productMadeAtEnd = false;
242  //Need to know if the product from this processes is added at end of transition
243  for (unsigned int j = 0; j < matchingHolders.size(); ++j) {
244  if ((not ambiguous[j]) and ProductResolverIndexInvalid != matchingHolders[j] and
245  productResolvers_[matchingHolders[j]]->branchDescription().availableOnlyAtEndTransition()) {
246  productMadeAtEnd = true;
247  break;
248  }
249  }
250  std::shared_ptr<ProductResolverBase> newHolder =
251  std::make_shared<NoProcessProductResolver>(matchingHolders, ambiguous, productMadeAtEnd);
252  productResolvers_.at(productResolverIndex) = newHolder;
253  }
254  matchingHolders.assign(lookupProcessNames.size(), ProductResolverIndexInvalid);
255  ambiguous.assign(lookupProcessNames.size(), false);
256  numberOfMatches = 0;
257  lastMatchIndex = ProductResolverIndexInvalid;
258  }
259  productResolverIndex = product.index();
260  } else {
261  std::string process(&processNamesCharArray.at(product.startInProcessNames()));
262  auto iter = std::find(lookupProcessNames.begin(), lookupProcessNames.end(), process);
263  assert(iter != lookupProcessNames.end());
264  ProductResolverIndex iMatchingIndex = product.index();
265  lastMatchIndex = iMatchingIndex;
266  assert(iMatchingIndex != ProductResolverIndexInvalid);
267  ++numberOfMatches;
268  if (iMatchingIndex == ProductResolverIndexAmbiguous) {
269  assert(k >= beginElements);
270  ambiguous.at(iter - lookupProcessNames.begin()) = true;
271  } else {
272  matchingHolders.at(iter - lookupProcessNames.begin()) = iMatchingIndex;
273  }
274  }
275  }
276  }
277  //Need to know if the product from this processes is added at end of transition
278  if ((numberOfMatches == 1) and (lastMatchIndex != ProductResolverIndexAmbiguous)) {
279  //only one choice so use a special resolver
280  productResolvers_.at(productResolverIndex) =
281  std::make_shared<SingleChoiceNoProcessProductResolver>(lastMatchIndex);
282  } else {
283  bool productMadeAtEnd = false;
284  for (unsigned int i = 0; i < matchingHolders.size(); ++i) {
285  if ((not ambiguous[i]) and ProductResolverIndexInvalid != matchingHolders[i] and
286  productResolvers_[matchingHolders[i]]->branchDescription().availableOnlyAtEndTransition()) {
287  productMadeAtEnd = true;
288  break;
289  }
290  }
291  std::shared_ptr<ProductResolverBase> newHolder =
292  std::make_shared<NoProcessProductResolver>(matchingHolders, ambiguous, productMadeAtEnd);
293  productResolvers_.at(productResolverIndex) = newHolder;
294  }
295  }
296  }
297 
299 
300  // Number of products in the Principal.
301  // For products in an input file and not yet read in due to delayed read,
302  // this routine assumes a real product is there.
303  size_t Principal::size() const {
304  size_t size = 0U;
305  for (auto const& prod : *this) {
306  if (prod->singleProduct() && // Not a NoProcessProductResolver
307  !prod->productUnavailable() && !prod->unscheduledWasNotRun() && !prod->branchDescription().dropped()) {
308  ++size;
309  }
310  }
311  return size;
312  }
313 
314  // adjust provenance for input products after new input file has been merged
316  ProductRegistry::ProductList const& prodsList = reg.productList();
317  for (auto const& prod : prodsList) {
318  BranchDescription const& bd = prod.second;
319  if (!bd.produced() && (bd.branchType() == branchType_)) {
320  auto cbd = std::make_shared<BranchDescription const>(bd);
321  auto phb = getExistingProduct(cbd->branchID());
322  if (phb == nullptr || phb->branchDescription().branchName() != cbd->branchName()) {
323  return false;
324  }
325  phb->resetBranchDescription(cbd);
326  }
327  }
328  return true;
329  }
330 
331  void Principal::addScheduledProduct(std::shared_ptr<BranchDescription const> bd) {
332  auto phb = std::make_unique<PuttableProductResolver>(std::move(bd));
334  }
335 
336  void Principal::addSourceProduct(std::shared_ptr<BranchDescription const> bd) {
337  auto phb = std::make_unique<PuttableProductResolver>(std::move(bd));
339  }
340 
341  void Principal::addDelayedReaderInputProduct(std::shared_ptr<BranchDescription const> bd) {
342  addProductOrThrow(std::make_unique<DelayedReaderInputProductResolver>(std::move(bd)));
343  }
344 
345  void Principal::addPutOnReadInputProduct(std::shared_ptr<BranchDescription const> bd) {
346  addProductOrThrow(std::make_unique<PutOnReadInputProductResolver>(std::move(bd)));
347  }
348 
349  void Principal::addUnscheduledProduct(std::shared_ptr<BranchDescription const> bd) {
350  addProductOrThrow(std::make_unique<UnscheduledProductResolver>(std::move(bd)));
351  }
352 
353  void Principal::addAliasedProduct(std::shared_ptr<BranchDescription const> bd) {
354  ProductResolverIndex index = preg_->indexFrom(bd->originalBranchID());
356 
357  addProductOrThrow(std::make_unique<AliasProductResolver>(
358  std::move(bd), dynamic_cast<DataManagingOrAliasProductResolver&>(*productResolvers_[index])));
359  }
360 
361  void Principal::addSwitchProducerProduct(std::shared_ptr<BranchDescription const> bd) {
362  ProductResolverIndex index = preg_->indexFrom(bd->switchAliasForBranchID());
364 
365  addProductOrThrow(std::make_unique<SwitchProducerProductResolver>(
366  std::move(bd), dynamic_cast<DataManagingOrAliasProductResolver&>(*productResolvers_[index])));
367  }
368 
369  void Principal::addSwitchAliasProduct(std::shared_ptr<BranchDescription const> bd) {
370  ProductResolverIndex index = preg_->indexFrom(bd->switchAliasForBranchID());
372 
373  addProductOrThrow(std::make_unique<SwitchAliasProductResolver>(
374  std::move(bd), dynamic_cast<DataManagingOrAliasProductResolver&>(*productResolvers_[index])));
375  }
376 
377  void Principal::addParentProcessProduct(std::shared_ptr<BranchDescription const> bd) {
378  addProductOrThrow(std::make_unique<ParentProcessProductResolver>(std::move(bd)));
379  }
380 
381  // "Zero" the principal so it can be reused for another Event.
383  //We do not clear the product history information
384  // because it rarely changes and recalculating takes
385  // time.
386  reader_ = nullptr;
387  for (auto& prod : *this) {
388  prod->resetProductData();
389  }
390  }
391 
392  void Principal::deleteProduct(BranchID const& id) const {
393  auto phb = getExistingProduct(id);
394  assert(nullptr != phb);
395  phb->unsafe_deleteProduct();
396  }
397 
399  applyToResolvers([&iConfigure](ProductResolverBase* iResolver) { iResolver->setupUnscheduled(iConfigure); });
400  }
401 
403  //increment identifier here since clearPrincipal isn't called for Run/Lumi
405  if (reader) {
406  reader_ = reader;
407  }
408  }
409 
410  // Set the principal for the Event, Lumi, or Run.
412  ProcessHistory const* processHistory,
415 
416  if (historyAppender_ && productRegistry().anyProductProduced()) {
421  }
422  } else {
423  std::shared_ptr<ProcessHistory const> inputProcessHistory;
425  if (hist.isValid()) {
426  //does not own the pointer
427  auto noDel = [](void const*) {};
428  inputProcessHistory = std::shared_ptr<ProcessHistory const>(processHistory, noDel);
429  if (inputProcessHistory.get() == nullptr) {
430  throw Exception(errors::LogicError) << "Principal::fillPrincipal\n"
431  << "Input ProcessHistory not found in registry\n"
432  << "Contact a Framework developer\n";
433  }
434  } else {
435  //Since this is static we don't want it deleted
436  inputProcessHistory = std::shared_ptr<ProcessHistory const>(&s_emptyProcessHistory, [](void const*) {});
437  //no need to do any ordering since it is empty
439  }
441  processHistoryPtr_ = inputProcessHistory;
443  }
444  }
445 
447  std::vector<std::string> const& lookupProcessNames = productLookup_->lookupProcessNames();
448  lookupProcessOrder_.assign(lookupProcessNames.size(), 0);
449  unsigned int k = 0;
450 
451  // We loop over processes in reverse order of the ProcessHistory.
452  // If any entries in the product lookup tables are associated with
453  // the process we add it to the vector of processes in the order
454  // the lookup should be performed. There is one exception though,
455  // We start with the current process even if it is not in the ProcessHistory.
456  // The current process might be needed but not be in the process
457  // history if all the products produced in the current process are
458  // transient.
459  {
460  auto nameIterCurrentProcess =
461  std::find(lookupProcessNames.begin(), lookupProcessNames.end(), processConfiguration_->processName());
462  if (nameIterCurrentProcess != lookupProcessNames.end()) {
463  lookupProcessOrder_.at(k) = nameIterCurrentProcess - lookupProcessNames.begin();
464  ++k;
465  }
466  }
467 
468  // We just looked for the current process so skip it if
469  // it is in the ProcessHistory.
470  auto iter = processHistoryPtr_->rbegin();
471  if (iter->processName() == processConfiguration_->processName()) {
472  ++iter;
473  }
474 
475  for (auto iEnd = processHistoryPtr_->rend(); iter != iEnd; ++iter) {
476  auto nameIter = std::find(lookupProcessNames.begin(), lookupProcessNames.end(), iter->processName());
477  if (nameIter == lookupProcessNames.end()) {
478  continue;
479  }
480  lookupProcessOrder_.at(k) = nameIter - lookupProcessNames.begin();
481  ++k;
482  }
484  }
485  }
486 
487  // Set the principal for the ProcessBlock
488  void Principal::fillPrincipal(std::string const& processNameOfBlock, DelayedReader* reader) {
490 
491  std::vector<std::string> const& lookupProcessNames = productLookup_->lookupProcessNames();
492  lookupProcessOrder_.assign(lookupProcessNames.size(), 0);
493  if (!lookupProcessOrder_.empty()) {
494  auto iter = std::find(lookupProcessNames.begin(), lookupProcessNames.end(), processNameOfBlock);
495  if (iter != lookupProcessNames.end()) {
496  lookupProcessOrder_[0] = iter - lookupProcessNames.begin();
497  }
498  }
499  }
500 
502  return const_cast<ProductResolverBase*>(const_cast<const Principal*>(this)->getExistingProduct(branchID));
503  }
504 
506  ProductResolverIndex index = preg_->indexFrom(branchID);
508  return productResolvers_.at(index).get();
509  }
510 
512  auto phb = getExistingProduct(productResolver.branchDescription().branchID());
513  if (nullptr != phb && BranchKey(productResolver.branchDescription()) != BranchKey(phb->branchDescription())) {
514  BranchDescription const& newProduct = phb->branchDescription();
515  BranchDescription const& existing = productResolver.branchDescription();
516  if (newProduct.branchName() != existing.branchName() && newProduct.branchID() == existing.branchID()) {
517  throw cms::Exception("HashCollision")
518  << "Principal::getExistingProduct\n"
519  << " Branch " << newProduct.branchName() << " has same branch ID as branch " << existing.branchName()
520  << "\n"
521  << "Workaround: change process name or product instance name of " << newProduct.branchName() << "\n";
522  } else {
523  assert(nullptr == phb || BranchKey(productResolver.branchDescription()) == BranchKey(phb->branchDescription()));
524  }
525  }
526  return phb;
527  }
528 
529  void Principal::addProduct_(std::unique_ptr<ProductResolverBase> productResolver) {
530  BranchDescription const& bd = productResolver->branchDescription();
531  assert(!bd.className().empty());
532  assert(!bd.friendlyClassName().empty());
533  assert(!bd.moduleLabel().empty());
534  assert(!bd.processName().empty());
535  SharedProductPtr phb(productResolver.release());
536 
537  ProductResolverIndex index = preg_->indexFrom(bd.branchID());
539  productResolvers_[index] = phb;
540  }
541 
542  void Principal::addProductOrThrow(std::unique_ptr<ProductResolverBase> productResolver) {
543  ProductResolverBase const* phb = getExistingProduct(*productResolver);
544  if (phb != nullptr) {
545  BranchDescription const& bd = productResolver->branchDescription();
546  throw Exception(errors::InsertFailure, "AlreadyPresent")
547  << "addProductOrThrow: Problem found while adding product, "
548  << "product already exists for (" << bd.friendlyClassName() << "," << bd.moduleLabel() << ","
549  << bd.productInstanceName() << "," << bd.processName() << ")\n";
550  }
551  addProduct_(std::move(productResolver));
552  }
553 
555  ProductResolverIndex index = preg_->indexFrom(bid);
557  return ConstProductResolverPtr();
558  }
560  }
561 
564  return phb;
565  }
566 
567  unsigned int Principal::processBlockIndex(std::string const&) const {
568  throw Exception(errors::LogicError) << "Principal::processBlockIndex not implemented for this type of Principal";
569  }
570 
572  TypeID const& typeID,
573  InputTag const& inputTag,
574  EDConsumerBase const* consumer,
576  ModuleCallingContext const* mcc) const {
577  // Not implemented for ProcessBlocks, it might work though, not tested
578  // The other getByLabel function is used for ProcessBlocks by TestProcessor
580 
581  ProductData const* result = findProductByLabel(kindOfType, typeID, inputTag, consumer, sra, mcc);
582  if (result == nullptr) {
583  return BasicHandle(makeHandleExceptionFactory([=]() -> std::shared_ptr<cms::Exception> {
584  return makeNotFoundException(
585  "getByLabel",
586  kindOfType,
587  typeID,
588  inputTag.label(),
589  inputTag.instance(),
591  }));
592  }
593  return BasicHandle(result->wrapper(), &(result->provenance()));
594  }
595 
597  TypeID const& typeID,
598  std::string const& label,
599  std::string const& instance,
600  std::string const& process,
601  EDConsumerBase const* consumer,
603  ModuleCallingContext const* mcc) const {
604  ProductData const* result = findProductByLabel(kindOfType, typeID, label, instance, process, consumer, sra, mcc);
605  if (result == nullptr) {
606  return BasicHandle(makeHandleExceptionFactory([=]() -> std::shared_ptr<cms::Exception> {
607  return makeNotFoundException("getByLabel", kindOfType, typeID, label, instance, process);
608  }));
609  }
610  return BasicHandle(result->wrapper(), &(result->provenance()));
611  }
612 
614  TypeID const&,
616  bool skipCurrentProcess,
617  bool& ambiguous,
619  ModuleCallingContext const* mcc) const {
621  auto& productResolver = productResolvers_[index];
622  assert(nullptr != productResolver.get());
623  auto resolution = productResolver->resolveProduct(*this, skipCurrentProcess, sra, mcc);
624  if (resolution.isAmbiguous()) {
625  ambiguous = true;
626  //The caller is looking explicitly for this case
627  // and uses the extra data at the caller to setup the exception
628  return BasicHandle::makeInvalid();
629  }
630  auto productData = resolution.data();
631  if (productData == nullptr) {
632  //The caller is looking explicitly for this case
633  // and uses the extra data at the caller to setup the exception
634  return BasicHandle::makeInvalid();
635  }
636  return BasicHandle(productData->wrapper(), &(productData->provenance()));
637  }
638 
641  bool skipCurrentProcess,
642  ServiceToken const& token,
643  ModuleCallingContext const* mcc) const {
644  auto const& productResolver = productResolvers_.at(index);
645  assert(nullptr != productResolver.get());
646  productResolver->prefetchAsync(task, *this, skipCurrentProcess, token, nullptr, mcc);
647  }
648 
649  void Principal::getManyByType(TypeID const& typeID,
651  EDConsumerBase const* consumer,
653  ModuleCallingContext const* mcc) const {
654  // Not implemented for ProcessBlocks
656 
657  assert(results.empty());
658 
659  if (UNLIKELY(consumer and (not consumer->registeredToConsumeMany(typeID, branchType())))) {
660  failedToRegisterConsumesMany(typeID);
661  }
662 
663  // This finds the indexes to all the ProductResolver's matching the type
665 
666  if (matches.numberOfMatches() == 0) {
667  return;
668  }
669 
670  results.reserve(matches.numberOfMatches());
671 
672  // Loop over the ProductResolvers. Add the products that are actually
673  // present into the results. This will also trigger delayed reading,
674  // on demand production, and check for deleted products as appropriate.
675 
676  // Over the years the code that uses getManyByType has grown to depend
677  // on the ordering of the results. The order originally was just an
678  // accident of how previous versions of the code were written, but
679  // here we have to go through some extra effort to preserve that ordering.
680 
681  // We build a list of holders that match a particular label and instance.
682  // When that list is complete we call findProducts, which loops over
683  // that list in reverse order of the ProcessHistory (starts with the
684  // most recent). Then we clear the list and repeat this until all the
685  // matching label and instance subsets have been dealt with.
686 
687  // Note that the function isFullyResolved returns true for the ProductResolvers
688  // that are associated with an empty process name. Those are the ones that
689  // know how to search for the most recent process name matching
690  // a label and instance. We do not need these for getManyByType and
691  // skip them. In addition to skipping them, we make use of the fact
692  // that they mark the beginning of each subset of holders with the same
693  // label and instance. They tell us when to call findProducts.
694 
695  std::vector<ProductResolverBase const*> holders;
696 
697  for (unsigned int i = 0; i < matches.numberOfMatches(); ++i) {
699 
700  if (!matches.isFullyResolved(i)) {
701  if (!holders.empty()) {
702  // Process the ones with a particular module label and instance
703  findProducts(holders, typeID, results, sra, mcc);
704  holders.clear();
705  }
706  } else {
707  ProductResolverBase const* productResolver = productResolvers_.at(index).get();
708  assert(productResolver);
709  holders.push_back(productResolver);
710  }
711  }
712  // Do not miss the last subset of products
713  if (!holders.empty()) {
714  findProducts(holders, typeID, results, sra, mcc);
715  }
716  return;
717  }
718 
719  void Principal::findProducts(std::vector<ProductResolverBase const*> const& holders,
720  TypeID const&,
723  ModuleCallingContext const* mcc) const {
724  for (auto iter = processHistoryPtr_->rbegin(), iEnd = processHistoryPtr_->rend(); iter != iEnd; ++iter) {
725  std::string const& process = iter->processName();
726  for (auto productResolver : holders) {
727  BranchDescription const& bd = productResolver->branchDescription();
728  if (process == bd.processName()) {
729  // Ignore aliases to avoid matching the same product multiple times.
730  if (bd.isAnyAlias()) {
731  continue;
732  }
733 
734  ProductData const* productData = productResolver->resolveProduct(*this, false, sra, mcc).data();
735  if (productData) {
736  // Skip product if not available.
737  results.emplace_back(productData->wrapper(), &(productData->provenance()));
738  }
739  }
740  }
741  }
742  }
743 
745  TypeID const& typeID,
746  InputTag const& inputTag,
747  EDConsumerBase const* consumer,
749  ModuleCallingContext const* mcc) const {
750  bool skipCurrentProcess = inputTag.willSkipCurrentProcess();
751 
753 
755  char const* processName = inputTag.process().c_str();
756  if (skipCurrentProcess) {
757  processName = "\0";
758  } else if (inputTag.process() == InputTag::kCurrentProcess) {
760  }
761 
762  index =
763  productLookup().index(kindOfType, typeID, inputTag.label().c_str(), inputTag.instance().c_str(), processName);
764 
766  throwAmbiguousException("findProductByLabel",
767  typeID,
768  inputTag.label(),
769  inputTag.instance(),
771  } else if (index == ProductResolverIndexInvalid) {
772  return nullptr;
773  }
774  inputTag.tryToCacheIndex(index, typeID, branchType(), &productRegistry());
775  }
776  if (UNLIKELY(consumer and (not consumer->registeredToConsume(index, skipCurrentProcess, branchType())))) {
777  failedToRegisterConsumes(kindOfType,
778  typeID,
779  inputTag.label(),
780  inputTag.instance(),
782  }
783 
784  auto const& productResolver = productResolvers_[index];
785 
786  auto resolution = productResolver->resolveProduct(*this, skipCurrentProcess, sra, mcc);
787  if (resolution.isAmbiguous()) {
788  throwAmbiguousException("findProductByLabel",
789  typeID,
790  inputTag.label(),
791  inputTag.instance(),
793  }
794  return resolution.data();
795  }
796 
798  TypeID const& typeID,
799  std::string const& label,
800  std::string const& instance,
801  std::string const& process,
802  EDConsumerBase const* consumer,
804  ModuleCallingContext const* mcc) const {
806  productLookup().index(kindOfType, typeID, label.c_str(), instance.c_str(), process.c_str());
807 
809  throwAmbiguousException("findProductByLabel", typeID, label, instance, process);
810  } else if (index == ProductResolverIndexInvalid) {
811  return nullptr;
812  }
813 
814  if (UNLIKELY(consumer and (not consumer->registeredToConsume(index, false, branchType())))) {
815  failedToRegisterConsumes(kindOfType, typeID, label, instance, process);
816  }
817 
818  auto const& productResolver = productResolvers_[index];
819 
820  auto resolution = productResolver->resolveProduct(*this, false, sra, mcc);
821  if (resolution.isAmbiguous()) {
822  throwAmbiguousException("findProductByLabel", typeID, label, instance, process);
823  }
824  return resolution.data();
825  }
826 
828  InputTag const& tag,
829  ModuleCallingContext const* mcc) const {
830  // Not implemented for ProcessBlocks
832 
833  ProductData const* productData = findProductByLabel(PRODUCT_TYPE, typeID, tag, nullptr, nullptr, mcc);
834  return productData;
835  }
836 
837  Provenance const& Principal::getProvenance(BranchID const& bid) const {
839  if (phb == nullptr) {
841  }
842 
843  if (phb->unscheduledWasNotRun()) {
845  << "Requesting provenance from unrun EDProducer. The requested branch ID was: " << bid;
846  }
847  return *phb->provenance();
848  }
849 
852  if (phb == nullptr) {
853  throwProductNotFoundException("getStableProvenance", errors::ProductNotFound, bid);
854  }
855  //NOTE: in all implementations, this never returns a nullptr
856  return *phb->stableProvenance();
857  }
858 
859  // This one is mostly for test printout purposes
860  // No attempt to trigger on demand execution
861  // Skips provenance when the EDProduct is not there
862  void Principal::getAllProvenance(std::vector<Provenance const*>& provenances) const {
863  provenances.clear();
864  for (auto const& productResolver : *this) {
865  if (productResolver->singleProduct() && productResolver->provenanceAvailable() &&
866  !productResolver->branchDescription().isAnyAlias()) {
867  // We do not attempt to get the event/lumi/run status from the provenance,
868  // because the per event provenance may have been dropped.
869  if (productResolver->provenance()->branchDescription().present()) {
870  provenances.push_back(productResolver->provenance());
871  }
872  }
873  }
874  }
875 
876  // This one is also mostly for test printout purposes
877  // No attempt to trigger on demand execution
878  // Skips provenance for dropped branches.
879  void Principal::getAllStableProvenance(std::vector<StableProvenance const*>& provenances) const {
880  provenances.clear();
881  for (auto const& productResolver : *this) {
882  if (productResolver->singleProduct() && !productResolver->branchDescription().isAnyAlias()) {
883  if (productResolver->stableProvenance()->branchDescription().present()) {
884  provenances.push_back(productResolver->stableProvenance());
885  }
886  }
887  }
888  }
889 
890  void Principal::recombine(Principal& other, std::vector<BranchID> const& bids) {
891  for (auto& prod : bids) {
892  ProductResolverIndex index = preg_->indexFrom(prod);
894  ProductResolverIndex indexO = other.preg_->indexFrom(prod);
896  get_underlying_safe(productResolvers_[index]).swap(get_underlying_safe(other.productResolvers_[indexO]));
897  }
898  reader_->mergeReaders(other.reader());
899  }
900 
901  WrapperBase const* Principal::getIt(ProductID const&) const {
902  assert(false);
903  return nullptr;
904  }
905 
906  std::optional<std::tuple<WrapperBase const*, unsigned int>> Principal::getThinnedProduct(ProductID const&,
907  unsigned int) const {
908  assert(false);
909  return std::nullopt;
910  }
911 
913  std::vector<WrapperBase const*>&,
914  std::vector<unsigned int>&) const {
915  assert(false);
916  }
917 
919  assert(false);
920  return std::monostate{};
921  }
922 
923  void Principal::put_(std::unique_ptr<WrapperBase> prod, ProductResolverBase const* phb) const {
924  dynamic_cast<ProductPutterBase const*>(phb)->putProduct(std::move(prod));
925  }
926 
927  void Principal::put_(BranchDescription const& bd, std::unique_ptr<WrapperBase> edp) const {
928  if (edp.get() == nullptr) {
929  throw edm::Exception(edm::errors::InsertFailure, "Null Pointer")
930  << "put: Cannot put because unique_ptr to product is null."
931  << "\n";
932  }
933  auto phb = getExistingProduct(bd.branchID());
934  assert(phb);
935  // ProductResolver assumes ownership
936  put_(std::move(edp), phb);
937  }
938 
940  if (preg_->getNextIndexValue(branchType_) != productResolvers_.size()) {
941  bool changed = false;
942  productResolvers_.resize(preg_->getNextIndexValue(branchType_));
943  for (auto const& prod : preg_->productList()) {
944  BranchDescription const& bd = prod.second;
945  if (bd.branchType() == branchType_) {
946  ProductResolverIndex index = preg_->indexFrom(bd.branchID());
948  if (!productResolvers_[index]) {
949  // no product holder. Must add one. The new entry must be an input product holder.
950  assert(!bd.produced());
951  auto cbd = std::make_shared<BranchDescription const>(bd);
952  if (bd.onDemand()) {
954  } else {
956  }
957  changed = true;
958  }
959  }
960  }
961  if (changed) {
962  changedIndexes_();
963  }
964  }
965  assert(preg_->getNextIndexValue(branchType_) == productResolvers_.size());
966  }
967 
969  if (not reader()) {
970  return;
971  }
972 
973  for (auto& prod : *this) {
974  prod->retrieveAndMerge(*this, mergeableRunProductMetadata);
975  }
976  }
977 } // namespace edm
std::optional< std::tuple< WrapperBase const *, unsigned int > > getThinnedProduct(ProductID const &, unsigned int) const override
Definition: Principal.cc:906
BranchType branchType_
Definition: Principal.h:293
void findProducts(std::vector< ProductResolverBase const *> const &holders, TypeID const &typeID, BasicHandleVec &results, SharedResourcesAcquirer *sra, ModuleCallingContext const *mcc) const
Definition: Principal.cc:719
size
Write out results.
void fillPrincipal(DelayedReader *reader)
Definition: Principal.cc:402
static ProcessHistory const s_emptyProcessHistory
Definition: Principal.cc:34
void clearPrincipal()
Definition: Principal.cc:382
DelayedReader * reader_
Definition: Principal.h:291
void getAllProvenance(std::vector< Provenance const *> &provenances) const
Definition: Principal.cc:862
ProcessHistoryID processHistoryIDBeforeConfig_
Definition: Principal.h:274
void setupUnscheduled(UnscheduledConfigurator const &)
Definition: Principal.cc:398
unsigned int ProductResolverIndex
BasicHandle getByToken(KindOfType kindOfType, TypeID const &typeID, ProductResolverIndex index, bool skipCurrentProcess, bool &ambiguous, SharedResourcesAcquirer *sra, ModuleCallingContext const *mcc) const
Definition: Principal.cc:613
static std::string const source("source")
ProductResolverCollection productResolvers_
Definition: Principal.h:279
std::variant< unsigned int, detail::GetThinnedKeyFromExceptionFactory, std::monostate > OptionalThinnedKey
std::shared_ptr< ProcessHistory const > processHistoryPtr_
Definition: Principal.h:271
ProductList const & productList() const
BranchID const & branchID() const
static PFTauRenderPlugin instance
ProductRegistry const & productRegistry() const
Definition: Principal.h:146
Provenance const & provenance() const
Definition: ProductData.h:33
std::shared_ptr< ProductResolverBase > SharedProductPtr
Definition: Principal.h:66
void addProduct_(std::unique_ptr< ProductResolverBase > phb)
Definition: Principal.cc:529
static std::atomic< Principal::CacheIdentifier_t > s_nextIdentifier
Definition: Principal.cc:117
StableProvenance const & getStableProvenance(BranchID const &bid) const
Definition: Principal.cc:850
std::map< BranchKey, BranchDescription > ProductList
static Principal::CacheIdentifier_t nextIdentifier()
Definition: Principal.cc:118
ProcessHistoryID processHistoryID_
Definition: Principal.h:273
void mergeReaders(DelayedReader *other)
Definition: DelayedReader.h:36
ProductResolverBase * getExistingProduct(BranchID const &branchID)
Definition: Principal.cc:501
virtual void setupUnscheduled(UnscheduledConfigurator const &)
void getThinnedProducts(ProductID const &, std::vector< WrapperBase const *> &, std::vector< unsigned int > &) const override
Definition: Principal.cc:912
void applyToResolvers(F iFunc)
Definition: Principal.h:217
~Principal() override
Definition: Principal.cc:298
void prefetchAsync(WaitingTaskHolder waitTask, ProductResolverIndex index, bool skipCurrentProcess, ServiceToken const &token, ModuleCallingContext const *mcc) const
Definition: Principal.cc:639
size_t size() const
Definition: Principal.cc:303
reader
Definition: DQM.py:105
constexpr std::shared_ptr< T > & get_underlying_safe(propagate_const< std::shared_ptr< T >> &iP)
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
assert(be >=bs)
edm::propagate_const< HistoryAppender * > historyAppender_
Definition: Principal.h:298
Principal(std::shared_ptr< ProductRegistry const > reg, std::shared_ptr< ProductResolverIndexHelper const > productLookup, ProcessConfiguration const &pc, BranchType bt, HistoryAppender *historyAppender, bool isForPrimaryProcess=true)
Definition: Principal.cc:122
WrapperBase const * wrapper() const
Definition: ProductData.h:35
void addUnscheduledProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:349
Matches relatedIndexes(KindOfType kindOfType, TypeID const &typeID, char const *moduleLabel, char const *instance) const
void getManyByType(TypeID const &typeID, BasicHandleVec &results, EDConsumerBase const *consumes, SharedResourcesAcquirer *sra, ModuleCallingContext const *mcc) const
Definition: Principal.cc:649
BranchType
Definition: BranchType.h:11
ProductData const * findProductByLabel(KindOfType kindOfType, TypeID const &typeID, InputTag const &inputTag, EDConsumerBase const *consumer, SharedResourcesAcquirer *sra, ModuleCallingContext const *mcc) const
Definition: Principal.cc:744
void addAliasedProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:353
static void throwAmbiguousException(const char *where, TypeID const &productType, std::string const &label, std::string const &instance, std::string const &process)
Definition: Principal.cc:77
std::vector< unsigned int > lookupProcessOrder_
Definition: Principal.h:286
virtual unsigned int processBlockIndex(std::string const &processName) const
Definition: Principal.cc:567
deep_tau::DeepTauBase::BasicDiscriminator bd
Definition: DeepTauId.cc:808
char const * label
WrapperBase const * getIt(ProductID const &) const override
Definition: Principal.cc:901
std::shared_ptr< ProductResolverIndexHelper const > productLookup_
Definition: Principal.h:284
std::string const & branchName() const
void addProductOrThrow(std::unique_ptr< ProductResolverBase > phb)
Definition: Principal.cc:542
std::shared_ptr< ProductRegistry const > preg_
Definition: Principal.h:283
CacheIdentifier_t cacheIdentifier_
Definition: Principal.h:300
ProductResolverIndex index(KindOfType kindOfType, TypeID const &typeID, char const *moduleLabel, char const *instance, char const *process=nullptr) const
std::shared_ptr< HandleExceptionFactory > makeHandleExceptionFactory(T &&iFunctor)
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
BasicHandle getByLabel(KindOfType kindOfType, TypeID const &typeID, InputTag const &inputTag, EDConsumerBase const *consumes, SharedResourcesAcquirer *sra, ModuleCallingContext const *mcc) const
Definition: Principal.cc:571
void getAllStableProvenance(std::vector< StableProvenance const *> &provenances) const
Definition: Principal.cc:879
ProcessHistoryID orderProcessHistoryID_
Definition: Principal.h:287
virtual void changedIndexes_()
Definition: Principal.h:225
static const std::string kCurrentProcess
Definition: InputTag.h:54
void addSourceProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:336
void addPutOnReadInputProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:345
void deleteProduct(BranchID const &id) const
Definition: Principal.cc:392
void addDelayedReaderInputProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:341
string ranges
Definition: diffTwoXMLs.py:79
__shared__ Hist hist
void put_(BranchDescription const &bd, std::unique_ptr< WrapperBase > edp) const
Definition: Principal.cc:927
void addParentProcessProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:377
ProductData const * findProductByTag(TypeID const &typeID, InputTag const &tag, ModuleCallingContext const *mcc) const
Definition: Principal.cc:827
void addScheduledProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:331
static BasicHandle makeInvalid()
Definition: BasicHandle.h:93
ProcessHistory const & processHistory() const
Definition: Principal.h:140
void addSwitchProducerProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:361
BranchDescription const & branchDescription() const
static std::shared_ptr< cms::Exception > makeNotFoundException(char const *where, KindOfType kindOfType, TypeID const &productType, std::string const &label, std::string const &instance, std::string const &process)
Definition: Principal.cc:53
ProductResolverBase const * ConstProductResolverPtr
Definition: Principal.h:62
std::string const & processName() const
HLT enums.
void readAllFromSourceAndMergeImmediately(MergeableRunProductMetadata const *mergeableRunProductMetadata=nullptr)
Definition: Principal.cc:968
unsigned long CacheIdentifier_t
Definition: Principal.h:184
bool adjustToNewProductRegistry(ProductRegistry const &reg)
Definition: Principal.cc:315
Provenance const & getProvenance(BranchID const &bid) const
Definition: Principal.cc:837
void adjustIndexesAfterProductRegistryAddition()
Definition: Principal.cc:939
static void throwProductNotFoundException(char const *where, errors::ErrorCodes error, BranchID const &bid)
Definition: Principal.cc:48
ProductResolverIndexHelper const & productLookup() const
Definition: Principal.h:148
#define UNLIKELY(x)
Definition: Likely.h:21
static std::string appendCurrentProcessIfAlias(std::string const &processFromInputTag, std::string const &currentProcess)
Definition: Principal.cc:36
OptionalThinnedKey getThinnedKeyFrom(ProductID const &parent, unsigned int key, ProductID const &thinned) const override
Definition: Principal.cc:918
void recombine(Principal &other, std::vector< BranchID > const &bids)
Definition: Principal.cc:890
ConstProductResolverPtr getProductResolverByIndex(ProductResolverIndex const &oid) const
Definition: Principal.cc:562
void resetBranchDescription(std::shared_ptr< BranchDescription const > bd)
ProcessConfiguration const * processConfiguration_
Definition: Principal.h:276
void addSwitchAliasProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:369
def move(src, dest)
Definition: eostools.py:511
std::vector< BasicHandle > BasicHandleVec
Definition: Principal.h:63
DelayedReader * reader() const
Definition: Principal.h:187
BranchType const & branchType() const
Definition: Principal.h:181
ConstProductResolverPtr getProductResolver(BranchID const &oid) const
Definition: Principal.cc:554