CMS 3D CMS Logo

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