CMS 3D CMS Logo

Principal.cc
Go to the documentation of this file.
1 
3 #ifdef __clang__
4 #pragma GCC diagnostic ignored "-Wc++20-extensions"
5 #endif
6 
8 
18 #include "ProductResolvers.h"
24 
26 
27 #include <algorithm>
28 #include <cstring>
29 #include <limits>
30 #include <sstream>
31 #include <stdexcept>
32 #include <typeinfo>
33 #include <atomic>
34 
35 namespace edm {
36 
38 
39  static std::string appendCurrentProcessIfAlias(std::string const& processFromInputTag,
40  std::string const& currentProcess) {
41  if (processFromInputTag == InputTag::kCurrentProcess) {
42  std::string returnValue = processFromInputTag;
43  returnValue += " (";
44  returnValue += currentProcess;
45  returnValue += ")";
46  return returnValue;
47  }
48  return processFromInputTag;
49  }
50 
51  static void throwProductNotFoundException(char const* where, errors::ErrorCodes error, BranchID const& bid) {
52  throw Exception(error, "InvalidID") << "Principal::" << where << ": no product with given branch id: " << bid
53  << "\n";
54  }
55 
56  static std::shared_ptr<cms::Exception> makeNotFoundException(char const* where,
57  KindOfType kindOfType,
58  TypeID const& productType,
59  std::string const& label,
60  std::string const& instance,
61  std::string const& process) {
62  std::shared_ptr<cms::Exception> exception = std::make_shared<Exception>(errors::ProductNotFound);
63  if (kindOfType == PRODUCT_TYPE) {
64  *exception << "Principal::" << where
65  << ": Found zero products matching all criteria\nLooking for type: " << productType << "\n"
66  << "Looking for module label: " << label << "\n"
67  << "Looking for productInstanceName: " << instance << "\n"
68  << (process.empty() ? "" : "Looking for process: ") << process << "\n";
69  } else {
70  *exception << "Principal::" << where
71  << ": Found zero products matching all criteria\nLooking for a container with elements of type: "
72  << productType << "\n"
73  << "Looking for module label: " << label << "\n"
74  << "Looking for productInstanceName: " << instance << "\n"
75  << (process.empty() ? "" : "Looking for process: ") << process << "\n";
76  }
77  return exception;
78  }
79 
80  static void throwAmbiguousException(const char* where,
81  TypeID const& productType,
82  std::string const& label,
83  std::string const& instance,
84  std::string const& process) {
85  cms::Exception exception("AmbiguousProduct");
86  exception << "Principal::" << where
87  << ": More than 1 product matches all criteria\nLooking for type: " << productType << "\n"
88  << "Looking for module label: " << label << "\n"
89  << "Looking for productInstanceName: " << instance << "\n"
90  << (process.empty() ? "" : "Looking for process: ") << process << "\n"
91  << "This can only occur with get function calls using a Handle<View> argument.\n"
92  << "Try a get not using a View or change the instance name of one of the products";
93  throw exception;
94  }
95 
96  namespace {
97  void failedToRegisterConsumes(KindOfType kindOfType,
98  TypeID const& productType,
99  std::string const& moduleLabel,
100  std::string const& productInstanceName,
101  std::string const& processName) {
102  cms::Exception exception("GetByLabelWithoutRegistration");
103  exception << "::getByLabel without corresponding call to consumes or mayConsumes for this module.\n"
104  << (kindOfType == PRODUCT_TYPE ? " type: " : " type: edm::View<") << productType
105  << (kindOfType == PRODUCT_TYPE ? "\n module label: " : ">\n module label: ") << moduleLabel
106  << "\n product instance name: '" << productInstanceName << "'\n process name: '" << processName
107  << "'\n";
108  throw exception;
109  }
110  } // namespace
111 
112  //0 means unset
113  static std::atomic<Principal::CacheIdentifier_t> s_nextIdentifier{1};
115  return s_nextIdentifier.fetch_add(1, std::memory_order_acq_rel);
116  }
117 
118  Principal::Principal(std::shared_ptr<ProductRegistry const> reg,
119  std::shared_ptr<ProductResolverIndexHelper const> productLookup,
120  ProcessConfiguration const& pc,
121  BranchType bt,
122  HistoryAppender* historyAppender,
123  bool isForPrimaryProcess)
124  : EDProductGetter(),
125  processHistoryPtr_(),
126  processHistoryID_(),
127  processHistoryIDBeforeConfig_(),
128  processConfiguration_(&pc),
129  productResolvers_(),
130  preg_(reg),
131  productLookup_(productLookup),
132  lookupProcessOrder_(productLookup->lookupProcessNames().size(), 0),
133  reader_(),
134  branchType_(bt),
135  historyAppender_(historyAppender),
136  cacheIdentifier_(nextIdentifier()) {
137  productResolvers_.resize(reg->getNextIndexValue(bt));
138  //Now that these have been set, we can create the list of Branches we need.
139  std::string const source("source");
140  ProductRegistry::ProductList const& prodsList = reg->productList();
141  // The constructor of an alias product holder takes as an argument the product holder for which it is an alias.
142  // So, the non-alias product holders must be created first.
143  // Therefore, on this first pass, skip current EDAliases.
144  bool hasAliases = false;
145  bool hasSwitchAliases = false;
146  for (auto const& prod : prodsList) {
147  BranchDescription const& bd = prod.second;
148  if (bd.branchType() == branchType_) {
149  if (isForPrimaryProcess or bd.processName() == pc.processName()) {
150  if (bd.isAlias()) {
151  hasAliases = true;
152  } else if (bd.isSwitchAlias()) {
153  hasSwitchAliases = true;
154  } else {
155  auto cbd = std::make_shared<BranchDescription const>(bd);
156  if (bd.produced()) {
157  if (bd.moduleLabel() == source) {
158  addSourceProduct(cbd);
159  } else if (bd.onDemand()) {
161  if (bd.isTransform()) {
162  addTransformProduct(cbd);
163  } else {
165  }
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::addTransformProduct(std::shared_ptr<BranchDescription const> bd) {
354  addProductOrThrow(std::make_unique<TransformingProductResolver>(std::move(bd)));
355  }
356 
357  void Principal::addAliasedProduct(std::shared_ptr<BranchDescription const> bd) {
358  ProductResolverIndex index = preg_->indexFrom(bd->originalBranchID());
360 
361  addProductOrThrow(std::make_unique<AliasProductResolver>(
362  std::move(bd), dynamic_cast<DataManagingOrAliasProductResolver&>(*productResolvers_[index])));
363  }
364 
365  void Principal::addSwitchProducerProduct(std::shared_ptr<BranchDescription const> bd) {
366  ProductResolverIndex index = preg_->indexFrom(bd->switchAliasForBranchID());
368 
369  addProductOrThrow(std::make_unique<SwitchProducerProductResolver>(
370  std::move(bd), dynamic_cast<DataManagingOrAliasProductResolver&>(*productResolvers_[index])));
371  }
372 
373  void Principal::addSwitchAliasProduct(std::shared_ptr<BranchDescription const> bd) {
374  ProductResolverIndex index = preg_->indexFrom(bd->switchAliasForBranchID());
376 
377  addProductOrThrow(std::make_unique<SwitchAliasProductResolver>(
378  std::move(bd), dynamic_cast<DataManagingOrAliasProductResolver&>(*productResolvers_[index])));
379  }
380 
381  void Principal::addParentProcessProduct(std::shared_ptr<BranchDescription const> bd) {
382  addProductOrThrow(std::make_unique<ParentProcessProductResolver>(std::move(bd)));
383  }
384 
385  // "Zero" the principal so it can be reused for another Event.
387  //We do not clear the product history information
388  // because it rarely changes and recalculating takes
389  // time.
390  reader_ = nullptr;
391  for (auto& prod : *this) {
392  prod->resetProductData();
393  }
394  }
395 
396  void Principal::deleteProduct(BranchID const& id) const {
397  auto phb = getExistingProduct(id);
398  assert(nullptr != phb);
399  phb->unsafe_deleteProduct();
400  }
401 
403  applyToResolvers([&iConfigure](ProductResolverBase* iResolver) { iResolver->setupUnscheduled(iConfigure); });
404  }
405 
407  //increment identifier here since clearPrincipal isn't called for Run/Lumi
409  if (reader) {
410  reader_ = reader;
411  }
412  }
413 
414  // Set the principal for the Event, Lumi, or Run.
416  ProcessHistory const* processHistory,
419 
420  if (historyAppender_ && productRegistry().anyProductProduced()) {
425  }
426  } else {
427  std::shared_ptr<ProcessHistory const> inputProcessHistory;
429  if (hist.isValid()) {
430  //does not own the pointer
431  auto noDel = [](void const*) {};
432  inputProcessHistory = std::shared_ptr<ProcessHistory const>(processHistory, noDel);
433  if (inputProcessHistory.get() == nullptr) {
434  throw Exception(errors::LogicError) << "Principal::fillPrincipal\n"
435  << "Input ProcessHistory not found in registry\n"
436  << "Contact a Framework developer\n";
437  }
438  } else {
439  //Since this is static we don't want it deleted
440  inputProcessHistory = std::shared_ptr<ProcessHistory const>(&s_emptyProcessHistory, [](void const*) {});
441  //no need to do any ordering since it is empty
443  }
445  processHistoryPtr_ = inputProcessHistory;
447  }
448  }
449 
451  std::vector<std::string> const& lookupProcessNames = productLookup_->lookupProcessNames();
452  lookupProcessOrder_.assign(lookupProcessNames.size(), 0);
453  unsigned int k = 0;
454 
455  // We loop over processes in reverse order of the ProcessHistory.
456  // If any entries in the product lookup tables are associated with
457  // the process we add it to the vector of processes in the order
458  // the lookup should be performed. There is one exception though,
459  // We start with the current process even if it is not in the ProcessHistory.
460  // The current process might be needed but not be in the process
461  // history if all the products produced in the current process are
462  // transient.
463  {
464  auto nameIterCurrentProcess =
465  std::find(lookupProcessNames.begin(), lookupProcessNames.end(), processConfiguration_->processName());
466  if (nameIterCurrentProcess != lookupProcessNames.end()) {
467  lookupProcessOrder_.at(k) = nameIterCurrentProcess - lookupProcessNames.begin();
468  ++k;
469  }
470  }
471 
472  // We just looked for the current process so skip it if
473  // it is in the ProcessHistory.
474  auto iter = processHistoryPtr_->rbegin();
475  if (iter->processName() == processConfiguration_->processName()) {
476  ++iter;
477  }
478 
479  for (auto iEnd = processHistoryPtr_->rend(); iter != iEnd; ++iter) {
480  auto nameIter = std::find(lookupProcessNames.begin(), lookupProcessNames.end(), iter->processName());
481  if (nameIter == lookupProcessNames.end()) {
482  continue;
483  }
484  lookupProcessOrder_.at(k) = nameIter - lookupProcessNames.begin();
485  ++k;
486  }
488  }
489  }
490 
491  // Set the principal for the ProcessBlock
492  void Principal::fillPrincipal(std::string const& processNameOfBlock, DelayedReader* reader) {
494 
495  std::vector<std::string> const& lookupProcessNames = productLookup_->lookupProcessNames();
496  lookupProcessOrder_.assign(lookupProcessNames.size(), 0);
497  if (!lookupProcessOrder_.empty()) {
498  auto iter = std::find(lookupProcessNames.begin(), lookupProcessNames.end(), processNameOfBlock);
499  if (iter != lookupProcessNames.end()) {
500  lookupProcessOrder_[0] = iter - lookupProcessNames.begin();
501  }
502  }
503  }
504 
506  return const_cast<ProductResolverBase*>(const_cast<const Principal*>(this)->getExistingProduct(branchID));
507  }
508 
510  ProductResolverIndex index = preg_->indexFrom(branchID);
512  return productResolvers_.at(index).get();
513  }
514 
516  auto phb = getExistingProduct(productResolver.branchDescription().branchID());
517  if (nullptr != phb && BranchKey(productResolver.branchDescription()) != BranchKey(phb->branchDescription())) {
518  BranchDescription const& newProduct = phb->branchDescription();
519  BranchDescription const& existing = productResolver.branchDescription();
520  if (newProduct.branchName() != existing.branchName() && newProduct.branchID() == existing.branchID()) {
521  throw cms::Exception("HashCollision")
522  << "Principal::getExistingProduct\n"
523  << " Branch " << newProduct.branchName() << " has same branch ID as branch " << existing.branchName()
524  << "\n"
525  << "Workaround: change process name or product instance name of " << newProduct.branchName() << "\n";
526  } else {
527  assert(nullptr == phb || BranchKey(productResolver.branchDescription()) == BranchKey(phb->branchDescription()));
528  }
529  }
530  return phb;
531  }
532 
533  void Principal::addProduct_(std::unique_ptr<ProductResolverBase> productResolver) {
534  BranchDescription const& bd = productResolver->branchDescription();
535  assert(!bd.className().empty());
536  assert(!bd.friendlyClassName().empty());
537  assert(!bd.moduleLabel().empty());
538  assert(!bd.processName().empty());
539  SharedProductPtr phb(productResolver.release());
540 
541  ProductResolverIndex index = preg_->indexFrom(bd.branchID());
543  productResolvers_[index] = phb;
544  }
545 
546  void Principal::addProductOrThrow(std::unique_ptr<ProductResolverBase> productResolver) {
547  ProductResolverBase const* phb = getExistingProduct(*productResolver);
548  if (phb != nullptr) {
549  BranchDescription const& bd = productResolver->branchDescription();
550  throw Exception(errors::InsertFailure, "AlreadyPresent")
551  << "addProductOrThrow: Problem found while adding product, "
552  << "product already exists for (" << bd.friendlyClassName() << "," << bd.moduleLabel() << ","
553  << bd.productInstanceName() << "," << bd.processName() << ")\n";
554  }
555  addProduct_(std::move(productResolver));
556  }
557 
559  ProductResolverIndex index = preg_->indexFrom(bid);
561  return ConstProductResolverPtr();
562  }
564  }
565 
567  ProductResolverIndex const& index) const noexcept {
568  ConstProductResolverPtr const phb = productResolvers_[index].get();
569  return phb;
570  }
571 
572  unsigned int Principal::processBlockIndex(std::string const&) const {
573  throw Exception(errors::LogicError) << "Principal::processBlockIndex not implemented for this type of Principal";
574  }
575 
577  TypeID const& typeID,
578  InputTag const& inputTag,
579  EDConsumerBase const* consumer,
581  ModuleCallingContext const* mcc) const {
582  // Not implemented for ProcessBlocks, it might work though, not tested
583  // The other getByLabel function is used for ProcessBlocks by TestProcessor
585 
586  ProductData const* result = findProductByLabel(kindOfType, typeID, inputTag, consumer, sra, mcc);
587  if (result == nullptr) {
588  return BasicHandle(makeHandleExceptionFactory([=, this]() -> std::shared_ptr<cms::Exception> {
589  return makeNotFoundException(
590  "getByLabel",
591  kindOfType,
592  typeID,
593  inputTag.label(),
594  inputTag.instance(),
596  }));
597  }
598  return BasicHandle(result->wrapper(), &(result->provenance()));
599  }
600 
602  TypeID const& typeID,
603  std::string const& label,
604  std::string const& instance,
605  std::string const& process,
606  EDConsumerBase const* consumer,
608  ModuleCallingContext const* mcc) const {
609  ProductData const* result = findProductByLabel(kindOfType, typeID, label, instance, process, consumer, sra, mcc);
610  if (result == nullptr) {
611  return BasicHandle(makeHandleExceptionFactory([=]() -> std::shared_ptr<cms::Exception> {
612  return makeNotFoundException("getByLabel", kindOfType, typeID, label, instance, process);
613  }));
614  }
615  return BasicHandle(result->wrapper(), &(result->provenance()));
616  }
617 
619  TypeID const&,
621  bool skipCurrentProcess,
622  bool& ambiguous,
624  ModuleCallingContext const* mcc) const {
626  auto& productResolver = productResolvers_[index];
627  assert(nullptr != productResolver.get());
628  auto resolution = productResolver->resolveProduct(*this, skipCurrentProcess, sra, mcc);
629  if (resolution.isAmbiguous()) {
630  ambiguous = true;
631  //The caller is looking explicitly for this case
632  // and uses the extra data at the caller to setup the exception
633  return BasicHandle::makeInvalid();
634  }
635  auto productData = resolution.data();
636  if (productData == nullptr) {
637  //The caller is looking explicitly for this case
638  // and uses the extra data at the caller to setup the exception
639  return BasicHandle::makeInvalid();
640  }
641  return BasicHandle(productData->wrapper(), &(productData->provenance()));
642  }
643 
646  bool skipCurrentProcess,
647  ServiceToken const& token,
648  ModuleCallingContext const* mcc) const {
649  auto const& productResolver = productResolvers_.at(index);
650  assert(nullptr != productResolver.get());
651  productResolver->prefetchAsync(task, *this, skipCurrentProcess, token, nullptr, mcc);
652  }
653 
655  TypeID const& typeID,
656  InputTag const& inputTag,
657  EDConsumerBase const* consumer,
659  ModuleCallingContext const* mcc) const {
660  bool skipCurrentProcess = inputTag.willSkipCurrentProcess();
661 
663 
665  char const* processName = inputTag.process().c_str();
666  if (skipCurrentProcess) {
667  processName = "\0";
668  } else if (inputTag.process() == InputTag::kCurrentProcess) {
670  }
671 
672  index =
673  productLookup().index(kindOfType, typeID, inputTag.label().c_str(), inputTag.instance().c_str(), processName);
674 
676  throwAmbiguousException("findProductByLabel",
677  typeID,
678  inputTag.label(),
679  inputTag.instance(),
681  } else if (index == ProductResolverIndexInvalid) {
682  // can occur because of missing consumes if nothing else in the process consumes the product
683  for (auto const& item : preg_->productList()) {
684  auto const& bd = item.second;
685  if (bd.present() and bd.unwrappedTypeID() == typeID and bd.moduleLabel() == inputTag.label() and
686  bd.productInstanceName() == inputTag.instance()) {
687  bool const inCurrentProcess = bd.processName() == processConfiguration_->processName();
688  if (inputTag.process().empty() or bd.processName() == inputTag.process() or
689  (skipCurrentProcess and not inCurrentProcess) or
690  (inputTag.process() == InputTag::kCurrentProcess and inCurrentProcess)) {
691  failedToRegisterConsumes(
692  kindOfType,
693  typeID,
694  inputTag.label(),
695  inputTag.instance(),
697  }
698  }
699  }
700  return nullptr;
701  }
702  inputTag.tryToCacheIndex(index, typeID, branchType(), &productRegistry());
703  }
704  if (UNLIKELY(consumer and (not consumer->registeredToConsume(index, skipCurrentProcess, branchType())))) {
705  failedToRegisterConsumes(kindOfType,
706  typeID,
707  inputTag.label(),
708  inputTag.instance(),
710  }
711 
712  auto const& productResolver = productResolvers_[index];
713 
714  auto resolution = productResolver->resolveProduct(*this, skipCurrentProcess, sra, mcc);
715  if (resolution.isAmbiguous()) {
716  throwAmbiguousException("findProductByLabel",
717  typeID,
718  inputTag.label(),
719  inputTag.instance(),
721  }
722  return resolution.data();
723  }
724 
726  TypeID const& typeID,
727  std::string const& label,
728  std::string const& instance,
729  std::string const& process,
730  EDConsumerBase const* consumer,
732  ModuleCallingContext const* mcc) const {
734  productLookup().index(kindOfType, typeID, label.c_str(), instance.c_str(), process.c_str());
735 
737  throwAmbiguousException("findProductByLabel", typeID, label, instance, process);
738  } else if (index == ProductResolverIndexInvalid) {
739  // can occur because of missing consumes if nothing else in the process consumes the product
740  for (auto const& item : preg_->productList()) {
741  auto const& bd = item.second;
742  if (bd.present() and bd.unwrappedTypeID() == typeID and bd.moduleLabel() == label and
743  bd.productInstanceName() == instance) {
744  if (process.empty() or bd.processName() == process) {
745  failedToRegisterConsumes(kindOfType, typeID, label, instance, process);
746  }
747  }
748  }
749  return nullptr;
750  }
751 
752  if (UNLIKELY(consumer and (not consumer->registeredToConsume(index, false, branchType())))) {
753  failedToRegisterConsumes(kindOfType, typeID, label, instance, process);
754  }
755 
756  auto const& productResolver = productResolvers_[index];
757 
758  auto resolution = productResolver->resolveProduct(*this, false, sra, mcc);
759  if (resolution.isAmbiguous()) {
760  throwAmbiguousException("findProductByLabel", typeID, label, instance, process);
761  }
762  return resolution.data();
763  }
764 
766  InputTag const& tag,
767  ModuleCallingContext const* mcc) const {
768  // Not implemented for ProcessBlocks
770 
771  ProductData const* productData = findProductByLabel(PRODUCT_TYPE, typeID, tag, nullptr, nullptr, mcc);
772  return productData;
773  }
774 
775  Provenance const& Principal::getProvenance(BranchID const& bid) const {
777  if (phb == nullptr) {
779  }
780 
781  if (phb->unscheduledWasNotRun()) {
783  << "Requesting provenance from unrun EDProducer. The requested branch ID was: " << bid;
784  }
785  return *phb->provenance();
786  }
787 
790  if (phb == nullptr) {
791  throwProductNotFoundException("getStableProvenance", errors::ProductNotFound, bid);
792  }
793  //NOTE: in all implementations, this never returns a nullptr
794  return *phb->stableProvenance();
795  }
796 
797  // This one is mostly for test printout purposes
798  // No attempt to trigger on demand execution
799  // Skips provenance when the EDProduct is not there
800  void Principal::getAllProvenance(std::vector<Provenance const*>& provenances) const {
801  provenances.clear();
802  for (auto const& productResolver : *this) {
803  if (productResolver->singleProduct() && productResolver->provenanceAvailable() &&
804  !productResolver->branchDescription().isAnyAlias()) {
805  // We do not attempt to get the event/lumi/run status from the provenance,
806  // because the per event provenance may have been dropped.
807  if (productResolver->provenance()->branchDescription().present()) {
808  provenances.push_back(productResolver->provenance());
809  }
810  }
811  }
812  }
813 
814  // This one is also mostly for test printout purposes
815  // No attempt to trigger on demand execution
816  // Skips provenance for dropped branches.
817  void Principal::getAllStableProvenance(std::vector<StableProvenance const*>& provenances) const {
818  provenances.clear();
819  for (auto const& productResolver : *this) {
820  if (productResolver->singleProduct() && !productResolver->branchDescription().isAnyAlias()) {
821  if (productResolver->stableProvenance()->branchDescription().present()) {
822  provenances.push_back(productResolver->stableProvenance());
823  }
824  }
825  }
826  }
827 
828  void Principal::recombine(Principal& other, std::vector<BranchID> const& bids) {
829  for (auto& prod : bids) {
830  ProductResolverIndex index = preg_->indexFrom(prod);
832  ProductResolverIndex indexO = other.preg_->indexFrom(prod);
834  get_underlying_safe(productResolvers_[index]).swap(get_underlying_safe(other.productResolvers_[indexO]));
835  }
836  reader_->mergeReaders(other.reader());
837  }
838 
839  WrapperBase const* Principal::getIt(ProductID const&) const {
840  assert(false);
841  return nullptr;
842  }
843 
844  std::optional<std::tuple<WrapperBase const*, unsigned int>> Principal::getThinnedProduct(ProductID const&,
845  unsigned int) const {
846  assert(false);
847  return std::nullopt;
848  }
849 
851  std::vector<WrapperBase const*>&,
852  std::vector<unsigned int>&) const {
853  assert(false);
854  }
855 
857  assert(false);
858  return std::monostate{};
859  }
860 
861  void Principal::put_(std::unique_ptr<WrapperBase> prod, ProductResolverBase const* phb) const {
862  dynamic_cast<ProductPutterBase const*>(phb)->putProduct(std::move(prod));
863  }
864 
865  void Principal::put_(BranchDescription const& bd, std::unique_ptr<WrapperBase> edp) const {
866  if (edp.get() == nullptr) {
867  throw edm::Exception(edm::errors::InsertFailure, "Null Pointer")
868  << "put: Cannot put because unique_ptr to product is null."
869  << "\n";
870  }
871  auto phb = getExistingProduct(bd.branchID());
872  assert(phb);
873  // ProductResolver assumes ownership
874  put_(std::move(edp), phb);
875  }
876 
878  if (preg_->getNextIndexValue(branchType_) != productResolvers_.size()) {
879  bool changed = false;
880  productResolvers_.resize(preg_->getNextIndexValue(branchType_));
881  for (auto const& prod : preg_->productList()) {
882  BranchDescription const& bd = prod.second;
883  if (bd.branchType() == branchType_) {
884  ProductResolverIndex index = preg_->indexFrom(bd.branchID());
886  if (!productResolvers_[index]) {
887  // no product holder. Must add one. The new entry must be an input product holder.
888  assert(!bd.produced());
889  auto cbd = std::make_shared<BranchDescription const>(bd);
890  if (bd.onDemand()) {
892  } else {
894  }
895  changed = true;
896  }
897  }
898  }
899  if (changed) {
900  changedIndexes_();
901  }
902  }
903  assert(preg_->getNextIndexValue(branchType_) == productResolvers_.size());
904  }
905 
907  if (not reader()) {
908  return;
909  }
910 
911  for (auto& prod : *this) {
912  prod->retrieveAndMerge(*this, mergeableRunProductMetadata);
913  }
914  }
915 } // namespace edm
std::optional< std::tuple< WrapperBase const *, unsigned int > > getThinnedProduct(ProductID const &, unsigned int) const override
Definition: Principal.cc:844
BranchType branchType_
Definition: Principal.h:282
void fillPrincipal(DelayedReader *reader)
Definition: Principal.cc:406
static ProcessHistory const s_emptyProcessHistory
Definition: Principal.cc:37
void clearPrincipal()
Definition: Principal.cc:386
DelayedReader * reader_
Definition: Principal.h:280
void getAllProvenance(std::vector< Provenance const *> &provenances) const
Definition: Principal.cc:800
ProcessHistoryID processHistoryIDBeforeConfig_
Definition: Principal.h:263
void setupUnscheduled(UnscheduledConfigurator const &)
Definition: Principal.cc:402
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:618
static std::string const source("source")
ProductResolverCollection productResolvers_
Definition: Principal.h:268
std::variant< unsigned int, detail::GetThinnedKeyFromExceptionFactory, std::monostate > OptionalThinnedKey
std::shared_ptr< ProcessHistory const > processHistoryPtr_
Definition: Principal.h:260
ProductList const & productList() const
BranchID const & branchID() const
static PFTauRenderPlugin instance
ProductRegistry const & productRegistry() const
Definition: Principal.h:140
std::shared_ptr< ProductResolverBase > SharedProductPtr
Definition: Principal.h:66
void addProduct_(std::unique_ptr< ProductResolverBase > phb)
Definition: Principal.cc:533
BranchType const & branchType() const
static std::atomic< Principal::CacheIdentifier_t > s_nextIdentifier
Definition: Principal.cc:113
StableProvenance const & getStableProvenance(BranchID const &bid) const
Definition: Principal.cc:788
std::map< BranchKey, BranchDescription > ProductList
static Principal::CacheIdentifier_t nextIdentifier()
Definition: Principal.cc:114
ProcessHistoryID processHistoryID_
Definition: Principal.h:262
void mergeReaders(DelayedReader *other)
Definition: DelayedReader.h:36
ProductResolverBase * getExistingProduct(BranchID const &branchID)
Definition: Principal.cc:505
virtual void setupUnscheduled(UnscheduledConfigurator const &)
void getThinnedProducts(ProductID const &, std::vector< WrapperBase const *> &, std::vector< unsigned int > &) const override
Definition: Principal.cc:850
void applyToResolvers(F iFunc)
Definition: Principal.h:211
~Principal() override
Definition: Principal.cc:298
std::string const & processName() const
void prefetchAsync(WaitingTaskHolder waitTask, ProductResolverIndex index, bool skipCurrentProcess, ServiceToken const &token, ModuleCallingContext const *mcc) const
Definition: Principal.cc:644
size_t size() const
Definition: Principal.cc:303
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
ConstProductResolverPtr getProductResolverByIndex(ProductResolverIndex const &oid) const noexcept
Definition: Principal.cc:566
assert(be >=bs)
edm::propagate_const< HistoryAppender * > historyAppender_
Definition: Principal.h:287
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:118
std::string const & friendlyClassName() const
void addUnscheduledProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:349
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:654
void addAliasedProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:357
static void throwAmbiguousException(const char *where, TypeID const &productType, std::string const &label, std::string const &instance, std::string const &process)
Definition: Principal.cc:80
std::vector< unsigned int > lookupProcessOrder_
Definition: Principal.h:275
virtual unsigned int processBlockIndex(std::string const &processName) const
Definition: Principal.cc:572
char const * label
WrapperBase const * getIt(ProductID const &) const override
Definition: Principal.cc:839
std::shared_ptr< ProductResolverIndexHelper const > productLookup_
Definition: Principal.h:273
std::string const & className() const
std::string const & branchName() const
void addProductOrThrow(std::unique_ptr< ProductResolverBase > phb)
Definition: Principal.cc:546
std::shared_ptr< ProductRegistry const > preg_
Definition: Principal.h:272
CacheIdentifier_t cacheIdentifier_
Definition: Principal.h:289
ProductResolverIndex index(KindOfType kindOfType, TypeID const &typeID, char const *moduleLabel, char const *instance, char const *process=nullptr) const
std::string const & productInstanceName() 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:576
void getAllStableProvenance(std::vector< StableProvenance const *> &provenances) const
Definition: Principal.cc:817
ProcessHistoryID orderProcessHistoryID_
Definition: Principal.h:276
virtual void changedIndexes_()
Definition: Principal.h:219
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:396
void addDelayedReaderInputProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:341
string ranges
Definition: diffTwoXMLs.py:79
void put_(BranchDescription const &bd, std::unique_ptr< WrapperBase > edp) const
Definition: Principal.cc:865
void addParentProcessProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:381
ProductData const * findProductByTag(TypeID const &typeID, InputTag const &tag, ModuleCallingContext const *mcc) const
Definition: Principal.cc:765
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:134
void addSwitchProducerProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:365
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:56
ProductResolverBase const * ConstProductResolverPtr
Definition: Principal.h:62
std::string const & processName() const
HLT enums.
void readAllFromSourceAndMergeImmediately(MergeableRunProductMetadata const *mergeableRunProductMetadata=nullptr)
Definition: Principal.cc:906
unsigned long CacheIdentifier_t
Definition: Principal.h:178
bool adjustToNewProductRegistry(ProductRegistry const &reg)
Definition: Principal.cc:315
Provenance const & getProvenance(BranchID const &bid) const
Definition: Principal.cc:775
void adjustIndexesAfterProductRegistryAddition()
Definition: Principal.cc:877
static void throwProductNotFoundException(char const *where, errors::ErrorCodes error, BranchID const &bid)
Definition: Principal.cc:51
ProductResolverIndexHelper const & productLookup() const
Definition: Principal.h:142
#define UNLIKELY(x)
Definition: Likely.h:21
void addTransformProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:353
static std::string appendCurrentProcessIfAlias(std::string const &processFromInputTag, std::string const &currentProcess)
Definition: Principal.cc:39
OptionalThinnedKey getThinnedKeyFrom(ProductID const &parent, unsigned int key, ProductID const &thinned) const override
Definition: Principal.cc:856
void recombine(Principal &other, std::vector< BranchID > const &bids)
Definition: Principal.cc:828
std::string const & moduleLabel() const
void resetBranchDescription(std::shared_ptr< BranchDescription const > bd)
ProcessConfiguration const * processConfiguration_
Definition: Principal.h:265
void addSwitchAliasProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:373
def move(src, dest)
Definition: eostools.py:511
DelayedReader * reader() const
Definition: Principal.h:181
BranchType const & branchType() const
Definition: Principal.h:175
ConstProductResolverPtr getProductResolver(BranchID const &oid) const
Definition: Principal.cc:558