CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_1/src/DataFormats/Provenance/src/ProductRegistry.cc

Go to the documentation of this file.
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     // Loop over entries in the main product registry.
00208     while(j != s || i != e) {
00209       if(j != s && j->second.produced()) {
00210         // Ignore branches just produced (i.e. not in input file).
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     //NOTE it might be possible to remove the need for this temporary map because the productList is ordered by the
00261     // BranchKey and for the same C++ class type the BranchKey will sort just like CompareTypeInBranchTypeConstBranchDescription
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       //insert returns a pair<iterator, bool> and we want the address of the ConstBranchDescription that was created in the map
00276       // this is safe since items in a map always retain their memory address
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       //only do the following if the data is supposed to be available in the event
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             // Here we look in the object named "type" for a typedef
00294             // named "value_type" and get the type for it.
00295             // Then check to ensure the dictionary is defined
00296             // for this value_type.
00297             // I do not throw an exception here if the check fails
00298             // because there are known cases where the dictionary does
00299             // not exist and we do not need to support those cases.
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               // Repeat this for all public base classes of the value_type
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 }