00001
00004 #include <algorithm>
00005 #include <sstream>
00006 #include <stdexcept>
00007
00008 #include "FWCore/Framework/interface/Principal.h"
00009 #include "DataFormats/Provenance/interface/BranchMapper.h"
00010 #include "DataFormats/Provenance/interface/ProcessHistory.h"
00011 #include "DataFormats/Provenance/interface/ProcessHistoryRegistry.h"
00012 #include "DataFormats/Provenance/interface/ProductRegistry.h"
00013 #include "DataFormats/Provenance/interface/ProductStatus.h"
00014 #include "DataFormats/Common/interface/BasicHandle.h"
00015 #include "FWCore/Utilities/interface/TypeID.h"
00016 #include "FWCore/Utilities/interface/EDMException.h"
00017 #include "FWCore/Utilities/interface/Algorithms.h"
00018 #include "FWCore/Framework/interface/Selector.h"
00019
00020
00021 namespace edm {
00022
00023 Principal::Principal(boost::shared_ptr<ProductRegistry const> reg,
00024 ProcessConfiguration const& pc,
00025 ProcessHistoryID const& hist,
00026 boost::shared_ptr<BranchMapper> mapper,
00027 boost::shared_ptr<DelayedReader> rtrv) :
00028 EDProductGetter(),
00029 processHistoryID_(hist),
00030 processHistoryPtr_(boost::shared_ptr<ProcessHistory>(new ProcessHistory)),
00031 processConfiguration_(pc),
00032 processHistoryModified_(false),
00033 groups_(),
00034 preg_(reg),
00035 branchMapperPtr_(mapper),
00036 store_(rtrv)
00037 {
00038 if (processHistoryID_.isValid()) {
00039 ProcessHistoryRegistry& history(*ProcessHistoryRegistry::instance());
00040 assert(history.notEmpty());
00041 bool found = history.getMapped(processHistoryID_, *processHistoryPtr_);
00042 assert(found);
00043 }
00044 }
00045
00046 Principal::~Principal() {
00047 }
00048
00049 Group*
00050 Principal::getExistingGroup(Group const& group) {
00051 GroupCollection::const_iterator it = groups_.find(group.productDescription().branchID());
00052 if (it == groups_.end()) return 0;
00053 return it->second.get();
00054 }
00055
00056 void
00057 Principal::addGroup_(std::auto_ptr<Group> group) {
00058 ConstBranchDescription const& bd = group->productDescription();
00059 assert (!bd.className().empty());
00060 assert (!bd.friendlyClassName().empty());
00061 assert (!bd.moduleLabel().empty());
00062 assert (!bd.processName().empty());
00063 SharedGroupPtr g(group);
00064 groups_.insert(std::make_pair(bd.branchID(), g));
00065 }
00066
00067 void
00068 Principal::replaceGroup(std::auto_ptr<Group> group) {
00069 ConstBranchDescription const& bd = group->productDescription();
00070 assert (!bd.className().empty());
00071 assert (!bd.friendlyClassName().empty());
00072 assert (!bd.moduleLabel().empty());
00073 assert (!bd.processName().empty());
00074 SharedGroupPtr g(group);
00075 groups_[bd.branchID()]->replace(*g);
00076 }
00077
00078 void
00079 Principal::addToProcessHistory() const {
00080 if (processHistoryModified_) return;
00081 ProcessHistory& ph = *processHistoryPtr_;
00082 std::string const& processName = processConfiguration_.processName();
00083 for (ProcessHistory::const_iterator it = ph.begin(), itEnd = ph.end(); it != itEnd; ++it) {
00084 if (processName == it->processName()) {
00085 throw edm::Exception(errors::Configuration, "Duplicate Process")
00086 << "The process name " << processName << " was previously used on these products.\n"
00087 << "Please modify the configuration file to use a distinct process name.\n";
00088 }
00089 }
00090 ph.push_back(processConfiguration_);
00091
00092
00093
00094
00095
00096
00097
00098 ProcessHistoryRegistry::instance()->insertMapped(ph);
00099 processHistoryID_ = ph.id();
00100 processHistoryModified_ = true;
00101 }
00102
00103 ProcessHistory const&
00104 Principal::processHistory() const {
00105 return *processHistoryPtr_;
00106 }
00107
00108 Principal::SharedConstGroupPtr const
00109 Principal::getGroup(BranchID const& bid, bool resolveProd, bool resolveProv, bool fillOnDemand) const {
00110 GroupCollection::const_iterator it = groups_.find(bid);
00111 if (it == groups_.end()) {
00112 return SharedConstGroupPtr();
00113 }
00114 SharedConstGroupPtr const& g = it->second;
00115 if (resolveProv && (g->provenanceAvailable() || g->onDemand())) {
00116 if(g->onDemand()) {
00117
00118 this->resolveProduct(*g, true);
00119
00120 if( 0 == g->product()) {
00121
00122 return SharedConstGroupPtr();
00123 }
00124 }
00125 this->resolveProvenance(*g);
00126 }
00127 if (resolveProd && !g->productUnavailable()) {
00128 this->resolveProduct(*g, fillOnDemand);
00129 if(g->onDemand() && 0 == g->product()) {
00130
00131 return SharedConstGroupPtr();
00132 }
00133 }
00134 return g;
00135 }
00136
00137 BasicHandle
00138 Principal::getBySelector(TypeID const& productType,
00139 SelectorBase const& sel) const {
00140
00141 BasicHandleVec results;
00142
00143 int nFound = findGroups(productType,
00144 preg_->productLookup(),
00145 sel,
00146 results,
00147 true);
00148
00149 if (nFound == 0) {
00150 boost::shared_ptr<cms::Exception> whyFailed( new edm::Exception(edm::errors::ProductNotFound) );
00151 *whyFailed
00152 << "getBySelector: Found zero products matching all criteria\n"
00153 << "Looking for type: " << productType << "\n";
00154 return BasicHandle(whyFailed);
00155 }
00156 if (nFound > 1) {
00157 throw edm::Exception(edm::errors::ProductNotFound)
00158 << "getBySelector: Found "<<nFound<<" products rather than one which match all criteria\n"
00159 << "Looking for type: " << productType << "\n";
00160 }
00161 return results[0];
00162 }
00163
00164 BasicHandle
00165 Principal::getByLabel(TypeID const& productType,
00166 std::string const& label,
00167 std::string const& productInstanceName) const {
00168 BasicHandleVec results;
00169
00170 edm::Selector sel(edm::ModuleLabelSelector(label) &&
00171 edm::ProductInstanceNameSelector(productInstanceName));
00172
00173 int nFound = findGroups(productType,
00174 preg_->productLookup(),
00175 sel,
00176 results,
00177 true);
00178
00179 if (nFound == 0) {
00180 boost::shared_ptr<cms::Exception> whyFailed( new edm::Exception(edm::errors::ProductNotFound) );
00181 *whyFailed
00182 << "getByLabel: Found zero products matching all criteria\n"
00183 << "Looking for type: " << productType << "\n"
00184 << "Looking for module label: " << label << "\n"
00185 << "Looking for productInstanceName: " << productInstanceName << "\n";
00186 return BasicHandle(whyFailed);
00187 }
00188 if (nFound > 1) {
00189 throw edm::Exception(edm::errors::ProductNotFound)
00190 << "getByLabel: Found "<<nFound<<" products rather than one which match all criteria\n"
00191 << "Looking for type: " << productType << "\n"
00192 << "Looking for module label: " << label << "\n"
00193 << "Looking for productInstanceName: " << productInstanceName << "\n";
00194 }
00195 return results[0];
00196 }
00197
00198 BasicHandle
00199 Principal::getByLabel(TypeID const& productType,
00200 std::string const& label,
00201 std::string const& productInstanceName,
00202 std::string const& processName) const
00203 {
00204
00205 BasicHandleVec results;
00206
00207 edm::Selector sel(edm::ModuleLabelSelector(label) &&
00208 edm::ProductInstanceNameSelector(productInstanceName) &&
00209 edm::ProcessNameSelector(processName));
00210
00211 int nFound = findGroups(productType,
00212 preg_->productLookup(),
00213 sel,
00214 results,
00215 true);
00216
00217 if (nFound == 0) {
00218 boost::shared_ptr<cms::Exception> whyFailed( new edm::Exception(edm::errors::ProductNotFound) );
00219 *whyFailed
00220 << "getByLabel: Found zero products matching all criteria\n"
00221 << "Looking for type: " << productType << "\n"
00222 << "Looking for module label: " << label << "\n"
00223 << "Looking for productInstanceName: " << productInstanceName << "\n"
00224 << "Looking for process: " << processName << "\n";
00225 return BasicHandle(whyFailed);
00226 }
00227 if (nFound > 1) {
00228 throw edm::Exception(edm::errors::ProductNotFound)
00229 << "getByLabel: Found "<<nFound<<" products rather than one which match all criteria\n"
00230 << "Looking for type: " << productType << "\n"
00231 << "Looking for module label: " << label << "\n"
00232 << "Looking for productInstanceName: " << productInstanceName << "\n"
00233 << "Looking for process: " << processName << "\n";
00234 }
00235 return results[0];
00236 }
00237
00238
00239 void
00240 Principal::getMany(TypeID const& productType,
00241 SelectorBase const& sel,
00242 BasicHandleVec& results) const {
00243
00244 findGroups(productType,
00245 preg_->productLookup(),
00246 sel,
00247 results,
00248 false);
00249
00250 return;
00251 }
00252
00253 BasicHandle
00254 Principal::getByType(TypeID const& productType) const {
00255
00256 BasicHandleVec results;
00257
00258 edm::MatchAllSelector sel;
00259
00260 int nFound = findGroups(productType,
00261 preg_->productLookup(),
00262 sel,
00263 results,
00264 true);
00265
00266 if (nFound == 0) {
00267 boost::shared_ptr<cms::Exception> whyFailed( new edm::Exception(edm::errors::ProductNotFound) );
00268 *whyFailed
00269 << "getByType: Found zero products matching all criteria\n"
00270 << "Looking for type: " << productType << "\n";
00271 return BasicHandle(whyFailed);
00272 }
00273 if (nFound > 1) {
00274 throw edm::Exception(edm::errors::ProductNotFound)
00275 << "getByType: Found "<<nFound <<" products rather than one which match all criteria\n"
00276 << "Looking for type: " << productType << "\n";
00277 }
00278 return results[0];
00279 }
00280
00281 void
00282 Principal::getManyByType(TypeID const& productType,
00283 BasicHandleVec& results) const {
00284
00285 edm::MatchAllSelector sel;
00286
00287 findGroups(productType,
00288 preg_->productLookup(),
00289 sel,
00290 results,
00291 false);
00292 return;
00293 }
00294
00295 size_t
00296 Principal::getMatchingSequence(TypeID const& typeID,
00297 SelectorBase const& selector,
00298 BasicHandleVec& results,
00299 bool stopIfProcessHasMatch) const {
00300
00301
00302
00303 return findGroups(typeID,
00304 preg_->elementLookup(),
00305 selector,
00306 results,
00307 stopIfProcessHasMatch);
00308 }
00309
00310 void
00311 Principal::readImmediate() const {
00312 for (Principal::const_iterator i = begin(), iEnd = end(); i != iEnd; ++i) {
00313 if (i->second->provenanceAvailable()) {
00314 resolveProvenance(*i->second);
00315 }
00316 if (!i->second->productUnavailable()) {
00317 resolveProduct(*i->second, false);
00318 }
00319 }
00320 branchMapperPtr_->setDelayedRead(false);
00321 }
00322
00323 size_t
00324 Principal::findGroups(TypeID const& typeID,
00325 TypeLookup const& typeLookup,
00326 SelectorBase const& selector,
00327 BasicHandleVec& results,
00328 bool stopIfProcessHasMatch) const {
00329 assert(results.empty());
00330
00331
00332
00333
00334
00335 if (!typeID.hasDictionary()) {
00336 return 0;
00337 }
00338
00339 TypeLookup::const_iterator i = typeLookup.find(typeID.friendlyClassName());
00340
00341 if (i == typeLookup.end()) {
00342 return 0;
00343 }
00344
00345 const ProcessLookup& processLookup = i->second;
00346
00347
00348
00349
00350 findGroupsForProcess(processConfiguration_.processName(),
00351 processLookup,
00352 selector,
00353 results);
00354
00355
00356
00357 for (ProcessHistory::const_reverse_iterator iproc = processHistory().rbegin(),
00358 eproc = processHistory().rend();
00359 iproc != eproc && (results.empty() || !stopIfProcessHasMatch);
00360 ++iproc) {
00361
00362
00363 if (iproc->processName() == processConfiguration_.processName()) continue;
00364
00365 findGroupsForProcess(iproc->processName(),
00366 processLookup,
00367 selector,
00368 results);
00369 }
00370 return results.size();
00371 }
00372
00373 void
00374 Principal::findGroupsForProcess(std::string const& processName,
00375 ProcessLookup const& processLookup,
00376 SelectorBase const& selector,
00377 BasicHandleVec& results) const {
00378
00379 ProcessLookup::const_iterator j = processLookup.find(processName);
00380
00381 if (j == processLookup.end()) return;
00382
00383
00384
00385
00386 std::vector<BranchID> const& vindex = j->second;
00387
00388 for (std::vector<BranchID>::const_iterator ib(vindex.begin()), ie(vindex.end());
00389 ib != ie;
00390 ++ib) {
00391 SharedConstGroupPtr const& group = getGroup(*ib, false, false, false);
00392 if(group.get() == 0) {
00393 continue;
00394 }
00395
00396 if (selector.match(group->productDescription())) {
00397
00398
00399 if (!group->productUnavailable()) {
00400 this->resolveProduct(*group, true);
00401
00402
00403 if (!group->productUnavailable() && !group->onDemand()) {
00404
00405 BasicHandle bh(group->product(), group->provenance());
00406 bh.provenance()->setStore(branchMapperPtr_);
00407 results.push_back(bh);
00408 }
00409 }
00410 }
00411 }
00412 return;
00413 }
00414
00415 void
00416 Principal::resolveProduct(Group const& g, bool fillOnDemand) const {
00417 if (g.productUnavailable()) {
00418 throw edm::Exception(errors::ProductNotFound,"InaccessibleProduct")
00419 << "resolve_: product is not accessible\n"
00420 << g.provenance() << '\n';
00421 }
00422
00423 if (g.product()) return;
00424
00425
00426 if (g.onDemand()) {
00427 if (fillOnDemand) unscheduledFill(g.productDescription().moduleLabel());
00428 return;
00429 }
00430
00431
00432 BranchKey const bk = BranchKey(g.productDescription());
00433 std::auto_ptr<EDProduct> edp(store_->getProduct(bk, this));
00434
00435
00436 g.setProduct(edp);
00437 }
00438
00439 void
00440 Principal::recombine(Principal & other, std::vector<BranchID> const& bids) {
00441 for (std::vector<BranchID>::const_iterator it = bids.begin(), itEnd = bids.end(); it != itEnd; ++it) {
00442 groups_[*it].swap(other.groups_[*it]);
00443 }
00444 store_->mergeReaders(other.store());
00445 branchMapperPtr_->mergeMappers(other.branchMapperPtr());
00446 }
00447
00448 EDProduct const*
00449 Principal::getIt(ProductID const& pid) const {
00450 assert(0);
00451 return 0;
00452 }
00453 }