21 #include "TDictAttributeMap.h"
37 anyProductProduced_(
false),
38 productLookups_{{std::make_unique<ProductResolverIndexHelper>(),
39 std::make_unique<ProductResolverIndexHelper>(),
40 std::make_unique<ProductResolverIndexHelper>(),
41 std::make_unique<ProductResolverIndexHelper>()}},
44 for (
bool& isProduced : productProduced_)
50 for (
bool& isProduced : productProduced_)
52 anyProductProduced_ =
false;
55 for (
auto& iterProductLookup : productLookups_) {
56 iterProductLookup = std::make_unique<ProductResolverIndexHelper>();
58 nextIndexValues_.fill(0);
60 branchIDToIndex_.clear();
71 std::pair<ProductList::iterator, bool>
ret =
78 <<
"\nThe Framework requires a unique branch name for each product\n"
79 <<
"which consists of four parts: a friendly class name, module label,\n"
80 <<
"product instance name, and process name. A product has been\n"
81 <<
"registered with a duplicate branch name. The most common way\n"
82 <<
"to fix this error is to modify the product instance name in\n"
83 <<
"one of the offending 'produces' function calls. Another fix\n"
84 <<
"would be to delete one of them if they are for the same product.\n\n"
85 <<
" friendly class name = " <<
previous.second.friendlyClassName() <<
"\n"
86 <<
" module label = " <<
previous.second.moduleLabel() <<
"\n"
87 <<
" product instance name = " <<
previous.second.productInstanceName() <<
"\n"
88 <<
" process name = " <<
previous.second.processName() <<
"\n\n"
89 <<
"The following additional information is not used as part of\n"
90 <<
"the unique branch identifier.\n\n"
91 <<
" branch types = " <<
previous.second.branchType() <<
" " << productDesc.
branchType() <<
"\n"
92 <<
" class name = " <<
previous.second.fullClassName() <<
"\n\n"
93 <<
"Note that if the four parts of the branch name are the same,\n"
94 <<
"then this error will occur even if the branch types differ!\n\n";
98 <<
"The process name " << productDesc.
processName() <<
" was previously used for products in the input.\n"
99 <<
"This has caused branch name conflicts between input products and new products.\n"
100 <<
"Please modify the configuration file to use a distinct process name.\n"
101 <<
"Alternately, drop all input products using that process name and the\n"
102 <<
"descendants of those products.\n";
131 iter->second.merge(productDesc);
138 if (it->second.branchType() == brType) {
157 if (initializeLookupInfo) {
164 std::set<TypeID>
const& elementTypesConsumed,
176 <<
"cannot modify the ProductRegistry because it is frozen\n";
183 <<
"cannot read the ProductRegistry because it is not yet frozen\n";
190 std::vector<std::string>
result;
194 result.push_back(product.second.branchName());
200 std::vector<BranchDescription const*>
result;
204 result.push_back(&product.second);
210 for (
auto const& product :
other) {
224 bool hasAliases =
false;
225 std::vector<BranchID> onDemandIDs;
228 unscheduledLabels.end() != unscheduledLabels.find(
prod.second.moduleLabel())) {
229 prod.second.setOnDemand(
true);
230 onDemandIDs.push_back(
prod.second.branchID());
232 if (
prod.second.produced() &&
prod.second.isAlias()) {
239 std::sort(onDemandIDs.begin(), onDemandIDs.end());
241 if (
prod.second.isAlias()) {
242 if (std::binary_search(onDemandIDs.begin(), onDemandIDs.end(),
prod.second.aliasForBranchID())) {
243 prod.second.setOnDemand(
true);
253 std::ostringstream differences;
255 ProductRegistry::ProductList::iterator
j =
productList_.begin();
256 ProductRegistry::ProductList::iterator
s =
productList_.end();
257 ProductRegistry::ProductList::const_iterator
i =
other.productList().begin();
258 ProductRegistry::ProductList::const_iterator
e =
other.productList().end();
261 while (
j !=
s ||
i !=
e) {
262 if (
j !=
s &&
j->second.produced()) {
265 }
else if (
j ==
s || (
i !=
e &&
i->first <
j->first)) {
266 if (
i->second.present()) {
267 differences <<
"Branch '" <<
i->second.branchName() <<
"' is in file '" <<
fileName <<
"'\n";
268 differences <<
" but not in previous files.\n";
275 }
else if (
i ==
e || (
j !=
s &&
j->first <
i->first)) {
277 differences <<
"Branch '" <<
j->second.branchName() <<
"' is in previous files\n";
278 differences <<
" but not in file '" <<
fileName <<
"'.\n";
284 j->second.merge(
i->second);
292 return differences.str();
296 std::set<TypeID>
const* elementTypesConsumed,
298 std::map<TypeID, TypeID> containedTypeMap;
299 std::map<TypeID, std::vector<TypeWithDict>> containedTypeToBaseTypesMap;
301 std::vector<std::string> missingDictionaries;
302 std::vector<std::string> branchNamesForMissing;
303 std::vector<std::string> producedTypes;
308 auto const&
desc = product.second;
312 if (
desc.produced() && !
desc.transient()) {
317 if (
desc.present()) {
322 if (!
desc.produced()) {
325 branchNamesForMissing.emplace_back(
desc.branchName());
326 producedTypes.emplace_back(
desc.className() +
std::string(
" (read from input)"));
330 TypeID typeID(
desc.unwrappedType().typeInfo());
332 auto iterContainedType = containedTypeMap.find(typeID);
333 bool alreadySawThisType = (iterContainedType != containedTypeMap.end());
335 if (!
desc.produced() && !alreadySawThisType) {
337 branchNamesForMissing.emplace_back(
desc.branchName());
338 producedTypes.emplace_back(
desc.className() +
std::string(
" (read from input)"));
343 TypeID wrappedTypeID(
desc.wrappedType().typeInfo());
346 if (alreadySawThisType) {
347 containedTypeID = iterContainedType->second;
351 bool hasContainedType = (containedTypeID !=
TypeID(
typeid(
void)) && containedTypeID !=
TypeID());
353 std::vector<TypeWithDict>* baseTypesOfContainedType =
nullptr;
355 if (!alreadySawThisType) {
356 bool alreadyCheckedConstituents =
desc.produced() && !
desc.transient();
357 if (!alreadyCheckedConstituents && !
desc.transient()) {
360 branchNamesForMissing.emplace_back(
desc.branchName());
361 producedTypes.emplace_back(
desc.className() +
std::string(
" (read from input)"));
366 if (hasContainedType) {
367 auto iterBaseTypes = containedTypeToBaseTypesMap.find(containedTypeID);
368 if (iterBaseTypes == containedTypeToBaseTypesMap.end()) {
369 std::vector<TypeWithDict> baseTypes;
371 branchNamesForMissing.emplace_back(
desc.branchName());
372 if (
desc.produced()) {
373 producedTypes.emplace_back(
desc.className() +
std::string(
" (produced in current process)"));
375 producedTypes.emplace_back(
desc.className() +
std::string(
" (read from input)"));
379 iterBaseTypes = containedTypeToBaseTypesMap.insert(std::make_pair(containedTypeID, baseTypes)).first;
381 baseTypesOfContainedType = &iterBaseTypes->second;
386 containedTypeMap.emplace(typeID, containedTypeID);
388 if (hasContainedType) {
389 auto iterBaseTypes = containedTypeToBaseTypesMap.find(containedTypeID);
390 if (iterBaseTypes != containedTypeToBaseTypesMap.end()) {
391 baseTypesOfContainedType = &iterBaseTypes->second;
396 if (productTypesConsumed !=
nullptr && !
desc.produced()) {
397 bool mainTypeConsumed = (productTypesConsumed->find(typeID) != productTypesConsumed->end());
398 bool containedTypeConsumed =
399 hasContainedType && (elementTypesConsumed->find(containedTypeID) != elementTypesConsumed->end());
400 if (hasContainedType && !containedTypeConsumed && baseTypesOfContainedType !=
nullptr) {
401 for (
TypeWithDict const& baseType : *baseTypesOfContainedType) {
402 if (elementTypesConsumed->find(
TypeID(baseType.typeInfo())) != elementTypesConsumed->end()) {
403 containedTypeConsumed =
true;
408 if (!containedTypeConsumed) {
409 if (mainTypeConsumed) {
414 if (hasContainedType) {
415 containedTypeID =
TypeID(
typeid(
void));
428 desc.moduleLabel().c_str(),
429 desc.productInstanceName().c_str(),
430 desc.processName().c_str(),
432 baseTypesOfContainedType);
437 if (!missingDictionaries.empty()) {
438 std::string context(
"Calling ProductRegistry::initializeLookupTables");
443 iterProductLookup->setFrozen();
446 unsigned int indexIntoNextIndexValue = 0;
449 ++indexIntoNextIndexValue;
453 auto const&
desc = product.second;
460 productTypesConsumed, elementTypesConsumed, containedTypeMap, containedTypeToBaseTypesMap);
466 std::set<TypeID>
const* elementTypesConsumed,
467 std::map<TypeID, TypeID>
const& containedTypeMap,
468 std::map<
TypeID, std::vector<TypeWithDict>>
const& containedTypeToBaseTypesMap) {
471 auto iterContainedType = containedTypeMap.find(std::get<Transients::kType>(
item));
472 if (iterContainedType == containedTypeMap.end()) {
474 ex <<
"containedTypeMap did not contain " << std::get<Transients::kType>(
item).className()
475 <<
" that is used in EDAlias " << std::get<Transients::kModuleLabel>(
item)
476 <<
".\nThis should not happen, contact framework developers";
477 ex.
addContext(
"Calling ProductRegistry::initializeLookupTables()");
480 auto const& containedTypeID = iterContainedType->second;
481 bool const hasContainedType = (containedTypeID !=
TypeID(
typeid(
void)) && containedTypeID !=
TypeID());
482 if (not hasContainedType) {
486 if (elementTypesConsumed->find(containedTypeID) != elementTypesConsumed->end()) {
489 std::get<Transients::kModuleLabel>(
item),
490 std::get<Transients::kProductInstanceName>(
item),
491 std::get<Transients::kAliasForModuleLabel>(
item));
494 auto iterBaseTypes = containedTypeToBaseTypesMap.find(containedTypeID);
495 if (iterBaseTypes == containedTypeToBaseTypesMap.end()) {
498 for (
TypeWithDict const& baseType : iterBaseTypes->second) {
500 if (elementTypesConsumed->find(baseTypeID) != elementTypesConsumed->end()) {
503 std::get<Transients::kModuleLabel>(
item),
504 std::get<Transients::kProductInstanceName>(
item),
505 std::get<Transients::kAliasForModuleLabel>(
item));
510 std::make_move_iterator(elementAliases.begin()),
511 std::make_move_iterator(elementAliases.end()));
515 std::set<TypeID>
const* productTypesConsumed,
516 std::set<TypeID>
const* elementTypesConsumed,
517 std::map<TypeID, TypeID>
const& containedTypeMap,
518 std::map<
TypeID, std::vector<TypeWithDict>>& containedTypeToBaseTypesMap) {
519 std::vector<std::string> missingDictionaries;
520 std::set<std::string> consumedTypesWithMissingDictionaries;
522 if (productTypesConsumed) {
524 for (
auto const& consumedTypeID : *productTypesConsumed) {
528 if (containedTypeMap.find(consumedTypeID) == containedTypeMap.end()) {
533 consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
536 bool transient =
false;
537 TDictAttributeMap*
wp = wrappedType.getClass()->GetAttributeMap();
538 if (
wp &&
wp->HasKey(
"persistent") && !strcmp(
wp->GetPropertyAsString(
"persistent"),
"false")) {
543 consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
548 bool hasContainedType = (containedTypeID !=
TypeID(
typeid(
void)) && containedTypeID !=
TypeID());
549 if (hasContainedType) {
550 if (containedTypeToBaseTypesMap.find(containedTypeID) == containedTypeToBaseTypesMap.end()) {
551 std::vector<TypeWithDict> bases;
554 consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
556 containedTypeToBaseTypesMap.insert(std::make_pair(containedTypeID, bases));
561 consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
566 if (!missingDictionaries.empty()) {
568 "Calling ProductRegistry::initializeLookupTables, checking dictionaries for consumed products");
573 if (elementTypesConsumed) {
574 missingDictionaries.clear();
575 consumedTypesWithMissingDictionaries.clear();
576 for (
auto const& consumedTypeID : *elementTypesConsumed) {
577 if (containedTypeToBaseTypesMap.find(consumedTypeID) == containedTypeToBaseTypesMap.end()) {
578 std::vector<TypeWithDict> bases;
581 consumedTypesWithMissingDictionaries.emplace(consumedTypeID.className());
585 if (!missingDictionaries.empty()) {
587 "Calling ProductRegistry::initializeLookupTables, checking dictionaries for elements of products consumed "
598 <<
"The process name " << *
processName <<
" was previously used for products in the input.\n"
599 <<
"Please modify the configuration file to use a distinct process name.\n"
600 <<
"Alternately, drop all input products using that process name and the\n"
601 <<
"descendants of those products.\n";
610 return itFind->second;
616 std::string_view productInstanceName)
const {
617 auto aliasFields = [](
auto const&
item) {
618 return std::tie(std::get<Transients::kKind>(
item),
619 std::get<Transients::kType>(
item),
620 std::get<Transients::kModuleLabel>(
item),
621 std::get<Transients::kProductInstanceName>(
item));
629 std::vector<std::string>
ret;
631 ret.emplace_back(std::get<Transients::kAliasForModuleLabel>(*
found));
638 os << product.second <<
"\n-----\n";