File indexing completed on 2023-03-17 10:51:07
0001 #include "DataFormats/Provenance/interface/BranchDescription.h"
0002
0003 #include "FWCore/Utilities/interface/EDMException.h"
0004 #include "FWCore/Utilities/interface/Exception.h"
0005 #include "FWCore/Utilities/interface/FriendlyName.h"
0006 #include "FWCore/Reflection/interface/FunctionWithDict.h"
0007 #include "FWCore/Reflection/interface/TypeWithDict.h"
0008 #include "FWCore/Utilities/interface/WrappedClassName.h"
0009
0010 #include "TDictAttributeMap.h"
0011
0012 #include <cassert>
0013 #include <ostream>
0014 #include <sstream>
0015
0016 class TClass;
0017
0018 namespace edm {
0019 BranchDescription::Transients::Transients()
0020 : parameterSetID_(),
0021 moduleName_(),
0022 branchName_(),
0023 wrappedName_(),
0024 wrappedType_(),
0025 unwrappedType_(),
0026 splitLevel_(),
0027 basketSize_(),
0028 produced_(false),
0029 onDemand_(false),
0030 isTransform_(false),
0031 dropped_(false),
0032 transient_(false),
0033 availableOnlyAtEndTransition_(false),
0034 isMergeable_(false) {}
0035
0036 void BranchDescription::Transients::reset() { *this = BranchDescription::Transients(); }
0037
0038 BranchDescription::BranchDescription()
0039 : branchType_(InEvent),
0040 moduleLabel_(),
0041 processName_(),
0042 branchID_(),
0043 fullClassName_(),
0044 friendlyClassName_(),
0045 productInstanceName_(),
0046 branchAliases_(),
0047 aliasForBranchID_(),
0048 transient_() {
0049
0050 }
0051
0052 BranchDescription::BranchDescription(BranchType const& branchType,
0053 std::string const& moduleLabel,
0054 std::string const& processName,
0055 std::string const& className,
0056 std::string const& friendlyClassName,
0057 std::string const& productInstanceName,
0058 std::string const& moduleName,
0059 ParameterSetID const& parameterSetID,
0060 TypeWithDict const& theTypeWithDict,
0061 bool produced,
0062 bool availableOnlyAtEndTransition,
0063 std::set<std::string> const& aliases)
0064 : branchType_(branchType),
0065 moduleLabel_(moduleLabel),
0066 processName_(processName),
0067 branchID_(),
0068 fullClassName_(className),
0069 friendlyClassName_(friendlyClassName),
0070 productInstanceName_(productInstanceName),
0071 branchAliases_(aliases),
0072 transient_() {
0073 setDropped(false);
0074 setProduced(produced);
0075 setOnDemand(false);
0076 transient_.moduleName_ = moduleName;
0077 transient_.parameterSetID_ = parameterSetID;
0078 transient_.availableOnlyAtEndTransition_ = availableOnlyAtEndTransition;
0079 setUnwrappedType(theTypeWithDict);
0080 init();
0081 }
0082
0083 BranchDescription::BranchDescription(BranchDescription const& aliasForBranch,
0084 std::string const& moduleLabelAlias,
0085 std::string const& productInstanceAlias)
0086 : branchType_(aliasForBranch.branchType()),
0087 moduleLabel_(moduleLabelAlias),
0088 processName_(aliasForBranch.processName()),
0089 branchID_(),
0090 fullClassName_(aliasForBranch.className()),
0091 friendlyClassName_(aliasForBranch.friendlyClassName()),
0092 productInstanceName_(productInstanceAlias),
0093 branchAliases_(aliasForBranch.branchAliases()),
0094 aliasForBranchID_(aliasForBranch.branchID()),
0095 transient_() {
0096 setDropped(false);
0097 setProduced(aliasForBranch.produced());
0098 setOnDemand(false);
0099 transient_.availableOnlyAtEndTransition_ = aliasForBranch.availableOnlyAtEndTransition();
0100 transient_.moduleName_ = aliasForBranch.moduleName();
0101 transient_.parameterSetID_ = aliasForBranch.parameterSetID();
0102 setUnwrappedType(aliasForBranch.unwrappedType());
0103 init();
0104 }
0105
0106 void BranchDescription::initBranchName() {
0107 if (!branchName().empty()) {
0108 return;
0109 }
0110 throwIfInvalid_();
0111
0112 char const underscore('_');
0113 char const period('.');
0114
0115 if (friendlyClassName_.find(underscore) != std::string::npos) {
0116 throw cms::Exception("IllegalCharacter")
0117 << "Class name '" << friendlyClassName()
0118 << "' contains an underscore ('_'), which is illegal in the name of a product.\n";
0119 }
0120
0121
0122
0123
0124
0125
0126 if (productInstanceName_.find(underscore) != std::string::npos) {
0127 throw cms::Exception("IllegalCharacter")
0128 << "Product instance name '" << productInstanceName()
0129 << "' contains an underscore ('_'), which is illegal in a product instance name.\n";
0130 }
0131
0132 if (processName_.find(underscore) != std::string::npos) {
0133 throw cms::Exception("IllegalCharacter")
0134 << "Process name '" << processName()
0135 << "' contains an underscore ('_'), which is illegal in a process name.\n";
0136 }
0137
0138 std::string& brName = transient_.branchName_;
0139 brName.reserve(friendlyClassName().size() + moduleLabel().size() + productInstanceName().size() +
0140 processName().size() + 4);
0141 brName += friendlyClassName();
0142 brName += underscore;
0143 brName += moduleLabel();
0144 brName += underscore;
0145 brName += productInstanceName();
0146 brName += underscore;
0147 brName += processName();
0148 brName += period;
0149
0150 if (!branchID_.isValid()) {
0151 branchID_.setID(brName);
0152 }
0153 }
0154
0155 void BranchDescription::initFromDictionary() {
0156 if (bool(wrappedType())) {
0157 return;
0158 }
0159
0160 throwIfInvalid_();
0161
0162 try {
0163 setWrappedName(wrappedClassName(fullClassName()));
0164
0165 setUnwrappedType(TypeWithDict::byName(fullClassName()));
0166 if (!bool(unwrappedType())) {
0167 setSplitLevel(invalidSplitLevel);
0168 setBasketSize(invalidBasketSize);
0169 setTransient(false);
0170 return;
0171 }
0172 } catch (edm::Exception& caughtException) {
0173 caughtException.addContext(std::string{"While initializing meta data for branch: "} + branchName());
0174 throw;
0175 }
0176
0177 edm::TypeWithDict wrType(TypeWithDict::byName(wrappedName()));
0178 try {
0179 setWrappedType(wrType);
0180 if (!bool(wrappedType())) {
0181 setSplitLevel(invalidSplitLevel);
0182 setBasketSize(invalidBasketSize);
0183 return;
0184 }
0185 } catch (edm::Exception& caughtException) {
0186 caughtException.addContext(std::string{"While initializing meta data for branch: "} + branchName());
0187 throw;
0188 }
0189
0190 setTransient(false);
0191 setSplitLevel(invalidSplitLevel);
0192 setBasketSize(invalidBasketSize);
0193 TDictAttributeMap* wp = wrappedType().getClass()->GetAttributeMap();
0194 if (wp && wp->HasKey("persistent") && !strcmp(wp->GetPropertyAsString("persistent"), "false")) {
0195
0196 setTransient(true);
0197 return;
0198 } else {
0199
0200
0201
0202
0203 char const underscore('_');
0204 if (moduleLabel_.find(underscore) != std::string::npos) {
0205 throw cms::Exception("IllegalCharacter")
0206 << "Module label '" << moduleLabel()
0207 << "' contains an underscore ('_'), which is illegal in a module label.\n";
0208 }
0209 }
0210
0211 if (wp && wp->HasKey("splitLevel")) {
0212 setSplitLevel(strtol(wp->GetPropertyAsString("splitLevel"), nullptr, 0));
0213 if (splitLevel() < 0) {
0214 throw cms::Exception("IllegalSplitLevel") << "' An illegal ROOT split level of " << splitLevel()
0215 << " is specified for class " << wrappedName() << ".'\n";
0216 }
0217 setSplitLevel(splitLevel() + 1);
0218 }
0219 if (wp && wp->HasKey("basketSize")) {
0220 setBasketSize(strtol(wp->GetPropertyAsString("basketSize"), nullptr, 0));
0221 if (basketSize() <= 0) {
0222 throw cms::Exception("IllegalBasketSize") << "' An illegal ROOT basket size of " << basketSize()
0223 << " is specified for class " << wrappedName() << "'.\n";
0224 }
0225 }
0226 }
0227
0228 void BranchDescription::merge(BranchDescription const& other) {
0229 branchAliases_.insert(other.branchAliases().begin(), other.branchAliases().end());
0230 if (splitLevel() == invalidSplitLevel)
0231 setSplitLevel(other.splitLevel());
0232 if (basketSize() == invalidBasketSize)
0233 setBasketSize(other.basketSize());
0234 }
0235
0236 void BranchDescription::setSwitchAliasForBranch(BranchDescription const& aliasForBranch) {
0237 if (branchType_ != aliasForBranch.branchType()) {
0238 throw Exception(errors::LogicError) << "BranchDescription::setSwitchAliasForBranch: branchType (" << branchType_
0239 << ") differs from aliasForBranch (" << aliasForBranch.branchType()
0240 << ").\nPlease report this error to the FWCore developers";
0241 }
0242 if (produced() != aliasForBranch.produced()) {
0243 throw Exception(errors::LogicError) << "BranchDescription::setSwitchAliasForBranch: produced differs from "
0244 "aliasForBranch.\nPlease report this error to the FWCore developers";
0245 }
0246 if (unwrappedTypeID().typeInfo() != aliasForBranch.unwrappedType().typeInfo()) {
0247 throw Exception(errors::LogicError)
0248 << "BranchDescription::setSwitchAliasForBranch: unwrapped type info (" << unwrappedTypeID().name()
0249 << ") differs from aliasForBranch (" << aliasForBranch.unwrappedType().typeInfo().name()
0250 << ").\nPlease report this error to the FWCore developers";
0251 }
0252
0253 branchAliases_ = aliasForBranch.branchAliases();
0254 transient_.switchAliasForBranchID_ = aliasForBranch.originalBranchID();
0255 transient_.availableOnlyAtEndTransition_ = aliasForBranch.availableOnlyAtEndTransition();
0256 }
0257
0258 void BranchDescription::write(std::ostream& os) const {
0259 os << "Branch Type = " << branchType() << std::endl;
0260 os << "Process Name = " << processName() << std::endl;
0261 os << "ModuleLabel = " << moduleLabel() << std::endl;
0262 os << "Branch ID = " << branchID() << '\n';
0263 os << "Class Name = " << fullClassName() << '\n';
0264 os << "Friendly Class Name = " << friendlyClassName() << '\n';
0265 os << "Product Instance Name = " << productInstanceName() << std::endl;
0266 }
0267
0268 void throwExceptionWithText(char const* txt) {
0269 Exception e(errors::LogicError);
0270 e << "Problem using an incomplete BranchDescription\n"
0271 << txt << "\nPlease report this error to the FWCore developers";
0272 throw e;
0273 }
0274
0275 void BranchDescription::throwIfInvalid_() const {
0276 if (branchType_ >= NumBranchTypes)
0277 throwExceptionWithText("Illegal BranchType detected");
0278
0279 if (moduleLabel_.empty())
0280 throwExceptionWithText("Module label is not allowed to be empty");
0281
0282 if (processName_.empty())
0283 throwExceptionWithText("Process name is not allowed to be empty");
0284
0285 if (fullClassName_.empty())
0286 throwExceptionWithText("Full class name is not allowed to be empty");
0287
0288 if (friendlyClassName_.empty())
0289 throwExceptionWithText("Friendly class name is not allowed to be empty");
0290
0291 if (produced() && !parameterSetID().isValid())
0292 throwExceptionWithText("Invalid ParameterSetID detected");
0293 }
0294
0295 void BranchDescription::updateFriendlyClassName() {
0296 friendlyClassName_ = friendlyname::friendlyName(fullClassName());
0297 clearBranchName();
0298 initBranchName();
0299 }
0300
0301 bool operator<(BranchDescription const& a, BranchDescription const& b) {
0302 if (a.processName() < b.processName())
0303 return true;
0304 if (b.processName() < a.processName())
0305 return false;
0306 if (a.fullClassName() < b.fullClassName())
0307 return true;
0308 if (b.fullClassName() < a.fullClassName())
0309 return false;
0310 if (a.friendlyClassName() < b.friendlyClassName())
0311 return true;
0312 if (b.friendlyClassName() < a.friendlyClassName())
0313 return false;
0314 if (a.productInstanceName() < b.productInstanceName())
0315 return true;
0316 if (b.productInstanceName() < a.productInstanceName())
0317 return false;
0318 if (a.moduleLabel() < b.moduleLabel())
0319 return true;
0320 if (b.moduleLabel() < a.moduleLabel())
0321 return false;
0322 if (a.branchType() < b.branchType())
0323 return true;
0324 if (b.branchType() < a.branchType())
0325 return false;
0326 if (a.branchID() < b.branchID())
0327 return true;
0328 if (b.branchID() < a.branchID())
0329 return false;
0330 if (a.branchAliases() < b.branchAliases())
0331 return true;
0332 if (b.branchAliases() < a.branchAliases())
0333 return false;
0334 if (a.present() < b.present())
0335 return true;
0336 if (b.present() < a.present())
0337 return false;
0338 return false;
0339 }
0340
0341 bool combinable(BranchDescription const& a, BranchDescription const& b) {
0342 return (a.branchType() == b.branchType()) && (a.processName() == b.processName()) &&
0343 (a.fullClassName() == b.fullClassName()) && (a.friendlyClassName() == b.friendlyClassName()) &&
0344 (a.productInstanceName() == b.productInstanceName()) && (a.moduleLabel() == b.moduleLabel()) &&
0345 (a.branchID() == b.branchID());
0346 }
0347
0348 bool operator==(BranchDescription const& a, BranchDescription const& b) {
0349 return combinable(a, b) && (a.dropped() == b.dropped()) && (a.branchAliases() == b.branchAliases());
0350 }
0351
0352 std::string match(BranchDescription const& a, BranchDescription const& b, std::string const& fileName) {
0353 std::ostringstream differences;
0354 if (a.branchName() != b.branchName()) {
0355 differences << "Branch name '" << b.branchName() << "' does not match '" << a.branchName() << "'.\n";
0356
0357
0358
0359
0360
0361 }
0362 if (a.branchType() != b.branchType()) {
0363 differences << "Branch '" << b.branchName() << "' is a(n) '" << b.branchType() << "' branch\n";
0364 differences << " in file '" << fileName << "', but a(n) '" << a.branchType()
0365 << "' branch in previous files.\n";
0366 }
0367 if (a.branchID() != b.branchID()) {
0368 differences << "Branch '" << b.branchName() << "' has a branch ID of '" << b.branchID() << "'\n";
0369 differences << " in file '" << fileName << "', but '" << a.branchID() << "' in previous files.\n";
0370 }
0371 if (a.fullClassName() != b.fullClassName()) {
0372 differences << "Products on branch '" << b.branchName() << "' have type '" << b.fullClassName() << "'\n";
0373 differences << " in file '" << fileName << "', but '" << a.fullClassName() << "' in previous files.\n";
0374 }
0375 if (!b.dropped() && a.dropped()) {
0376 differences << "Branch '" << a.branchName() << "' was dropped in the first input file but is present in '"
0377 << fileName << "'.\n";
0378 }
0379 return differences.str();
0380 }
0381 }