CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/DataFormats/Provenance/src/ProductRegistry.cc

Go to the documentation of this file.
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     // Loop over entries in the main product registry.
00227     while(j != s || i != e) {
00228       if(j != s && j->second.produced()) {
00229         // Ignore branches just produced (i.e. not in input file).
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       //only do the following if the data is supposed to be available in the event
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 }