CMS 3D CMS Logo

ProductRegistry.cc
Go to the documentation of this file.
1 
12 
14 
21 
22 #include "TDictAttributeMap.h"
23 
24 #include <cassert>
25 #include <iterator>
26 #include <limits>
27 #include <set>
28 #include <sstream>
29 #include <ostream>
30 
31 namespace edm {
32 
34  productList_(),
35  transient_() {
36  }
37 
39  frozen_(false),
40  productProduced_(),
41  anyProductProduced_(false),
42  eventProductLookup_(new ProductResolverIndexHelper),
43  lumiProductLookup_(new ProductResolverIndexHelper),
44  runProductLookup_(new ProductResolverIndexHelper),
45  eventNextIndexValue_(0),
46  lumiNextIndexValue_(0),
47  runNextIndexValue_(0),
48 
49  branchIDToIndex_() {
50  for(bool& isProduced : productProduced_) isProduced = false;
51  }
52 
53  void
55  frozen_ = false;
56  for(bool& isProduced : productProduced_) isProduced = false;
57  anyProductProduced_ = false;
58 
59  // propagate_const<T> has no reset() function
60  eventProductLookup_ = std::make_unique<ProductResolverIndexHelper>();
61  lumiProductLookup_ = std::make_unique<ProductResolverIndexHelper>();
62  runProductLookup_ = std::make_unique<ProductResolverIndexHelper>();
63 
67 
68  branchIDToIndex_.clear();
69  }
70 
72  productList_(productList),
73  transient_() {
74  freezeIt(toBeFrozen);
75  }
76 
77  void
79  bool fromListener) {
80  assert(productDesc.produced());
81  throwIfFrozen();
82  std::pair<ProductList::iterator, bool> ret =
83  productList_.insert(std::make_pair(BranchKey(productDesc), productDesc));
84  if(!ret.second) {
85  auto const& previous = *productList_.find(BranchKey(productDesc));
86  if(previous.second.produced()) {
87  // Duplicate registration in current process
88  throw Exception(errors::LogicError , "Duplicate Product")
89  << "The produced product " << previous.second << " is registered more than once.\n"
90  << "Please remove the redundant 'produces' call(s).\n";
91  } else {
92  // Duplicate registration in previous process
93  throw Exception(errors::Configuration, "Duplicate Process Name.\n")
94  << "The process name " << productDesc.processName() << " was previously used for products in the input.\n"
95  << "This has caused branch name conflicts between input products and new products.\n"
96  << "Please modify the configuration file to use a distinct process name.\n"
97  << "Alternately, drop all input products using that process name and the\n"
98  << "descendants of those products.\n";
99  }
100  }
101  addCalled(productDesc, fromListener);
102  }
103 
104  void
106  std::string const& labelAlias,
107  std::string const& instanceAlias) {
108  assert(productDesc.produced());
109  assert(productDesc.branchID().isValid());
110  throwIfFrozen();
111  BranchDescription bd(productDesc, labelAlias, instanceAlias);
112  std::pair<ProductList::iterator, bool> ret =
113  productList_.insert(std::make_pair(BranchKey(bd), bd));
114  assert(ret.second);
115  transient_.aliasToOriginal_.emplace_back(labelAlias,
116  productDesc.moduleLabel());
117  addCalled(bd, false);
118  }
119 
120  void
122  assert(!productDesc.produced());
123  throwIfFrozen();
124  BranchKey k = BranchKey(productDesc);
125  ProductList::iterator iter = productList_.find(k);
126  if(iter == productList_.end()) {
127  productList_.insert(std::make_pair(k, productDesc));
128  } else {
129  assert(combinable(iter->second, productDesc));
130  iter->second.merge(productDesc);
131  }
132  }
133 
134  bool
137  for(ProductList::const_iterator it = productList_.begin(), itEnd = productList_.end();
138  it != itEnd; ++it) {
139  if(it->second.branchType() == brType) {
140  return true;
141  }
142  }
143  return false;
144  }
145 
146  std::shared_ptr<ProductResolverIndexHelper const>
148  if (branchType == InEvent) return transient_.eventProductLookup();
149  if (branchType == InLumi) return transient_.lumiProductLookup();
150  return transient_.runProductLookup();
151  }
152 
153  std::shared_ptr<ProductResolverIndexHelper>
155  if (branchType == InEvent) return transient_.eventProductLookup();
156  if (branchType == InLumi) return transient_.lumiProductLookup();
157  return transient_.runProductLookup();
158  }
159 
160  void
161  ProductRegistry::setFrozen(bool initializeLookupInfo) {
162  if(frozen()) return;
163  freezeIt();
164  if(initializeLookupInfo) {
165  initializeLookupTables(nullptr, nullptr, nullptr);
166  }
168  }
169 
170  void
171  ProductRegistry::setFrozen(std::set<TypeID> const& productTypesConsumed,
172  std::set<TypeID> const& elementTypesConsumed,
173  std::string const& processName) {
174  if(frozen()) return;
175  freezeIt();
176  initializeLookupTables(&productTypesConsumed, &elementTypesConsumed, &processName);
178  }
179 
180  void
182  if(frozen()) {
183  throw cms::Exception("ProductRegistry", "throwIfFrozen")
184  << "cannot modify the ProductRegistry because it is frozen\n";
185  }
186  }
187 
188  void
190  if(!frozen()) {
191  throw cms::Exception("ProductRegistry", "throwIfNotFrozen")
192  << "cannot read the ProductRegistry because it is not yet frozen\n";
193  }
194  }
195 
196  void
198  }
199 
200  std::vector<std::string>
202  std::vector<std::string> result;
203  result.reserve(productList().size());
204 
205  for(auto const& product : productList()) {
206  result.push_back(product.second.branchName());
207  }
208  return result;
209  }
210 
211  std::vector<BranchDescription const*>
213  std::vector<BranchDescription const*> result;
214  result.reserve(productList().size());
215 
216  for(auto const& product : productList()) {
217  result.push_back(&product.second);
218  }
219  return result;
220  }
221 
222  void
224  for(auto const& product : other) {
225  copyProduct(product.second);
226  }
227  }
228 
229  void
230  ProductRegistry::updateFromInput(std::vector<BranchDescription> const& other) {
231  for(BranchDescription const& branchDescription : other) {
232  copyProduct(branchDescription);
233  }
234  }
235 
238  std::string const& fileName,
239  BranchDescription::MatchMode branchesMustMatch) {
240  std::ostringstream differences;
241 
242  ProductRegistry::ProductList::iterator j = productList_.begin();
243  ProductRegistry::ProductList::iterator s = productList_.end();
244  ProductRegistry::ProductList::const_iterator i = other.productList().begin();
245  ProductRegistry::ProductList::const_iterator e = other.productList().end();
246 
247  // Loop over entries in the main product registry.
248  while(j != s || i != e) {
249  if(j != s && j->second.produced()) {
250  // Ignore branches just produced (i.e. not in input file).
251  ++j;
252  } else if(j == s || (i != e && i->first < j->first)) {
253  if(i->second.present()) {
254  differences << "Branch '" << i->second.branchName() << "' is in file '" << fileName << "'\n";
255  differences << " but not in previous files.\n";
256  } else {
257  productList_.insert(*i);
258  transient_.branchIDToIndex_[i->second.branchID()] = getNextIndexValue(i->second.branchType());
259  ++nextIndexValue(i->second.branchType());
260  }
261  ++i;
262  } else if(i == e || (j != s && j->first < i->first)) {
263  if(j->second.present() && branchesMustMatch == BranchDescription::Strict) {
264  differences << "Branch '" << j->second.branchName() << "' is in previous files\n";
265  differences << " but not in file '" << fileName << "'.\n";
266  }
267  ++j;
268  } else {
269  std::string difs = match(j->second, i->second, fileName);
270  if(difs.empty()) {
271  j->second.merge(i->second);
272  } else {
273  differences << difs;
274  }
275  ++i;
276  ++j;
277  }
278  }
279  return differences.str();
280  }
281 
282  void ProductRegistry::initializeLookupTables(std::set<TypeID> const* productTypesConsumed,
283  std::set<TypeID> const* elementTypesConsumed,
284  std::string const* processName) {
285 
286  std::map<TypeID, TypeID> containedTypeMap;
287  std::map<TypeID, std::vector<TypeWithDict> > containedTypeToBaseTypesMap;
288 
289  std::vector<std::string> missingDictionaries;
290  std::vector<std::string> branchNamesForMissing;
291  std::vector<std::string> producedTypes;
292 
294 
295  for(auto const& product : productList_) {
296  auto const& desc = product.second;
297 
298  checkForDuplicateProcessName(desc, processName);
299 
300  if(desc.produced()) {
301  setProductProduced(desc.branchType());
302  }
303 
304  //only do the following if the data is supposed to be available in the event
305  if(desc.present()) {
306 
307  // Check dictionaries (we already checked for the produced ones earlier somewhere else).
308  // We have to have the dictionaries to properly setup the lookup tables for support of
309  // Views. Also we need them to determine which present products are declared to be
310  // consumed in the case where the consumed type is a View<T>.
311  if (!desc.produced()) {
312  if (!checkDictionary(missingDictionaries, desc.className(), desc.unwrappedType())) {
313  checkDictionaryOfWrappedType(missingDictionaries, desc.className());
314  branchNamesForMissing.emplace_back(desc.branchName());
315  producedTypes.emplace_back(desc.className() + std::string(" (read from input)"));
316  continue;
317  }
318  }
319  TypeID typeID(desc.unwrappedType().typeInfo());
320 
321  auto iter = containedTypeMap.find(typeID);
322  bool alreadySawThisType = (iter != containedTypeMap.end());
323 
324  if (!desc.produced() && !alreadySawThisType) {
325  if (!checkDictionary(missingDictionaries, desc.wrappedName(), desc.wrappedType())) {
326  branchNamesForMissing.emplace_back(desc.branchName());
327  producedTypes.emplace_back(desc.className() + std::string(" (read from input)"));
328  continue;
329  }
330  }
331 
332  TypeID wrappedTypeID(desc.wrappedType().typeInfo());
333 
334  TypeID containedTypeID;
335  if (alreadySawThisType) {
336  containedTypeID = iter->second;
337  } else {
338  containedTypeID = productholderindexhelper::getContainedTypeFromWrapper(wrappedTypeID, typeID.className());
339  }
340  bool hasContainedType = (containedTypeID != TypeID(typeid(void)) && containedTypeID != TypeID());
341 
342  std::vector<TypeWithDict>* baseTypesOfContainedType = nullptr;
343 
344  if (!alreadySawThisType) {
345  bool alreadyCheckedConstituents = desc.produced() && !desc.transient();
346  if (!alreadyCheckedConstituents && !desc.transient()) {
347  // This checks dictionaries of the wrapped class and all its constituent classes
348  if (!checkClassDictionaries(missingDictionaries, desc.wrappedName(), desc.wrappedType())) {
349  branchNamesForMissing.emplace_back(desc.branchName());
350  producedTypes.emplace_back(desc.className() + std::string(" (read from input)"));
351  continue;
352  }
353  }
354 
355  if (hasContainedType) {
356  auto iter = containedTypeToBaseTypesMap.find(containedTypeID);
357  if (iter == containedTypeToBaseTypesMap.end()) {
358  std::vector<TypeWithDict> baseTypes;
359  if (!public_base_classes(missingDictionaries, containedTypeID, baseTypes)) {
360  branchNamesForMissing.emplace_back(desc.branchName());
361  if (desc.produced()) {
362  producedTypes.emplace_back(desc.className() + std::string(" (produced in current process)"));
363  } else {
364  producedTypes.emplace_back(desc.className() + std::string(" (read from input)"));
365  }
366  continue;
367  }
368  iter = containedTypeToBaseTypesMap.insert(std::make_pair(containedTypeID, baseTypes)).first;
369  }
370  baseTypesOfContainedType = &iter->second;
371  }
372 
373  // Do this after the dictionary checks of constituents so the list of branch names for missing types
374  // is complete
375  containedTypeMap.emplace(typeID, containedTypeID);
376  } else {
377  if (hasContainedType) {
378  auto iter = containedTypeToBaseTypesMap.find(containedTypeID);
379  if (iter != containedTypeToBaseTypesMap.end()) {
380  baseTypesOfContainedType = &iter->second;
381  }
382  }
383  }
384 
385  if(productTypesConsumed != nullptr && !desc.produced()) {
386  bool mainTypeConsumed = (productTypesConsumed->find(typeID) != productTypesConsumed->end());
387  bool containedTypeConsumed = hasContainedType && (elementTypesConsumed->find(containedTypeID) != elementTypesConsumed->end());
388  if(hasContainedType && !containedTypeConsumed && baseTypesOfContainedType != nullptr) {
389  for(TypeWithDict const& baseType : *baseTypesOfContainedType) {
390  if(elementTypesConsumed->find(TypeID(baseType.typeInfo())) != elementTypesConsumed->end()) {
391  containedTypeConsumed = true;
392  break;
393  }
394  }
395  }
396  if(!containedTypeConsumed) {
397  if(mainTypeConsumed) {
398  // The main type is consumed, but either
399  // there is no contained type, or if there is,
400  // neither it nor any of its base classes are consumed.
401  // Set the contained type, if there is one, to void,
402  if(hasContainedType) {
403  containedTypeID = TypeID(typeid(void));
404  }
405  } else {
406  // The main type is not consumed, and either
407  // there is no contained type, or if there is,
408  // neither it nor any of its base classes are consumed.
409  // Don't insert anything in the lookup tables.
410  continue;
411  }
412  }
413  }
415  productLookup(desc.branchType())->insert(typeID,
416  desc.moduleLabel().c_str(),
417  desc.productInstanceName().c_str(),
418  desc.processName().c_str(),
419  containedTypeID,
420  baseTypesOfContainedType);
421 
422  transient_.branchIDToIndex_[desc.branchID()] = index;
423  }
424  }
425  if (!missingDictionaries.empty()) {
426  std::string context("Calling ProductRegistry::initializeLookupTables");
427  throwMissingDictionariesException(missingDictionaries, context, producedTypes, branchNamesForMissing);
428  }
429 
430  productLookup(InEvent)->setFrozen();
431  productLookup(InLumi)->setFrozen();
432  productLookup(InRun)->setFrozen();
433 
435  transient_.lumiNextIndexValue_ = productLookup(InLumi)->nextIndexValue();
436  transient_.runNextIndexValue_ = productLookup(InRun)->nextIndexValue();
437 
438  for(auto const& product : productList_) {
439  auto const& desc = product.second;
440  if (transient_.branchIDToIndex_.find(desc.branchID()) == transient_.branchIDToIndex_.end()) {
441  transient_.branchIDToIndex_[desc.branchID()] = getNextIndexValue(desc.branchType());
442  ++nextIndexValue(desc.branchType());
443  }
444  }
445  checkDictionariesOfConsumedTypes(productTypesConsumed, elementTypesConsumed, containedTypeMap, containedTypeToBaseTypesMap);
446  }
447 
448  void
449  ProductRegistry::checkDictionariesOfConsumedTypes(std::set<TypeID> const* productTypesConsumed,
450  std::set<TypeID> const* elementTypesConsumed,
451  std::map<TypeID, TypeID> const& containedTypeMap,
452  std::map<TypeID, std::vector<TypeWithDict> >& containedTypeToBaseTypesMap) {
453 
454  std::vector<std::string> missingDictionaries;
455  std::set<std::string> consumedTypesWithMissingDictionaries;
456 
457  if (productTypesConsumed) {
458 
459 
460  // Check dictionaries for all classes declared to be consumed
461  for (auto const& consumedTypeID : *productTypesConsumed) {
462 
463  // We use the containedTypeMap to see which types have already
464  // had their dictionaries checked. We do not waste time rechecking
465  // those dictionaries.
466  if (containedTypeMap.find(consumedTypeID) == containedTypeMap.end()) {
467 
468  std::string wrappedName = wrappedClassName(consumedTypeID.className());
469  TypeWithDict wrappedType = TypeWithDict::byName(wrappedName);
470  if (!checkDictionary(missingDictionaries, wrappedName, wrappedType)) {
471  checkDictionary(missingDictionaries, consumedTypeID);
472  consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
473  continue;
474  }
475  bool transient = false;
476  TDictAttributeMap* wp = wrappedType.getClass()->GetAttributeMap();
477  if (wp && wp->HasKey("persistent") && !strcmp(wp->GetPropertyAsString("persistent"), "false")) {
478  transient = true;
479  }
480  if (transient) {
481  if(!checkDictionary(missingDictionaries, consumedTypeID)) {
482  consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
483  }
484 
485  TypeID containedTypeID = productholderindexhelper::getContainedTypeFromWrapper(TypeID(wrappedType.typeInfo()), consumedTypeID.className());
486  bool hasContainedType = (containedTypeID != TypeID(typeid(void)) && containedTypeID != TypeID());
487  if (hasContainedType) {
488  if (containedTypeToBaseTypesMap.find(containedTypeID) == containedTypeToBaseTypesMap.end()) {
489  std::vector<TypeWithDict> bases;
490  // Run this to check for missing dictionaries, bases is not really used
491  if (!public_base_classes(missingDictionaries, containedTypeID, bases)) {
492  consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
493  }
494  containedTypeToBaseTypesMap.insert(std::make_pair(containedTypeID, bases));
495  }
496  }
497  } else {
498  if (!checkClassDictionaries(missingDictionaries, wrappedName, wrappedType)) {
499  consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
500  }
501  }
502  }
503  }
504  if (!missingDictionaries.empty()) {
505  std::string context("Calling ProductRegistry::initializeLookupTables, checking dictionaries for consumed products");
506  throwMissingDictionariesException(missingDictionaries, context, consumedTypesWithMissingDictionaries, false);
507  }
508  }
509 
510  if (elementTypesConsumed) {
511  missingDictionaries.clear();
512  consumedTypesWithMissingDictionaries.clear();
513  for (auto const& consumedTypeID : *elementTypesConsumed) {
514  if (containedTypeToBaseTypesMap.find(consumedTypeID) == containedTypeToBaseTypesMap.end()) {
515  std::vector<TypeWithDict> bases;
516  // Run this to check for missing dictionaries, bases is not really used
517  if (!public_base_classes(missingDictionaries, consumedTypeID, bases)) {
518  consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
519  }
520  }
521  }
522  if (!missingDictionaries.empty()) {
523  std::string context("Calling ProductRegistry::initializeLookupTables, checking dictionaries for elements of products consumed using View");
524  throwMissingDictionariesException(missingDictionaries, context, consumedTypesWithMissingDictionaries, true);
525  }
526  }
527  }
528 
530  std::string const* processName) const {
531  if (processName &&
532  !desc.produced() &&
533  (*processName == desc.processName())) {
534 
535  throw Exception(errors::Configuration, "Duplicate Process Name.\n")
536  << "The process name " << *processName << " was previously used for products in the input.\n"
537  << "Please modify the configuration file to use a distinct process name.\n"
538  << "Alternately, drop all input products using that process name and the\n"
539  << "descendants of those products.\n";
540  }
541  }
542 
544  std::map<BranchID, ProductResolverIndex>::const_iterator itFind = transient_.branchIDToIndex_.find(iID);
545  if(itFind == transient_.branchIDToIndex_.end()) {
547  }
548  return itFind->second;
549  }
550 
551  void ProductRegistry::print(std::ostream& os) const {
552  for(auto const& product: productList_) {
553  os << product.second << "\n-----\n";
554  }
555  }
556 
557  ProductResolverIndex const&
559  if (branchType == InEvent) return transient_.eventNextIndexValue_;
560  if (branchType == InLumi) return transient_.lumiNextIndexValue_;
562  }
563 
566  if (branchType == InEvent) return transient_.eventNextIndexValue_;
567  if (branchType == InLumi) return transient_.lumiNextIndexValue_;
569  }
570 }
edm::propagate_const< std::shared_ptr< ProductResolverIndexHelper > > lumiProductLookup_
void setProductProduced(BranchType branchType)
void throwMissingDictionariesException(std::vector< std::string > &missingDictionaries, std::string const &context)
unsigned int ProductResolverIndex
void throwIfNotFrozen() const
TypeID getContainedTypeFromWrapper(TypeID const &wrappedtypeID, std::string const &className)
std::vector< std::string > allBranchNames() const
std::map< BranchKey, BranchDescription > ProductList
bool public_base_classes(std::vector< std::string > &missingDictionaries, TypeID const &typeID, std::vector< TypeWithDict > &baseTypes)
bool anyProducts(BranchType const brType) const
std::string const & processName() const
std::shared_ptr< ProductResolverIndexHelper const > lumiProductLookup() const
ProductList::size_type size() const
bool isValid() const
Definition: BranchID.h:24
void addLabelAlias(BranchDescription const &productdesc, std::string const &labelAlias, std::string const &instanceAlias)
std::shared_ptr< ProductResolverIndexHelper const > eventProductLookup() const
BranchType
Definition: BranchType.h:11
virtual void addCalled(BranchDescription const &, bool iFromListener)
static TypeWithDict byName(std::string const &name)
Definition: TypeWithDict.cc:60
ProductList const & productList() const
void initializeLookupTables(std::set< TypeID > const *productTypesConsumed, std::set< TypeID > const *elementTypesConsumed, std::string const *processName)
std::string const & moduleLabel() const
ProductResolverIndex eventNextIndexValue_
bool combinable(BranchDescription const &a, BranchDescription const &b)
bool checkDictionary(std::vector< std::string > &missingDictionaries, TypeID const &typeID)
std::shared_ptr< ProductResolverIndexHelper const > runProductLookup() const
ProductResolverIndex lumiNextIndexValue_
void checkForDuplicateProcessName(BranchDescription const &desc, std::string const *processName) const
ProductResolverIndex & nextIndexValue(BranchType branchType)
bool checkClassDictionaries(std::vector< std::string > &missingDictionaries, TypeID const &typeID)
std::vector< BranchDescription const * > allBranchDescriptions() const
std::string merge(ProductRegistry const &other, std::string const &fileName, BranchDescription::MatchMode branchesMustMatch=BranchDescription::Permissive)
boost::array< bool, NumBranchTypes > productProduced_
BranchID const & branchID() const
bool insert(Storage &iStorage, ItemType *iItem, const IdTag &iIdTag)
Definition: HCMethods.h:49
void setFrozen(bool initializeLookupInfo=true)
void freezeIt(bool frozen=true)
void print(std::ostream &os) const
int k[5][pyjets_maxn]
void sort_all(RandomAccessSequence &s)
wrappers for std::sort
Definition: Algorithms.h:120
ProductResolverIndex runNextIndexValue_
std::string wrappedClassName(std::string const &iFullName)
std::vector< std::pair< std::string, std::string > > aliasToOriginal_
std::shared_ptr< ProductResolverIndexHelper const > productLookup(BranchType branchType) const
ProductResolverIndex const & getNextIndexValue(BranchType branchType) const
HLT enums.
void throwIfFrozen() const
std::string const & className() const
Definition: TypeID.cc:46
void updateFromInput(ProductList const &other)
bool checkDictionaryOfWrappedType(std::vector< std::string > &missingDictionaries, TypeID const &unwrappedTypeID)
void checkDictionariesOfConsumedTypes(std::set< TypeID > const *productTypesConsumed, std::set< TypeID > const *elementTypesConsumed, std::map< TypeID, TypeID > const &containedTypeMap, std::map< TypeID, std::vector< TypeWithDict > > &containedTypeToBaseTypesMap)
edm::propagate_const< std::shared_ptr< ProductResolverIndexHelper > > eventProductLookup_
ProductResolverIndex indexFrom(BranchID const &iID) const
void addProduct(BranchDescription const &productdesc, bool iFromListener=false)
std::map< BranchID, ProductResolverIndex > branchIDToIndex_
edm::propagate_const< std::shared_ptr< ProductResolverIndexHelper > > runProductLookup_
def branchType(schema, name)
Definition: revisionDML.py:112
void copyProduct(BranchDescription const &productdesc)
std::string match(BranchDescription const &a, BranchDescription const &b, std::string const &fileName)