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()) {
165  if (bd.isTransform()) {
166  addTransformProduct(cbd);
167  } else {
169  }
170  } else {
171  addScheduledProduct(cbd);
172  }
173  } else {
174  if (bd.onDemand()) {
176  } else {
178  }
179  }
180  }
181  } else {
182  //We are in a SubProcess and this branch is from the parent
183  auto cbd = std::make_shared<BranchDescription const>(bd);
185  }
186  }
187  }
188  // Now process any EDAliases
189  if (hasAliases) {
190  for (auto const& prod : prodsList) {
191  BranchDescription const& bd = prod.second;
192  if (bd.isAlias() && bd.branchType() == branchType_) {
193  addAliasedProduct(std::make_shared<BranchDescription const>(bd));
194  }
195  }
196  }
197  // Finally process any SwitchProducer aliases
198  if (hasSwitchAliases) {
199  for (auto const& prod : prodsList) {
200  BranchDescription const& bd = prod.second;
201  if (bd.isSwitchAlias() && bd.branchType() == branchType_) {
203  auto cbd = std::make_shared<BranchDescription const>(bd);
204  // Need different implementation for SwitchProducers not
205  // in any Path (onDemand) and for those in a Path in order
206  // to prevent the switch-aliased-for EDProducers from
207  // being run when the SwitchProducer is in a Path after a
208  // failing EDFilter.
209  if (bd.onDemand()) {
211  } else {
213  }
214  }
215  }
216  }
217 
218  // Now create the ProductResolvers that search in reverse process
219  // order and are used for queries where the process name is the
220  // empty string
221  std::vector<std::string> const& lookupProcessNames = productLookup_->lookupProcessNames();
222  std::vector<ProductResolverIndex> matchingHolders(lookupProcessNames.size(), ProductResolverIndexInvalid);
223  std::vector<bool> ambiguous(lookupProcessNames.size(), false);
224  unsigned int beginElements = productLookup_->beginElements();
225  std::vector<TypeID> const& sortedTypeIDs = productLookup_->sortedTypeIDs();
226  std::vector<ProductResolverIndexHelper::Range> const& ranges = productLookup_->ranges();
227  std::vector<ProductResolverIndexHelper::IndexAndNames> const& indexAndNames = productLookup_->indexAndNames();
228  std::vector<char> const& processNamesCharArray = productLookup_->processNames();
229 
230  unsigned int numberOfMatches = 0;
232  if (!sortedTypeIDs.empty()) {
233  ProductResolverIndex productResolverIndex = ProductResolverIndexInvalid;
234  for (unsigned int k = 0, kEnd = sortedTypeIDs.size(); k < kEnd; ++k) {
236  for (unsigned int i = range.begin(); i < range.end(); ++i) {
237  ProductResolverIndexHelper::IndexAndNames const& product = indexAndNames.at(i);
238  if (product.startInProcessNames() == 0) {
239  if (productResolverIndex != ProductResolverIndexInvalid) {
240  if ((numberOfMatches == 1) and (lastMatchIndex != ProductResolverIndexAmbiguous)) {
241  //only one choice so use a special resolver
242  productResolvers_.at(productResolverIndex) =
243  std::make_shared<SingleChoiceNoProcessProductResolver>(lastMatchIndex);
244  } else {
245  bool productMadeAtEnd = false;
246  //Need to know if the product from this processes is added at end of transition
247  for (unsigned int j = 0; j < matchingHolders.size(); ++j) {
248  if ((not ambiguous[j]) and ProductResolverIndexInvalid != matchingHolders[j] and
249  productResolvers_[matchingHolders[j]]->branchDescription().availableOnlyAtEndTransition()) {
250  productMadeAtEnd = true;
251  break;
252  }
253  }
254  std::shared_ptr<ProductResolverBase> newHolder =
255  std::make_shared<NoProcessProductResolver>(matchingHolders, ambiguous, productMadeAtEnd);
256  productResolvers_.at(productResolverIndex) = newHolder;
257  }
258  matchingHolders.assign(lookupProcessNames.size(), ProductResolverIndexInvalid);
259  ambiguous.assign(lookupProcessNames.size(), false);
260  numberOfMatches = 0;
261  lastMatchIndex = ProductResolverIndexInvalid;
262  }
263  productResolverIndex = product.index();
264  } else {
265  std::string process(&processNamesCharArray.at(product.startInProcessNames()));
266  auto iter = std::find(lookupProcessNames.begin(), lookupProcessNames.end(), process);
267  assert(iter != lookupProcessNames.end());
268  ProductResolverIndex iMatchingIndex = product.index();
269  lastMatchIndex = iMatchingIndex;
270  assert(iMatchingIndex != ProductResolverIndexInvalid);
271  ++numberOfMatches;
272  if (iMatchingIndex == ProductResolverIndexAmbiguous) {
273  assert(k >= beginElements);
274  ambiguous.at(iter - lookupProcessNames.begin()) = true;
275  } else {
276  matchingHolders.at(iter - lookupProcessNames.begin()) = iMatchingIndex;
277  }
278  }
279  }
280  }
281  //Need to know if the product from this processes is added at end of transition
282  if ((numberOfMatches == 1) and (lastMatchIndex != ProductResolverIndexAmbiguous)) {
283  //only one choice so use a special resolver
284  productResolvers_.at(productResolverIndex) =
285  std::make_shared<SingleChoiceNoProcessProductResolver>(lastMatchIndex);
286  } else {
287  bool productMadeAtEnd = false;
288  for (unsigned int i = 0; i < matchingHolders.size(); ++i) {
289  if ((not ambiguous[i]) and ProductResolverIndexInvalid != matchingHolders[i] and
290  productResolvers_[matchingHolders[i]]->branchDescription().availableOnlyAtEndTransition()) {
291  productMadeAtEnd = true;
292  break;
293  }
294  }
295  std::shared_ptr<ProductResolverBase> newHolder =
296  std::make_shared<NoProcessProductResolver>(matchingHolders, ambiguous, productMadeAtEnd);
297  productResolvers_.at(productResolverIndex) = newHolder;
298  }
299  }
300  }
301 
303 
304  // Number of products in the Principal.
305  // For products in an input file and not yet read in due to delayed read,
306  // this routine assumes a real product is there.
307  size_t Principal::size() const {
308  size_t size = 0U;
309  for (auto const& prod : *this) {
310  if (prod->singleProduct() && // Not a NoProcessProductResolver
311  !prod->productUnavailable() && !prod->unscheduledWasNotRun() && !prod->branchDescription().dropped()) {
312  ++size;
313  }
314  }
315  return size;
316  }
317 
318  // adjust provenance for input products after new input file has been merged
320  ProductRegistry::ProductList const& prodsList = reg.productList();
321  for (auto const& prod : prodsList) {
322  BranchDescription const& bd = prod.second;
323  if (!bd.produced() && (bd.branchType() == branchType_)) {
324  auto cbd = std::make_shared<BranchDescription const>(bd);
325  auto phb = getExistingProduct(cbd->branchID());
326  if (phb == nullptr || phb->branchDescription().branchName() != cbd->branchName()) {
327  return false;
328  }
329  phb->resetBranchDescription(cbd);
330  }
331  }
332  return true;
333  }
334 
335  void Principal::addScheduledProduct(std::shared_ptr<BranchDescription const> bd) {
336  auto phb = std::make_unique<PuttableProductResolver>(std::move(bd));
338  }
339 
340  void Principal::addSourceProduct(std::shared_ptr<BranchDescription const> bd) {
341  auto phb = std::make_unique<PuttableProductResolver>(std::move(bd));
343  }
344 
345  void Principal::addDelayedReaderInputProduct(std::shared_ptr<BranchDescription const> bd) {
346  addProductOrThrow(std::make_unique<DelayedReaderInputProductResolver>(std::move(bd)));
347  }
348 
349  void Principal::addPutOnReadInputProduct(std::shared_ptr<BranchDescription const> bd) {
350  addProductOrThrow(std::make_unique<PutOnReadInputProductResolver>(std::move(bd)));
351  }
352 
353  void Principal::addUnscheduledProduct(std::shared_ptr<BranchDescription const> bd) {
354  addProductOrThrow(std::make_unique<UnscheduledProductResolver>(std::move(bd)));
355  }
356 
357  void Principal::addTransformProduct(std::shared_ptr<BranchDescription const> bd) {
358  addProductOrThrow(std::make_unique<TransformingProductResolver>(std::move(bd)));
359  }
360 
361  void Principal::addAliasedProduct(std::shared_ptr<BranchDescription const> bd) {
362  ProductResolverIndex index = preg_->indexFrom(bd->originalBranchID());
364 
365  addProductOrThrow(std::make_unique<AliasProductResolver>(
366  std::move(bd), dynamic_cast<DataManagingOrAliasProductResolver&>(*productResolvers_[index])));
367  }
368 
369  void Principal::addSwitchProducerProduct(std::shared_ptr<BranchDescription const> bd) {
370  ProductResolverIndex index = preg_->indexFrom(bd->switchAliasForBranchID());
372 
373  addProductOrThrow(std::make_unique<SwitchProducerProductResolver>(
374  std::move(bd), dynamic_cast<DataManagingOrAliasProductResolver&>(*productResolvers_[index])));
375  }
376 
377  void Principal::addSwitchAliasProduct(std::shared_ptr<BranchDescription const> bd) {
378  ProductResolverIndex index = preg_->indexFrom(bd->switchAliasForBranchID());
380 
381  addProductOrThrow(std::make_unique<SwitchAliasProductResolver>(
382  std::move(bd), dynamic_cast<DataManagingOrAliasProductResolver&>(*productResolvers_[index])));
383  }
384 
385  void Principal::addParentProcessProduct(std::shared_ptr<BranchDescription const> bd) {
386  addProductOrThrow(std::make_unique<ParentProcessProductResolver>(std::move(bd)));
387  }
388 
389  // "Zero" the principal so it can be reused for another Event.
391  //We do not clear the product history information
392  // because it rarely changes and recalculating takes
393  // time.
394  reader_ = nullptr;
395  for (auto& prod : *this) {
396  prod->resetProductData();
397  }
398  }
399 
400  void Principal::deleteProduct(BranchID const& id) const {
401  auto phb = getExistingProduct(id);
402  assert(nullptr != phb);
403  phb->unsafe_deleteProduct();
404  }
405 
407  applyToResolvers([&iConfigure](ProductResolverBase* iResolver) { iResolver->setupUnscheduled(iConfigure); });
408  }
409 
411  //increment identifier here since clearPrincipal isn't called for Run/Lumi
413  if (reader) {
414  reader_ = reader;
415  }
416  }
417 
418  // Set the principal for the Event, Lumi, or Run.
420  ProcessHistory const* processHistory,
423 
424  if (historyAppender_ && productRegistry().anyProductProduced()) {
429  }
430  } else {
431  std::shared_ptr<ProcessHistory const> inputProcessHistory;
433  if (hist.isValid()) {
434  //does not own the pointer
435  auto noDel = [](void const*) {};
436  inputProcessHistory = std::shared_ptr<ProcessHistory const>(processHistory, noDel);
437  if (inputProcessHistory.get() == nullptr) {
438  throw Exception(errors::LogicError) << "Principal::fillPrincipal\n"
439  << "Input ProcessHistory not found in registry\n"
440  << "Contact a Framework developer\n";
441  }
442  } else {
443  //Since this is static we don't want it deleted
444  inputProcessHistory = std::shared_ptr<ProcessHistory const>(&s_emptyProcessHistory, [](void const*) {});
445  //no need to do any ordering since it is empty
447  }
449  processHistoryPtr_ = inputProcessHistory;
451  }
452  }
453 
455  std::vector<std::string> const& lookupProcessNames = productLookup_->lookupProcessNames();
456  lookupProcessOrder_.assign(lookupProcessNames.size(), 0);
457  unsigned int k = 0;
458 
459  // We loop over processes in reverse order of the ProcessHistory.
460  // If any entries in the product lookup tables are associated with
461  // the process we add it to the vector of processes in the order
462  // the lookup should be performed. There is one exception though,
463  // We start with the current process even if it is not in the ProcessHistory.
464  // The current process might be needed but not be in the process
465  // history if all the products produced in the current process are
466  // transient.
467  {
468  auto nameIterCurrentProcess =
469  std::find(lookupProcessNames.begin(), lookupProcessNames.end(), processConfiguration_->processName());
470  if (nameIterCurrentProcess != lookupProcessNames.end()) {
471  lookupProcessOrder_.at(k) = nameIterCurrentProcess - lookupProcessNames.begin();
472  ++k;
473  }
474  }
475 
476  // We just looked for the current process so skip it if
477  // it is in the ProcessHistory.
478  auto iter = processHistoryPtr_->rbegin();
479  if (iter->processName() == processConfiguration_->processName()) {
480  ++iter;
481  }
482 
483  for (auto iEnd = processHistoryPtr_->rend(); iter != iEnd; ++iter) {
484  auto nameIter = std::find(lookupProcessNames.begin(), lookupProcessNames.end(), iter->processName());
485  if (nameIter == lookupProcessNames.end()) {
486  continue;
487  }
488  lookupProcessOrder_.at(k) = nameIter - lookupProcessNames.begin();
489  ++k;
490  }
492  }
493  }
494 
495  // Set the principal for the ProcessBlock
496  void Principal::fillPrincipal(std::string const& processNameOfBlock, DelayedReader* reader) {
498 
499  std::vector<std::string> const& lookupProcessNames = productLookup_->lookupProcessNames();
500  lookupProcessOrder_.assign(lookupProcessNames.size(), 0);
501  if (!lookupProcessOrder_.empty()) {
502  auto iter = std::find(lookupProcessNames.begin(), lookupProcessNames.end(), processNameOfBlock);
503  if (iter != lookupProcessNames.end()) {
504  lookupProcessOrder_[0] = iter - lookupProcessNames.begin();
505  }
506  }
507  }
508 
510  return const_cast<ProductResolverBase*>(const_cast<const Principal*>(this)->getExistingProduct(branchID));
511  }
512 
514  ProductResolverIndex index = preg_->indexFrom(branchID);
516  return productResolvers_.at(index).get();
517  }
518 
520  auto phb = getExistingProduct(productResolver.branchDescription().branchID());
521  if (nullptr != phb && BranchKey(productResolver.branchDescription()) != BranchKey(phb->branchDescription())) {
522  BranchDescription const& newProduct = phb->branchDescription();
523  BranchDescription const& existing = productResolver.branchDescription();
524  if (newProduct.branchName() != existing.branchName() && newProduct.branchID() == existing.branchID()) {
525  throw cms::Exception("HashCollision")
526  << "Principal::getExistingProduct\n"
527  << " Branch " << newProduct.branchName() << " has same branch ID as branch " << existing.branchName()
528  << "\n"
529  << "Workaround: change process name or product instance name of " << newProduct.branchName() << "\n";
530  } else {
531  assert(nullptr == phb || BranchKey(productResolver.branchDescription()) == BranchKey(phb->branchDescription()));
532  }
533  }
534  return phb;
535  }
536 
537  void Principal::addProduct_(std::unique_ptr<ProductResolverBase> productResolver) {
538  BranchDescription const& bd = productResolver->branchDescription();
539  assert(!bd.className().empty());
540  assert(!bd.friendlyClassName().empty());
541  assert(!bd.moduleLabel().empty());
542  assert(!bd.processName().empty());
543  SharedProductPtr phb(productResolver.release());
544 
545  ProductResolverIndex index = preg_->indexFrom(bd.branchID());
547  productResolvers_[index] = phb;
548  }
549 
550  void Principal::addProductOrThrow(std::unique_ptr<ProductResolverBase> productResolver) {
551  ProductResolverBase const* phb = getExistingProduct(*productResolver);
552  if (phb != nullptr) {
553  BranchDescription const& bd = productResolver->branchDescription();
554  throw Exception(errors::InsertFailure, "AlreadyPresent")
555  << "addProductOrThrow: Problem found while adding product, "
556  << "product already exists for (" << bd.friendlyClassName() << "," << bd.moduleLabel() << ","
557  << bd.productInstanceName() << "," << bd.processName() << ")\n";
558  }
559  addProduct_(std::move(productResolver));
560  }
561 
563  ProductResolverIndex index = preg_->indexFrom(bid);
565  return ConstProductResolverPtr();
566  }
568  }
569 
572  return phb;
573  }
574 
575  unsigned int Principal::processBlockIndex(std::string const&) const {
576  throw Exception(errors::LogicError) << "Principal::processBlockIndex not implemented for this type of Principal";
577  }
578 
580  TypeID const& typeID,
581  InputTag const& inputTag,
582  EDConsumerBase const* consumer,
584  ModuleCallingContext const* mcc) const {
585  // Not implemented for ProcessBlocks, it might work though, not tested
586  // The other getByLabel function is used for ProcessBlocks by TestProcessor
588 
589  ProductData const* result = findProductByLabel(kindOfType, typeID, inputTag, consumer, sra, mcc);
590  if (result == nullptr) {
591  return BasicHandle(makeHandleExceptionFactory([=]() -> std::shared_ptr<cms::Exception> {
592  return makeNotFoundException(
593  "getByLabel",
594  kindOfType,
595  typeID,
596  inputTag.label(),
597  inputTag.instance(),
599  }));
600  }
601  return BasicHandle(result->wrapper(), &(result->provenance()));
602  }
603 
605  TypeID const& typeID,
606  std::string const& label,
607  std::string const& instance,
608  std::string const& process,
609  EDConsumerBase const* consumer,
611  ModuleCallingContext const* mcc) const {
612  ProductData const* result = findProductByLabel(kindOfType, typeID, label, instance, process, consumer, sra, mcc);
613  if (result == nullptr) {
614  return BasicHandle(makeHandleExceptionFactory([=]() -> std::shared_ptr<cms::Exception> {
615  return makeNotFoundException("getByLabel", kindOfType, typeID, label, instance, process);
616  }));
617  }
618  return BasicHandle(result->wrapper(), &(result->provenance()));
619  }
620 
622  TypeID const&,
624  bool skipCurrentProcess,
625  bool& ambiguous,
627  ModuleCallingContext const* mcc) const {
629  auto& productResolver = productResolvers_[index];
630  assert(nullptr != productResolver.get());
631  auto resolution = productResolver->resolveProduct(*this, skipCurrentProcess, sra, mcc);
632  if (resolution.isAmbiguous()) {
633  ambiguous = true;
634  //The caller is looking explicitly for this case
635  // and uses the extra data at the caller to setup the exception
636  return BasicHandle::makeInvalid();
637  }
638  auto productData = resolution.data();
639  if (productData == nullptr) {
640  //The caller is looking explicitly for this case
641  // and uses the extra data at the caller to setup the exception
642  return BasicHandle::makeInvalid();
643  }
644  return BasicHandle(productData->wrapper(), &(productData->provenance()));
645  }
646 
649  bool skipCurrentProcess,
650  ServiceToken const& token,
651  ModuleCallingContext const* mcc) const {
652  auto const& productResolver = productResolvers_.at(index);
653  assert(nullptr != productResolver.get());
654  productResolver->prefetchAsync(task, *this, skipCurrentProcess, token, nullptr, mcc);
655  }
656 
657  void Principal::getManyByType(TypeID const& typeID,
659  EDConsumerBase const* consumer,
661  ModuleCallingContext const* mcc) const {
662  // Not implemented for ProcessBlocks
664 
665  assert(results.empty());
666 
667  if (UNLIKELY(consumer and (not consumer->registeredToConsumeMany(typeID, branchType())))) {
668  failedToRegisterConsumesMany(typeID);
669  }
670 
671  // This finds the indexes to all the ProductResolver's matching the type
673 
674  if (matches.numberOfMatches() == 0) {
675  return;
676  }
677 
678  results.reserve(matches.numberOfMatches());
679 
680  // Loop over the ProductResolvers. Add the products that are actually
681  // present into the results. This will also trigger delayed reading,
682  // on demand production, and check for deleted products as appropriate.
683 
684  // Over the years the code that uses getManyByType has grown to depend
685  // on the ordering of the results. The order originally was just an
686  // accident of how previous versions of the code were written, but
687  // here we have to go through some extra effort to preserve that ordering.
688 
689  // We build a list of holders that match a particular label and instance.
690  // When that list is complete we call findProducts, which loops over
691  // that list in reverse order of the ProcessHistory (starts with the
692  // most recent). Then we clear the list and repeat this until all the
693  // matching label and instance subsets have been dealt with.
694 
695  // Note that the function isFullyResolved returns true for the ProductResolvers
696  // that are associated with an empty process name. Those are the ones that
697  // know how to search for the most recent process name matching
698  // a label and instance. We do not need these for getManyByType and
699  // skip them. In addition to skipping them, we make use of the fact
700  // that they mark the beginning of each subset of holders with the same
701  // label and instance. They tell us when to call findProducts.
702 
703  std::vector<ProductResolverBase const*> holders;
704 
705  for (unsigned int i = 0; i < matches.numberOfMatches(); ++i) {
707 
708  if (!matches.isFullyResolved(i)) {
709  if (!holders.empty()) {
710  // Process the ones with a particular module label and instance
711  findProducts(holders, typeID, results, sra, mcc);
712  holders.clear();
713  }
714  } else {
715  ProductResolverBase const* productResolver = productResolvers_.at(index).get();
716  assert(productResolver);
717  holders.push_back(productResolver);
718  }
719  }
720  // Do not miss the last subset of products
721  if (!holders.empty()) {
722  findProducts(holders, typeID, results, sra, mcc);
723  }
724  return;
725  }
726 
727  void Principal::findProducts(std::vector<ProductResolverBase const*> const& holders,
728  TypeID const&,
731  ModuleCallingContext const* mcc) const {
732  for (auto iter = processHistoryPtr_->rbegin(), iEnd = processHistoryPtr_->rend(); iter != iEnd; ++iter) {
733  std::string const& process = iter->processName();
734  for (auto productResolver : holders) {
735  BranchDescription const& bd = productResolver->branchDescription();
736  if (process == bd.processName()) {
737  // Ignore aliases to avoid matching the same product multiple times.
738  if (bd.isAnyAlias()) {
739  continue;
740  }
741 
742  ProductData const* productData = productResolver->resolveProduct(*this, false, sra, mcc).data();
743  if (productData) {
744  // Skip product if not available.
745  results.emplace_back(productData->wrapper(), &(productData->provenance()));
746  }
747  }
748  }
749  }
750  }
751 
753  TypeID const& typeID,
754  InputTag const& inputTag,
755  EDConsumerBase const* consumer,
757  ModuleCallingContext const* mcc) const {
758  bool skipCurrentProcess = inputTag.willSkipCurrentProcess();
759 
761 
763  char const* processName = inputTag.process().c_str();
764  if (skipCurrentProcess) {
765  processName = "\0";
766  } else if (inputTag.process() == InputTag::kCurrentProcess) {
768  }
769 
770  index =
771  productLookup().index(kindOfType, typeID, inputTag.label().c_str(), inputTag.instance().c_str(), processName);
772 
774  throwAmbiguousException("findProductByLabel",
775  typeID,
776  inputTag.label(),
777  inputTag.instance(),
779  } else if (index == ProductResolverIndexInvalid) {
780  // can occur because of missing consumes if nothing else in the process consumes the product
781  for (auto const& item : preg_->productList()) {
782  auto const& bd = item.second;
783  if (bd.present() and bd.unwrappedTypeID() == typeID and bd.moduleLabel() == inputTag.label() and
784  bd.productInstanceName() == inputTag.instance()) {
785  bool const inCurrentProcess = bd.processName() == processConfiguration_->processName();
786  if (inputTag.process().empty() or bd.processName() == inputTag.process() or
787  (skipCurrentProcess and not inCurrentProcess) or
788  (inputTag.process() == InputTag::kCurrentProcess and inCurrentProcess)) {
789  failedToRegisterConsumes(
790  kindOfType,
791  typeID,
792  inputTag.label(),
793  inputTag.instance(),
795  }
796  }
797  }
798  return nullptr;
799  }
800  inputTag.tryToCacheIndex(index, typeID, branchType(), &productRegistry());
801  }
802  if (UNLIKELY(consumer and (not consumer->registeredToConsume(index, skipCurrentProcess, branchType())))) {
803  failedToRegisterConsumes(kindOfType,
804  typeID,
805  inputTag.label(),
806  inputTag.instance(),
808  }
809 
810  auto const& productResolver = productResolvers_[index];
811 
812  auto resolution = productResolver->resolveProduct(*this, skipCurrentProcess, sra, mcc);
813  if (resolution.isAmbiguous()) {
814  throwAmbiguousException("findProductByLabel",
815  typeID,
816  inputTag.label(),
817  inputTag.instance(),
819  }
820  return resolution.data();
821  }
822 
824  TypeID const& typeID,
825  std::string const& label,
826  std::string const& instance,
827  std::string const& process,
828  EDConsumerBase const* consumer,
830  ModuleCallingContext const* mcc) const {
832  productLookup().index(kindOfType, typeID, label.c_str(), instance.c_str(), process.c_str());
833 
835  throwAmbiguousException("findProductByLabel", typeID, label, instance, process);
836  } else if (index == ProductResolverIndexInvalid) {
837  // can occur because of missing consumes if nothing else in the process consumes the product
838  for (auto const& item : preg_->productList()) {
839  auto const& bd = item.second;
840  if (bd.present() and bd.unwrappedTypeID() == typeID and bd.moduleLabel() == label and
841  bd.productInstanceName() == instance) {
842  if (process.empty() or bd.processName() == process) {
843  failedToRegisterConsumes(kindOfType, typeID, label, instance, process);
844  }
845  }
846  }
847  return nullptr;
848  }
849 
850  if (UNLIKELY(consumer and (not consumer->registeredToConsume(index, false, branchType())))) {
851  failedToRegisterConsumes(kindOfType, typeID, label, instance, process);
852  }
853 
854  auto const& productResolver = productResolvers_[index];
855 
856  auto resolution = productResolver->resolveProduct(*this, false, sra, mcc);
857  if (resolution.isAmbiguous()) {
858  throwAmbiguousException("findProductByLabel", typeID, label, instance, process);
859  }
860  return resolution.data();
861  }
862 
864  InputTag const& tag,
865  ModuleCallingContext const* mcc) const {
866  // Not implemented for ProcessBlocks
868 
869  ProductData const* productData = findProductByLabel(PRODUCT_TYPE, typeID, tag, nullptr, nullptr, mcc);
870  return productData;
871  }
872 
873  Provenance const& Principal::getProvenance(BranchID const& bid) const {
875  if (phb == nullptr) {
877  }
878 
879  if (phb->unscheduledWasNotRun()) {
881  << "Requesting provenance from unrun EDProducer. The requested branch ID was: " << bid;
882  }
883  return *phb->provenance();
884  }
885 
888  if (phb == nullptr) {
889  throwProductNotFoundException("getStableProvenance", errors::ProductNotFound, bid);
890  }
891  //NOTE: in all implementations, this never returns a nullptr
892  return *phb->stableProvenance();
893  }
894 
895  // This one is mostly for test printout purposes
896  // No attempt to trigger on demand execution
897  // Skips provenance when the EDProduct is not there
898  void Principal::getAllProvenance(std::vector<Provenance const*>& provenances) const {
899  provenances.clear();
900  for (auto const& productResolver : *this) {
901  if (productResolver->singleProduct() && productResolver->provenanceAvailable() &&
902  !productResolver->branchDescription().isAnyAlias()) {
903  // We do not attempt to get the event/lumi/run status from the provenance,
904  // because the per event provenance may have been dropped.
905  if (productResolver->provenance()->branchDescription().present()) {
906  provenances.push_back(productResolver->provenance());
907  }
908  }
909  }
910  }
911 
912  // This one is also mostly for test printout purposes
913  // No attempt to trigger on demand execution
914  // Skips provenance for dropped branches.
915  void Principal::getAllStableProvenance(std::vector<StableProvenance const*>& provenances) const {
916  provenances.clear();
917  for (auto const& productResolver : *this) {
918  if (productResolver->singleProduct() && !productResolver->branchDescription().isAnyAlias()) {
919  if (productResolver->stableProvenance()->branchDescription().present()) {
920  provenances.push_back(productResolver->stableProvenance());
921  }
922  }
923  }
924  }
925 
926  void Principal::recombine(Principal& other, std::vector<BranchID> const& bids) {
927  for (auto& prod : bids) {
928  ProductResolverIndex index = preg_->indexFrom(prod);
930  ProductResolverIndex indexO = other.preg_->indexFrom(prod);
932  get_underlying_safe(productResolvers_[index]).swap(get_underlying_safe(other.productResolvers_[indexO]));
933  }
934  reader_->mergeReaders(other.reader());
935  }
936 
937  WrapperBase const* Principal::getIt(ProductID const&) const {
938  assert(false);
939  return nullptr;
940  }
941 
942  std::optional<std::tuple<WrapperBase const*, unsigned int>> Principal::getThinnedProduct(ProductID const&,
943  unsigned int) const {
944  assert(false);
945  return std::nullopt;
946  }
947 
949  std::vector<WrapperBase const*>&,
950  std::vector<unsigned int>&) const {
951  assert(false);
952  }
953 
955  assert(false);
956  return std::monostate{};
957  }
958 
959  void Principal::put_(std::unique_ptr<WrapperBase> prod, ProductResolverBase const* phb) const {
960  dynamic_cast<ProductPutterBase const*>(phb)->putProduct(std::move(prod));
961  }
962 
963  void Principal::put_(BranchDescription const& bd, std::unique_ptr<WrapperBase> edp) const {
964  if (edp.get() == nullptr) {
965  throw edm::Exception(edm::errors::InsertFailure, "Null Pointer")
966  << "put: Cannot put because unique_ptr to product is null."
967  << "\n";
968  }
969  auto phb = getExistingProduct(bd.branchID());
970  assert(phb);
971  // ProductResolver assumes ownership
972  put_(std::move(edp), phb);
973  }
974 
976  if (preg_->getNextIndexValue(branchType_) != productResolvers_.size()) {
977  bool changed = false;
978  productResolvers_.resize(preg_->getNextIndexValue(branchType_));
979  for (auto const& prod : preg_->productList()) {
980  BranchDescription const& bd = prod.second;
981  if (bd.branchType() == branchType_) {
982  ProductResolverIndex index = preg_->indexFrom(bd.branchID());
984  if (!productResolvers_[index]) {
985  // no product holder. Must add one. The new entry must be an input product holder.
986  assert(!bd.produced());
987  auto cbd = std::make_shared<BranchDescription const>(bd);
988  if (bd.onDemand()) {
990  } else {
992  }
993  changed = true;
994  }
995  }
996  }
997  if (changed) {
998  changedIndexes_();
999  }
1000  }
1001  assert(preg_->getNextIndexValue(branchType_) == productResolvers_.size());
1002  }
1003 
1005  if (not reader()) {
1006  return;
1007  }
1008 
1009  for (auto& prod : *this) {
1010  prod->retrieveAndMerge(*this, mergeableRunProductMetadata);
1011  }
1012  }
1013 } // namespace edm
std::optional< std::tuple< WrapperBase const *, unsigned int > > getThinnedProduct(ProductID const &, unsigned int) const override
Definition: Principal.cc:942
BranchType branchType_
Definition: Principal.h:294
void findProducts(std::vector< ProductResolverBase const *> const &holders, TypeID const &typeID, BasicHandleVec &results, SharedResourcesAcquirer *sra, ModuleCallingContext const *mcc) const
Definition: Principal.cc:727
size
Write out results.
void fillPrincipal(DelayedReader *reader)
Definition: Principal.cc:410
static ProcessHistory const s_emptyProcessHistory
Definition: Principal.cc:34
void clearPrincipal()
Definition: Principal.cc:390
DelayedReader * reader_
Definition: Principal.h:292
void getAllProvenance(std::vector< Provenance const *> &provenances) const
Definition: Principal.cc:898
ProcessHistoryID processHistoryIDBeforeConfig_
Definition: Principal.h:275
void setupUnscheduled(UnscheduledConfigurator const &)
Definition: Principal.cc:406
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:621
static std::string const source("source")
ProductResolverCollection productResolvers_
Definition: Principal.h:280
std::variant< unsigned int, detail::GetThinnedKeyFromExceptionFactory, std::monostate > OptionalThinnedKey
std::shared_ptr< ProcessHistory const > processHistoryPtr_
Definition: Principal.h:272
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:537
static std::atomic< Principal::CacheIdentifier_t > s_nextIdentifier
Definition: Principal.cc:117
StableProvenance const & getStableProvenance(BranchID const &bid) const
Definition: Principal.cc:886
std::map< BranchKey, BranchDescription > ProductList
static Principal::CacheIdentifier_t nextIdentifier()
Definition: Principal.cc:118
ProcessHistoryID processHistoryID_
Definition: Principal.h:274
void mergeReaders(DelayedReader *other)
Definition: DelayedReader.h:36
ProductResolverBase * getExistingProduct(BranchID const &branchID)
Definition: Principal.cc:509
virtual void setupUnscheduled(UnscheduledConfigurator const &)
void getThinnedProducts(ProductID const &, std::vector< WrapperBase const *> &, std::vector< unsigned int > &) const override
Definition: Principal.cc:948
void applyToResolvers(F iFunc)
Definition: Principal.h:217
~Principal() override
Definition: Principal.cc:302
void prefetchAsync(WaitingTaskHolder waitTask, ProductResolverIndex index, bool skipCurrentProcess, ServiceToken const &token, ModuleCallingContext const *mcc) const
Definition: Principal.cc:647
size_t size() const
Definition: Principal.cc:307
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:299
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:353
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:657
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:752
void addAliasedProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:361
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:287
virtual unsigned int processBlockIndex(std::string const &processName) const
Definition: Principal.cc:575
deep_tau::DeepTauBase::BasicDiscriminator bd
Definition: DeepTauId.cc:808
char const * label
WrapperBase const * getIt(ProductID const &) const override
Definition: Principal.cc:937
std::shared_ptr< ProductResolverIndexHelper const > productLookup_
Definition: Principal.h:285
std::string const & branchName() const
void addProductOrThrow(std::unique_ptr< ProductResolverBase > phb)
Definition: Principal.cc:550
std::shared_ptr< ProductRegistry const > preg_
Definition: Principal.h:284
CacheIdentifier_t cacheIdentifier_
Definition: Principal.h:301
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:579
void getAllStableProvenance(std::vector< StableProvenance const *> &provenances) const
Definition: Principal.cc:915
ProcessHistoryID orderProcessHistoryID_
Definition: Principal.h:288
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:340
void addPutOnReadInputProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:349
void deleteProduct(BranchID const &id) const
Definition: Principal.cc:400
void addDelayedReaderInputProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:345
string ranges
Definition: diffTwoXMLs.py:79
void put_(BranchDescription const &bd, std::unique_ptr< WrapperBase > edp) const
Definition: Principal.cc:963
void addParentProcessProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:385
ProductData const * findProductByTag(TypeID const &typeID, InputTag const &tag, ModuleCallingContext const *mcc) const
Definition: Principal.cc:863
void addScheduledProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:335
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:369
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:1004
unsigned long CacheIdentifier_t
Definition: Principal.h:184
bool adjustToNewProductRegistry(ProductRegistry const &reg)
Definition: Principal.cc:319
results
Definition: mysort.py:8
Provenance const & getProvenance(BranchID const &bid) const
Definition: Principal.cc:873
void adjustIndexesAfterProductRegistryAddition()
Definition: Principal.cc:975
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
void addTransformProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:357
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:954
void recombine(Principal &other, std::vector< BranchID > const &bids)
Definition: Principal.cc:926
ConstProductResolverPtr getProductResolverByIndex(ProductResolverIndex const &oid) const
Definition: Principal.cc:570
void resetBranchDescription(std::shared_ptr< BranchDescription const > bd)
ProcessConfiguration const * processConfiguration_
Definition: Principal.h:277
void addSwitchAliasProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:377
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:562