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()) {
164  assert(branchType_ == InEvent);
166  } else {
167  addScheduledProduct(cbd);
168  }
169  } else {
170  addInputProduct(cbd);
171  }
172  }
173  } else {
174  //We are in a SubProcess and this branch is from the parent
175  auto cbd = std::make_shared<BranchDescription const>(bd);
177  }
178  }
179  }
180  // Now process any EDAliases
181  if (hasAliases) {
182  for (auto const& prod : prodsList) {
183  BranchDescription const& bd = prod.second;
184  if (bd.isAlias() && bd.branchType() == branchType_) {
185  addAliasedProduct(std::make_shared<BranchDescription const>(bd));
186  }
187  }
188  }
189  // Finally process any SwitchProducer aliases
190  if (hasSwitchAliases) {
191  for (auto const& prod : prodsList) {
192  BranchDescription const& bd = prod.second;
193  if (bd.isSwitchAlias() && bd.branchType() == branchType_) {
194  assert(branchType_ == InEvent);
195  auto cbd = std::make_shared<BranchDescription const>(bd);
196  // Need different implementation for SwitchProducers not
197  // in any Path (onDemand) and for those in a Path in order
198  // to prevent the switch-aliased-for EDProducers from
199  // being run when the SwitchProducer is in a Path after a
200  // failing EDFilter.
201  if (bd.onDemand()) {
203  } else {
205  }
206  }
207  }
208  }
209 
210  // Now create the ProductResolvers that search in reverse process
211  // order and are used for queries where the process name is the
212  // empty string
213  std::vector<std::string> const& lookupProcessNames = productLookup_->lookupProcessNames();
214  std::vector<ProductResolverIndex> matchingHolders(lookupProcessNames.size(), ProductResolverIndexInvalid);
215  std::vector<bool> ambiguous(lookupProcessNames.size(), false);
216  unsigned int beginElements = productLookup_->beginElements();
217  std::vector<TypeID> const& sortedTypeIDs = productLookup_->sortedTypeIDs();
218  std::vector<ProductResolverIndexHelper::Range> const& ranges = productLookup_->ranges();
219  std::vector<ProductResolverIndexHelper::IndexAndNames> const& indexAndNames = productLookup_->indexAndNames();
220  std::vector<char> const& processNamesCharArray = productLookup_->processNames();
221 
222  unsigned int numberOfMatches = 0;
224  if (!sortedTypeIDs.empty()) {
225  ProductResolverIndex productResolverIndex = ProductResolverIndexInvalid;
226  for (unsigned int k = 0, kEnd = sortedTypeIDs.size(); k < kEnd; ++k) {
227  ProductResolverIndexHelper::Range const& range = ranges.at(k);
228  for (unsigned int i = range.begin(); i < range.end(); ++i) {
229  ProductResolverIndexHelper::IndexAndNames const& product = indexAndNames.at(i);
230  if (product.startInProcessNames() == 0) {
231  if (productResolverIndex != ProductResolverIndexInvalid) {
232  if ((numberOfMatches == 1) and (lastMatchIndex != ProductResolverIndexAmbiguous)) {
233  //only one choice so use a special resolver
234  productResolvers_.at(productResolverIndex) =
235  std::make_shared<SingleChoiceNoProcessProductResolver>(lastMatchIndex);
236  } else {
237  bool productMadeAtEnd = false;
238  //Need to know if the product from this processes is added at end of transition
239  for (unsigned int j = 0; j < matchingHolders.size(); ++j) {
240  if ((not ambiguous[j]) and ProductResolverIndexInvalid != matchingHolders[j] and
241  productResolvers_[matchingHolders[j]]->branchDescription().availableOnlyAtEndTransition()) {
242  productMadeAtEnd = true;
243  break;
244  }
245  }
246  std::shared_ptr<ProductResolverBase> newHolder =
247  std::make_shared<NoProcessProductResolver>(matchingHolders, ambiguous, productMadeAtEnd);
248  productResolvers_.at(productResolverIndex) = newHolder;
249  }
250  matchingHolders.assign(lookupProcessNames.size(), ProductResolverIndexInvalid);
251  ambiguous.assign(lookupProcessNames.size(), false);
252  numberOfMatches = 0;
253  lastMatchIndex = ProductResolverIndexInvalid;
254  }
255  productResolverIndex = product.index();
256  } else {
257  std::string process(&processNamesCharArray.at(product.startInProcessNames()));
258  auto iter = std::find(lookupProcessNames.begin(), lookupProcessNames.end(), process);
259  assert(iter != lookupProcessNames.end());
260  ProductResolverIndex iMatchingIndex = product.index();
261  lastMatchIndex = iMatchingIndex;
262  assert(iMatchingIndex != ProductResolverIndexInvalid);
263  ++numberOfMatches;
264  if (iMatchingIndex == ProductResolverIndexAmbiguous) {
265  assert(k >= beginElements);
266  ambiguous.at(iter - lookupProcessNames.begin()) = true;
267  } else {
268  matchingHolders.at(iter - lookupProcessNames.begin()) = iMatchingIndex;
269  }
270  }
271  }
272  }
273  //Need to know if the product from this processes is added at end of transition
274  if ((numberOfMatches == 1) and (lastMatchIndex != ProductResolverIndexAmbiguous)) {
275  //only one choice so use a special resolver
276  productResolvers_.at(productResolverIndex) =
277  std::make_shared<SingleChoiceNoProcessProductResolver>(lastMatchIndex);
278  } else {
279  bool productMadeAtEnd = false;
280  for (unsigned int i = 0; i < matchingHolders.size(); ++i) {
281  if ((not ambiguous[i]) and ProductResolverIndexInvalid != matchingHolders[i] and
282  productResolvers_[matchingHolders[i]]->branchDescription().availableOnlyAtEndTransition()) {
283  productMadeAtEnd = true;
284  break;
285  }
286  }
287  std::shared_ptr<ProductResolverBase> newHolder =
288  std::make_shared<NoProcessProductResolver>(matchingHolders, ambiguous, productMadeAtEnd);
289  productResolvers_.at(productResolverIndex) = newHolder;
290  }
291  }
292  }
293 
295 
296  // Number of products in the Principal.
297  // For products in an input file and not yet read in due to delayed read,
298  // this routine assumes a real product is there.
299  size_t Principal::size() const {
300  size_t size = 0U;
301  for (auto const& prod : *this) {
302  if (prod->singleProduct() && // Not a NoProcessProductResolver
303  !prod->productUnavailable() && !prod->unscheduledWasNotRun() && !prod->branchDescription().dropped()) {
304  ++size;
305  }
306  }
307  return size;
308  }
309 
310  // adjust provenance for input products after new input file has been merged
312  ProductRegistry::ProductList const& prodsList = reg.productList();
313  for (auto const& prod : prodsList) {
314  BranchDescription const& bd = prod.second;
315  if (!bd.produced() && (bd.branchType() == branchType_)) {
316  auto cbd = std::make_shared<BranchDescription const>(bd);
317  auto phb = getExistingProduct(cbd->branchID());
318  if (phb == nullptr || phb->branchDescription().branchName() != cbd->branchName()) {
319  return false;
320  }
321  phb->resetBranchDescription(cbd);
322  }
323  }
324  return true;
325  }
326 
327  void Principal::addScheduledProduct(std::shared_ptr<BranchDescription const> bd) {
328  auto phb = std::make_unique<PuttableProductResolver>(std::move(bd));
330  }
331 
332  void Principal::addSourceProduct(std::shared_ptr<BranchDescription const> bd) {
333  auto phb = std::make_unique<PuttableProductResolver>(std::move(bd));
335  }
336 
337  void Principal::addInputProduct(std::shared_ptr<BranchDescription const> bd) {
338  addProductOrThrow(std::make_unique<InputProductResolver>(std::move(bd)));
339  }
340 
341  void Principal::addUnscheduledProduct(std::shared_ptr<BranchDescription const> bd) {
342  addProductOrThrow(std::make_unique<UnscheduledProductResolver>(std::move(bd)));
343  }
344 
345  void Principal::addAliasedProduct(std::shared_ptr<BranchDescription const> bd) {
346  ProductResolverIndex index = preg_->indexFrom(bd->originalBranchID());
347  assert(index != ProductResolverIndexInvalid);
348 
349  addProductOrThrow(std::make_unique<AliasProductResolver>(
350  std::move(bd), dynamic_cast<DataManagingOrAliasProductResolver&>(*productResolvers_[index])));
351  }
352 
353  void Principal::addSwitchProducerProduct(std::shared_ptr<BranchDescription const> bd) {
354  ProductResolverIndex index = preg_->indexFrom(bd->switchAliasForBranchID());
355  assert(index != ProductResolverIndexInvalid);
356 
357  addProductOrThrow(std::make_unique<SwitchProducerProductResolver>(
358  std::move(bd), dynamic_cast<DataManagingOrAliasProductResolver&>(*productResolvers_[index])));
359  }
360 
361  void Principal::addSwitchAliasProduct(std::shared_ptr<BranchDescription const> bd) {
362  ProductResolverIndex index = preg_->indexFrom(bd->switchAliasForBranchID());
363  assert(index != ProductResolverIndexInvalid);
364 
365  addProductOrThrow(std::make_unique<SwitchAliasProductResolver>(
366  std::move(bd), dynamic_cast<DataManagingOrAliasProductResolver&>(*productResolvers_[index])));
367  }
368 
369  void Principal::addParentProcessProduct(std::shared_ptr<BranchDescription const> bd) {
370  addProductOrThrow(std::make_unique<ParentProcessProductResolver>(std::move(bd)));
371  }
372 
373  // "Zero" the principal so it can be reused for another Event.
375  //We do not clear the product history information
376  // because it rarely changes and recalculating takes
377  // time.
378  reader_ = nullptr;
379  for (auto& prod : *this) {
380  prod->resetProductData();
381  }
382  }
383 
384  void Principal::deleteProduct(BranchID const& id) const {
385  auto phb = getExistingProduct(id);
386  assert(nullptr != phb);
387  phb->unsafe_deleteProduct();
388  }
389 
391  applyToResolvers([&iConfigure](ProductResolverBase* iResolver) { iResolver->setupUnscheduled(iConfigure); });
392  }
393 
394  // Set the principal for the Event, Lumi, or Run.
396  ProcessHistoryRegistry const& processHistoryRegistry,
398  //increment identifier here since clearPrincipal isn't called for Run/Lumi
400  if (reader) {
401  reader_ = reader;
402  }
403 
404  if (historyAppender_ && productRegistry().anyProductProduced()) {
405  if ((not processHistoryPtr_) || (processHistoryIDBeforeConfig_ != hist)) {
406  processHistoryPtr_ = historyAppender_->appendToProcessHistory(
407  hist, processHistoryRegistry.getMapped(hist), *processConfiguration_);
408  processHistoryID_ = processHistoryPtr_->id();
410  }
411  } else {
412  std::shared_ptr<ProcessHistory const> inputProcessHistory;
413  if ((not processHistoryPtr_) || (processHistoryIDBeforeConfig_ != hist)) {
414  if (hist.isValid()) {
415  //does not own the pointer
416  auto noDel = [](void const*) {};
417  inputProcessHistory = std::shared_ptr<ProcessHistory const>(processHistoryRegistry.getMapped(hist), noDel);
418  if (inputProcessHistory.get() == nullptr) {
419  throw Exception(errors::LogicError) << "Principal::fillPrincipal\n"
420  << "Input ProcessHistory not found in registry\n"
421  << "Contact a Framework developer\n";
422  }
423  } else {
424  //Since this is static we don't want it deleted
425  inputProcessHistory = std::shared_ptr<ProcessHistory const>(&s_emptyProcessHistory, [](void const*) {});
426  //no need to do any ordering since it is empty
428  }
430  processHistoryPtr_ = inputProcessHistory;
432  }
433  }
434 
436  std::vector<std::string> const& lookupProcessNames = productLookup_->lookupProcessNames();
437  lookupProcessOrder_.assign(lookupProcessNames.size(), 0);
438  unsigned int k = 0;
439 
440  // We loop over processes in reverse order of the ProcessHistory.
441  // If any entries in the product lookup tables are associated with
442  // the process we add it to the vector of processes in the order
443  // the lookup should be performed. There is one exception though,
444  // We start with the current process even if it is not in the ProcessHistory.
445  // The current process might be needed but not be in the process
446  // history if all the products produced in the current process are
447  // transient.
448  {
449  auto nameIterCurrentProcess =
450  std::find(lookupProcessNames.begin(), lookupProcessNames.end(), processConfiguration_->processName());
451  if (nameIterCurrentProcess != lookupProcessNames.end()) {
452  lookupProcessOrder_.at(k) = nameIterCurrentProcess - lookupProcessNames.begin();
453  ++k;
454  }
455  }
456 
457  // We just looked for the current process so skip it if
458  // it is in the ProcessHistory.
459  auto iter = processHistoryPtr_->rbegin();
460  if (iter->processName() == processConfiguration_->processName()) {
461  ++iter;
462  }
463 
464  for (auto iEnd = processHistoryPtr_->rend(); iter != iEnd; ++iter) {
465  auto nameIter = std::find(lookupProcessNames.begin(), lookupProcessNames.end(), iter->processName());
466  if (nameIter == lookupProcessNames.end()) {
467  continue;
468  }
469  lookupProcessOrder_.at(k) = nameIter - lookupProcessNames.begin();
470  ++k;
471  }
473  }
474  }
475 
477  return const_cast<ProductResolverBase*>(const_cast<const Principal*>(this)->getExistingProduct(branchID));
478  }
479 
481  ProductResolverIndex index = preg_->indexFrom(branchID);
482  assert(index != ProductResolverIndexInvalid);
483  return productResolvers_.at(index).get();
484  }
485 
487  auto phb = getExistingProduct(productResolver.branchDescription().branchID());
488  if (nullptr != phb && BranchKey(productResolver.branchDescription()) != BranchKey(phb->branchDescription())) {
489  BranchDescription const& newProduct = phb->branchDescription();
490  BranchDescription const& existing = productResolver.branchDescription();
491  if (newProduct.branchName() != existing.branchName() && newProduct.branchID() == existing.branchID()) {
492  throw cms::Exception("HashCollision")
493  << "Principal::getExistingProduct\n"
494  << " Branch " << newProduct.branchName() << " has same branch ID as branch " << existing.branchName()
495  << "\n"
496  << "Workaround: change process name or product instance name of " << newProduct.branchName() << "\n";
497  } else {
498  assert(nullptr == phb || BranchKey(productResolver.branchDescription()) == BranchKey(phb->branchDescription()));
499  }
500  }
501  return phb;
502  }
503 
504  void Principal::addProduct_(std::unique_ptr<ProductResolverBase> productResolver) {
505  BranchDescription const& bd = productResolver->branchDescription();
506  assert(!bd.className().empty());
507  assert(!bd.friendlyClassName().empty());
508  assert(!bd.moduleLabel().empty());
509  assert(!bd.processName().empty());
510  SharedProductPtr phb(productResolver.release());
511 
512  ProductResolverIndex index = preg_->indexFrom(bd.branchID());
513  assert(index != ProductResolverIndexInvalid);
514  productResolvers_[index] = phb;
515  }
516 
517  void Principal::addProductOrThrow(std::unique_ptr<ProductResolverBase> productResolver) {
518  ProductResolverBase const* phb = getExistingProduct(*productResolver);
519  if (phb != nullptr) {
520  BranchDescription const& bd = productResolver->branchDescription();
521  throw Exception(errors::InsertFailure, "AlreadyPresent")
522  << "addProductOrThrow: Problem found while adding product, "
523  << "product already exists for (" << bd.friendlyClassName() << "," << bd.moduleLabel() << ","
524  << bd.productInstanceName() << "," << bd.processName() << ")\n";
525  }
526  addProduct_(std::move(productResolver));
527  }
528 
530  ProductResolverIndex index = preg_->indexFrom(bid);
531  if (index == ProductResolverIndexInvalid) {
532  return ConstProductResolverPtr();
533  }
534  return getProductResolverByIndex(index);
535  }
536 
539  return phb;
540  }
541 
543  TypeID const& typeID,
544  InputTag const& inputTag,
545  EDConsumerBase const* consumer,
547  ModuleCallingContext const* mcc) const {
548  ProductData const* result = findProductByLabel(kindOfType, typeID, inputTag, consumer, sra, mcc);
549  if (result == nullptr) {
550  return BasicHandle(makeHandleExceptionFactory([=]() -> std::shared_ptr<cms::Exception> {
551  return makeNotFoundException(
552  "getByLabel",
553  kindOfType,
554  typeID,
555  inputTag.label(),
556  inputTag.instance(),
558  }));
559  }
560  return BasicHandle(result->wrapper(), &(result->provenance()));
561  }
562 
564  TypeID const& typeID,
565  std::string const& label,
566  std::string const& instance,
567  std::string const& process,
568  EDConsumerBase const* consumer,
570  ModuleCallingContext const* mcc) const {
571  ProductData const* result = findProductByLabel(kindOfType, typeID, label, instance, process, consumer, sra, mcc);
572  if (result == nullptr) {
573  return BasicHandle(makeHandleExceptionFactory([=]() -> std::shared_ptr<cms::Exception> {
574  return makeNotFoundException("getByLabel", kindOfType, typeID, label, instance, process);
575  }));
576  }
577  return BasicHandle(result->wrapper(), &(result->provenance()));
578  }
579 
581  TypeID const&,
583  bool skipCurrentProcess,
584  bool& ambiguous,
586  ModuleCallingContext const* mcc) const {
587  assert(index != ProductResolverIndexInvalid);
588  auto& productResolver = productResolvers_[index];
589  assert(nullptr != productResolver.get());
590  auto resolution = productResolver->resolveProduct(*this, skipCurrentProcess, sra, mcc);
591  if (resolution.isAmbiguous()) {
592  ambiguous = true;
593  //The caller is looking explicitly for this case
594  // and uses the extra data at the caller to setup the exception
595  return BasicHandle::makeInvalid();
596  }
597  auto productData = resolution.data();
598  if (productData == nullptr) {
599  //The caller is looking explicitly for this case
600  // and uses the extra data at the caller to setup the exception
601  return BasicHandle::makeInvalid();
602  }
603  return BasicHandle(productData->wrapper(), &(productData->provenance()));
604  }
605 
608  bool skipCurrentProcess,
609  ServiceToken const& token,
610  ModuleCallingContext const* mcc) const {
611  auto const& productResolver = productResolvers_.at(index);
612  assert(nullptr != productResolver.get());
613  productResolver->prefetchAsync(task, *this, skipCurrentProcess, token, nullptr, mcc);
614  }
615 
616  void Principal::getManyByType(TypeID const& typeID,
618  EDConsumerBase const* consumer,
620  ModuleCallingContext const* mcc) const {
621  assert(results.empty());
622 
623  if (UNLIKELY(consumer and (not consumer->registeredToConsumeMany(typeID, branchType())))) {
624  failedToRegisterConsumesMany(typeID);
625  }
626 
627  // This finds the indexes to all the ProductResolver's matching the type
629 
630  if (matches.numberOfMatches() == 0) {
631  return;
632  }
633 
634  results.reserve(matches.numberOfMatches());
635 
636  // Loop over the ProductResolvers. Add the products that are actually
637  // present into the results. This will also trigger delayed reading,
638  // on demand production, and check for deleted products as appropriate.
639 
640  // Over the years the code that uses getManyByType has grown to depend
641  // on the ordering of the results. The order originally was just an
642  // accident of how previous versions of the code were written, but
643  // here we have to go through some extra effort to preserve that ordering.
644 
645  // We build a list of holders that match a particular label and instance.
646  // When that list is complete we call findProducts, which loops over
647  // that list in reverse order of the ProcessHistory (starts with the
648  // most recent). Then we clear the list and repeat this until all the
649  // matching label and instance subsets have been dealt with.
650 
651  // Note that the function isFullyResolved returns true for the ProductResolvers
652  // that are associated with an empty process name. Those are the ones that
653  // know how to search for the most recent process name matching
654  // a label and instance. We do not need these for getManyByType and
655  // skip them. In addition to skipping them, we make use of the fact
656  // that they mark the beginning of each subset of holders with the same
657  // label and instance. They tell us when to call findProducts.
658 
659  std::vector<ProductResolverBase const*> holders;
660 
661  for (unsigned int i = 0; i < matches.numberOfMatches(); ++i) {
662  ProductResolverIndex index = matches.index(i);
663 
664  if (!matches.isFullyResolved(i)) {
665  if (!holders.empty()) {
666  // Process the ones with a particular module label and instance
667  findProducts(holders, typeID, results, sra, mcc);
668  holders.clear();
669  }
670  } else {
671  ProductResolverBase const* productResolver = productResolvers_.at(index).get();
672  assert(productResolver);
673  holders.push_back(productResolver);
674  }
675  }
676  // Do not miss the last subset of products
677  if (!holders.empty()) {
678  findProducts(holders, typeID, results, sra, mcc);
679  }
680  return;
681  }
682 
683  void Principal::findProducts(std::vector<ProductResolverBase const*> const& holders,
684  TypeID const&,
687  ModuleCallingContext const* mcc) const {
688  for (auto iter = processHistoryPtr_->rbegin(), iEnd = processHistoryPtr_->rend(); iter != iEnd; ++iter) {
689  std::string const& process = iter->processName();
690  for (auto productResolver : holders) {
691  BranchDescription const& bd = productResolver->branchDescription();
692  if (process == bd.processName()) {
693  // Ignore aliases to avoid matching the same product multiple times.
694  if (bd.isAnyAlias()) {
695  continue;
696  }
697 
698  ProductData const* productData = productResolver->resolveProduct(*this, false, sra, mcc).data();
699  if (productData) {
700  // Skip product if not available.
701  results.emplace_back(productData->wrapper(), &(productData->provenance()));
702  }
703  }
704  }
705  }
706  }
707 
709  TypeID const& typeID,
710  InputTag const& inputTag,
711  EDConsumerBase const* consumer,
713  ModuleCallingContext const* mcc) const {
714  bool skipCurrentProcess = inputTag.willSkipCurrentProcess();
715 
717 
718  if (index == ProductResolverIndexInvalid) {
719  char const* processName = inputTag.process().c_str();
720  if (skipCurrentProcess) {
721  processName = "\0";
722  } else if (inputTag.process() == InputTag::kCurrentProcess) {
723  processName = processConfiguration_->processName().c_str();
724  }
725 
726  index =
727  productLookup().index(kindOfType, typeID, inputTag.label().c_str(), inputTag.instance().c_str(), processName);
728 
729  if (index == ProductResolverIndexAmbiguous) {
730  throwAmbiguousException("findProductByLabel",
731  typeID,
732  inputTag.label(),
733  inputTag.instance(),
735  } else if (index == ProductResolverIndexInvalid) {
736  return nullptr;
737  }
738  inputTag.tryToCacheIndex(index, typeID, branchType(), &productRegistry());
739  }
740  if (UNLIKELY(consumer and (not consumer->registeredToConsume(index, skipCurrentProcess, branchType())))) {
741  failedToRegisterConsumes(kindOfType,
742  typeID,
743  inputTag.label(),
744  inputTag.instance(),
746  }
747 
748  auto const& productResolver = productResolvers_[index];
749 
750  auto resolution = productResolver->resolveProduct(*this, skipCurrentProcess, sra, mcc);
751  if (resolution.isAmbiguous()) {
752  throwAmbiguousException("findProductByLabel",
753  typeID,
754  inputTag.label(),
755  inputTag.instance(),
757  }
758  return resolution.data();
759  }
760 
762  TypeID const& typeID,
763  std::string const& label,
764  std::string const& instance,
765  std::string const& process,
766  EDConsumerBase const* consumer,
768  ModuleCallingContext const* mcc) const {
770  productLookup().index(kindOfType, typeID, label.c_str(), instance.c_str(), process.c_str());
771 
772  if (index == ProductResolverIndexAmbiguous) {
773  throwAmbiguousException("findProductByLabel", typeID, label, instance, process);
774  } else if (index == ProductResolverIndexInvalid) {
775  return nullptr;
776  }
777 
778  if (UNLIKELY(consumer and (not consumer->registeredToConsume(index, false, branchType())))) {
779  failedToRegisterConsumes(kindOfType, typeID, label, instance, process);
780  }
781 
782  auto const& productResolver = productResolvers_[index];
783 
784  auto resolution = productResolver->resolveProduct(*this, false, sra, mcc);
785  if (resolution.isAmbiguous()) {
786  throwAmbiguousException("findProductByLabel", typeID, label, instance, process);
787  }
788  return resolution.data();
789  }
790 
792  InputTag const& tag,
793  ModuleCallingContext const* mcc) const {
794  ProductData const* productData = findProductByLabel(PRODUCT_TYPE, typeID, tag, nullptr, nullptr, mcc);
795  return productData;
796  }
797 
800  if (phb == nullptr) {
802  }
803 
804  if (phb->unscheduledWasNotRun()) {
805  if (not phb->resolveProduct(*this, false, nullptr, mcc).data()) {
806  throwProductNotFoundException("getProvenance(onDemand)", errors::ProductNotFound, bid);
807  }
808  }
809  return *phb->provenance();
810  }
811 
812  // This one is mostly for test printout purposes
813  // No attempt to trigger on demand execution
814  // Skips provenance when the EDProduct is not there
815  void Principal::getAllProvenance(std::vector<Provenance const*>& provenances) const {
816  provenances.clear();
817  for (auto const& productResolver : *this) {
818  if (productResolver->singleProduct() && productResolver->provenanceAvailable() &&
819  !productResolver->branchDescription().isAnyAlias()) {
820  // We do not attempt to get the event/lumi/run status from the provenance,
821  // because the per event provenance may have been dropped.
822  if (productResolver->provenance()->branchDescription().present()) {
823  provenances.push_back(productResolver->provenance());
824  }
825  }
826  }
827  }
828 
829  // This one is also mostly for test printout purposes
830  // No attempt to trigger on demand execution
831  // Skips provenance for dropped branches.
832  void Principal::getAllStableProvenance(std::vector<StableProvenance const*>& provenances) const {
833  provenances.clear();
834  for (auto const& productResolver : *this) {
835  if (productResolver->singleProduct() && !productResolver->branchDescription().isAnyAlias()) {
836  if (productResolver->stableProvenance()->branchDescription().present()) {
837  provenances.push_back(productResolver->stableProvenance());
838  }
839  }
840  }
841  }
842 
843  void Principal::recombine(Principal& other, std::vector<BranchID> const& bids) {
844  for (auto& prod : bids) {
845  ProductResolverIndex index = preg_->indexFrom(prod);
846  assert(index != ProductResolverIndexInvalid);
847  ProductResolverIndex indexO = other.preg_->indexFrom(prod);
848  assert(indexO != ProductResolverIndexInvalid);
850  }
851  reader_->mergeReaders(other.reader());
852  }
853 
854  WrapperBase const* Principal::getIt(ProductID const&) const {
855  assert(false);
856  return nullptr;
857  }
858 
859  WrapperBase const* Principal::getThinnedProduct(ProductID const&, unsigned int&) const {
860  assert(false);
861  return nullptr;
862  }
863 
865  std::vector<WrapperBase const*>&,
866  std::vector<unsigned int>&) const {
867  assert(false);
868  }
869 
870  void Principal::putOrMerge(std::unique_ptr<WrapperBase> prod, ProductResolverBase const* phb) const {
871  phb->putOrMergeProduct(std::move(prod));
872  }
873 
874  void Principal::putOrMerge(BranchDescription const& bd, std::unique_ptr<WrapperBase> edp) const {
875  if (edp.get() == nullptr) {
876  throw edm::Exception(edm::errors::InsertFailure, "Null Pointer")
877  << "put: Cannot put because unique_ptr to product is null."
878  << "\n";
879  }
880  auto phb = getExistingProduct(bd.branchID());
881  assert(phb);
882  // ProductResolver assumes ownership
883  putOrMerge(std::move(edp), phb);
884  }
885 
887  if (preg_->getNextIndexValue(branchType_) != productResolvers_.size()) {
888  productResolvers_.resize(preg_->getNextIndexValue(branchType_));
889  for (auto const& prod : preg_->productList()) {
890  BranchDescription const& bd = prod.second;
891  if (bd.branchType() == branchType_) {
892  ProductResolverIndex index = preg_->indexFrom(bd.branchID());
893  assert(index != ProductResolverIndexInvalid);
894  if (!productResolvers_[index]) {
895  // no product holder. Must add one. The new entry must be an input product holder.
896  assert(!bd.produced());
897  auto cbd = std::make_shared<BranchDescription const>(bd);
898  addInputProduct(cbd);
899  }
900  }
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
BranchType branchType_
Definition: Principal.h:282
size
Write out results.
ProductResolverIndex index(unsigned int i) const
static ProcessHistory const s_emptyProcessHistory
Definition: Principal.cc:34
ProductRegistry const & productRegistry() const
Definition: Principal.h:146
Provenance const & provenance() const
Definition: ProductData.h:32
void clearPrincipal()
Definition: Principal.cc:374
std::string const & branchName() const
size_t size() const
Definition: Principal.cc:299
DelayedReader * reader_
Definition: Principal.h:280
BranchType const & branchType() const
ProcessHistoryID processHistoryIDBeforeConfig_
Definition: Principal.h:263
void setupUnscheduled(UnscheduledConfigurator const &)
Definition: Principal.cc:390
unsigned int ProductResolverIndex
bool getMapped(ProcessHistoryID const &key, ProcessHistory &value) const
static std::string const source("source")
ProductResolverCollection productResolvers_
Definition: Principal.h:268
std::shared_ptr< ProcessHistory const > processHistoryPtr_
Definition: Principal.h:260
static PFTauRenderPlugin instance
std::shared_ptr< ProductResolverBase > SharedProductPtr
Definition: Principal.h:68
void addProduct_(std::unique_ptr< ProductResolverBase > phb)
Definition: Principal.cc:504
static std::atomic< Principal::CacheIdentifier_t > s_nextIdentifier
Definition: Principal.cc:117
std::map< BranchKey, BranchDescription > ProductList
static Principal::CacheIdentifier_t nextIdentifier()
Definition: Principal.cc:118
ProcessHistoryID processHistoryID_
Definition: Principal.h:262
void mergeReaders(DelayedReader *other)
Definition: DelayedReader.h:36
ProductResolverBase * getExistingProduct(BranchID const &branchID)
Definition: Principal.cc:476
virtual void setupUnscheduled(UnscheduledConfigurator const &)
void getAllProvenance(std::vector< Provenance const * > &provenances) const
Definition: Principal.cc:815
void applyToResolvers(F iFunc)
Definition: Principal.h:214
void getAllStableProvenance(std::vector< StableProvenance const * > &provenances) const
Definition: Principal.cc:832
~Principal() override
Definition: Principal.cc:294
Provenance getProvenance(BranchID const &bid, ModuleCallingContext const *mcc) const
Definition: Principal.cc:798
WrapperBase const * wrapper() const
Definition: ProductData.h:34
void getThinnedProducts(ProductID const &, std::vector< WrapperBase const * > &, std::vector< unsigned int > &) const override
Definition: Principal.cc:864
std::string const & processName() const
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
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
void addInputProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:337
edm::propagate_const< HistoryAppender * > historyAppender_
Definition: Principal.h:287
void readAllFromSourceAndMergeImmediately(MergeableRunProductMetadata const *mergeableRunProductMetadata=0)
Definition: Principal.cc:906
void prefetchAsync(WaitingTask *waitTask, ProductResolverIndex index, bool skipCurrentProcess, ServiceToken const &token, ModuleCallingContext const *mcc) const
Definition: Principal.cc:606
BranchType
Definition: BranchType.h:11
ProductResolverIndex indexFor(TypeID const &typeID, BranchType branchType, void const *productRegistry) const
Definition: InputTag.cc:177
void putOrMergeProduct(std::unique_ptr< WrapperBase > edp, MergeableRunProductMetadata const *mergeableRunProductMetadata=nullptr) const
void tryToCacheIndex(ProductResolverIndex index, TypeID const &typeID, BranchType branchType, void const *productRegistry) const
Definition: InputTag.cc:193
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::string const & processName() const
ProductList const & productList() const
std::vector< unsigned int > lookupProcessOrder_
Definition: Principal.h:275
char const * label
BasicHandle getByLabel(KindOfType kindOfType, TypeID const &typeID, InputTag const &inputTag, EDConsumerBase const *consumes, SharedResourcesAcquirer *sra, ModuleCallingContext const *mcc) const
Definition: Principal.cc:542
void addScheduledProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:327
std::string const & className() const
ProductData const * findProductByTag(TypeID const &typeID, InputTag const &tag, ModuleCallingContext const *mcc) const
Definition: Principal.cc:791
std::shared_ptr< ProductResolverIndexHelper const > productLookup_
Definition: Principal.h:273
std::string const & moduleLabel() const
void addProductOrThrow(std::unique_ptr< ProductResolverBase > phb)
Definition: Principal.cc:517
std::shared_ptr< ProductRegistry const > preg_
Definition: Principal.h:272
std::string const & productInstanceName() const
bool registeredToConsume(ProductResolverIndex, bool, BranchType) const
CacheIdentifier_t cacheIdentifier_
Definition: Principal.h:289
BranchType const & branchType() const
Definition: Principal.h:180
std::shared_ptr< HandleExceptionFactory > makeHandleExceptionFactory(T &&iFunctor)
void putOrMerge(BranchDescription const &bd, std::unique_ptr< WrapperBase > edp) const
Definition: Principal.cc:874
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
void addSourceProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:332
Matches relatedIndexes(KindOfType kindOfType, TypeID const &typeID, char const *moduleLabel, char const *instance) const
ProcessHistoryID orderProcessHistoryID_
Definition: Principal.h:276
static const std::string kCurrentProcess
Definition: InputTag.h:54
std::string const & friendlyClassName() const
BranchID const & branchID() const
std::shared_ptr< T > & get_underlying_safe(propagate_const< std::shared_ptr< T >> &iP)
void addParentProcessProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:369
string ranges
Definition: diffTwoXMLs.py:79
DelayedReader * reader() const
Definition: Principal.h:186
bool willSkipCurrentProcess() const
Definition: InputTag.h:42
static BasicHandle makeInvalid()
Definition: BasicHandle.h:92
bool registeredToConsumeMany(TypeID const &, BranchType) const
void addSwitchAliasProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:361
void addUnscheduledProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:341
WrapperBase const * getIt(ProductID const &) const override
Definition: Principal.cc:854
ProductResolverIndexHelper const & productLookup() const
Definition: Principal.h:148
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:64
std::string const & label() const
Definition: InputTag.h:36
void findProducts(std::vector< ProductResolverBase const * > const &holders, TypeID const &typeID, BasicHandleVec &results, SharedResourcesAcquirer *sra, ModuleCallingContext const *mcc) const
Definition: Principal.cc:683
std::string const & process() const
Definition: InputTag.h:40
HLT enums.
unsigned long CacheIdentifier_t
Definition: Principal.h:183
WrapperBase const * getThinnedProduct(ProductID const &, unsigned int &) const override
Definition: Principal.cc:859
bool isValid() const
Definition: Hash.h:141
bool adjustToNewProductRegistry(ProductRegistry const &reg)
Definition: Principal.cc:311
BranchDescription const & branchDescription() const
ProductData const * findProductByLabel(KindOfType kindOfType, TypeID const &typeID, InputTag const &inputTag, EDConsumerBase const *consumer, SharedResourcesAcquirer *sra, ModuleCallingContext const *mcc) const
Definition: Principal.cc:708
ConstProductResolverPtr getProductResolverByIndex(ProductResolverIndex const &oid) const
Definition: Principal.cc:537
void addSwitchProducerProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:353
ConstProductResolverPtr getProductResolver(BranchID const &oid) const
Definition: Principal.cc:529
void resetBranchDescription(std::shared_ptr< BranchDescription const > bd)
void adjustIndexesAfterProductRegistryAddition()
Definition: Principal.cc:886
static void throwProductNotFoundException(char const *where, errors::ErrorCodes error, BranchID const &bid)
Definition: Principal.cc:48
BasicHandle getByToken(KindOfType kindOfType, TypeID const &typeID, ProductResolverIndex index, bool skipCurrentProcess, bool &ambiguous, SharedResourcesAcquirer *sra, ModuleCallingContext const *mcc) const
Definition: Principal.cc:580
#define UNLIKELY(x)
Definition: Likely.h:21
static std::string appendCurrentProcessIfAlias(std::string const &processFromInputTag, std::string const &currentProcess)
Definition: Principal.cc:36
void addAliasedProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:345
void fillPrincipal(ProcessHistoryID const &hist, ProcessHistoryRegistry const &phr, DelayedReader *reader)
Definition: Principal.cc:395
void recombine(Principal &other, std::vector< BranchID > const &bids)
Definition: Principal.cc:843
std::string const & instance() const
Definition: InputTag.h:37
ProcessConfiguration const * processConfiguration_
Definition: Principal.h:265
def move(src, dest)
Definition: eostools.py:511
ProductResolverIndex index(KindOfType kindOfType, TypeID const &typeID, char const *moduleLabel, char const *instance, char const *process=nullptr) const
std::vector< BasicHandle > BasicHandleVec
Definition: Principal.h:65
void getManyByType(TypeID const &typeID, BasicHandleVec &results, EDConsumerBase const *consumes, SharedResourcesAcquirer *sra, ModuleCallingContext const *mcc) const
Definition: Principal.cc:616
void deleteProduct(BranchID const &id) const
Definition: Principal.cc:384