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 i = 0; i < matchingHolders.size(); ++i) {
240  if ((not ambiguous[i]) and ProductResolverIndexInvalid != matchingHolders[i] and
241  productResolvers_[matchingHolders[i]]->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  auto nameIter =
449  std::find(lookupProcessNames.begin(), lookupProcessNames.end(), processConfiguration_->processName());
450  if (nameIter != lookupProcessNames.end()) {
451  lookupProcessOrder_.at(k) = nameIter - lookupProcessNames.begin();
452  ++k;
453  }
454 
455  // We just looked for the current process so skip it if
456  // it is in the ProcessHistory.
457  auto iter = processHistoryPtr_->rbegin();
458  if (iter->processName() == processConfiguration_->processName()) {
459  ++iter;
460  }
461 
462  for (auto iEnd = processHistoryPtr_->rend(); iter != iEnd; ++iter) {
463  auto nameIter = std::find(lookupProcessNames.begin(), lookupProcessNames.end(), iter->processName());
464  if (nameIter == lookupProcessNames.end()) {
465  continue;
466  }
467  lookupProcessOrder_.at(k) = nameIter - lookupProcessNames.begin();
468  ++k;
469  }
471  }
472  }
473 
475  return const_cast<ProductResolverBase*>(const_cast<const Principal*>(this)->getExistingProduct(branchID));
476  }
477 
479  ProductResolverIndex index = preg_->indexFrom(branchID);
480  assert(index != ProductResolverIndexInvalid);
481  return productResolvers_.at(index).get();
482  }
483 
485  auto phb = getExistingProduct(productResolver.branchDescription().branchID());
486  if (nullptr != phb && BranchKey(productResolver.branchDescription()) != BranchKey(phb->branchDescription())) {
487  BranchDescription const& newProduct = phb->branchDescription();
488  BranchDescription const& existing = productResolver.branchDescription();
489  if (newProduct.branchName() != existing.branchName() && newProduct.branchID() == existing.branchID()) {
490  throw cms::Exception("HashCollision")
491  << "Principal::getExistingProduct\n"
492  << " Branch " << newProduct.branchName() << " has same branch ID as branch " << existing.branchName()
493  << "\n"
494  << "Workaround: change process name or product instance name of " << newProduct.branchName() << "\n";
495  } else {
496  assert(nullptr == phb || BranchKey(productResolver.branchDescription()) == BranchKey(phb->branchDescription()));
497  }
498  }
499  return phb;
500  }
501 
502  void Principal::addProduct_(std::unique_ptr<ProductResolverBase> productResolver) {
503  BranchDescription const& bd = productResolver->branchDescription();
504  assert(!bd.className().empty());
505  assert(!bd.friendlyClassName().empty());
506  assert(!bd.moduleLabel().empty());
507  assert(!bd.processName().empty());
508  SharedProductPtr phb(productResolver.release());
509 
510  ProductResolverIndex index = preg_->indexFrom(bd.branchID());
511  assert(index != ProductResolverIndexInvalid);
512  productResolvers_[index] = phb;
513  }
514 
515  void Principal::addProductOrThrow(std::unique_ptr<ProductResolverBase> productResolver) {
516  ProductResolverBase const* phb = getExistingProduct(*productResolver);
517  if (phb != nullptr) {
518  BranchDescription const& bd = productResolver->branchDescription();
519  throw Exception(errors::InsertFailure, "AlreadyPresent")
520  << "addProductOrThrow: Problem found while adding product, "
521  << "product already exists for (" << bd.friendlyClassName() << "," << bd.moduleLabel() << ","
522  << bd.productInstanceName() << "," << bd.processName() << ")\n";
523  }
524  addProduct_(std::move(productResolver));
525  }
526 
528  ProductResolverIndex index = preg_->indexFrom(bid);
529  if (index == ProductResolverIndexInvalid) {
530  return ConstProductResolverPtr();
531  }
532  return getProductResolverByIndex(index);
533  }
534 
537  return phb;
538  }
539 
541  TypeID const& typeID,
542  InputTag const& inputTag,
543  EDConsumerBase const* consumer,
545  ModuleCallingContext const* mcc) const {
546  ProductData const* result = findProductByLabel(kindOfType, typeID, inputTag, consumer, sra, mcc);
547  if (result == nullptr) {
548  return BasicHandle(makeHandleExceptionFactory([=]() -> std::shared_ptr<cms::Exception> {
549  return makeNotFoundException(
550  "getByLabel",
551  kindOfType,
552  typeID,
553  inputTag.label(),
554  inputTag.instance(),
556  }));
557  }
558  return BasicHandle(result->wrapper(), &(result->provenance()));
559  }
560 
562  TypeID const& typeID,
563  std::string const& label,
564  std::string const& instance,
565  std::string const& process,
566  EDConsumerBase const* consumer,
568  ModuleCallingContext const* mcc) const {
569  ProductData const* result = findProductByLabel(kindOfType, typeID, label, instance, process, consumer, sra, mcc);
570  if (result == nullptr) {
571  return BasicHandle(makeHandleExceptionFactory([=]() -> std::shared_ptr<cms::Exception> {
572  return makeNotFoundException("getByLabel", kindOfType, typeID, label, instance, process);
573  }));
574  }
575  return BasicHandle(result->wrapper(), &(result->provenance()));
576  }
577 
579  TypeID const&,
581  bool skipCurrentProcess,
582  bool& ambiguous,
584  ModuleCallingContext const* mcc) const {
585  assert(index != ProductResolverIndexInvalid);
586  auto& productResolver = productResolvers_[index];
587  assert(nullptr != productResolver.get());
588  auto resolution = productResolver->resolveProduct(*this, skipCurrentProcess, sra, mcc);
589  if (resolution.isAmbiguous()) {
590  ambiguous = true;
591  //The caller is looking explicitly for this case
592  // and uses the extra data at the caller to setup the exception
593  return BasicHandle::makeInvalid();
594  }
595  auto productData = resolution.data();
596  if (productData == nullptr) {
597  //The caller is looking explicitly for this case
598  // and uses the extra data at the caller to setup the exception
599  return BasicHandle::makeInvalid();
600  }
601  return BasicHandle(productData->wrapper(), &(productData->provenance()));
602  }
603 
606  bool skipCurrentProcess,
607  ServiceToken const& token,
608  ModuleCallingContext const* mcc) const {
609  auto const& productResolver = productResolvers_.at(index);
610  assert(nullptr != productResolver.get());
611  productResolver->prefetchAsync(task, *this, skipCurrentProcess, token, nullptr, mcc);
612  }
613 
614  void Principal::getManyByType(TypeID const& typeID,
616  EDConsumerBase const* consumer,
618  ModuleCallingContext const* mcc) const {
619  assert(results.empty());
620 
621  if (UNLIKELY(consumer and (not consumer->registeredToConsumeMany(typeID, branchType())))) {
622  failedToRegisterConsumesMany(typeID);
623  }
624 
625  // This finds the indexes to all the ProductResolver's matching the type
627 
628  if (matches.numberOfMatches() == 0) {
629  return;
630  }
631 
632  results.reserve(matches.numberOfMatches());
633 
634  // Loop over the ProductResolvers. Add the products that are actually
635  // present into the results. This will also trigger delayed reading,
636  // on demand production, and check for deleted products as appropriate.
637 
638  // Over the years the code that uses getManyByType has grown to depend
639  // on the ordering of the results. The order originally was just an
640  // accident of how previous versions of the code were written, but
641  // here we have to go through some extra effort to preserve that ordering.
642 
643  // We build a list of holders that match a particular label and instance.
644  // When that list is complete we call findProducts, which loops over
645  // that list in reverse order of the ProcessHistory (starts with the
646  // most recent). Then we clear the list and repeat this until all the
647  // matching label and instance subsets have been dealt with.
648 
649  // Note that the function isFullyResolved returns true for the ProductResolvers
650  // that are associated with an empty process name. Those are the ones that
651  // know how to search for the most recent process name matching
652  // a label and instance. We do not need these for getManyByType and
653  // skip them. In addition to skipping them, we make use of the fact
654  // that they mark the beginning of each subset of holders with the same
655  // label and instance. They tell us when to call findProducts.
656 
657  std::vector<ProductResolverBase const*> holders;
658 
659  for (unsigned int i = 0; i < matches.numberOfMatches(); ++i) {
660  ProductResolverIndex index = matches.index(i);
661 
662  if (!matches.isFullyResolved(i)) {
663  if (!holders.empty()) {
664  // Process the ones with a particular module label and instance
665  findProducts(holders, typeID, results, sra, mcc);
666  holders.clear();
667  }
668  } else {
669  ProductResolverBase const* productResolver = productResolvers_.at(index).get();
670  assert(productResolver);
671  holders.push_back(productResolver);
672  }
673  }
674  // Do not miss the last subset of products
675  if (!holders.empty()) {
676  findProducts(holders, typeID, results, sra, mcc);
677  }
678  return;
679  }
680 
681  void Principal::findProducts(std::vector<ProductResolverBase const*> const& holders,
682  TypeID const&,
685  ModuleCallingContext const* mcc) const {
686  for (auto iter = processHistoryPtr_->rbegin(), iEnd = processHistoryPtr_->rend(); iter != iEnd; ++iter) {
687  std::string const& process = iter->processName();
688  for (auto productResolver : holders) {
689  BranchDescription const& bd = productResolver->branchDescription();
690  if (process == bd.processName()) {
691  // Ignore aliases to avoid matching the same product multiple times.
692  if (bd.isAnyAlias()) {
693  continue;
694  }
695 
696  ProductData const* productData = productResolver->resolveProduct(*this, false, sra, mcc).data();
697  if (productData) {
698  // Skip product if not available.
699  results.emplace_back(productData->wrapper(), &(productData->provenance()));
700  }
701  }
702  }
703  }
704  }
705 
707  TypeID const& typeID,
708  InputTag const& inputTag,
709  EDConsumerBase const* consumer,
711  ModuleCallingContext const* mcc) const {
712  bool skipCurrentProcess = inputTag.willSkipCurrentProcess();
713 
715 
716  if (index == ProductResolverIndexInvalid) {
717  char const* processName = inputTag.process().c_str();
718  if (skipCurrentProcess) {
719  processName = "\0";
720  } else if (inputTag.process() == InputTag::kCurrentProcess) {
721  processName = processConfiguration_->processName().c_str();
722  }
723 
724  index =
725  productLookup().index(kindOfType, typeID, inputTag.label().c_str(), inputTag.instance().c_str(), processName);
726 
727  if (index == ProductResolverIndexAmbiguous) {
728  throwAmbiguousException("findProductByLabel",
729  typeID,
730  inputTag.label(),
731  inputTag.instance(),
733  } else if (index == ProductResolverIndexInvalid) {
734  return nullptr;
735  }
736  inputTag.tryToCacheIndex(index, typeID, branchType(), &productRegistry());
737  }
738  if (UNLIKELY(consumer and (not consumer->registeredToConsume(index, skipCurrentProcess, branchType())))) {
739  failedToRegisterConsumes(kindOfType,
740  typeID,
741  inputTag.label(),
742  inputTag.instance(),
744  }
745 
746  auto const& productResolver = productResolvers_[index];
747 
748  auto resolution = productResolver->resolveProduct(*this, skipCurrentProcess, sra, mcc);
749  if (resolution.isAmbiguous()) {
750  throwAmbiguousException("findProductByLabel",
751  typeID,
752  inputTag.label(),
753  inputTag.instance(),
755  }
756  return resolution.data();
757  }
758 
760  TypeID const& typeID,
761  std::string const& label,
762  std::string const& instance,
763  std::string const& process,
764  EDConsumerBase const* consumer,
766  ModuleCallingContext const* mcc) const {
768  productLookup().index(kindOfType, typeID, label.c_str(), instance.c_str(), process.c_str());
769 
770  if (index == ProductResolverIndexAmbiguous) {
771  throwAmbiguousException("findProductByLabel", typeID, label, instance, process);
772  } else if (index == ProductResolverIndexInvalid) {
773  return nullptr;
774  }
775 
776  if (UNLIKELY(consumer and (not consumer->registeredToConsume(index, false, branchType())))) {
777  failedToRegisterConsumes(kindOfType, typeID, label, instance, process);
778  }
779 
780  auto const& productResolver = productResolvers_[index];
781 
782  auto resolution = productResolver->resolveProduct(*this, false, sra, mcc);
783  if (resolution.isAmbiguous()) {
784  throwAmbiguousException("findProductByLabel", typeID, label, instance, process);
785  }
786  return resolution.data();
787  }
788 
790  InputTag const& tag,
791  ModuleCallingContext const* mcc) const {
792  ProductData const* productData = findProductByLabel(PRODUCT_TYPE, typeID, tag, nullptr, nullptr, mcc);
793  return productData;
794  }
795 
798  if (phb == nullptr) {
800  }
801 
802  if (phb->unscheduledWasNotRun()) {
803  if (not phb->resolveProduct(*this, false, nullptr, mcc).data()) {
804  throwProductNotFoundException("getProvenance(onDemand)", errors::ProductNotFound, bid);
805  }
806  }
807  return *phb->provenance();
808  }
809 
810  // This one is mostly for test printout purposes
811  // No attempt to trigger on demand execution
812  // Skips provenance when the EDProduct is not there
813  void Principal::getAllProvenance(std::vector<Provenance const*>& provenances) const {
814  provenances.clear();
815  for (auto const& productResolver : *this) {
816  if (productResolver->singleProduct() && productResolver->provenanceAvailable() &&
817  !productResolver->branchDescription().isAnyAlias()) {
818  // We do not attempt to get the event/lumi/run status from the provenance,
819  // because the per event provenance may have been dropped.
820  if (productResolver->provenance()->branchDescription().present()) {
821  provenances.push_back(productResolver->provenance());
822  }
823  }
824  }
825  }
826 
827  // This one is also mostly for test printout purposes
828  // No attempt to trigger on demand execution
829  // Skips provenance for dropped branches.
830  void Principal::getAllStableProvenance(std::vector<StableProvenance const*>& provenances) const {
831  provenances.clear();
832  for (auto const& productResolver : *this) {
833  if (productResolver->singleProduct() && !productResolver->branchDescription().isAnyAlias()) {
834  if (productResolver->stableProvenance()->branchDescription().present()) {
835  provenances.push_back(productResolver->stableProvenance());
836  }
837  }
838  }
839  }
840 
841  void Principal::recombine(Principal& other, std::vector<BranchID> const& bids) {
842  for (auto& prod : bids) {
843  ProductResolverIndex index = preg_->indexFrom(prod);
844  assert(index != ProductResolverIndexInvalid);
845  ProductResolverIndex indexO = other.preg_->indexFrom(prod);
846  assert(indexO != ProductResolverIndexInvalid);
848  }
849  reader_->mergeReaders(other.reader());
850  }
851 
852  WrapperBase const* Principal::getIt(ProductID const&) const {
853  assert(false);
854  return nullptr;
855  }
856 
857  WrapperBase const* Principal::getThinnedProduct(ProductID const&, unsigned int&) const {
858  assert(false);
859  return nullptr;
860  }
861 
863  std::vector<WrapperBase const*>&,
864  std::vector<unsigned int>&) const {
865  assert(false);
866  }
867 
868  void Principal::putOrMerge(std::unique_ptr<WrapperBase> prod, ProductResolverBase const* phb) const {
869  phb->putOrMergeProduct(std::move(prod));
870  }
871 
872  void Principal::putOrMerge(BranchDescription const& bd, std::unique_ptr<WrapperBase> edp) const {
873  if (edp.get() == nullptr) {
874  throw edm::Exception(edm::errors::InsertFailure, "Null Pointer")
875  << "put: Cannot put because unique_ptr to product is null."
876  << "\n";
877  }
878  auto phb = getExistingProduct(bd.branchID());
879  assert(phb);
880  // ProductResolver assumes ownership
881  putOrMerge(std::move(edp), phb);
882  }
883 
885  if (preg_->getNextIndexValue(branchType_) != productResolvers_.size()) {
886  productResolvers_.resize(preg_->getNextIndexValue(branchType_));
887  for (auto const& prod : preg_->productList()) {
888  BranchDescription const& bd = prod.second;
889  if (bd.branchType() == branchType_) {
890  ProductResolverIndex index = preg_->indexFrom(bd.branchID());
891  assert(index != ProductResolverIndexInvalid);
892  if (!productResolvers_[index]) {
893  // no product holder. Must add one. The new entry must be an input product holder.
894  assert(!bd.produced());
895  auto cbd = std::make_shared<BranchDescription const>(bd);
896  addInputProduct(cbd);
897  }
898  }
899  }
900  }
901  assert(preg_->getNextIndexValue(branchType_) == productResolvers_.size());
902  }
903 
905  if (not reader()) {
906  return;
907  }
908 
909  for (auto& prod : *this) {
910  prod->retrieveAndMerge(*this, mergeableRunProductMetadata);
911  }
912  }
913 } // 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:502
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:474
virtual void setupUnscheduled(UnscheduledConfigurator const &)
void getAllProvenance(std::vector< Provenance const * > &provenances) const
Definition: Principal.cc:813
void applyToResolvers(F iFunc)
Definition: Principal.h:214
void getAllStableProvenance(std::vector< StableProvenance const * > &provenances) const
Definition: Principal.cc:830
~Principal() override
Definition: Principal.cc:294
Provenance getProvenance(BranchID const &bid, ModuleCallingContext const *mcc) const
Definition: Principal.cc:796
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:862
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:20
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:904
void prefetchAsync(WaitingTask *waitTask, ProductResolverIndex index, bool skipCurrentProcess, ServiceToken const &token, ModuleCallingContext const *mcc) const
Definition: Principal.cc:604
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:540
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:789
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:515
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:872
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
int k[5][pyjets_maxn]
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:112
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:852
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:681
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:857
bool isValid() const
Definition: Hash.h:154
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:706
ConstProductResolverPtr getProductResolverByIndex(ProductResolverIndex const &oid) const
Definition: Principal.cc:535
void addSwitchProducerProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:353
ConstProductResolverPtr getProductResolver(BranchID const &oid) const
Definition: Principal.cc:527
void resetBranchDescription(std::shared_ptr< BranchDescription const > bd)
void adjustIndexesAfterProductRegistryAddition()
Definition: Principal.cc:884
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:578
#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:841
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:614
void deleteProduct(BranchID const &id) const
Definition: Principal.cc:384