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
00197 while(j != s || i != e) {
00198 if(j != s && j->second.produced()) {
00199
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
00250
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
00263
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
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
00282
00283
00284
00285
00286
00287
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
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 }