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
00182 while(j != s || i != e) {
00183 if(j != s && j->second.produced()) {
00184
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
00231
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
00244
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
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
00268
00269
00270
00271
00272
00273
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
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 }