Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:54:31

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