CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/FWCore/Framework/src/Principal.cc

Go to the documentation of this file.
00001 
00004 #include <algorithm>
00005 #include <sstream>
00006 #include <stdexcept>
00007 #include <limits>
00008 #include <cstring>
00009 
00010 #include "FWCore/Framework/interface/Principal.h"
00011 #include "DataFormats/Provenance/interface/ProcessHistoryRegistry.h"
00012 #include "DataFormats/Provenance/interface/ProductRegistry.h"
00013 #include "FWCore/Utilities/interface/EDMException.h"
00014 #include "FWCore/Framework/interface/DelayedReader.h"
00015 #include "FWCore/Framework/interface/Selector.h"
00016 //using boost::lambda::_1;
00017 
00018 namespace edm {
00019 
00020   Principal::Principal(boost::shared_ptr<ProductRegistry const> reg,
00021                        ProcessConfiguration const& pc,
00022                        BranchType bt) :
00023     EDProductGetter(),
00024     processHistoryPtr_(boost::shared_ptr<ProcessHistory>(new ProcessHistory)),
00025     processHistoryID_(processHistoryPtr_->id()),
00026     processConfiguration_(&pc),
00027     groups_(reg->constProductList().size(), SharedGroupPtr()),
00028     preg_(reg),
00029     branchMapperPtr_(),
00030     store_(),
00031     productPtrs_(),
00032     branchType_(bt) {
00033     //Now that these have been set, we can create the list of Branches we need.
00034     std::string const source("source");
00035     ProductRegistry::ProductList const& prodsList = reg->productList();
00036     for(ProductRegistry::ProductList::const_iterator itProdInfo = prodsList.begin(),
00037           itProdInfoEnd = prodsList.end();
00038         itProdInfo != itProdInfoEnd;
00039         ++itProdInfo) {
00040       if (itProdInfo->second.branchType() == branchType_) {
00041         boost::shared_ptr<ConstBranchDescription> bd(new ConstBranchDescription(itProdInfo->second));
00042         if (bd->produced()) {
00043           if (bd->moduleLabel() == source) {
00044             addGroupSource(bd);
00045           } else if(bd->onDemand()) {
00046             assert(bt == InEvent);
00047             addOnDemandGroup(bd);
00048           } else {
00049             addGroupScheduled(bd);
00050           }
00051         } else {
00052           addGroupInput(bd);
00053         }
00054       }
00055     }
00056   }
00057 
00058   Principal::~Principal() {
00059   }
00060 
00061   // Number of products in the Principal.
00062   // For products in an input file and not yet read in due to delayed read,
00063   // this routine assumes a real product is there.
00064   size_t
00065   Principal::size() const {
00066     size_t size = 0U;
00067     for(const_iterator it = this->begin(), itEnd = this->end(); it != itEnd; ++it) {
00068       Group const& g = **it;
00069       if (!g.productUnavailable() && !g.onDemand() && !g.branchDescription().dropped()) {
00070         ++size;
00071       }
00072     }
00073     return size;
00074   }
00075 
00076   //adjust provenance for input groups after new input file has been merged
00077   bool
00078   Principal::adjustToNewProductRegistry(ProductRegistry const& reg) {
00079     if(reg.constProductList().size() > groups_.size()) {
00080       return false;
00081     }
00082     ProductRegistry::ProductList const& prodsList = reg.productList();
00083     for(ProductRegistry::ProductList::const_iterator itProdInfo = prodsList.begin(),
00084           itProdInfoEnd = prodsList.end();
00085         itProdInfo != itProdInfoEnd;
00086         ++itProdInfo) {
00087     if (!itProdInfo->second.produced() && (itProdInfo->second.branchType() == branchType_)) {
00088         boost::shared_ptr<ConstBranchDescription> bd(new ConstBranchDescription(itProdInfo->second));
00089         Group *g = getExistingGroup(itProdInfo->second.branchID());
00090         if (g == 0 || g->branchDescription().branchName() != bd->branchName()) {
00091             return false;
00092         }
00093         g->resetBranchDescription(bd);
00094       }
00095     }
00096     return true;
00097   }
00098 
00099   void
00100   Principal::addGroupScheduled(boost::shared_ptr<ConstBranchDescription> bd) {
00101     std::auto_ptr<Group> g(new ScheduledGroup(bd));
00102     addGroupOrThrow(g);
00103   }
00104 
00105   void
00106   Principal::addGroupSource(boost::shared_ptr<ConstBranchDescription> bd) {
00107     std::auto_ptr<Group> g(new SourceGroup(bd));
00108     addGroupOrThrow(g);
00109   }
00110 
00111   void
00112   Principal::addGroupInput(boost::shared_ptr<ConstBranchDescription> bd) {
00113     std::auto_ptr<Group> g(new InputGroup(bd));
00114     addGroupOrThrow(g);
00115   }
00116 
00117   void
00118   Principal::addOnDemandGroup(boost::shared_ptr<ConstBranchDescription> bd) {
00119     std::auto_ptr<Group> g(new UnscheduledGroup(bd));
00120     addGroupOrThrow(g);
00121   }
00122 
00123   // "Zero" the principal so it can be reused for another Event.
00124   void
00125   Principal::clearPrincipal() {
00126     processHistoryPtr_.reset(new ProcessHistory);
00127     processHistoryID_ = processHistoryPtr_->id();
00128     branchMapperPtr_.reset();
00129     store_.reset();
00130     for (Principal::const_iterator i = begin(), iEnd = end(); i != iEnd; ++i) {
00131       (*i)->resetGroupData();
00132     }
00133     productPtrs_.clear();
00134   }
00135 
00136   // Set the principal for the Event, Lumi, or Run.
00137   void
00138   Principal::fillPrincipal(ProcessHistoryID const& hist, boost::shared_ptr<BranchMapper> mapper, boost::shared_ptr<DelayedReader> rtrv) {
00139     branchMapperPtr_ = mapper;
00140     store_ = rtrv;
00141     if (hist.isValid()) {
00142       ProcessHistoryRegistry& history(*ProcessHistoryRegistry::instance());
00143       assert(history.notEmpty());
00144       bool found = history.getMapped(hist, *processHistoryPtr_);
00145       assert(found);
00146       processHistoryID_ = processHistoryPtr_->id();
00147     }
00148     preg_->productLookup().reorderIfNecessary(branchType_, *processHistoryPtr_,
00149                                          processConfiguration_->processName());
00150     preg_->elementLookup().reorderIfNecessary(branchType_, *processHistoryPtr_,
00151                                          processConfiguration_->processName());
00152   }
00153 
00154   Group*
00155   Principal::getExistingGroup(BranchID const& branchID) {
00156     ProductTransientIndex index = preg_->indexFrom(branchID);
00157     assert(index != ProductRegistry::kInvalidIndex);
00158     SharedGroupPtr ptr = groups_.at(index);
00159     return ptr.get();
00160   }
00161 
00162   Group*
00163   Principal::getExistingGroup(Group const& group) {
00164     Group* g = getExistingGroup(group.branchDescription().branchID());
00165     assert(0 == g || BranchKey(group.branchDescription()) == BranchKey(g->branchDescription()));
00166     return g;
00167   }
00168 
00169   void
00170   Principal::addGroup_(std::auto_ptr<Group> group) {
00171     ConstBranchDescription const& bd = group->branchDescription();
00172     assert (!bd.className().empty());
00173     assert (!bd.friendlyClassName().empty());
00174     assert (!bd.moduleLabel().empty());
00175     assert (!bd.processName().empty());
00176     SharedGroupPtr g(group);
00177 
00178     ProductTransientIndex index = preg_->indexFrom(bd.branchID());
00179     assert(index != ProductRegistry::kInvalidIndex);
00180     groups_[index] = g;
00181   }
00182 
00183   void
00184   Principal::addGroupOrThrow(std::auto_ptr<Group> group) {
00185     Group const* g = getExistingGroup(*group);
00186     if (g != 0) {
00187       ConstBranchDescription const& bd = group->branchDescription();
00188       throw edm::Exception(edm::errors::InsertFailure,"AlreadyPresent")
00189           << "addGroupOrThrow: Problem found while adding product, "
00190           << "product already exists for ("
00191           << bd.friendlyClassName() << ","
00192           << bd.moduleLabel() << ","
00193           << bd.productInstanceName() << ","
00194           << bd.processName()
00195           << ")\n";
00196     }
00197     addGroup_(group);
00198   }
00199 
00200   void
00201   Principal::setProcessHistory(Principal const& principal) {
00202     *processHistoryPtr_ = *principal.processHistoryPtr_;
00203     processHistoryID_ = processHistoryPtr_->id();
00204   }
00205 
00206   Principal::SharedConstGroupPtr const
00207   Principal::getGroup(BranchID const& bid, bool resolveProd, bool fillOnDemand) const {
00208     ProductTransientIndex index = preg_->indexFrom(bid);
00209     if(index == ProductRegistry::kInvalidIndex){
00210        return SharedConstGroupPtr();
00211     }
00212     return getGroupByIndex(index, resolveProd, fillOnDemand);
00213   }
00214 
00215   Principal::SharedConstGroupPtr const
00216   Principal::getGroupByIndex(ProductTransientIndex const& index, bool resolveProd, bool fillOnDemand) const {
00217 
00218     SharedConstGroupPtr const& g = groups_[index];
00219     if (0 == g.get()) {
00220       return g;
00221     }
00222     if (resolveProd && !g->productUnavailable()) {
00223       this->resolveProduct(*g, fillOnDemand);
00224     }
00225     return g;
00226   }
00227 
00228   BasicHandle
00229   Principal::getBySelector(TypeID const& productType,
00230                            SelectorBase const& sel) const {
00231     BasicHandle result;
00232 
00233     int nFound = findGroup(productType,
00234                            preg_->productLookup(),
00235                            sel,
00236                            result);
00237 
00238     if (nFound == 0) {
00239       boost::shared_ptr<cms::Exception> whyFailed(new edm::Exception(edm::errors::ProductNotFound));
00240       *whyFailed
00241         << "getBySelector: Found zero products matching all criteria\n"
00242         << "Looking for type: " << productType << "\n";
00243       return BasicHandle(whyFailed);
00244     }
00245     if (nFound > 1) {
00246       throw edm::Exception(edm::errors::ProductNotFound)
00247         << "getBySelector: Found " << nFound << " products rather than one which match all criteria\n"
00248         << "Looking for type: " << productType << "\n";
00249     }
00250     return result;
00251   }
00252 
00253   BasicHandle
00254   Principal::getByLabel(TypeID const& productType,
00255                         std::string const& label,
00256                         std::string const& productInstanceName,
00257                         std::string const& processName,
00258                         size_t& cachedOffset,
00259                         int& fillCount) const {
00260 
00261     BasicHandle result;
00262 
00263     bool found = findGroupByLabel(productType,
00264                                   preg_->productLookup(),
00265                                   label,
00266                                   productInstanceName,
00267                                   processName,
00268                                   cachedOffset,
00269                                   fillCount,
00270                                   result);
00271 
00272     if (!found) {
00273       boost::shared_ptr<cms::Exception> whyFailed(new edm::Exception(edm::errors::ProductNotFound));
00274       *whyFailed
00275         << "getByLabel: Found zero products matching all criteria\n"
00276         << "Looking for type: " << productType << "\n"
00277         << "Looking for module label: " << label << "\n"
00278         << "Looking for productInstanceName: " << productInstanceName << "\n"
00279         << (processName.empty() ? "" : "Looking for process: ") << processName << "\n";
00280       return BasicHandle(whyFailed);
00281     }
00282     return result;
00283   }
00284 
00285 
00286   void
00287   Principal::getMany(TypeID const& productType,
00288                      SelectorBase const& sel,
00289                      BasicHandleVec& results) const {
00290 
00291     findGroups(productType,
00292                preg_->productLookup(),
00293                sel,
00294                results);
00295 
00296     return;
00297   }
00298 
00299   BasicHandle
00300   Principal::getByType(TypeID const& productType) const {
00301 
00302     BasicHandle result;
00303     MatchAllSelector sel;
00304 
00305     int nFound = findGroup(productType,
00306                            preg_->productLookup(),
00307                            sel,
00308                            result);
00309 
00310     if (nFound == 0) {
00311       boost::shared_ptr<cms::Exception> whyFailed(new edm::Exception(edm::errors::ProductNotFound));
00312       *whyFailed
00313         << "getByType: Found zero products matching all criteria\n"
00314         << "Looking for type: " << productType << "\n";
00315       return BasicHandle(whyFailed);
00316     }
00317     if (nFound > 1) {
00318       throw edm::Exception(edm::errors::ProductNotFound)
00319         << "getByType: Found " << nFound << " products rather than one which match all criteria\n"
00320         << "Looking for type: " << productType << "\n";
00321     }
00322     return result;
00323   }
00324 
00325   void
00326   Principal::getManyByType(TypeID const& productType,
00327                            BasicHandleVec& results) const {
00328 
00329     MatchAllSelector sel;
00330 
00331     findGroups(productType,
00332                preg_->productLookup(),
00333                sel,
00334                results);
00335     return;
00336   }
00337 
00338   size_t
00339   Principal::getMatchingSequence(TypeID const& typeID,
00340                                  SelectorBase const& selector,
00341                                  BasicHandle& result) const {
00342 
00343     // One new argument is the element lookup container
00344     // Otherwise this just passes through the arguments to findGroup
00345     return findGroup(typeID,
00346                      preg_->elementLookup(),
00347                      selector,
00348                      result);
00349   }
00350 
00351   size_t
00352   Principal::findGroups(TypeID const& typeID,
00353                         TransientProductLookupMap const& typeLookup,
00354                         SelectorBase const& selector,
00355                         BasicHandleVec& results) const {
00356     assert(results.empty());
00357 
00358     typedef TransientProductLookupMap TypeLookup;
00359     // A class without a dictionary cannot be in an Event/Lumi/Run.
00360     // First, we check if the class has a dictionary.  If it does not,
00361     // we return immediately.
00362     std::pair<TypeLookup::const_iterator, TypeLookup::const_iterator> const range = typeLookup.equal_range(TypeInBranchType(typeID,branchType_));
00363     if(range.first == range.second) {
00364       return 0;
00365     }
00366 
00367     results.reserve(range.second - range.first);
00368 
00369     for(TypeLookup::const_iterator it = range.first; it != range.second; ++it) {
00370 
00371       if(selector.match(*(it->branchDescription()))) {
00372 
00373         //now see if the data is actually available
00374         SharedConstGroupPtr const& group = getGroupByIndex(it->index(), false, false);
00375         // Skip product if not available.
00376         if (group && !group->productUnavailable()) {
00377           this->resolveProduct(*group, true);
00378           // If the product is a dummy filler, group will now be marked unavailable.
00379           // Unscheduled execution can fail to produce the EDProduct so check
00380           if (!group->productUnavailable() && !group->onDemand()) {
00381             // Found a good match, save it
00382             BasicHandle bh(group->product(), group->provenance());
00383             results.push_back(bh);
00384           }
00385         }
00386       }
00387     }
00388     return results.size();
00389   }
00390 
00391   size_t
00392   Principal::findGroup(TypeID const& typeID,
00393                        TransientProductLookupMap const& typeLookup,
00394                        SelectorBase const& selector,
00395                        BasicHandle& result) const {
00396     assert(!result.isValid());
00397 
00398     size_t count = 0U;
00399 
00400     typedef TransientProductLookupMap TypeLookup;
00401     // A class without a dictionary cannot be in an Event/Lumi/Run.
00402     // First, we check if the class has a dictionary.  If it does not,
00403     // we return immediately.
00404     std::pair<TypeLookup::const_iterator, TypeLookup::const_iterator> const range = typeLookup.equal_range(TypeInBranchType(typeID,branchType_));
00405     if(range.first == range.second) {
00406       return 0;
00407     }
00408 
00409     unsigned int processLevelFound = std::numeric_limits<unsigned int>::max();
00410     for(TypeLookup::const_iterator it = range.first; it != range.second; ++it) {
00411       if(it->processIndex() > processLevelFound) {
00412         //this is for a less recent process and we've already found a match for a more recent process
00413         continue;
00414       }
00415 
00416       if(selector.match(*(it->branchDescription()))) {
00417 
00418         //now see if the data is actually available
00419         SharedConstGroupPtr const& group = getGroupByIndex(it->index(), false, false);
00420         // Skip product if not available.
00421         if (group && !group->productUnavailable()) {
00422           this->resolveProduct(*group, true);
00423           // If the product is a dummy filler, group will now be marked unavailable.
00424           // Unscheduled execution can fail to produce the EDProduct so check
00425           if (!group->productUnavailable() && !group->onDemand()) {
00426             if(it->processIndex() < processLevelFound) {
00427               processLevelFound = it->processIndex();
00428               count = 0U;
00429             }
00430             if (count == 0U) {
00431               // Found a unique (so far) match, save it
00432               result = BasicHandle(group->product(), group->provenance());
00433             }
00434             ++count;
00435           }
00436         }
00437       }
00438     }
00439     if (count != 1) result = BasicHandle();
00440     return count;
00441   }
00442 
00443   bool
00444   Principal::findGroupByLabel(TypeID const& typeID,
00445                               TransientProductLookupMap const& typeLookup,
00446                               std::string const& moduleLabel,
00447                               std::string const& productInstanceName,
00448                               std::string const& processName,
00449                               size_t& cachedOffset,
00450                               int& fillCount,
00451                               BasicHandle& result) const {
00452     assert(!result.isValid());
00453 
00454     typedef TransientProductLookupMap TypeLookup;
00455     bool isCached = (fillCount > 0 && fillCount == typeLookup.fillCount());
00456     bool toBeCached = (fillCount >= 0 && !isCached);
00457 
00458     std::pair<TypeLookup::const_iterator, TypeLookup::const_iterator> range =
00459         (isCached ? std::make_pair(typeLookup.begin() + cachedOffset, typeLookup.end()) : typeLookup.equal_range(TypeInBranchType(typeID,branchType_), moduleLabel, productInstanceName));
00460 
00461     if (toBeCached) {
00462       cachedOffset = range.first - typeLookup.begin();
00463       fillCount = typeLookup.fillCount();
00464     }
00465 
00466     if(range.first == range.second) {
00467       if (toBeCached) {
00468         cachedOffset = typeLookup.end() - typeLookup.begin();
00469       }
00470       return false;
00471     }
00472 
00473     if (!processName.empty()) {
00474       if (isCached) {
00475         assert(processName == range.first->branchDescription()->processName());
00476         range.second = range.first + 1;
00477       } else if (toBeCached) {
00478         bool processFound = false;
00479         for(TypeLookup::const_iterator it = range.first; it != range.second; ++it) {
00480           if (it->isFirst() && it != range.first) {
00481             break;
00482           }
00483           if (processName == it->branchDescription()->processName()) {
00484             processFound = true;
00485             range.first = it;
00486             cachedOffset = range.first - typeLookup.begin();
00487             range.second = range.first + 1;
00488             break;
00489           }
00490         }
00491         if (!processFound) {
00492           cachedOffset = typeLookup.end() - typeLookup.begin();
00493           return false;
00494         }
00495       } // end if(toBeCached)
00496     }
00497 
00498     for(TypeLookup::const_iterator it = range.first; it != range.second; ++it) {
00499       if (it->isFirst() && it != range.first) {
00500         return false;
00501       }
00502       if (!processName.empty() && processName != it->branchDescription()->processName()) {
00503         continue;
00504       }
00505       //now see if the data is actually available
00506       SharedConstGroupPtr const& group = getGroupByIndex(it->index(), false, false);
00507       // Skip product if not available.
00508       if (group && !group->productUnavailable()) {
00509         this->resolveProduct(*group, true);
00510         // If the product is a dummy filler, group will now be marked unavailable.
00511         // Unscheduled execution can fail to produce the EDProduct so check
00512         if (!group->productUnavailable() && !group->onDemand()) {
00513           // Found the match
00514           result = BasicHandle(group->product(), group->provenance());
00515           return true;
00516         }
00517       }
00518     }
00519     return false;
00520   }
00521 
00522   OutputHandle
00523   Principal::getForOutput(BranchID const& bid, bool getProd) const {
00524     SharedConstGroupPtr const& g = getGroup(bid, getProd, false);
00525     if (g.get() == 0) {
00526         throw edm::Exception(edm::errors::LogicError, "Principal::getForOutput\n")
00527          << "No entry is present for this branch.\n"
00528          << "The branch id is " << bid << "\n"
00529          << "Contact a framework developer.\n";
00530     }
00531     if (!g->provenance() || (!g->product() && !g->productProvenancePtr())) {
00532       return OutputHandle();
00533     }
00534     return OutputHandle(g->product().get(), &g->branchDescription(), g->productProvenancePtr());
00535   }
00536 
00537   Provenance
00538   Principal::getProvenance(BranchID const& bid) const {
00539     SharedConstGroupPtr const& g = getGroup(bid, false, true);
00540     if (g.get() == 0) {
00541       throw edm::Exception(edm::errors::ProductNotFound,"InvalidID")
00542         << "getProvenance: no product with given branch id: "<< bid << "\n";
00543     }
00544 
00545     if (g->onDemand()) {
00546       unscheduledFill(g->branchDescription().moduleLabel());
00547     }
00548     // We already tried to produce the unscheduled products above
00549     // If they still are not there, then throw
00550     if (g->onDemand()) {
00551       throw edm::Exception(edm::errors::ProductNotFound)
00552         << "getProvenance: no product with given BranchID: "<< bid <<"\n";
00553     }
00554 
00555     return *g->provenance();
00556   }
00557 
00558   // This one is mostly for test printout purposes
00559   // No attempt to trigger on demand execution
00560   // Skips provenance when the EDProduct is not there
00561   void
00562   Principal::getAllProvenance(std::vector<Provenance const*>& provenances) const {
00563     provenances.clear();
00564     for (const_iterator i = begin(), iEnd = end(); i != iEnd; ++i) {
00565       if ((*i)->provenanceAvailable()) {
00566         // We do not attempt to get the event/lumi/run status from the provenance,
00567         // because the per event provenance may have been dropped.
00568         if ((*i)->provenance()->product().present()) {
00569            provenances.push_back((*i)->provenance());
00570         }
00571       }
00572     }
00573   }
00574 
00575   void
00576   Principal::recombine(Principal& other, std::vector<BranchID> const& bids) {
00577     for (std::vector<BranchID>::const_iterator it = bids.begin(), itEnd = bids.end(); it != itEnd; ++it) {
00578       ProductTransientIndex index= preg_->indexFrom(*it);
00579       assert(index!=ProductRegistry::kInvalidIndex);
00580       ProductTransientIndex indexO = other.preg_->indexFrom(*it);
00581       assert(indexO!=ProductRegistry::kInvalidIndex);
00582       groups_[index].swap(other.groups_[indexO]);
00583     }
00584     store_->mergeReaders(other.store());
00585     branchMapperPtr_->mergeMappers(other.branchMapperPtr());
00586   }
00587 
00588   EDProduct const*
00589   Principal::getIt(ProductID const& pid) const {
00590     assert(0);
00591     return 0;
00592   }
00593 
00594   void
00595   Principal::maybeFlushCache(TypeID const& tid, InputTag const& tag) const {
00596     if (tag.typeID() != tid ||
00597         tag.branchType() != branchType() ||
00598         tag.productRegistry() != &productRegistry()) {
00599       tag.fillCount() = 0;
00600       tag.cachedOffset() = 0U;
00601       tag.typeID() = tid;
00602       tag.branchType() = branchType();
00603       tag.productRegistry() = &productRegistry();
00604     }
00605   }
00606 
00607   void
00608   Principal::checkUniquenessAndType(std::auto_ptr<EDProduct>& prod, Group const* g) const {
00609     if (prod.get() == 0) return;
00610     // These are defensive checks against things that should never happen, but have.
00611     // Checks that the same physical product has not already been put into the event.
00612     bool alreadyPresent = !productPtrs_.insert(prod.get()).second;
00613     if (alreadyPresent) {
00614       g->checkType(*prod.release());
00615       throw edm::Exception(errors::EventCorruption)
00616           << "Product on branch " << g->branchDescription().branchName() << " occurs twice in the same event.\n";
00617     }
00618     // Checks that the real type of the product matches the branch.
00619     g->checkType(*prod);
00620   }
00621 
00622   void
00623   Principal::putOrMerge(std::auto_ptr<EDProduct> prod, Group const* g) const {
00624     bool willBePut = g->putOrMergeProduct();
00625     if (willBePut) {
00626       checkUniquenessAndType(prod, g);
00627       g->putProduct(prod);
00628     } else {
00629       g->checkType(*prod);
00630       g->mergeProduct(prod);
00631     }
00632   }
00633 
00634   void
00635   Principal::putOrMerge(std::auto_ptr<EDProduct> prod, std::auto_ptr<ProductProvenance> prov, Group* g) {
00636     bool willBePut = g->putOrMergeProduct();
00637     if (willBePut) {
00638       checkUniquenessAndType(prod, g);
00639       g->putProduct(prod, prov);
00640     } else {
00641       g->checkType(*prod);
00642       g->mergeProduct(prod, prov);
00643     }
00644   }
00645 
00646   void
00647   Principal::swapBase(Principal& iOther) {
00648     std::swap(processHistoryPtr_, iOther.processHistoryPtr_);
00649     std::swap(processHistoryID_, iOther.processHistoryID_);
00650     std::swap(processConfiguration_,iOther.processConfiguration_);
00651     std::swap(groups_,iOther.groups_);
00652     std::swap(preg_, iOther.preg_);
00653     std::swap(branchMapperPtr_,iOther.branchMapperPtr_);
00654     std::swap(store_,iOther.store_);
00655   }
00656 
00657   void
00658   Principal::adjustIndexesAfterProductRegistryAddition() {
00659     if (preg_->constProductList().size() > groups_.size()) {
00660       GroupCollection newGroups(preg_->constProductList().size(), SharedGroupPtr());
00661       for (Principal::const_iterator i = begin(), iEnd = end(); i != iEnd; ++i) {
00662         ProductTransientIndex index = preg_->indexFrom((*i)->branchDescription().branchID());
00663         assert(index != ProductRegistry::kInvalidIndex);
00664         newGroups[index] = *i;
00665       }
00666       groups_.swap(newGroups);
00667       // Now we must add new groups for any new product registry entries.
00668       ProductRegistry::ProductList const& prodsList = preg_->productList();
00669       for(ProductRegistry::ProductList::const_iterator itProdInfo = prodsList.begin(),
00670           itProdInfoEnd = prodsList.end();
00671           itProdInfo != itProdInfoEnd;
00672           ++itProdInfo) {
00673         if (itProdInfo->second.branchType() == branchType_) {
00674           ProductTransientIndex index = preg_->indexFrom(itProdInfo->second.branchID());
00675           assert(index != ProductRegistry::kInvalidIndex);
00676           if (!groups_[index]) {
00677             // no group.  Must add one. The new entry must be an input group.
00678             assert(!itProdInfo->second.produced());
00679             boost::shared_ptr<ConstBranchDescription> bd(new ConstBranchDescription(itProdInfo->second));
00680             addGroupInput(bd);
00681           }
00682         }
00683       }
00684     }
00685   }
00686 }