CMS 3D CMS Logo

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