Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:05:03

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     // do not call init here! It will result in an exception throw.
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);  // will be re-set externally to the aliasForBranch.onDemand() after that one has been set
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;  // already called
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     // Module labels of non-persistent products are allowed to contain
0122     // underscores. For module labels of persistent products, the module
0123     // label is checked for underscores in the function initFromDictionary
0124     // after we determine whether the product is persistent or not.
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;  // already initialized;
0158     }
0159 
0160     throwIfInvalid_();
0161 
0162     try {
0163       setWrappedName(wrappedClassName(fullClassName()));
0164       // unwrapped type.
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       // Set transient if persistent == "false".
0196       setTransient(true);
0197       return;
0198     } else {
0199       // Module labels of persistent products cannot contain underscores,
0200       // but for non-persistent products it is allowed because path names
0201       // are used as module labels for path status products and there
0202       // are many path names that include underscores.
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);  //Compensate for wrapper
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       // Need not compare components of branch name individually.
0357       // (a.friendlyClassName() != b.friendlyClassName())
0358       // (a.moduleLabel() != b.moduleLabel())
0359       // (a.productInstanceName() != b.productInstanceName())
0360       // (a.processName() != b.processName())
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 }  // namespace edm