21 #include "TDictAttributeMap.h"
37 anyProductProduced_(
false),
41 eventNextIndexValue_(0),
42 lumiNextIndexValue_(0),
43 runNextIndexValue_(0),
52 for (
bool& isProduced : productProduced_)
54 anyProductProduced_ =
false;
57 eventProductLookup_ = std::make_unique<ProductResolverIndexHelper>();
58 lumiProductLookup_ = std::make_unique<ProductResolverIndexHelper>();
59 runProductLookup_ = std::make_unique<ProductResolverIndexHelper>();
61 eventNextIndexValue_ = 0;
62 lumiNextIndexValue_ = 0;
63 runNextIndexValue_ = 0;
65 branchIDToIndex_.clear();
76 std::pair<ProductList::iterator, bool>
ret =
80 if (previous.second.produced()) {
83 <<
"\nThe Framework requires a unique branch name for each product\n"
84 <<
"which consists of four parts: a friendly class name, module label,\n"
85 <<
"product instance name, and process name. A product has been\n"
86 <<
"registered with a duplicate branch name. The most common way\n"
87 <<
"to fix this error is to modify the product instance name in\n"
88 <<
"one of the offending 'produces' function calls. Another fix\n"
89 <<
"would be to delete one of them if they are for the same product.\n\n"
90 <<
" friendly class name = " << previous.second.friendlyClassName() <<
"\n"
91 <<
" module label = " << previous.second.moduleLabel() <<
"\n"
92 <<
" product instance name = " << previous.second.productInstanceName() <<
"\n"
93 <<
" process name = " << previous.second.processName() <<
"\n\n"
94 <<
"The following additional information is not used as part of\n"
95 <<
"the unique branch identifier.\n\n"
96 <<
" branch types = " << previous.second.branchType() <<
" " << productDesc.
branchType() <<
"\n"
97 <<
" class name = " << previous.second.fullClassName() <<
"\n\n"
98 <<
"Note that if the four parts of the branch name are the same,\n"
99 <<
"then this error will occur even if the branch types differ!\n\n";
103 <<
"The process name " << productDesc.
processName() <<
" was previously used for products in the input.\n"
104 <<
"This has caused branch name conflicts between input products and new products.\n"
105 <<
"Please modify the configuration file to use a distinct process name.\n"
106 <<
"Alternately, drop all input products using that process name and the\n"
107 <<
"descendants of those products.\n";
135 iter->second.merge(productDesc);
142 if (it->second.branchType() == brType) {
169 if (initializeLookupInfo) {
176 std::set<TypeID>
const& elementTypesConsumed,
188 <<
"cannot modify the ProductRegistry because it is frozen\n";
195 <<
"cannot read the ProductRegistry because it is not yet frozen\n";
202 std::vector<std::string>
result;
206 result.push_back(product.second.branchName());
212 std::vector<BranchDescription const*>
result;
216 result.push_back(&product.second);
222 for (
auto const& product :
other) {
236 bool hasAliases =
false;
237 std::vector<BranchID> onDemandIDs;
240 unscheduledLabels.end() != unscheduledLabels.find(
prod.second.moduleLabel())) {
241 prod.second.setOnDemand(
true);
242 onDemandIDs.push_back(
prod.second.branchID());
244 if (
prod.second.produced() &&
prod.second.isAlias()) {
251 std::sort(onDemandIDs.begin(), onDemandIDs.end());
253 if (
prod.second.isAlias()) {
254 if (std::binary_search(onDemandIDs.begin(), onDemandIDs.end(),
prod.second.aliasForBranchID())) {
255 prod.second.setOnDemand(
true);
265 std::ostringstream differences;
267 ProductRegistry::ProductList::iterator
j =
productList_.begin();
268 ProductRegistry::ProductList::iterator
s =
productList_.end();
269 ProductRegistry::ProductList::const_iterator
i =
other.productList().begin();
270 ProductRegistry::ProductList::const_iterator
e =
other.productList().end();
273 while (
j !=
s ||
i !=
e) {
274 if (
j !=
s &&
j->second.produced()) {
277 }
else if (
j ==
s || (
i !=
e &&
i->first <
j->first)) {
278 if (
i->second.present()) {
279 differences <<
"Branch '" <<
i->second.branchName() <<
"' is in file '" <<
fileName <<
"'\n";
280 differences <<
" but not in previous files.\n";
287 }
else if (
i ==
e || (
j !=
s &&
j->first <
i->first)) {
289 differences <<
"Branch '" <<
j->second.branchName() <<
"' is in previous files\n";
290 differences <<
" but not in file '" <<
fileName <<
"'.\n";
296 j->second.merge(
i->second);
304 return differences.str();
308 std::set<TypeID>
const* elementTypesConsumed,
310 std::map<TypeID, TypeID> containedTypeMap;
311 std::map<TypeID, std::vector<TypeWithDict> > containedTypeToBaseTypesMap;
313 std::vector<std::string> missingDictionaries;
314 std::vector<std::string> branchNamesForMissing;
315 std::vector<std::string> producedTypes;
320 auto const& desc = product.second;
324 if (desc.produced() && !desc.transient()) {
329 if (desc.present()) {
334 if (!desc.produced()) {
335 if (!
checkDictionary(missingDictionaries, desc.className(), desc.unwrappedType())) {
337 branchNamesForMissing.emplace_back(desc.branchName());
338 producedTypes.emplace_back(desc.className() +
std::string(
" (read from input)"));
342 TypeID typeID(desc.unwrappedType().typeInfo());
344 auto iterContainedType = containedTypeMap.find(typeID);
345 bool alreadySawThisType = (iterContainedType != containedTypeMap.end());
347 if (!desc.produced() && !alreadySawThisType) {
348 if (!
checkDictionary(missingDictionaries, desc.wrappedName(), desc.wrappedType())) {
349 branchNamesForMissing.emplace_back(desc.branchName());
350 producedTypes.emplace_back(desc.className() +
std::string(
" (read from input)"));
355 TypeID wrappedTypeID(desc.wrappedType().typeInfo());
358 if (alreadySawThisType) {
359 containedTypeID = iterContainedType->second;
363 bool hasContainedType = (containedTypeID !=
TypeID(
typeid(
void)) && containedTypeID !=
TypeID());
365 std::vector<TypeWithDict>* baseTypesOfContainedType =
nullptr;
367 if (!alreadySawThisType) {
368 bool alreadyCheckedConstituents = desc.produced() && !desc.transient();
369 if (!alreadyCheckedConstituents && !desc.transient()) {
372 branchNamesForMissing.emplace_back(desc.branchName());
373 producedTypes.emplace_back(desc.className() +
std::string(
" (read from input)"));
378 if (hasContainedType) {
379 auto iterBaseTypes = containedTypeToBaseTypesMap.find(containedTypeID);
380 if (iterBaseTypes == containedTypeToBaseTypesMap.end()) {
381 std::vector<TypeWithDict> baseTypes;
383 branchNamesForMissing.emplace_back(desc.branchName());
384 if (desc.produced()) {
385 producedTypes.emplace_back(desc.className() +
std::string(
" (produced in current process)"));
387 producedTypes.emplace_back(desc.className() +
std::string(
" (read from input)"));
391 iterBaseTypes = containedTypeToBaseTypesMap.insert(std::make_pair(containedTypeID, baseTypes)).first;
393 baseTypesOfContainedType = &iterBaseTypes->second;
398 containedTypeMap.emplace(typeID, containedTypeID);
400 if (hasContainedType) {
401 auto iterBaseTypes = containedTypeToBaseTypesMap.find(containedTypeID);
402 if (iterBaseTypes != containedTypeToBaseTypesMap.end()) {
403 baseTypesOfContainedType = &iterBaseTypes->second;
408 if (productTypesConsumed !=
nullptr && !desc.produced()) {
409 bool mainTypeConsumed = (productTypesConsumed->find(typeID) != productTypesConsumed->end());
410 bool containedTypeConsumed =
411 hasContainedType && (elementTypesConsumed->find(containedTypeID) != elementTypesConsumed->end());
412 if (hasContainedType && !containedTypeConsumed && baseTypesOfContainedType !=
nullptr) {
413 for (
TypeWithDict const& baseType : *baseTypesOfContainedType) {
414 if (elementTypesConsumed->find(
TypeID(baseType.typeInfo())) != elementTypesConsumed->end()) {
415 containedTypeConsumed =
true;
420 if (!containedTypeConsumed) {
421 if (mainTypeConsumed) {
426 if (hasContainedType) {
427 containedTypeID =
TypeID(
typeid(
void));
440 desc.moduleLabel().c_str(),
441 desc.productInstanceName().c_str(),
442 desc.processName().c_str(),
444 baseTypesOfContainedType);
449 if (!missingDictionaries.empty()) {
450 std::string context(
"Calling ProductRegistry::initializeLookupTables");
463 auto const& desc = product.second;
470 productTypesConsumed, elementTypesConsumed, containedTypeMap, containedTypeToBaseTypesMap);
474 std::set<TypeID>
const* productTypesConsumed,
475 std::set<TypeID>
const* elementTypesConsumed,
476 std::map<TypeID, TypeID>
const& containedTypeMap,
477 std::map<
TypeID, std::vector<TypeWithDict> >& containedTypeToBaseTypesMap) {
478 std::vector<std::string> missingDictionaries;
479 std::set<std::string> consumedTypesWithMissingDictionaries;
481 if (productTypesConsumed) {
483 for (
auto const& consumedTypeID : *productTypesConsumed) {
487 if (containedTypeMap.find(consumedTypeID) == containedTypeMap.end()) {
492 consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
495 bool transient =
false;
496 TDictAttributeMap*
wp = wrappedType.getClass()->GetAttributeMap();
497 if (
wp &&
wp->HasKey(
"persistent") && !strcmp(
wp->GetPropertyAsString(
"persistent"),
"false")) {
502 consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
507 bool hasContainedType = (containedTypeID !=
TypeID(
typeid(
void)) && containedTypeID !=
TypeID());
508 if (hasContainedType) {
509 if (containedTypeToBaseTypesMap.find(containedTypeID) == containedTypeToBaseTypesMap.end()) {
510 std::vector<TypeWithDict> bases;
513 consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
515 containedTypeToBaseTypesMap.insert(std::make_pair(containedTypeID, bases));
520 consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
525 if (!missingDictionaries.empty()) {
527 "Calling ProductRegistry::initializeLookupTables, checking dictionaries for consumed products");
532 if (elementTypesConsumed) {
533 missingDictionaries.clear();
534 consumedTypesWithMissingDictionaries.clear();
535 for (
auto const& consumedTypeID : *elementTypesConsumed) {
536 if (containedTypeToBaseTypesMap.find(consumedTypeID) == containedTypeToBaseTypesMap.end()) {
537 std::vector<TypeWithDict> bases;
540 consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
544 if (!missingDictionaries.empty()) {
546 "Calling ProductRegistry::initializeLookupTables, checking dictionaries for elements of products consumed "
557 <<
"The process name " << *
processName <<
" was previously used for products in the input.\n"
558 <<
"Please modify the configuration file to use a distinct process name.\n"
559 <<
"Alternately, drop all input products using that process name and the\n"
560 <<
"descendants of those products.\n";
569 return itFind->second;
574 os << product.second <<
"\n-----\n";