00001
00011 #include "DataFormats/Provenance/interface/ProductRegistry.h"
00012
00013 #include "FWCore/Utilities/interface/Algorithms.h"
00014 #include "FWCore/Utilities/interface/EDMException.h"
00015 #include "FWCore/Utilities/interface/DictionaryTools.h"
00016 #include "FWCore/Utilities/interface/TypeID.h"
00017 #include "FWCore/Utilities/interface/TypeWithDict.h"
00018 #include "FWCore/Utilities/interface/WrappedClassName.h"
00019
00020 #include <algorithm>
00021 #include <limits>
00022 #include <sstream>
00023
00024 namespace edm {
00025 namespace {
00026 void checkDicts(BranchDescription const& productDesc) {
00027 if(productDesc.transient()) {
00028 checkDictionaries(productDesc.fullClassName(), true);
00029 checkDictionaries(wrappedClassName(productDesc.fullClassName()), true);
00030 } else {
00031 checkDictionaries(wrappedClassName(productDesc.fullClassName()), false);
00032 }
00033 }
00034 }
00035
00036 ProductRegistry::ProductRegistry() :
00037 productList_(),
00038 transient_() {
00039 }
00040
00041 ProductRegistry::Transients::Transients() :
00042 frozen_(false),
00043 constProductList_(),
00044 productProduced_(),
00045 anyProductProduced_(false),
00046 productLookup_(),
00047 elementLookup_(),
00048 branchIDToIndex_(),
00049 producedBranchListIndex_(std::numeric_limits<BranchListIndex>::max()),
00050 missingDictionaries_() {
00051 for(bool& isProduced : productProduced_) isProduced = false;
00052 }
00053
00054 void
00055 ProductRegistry::Transients::reset() {
00056 frozen_ = false;
00057 constProductList_.clear();
00058 for(bool& isProduced : productProduced_) isProduced = false;
00059 anyProductProduced_ = false;
00060 productLookup_.reset();
00061 elementLookup_.reset();
00062 branchIDToIndex_.clear();
00063 producedBranchListIndex_ = std::numeric_limits<BranchListIndex>::max();
00064 missingDictionaries_.clear();
00065 }
00066
00067 ProductRegistry::ProductRegistry(ProductList const& productList, bool toBeFrozen) :
00068 productList_(productList),
00069 transient_() {
00070 frozen() = toBeFrozen;
00071 }
00072
00073 void
00074 ProductRegistry::addProduct(BranchDescription const& productDesc,
00075 bool fromListener) {
00076 assert(productDesc.produced());
00077 throwIfFrozen();
00078 checkDicts(productDesc);
00079 std::pair<ProductList::iterator, bool> ret =
00080 productList_.insert(std::make_pair(BranchKey(productDesc), productDesc));
00081 if(!ret.second) {
00082 throw Exception(errors::Configuration, "Duplicate Process")
00083 << "The process name " << productDesc.processName() << " was previously used on these products.\n"
00084 << "Please modify the configuration file to use a distinct process name.\n";
00085 }
00086 addCalled(productDesc, fromListener);
00087 }
00088
00089 void
00090 ProductRegistry::addLabelAlias(BranchDescription const& productDesc,
00091 std::string const& labelAlias,
00092 std::string const& instanceAlias) {
00093 assert(productDesc.produced());
00094 assert(productDesc.branchID().isValid());
00095 throwIfFrozen();
00096 BranchDescription bd(productDesc, labelAlias, instanceAlias);
00097 std::pair<ProductList::iterator, bool> ret =
00098 productList_.insert(std::make_pair(BranchKey(bd), bd));
00099 assert(ret.second);
00100 addCalled(bd, false);
00101 }
00102
00103 void
00104 ProductRegistry::copyProduct(BranchDescription const& productDesc) {
00105 assert(!productDesc.produced());
00106 throwIfFrozen();
00107 productDesc.init();
00108 BranchKey k = BranchKey(productDesc);
00109 ProductList::iterator iter = productList_.find(k);
00110 if(iter == productList_.end()) {
00111 productList_.insert(std::make_pair(k, productDesc));
00112 } else {
00113 assert(combinable(iter->second, productDesc));
00114 iter->second.merge(productDesc);
00115 }
00116 }
00117
00118 bool
00119 ProductRegistry::anyProducts(BranchType brType) const {
00120 throwIfNotFrozen();
00121 for(ProductList::const_iterator it = productList_.begin(), itEnd = productList_.end();
00122 it != itEnd; ++it) {
00123 if(it->second.branchType() == brType) {
00124 return true;
00125 }
00126 }
00127 return false;
00128 }
00129
00130 void
00131 ProductRegistry::setFrozen(bool initializeLookupInfo) const {
00132 if(frozen()) return;
00133 frozen() = true;
00134 if(initializeLookupInfo) {
00135 initializeLookupTables();
00136 }
00137 }
00138
00139 void
00140 ProductRegistry::throwIfFrozen() const {
00141 if(frozen()) {
00142 throw cms::Exception("ProductRegistry", "throwIfFrozen")
00143 << "cannot modify the ProductRegistry because it is frozen\n";
00144 }
00145 }
00146
00147 void
00148 ProductRegistry::throwIfNotFrozen() const {
00149 if(!frozen()) {
00150 throw cms::Exception("ProductRegistry", "throwIfNotFrozen")
00151 << "cannot read the ProductRegistry because it is not yet frozen\n";
00152 }
00153 }
00154
00155 void
00156 ProductRegistry::addCalled(BranchDescription const&, bool) {
00157 }
00158
00159 std::vector<std::string>
00160 ProductRegistry::allBranchNames() const {
00161 std::vector<std::string> result;
00162 result.reserve(productList().size());
00163
00164 for(auto const& product : productList()) {
00165 result.push_back(product.second.branchName());
00166 }
00167 return result;
00168 }
00169
00170 std::vector<BranchDescription const*>
00171 ProductRegistry::allBranchDescriptions() const {
00172 std::vector<BranchDescription const*> result;
00173 result.reserve(productList().size());
00174
00175 for(auto const& product : productList()) {
00176 result.push_back(&product.second);
00177 }
00178 return result;
00179 }
00180
00181 void
00182 ProductRegistry::updateFromInput(ProductList const& other) {
00183 for(auto const& product : other) {
00184 copyProduct(product.second);
00185 }
00186 }
00187
00188 void
00189 ProductRegistry::updateFromInput(std::vector<BranchDescription> const& other) {
00190 for(BranchDescription const& branchDescription : other) {
00191 copyProduct(branchDescription);
00192 }
00193 }
00194
00195 std::string
00196 ProductRegistry::merge(ProductRegistry const& other,
00197 std::string const& fileName,
00198 BranchDescription::MatchMode parametersMustMatch,
00199 BranchDescription::MatchMode branchesMustMatch) {
00200 std::ostringstream differences;
00201
00202 ProductRegistry::ProductList::iterator j = productList_.begin();
00203 ProductRegistry::ProductList::iterator s = productList_.end();
00204 ProductRegistry::ProductList::const_iterator i = other.productList().begin();
00205 ProductRegistry::ProductList::const_iterator e = other.productList().end();
00206
00207
00208 while(j != s || i != e) {
00209 if(j != s && j->second.produced()) {
00210
00211 ++j;
00212 } else if(j == s || (i != e && i->first < j->first)) {
00213 if(i->second.present()) {
00214 differences << "Branch '" << i->second.branchName() << "' is in file '" << fileName << "'\n";
00215 differences << " but not in previous files.\n";
00216 } else {
00217 productList_.insert(*i);
00218 }
00219 ++i;
00220 } else if(i == e || (j != s && j->first < i->first)) {
00221 if(j->second.present() && branchesMustMatch == BranchDescription::Strict) {
00222 differences << "Branch '" << j->second.branchName() << "' is in previous files\n";
00223 differences << " but not in file '" << fileName << "'.\n";
00224 }
00225 ++j;
00226 } else {
00227 std::string difs = match(j->second, i->second, fileName, parametersMustMatch);
00228 if(difs.empty()) {
00229 if(parametersMustMatch == BranchDescription::Permissive) j->second.merge(i->second);
00230 } else {
00231 differences << difs;
00232 }
00233 ++i;
00234 ++j;
00235 }
00236 }
00237 initializeLookupTables();
00238 return differences.str();
00239 }
00240
00241 static void
00242 fillLookup(TypeWithDict const& type,
00243 ProductTransientIndex const& index,
00244 ConstBranchDescription const* branchDesc,
00245 TransientProductLookupMap::FillFromMap& oMap) {
00246 oMap[std::make_pair(TypeInBranchType(TypeID(type.typeInfo()),
00247 branchDesc->branchType()),
00248 branchDesc)] = index;
00249 }
00250
00251 void ProductRegistry::initializeLookupTables() const {
00252 StringSet savedMissingTypes;
00253 savedMissingTypes.swap(missingTypes());
00254 StringSet savedFoundTypes;
00255 savedFoundTypes.swap(foundTypes());
00256 constProductList().clear();
00257 transient_.branchIDToIndex_.clear();
00258 ProductTransientIndex index = 0;
00259
00260
00261
00262 typedef TransientProductLookupMap::FillFromMap TempLookupMap;
00263 TempLookupMap tempProductLookupMap;
00264 TempLookupMap tempElementLookupMap;
00265
00266 StringSet usedProcessNames;
00267 StringSet missingDicts;
00268 for(auto const& product : productList_) {
00269 auto const& key = product.first;
00270 auto const& desc = product.second;
00271 if(desc.produced()) {
00272 setProductProduced(desc.branchType());
00273 }
00274
00275
00276
00277 ConstBranchDescription const* pBD = &(constProductList().insert(std::make_pair(key, ConstBranchDescription(desc))).first->second);
00278
00279 transient_.branchIDToIndex_[desc.branchID()] = index;
00280
00281 usedProcessNames.insert(pBD->processName());
00282
00283
00284 if(desc.present()) {
00285 TypeWithDict type(TypeWithDict::byName(desc.className()));
00286 TypeWithDict wrappedType(TypeWithDict::byName(wrappedClassName(desc.className())));
00287 if(!bool(type) || !bool(wrappedType)) {
00288 missingDicts.insert(desc.className());
00289 } else {
00290 fillLookup(type, index, pBD, tempProductLookupMap);
00291
00292 if(bool(type)) {
00293
00294
00295
00296
00297
00298
00299
00300 TypeWithDict valueType;
00301 if((is_RefVector(type, valueType) ||
00302 is_PtrVector(type, valueType) ||
00303 is_RefToBaseVector(type, valueType) ||
00304 value_type_of(type, valueType))
00305 && bool(valueType)) {
00306
00307 fillLookup(valueType, index, pBD, tempElementLookupMap);
00308
00309
00310 std::vector<TypeWithDict> baseTypes;
00311 public_base_classes(valueType, baseTypes);
00312
00313 for(TypeWithDict const& baseType : baseTypes) {
00314 fillLookup(baseType, index, pBD, tempElementLookupMap);
00315 }
00316 }
00317 }
00318 }
00319 }
00320 ++index;
00321 }
00322 missingDictionaries().reserve(missingDicts.size());
00323 copy_all(missingDicts, std::back_inserter(missingDictionaries()));
00324 productLookup().fillFrom(tempProductLookupMap);
00325 elementLookup().fillFrom(tempElementLookupMap);
00326 savedMissingTypes.swap(missingTypes());
00327 savedFoundTypes.swap(foundTypes());
00328 }
00329
00330 ProductTransientIndex ProductRegistry::indexFrom(BranchID const& iID) const {
00331 std::map<BranchID, ProductTransientIndex>::iterator itFind = transient_.branchIDToIndex_.find(iID);
00332 if(itFind == transient_.branchIDToIndex_.end()) {
00333 return kInvalidIndex;
00334 }
00335 return itFind->second;
00336 }
00337
00338 void ProductRegistry::print(std::ostream& os) const {
00339 for(auto const& product: productList_) {
00340 os << product.second << "\n-----\n";
00341 }
00342 }
00343 }