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