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
37  std::string appendCurrentProcessIfAlias(std::string const& processFromInputTag, 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
49  void
51  throw Exception(error, "InvalidID")
52  << "Principal::" << where << ": no product with given branch id: "<< bid << "\n";
53  }
54 
55  static
56  std::shared_ptr<cms::Exception>
57  makeNotFoundException(char const* where, KindOfType kindOfType,
58  TypeID const& productType, std::string const& label, std::string const& instance, 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 << ": Found zero products matching all criteria\nLooking for type: " << productType << "\n"
62  << "Looking for module label: " << label << "\n" << "Looking for productInstanceName: " << instance << "\n"
63  << (process.empty() ? "" : "Looking for process: ") << process << "\n";
64  } else {
65  *exception << "Principal::" << where << ": Found zero products matching all criteria\nLooking for a container with elements of type: " << productType << "\n"
66  << "Looking for module label: " << label << "\n" << "Looking for productInstanceName: " << instance << "\n"
67  << (process.empty() ? "" : "Looking for process: ") << process << "\n";
68  }
69  return exception;
70  }
71 
72  static
73  void
74  throwAmbiguousException(const char* where, TypeID const& productType,std::string const& label, std::string const& instance, std::string const& process) {
75  cms::Exception exception("AmbiguousProduct");
76  exception << "Principal::" << where << ": More than 1 product matches all criteria\nLooking for type: " << productType << "\n"
77  << "Looking for module label: " << label << "\n" << "Looking for productInstanceName: " << instance << "\n"
78  << (process.empty() ? "" : "Looking for process: ") << process << "\n"
79  << "This can only occur with get function calls using a Handle<View> argument.\n"
80  << "Try a get not using a View or change the instance name of one of the products";
81  throw exception;
82 
83  }
84 
85  namespace {
86  void failedToRegisterConsumesMany(edm::TypeID const& iType) {
87  cms::Exception exception("GetManyWithoutRegistration");
88  exception << "::getManyByType called for " << iType
89  << " without a corresponding consumesMany being called for this module. \n";
90  throw exception;
91  }
92 
93  void failedToRegisterConsumes(KindOfType kindOfType,
94  TypeID const& productType,
95  std::string const& moduleLabel,
96  std::string const& productInstanceName,
97  std::string const& processName) {
98  cms::Exception exception("GetByLabelWithoutRegistration");
99  exception << "::getByLabel without corresponding call to consumes or mayConsumes for this module.\n"
100  << (kindOfType == PRODUCT_TYPE ? " type: " : " type: edm::View<") << productType
101  << (kindOfType == PRODUCT_TYPE ? "\n module label: " : ">\n module label: ") << moduleLabel
102  <<"\n product instance name: '" << productInstanceName
103  <<"'\n process name: '" << processName << "'\n";
104  throw exception;
105  }
106 }
107 
108  //0 means unset
109  static std::atomic<Principal::CacheIdentifier_t> s_nextIdentifier{1};
111  return s_nextIdentifier.fetch_add(1,std::memory_order_acq_rel);
112  }
113 
114  Principal::Principal(std::shared_ptr<ProductRegistry const> reg,
115  std::shared_ptr<ProductResolverIndexHelper const> productLookup,
116  ProcessConfiguration const& pc,
117  BranchType bt,
118  HistoryAppender* historyAppender,
119  bool isForPrimaryProcess) :
120  EDProductGetter(),
121  processHistoryPtr_(),
122  processHistoryID_(),
123  processHistoryIDBeforeConfig_(),
124  processConfiguration_(&pc),
125  productResolvers_(),
126  preg_(reg),
127  productLookup_(productLookup),
128  lookupProcessOrder_(productLookup->lookupProcessNames().size(), 0),
129  reader_(),
130  branchType_(bt),
131  historyAppender_(historyAppender),
132  cacheIdentifier_(nextIdentifier())
133  {
134  productResolvers_.resize(reg->getNextIndexValue(bt));
135  //Now that these have been set, we can create the list of Branches we need.
136  std::string const source("source");
137  ProductRegistry::ProductList const& prodsList = reg->productList();
138  // The constructor of an alias product holder takes as an argument the product holder for which it is an alias.
139  // So, the non-alias product holders must be created first.
140  // Therefore, on this first pass, skip current EDAliases.
141  bool hasAliases = false;
142  for(auto const& prod : prodsList) {
143  BranchDescription const& bd = prod.second;
144  if(bd.branchType() == branchType_) {
145  if(isForPrimaryProcess or bd.processName() == pc.processName()) {
146  if(bd.isAlias()) {
147  hasAliases = true;
148  } else {
149  auto cbd = std::make_shared<BranchDescription const>(bd);
150  if(bd.produced()) {
151  if(bd.moduleLabel() == source) {
152  addSourceProduct(cbd);
153  } else if(bd.onDemand()) {
154  assert(branchType_ == InEvent);
156  } else {
157  addScheduledProduct(cbd);
158  }
159  } else {
160  addInputProduct(cbd);
161  }
162  }
163  } else {
164  //We are in a SubProcess and this branch is from the parent
165  auto cbd =std::make_shared<BranchDescription const>(bd);
167  }
168  }
169  }
170  // Now process any EDAliases
171  if(hasAliases) {
172  for(auto const& prod : prodsList) {
173  BranchDescription const& bd = prod.second;
174  if(bd.isAlias() && bd.branchType() == branchType_) {
175  auto cbd = std::make_shared<BranchDescription const>(bd);
176  addAliasedProduct(cbd);
177  }
178  }
179  }
180 
181  // Now create the ProductResolvers that search in reverse process
182  // order and are used for queries where the process name is the
183  // empty string
184  std::vector<std::string> const& lookupProcessNames = productLookup_->lookupProcessNames();
185  std::vector<ProductResolverIndex> matchingHolders(lookupProcessNames.size(), ProductResolverIndexInvalid);
186  std::vector<bool> ambiguous(lookupProcessNames.size(), false);
187  unsigned int beginElements = productLookup_->beginElements();
188  std::vector<TypeID> const& sortedTypeIDs = productLookup_->sortedTypeIDs();
189  std::vector<ProductResolverIndexHelper::Range> const& ranges = productLookup_->ranges();
190  std::vector<ProductResolverIndexHelper::IndexAndNames> const& indexAndNames = productLookup_->indexAndNames();
191  std::vector<char> const& processNamesCharArray = productLookup_->processNames();
192 
193  unsigned int numberOfMatches = 0;
195  if (!sortedTypeIDs.empty()) {
196  ProductResolverIndex productResolverIndex = ProductResolverIndexInvalid;
197  for(unsigned int k = 0, kEnd = sortedTypeIDs.size(); k < kEnd; ++k) {
198  ProductResolverIndexHelper::Range const& range = ranges.at(k);
199  for (unsigned int i = range.begin(); i < range.end(); ++i) {
200  ProductResolverIndexHelper::IndexAndNames const& product = indexAndNames.at(i);
201  if (product.startInProcessNames() == 0) {
202  if (productResolverIndex != ProductResolverIndexInvalid) {
203  if ((numberOfMatches == 1) and
204  (lastMatchIndex != ProductResolverIndexAmbiguous)) {
205  //only one choice so use a special resolver
206  productResolvers_.at(productResolverIndex) = std::make_shared<SingleChoiceNoProcessProductResolver>(lastMatchIndex);
207  } else {
208  bool productMadeAtEnd = false;
209  //Need to know if the product from this processes is added at end of transition
210  for(unsigned int i=0; i< matchingHolders.size();++i) {
211  if( (not ambiguous[i]) and
212  ProductResolverIndexInvalid != matchingHolders[i] and
213  productResolvers_[matchingHolders[i]]->branchDescription().availableOnlyAtEndTransition()) {
214  productMadeAtEnd = true;
215  break;
216  }
217  }
218  std::shared_ptr<ProductResolverBase> newHolder = std::make_shared<NoProcessProductResolver>(matchingHolders, ambiguous, productMadeAtEnd);
219  productResolvers_.at(productResolverIndex) = newHolder;
220  }
221  matchingHolders.assign(lookupProcessNames.size(), ProductResolverIndexInvalid);
222  ambiguous.assign(lookupProcessNames.size(), false);
223  numberOfMatches= 0;
224  lastMatchIndex = ProductResolverIndexInvalid;
225  }
226  productResolverIndex = product.index();
227  } else {
228  std::string process(&processNamesCharArray.at(product.startInProcessNames()));
229  auto iter = std::find(lookupProcessNames.begin(), lookupProcessNames.end(), process);
230  assert(iter != lookupProcessNames.end());
231  ProductResolverIndex iMatchingIndex = product.index();
232  lastMatchIndex = iMatchingIndex;
233  assert(iMatchingIndex != ProductResolverIndexInvalid);
234  ++numberOfMatches;
235  if (iMatchingIndex == ProductResolverIndexAmbiguous) {
236  assert(k >= beginElements);
237  ambiguous.at(iter - lookupProcessNames.begin()) = true;
238  } else {
239  matchingHolders.at(iter - lookupProcessNames.begin()) = iMatchingIndex;
240  }
241  }
242  }
243  }
244  //Need to know if the product from this processes is added at end of transition
245  if ((numberOfMatches == 1) and
246  (lastMatchIndex != ProductResolverIndexAmbiguous)) {
247  //only one choice so use a special resolver
248  productResolvers_.at(productResolverIndex) = std::make_shared<SingleChoiceNoProcessProductResolver>(lastMatchIndex);
249  } else {
250  bool productMadeAtEnd = false;
251  for(unsigned int i=0; i< matchingHolders.size();++i) {
252  if( (not ambiguous[i]) and
253  ProductResolverIndexInvalid != matchingHolders[i] and
254  productResolvers_[matchingHolders[i]]->branchDescription().availableOnlyAtEndTransition()) {
255  productMadeAtEnd = true;
256  break;
257  }
258  }
259  std::shared_ptr<ProductResolverBase> newHolder = std::make_shared<NoProcessProductResolver>(matchingHolders, ambiguous, productMadeAtEnd);
260  productResolvers_.at(productResolverIndex) = newHolder;
261  }
262  }
263  }
264 
266  }
267 
268  // Number of products in the Principal.
269  // For products in an input file and not yet read in due to delayed read,
270  // this routine assumes a real product is there.
271  size_t
272  Principal::size() const {
273  size_t size = 0U;
274  for(auto const& prod : *this) {
275  if(prod->singleProduct() && // Not a NoProcessProductResolver
276  !prod->productUnavailable() &&
277  !prod->unscheduledWasNotRun() &&
278  !prod->branchDescription().dropped()) {
279  ++size;
280  }
281  }
282  return size;
283  }
284 
285  // adjust provenance for input products after new input file has been merged
286  bool
288  ProductRegistry::ProductList const& prodsList = reg.productList();
289  for(auto const& prod : prodsList) {
290  BranchDescription const& bd = prod.second;
291  if(!bd.produced() && (bd.branchType() == branchType_)) {
292  auto cbd = std::make_shared<BranchDescription const>(bd);
293  auto phb = getExistingProduct(cbd->branchID());
294  if(phb == nullptr || phb->branchDescription().branchName() != cbd->branchName()) {
295  return false;
296  }
297  phb->resetBranchDescription(cbd);
298  }
299  }
300  return true;
301  }
302 
303  void
304  Principal::addScheduledProduct(std::shared_ptr<BranchDescription const> bd) {
305  auto phb = std::make_unique<PuttableProductResolver>(std::move(bd));
307  }
308 
309  void
310  Principal::addSourceProduct(std::shared_ptr<BranchDescription const> bd) {
311  auto phb = std::make_unique<PuttableProductResolver>(std::move(bd));
313  }
314 
315  void
316  Principal::addInputProduct(std::shared_ptr<BranchDescription const> bd) {
317  addProductOrThrow(std::make_unique<InputProductResolver>(std::move(bd)));
318  }
319 
320  void
321  Principal::addUnscheduledProduct(std::shared_ptr<BranchDescription const> bd) {
322  addProductOrThrow(std::make_unique<UnscheduledProductResolver>(std::move(bd)));
323  }
324 
325  void
326  Principal::addAliasedProduct(std::shared_ptr<BranchDescription const> bd) {
327  ProductResolverIndex index = preg_->indexFrom(bd->originalBranchID());
328  assert(index != ProductResolverIndexInvalid);
329 
330  addProductOrThrow(std::make_unique<AliasProductResolver>(std::move(bd), dynamic_cast<ProducedProductResolver&>(*productResolvers_[index])));
331  }
332 
333  void
334  Principal::addParentProcessProduct(std::shared_ptr<BranchDescription const> bd) {
335  addProductOrThrow(std::make_unique<ParentProcessProductResolver>(std::move(bd)));
336  }
337 
338  // "Zero" the principal so it can be reused for another Event.
339  void
341  //We do not clear the product history information
342  // because it rarely changes and recalculating takes
343  // time.
344  reader_ = nullptr;
345  for(auto& prod : *this) {
346  prod->resetProductData();
347  }
348  }
349 
350  void
352  auto phb = getExistingProduct(id);
353  assert(nullptr != phb);
354  phb->unsafe_deleteProduct();
355  }
356 
357  void
359  applyToResolvers([&iConfigure](ProductResolverBase* iResolver) {
360  iResolver->setupUnscheduled(iConfigure);
361  });
362  }
363 
364 
365  // Set the principal for the Event, Lumi, or Run.
366  void
368  ProcessHistoryRegistry const& processHistoryRegistry,
370  //increment identifier here since clearPrincipal isn't called for Run/Lumi
372  if(reader) {
373  reader_ = reader;
374  }
375 
376  if (historyAppender_ && productRegistry().anyProductProduced()) {
377  if( (not processHistoryPtr_) || (processHistoryIDBeforeConfig_ != hist) ) {
378  processHistoryPtr_ =
379  historyAppender_->appendToProcessHistory(hist,
380  processHistoryRegistry. getMapped(hist),
382  processHistoryID_ = processHistoryPtr_->id();
384  }
385  }
386  else {
387  std::shared_ptr<ProcessHistory const> inputProcessHistory;
388  if( (not processHistoryPtr_) || (processHistoryIDBeforeConfig_ != hist) ) {
389  if (hist.isValid()) {
390  //does not own the pointer
391  auto noDel =[](void const*){};
392  inputProcessHistory =
393  std::shared_ptr<ProcessHistory const>(processHistoryRegistry.getMapped(hist),noDel);
394  if (inputProcessHistory.get() == nullptr) {
396  << "Principal::fillPrincipal\n"
397  << "Input ProcessHistory not found in registry\n"
398  << "Contact a Framework developer\n";
399  }
400  } else {
401  //Since this is static we don't want it deleted
402  inputProcessHistory = std::shared_ptr<ProcessHistory const>(&s_emptyProcessHistory,[](void const*){});
403  //no need to do any ordering since it is empty
405  }
407  processHistoryPtr_ = inputProcessHistory;
409  }
410  }
411 
413  std::vector<std::string> const& lookupProcessNames = productLookup_->lookupProcessNames();
414  lookupProcessOrder_.assign(lookupProcessNames.size(), 0);
415  unsigned int k = 0;
416 
417  // We loop over processes in reverse order of the ProcessHistory.
418  // If any entries in the product lookup tables are associated with
419  // the process we add it to the vector of processes in the order
420  // the lookup should be performed. There is one exception though,
421  // We start with the current process even if it is not in the ProcessHistory.
422  // The current process might be needed but not be in the process
423  // history if all the products produced in the current process are
424  // transient.
425  auto nameIter = std::find(lookupProcessNames.begin(), lookupProcessNames.end(), processConfiguration_->processName());
426  if (nameIter != lookupProcessNames.end()) {
427  lookupProcessOrder_.at(k) = nameIter - lookupProcessNames.begin();
428  ++k;
429  }
430 
431  // We just looked for the current process so skip it if
432  // it is in the ProcessHistory.
433  auto iter = processHistoryPtr_->rbegin();
434  if (iter->processName() == processConfiguration_->processName()) {
435  ++iter;
436  }
437 
438  for (auto iEnd = processHistoryPtr_->rend(); iter != iEnd; ++iter) {
439  auto nameIter = std::find(lookupProcessNames.begin(), lookupProcessNames.end(), iter->processName());
440  if (nameIter == lookupProcessNames.end()) {
441  continue;
442  }
443  lookupProcessOrder_.at(k) = nameIter - lookupProcessNames.begin();
444  ++k;
445  }
447  }
448  }
449 
452  return const_cast<ProductResolverBase*>( const_cast<const Principal*>(this)->getExistingProduct(branchID));
453  }
454 
455  ProductResolverBase const*
456  Principal::getExistingProduct(BranchID const& branchID) const {
457  ProductResolverIndex index = preg_->indexFrom(branchID);
458  assert(index != ProductResolverIndexInvalid);
459  return productResolvers_.at(index).get();
460  }
461 
462  ProductResolverBase const*
463  Principal::getExistingProduct(ProductResolverBase const& productResolver) const {
464  auto phb = getExistingProduct(productResolver.branchDescription().branchID());
465  if(nullptr != phb && BranchKey(productResolver.branchDescription()) != BranchKey(phb->branchDescription())) {
466  BranchDescription const& newProduct = phb->branchDescription();
467  BranchDescription const& existing = productResolver.branchDescription();
468  if(newProduct.branchName() != existing.branchName() && newProduct.branchID() == existing.branchID()) {
469  throw cms::Exception("HashCollision") << "Principal::getExistingProduct\n" <<
470  " Branch " << newProduct.branchName() << " has same branch ID as branch " << existing.branchName() << "\n" <<
471  "Workaround: change process name or product instance name of " << newProduct.branchName() << "\n";
472  } else {
473  assert(nullptr == phb || BranchKey(productResolver.branchDescription()) == BranchKey(phb->branchDescription()));
474  }
475  }
476  return phb;
477  }
478 
479  void
480  Principal::addProduct_(std::unique_ptr<ProductResolverBase> productResolver) {
481  BranchDescription const& bd = productResolver->branchDescription();
482  assert (!bd.className().empty());
483  assert (!bd.friendlyClassName().empty());
484  assert (!bd.moduleLabel().empty());
485  assert (!bd.processName().empty());
486  SharedProductPtr phb(productResolver.release());
487 
488  ProductResolverIndex index = preg_->indexFrom(bd.branchID());
489  assert(index != ProductResolverIndexInvalid);
490  productResolvers_[index] = phb;
491  }
492 
493  void
494  Principal::addProductOrThrow(std::unique_ptr<ProductResolverBase> productResolver) {
495  ProductResolverBase const* phb = getExistingProduct(*productResolver);
496  if(phb != nullptr) {
497  BranchDescription const& bd = productResolver->branchDescription();
498  throw Exception(errors::InsertFailure, "AlreadyPresent")
499  << "addProductOrThrow: Problem found while adding product, "
500  << "product already exists for ("
501  << bd.friendlyClassName() << ","
502  << bd.moduleLabel() << ","
503  << bd.productInstanceName() << ","
504  << bd.processName()
505  << ")\n";
506  }
507  addProduct_(std::move(productResolver));
508  }
509 
512  ProductResolverIndex index = preg_->indexFrom(bid);
513  if(index == ProductResolverIndexInvalid){
514  return ConstProductResolverPtr();
515  }
516  return getProductResolverByIndex(index);
517  }
518 
521 
523  return phb;
524  }
525 
528  TypeID const& typeID,
529  InputTag const& inputTag,
530  EDConsumerBase const* consumer,
532  ModuleCallingContext const* mcc) const {
533 
534  ProductData const* result = findProductByLabel(kindOfType, typeID, inputTag, consumer, sra, mcc);
535  if(result == nullptr) {
536  return BasicHandle(makeHandleExceptionFactory([=]()->std::shared_ptr<cms::Exception> {
537  return makeNotFoundException("getByLabel", kindOfType, typeID, inputTag.label(), inputTag.instance(),
539  }));
540  }
541  return BasicHandle(result->wrapper(), &(result->provenance()));
542  }
543 
546  TypeID const& typeID,
547  std::string const& label,
548  std::string const& instance,
549  std::string const& process,
550  EDConsumerBase const* consumer,
552  ModuleCallingContext const* mcc) const {
553 
554  ProductData const* result = findProductByLabel(kindOfType, typeID, label, instance, process,consumer, sra, mcc);
555  if(result == nullptr) {
556  return BasicHandle(makeHandleExceptionFactory([=]()->std::shared_ptr<cms::Exception> {
557  return makeNotFoundException("getByLabel", kindOfType, typeID, label, instance, process);
558  }));
559  }
560  return BasicHandle(result->wrapper(), &(result->provenance()));
561  }
562 
565  TypeID const&,
567  bool skipCurrentProcess,
568  bool& ambiguous,
570  ModuleCallingContext const* mcc) const {
571  assert(index !=ProductResolverIndexInvalid);
572  auto& productResolver = productResolvers_[index];
573  assert(nullptr!=productResolver.get());
574  auto resolution = productResolver->resolveProduct(*this, skipCurrentProcess, sra, mcc);
575  if(resolution.isAmbiguous()) {
576  ambiguous = true;
577  return BasicHandle();
578  }
579  auto productData = resolution.data();
580  if(productData == nullptr) {
581  return BasicHandle();
582  }
583  return BasicHandle(productData->wrapper(), &(productData->provenance()));
584  }
585 
586  void
589  bool skipCurrentProcess,
590  ServiceToken const& token,
591  ModuleCallingContext const* mcc) const {
592  auto const& productResolver = productResolvers_.at(index);
593  assert(nullptr!=productResolver.get());
594  productResolver->prefetchAsync(task,*this, skipCurrentProcess,token, nullptr,mcc);
595  }
596 
597  void
600  EDConsumerBase const* consumer,
602  ModuleCallingContext const* mcc) const {
603 
604  assert(results.empty());
605 
606  if(UNLIKELY(consumer and (not consumer->registeredToConsumeMany(typeID,branchType())))) {
607  failedToRegisterConsumesMany(typeID);
608  }
609 
610  // This finds the indexes to all the ProductResolver's matching the type
613 
614  if (matches.numberOfMatches() == 0) {
615  return;
616  }
617 
618  results.reserve(matches.numberOfMatches());
619 
620  // Loop over the ProductResolvers. Add the products that are actually
621  // present into the results. This will also trigger delayed reading,
622  // on demand production, and check for deleted products as appropriate.
623 
624  // Over the years the code that uses getManyByType has grown to depend
625  // on the ordering of the results. The order originally was just an
626  // accident of how previous versions of the code were written, but
627  // here we have to go through some extra effort to preserve that ordering.
628 
629  // We build a list of holders that match a particular label and instance.
630  // When that list is complete we call findProducts, which loops over
631  // that list in reverse order of the ProcessHistory (starts with the
632  // most recent). Then we clear the list and repeat this until all the
633  // matching label and instance subsets have been dealt with.
634 
635  // Note that the function isFullyResolved returns true for the ProductResolvers
636  // that are associated with an empty process name. Those are the ones that
637  // know how to search for the most recent process name matching
638  // a label and instance. We do not need these for getManyByType and
639  // skip them. In addition to skipping them, we make use of the fact
640  // that they mark the beginning of each subset of holders with the same
641  // label and instance. They tell us when to call findProducts.
642 
643  std::vector<ProductResolverBase const*> holders;
644 
645  for(unsigned int i = 0; i < matches.numberOfMatches(); ++i) {
646 
647  ProductResolverIndex index = matches.index(i);
648 
649  if(!matches.isFullyResolved(i)) {
650  if(!holders.empty()) {
651  // Process the ones with a particular module label and instance
652  findProducts(holders, typeID, results, sra, mcc);
653  holders.clear();
654  }
655  } else {
656  ProductResolverBase const* productResolver = productResolvers_.at(index).get();
657  assert(productResolver);
658  holders.push_back(productResolver);
659  }
660  }
661  // Do not miss the last subset of products
662  if(!holders.empty()) {
663  findProducts(holders, typeID, results, sra, mcc);
664  }
665  return;
666  }
667 
668  void
669  Principal::findProducts(std::vector<ProductResolverBase const*> const& holders,
670  TypeID const&,
673  ModuleCallingContext const* mcc) const {
674 
675  for (auto iter = processHistoryPtr_->rbegin(),
676  iEnd = processHistoryPtr_->rend();
677  iter != iEnd; ++iter) {
678  std::string const& process = iter->processName();
679  for (auto productResolver : holders) {
680  BranchDescription const& bd = productResolver->branchDescription();
681  if (process == bd.processName()) {
682 
683  // Ignore aliases to avoid matching the same product multiple times.
684  if(bd.isAlias()) {
685  continue;
686  }
687 
688  ProductData const* productData = productResolver->resolveProduct(*this,false, sra, mcc).data();
689  if(productData) {
690  // Skip product if not available.
691  results.emplace_back(productData->wrapper(), &(productData->provenance()));
692  }
693  }
694  }
695  }
696  }
697 
698  ProductData const*
700  TypeID const& typeID,
701  InputTag const& inputTag,
702  EDConsumerBase const* consumer,
704  ModuleCallingContext const* mcc) const {
705 
706  bool skipCurrentProcess = inputTag.willSkipCurrentProcess();
707 
709 
710  if (index == ProductResolverIndexInvalid) {
711 
712  char const* processName = inputTag.process().c_str();
713  if (skipCurrentProcess) {
714  processName = "\0";
715  } else if (inputTag.process() == InputTag::kCurrentProcess) {
716  processName = processConfiguration_->processName().c_str();
717  }
718 
719  index = productLookup().index(kindOfType,
720  typeID,
721  inputTag.label().c_str(),
722  inputTag.instance().c_str(),
723  processName);
724 
725  if(index == ProductResolverIndexAmbiguous) {
726  throwAmbiguousException("findProductByLabel", typeID, inputTag.label(), inputTag.instance(),
728  } else if (index == ProductResolverIndexInvalid) {
729  return nullptr;
730  }
731  inputTag.tryToCacheIndex(index, typeID, branchType(), &productRegistry());
732  }
733  if(UNLIKELY( consumer and (not consumer->registeredToConsume(index, skipCurrentProcess, branchType())))) {
734  failedToRegisterConsumes(kindOfType,typeID,inputTag.label(),inputTag.instance(),
736  }
737 
738 
739  auto const& productResolver = productResolvers_[index];
740 
741  auto resolution = productResolver->resolveProduct(*this, skipCurrentProcess, sra, mcc);
742  if(resolution.isAmbiguous()) {
743  throwAmbiguousException("findProductByLabel", typeID, inputTag.label(), inputTag.instance(),
745  }
746  return resolution.data();
747  }
748 
749  ProductData const*
751  TypeID const& typeID,
752  std::string const& label,
753  std::string const& instance,
754  std::string const& process,
755  EDConsumerBase const* consumer,
757  ModuleCallingContext const* mcc) const {
758 
760  typeID,
761  label.c_str(),
762  instance.c_str(),
763  process.c_str());
764 
765  if(index == ProductResolverIndexAmbiguous) {
766  throwAmbiguousException("findProductByLabel", typeID, label, instance, process);
767  } else if (index == ProductResolverIndexInvalid) {
768  return nullptr;
769  }
770 
771  if(UNLIKELY( consumer and (not consumer->registeredToConsume(index, false, branchType())))) {
772  failedToRegisterConsumes(kindOfType,typeID,label,instance,process);
773  }
774 
775  auto const& productResolver = productResolvers_[index];
776 
777  auto resolution = productResolver->resolveProduct(*this, false, sra, mcc);
778  if(resolution.isAmbiguous()) {
779  throwAmbiguousException("findProductByLabel", typeID, label, instance, process);
780  }
781  return resolution.data();
782  }
783 
784  ProductData const*
785  Principal::findProductByTag(TypeID const& typeID, InputTag const& tag, ModuleCallingContext const* mcc) const {
786  ProductData const* productData =
788  typeID,
789  tag,
790  nullptr,
791  nullptr,
792  mcc);
793  return productData;
794  }
795 
796  Provenance
798  ModuleCallingContext const* mcc) const {
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
816  Principal::getAllProvenance(std::vector<Provenance const*>& provenances) const {
817  provenances.clear();
818  for(auto const& productResolver : *this) {
819  if(productResolver->singleProduct() && productResolver->provenanceAvailable() && !productResolver->branchDescription().isAlias()) {
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
833  Principal::getAllStableProvenance(std::vector<StableProvenance const*>& provenances) const {
834  provenances.clear();
835  for(auto const& productResolver : *this) {
836  if(productResolver->singleProduct() && !productResolver->branchDescription().isAlias()) {
837  if(productResolver->stableProvenance()->branchDescription().present()) {
838  provenances.push_back(productResolver->stableProvenance());
839  }
840  }
841  }
842  }
843 
844  void
845  Principal::recombine(Principal& other, std::vector<BranchID> const& bids) {
846  for(auto& prod : bids) {
847  ProductResolverIndex index= preg_->indexFrom(prod);
848  assert(index!=ProductResolverIndexInvalid);
849  ProductResolverIndex indexO = other.preg_->indexFrom(prod);
850  assert(indexO!=ProductResolverIndexInvalid);
852  }
853  reader_->mergeReaders(other.reader());
854  }
855 
856  WrapperBase const*
857  Principal::getIt(ProductID const&) const {
858  assert(false);
859  return nullptr;
860  }
861 
862  WrapperBase const*
863  Principal::getThinnedProduct(ProductID const&, unsigned int&) const {
864  assert(false);
865  return nullptr;
866  }
867 
868  void
870  std::vector<WrapperBase const*>&,
871  std::vector<unsigned int>&) const {
872  assert(false);
873  }
874 
875  void
876  Principal::putOrMerge(std::unique_ptr<WrapperBase> prod, ProductResolverBase const* phb) const {
877  phb->putOrMergeProduct(std::move(prod));
878  }
879 
880  void
881  Principal::putOrMerge(BranchDescription const& bd, std::unique_ptr<WrapperBase> edp) const {
882  if(edp.get() == nullptr) {
883  throw edm::Exception(edm::errors::InsertFailure,"Null Pointer")
884  << "put: Cannot put because unique_ptr to product is null."
885  << "\n";
886  }
887  auto phb = getExistingProduct(bd.branchID());
888  assert(phb);
889  // ProductResolver assumes ownership
890  putOrMerge(std::move(edp), phb);
891  }
892 
893 
894  void
896  if(preg_->getNextIndexValue(branchType_) != productResolvers_.size()) {
897  productResolvers_.resize(preg_->getNextIndexValue(branchType_));
898  for(auto const& prod : preg_->productList()) {
899  BranchDescription const& bd = prod.second;
900  if(bd.branchType() == branchType_) {
901  ProductResolverIndex index = preg_->indexFrom(bd.branchID());
902  assert(index != ProductResolverIndexInvalid);
903  if(!productResolvers_[index]) {
904  // no product holder. Must add one. The new entry must be an input product holder.
905  assert(!bd.produced());
906  auto cbd = std::make_shared<BranchDescription const>(bd);
907  addInputProduct(cbd);
908  }
909  }
910  }
911  }
912  assert(preg_->getNextIndexValue(branchType_) == productResolvers_.size());
913  }
914 
915  void
917  if(not reader()) {return;}
918 
919  for(auto & prod : *this) {
920  prod->retrieveAndMerge(*this, mergeableRunProductMetadata);
921  }
922  }
923 }
BranchType branchType_
Definition: Principal.h:278
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:150
Provenance const & provenance() const
Definition: ProductData.h:32
void clearPrincipal()
Definition: Principal.cc:340
std::string const & branchName() const
size_t size() const
Definition: Principal.cc:272
DelayedReader * reader_
Definition: Principal.h:276
BranchType const & branchType() const
ProcessHistoryID processHistoryIDBeforeConfig_
Definition: Principal.h:259
void setupUnscheduled(UnscheduledConfigurator const &)
Definition: Principal.cc:358
unsigned int ProductResolverIndex
bool getMapped(ProcessHistoryID const &key, ProcessHistory &value) const
static std::string const source("source")
ProductResolverCollection productResolvers_
Definition: Principal.h:264
std::shared_ptr< ProcessHistory const > processHistoryPtr_
Definition: Principal.h:256
static PFTauRenderPlugin instance
std::shared_ptr< ProductResolverBase > SharedProductPtr
Definition: Principal.h:68
void addProduct_(std::unique_ptr< ProductResolverBase > phb)
Definition: Principal.cc:480
static std::atomic< Principal::CacheIdentifier_t > s_nextIdentifier
Definition: Principal.cc:109
std::map< BranchKey, BranchDescription > ProductList
static Principal::CacheIdentifier_t nextIdentifier()
Definition: Principal.cc:110
ProcessHistoryID processHistoryID_
Definition: Principal.h:258
void mergeReaders(DelayedReader *other)
Definition: DelayedReader.h:35
ProductResolverBase * getExistingProduct(BranchID const &branchID)
Definition: Principal.cc:451
virtual void setupUnscheduled(UnscheduledConfigurator const &)
void getAllProvenance(std::vector< Provenance const * > &provenances) const
Definition: Principal.cc:816
void applyToResolvers(F iFunc)
Definition: Principal.h:210
void getAllStableProvenance(std::vector< StableProvenance const * > &provenances) const
Definition: Principal.cc:833
~Principal() override
Definition: Principal.cc:265
Provenance getProvenance(BranchID const &bid, ModuleCallingContext const *mcc) const
Definition: Principal.cc:797
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:869
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:114
void addInputProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:316
edm::propagate_const< HistoryAppender * > historyAppender_
Definition: Principal.h:283
void readAllFromSourceAndMergeImmediately(MergeableRunProductMetadata const *mergeableRunProductMetadata=0)
Definition: Principal.cc:916
void prefetchAsync(WaitingTask *waitTask, ProductResolverIndex index, bool skipCurrentProcess, ServiceToken const &token, ModuleCallingContext const *mcc) const
Definition: Principal.cc:587
BranchType
Definition: BranchType.h:11
ProductResolverIndex indexFor(TypeID const &typeID, BranchType branchType, void const *productRegistry) const
Definition: InputTag.cc:187
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:205
static void throwAmbiguousException(const char *where, TypeID const &productType, std::string const &label, std::string const &instance, std::string const &process)
Definition: Principal.cc:74
std::string const & processName() const
ProductList const & productList() const
std::vector< unsigned int > lookupProcessOrder_
Definition: Principal.h:271
BasicHandle getByLabel(KindOfType kindOfType, TypeID const &typeID, InputTag const &inputTag, EDConsumerBase const *consumes, SharedResourcesAcquirer *sra, ModuleCallingContext const *mcc) const
Definition: Principal.cc:527
void addScheduledProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:304
std::string const & className() const
ProductData const * findProductByTag(TypeID const &typeID, InputTag const &tag, ModuleCallingContext const *mcc) const
Definition: Principal.cc:785
std::shared_ptr< ProductResolverIndexHelper const > productLookup_
Definition: Principal.h:269
std::string const & moduleLabel() const
void addProductOrThrow(std::unique_ptr< ProductResolverBase > phb)
Definition: Principal.cc:494
std::shared_ptr< ProductRegistry const > preg_
Definition: Principal.h:268
std::string const & productInstanceName() const
bool registeredToConsume(ProductResolverIndex, bool, BranchType) const
CacheIdentifier_t cacheIdentifier_
Definition: Principal.h:285
BranchType const & branchType() const
Definition: Principal.h:177
std::shared_ptr< HandleExceptionFactory > makeHandleExceptionFactory(T &&iFunctor)
void putOrMerge(BranchDescription const &bd, std::unique_ptr< WrapperBase > edp) const
Definition: Principal.cc:881
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:310
Matches relatedIndexes(KindOfType kindOfType, TypeID const &typeID, char const *moduleLabel, char const *instance) const
ProcessHistoryID orderProcessHistoryID_
Definition: Principal.h:272
static const std::string kCurrentProcess
Definition: InputTag.h:51
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:334
int k[5][pyjets_maxn]
string ranges
Definition: diffTwoXMLs.py:79
DelayedReader * reader() const
Definition: Principal.h:183
bool willSkipCurrentProcess() const
Definition: InputTag.h:42
bool registeredToConsumeMany(TypeID const &, BranchType) const
void addUnscheduledProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:321
WrapperBase const * getIt(ProductID const &) const override
Definition: Principal.cc:857
ProductResolverIndexHelper const & productLookup() const
Definition: Principal.h:152
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:57
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:669
std::string const & process() const
Definition: InputTag.h:40
HLT enums.
unsigned long CacheIdentifier_t
Definition: Principal.h:180
WrapperBase const * getThinnedProduct(ProductID const &, unsigned int &) const override
Definition: Principal.cc:863
bool isValid() const
Definition: Hash.h:154
bool adjustToNewProductRegistry(ProductRegistry const &reg)
Definition: Principal.cc:287
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:699
ConstProductResolverPtr getProductResolverByIndex(ProductResolverIndex const &oid) const
Definition: Principal.cc:520
ConstProductResolverPtr getProductResolver(BranchID const &oid) const
Definition: Principal.cc:511
void resetBranchDescription(std::shared_ptr< BranchDescription const > bd)
void adjustIndexesAfterProductRegistryAddition()
Definition: Principal.cc:895
static void throwProductNotFoundException(char const *where, errors::ErrorCodes error, BranchID const &bid)
Definition: Principal.cc:50
BasicHandle getByToken(KindOfType kindOfType, TypeID const &typeID, ProductResolverIndex index, bool skipCurrentProcess, bool &ambiguous, SharedResourcesAcquirer *sra, ModuleCallingContext const *mcc) const
Definition: Principal.cc:564
static std::string appendCurrentProcessIfAlias(std::string const &processFromInputTag, std::string const &currentProcess)
Definition: Principal.cc:37
void addAliasedProduct(std::shared_ptr< BranchDescription const > bd)
Definition: Principal.cc:326
void fillPrincipal(ProcessHistoryID const &hist, ProcessHistoryRegistry const &phr, DelayedReader *reader)
Definition: Principal.cc:367
void recombine(Principal &other, std::vector< BranchID > const &bids)
Definition: Principal.cc:845
std::string const & instance() const
Definition: InputTag.h:37
ProcessConfiguration const * processConfiguration_
Definition: Principal.h:261
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:598
void deleteProduct(BranchID const &id) const
Definition: Principal.cc:351
#define UNLIKELY(x)