solver/detail/SolverQueueItemDelete.cc
solver/detail/SolverQueueItemUpdate.cc
solver/detail/SolverQueueItemInstallOneOf.cc
-
+ solver/detail/SATResolver.cc
)
SET( zypp_solver_detail_HEADERS
solver/detail/SolverQueueItemDelete.h
solver/detail/SolverQueueItemUpdate.h
solver/detail/SolverQueueItemInstallOneOf.h
-
+ solver/detail/SATResolver.h
)
INSTALL( FILES
sat/WhatProvides.cc
sat/LocaleSupport.cc
sat/LookupAttr.cc
- sat/SATResolver.cc
sat/SolvAttr.cc
)
sat/WhatProvides.h
sat/LocaleSupport.h
sat/LookupAttr.h
- sat/SATResolver.h
sat/SolvAttr.h
)
+++ /dev/null
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* SATResolver.cc
- *
- * Copyright (C) 2000-2002 Ximian, Inc.
- * Copyright (C) 2005 SUSE Linux Products GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-#include <sstream>
-#include "zypp/solver/detail/Helper.h"
-#include "zypp/base/String.h"
-#include "zypp/Capability.h"
-#include "zypp/ResStatus.h"
-#include "zypp/VendorAttr.h"
-#include "zypp/base/Logger.h"
-#include "zypp/base/String.h"
-#include "zypp/base/Gettext.h"
-#include "zypp/base/Algorithm.h"
-#include "zypp/ResPool.h"
-#include "zypp/ResFilters.h"
-#include "zypp/ZConfig.h"
-#include "zypp/sat/SATResolver.h"
-#include "zypp/sat/Pool.h"
-#include "zypp/sat/WhatProvides.h"
-#include "zypp/solver/detail/ProblemSolutionCombi.h"
-
-extern "C" {
-#include "satsolver/repo_solv.h"
-#include "satsolver/poolarch.h"
-#include "satsolver/evr.h"
-#include "satsolver/poolvendor.h"
-#include "satsolver/policy.h"
-#include "satsolver/bitmap.h"
-}
-
-/////////////////////////////////////////////////////////////////////////
-namespace zypp
-{ ///////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////
- namespace solver
- { /////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////
- namespace detail
- { ///////////////////////////////////////////////////////////////////
-
-using namespace std;
-
-IMPL_PTR_TYPE(SATResolver);
-
-//---------------------------------------------------------------------------
-// Callbacks for SAT policies
-//---------------------------------------------------------------------------
-
-int vendorCheck (Pool *pool, Solvable *solvable1, Solvable *solvable2) {
-// DBG << "vendorCheck: " << id2str(pool, solvable1->vendor) << " <--> " << id2str(pool, solvable1->vendor) << endl;
- return VendorAttr::instance().equivalent(id2str(pool, solvable1->vendor), id2str(pool, solvable2->vendor)) ? 0:1;
-}
-
-
-string
-itemToString (PoolItem item, bool shortVersion)
-{
- ostringstream os;
- if (!item) return "";
-
- if (item->kind() != ResTraits<zypp::Package>::kind)
- os << item->kind() << ':';
- os << item->name();
- if (!shortVersion) {
- os << '-' << item->edition();
- if (item->arch() != "") {
- os << '.' << item->arch();
- }
- Repository s = item->repository();
- if (s) {
- string alias = s.info().alias();
- if (!alias.empty()
- && alias != "@system")
- {
- os << '[' << s.info().alias() << ']';
- }
- }
- }
- return os.str();
-}
-
-
-//---------------------------------------------------------------------------
-
-std::ostream &
-SATResolver::dumpOn( std::ostream & os ) const
-{
- os << "<resolver>";
- os << " fixsystem = " << _fixsystem << endl;
- os << " allowdowngrade = " << _allowdowngrade << endl;
- os << " allowarchchange = " << _allowarchchange << endl;
- os << " allowvendorchange = " << _allowvendorchange << endl;
- os << " allowuninstall = " << _allowuninstall << endl;
- os << " updatesystem = " << _updatesystem << endl;
- os << " allowvirtualconflicts = " << _allowvirtualconflicts << endl;
- os << " noupdateprovide = " << _noupdateprovide << endl;
- os << " dosplitprovides = " << _dosplitprovides << endl;
- os << " onlyRequires = " << _onlyRequires << endl;
- return os << "<resolver/>" << endl;
-}
-
-//---------------------------------------------------------------------------
-
-SATResolver::SATResolver (const ResPool & pool, Pool *SATPool)
- : _pool (pool)
- , _SATPool (SATPool)
- , _solv(NULL)
- , _fixsystem(false)
- , _allowdowngrade(false)
- , _allowarchchange(false)
- , _allowvendorchange(false)
- , _allowuninstall(false)
- , _updatesystem(false)
- , _allowvirtualconflicts(false)
- , _noupdateprovide(false)
- , _dosplitprovides(false)
- , _onlyRequires(ZConfig::instance().solver_onlyRequires())
-
-{
-}
-
-
-SATResolver::~SATResolver()
-{
-}
-
-//---------------------------------------------------------------------------
-
-
-ResPool
-SATResolver::pool (void) const
-{
- return _pool;
-}
-
-
-void
-SATResolver::resetItemTransaction (PoolItem item)
-{
- bool found = false;
- for (PoolItemList::const_iterator iter = _items_to_remove.begin();
- iter != _items_to_remove.end(); iter++) {
- if (*iter == item) {
- _items_to_remove.remove(*iter);
- found = true;
- break;
- }
- }
- if (!found) {
- for (PoolItemList::const_iterator iter = _items_to_install.begin();
- iter != _items_to_install.end(); iter++) {
- if (*iter == item) {
- _items_to_install.remove(*iter);
- found = true;
- break;
- }
- }
- }
- if (!found) {
- for (PoolItemList::const_iterator iter = _items_to_keep.begin();
- iter != _items_to_keep.end(); iter++) {
- if (*iter == item) {
- _items_to_keep.remove(*iter);
- found = true;
- break;
- }
- }
- }
- if (!found) {
- for (PoolItemList::const_iterator iter = _items_to_lock.begin();
- iter != _items_to_lock.end(); iter++) {
- if (*iter == item) {
- _items_to_lock.remove(*iter);
- found = true;
- break;
- }
- }
- }
- if (!found) {
- for (PoolItemList::const_iterator iter = _items_to_update.begin();
- iter != _items_to_update.end(); iter++) {
- if (*iter == item) {
- _items_to_update.remove(*iter);
- found = true;
- break;
- }
- }
- }
-}
-
-
-void
-SATResolver::addPoolItemToInstall (PoolItem item)
-{
- resetItemTransaction (item);
- _items_to_install.push_back (item);
- _items_to_install.unique ();
-}
-
-
-void
-SATResolver::addPoolItemsToInstallFromList (PoolItemList & rl)
-{
- for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
- addPoolItemToInstall (*iter);
- }
-}
-
-
-void
-SATResolver::addPoolItemToRemove (PoolItem item)
-{
- resetItemTransaction (item);
- _items_to_remove.push_back (item);
- _items_to_remove.unique ();
-}
-
-
-void
-SATResolver::addPoolItemsToRemoveFromList (PoolItemList & rl)
-{
- for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
- addPoolItemToRemove (*iter);
- }
-}
-
-void
-SATResolver::addPoolItemToLock (PoolItem item)
-{
- resetItemTransaction (item);
- _items_to_lock.push_back (item);
- _items_to_lock.unique ();
-}
-
-void
-SATResolver::addPoolItemToKeep (PoolItem item)
-{
- resetItemTransaction (item);
- _items_to_keep.push_back (item);
- _items_to_keep.unique ();
-}
-
-//---------------------------------------------------------------------------
-
-// copy marked item from solution back to pool
-// if data != NULL, set as APPL_LOW (from establishPool())
-
-static void
-SATSolutionToPool (PoolItem item, const ResStatus & status, const ResStatus::TransactByValue causer)
-{
- // resetting
- item.status().resetTransact (causer);
- item.status().resetWeak ();
-
- bool r;
-
- // installation/deletion
- if (status.isToBeInstalled()) {
- r = item.status().setToBeInstalled (causer);
- _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") install !" << r);
- }
- else if (status.isToBeUninstalledDueToUpgrade()) {
- r = item.status().setToBeUninstalledDueToUpgrade (causer);
- _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") upgrade !" << r);
- }
- else if (status.isToBeUninstalled()) {
- r = item.status().setToBeUninstalled (causer);
- _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") remove !" << r);
- }
-
- // recommend/suggest
- if (status.isRecommended()) {
- item.status().setRecommended(true);
- _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") recommended !" << r);
- }
- else if (status.isSuggested()) {
- item.status().setSuggested(true);
- _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") suggested !" << r);
- }
-
- return;
-}
-
-
-//----------------------------------------------------------------------------
-// helper functions for distupgrade
-//----------------------------------------------------------------------------
-
-bool SATResolver::doesObsoleteItem (PoolItem candidate, PoolItem installed) {
- Solvable *sCandidate = _SATPool->solvables + candidate.satSolvable().id();
- ::_Repo *installedRepo = sat::Pool::instance().systemRepo().get();
-
- Id p, *pp, obsolete, *obsoleteIt;
-
- if ((!installedRepo || sCandidate->repo != installedRepo) && sCandidate->obsoletes) {
- obsoleteIt = sCandidate->repo->idarraydata + sCandidate->obsoletes;
- while ((obsolete = *obsoleteIt++) != 0)
- {
- for (pp = pool_whatprovides(_SATPool, obsolete) ; (p = *pp++) != 0; ) {
- if (p > 0 && installed.satSolvable().id() == (sat::detail::SolvableIdType)p) {
- MIL << candidate << " obsoletes " << installed << endl;
- return true;
- }
- }
- }
- }
- return false;
-}
-
-//----------------------------------------------------------------------------
-//----------------------------------------------------------------------------
-// resolvePool
-//----------------------------------------------------------------------------
-//----------------------------------------------------------------------------
-
-//----------------------------------------------------------------------------
-// Helper functions for the ZYPP-Pool
-//----------------------------------------------------------------------------
-
-
-//------------------------------------------------------------------------------------------------------------
-// This function loops over the pool and grabs all items
-// It clears all previous bySolver() states also
-//
-// Every toBeInstalled is passed to zypp::solver:detail::Resolver.addPoolItemToInstall()
-// Every toBeUninstalled is passed to zypp::solver:detail::Resolver.addPoolItemToRemove()
-//
-// Solver results must be written back to the pool.
-//------------------------------------------------------------------------------------------------------------
-
-
-struct SATCollectTransact : public resfilter::PoolItemFilterFunctor
-{
- SATResolver & resolver;
-
- SATCollectTransact (SATResolver & r)
- : resolver (r)
- { }
-
- bool operator()( PoolItem item ) // only transacts() items go here
- {
- ResStatus status = item.status();
- bool by_solver = (status.isBySolver() || status.isByApplLow());
-
- if (by_solver) {
- _XDEBUG("Resetting " << item );
- item.status().resetTransact( ResStatus::APPL_LOW );// clear any solver/establish transactions
- return true; // back out here, dont re-queue former solver result
- }
-
- if (status.isToBeInstalled()) {
- resolver.addPoolItemToInstall(item); // -> install!
- }
- else if (status.isToBeUninstalled()) {
- resolver.addPoolItemToRemove(item); // -> remove !
- }
- else if (status.isLocked()
- && !by_solver) {
- resolver.addPoolItemToLock (item);
- }
- else if (status.isKept()
- && !by_solver) {
- resolver.addPoolItemToKeep (item);
- }
-
- return true;
- }
-};
-
-
-//----------------------------------------------------------------------------
-//----------------------------------------------------------------------------
-// solving.....
-//----------------------------------------------------------------------------
-//----------------------------------------------------------------------------
-
-
-class CheckIfUpdate : public resfilter::PoolItemFilterFunctor
-{
- public:
- bool is_updated;
-
- CheckIfUpdate()
- : is_updated( false )
- {}
-
- // check this item will be installed
-
- bool operator()( PoolItem item )
- {
- if (item.status().isToBeInstalled())
- {
- is_updated = true;
- return false;
- }
- return true;
- }
-};
-
-
-class SetValidate : public resfilter::PoolItemFilterFunctor
-{
- public:
- Map installedmap, conflictsmap;
-
- SetValidate(Solver *solv)
- {
- solver_create_state_maps(solv, &installedmap, &conflictsmap);
- }
-
- // set validation
-
- bool operator()( PoolItem item )
- {
-
- if (isKind<Product>(item.resolvable())) {
- // FIXME This is a hack for registration 11.0 beta1
- item.status().setSatisfied();
- _XDEBUG("SATSolutionToPool(" << item << " ) satisfied. THIS IS A HACK !");
- return true;
- }
-
- int ret = solvable_trivial_installable_map(item.satSolvable().get(), &installedmap, &conflictsmap);
- item.status().setUndetermined();
-
- if (ret == -1) {
- item.status().setNonRelevant();
- _XDEBUG("SATSolutionToPool(" << item << " ) nonRelevant !");
- } else if (ret == 1) {
- item.status().setSatisfied();
- _XDEBUG("SATSolutionToPool(" << item << " ) satisfied !");
- } else if (ret == 0) {
- item.status().setBroken();
- _XDEBUG("SATSolutionToPool(" << item << " ) broken !");
- }
- return true;
- }
-};
-
-
-bool
-SATResolver::resolvePool(const CapabilitySet & requires_caps,
- const CapabilitySet & conflict_caps)
-{
- SATCollectTransact info (*this);
-
- MIL << "SATResolver::resolvePool()" << endl;
-
- if (_solv) {
- // remove old stuff
- solver_free(_solv);
- _solv = NULL;
- queue_free( &(_jobQueue) );
- }
-
- queue_init( &_jobQueue );
- _items_to_install.clear();
- _items_to_remove.clear();
- _items_to_lock.clear();
- _items_to_keep.clear();
-
- invokeOnEach ( _pool.begin(), _pool.end(),
- functor::functorRef<bool,PoolItem>(info) );
-
- for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) {
- PoolItem r = *iter;
-
- Id id = (*iter)->satSolvable().id();
- if (id == ID_NULL) {
- ERR << "Install: " << *iter << " not found" << endl;
- }
- MIL << "Install " << *iter << " with the SAT-Pool ID: " << id << endl;
- queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE );
- queue_push( &(_jobQueue), id );
- }
-
- for (PoolItemList::const_iterator iter = _items_to_update.begin(); iter != _items_to_update.end(); iter++) {
- PoolItem r = *iter;
-
- Id id = (*iter)->satSolvable().id();
- if (id == ID_NULL) {
- ERR << "Update explicit: " << *iter << " not found" << endl;
- }
- MIL << "Update explicit " << *iter << " with the SAT-Pool ID: " << id << endl;
- queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE_UPDATE );
- queue_push( &(_jobQueue), id );
- }
-
- for (PoolItemList::const_iterator iter = _items_to_remove.begin(); iter != _items_to_remove.end(); iter++) {
- sat::detail::IdType ident( (*iter)->satSolvable().ident().id() );
- MIL << "Delete " << *iter << " with the string ID: " << ident << endl;
- queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE_NAME );
- queue_push( &(_jobQueue), ident);
- }
-
- for (CapabilitySet::const_iterator iter = requires_caps.begin(); iter != requires_caps.end(); iter++) {
- queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE_PROVIDES );
- queue_push( &(_jobQueue), iter->id() );
- MIL << "Requires " << *iter << endl;
- }
-
- for (CapabilitySet::const_iterator iter = conflict_caps.begin(); iter != conflict_caps.end(); iter++) {
- queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE_PROVIDES);
- queue_push( &(_jobQueue), iter->id() );
- MIL << "Conflicts " << *iter << endl;
- }
-
- for (PoolItemList::const_iterator iter = _items_to_lock.begin(); iter != _items_to_lock.end(); iter++) {
- sat::detail::SolvableIdType ident( (*iter)->satSolvable().id() );
- if (iter->status().isInstalled()) {
- MIL << "Lock installed item " << *iter << " with the string ID: " << ident << endl;
- queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE );
- queue_push( &(_jobQueue), ident );
- } else {
- MIL << "Lock NOT installed item " << *iter << " with the string ID: " << ident << endl;
- queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE );
- queue_push( &(_jobQueue), ident );
- }
- }
-
- for (PoolItemList::const_iterator iter = _items_to_keep.begin(); iter != _items_to_keep.end(); iter++) {
- sat::detail::SolvableIdType ident( (*iter)->satSolvable().id() );
- if (iter->status().isInstalled()) {
- MIL << "Keep installed item " << *iter << " with the string ID: " << ident << endl;
- queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE | SOLVER_WEAK);
- queue_push( &(_jobQueue), ident );
- } else {
- MIL << "Keep NOT installed item " << *iter << " with the string ID: " << ident << endl;
- queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE | SOLVER_WEAK);
- queue_push( &(_jobQueue), ident );
- }
- }
-
- _solv = solver_create( _SATPool, sat::Pool::instance().systemRepo().get() );
- _solv->vendorCheckCb = &vendorCheck;
- _solv->fixsystem = _fixsystem;
- _solv->updatesystem = _updatesystem;
- _solv->allowdowngrade = _allowdowngrade;
- _solv->allowuninstall = _allowuninstall;
- _solv->allowarchchange = _allowarchchange;
- _solv->dosplitprovides = _dosplitprovides;
- _solv->noupdateprovide = _noupdateprovide;
- _solv->dontinstallrecommended = _onlyRequires;
-
- sat::Pool::instance().prepare();
-
- // Solve !
- MIL << "Starting solving...." << endl;
- MIL << *this;
- solver_solve( _solv, &(_jobQueue) );
- MIL << "....Solver end" << endl;
-
- // copying solution back to zypp pool
- //-----------------------------------------
-
- if (_solv->problems.count > 0 )
- {
- ERR << "Solverrun finished with an ERROR" << endl;
- return false;
- }
-
- /* solvables to be installed */
- for (int i = 0; i < _solv->decisionq.count; i++)
- {
- Id p;
- p = _solv->decisionq.elements[i];
- if (p < 0 || !sat::Solvable(p))
- continue;
- if (sat::Solvable(p).repository().get() == _solv->installed)
- continue;
-
- PoolItem poolItem = _pool.find (sat::Solvable(p));
- if (poolItem) {
- SATSolutionToPool (poolItem, ResStatus::toBeInstalled, ResStatus::SOLVER);
- } else {
- ERR << "id " << p << " not found in ZYPP pool." << endl;
- }
- }
-
- /* solvables to be erased */
- for (int i = _solv->installed->start; i < _solv->installed->start + _solv->installed->nsolvables; i++)
- {
- if (_solv->decisionmap[i] > 0)
- continue;
-
- PoolItem poolItem = _pool.find (sat::Solvable(i));
- if (poolItem) {
- // Check if this is an update
- CheckIfUpdate info;
- invokeOnEach( _pool.byIdentBegin( poolItem ),
- _pool.byIdentEnd( poolItem ),
- resfilter::ByUninstalled(), // ByUninstalled
- functor::functorRef<bool,PoolItem> (info) );
-
- if (info.is_updated) {
- SATSolutionToPool (poolItem, ResStatus::toBeUninstalledDueToUpgrade , ResStatus::SOLVER);
- } else {
- SATSolutionToPool (poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER);
- }
- } else {
- ERR << "id " << i << " not found in ZYPP pool." << endl;
- }
- }
-
- /* solvables which are recommended */
- for (int i = 0; i < _solv->recommendations.count; i++)
- {
- Id p;
- p = _solv->recommendations.elements[i];
- if (p < 0 || !sat::Solvable(p))
- continue;
-
- PoolItem poolItem = _pool.find (sat::Solvable(p));
- if (poolItem) {
- ResStatus status = poolItem.status();
- status.setRecommended (true);
- SATSolutionToPool (poolItem, status, ResStatus::SOLVER);
- } else {
- ERR << "id " << p << " not found in ZYPP pool." << endl;
- }
- }
-
- /* solvables which are suggested */
- for (int i = 0; i < _solv->suggestions.count; i++)
- {
- Id p;
- p = _solv->suggestions.elements[i];
- if (p < 0 || !sat::Solvable(p))
- continue;
-
- PoolItem poolItem = _pool.find (sat::Solvable(p));
- if (poolItem) {
- ResStatus status = poolItem.status();
- status.setSuggested (true);
- SATSolutionToPool (poolItem, status, ResStatus::SOLVER);
- } else {
- ERR << "id " << p << " not found in ZYPP pool." << endl;
- }
- }
-
- /* Write validation state back to pool */
- SetValidate infoValidate(_solv);
- invokeOnEach( _pool.begin(),
- _pool.end(),
- functor::not_c(resfilter::byKind<Package>()), // every solvable BUT packages
- functor::functorRef<bool,PoolItem> (infoValidate) );
-
- // cleanup
- solver_free(_solv);
- _solv = NULL;
- queue_free( &(_jobQueue) );
-
- MIL << "SATResolver::resolvePool() done" << endl;
- return true;
-}
-
-
-bool SATResolver::doUpdate()
-{
- MIL << "SATResolver::doUpdate()" << endl;
-
- if (_solv) {
- // remove old stuff
- solver_free(_solv);
- _solv = NULL;
- queue_free( &(_jobQueue) );
- }
-
- queue_init( &_jobQueue );
-
- _solv = solver_create( _SATPool, sat::Pool::instance().systemRepo().get() );
- _solv->vendorCheckCb = &vendorCheck;
-
- _solv->updatesystem = true;
- _solv->dontinstallrecommended = true; // #FIXME dontinstallrecommended maybe set to false if it works correctly
-
- sat::Pool::instance().prepare();
-
- // Solve !
- MIL << "Starting solving for update...." << endl;
- MIL << *this;
- solver_solve( _solv, &(_jobQueue) );
- MIL << "....Solver end" << endl;
-
- // copying solution back to zypp pool
- //-----------------------------------------
-
- /* solvables to be installed */
- for (int i = 0; i < _solv->decisionq.count; i++)
- {
- Id p;
- p = _solv->decisionq.elements[i];
- if (p < 0 || !sat::Solvable(p))
- continue;
- if (sat::Solvable(p).repository().get() == _solv->installed)
- continue;
-
- PoolItem poolItem = _pool.find (sat::Solvable(p));
- if (poolItem) {
- SATSolutionToPool (poolItem, ResStatus::toBeInstalled, ResStatus::SOLVER);
- } else {
- ERR << "id " << p << " not found in ZYPP pool." << endl;
- }
- }
-
- /* solvables to be erased */
- for (int i = _solv->installed->start; i < _solv->installed->start + _solv->installed->nsolvables; i++)
- {
- if (_solv->decisionmap[i] > 0)
- continue;
-
- PoolItem poolItem = _pool.find (sat::Solvable(i));
- if (poolItem) {
- // Check if this is an update
- CheckIfUpdate info;
- invokeOnEach( _pool.byIdentBegin( poolItem ),
- _pool.byIdentEnd( poolItem ),
- resfilter::ByUninstalled(), // ByUninstalled
- functor::functorRef<bool,PoolItem> (info) );
-
- if (info.is_updated) {
- SATSolutionToPool (poolItem, ResStatus::toBeUninstalledDueToUpgrade , ResStatus::SOLVER);
- } else {
- SATSolutionToPool (poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER);
- }
- } else {
- ERR << "id " << i << " not found in ZYPP pool." << endl;
- }
- }
-
- // cleanup
- solver_free(_solv);
- _solv = NULL;
- queue_free( &(_jobQueue) );
-
- MIL << "SATResolver::doUpdate() done" << endl;
- return true;
-}
-
-
-
-//----------------------------------------------------------------------------
-//----------------------------------------------------------------------------
-// error handling
-//----------------------------------------------------------------------------
-//----------------------------------------------------------------------------
-
-//----------------------------------------------------------------------------
-// helper function
-//----------------------------------------------------------------------------
-
-struct FindPackage : public resfilter::ResObjectFilterFunctor
-{
- ProblemSolutionCombi *problemSolution;
- TransactionKind action;
- FindPackage (ProblemSolutionCombi *p, const TransactionKind act)
- : problemSolution (p)
- , action (act)
- {
- }
-
- bool operator()( PoolItem p)
- {
- problemSolution->addSingleAction (p, action);
- return true;
- }
-};
-
-
-string SATResolver::SATprobleminfoString(Id problem, string &detail)
-{
- string ret;
- Pool *pool = _solv->pool;
- Id probr;
- Id dep, source, target;
- Solvable *s, *s2;
-
- probr = solver_findproblemrule(_solv, problem);
- switch (solver_problemruleinfo(_solv, &(_jobQueue), probr, &dep, &source, &target))
- {
- case SOLVER_PROBLEM_UPDATE_RULE:
- s = pool_id2solvable(pool, source);
- ret = str::form (_("problem with installed package %s"), solvable2str(pool, s));
- break;
- case SOLVER_PROBLEM_JOB_RULE:
- ret = str::form (_("conflicting requests"));
- break;
- case SOLVER_PROBLEM_JOB_NOTHING_PROVIDES_DEP:
- ret = str::form (_("nothing provides requested %s"), dep2str(pool, dep));
- break;
- case SOLVER_PROBLEM_NOT_INSTALLABLE:
- s = pool_id2solvable(pool, source);
- ret = str::form (_("%s is not installable"), solvable2str(pool, s));
- break;
- case SOLVER_PROBLEM_NOTHING_PROVIDES_DEP:
- s = pool_id2solvable(pool, source);
- ret = str::form (_("nothing provides %s needed by %s"), dep2str(pool, dep), solvable2str(pool, s));
- break;
- case SOLVER_PROBLEM_SAME_NAME:
- s = pool_id2solvable(pool, source);
- s2 = pool_id2solvable(pool, target);
- ret = str::form (_("cannot install both %s and %s"), solvable2str(pool, s), solvable2str(pool, s2));
- break;
- case SOLVER_PROBLEM_PACKAGE_CONFLICT:
- s = pool_id2solvable(pool, source);
- s2 = pool_id2solvable(pool, target);
- ret = str::form (_("%s conflicts with %s provided by %s"), solvable2str(pool, s), dep2str(pool, dep), solvable2str(pool, s2));
- break;
- case SOLVER_PROBLEM_PACKAGE_OBSOLETES:
- s = pool_id2solvable(pool, source);
- s2 = pool_id2solvable(pool, target);
- ret = str::form (_("%s obsoletes %s provided by %s"), solvable2str(pool, s), dep2str(pool, dep), solvable2str(pool, s2));
- break;
- case SOLVER_PROBLEM_DEP_PROVIDERS_NOT_INSTALLABLE:
- s = pool_id2solvable(pool, source);
- Capability cap(dep);
- sat::WhatProvides possibleProviders(cap);
-
- // check, if a provider will be deleted
- typedef list<PoolItem> ProviderList;
- ProviderList providerlistInstalled, providerlistUninstalled;
- for_( iter1, possibleProviders.begin(), possibleProviders.end() ) {
- PoolItem provider1 = ResPool::instance().find( *iter1 );
- // find pair of an installed/uninstalled item with the same NVR
- bool found = false;
- for_( iter2, possibleProviders.begin(), possibleProviders.end() ) {
- PoolItem provider2 = ResPool::instance().find( *iter2 );
- if (compareByNVR (provider1.resolvable(),provider2.resolvable()) == 0
- && ( (provider1.status().isInstalled() && provider2.status().isUninstalled())
- || (provider2.status().isInstalled() && provider1.status().isUninstalled()) )) {
- found = true;
- break;
- }
- }
- if (!found) {
- if (provider1.status().isInstalled())
- providerlistInstalled.push_back(provider1);
- else
- providerlistUninstalled.push_back(provider1);
- }
- }
-
- ret = str::form (_("%s requires %s, but this requirement cannot be provided"), solvable2str(pool, s), dep2str(pool, dep));
- if (providerlistInstalled.size() > 0) {
- detail += _("deleted providers: ");
- for (ProviderList::const_iterator iter = providerlistInstalled.begin(); iter != providerlistInstalled.end(); iter++) {
- if (iter == providerlistInstalled.begin())
- detail += itemToString (*iter, false);
- else
- detail += "\n " + itemToString (*iter, false);
- }
- }
- if (providerlistUninstalled.size() > 0) {
- if (detail.size() > 0)
- detail += _("\nuninstallable providers: ");
- else
- detail = _("uninstallable providers: ");
- for (ProviderList::const_iterator iter = providerlistUninstalled.begin(); iter != providerlistUninstalled.end(); iter++) {
- if (iter == providerlistUninstalled.begin())
- detail += itemToString (*iter, false);
- else
- detail += "\n " + itemToString (*iter, false);
- }
- }
- break;
- }
-
- return ret;
-}
-
-ResolverProblemList
-SATResolver::problems ()
-{
- ResolverProblemList resolverProblems;
- if (_solv && _solv->problems.count) {
- Pool *pool = _solv->pool;
- int pcnt;
- Id p, rp, what;
- Id problem, solution, element;
- Solvable *s, *sd;
-
- MIL << "Encountered problems! Here are the solutions:\n" << endl;
- pcnt = 1;
- problem = 0;
- while ((problem = solver_next_problem(_solv, problem)) != 0) {
- MIL << "Problem " << pcnt++ << ":" << endl;
- MIL << "====================================" << endl;
- string detail;
- string whatString = SATprobleminfoString (problem,detail);
- MIL << whatString << endl;
- MIL << "------------------------------------" << endl;
- ResolverProblem_Ptr resolverProblem = new ResolverProblem (whatString, detail);
- solution = 0;
- while ((solution = solver_next_solution(_solv, problem, solution)) != 0) {
- element = 0;
- ProblemSolutionCombi *problemSolution = new ProblemSolutionCombi(resolverProblem);
- while ((element = solver_next_solutionelement(_solv, problem, solution, element, &p, &rp)) != 0) {
- if (p == 0) {
- /* job, rp is index into job queue */
- what = _jobQueue.elements[rp];
- switch (_jobQueue.elements[rp-1])
- {
- case SOLVER_INSTALL_SOLVABLE: {
- s = pool->solvables + what;
- PoolItem poolItem = _pool.find (sat::Solvable(what));
- if (poolItem) {
- if (_solv->installed && s->repo == _solv->installed) {
- problemSolution->addSingleAction (poolItem, REMOVE);
- string description = str::form (_("do not keep %s installed"), solvable2str(pool, s) );
- MIL << description << endl;
- problemSolution->addDescription (description);
- } else {
- problemSolution->addSingleAction (poolItem, REMOVE);
- string description = str::form (_("do not install %s"), solvable2str(pool, s));
- MIL << description << endl;
- problemSolution->addDescription (description);
- }
- } else {
- ERR << "SOLVER_INSTALL_SOLVABLE: No item found for " << id2str(pool, s->name) << "-"
- << id2str(pool, s->evr) << "." << id2str(pool, s->arch) << endl;
- }
- }
- break;
- case SOLVER_ERASE_SOLVABLE: {
- s = pool->solvables + what;
- PoolItem poolItem = _pool.find (sat::Solvable(what));
- if (poolItem) {
- if (_solv->installed && s->repo == _solv->installed) {
- problemSolution->addSingleAction (poolItem, KEEP);
- string description = str::form (_("keep %s"), solvable2str(pool, s));
- MIL << description << endl;
- problemSolution->addDescription (description);
- } else {
- problemSolution->addSingleAction (poolItem, INSTALL);
- string description = str::form (_("do not forbid installation of %s"), solvable2str(pool, s));
- MIL << description << endl;
- problemSolution->addDescription (description);
- }
- } else {
- ERR << "SOLVER_ERASE_SOLVABLE: No item found for " << id2str(pool, s->name) << "-" << id2str(pool, s->evr) << "." <<
- id2str(pool, s->arch) << endl;
- }
- }
- break;
- case SOLVER_INSTALL_SOLVABLE_NAME:
- {
- FindPackage info (problemSolution, KEEP);
- IdString ident( what );
- invokeOnEach( _pool.byIdentBegin( ident ),
- _pool.byIdentEnd( ident ),
- resfilter::ByUninstalled (),
- functor::functorRef<bool,PoolItem> (info) );
- string description = str::form (_("do not install %s"), ident.c_str() );
- MIL << description << endl;
- problemSolution->addDescription (description);
- }
- break;
- case SOLVER_ERASE_SOLVABLE_NAME:
- {
- FindPackage info (problemSolution, KEEP);
- IdString ident( what );
- invokeOnEach( _pool.byIdentBegin( ident ),
- _pool.byIdentEnd( ident ),
- functor::chain (resfilter::ByInstalled (), // ByInstalled
- resfilter::ByTransact ()), // will be deinstalled
- functor::functorRef<bool,PoolItem> (info) );
- string description = str::form (_("keep %s"), ident.c_str());
- MIL << description << endl;
- problemSolution->addDescription (description);
- }
- break;
- case SOLVER_INSTALL_SOLVABLE_PROVIDES:
- {
- Id p, *pp;
- FOR_PROVIDES(p, pp, what);
- {
- PoolItem poolItem = _pool.find (sat::Solvable(p));
- if (poolItem.status().isToBeInstalled()
- || poolItem.status().staysUninstalled())
- problemSolution->addSingleAction (poolItem, KEEP);
- }
- string description = str::form (_("do not ask to install a solvable providing %s"), dep2str(pool, what));
- MIL << description << endl;
- problemSolution->addDescription (description);
- }
- break;
- case SOLVER_ERASE_SOLVABLE_PROVIDES:
- {
- Id p, *pp;
- FOR_PROVIDES(p, pp, what);
- {
- PoolItem poolItem = _pool.find (sat::Solvable(p));
- if (poolItem.status().isToBeUninstalled()
- || poolItem.status().staysInstalled())
- problemSolution->addSingleAction (poolItem, KEEP);
- }
- string description = str::form (_("do not ask to delete all solvables providing %s"), dep2str(pool, what));
- MIL << description << endl;
- problemSolution->addDescription (description);
- }
- break;
- case SOLVER_INSTALL_SOLVABLE_UPDATE:
- {
- PoolItem poolItem = _pool.find (sat::Solvable(what));
- s = pool->solvables + what;
- if (poolItem) {
- if (_solv->installed && s->repo == _solv->installed) {
- problemSolution->addSingleAction (poolItem, KEEP);
- string description = str::form (_("do not install most recent version of %s"), solvable2str(pool, s));
- MIL << description << endl;
- problemSolution->addDescription (description);
- } else {
- ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE " << poolItem << " is not selected for installation" << endl;
- }
- } else {
- ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE: No item found for " << id2str(pool, s->name) << "-" << id2str(pool, s->evr) << "." <<
- id2str(pool, s->arch) << endl;
- }
- }
- break;
- default:
- MIL << "- do something different" << endl;
- ERR << "No valid solution available" << endl;
- break;
- }
- } else {
- /* policy, replace p with rp */
- s = pool->solvables + p;
- sd = rp ? pool->solvables + rp : 0;
-
- PoolItem itemFrom = _pool.find (sat::Solvable(p));
- if (rp)
- {
- int gotone = 0;
-
- PoolItem itemTo = _pool.find (sat::Solvable(rp));
- if (itemFrom && itemTo) {
- problemSolution->addSingleAction (itemTo, INSTALL);
-
- if (evrcmp(pool, s->evr, sd->evr, EVRCMP_COMPARE ) > 0)
- {
- string description = str::form (_("downgrade of %s to %s"), solvable2str(pool, s), solvable2str(pool, sd));
- MIL << description << endl;
- problemSolution->addDescription (description);
- gotone = 1;
- }
- if (!_solv->allowarchchange && s->name == sd->name && s->arch != sd->arch && policy_illegal_archchange(_solv, s, sd))
- {
- string description = str::form (_("architecture change of %s to %s"), solvable2str(pool, s), solvable2str(pool, sd));
- MIL << description << endl;
- problemSolution->addDescription (description);
- gotone = 1;
- }
- if (!_solv->allowvendorchange && s->name == sd->name && s->vendor != sd->vendor && policy_illegal_vendorchange(_solv, s, sd))
- {
- string description = str::form (_("install %s (with vendor change)\n %s\n-->\n %s") ,
- solvable2str(pool, sd) , id2str(pool, s->vendor),
- string(sd->vendor ? id2str(pool, sd->vendor) : " (no vendor) ").c_str() );
- MIL << description << endl;
- problemSolution->addDescription (description);
- gotone = 1;
- }
- if (!gotone) {
- string description = str::form (_("replacement of %s with %s"), solvable2str(pool, s), solvable2str(pool, sd));
- MIL << description << endl;
- problemSolution->addDescription (description);
- }
- } else {
- ERR << id2str(pool, s->name) << "-" << id2str(pool, s->evr) << "." << id2str(pool, s->arch)
- << " or " << id2str(pool, sd->name) << "-" << id2str(pool, sd->evr) << "." << id2str(pool, sd->arch) << " not found" << endl;
- }
- }
- else
- {
- if (itemFrom) {
- string description = str::form (_("deinstallation of %s"), solvable2str(pool, s));
- MIL << description << endl;
- problemSolution->addDescription (description);
- problemSolution->addSingleAction (itemFrom, REMOVE);
- }
- }
- }
- }
- resolverProblem->addSolution (problemSolution,
- problemSolution->actionCount() > 1 ? true : false); // Solutions with more than 1 action will be shown first.
- MIL << "------------------------------------" << endl;
- }
- // save problem
- resolverProblems.push_back (resolverProblem);
- }
- }
- return resolverProblems;
-}
-
-void
-SATResolver::applySolutions (const ProblemSolutionList & solutions)
-{
- for (ProblemSolutionList::const_iterator iter = solutions.begin();
- iter != solutions.end(); ++iter) {
- ProblemSolution_Ptr solution = *iter;
- Resolver dummyResolver(_pool);
- if (!solution->apply (dummyResolver))
- break;
- }
-}
-
-
-
-///////////////////////////////////////////////////////////////////
-};// namespace detail
- /////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////
- };// namespace solver
- ///////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////
-};// namespace zypp
-/////////////////////////////////////////////////////////////////////////
-
+++ /dev/null
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* SATResolver.h
- *
- * Copyright (C) 2000-2002 Ximian, Inc.
- * Copyright (C) 2005 SUSE Linux Products GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-
-#ifndef ZYPP_SOLVER_DETAIL_SAT_RESOLVER_H
-#define ZYPP_SOLVER_DETAIL_SAT_RESOLVER_H
-
-#include <iosfwd>
-#include <list>
-#include <map>
-#include <string>
-
-#include "zypp/base/ReferenceCounted.h"
-#include "zypp/base/PtrTypes.h"
-#include "zypp/ResPool.h"
-#include "zypp/base/SerialNumber.h"
-#include "zypp/ProblemTypes.h"
-#include "zypp/ResolverProblem.h"
-#include "zypp/ProblemSolution.h"
-#include "zypp/Capability.h"
-extern "C" {
-#include "satsolver/solver.h"
-#include "satsolver/pool.h"
-}
-
-
-/////////////////////////////////////////////////////////////////////////
-namespace zypp
-{ ///////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////
- namespace solver
- { /////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////
- namespace detail
- { ///////////////////////////////////////////////////////////////////
-
-
-///////////////////////////////////////////////////////////////////
-//
-// CLASS NAME : SATResolver
-
-class SATResolver : public base::ReferenceCounted, private base::NonCopyable {
-
- private:
- ResPool _pool;
- Pool *_SATPool;
- Solver *_solv;
- Queue _jobQueue;
-
- // list populated by calls to addPoolItemTo*()
- PoolItemList _items_to_install;
- PoolItemList _items_to_update;
- PoolItemList _items_to_remove;
- PoolItemList _items_to_lock;
- PoolItemList _items_to_keep;
-
- bool _fixsystem; // repair errors in rpm dependency graph
- bool _allowdowngrade; // allow to downgrade installed solvable
- bool _allowarchchange; // allow to change architecture of installed solvables
- bool _allowvendorchange; // allow to change vendor of installed solvables
- bool _allowuninstall; // allow removal of installed solvables
- bool _updatesystem; // distupgrade
- bool _allowvirtualconflicts; // false: conflicts on package name, true: conflicts on package provides
- bool _noupdateprovide; // true: update packages needs not to provide old package
- bool _dosplitprovides; // true: consider legacy split provides
- bool _onlyRequires; // true: consider required packages only
-
- // ---------------------------------- methods
- std::string SATprobleminfoString (Id problem, std::string &detail);
- void resetItemTransaction (PoolItem item);
-
- public:
-
- SATResolver (const ResPool & pool, Pool *SATPool);
- virtual ~SATResolver();
-
- // ---------------------------------- I/O
-
- virtual std::ostream & dumpOn( std::ostream & str ) const;
- friend std::ostream& operator<<(std::ostream& str, const SATResolver & obj)
- { return obj.dumpOn (str); }
-
- ResPool pool (void) const;
- void setPool (const ResPool & pool) { _pool = pool; }
-
- bool resolvePool(const CapabilitySet & requires_caps,
- const CapabilitySet & conflict_caps);
- bool doUpdate();
-
- ResolverProblemList problems ();
- void applySolutions (const ProblemSolutionList &solutions);
-
- void addPoolItemToInstall (PoolItem item);
- void addPoolItemsToInstallFromList (PoolItemList & rl);
-
- void addPoolItemToLock (PoolItem item);
- void addPoolItemToKeep (PoolItem item);
-
- void addPoolItemToRemove (PoolItem item);
- void addPoolItemsToRemoveFromList (PoolItemList & rl);
-
- bool fixsystem () const {return _fixsystem;}
- void setFixsystem ( const bool fixsystem) { _fixsystem = fixsystem;}
-
- bool allowdowngrade () const {return _allowdowngrade;}
- void setAllowdowngrade ( const bool allowdowngrade) { _allowdowngrade = allowdowngrade;}
-
- bool allowarchchange () const {return _allowarchchange;}
- void setAllowarchchange ( const bool allowarchchange) { _allowarchchange = allowarchchange;}
-
- bool allowvendorchange () const {return _allowvendorchange;}
- void setAllowvendorchange ( const bool allowvendorchange) { _allowvendorchange = allowvendorchange;}
-
- bool allowuninstall () const {return _allowuninstall;}
- void setAllowuninstall ( const bool allowuninstall) { _allowuninstall = allowuninstall;}
-
- bool updatesystem () const {return _updatesystem;}
- void setUpdatesystem ( const bool updatesystem) { _updatesystem = updatesystem;}
-
- bool allowvirtualconflicts () const {return _allowvirtualconflicts;}
- void setAllowvirtualconflicts ( const bool allowvirtualconflicts) { _allowvirtualconflicts = allowvirtualconflicts;}
-
- bool noupdateprovide () const {return _noupdateprovide;}
- void setNoupdateprovide ( const bool noupdateprovide) { _noupdateprovide = noupdateprovide;}
-
- bool dosplitprovides () const {return _dosplitprovides;}
- void setDosplitprovides ( const bool dosplitprovides) { _dosplitprovides = dosplitprovides;}
-
- bool onlyRequires () const {return _onlyRequires;}
- void setOnlyRequires ( const bool onlyRequires) { _onlyRequires = onlyRequires;}
-
- bool doesObsoleteItem (PoolItem candidate, PoolItem installed);
-};
-
-///////////////////////////////////////////////////////////////////
- };// namespace detail
- /////////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////////
- };// namespace solver
- ///////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////
-};// namespace zypp
-/////////////////////////////////////////////////////////////////////////
-
-#endif // ZYPP_SOLVER_DETAIL_SAT_RESOLVER_H
#include "zypp/base/Iterator.h"
#include "zypp/base/Algorithm.h"
+#include "zypp/solver/detail/SATResolver.h"
+
#include "zypp/ResFilters.h"
#include "zypp/ResStatus.h"
#include "zypp/NameKindProxy.h"
-#include "zypp/sat/SATResolver.h"
#include "zypp/sat/Pool.h"
/////////////////////////////////////////////////////////////////////////
#include "zypp/solver/detail/Resolver.h"
#include "zypp/solver/detail/Helper.h"
#include "zypp/solver/detail/Testcase.h"
+#include "zypp/solver/detail/SATResolver.h"
#include "zypp/Capabilities.h"
#include "zypp/ZConfig.h"
#include "zypp/ResFilters.h"
#include "zypp/sat/Pool.h"
#include "zypp/sat/Solvable.h"
-#include "zypp/sat/SATResolver.h"
#define MAXSOLVERRUNS 5
#include "zypp/solver/detail/Helper.h"
#include "zypp/solver/detail/Resolver.h"
#include "zypp/solver/detail/Testcase.h"
+#include "zypp/solver/detail/SATResolver.h"
#include "zypp/ResolverProblem.h"
#include "zypp/ProblemSolution.h"
#include "zypp/Target.h"
-#include "zypp/sat/SATResolver.h"
-
/////////////////////////////////////////////////////////////////////////
namespace zypp
#include <sstream>
#include "zypp/solver/detail/Resolver.h"
+#include "zypp/solver/detail/SATResolver.h"
#include "zypp/Resolver.h"
#include "zypp/ResolverProblem.h"
-#include "zypp/sat/SATResolver.h"
#include "zypp/base/String.h"
#include "zypp/base/Logger.h"
--- /dev/null
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* SATResolver.cc
+ *
+ * Copyright (C) 2000-2002 Ximian, Inc.
+ * Copyright (C) 2005 SUSE Linux Products GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#include <sstream>
+#include "zypp/solver/detail/Helper.h"
+#include "zypp/base/String.h"
+#include "zypp/Capability.h"
+#include "zypp/ResStatus.h"
+#include "zypp/VendorAttr.h"
+#include "zypp/base/Logger.h"
+#include "zypp/base/String.h"
+#include "zypp/base/Gettext.h"
+#include "zypp/base/Algorithm.h"
+#include "zypp/ResPool.h"
+#include "zypp/ResFilters.h"
+#include "zypp/ZConfig.h"
+#include "zypp/sat/Pool.h"
+#include "zypp/sat/WhatProvides.h"
+#include "zypp/solver/detail/SATResolver.h"
+#include "zypp/solver/detail/ProblemSolutionCombi.h"
+
+extern "C" {
+#include "satsolver/repo_solv.h"
+#include "satsolver/poolarch.h"
+#include "satsolver/evr.h"
+#include "satsolver/poolvendor.h"
+#include "satsolver/policy.h"
+#include "satsolver/bitmap.h"
+}
+
+/////////////////////////////////////////////////////////////////////////
+namespace zypp
+{ ///////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////
+ namespace solver
+ { /////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////
+ namespace detail
+ { ///////////////////////////////////////////////////////////////////
+
+using namespace std;
+
+IMPL_PTR_TYPE(SATResolver);
+
+//---------------------------------------------------------------------------
+// Callbacks for SAT policies
+//---------------------------------------------------------------------------
+
+int vendorCheck (Pool *pool, Solvable *solvable1, Solvable *solvable2) {
+// DBG << "vendorCheck: " << id2str(pool, solvable1->vendor) << " <--> " << id2str(pool, solvable1->vendor) << endl;
+ return VendorAttr::instance().equivalent(id2str(pool, solvable1->vendor), id2str(pool, solvable2->vendor)) ? 0:1;
+}
+
+
+string
+itemToString (PoolItem item, bool shortVersion)
+{
+ ostringstream os;
+ if (!item) return "";
+
+ if (item->kind() != ResTraits<zypp::Package>::kind)
+ os << item->kind() << ':';
+ os << item->name();
+ if (!shortVersion) {
+ os << '-' << item->edition();
+ if (item->arch() != "") {
+ os << '.' << item->arch();
+ }
+ Repository s = item->repository();
+ if (s) {
+ string alias = s.info().alias();
+ if (!alias.empty()
+ && alias != "@system")
+ {
+ os << '[' << s.info().alias() << ']';
+ }
+ }
+ }
+ return os.str();
+}
+
+
+//---------------------------------------------------------------------------
+
+std::ostream &
+SATResolver::dumpOn( std::ostream & os ) const
+{
+ os << "<resolver>";
+ os << " fixsystem = " << _fixsystem << endl;
+ os << " allowdowngrade = " << _allowdowngrade << endl;
+ os << " allowarchchange = " << _allowarchchange << endl;
+ os << " allowvendorchange = " << _allowvendorchange << endl;
+ os << " allowuninstall = " << _allowuninstall << endl;
+ os << " updatesystem = " << _updatesystem << endl;
+ os << " allowvirtualconflicts = " << _allowvirtualconflicts << endl;
+ os << " noupdateprovide = " << _noupdateprovide << endl;
+ os << " dosplitprovides = " << _dosplitprovides << endl;
+ os << " onlyRequires = " << _onlyRequires << endl;
+ return os << "<resolver/>" << endl;
+}
+
+//---------------------------------------------------------------------------
+
+SATResolver::SATResolver (const ResPool & pool, Pool *SATPool)
+ : _pool (pool)
+ , _SATPool (SATPool)
+ , _solv(NULL)
+ , _fixsystem(false)
+ , _allowdowngrade(false)
+ , _allowarchchange(false)
+ , _allowvendorchange(false)
+ , _allowuninstall(false)
+ , _updatesystem(false)
+ , _allowvirtualconflicts(false)
+ , _noupdateprovide(false)
+ , _dosplitprovides(false)
+ , _onlyRequires(ZConfig::instance().solver_onlyRequires())
+
+{
+}
+
+
+SATResolver::~SATResolver()
+{
+}
+
+//---------------------------------------------------------------------------
+
+
+ResPool
+SATResolver::pool (void) const
+{
+ return _pool;
+}
+
+
+void
+SATResolver::resetItemTransaction (PoolItem item)
+{
+ bool found = false;
+ for (PoolItemList::const_iterator iter = _items_to_remove.begin();
+ iter != _items_to_remove.end(); iter++) {
+ if (*iter == item) {
+ _items_to_remove.remove(*iter);
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ for (PoolItemList::const_iterator iter = _items_to_install.begin();
+ iter != _items_to_install.end(); iter++) {
+ if (*iter == item) {
+ _items_to_install.remove(*iter);
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ for (PoolItemList::const_iterator iter = _items_to_keep.begin();
+ iter != _items_to_keep.end(); iter++) {
+ if (*iter == item) {
+ _items_to_keep.remove(*iter);
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ for (PoolItemList::const_iterator iter = _items_to_lock.begin();
+ iter != _items_to_lock.end(); iter++) {
+ if (*iter == item) {
+ _items_to_lock.remove(*iter);
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ for (PoolItemList::const_iterator iter = _items_to_update.begin();
+ iter != _items_to_update.end(); iter++) {
+ if (*iter == item) {
+ _items_to_update.remove(*iter);
+ found = true;
+ break;
+ }
+ }
+ }
+}
+
+
+void
+SATResolver::addPoolItemToInstall (PoolItem item)
+{
+ resetItemTransaction (item);
+ _items_to_install.push_back (item);
+ _items_to_install.unique ();
+}
+
+
+void
+SATResolver::addPoolItemsToInstallFromList (PoolItemList & rl)
+{
+ for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
+ addPoolItemToInstall (*iter);
+ }
+}
+
+
+void
+SATResolver::addPoolItemToRemove (PoolItem item)
+{
+ resetItemTransaction (item);
+ _items_to_remove.push_back (item);
+ _items_to_remove.unique ();
+}
+
+
+void
+SATResolver::addPoolItemsToRemoveFromList (PoolItemList & rl)
+{
+ for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
+ addPoolItemToRemove (*iter);
+ }
+}
+
+void
+SATResolver::addPoolItemToLock (PoolItem item)
+{
+ resetItemTransaction (item);
+ _items_to_lock.push_back (item);
+ _items_to_lock.unique ();
+}
+
+void
+SATResolver::addPoolItemToKeep (PoolItem item)
+{
+ resetItemTransaction (item);
+ _items_to_keep.push_back (item);
+ _items_to_keep.unique ();
+}
+
+//---------------------------------------------------------------------------
+
+// copy marked item from solution back to pool
+// if data != NULL, set as APPL_LOW (from establishPool())
+
+static void
+SATSolutionToPool (PoolItem item, const ResStatus & status, const ResStatus::TransactByValue causer)
+{
+ // resetting
+ item.status().resetTransact (causer);
+ item.status().resetWeak ();
+
+ bool r;
+
+ // installation/deletion
+ if (status.isToBeInstalled()) {
+ r = item.status().setToBeInstalled (causer);
+ _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") install !" << r);
+ }
+ else if (status.isToBeUninstalledDueToUpgrade()) {
+ r = item.status().setToBeUninstalledDueToUpgrade (causer);
+ _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") upgrade !" << r);
+ }
+ else if (status.isToBeUninstalled()) {
+ r = item.status().setToBeUninstalled (causer);
+ _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") remove !" << r);
+ }
+
+ // recommend/suggest
+ if (status.isRecommended()) {
+ item.status().setRecommended(true);
+ _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") recommended !" << r);
+ }
+ else if (status.isSuggested()) {
+ item.status().setSuggested(true);
+ _XDEBUG("SATSolutionToPool(" << item << ", " << status << ") suggested !" << r);
+ }
+
+ return;
+}
+
+
+//----------------------------------------------------------------------------
+// helper functions for distupgrade
+//----------------------------------------------------------------------------
+
+bool SATResolver::doesObsoleteItem (PoolItem candidate, PoolItem installed) {
+ Solvable *sCandidate = _SATPool->solvables + candidate.satSolvable().id();
+ ::_Repo *installedRepo = sat::Pool::instance().systemRepo().get();
+
+ Id p, *pp, obsolete, *obsoleteIt;
+
+ if ((!installedRepo || sCandidate->repo != installedRepo) && sCandidate->obsoletes) {
+ obsoleteIt = sCandidate->repo->idarraydata + sCandidate->obsoletes;
+ while ((obsolete = *obsoleteIt++) != 0)
+ {
+ for (pp = pool_whatprovides(_SATPool, obsolete) ; (p = *pp++) != 0; ) {
+ if (p > 0 && installed.satSolvable().id() == (sat::detail::SolvableIdType)p) {
+ MIL << candidate << " obsoletes " << installed << endl;
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+// resolvePool
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// Helper functions for the ZYPP-Pool
+//----------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------------------------------------
+// This function loops over the pool and grabs all items
+// It clears all previous bySolver() states also
+//
+// Every toBeInstalled is passed to zypp::solver:detail::Resolver.addPoolItemToInstall()
+// Every toBeUninstalled is passed to zypp::solver:detail::Resolver.addPoolItemToRemove()
+//
+// Solver results must be written back to the pool.
+//------------------------------------------------------------------------------------------------------------
+
+
+struct SATCollectTransact : public resfilter::PoolItemFilterFunctor
+{
+ SATResolver & resolver;
+
+ SATCollectTransact (SATResolver & r)
+ : resolver (r)
+ { }
+
+ bool operator()( PoolItem item ) // only transacts() items go here
+ {
+ ResStatus status = item.status();
+ bool by_solver = (status.isBySolver() || status.isByApplLow());
+
+ if (by_solver) {
+ _XDEBUG("Resetting " << item );
+ item.status().resetTransact( ResStatus::APPL_LOW );// clear any solver/establish transactions
+ return true; // back out here, dont re-queue former solver result
+ }
+
+ if (status.isToBeInstalled()) {
+ resolver.addPoolItemToInstall(item); // -> install!
+ }
+ else if (status.isToBeUninstalled()) {
+ resolver.addPoolItemToRemove(item); // -> remove !
+ }
+ else if (status.isLocked()
+ && !by_solver) {
+ resolver.addPoolItemToLock (item);
+ }
+ else if (status.isKept()
+ && !by_solver) {
+ resolver.addPoolItemToKeep (item);
+ }
+
+ return true;
+ }
+};
+
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+// solving.....
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+
+class CheckIfUpdate : public resfilter::PoolItemFilterFunctor
+{
+ public:
+ bool is_updated;
+
+ CheckIfUpdate()
+ : is_updated( false )
+ {}
+
+ // check this item will be installed
+
+ bool operator()( PoolItem item )
+ {
+ if (item.status().isToBeInstalled())
+ {
+ is_updated = true;
+ return false;
+ }
+ return true;
+ }
+};
+
+
+class SetValidate : public resfilter::PoolItemFilterFunctor
+{
+ public:
+ Map installedmap, conflictsmap;
+
+ SetValidate(Solver *solv)
+ {
+ solver_create_state_maps(solv, &installedmap, &conflictsmap);
+ }
+
+ // set validation
+
+ bool operator()( PoolItem item )
+ {
+
+ if (isKind<Product>(item.resolvable())) {
+ // FIXME This is a hack for registration 11.0 beta1
+ item.status().setSatisfied();
+ _XDEBUG("SATSolutionToPool(" << item << " ) satisfied. THIS IS A HACK !");
+ return true;
+ }
+
+ int ret = solvable_trivial_installable_map(item.satSolvable().get(), &installedmap, &conflictsmap);
+ item.status().setUndetermined();
+
+ if (ret == -1) {
+ item.status().setNonRelevant();
+ _XDEBUG("SATSolutionToPool(" << item << " ) nonRelevant !");
+ } else if (ret == 1) {
+ item.status().setSatisfied();
+ _XDEBUG("SATSolutionToPool(" << item << " ) satisfied !");
+ } else if (ret == 0) {
+ item.status().setBroken();
+ _XDEBUG("SATSolutionToPool(" << item << " ) broken !");
+ }
+ return true;
+ }
+};
+
+
+bool
+SATResolver::resolvePool(const CapabilitySet & requires_caps,
+ const CapabilitySet & conflict_caps)
+{
+ SATCollectTransact info (*this);
+
+ MIL << "SATResolver::resolvePool()" << endl;
+
+ if (_solv) {
+ // remove old stuff
+ solver_free(_solv);
+ _solv = NULL;
+ queue_free( &(_jobQueue) );
+ }
+
+ queue_init( &_jobQueue );
+ _items_to_install.clear();
+ _items_to_remove.clear();
+ _items_to_lock.clear();
+ _items_to_keep.clear();
+
+ invokeOnEach ( _pool.begin(), _pool.end(),
+ functor::functorRef<bool,PoolItem>(info) );
+
+ for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) {
+ PoolItem r = *iter;
+
+ Id id = (*iter)->satSolvable().id();
+ if (id == ID_NULL) {
+ ERR << "Install: " << *iter << " not found" << endl;
+ }
+ MIL << "Install " << *iter << " with the SAT-Pool ID: " << id << endl;
+ queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE );
+ queue_push( &(_jobQueue), id );
+ }
+
+ for (PoolItemList::const_iterator iter = _items_to_update.begin(); iter != _items_to_update.end(); iter++) {
+ PoolItem r = *iter;
+
+ Id id = (*iter)->satSolvable().id();
+ if (id == ID_NULL) {
+ ERR << "Update explicit: " << *iter << " not found" << endl;
+ }
+ MIL << "Update explicit " << *iter << " with the SAT-Pool ID: " << id << endl;
+ queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE_UPDATE );
+ queue_push( &(_jobQueue), id );
+ }
+
+ for (PoolItemList::const_iterator iter = _items_to_remove.begin(); iter != _items_to_remove.end(); iter++) {
+ sat::detail::IdType ident( (*iter)->satSolvable().ident().id() );
+ MIL << "Delete " << *iter << " with the string ID: " << ident << endl;
+ queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE_NAME );
+ queue_push( &(_jobQueue), ident);
+ }
+
+ for (CapabilitySet::const_iterator iter = requires_caps.begin(); iter != requires_caps.end(); iter++) {
+ queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE_PROVIDES );
+ queue_push( &(_jobQueue), iter->id() );
+ MIL << "Requires " << *iter << endl;
+ }
+
+ for (CapabilitySet::const_iterator iter = conflict_caps.begin(); iter != conflict_caps.end(); iter++) {
+ queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE_PROVIDES);
+ queue_push( &(_jobQueue), iter->id() );
+ MIL << "Conflicts " << *iter << endl;
+ }
+
+ for (PoolItemList::const_iterator iter = _items_to_lock.begin(); iter != _items_to_lock.end(); iter++) {
+ sat::detail::SolvableIdType ident( (*iter)->satSolvable().id() );
+ if (iter->status().isInstalled()) {
+ MIL << "Lock installed item " << *iter << " with the string ID: " << ident << endl;
+ queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE );
+ queue_push( &(_jobQueue), ident );
+ } else {
+ MIL << "Lock NOT installed item " << *iter << " with the string ID: " << ident << endl;
+ queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE );
+ queue_push( &(_jobQueue), ident );
+ }
+ }
+
+ for (PoolItemList::const_iterator iter = _items_to_keep.begin(); iter != _items_to_keep.end(); iter++) {
+ sat::detail::SolvableIdType ident( (*iter)->satSolvable().id() );
+ if (iter->status().isInstalled()) {
+ MIL << "Keep installed item " << *iter << " with the string ID: " << ident << endl;
+ queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE | SOLVER_WEAK);
+ queue_push( &(_jobQueue), ident );
+ } else {
+ MIL << "Keep NOT installed item " << *iter << " with the string ID: " << ident << endl;
+ queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE | SOLVER_WEAK);
+ queue_push( &(_jobQueue), ident );
+ }
+ }
+
+ _solv = solver_create( _SATPool, sat::Pool::instance().systemRepo().get() );
+ _solv->vendorCheckCb = &vendorCheck;
+ _solv->fixsystem = _fixsystem;
+ _solv->updatesystem = _updatesystem;
+ _solv->allowdowngrade = _allowdowngrade;
+ _solv->allowuninstall = _allowuninstall;
+ _solv->allowarchchange = _allowarchchange;
+ _solv->dosplitprovides = _dosplitprovides;
+ _solv->noupdateprovide = _noupdateprovide;
+ _solv->dontinstallrecommended = _onlyRequires;
+
+ sat::Pool::instance().prepare();
+
+ // Solve !
+ MIL << "Starting solving...." << endl;
+ MIL << *this;
+ solver_solve( _solv, &(_jobQueue) );
+ MIL << "....Solver end" << endl;
+
+ // copying solution back to zypp pool
+ //-----------------------------------------
+
+ if (_solv->problems.count > 0 )
+ {
+ ERR << "Solverrun finished with an ERROR" << endl;
+ return false;
+ }
+
+ /* solvables to be installed */
+ for (int i = 0; i < _solv->decisionq.count; i++)
+ {
+ Id p;
+ p = _solv->decisionq.elements[i];
+ if (p < 0 || !sat::Solvable(p))
+ continue;
+ if (sat::Solvable(p).repository().get() == _solv->installed)
+ continue;
+
+ PoolItem poolItem = _pool.find (sat::Solvable(p));
+ if (poolItem) {
+ SATSolutionToPool (poolItem, ResStatus::toBeInstalled, ResStatus::SOLVER);
+ } else {
+ ERR << "id " << p << " not found in ZYPP pool." << endl;
+ }
+ }
+
+ /* solvables to be erased */
+ for (int i = _solv->installed->start; i < _solv->installed->start + _solv->installed->nsolvables; i++)
+ {
+ if (_solv->decisionmap[i] > 0)
+ continue;
+
+ PoolItem poolItem = _pool.find (sat::Solvable(i));
+ if (poolItem) {
+ // Check if this is an update
+ CheckIfUpdate info;
+ invokeOnEach( _pool.byIdentBegin( poolItem ),
+ _pool.byIdentEnd( poolItem ),
+ resfilter::ByUninstalled(), // ByUninstalled
+ functor::functorRef<bool,PoolItem> (info) );
+
+ if (info.is_updated) {
+ SATSolutionToPool (poolItem, ResStatus::toBeUninstalledDueToUpgrade , ResStatus::SOLVER);
+ } else {
+ SATSolutionToPool (poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER);
+ }
+ } else {
+ ERR << "id " << i << " not found in ZYPP pool." << endl;
+ }
+ }
+
+ /* solvables which are recommended */
+ for (int i = 0; i < _solv->recommendations.count; i++)
+ {
+ Id p;
+ p = _solv->recommendations.elements[i];
+ if (p < 0 || !sat::Solvable(p))
+ continue;
+
+ PoolItem poolItem = _pool.find (sat::Solvable(p));
+ if (poolItem) {
+ ResStatus status = poolItem.status();
+ status.setRecommended (true);
+ SATSolutionToPool (poolItem, status, ResStatus::SOLVER);
+ } else {
+ ERR << "id " << p << " not found in ZYPP pool." << endl;
+ }
+ }
+
+ /* solvables which are suggested */
+ for (int i = 0; i < _solv->suggestions.count; i++)
+ {
+ Id p;
+ p = _solv->suggestions.elements[i];
+ if (p < 0 || !sat::Solvable(p))
+ continue;
+
+ PoolItem poolItem = _pool.find (sat::Solvable(p));
+ if (poolItem) {
+ ResStatus status = poolItem.status();
+ status.setSuggested (true);
+ SATSolutionToPool (poolItem, status, ResStatus::SOLVER);
+ } else {
+ ERR << "id " << p << " not found in ZYPP pool." << endl;
+ }
+ }
+
+ /* Write validation state back to pool */
+ SetValidate infoValidate(_solv);
+ invokeOnEach( _pool.begin(),
+ _pool.end(),
+ functor::not_c(resfilter::byKind<Package>()), // every solvable BUT packages
+ functor::functorRef<bool,PoolItem> (infoValidate) );
+
+ // cleanup
+ solver_free(_solv);
+ _solv = NULL;
+ queue_free( &(_jobQueue) );
+
+ MIL << "SATResolver::resolvePool() done" << endl;
+ return true;
+}
+
+
+bool SATResolver::doUpdate()
+{
+ MIL << "SATResolver::doUpdate()" << endl;
+
+ if (_solv) {
+ // remove old stuff
+ solver_free(_solv);
+ _solv = NULL;
+ queue_free( &(_jobQueue) );
+ }
+
+ queue_init( &_jobQueue );
+
+ _solv = solver_create( _SATPool, sat::Pool::instance().systemRepo().get() );
+ _solv->vendorCheckCb = &vendorCheck;
+
+ _solv->updatesystem = true;
+ _solv->dontinstallrecommended = true; // #FIXME dontinstallrecommended maybe set to false if it works correctly
+
+ sat::Pool::instance().prepare();
+
+ // Solve !
+ MIL << "Starting solving for update...." << endl;
+ MIL << *this;
+ solver_solve( _solv, &(_jobQueue) );
+ MIL << "....Solver end" << endl;
+
+ // copying solution back to zypp pool
+ //-----------------------------------------
+
+ /* solvables to be installed */
+ for (int i = 0; i < _solv->decisionq.count; i++)
+ {
+ Id p;
+ p = _solv->decisionq.elements[i];
+ if (p < 0 || !sat::Solvable(p))
+ continue;
+ if (sat::Solvable(p).repository().get() == _solv->installed)
+ continue;
+
+ PoolItem poolItem = _pool.find (sat::Solvable(p));
+ if (poolItem) {
+ SATSolutionToPool (poolItem, ResStatus::toBeInstalled, ResStatus::SOLVER);
+ } else {
+ ERR << "id " << p << " not found in ZYPP pool." << endl;
+ }
+ }
+
+ /* solvables to be erased */
+ for (int i = _solv->installed->start; i < _solv->installed->start + _solv->installed->nsolvables; i++)
+ {
+ if (_solv->decisionmap[i] > 0)
+ continue;
+
+ PoolItem poolItem = _pool.find (sat::Solvable(i));
+ if (poolItem) {
+ // Check if this is an update
+ CheckIfUpdate info;
+ invokeOnEach( _pool.byIdentBegin( poolItem ),
+ _pool.byIdentEnd( poolItem ),
+ resfilter::ByUninstalled(), // ByUninstalled
+ functor::functorRef<bool,PoolItem> (info) );
+
+ if (info.is_updated) {
+ SATSolutionToPool (poolItem, ResStatus::toBeUninstalledDueToUpgrade , ResStatus::SOLVER);
+ } else {
+ SATSolutionToPool (poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER);
+ }
+ } else {
+ ERR << "id " << i << " not found in ZYPP pool." << endl;
+ }
+ }
+
+ // cleanup
+ solver_free(_solv);
+ _solv = NULL;
+ queue_free( &(_jobQueue) );
+
+ MIL << "SATResolver::doUpdate() done" << endl;
+ return true;
+}
+
+
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+// error handling
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// helper function
+//----------------------------------------------------------------------------
+
+struct FindPackage : public resfilter::ResObjectFilterFunctor
+{
+ ProblemSolutionCombi *problemSolution;
+ TransactionKind action;
+ FindPackage (ProblemSolutionCombi *p, const TransactionKind act)
+ : problemSolution (p)
+ , action (act)
+ {
+ }
+
+ bool operator()( PoolItem p)
+ {
+ problemSolution->addSingleAction (p, action);
+ return true;
+ }
+};
+
+
+string SATResolver::SATprobleminfoString(Id problem, string &detail)
+{
+ string ret;
+ Pool *pool = _solv->pool;
+ Id probr;
+ Id dep, source, target;
+ Solvable *s, *s2;
+
+ probr = solver_findproblemrule(_solv, problem);
+ switch (solver_problemruleinfo(_solv, &(_jobQueue), probr, &dep, &source, &target))
+ {
+ case SOLVER_PROBLEM_UPDATE_RULE:
+ s = pool_id2solvable(pool, source);
+ ret = str::form (_("problem with installed package %s"), solvable2str(pool, s));
+ break;
+ case SOLVER_PROBLEM_JOB_RULE:
+ ret = str::form (_("conflicting requests"));
+ break;
+ case SOLVER_PROBLEM_JOB_NOTHING_PROVIDES_DEP:
+ ret = str::form (_("nothing provides requested %s"), dep2str(pool, dep));
+ break;
+ case SOLVER_PROBLEM_NOT_INSTALLABLE:
+ s = pool_id2solvable(pool, source);
+ ret = str::form (_("%s is not installable"), solvable2str(pool, s));
+ break;
+ case SOLVER_PROBLEM_NOTHING_PROVIDES_DEP:
+ s = pool_id2solvable(pool, source);
+ ret = str::form (_("nothing provides %s needed by %s"), dep2str(pool, dep), solvable2str(pool, s));
+ break;
+ case SOLVER_PROBLEM_SAME_NAME:
+ s = pool_id2solvable(pool, source);
+ s2 = pool_id2solvable(pool, target);
+ ret = str::form (_("cannot install both %s and %s"), solvable2str(pool, s), solvable2str(pool, s2));
+ break;
+ case SOLVER_PROBLEM_PACKAGE_CONFLICT:
+ s = pool_id2solvable(pool, source);
+ s2 = pool_id2solvable(pool, target);
+ ret = str::form (_("%s conflicts with %s provided by %s"), solvable2str(pool, s), dep2str(pool, dep), solvable2str(pool, s2));
+ break;
+ case SOLVER_PROBLEM_PACKAGE_OBSOLETES:
+ s = pool_id2solvable(pool, source);
+ s2 = pool_id2solvable(pool, target);
+ ret = str::form (_("%s obsoletes %s provided by %s"), solvable2str(pool, s), dep2str(pool, dep), solvable2str(pool, s2));
+ break;
+ case SOLVER_PROBLEM_DEP_PROVIDERS_NOT_INSTALLABLE:
+ s = pool_id2solvable(pool, source);
+ Capability cap(dep);
+ sat::WhatProvides possibleProviders(cap);
+
+ // check, if a provider will be deleted
+ typedef list<PoolItem> ProviderList;
+ ProviderList providerlistInstalled, providerlistUninstalled;
+ for_( iter1, possibleProviders.begin(), possibleProviders.end() ) {
+ PoolItem provider1 = ResPool::instance().find( *iter1 );
+ // find pair of an installed/uninstalled item with the same NVR
+ bool found = false;
+ for_( iter2, possibleProviders.begin(), possibleProviders.end() ) {
+ PoolItem provider2 = ResPool::instance().find( *iter2 );
+ if (compareByNVR (provider1.resolvable(),provider2.resolvable()) == 0
+ && ( (provider1.status().isInstalled() && provider2.status().isUninstalled())
+ || (provider2.status().isInstalled() && provider1.status().isUninstalled()) )) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ if (provider1.status().isInstalled())
+ providerlistInstalled.push_back(provider1);
+ else
+ providerlistUninstalled.push_back(provider1);
+ }
+ }
+
+ ret = str::form (_("%s requires %s, but this requirement cannot be provided"), solvable2str(pool, s), dep2str(pool, dep));
+ if (providerlistInstalled.size() > 0) {
+ detail += _("deleted providers: ");
+ for (ProviderList::const_iterator iter = providerlistInstalled.begin(); iter != providerlistInstalled.end(); iter++) {
+ if (iter == providerlistInstalled.begin())
+ detail += itemToString (*iter, false);
+ else
+ detail += "\n " + itemToString (*iter, false);
+ }
+ }
+ if (providerlistUninstalled.size() > 0) {
+ if (detail.size() > 0)
+ detail += _("\nuninstallable providers: ");
+ else
+ detail = _("uninstallable providers: ");
+ for (ProviderList::const_iterator iter = providerlistUninstalled.begin(); iter != providerlistUninstalled.end(); iter++) {
+ if (iter == providerlistUninstalled.begin())
+ detail += itemToString (*iter, false);
+ else
+ detail += "\n " + itemToString (*iter, false);
+ }
+ }
+ break;
+ }
+
+ return ret;
+}
+
+ResolverProblemList
+SATResolver::problems ()
+{
+ ResolverProblemList resolverProblems;
+ if (_solv && _solv->problems.count) {
+ Pool *pool = _solv->pool;
+ int pcnt;
+ Id p, rp, what;
+ Id problem, solution, element;
+ Solvable *s, *sd;
+
+ MIL << "Encountered problems! Here are the solutions:\n" << endl;
+ pcnt = 1;
+ problem = 0;
+ while ((problem = solver_next_problem(_solv, problem)) != 0) {
+ MIL << "Problem " << pcnt++ << ":" << endl;
+ MIL << "====================================" << endl;
+ string detail;
+ string whatString = SATprobleminfoString (problem,detail);
+ MIL << whatString << endl;
+ MIL << "------------------------------------" << endl;
+ ResolverProblem_Ptr resolverProblem = new ResolverProblem (whatString, detail);
+ solution = 0;
+ while ((solution = solver_next_solution(_solv, problem, solution)) != 0) {
+ element = 0;
+ ProblemSolutionCombi *problemSolution = new ProblemSolutionCombi(resolverProblem);
+ while ((element = solver_next_solutionelement(_solv, problem, solution, element, &p, &rp)) != 0) {
+ if (p == 0) {
+ /* job, rp is index into job queue */
+ what = _jobQueue.elements[rp];
+ switch (_jobQueue.elements[rp-1])
+ {
+ case SOLVER_INSTALL_SOLVABLE: {
+ s = pool->solvables + what;
+ PoolItem poolItem = _pool.find (sat::Solvable(what));
+ if (poolItem) {
+ if (_solv->installed && s->repo == _solv->installed) {
+ problemSolution->addSingleAction (poolItem, REMOVE);
+ string description = str::form (_("do not keep %s installed"), solvable2str(pool, s) );
+ MIL << description << endl;
+ problemSolution->addDescription (description);
+ } else {
+ problemSolution->addSingleAction (poolItem, REMOVE);
+ string description = str::form (_("do not install %s"), solvable2str(pool, s));
+ MIL << description << endl;
+ problemSolution->addDescription (description);
+ }
+ } else {
+ ERR << "SOLVER_INSTALL_SOLVABLE: No item found for " << id2str(pool, s->name) << "-"
+ << id2str(pool, s->evr) << "." << id2str(pool, s->arch) << endl;
+ }
+ }
+ break;
+ case SOLVER_ERASE_SOLVABLE: {
+ s = pool->solvables + what;
+ PoolItem poolItem = _pool.find (sat::Solvable(what));
+ if (poolItem) {
+ if (_solv->installed && s->repo == _solv->installed) {
+ problemSolution->addSingleAction (poolItem, KEEP);
+ string description = str::form (_("keep %s"), solvable2str(pool, s));
+ MIL << description << endl;
+ problemSolution->addDescription (description);
+ } else {
+ problemSolution->addSingleAction (poolItem, INSTALL);
+ string description = str::form (_("do not forbid installation of %s"), solvable2str(pool, s));
+ MIL << description << endl;
+ problemSolution->addDescription (description);
+ }
+ } else {
+ ERR << "SOLVER_ERASE_SOLVABLE: No item found for " << id2str(pool, s->name) << "-" << id2str(pool, s->evr) << "." <<
+ id2str(pool, s->arch) << endl;
+ }
+ }
+ break;
+ case SOLVER_INSTALL_SOLVABLE_NAME:
+ {
+ FindPackage info (problemSolution, KEEP);
+ IdString ident( what );
+ invokeOnEach( _pool.byIdentBegin( ident ),
+ _pool.byIdentEnd( ident ),
+ resfilter::ByUninstalled (),
+ functor::functorRef<bool,PoolItem> (info) );
+ string description = str::form (_("do not install %s"), ident.c_str() );
+ MIL << description << endl;
+ problemSolution->addDescription (description);
+ }
+ break;
+ case SOLVER_ERASE_SOLVABLE_NAME:
+ {
+ FindPackage info (problemSolution, KEEP);
+ IdString ident( what );
+ invokeOnEach( _pool.byIdentBegin( ident ),
+ _pool.byIdentEnd( ident ),
+ functor::chain (resfilter::ByInstalled (), // ByInstalled
+ resfilter::ByTransact ()), // will be deinstalled
+ functor::functorRef<bool,PoolItem> (info) );
+ string description = str::form (_("keep %s"), ident.c_str());
+ MIL << description << endl;
+ problemSolution->addDescription (description);
+ }
+ break;
+ case SOLVER_INSTALL_SOLVABLE_PROVIDES:
+ {
+ Id p, *pp;
+ FOR_PROVIDES(p, pp, what);
+ {
+ PoolItem poolItem = _pool.find (sat::Solvable(p));
+ if (poolItem.status().isToBeInstalled()
+ || poolItem.status().staysUninstalled())
+ problemSolution->addSingleAction (poolItem, KEEP);
+ }
+ string description = str::form (_("do not ask to install a solvable providing %s"), dep2str(pool, what));
+ MIL << description << endl;
+ problemSolution->addDescription (description);
+ }
+ break;
+ case SOLVER_ERASE_SOLVABLE_PROVIDES:
+ {
+ Id p, *pp;
+ FOR_PROVIDES(p, pp, what);
+ {
+ PoolItem poolItem = _pool.find (sat::Solvable(p));
+ if (poolItem.status().isToBeUninstalled()
+ || poolItem.status().staysInstalled())
+ problemSolution->addSingleAction (poolItem, KEEP);
+ }
+ string description = str::form (_("do not ask to delete all solvables providing %s"), dep2str(pool, what));
+ MIL << description << endl;
+ problemSolution->addDescription (description);
+ }
+ break;
+ case SOLVER_INSTALL_SOLVABLE_UPDATE:
+ {
+ PoolItem poolItem = _pool.find (sat::Solvable(what));
+ s = pool->solvables + what;
+ if (poolItem) {
+ if (_solv->installed && s->repo == _solv->installed) {
+ problemSolution->addSingleAction (poolItem, KEEP);
+ string description = str::form (_("do not install most recent version of %s"), solvable2str(pool, s));
+ MIL << description << endl;
+ problemSolution->addDescription (description);
+ } else {
+ ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE " << poolItem << " is not selected for installation" << endl;
+ }
+ } else {
+ ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE: No item found for " << id2str(pool, s->name) << "-" << id2str(pool, s->evr) << "." <<
+ id2str(pool, s->arch) << endl;
+ }
+ }
+ break;
+ default:
+ MIL << "- do something different" << endl;
+ ERR << "No valid solution available" << endl;
+ break;
+ }
+ } else {
+ /* policy, replace p with rp */
+ s = pool->solvables + p;
+ sd = rp ? pool->solvables + rp : 0;
+
+ PoolItem itemFrom = _pool.find (sat::Solvable(p));
+ if (rp)
+ {
+ int gotone = 0;
+
+ PoolItem itemTo = _pool.find (sat::Solvable(rp));
+ if (itemFrom && itemTo) {
+ problemSolution->addSingleAction (itemTo, INSTALL);
+
+ if (evrcmp(pool, s->evr, sd->evr, EVRCMP_COMPARE ) > 0)
+ {
+ string description = str::form (_("downgrade of %s to %s"), solvable2str(pool, s), solvable2str(pool, sd));
+ MIL << description << endl;
+ problemSolution->addDescription (description);
+ gotone = 1;
+ }
+ if (!_solv->allowarchchange && s->name == sd->name && s->arch != sd->arch && policy_illegal_archchange(_solv, s, sd))
+ {
+ string description = str::form (_("architecture change of %s to %s"), solvable2str(pool, s), solvable2str(pool, sd));
+ MIL << description << endl;
+ problemSolution->addDescription (description);
+ gotone = 1;
+ }
+ if (!_solv->allowvendorchange && s->name == sd->name && s->vendor != sd->vendor && policy_illegal_vendorchange(_solv, s, sd))
+ {
+ string description = str::form (_("install %s (with vendor change)\n %s\n-->\n %s") ,
+ solvable2str(pool, sd) , id2str(pool, s->vendor),
+ string(sd->vendor ? id2str(pool, sd->vendor) : " (no vendor) ").c_str() );
+ MIL << description << endl;
+ problemSolution->addDescription (description);
+ gotone = 1;
+ }
+ if (!gotone) {
+ string description = str::form (_("replacement of %s with %s"), solvable2str(pool, s), solvable2str(pool, sd));
+ MIL << description << endl;
+ problemSolution->addDescription (description);
+ }
+ } else {
+ ERR << id2str(pool, s->name) << "-" << id2str(pool, s->evr) << "." << id2str(pool, s->arch)
+ << " or " << id2str(pool, sd->name) << "-" << id2str(pool, sd->evr) << "." << id2str(pool, sd->arch) << " not found" << endl;
+ }
+ }
+ else
+ {
+ if (itemFrom) {
+ string description = str::form (_("deinstallation of %s"), solvable2str(pool, s));
+ MIL << description << endl;
+ problemSolution->addDescription (description);
+ problemSolution->addSingleAction (itemFrom, REMOVE);
+ }
+ }
+ }
+ }
+ resolverProblem->addSolution (problemSolution,
+ problemSolution->actionCount() > 1 ? true : false); // Solutions with more than 1 action will be shown first.
+ MIL << "------------------------------------" << endl;
+ }
+ // save problem
+ resolverProblems.push_back (resolverProblem);
+ }
+ }
+ return resolverProblems;
+}
+
+void
+SATResolver::applySolutions (const ProblemSolutionList & solutions)
+{
+ for (ProblemSolutionList::const_iterator iter = solutions.begin();
+ iter != solutions.end(); ++iter) {
+ ProblemSolution_Ptr solution = *iter;
+ Resolver dummyResolver(_pool);
+ if (!solution->apply (dummyResolver))
+ break;
+ }
+}
+
+
+
+///////////////////////////////////////////////////////////////////
+};// namespace detail
+ /////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////
+ };// namespace solver
+ ///////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////
+};// namespace zypp
+/////////////////////////////////////////////////////////////////////////
+
--- /dev/null
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* SATResolver.h
+ *
+ * Copyright (C) 2000-2002 Ximian, Inc.
+ * Copyright (C) 2005 SUSE Linux Products GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef ZYPP_SOLVER_DETAIL_SAT_RESOLVER_H
+#define ZYPP_SOLVER_DETAIL_SAT_RESOLVER_H
+
+#include <iosfwd>
+#include <list>
+#include <map>
+#include <string>
+
+#include "zypp/base/ReferenceCounted.h"
+#include "zypp/base/PtrTypes.h"
+#include "zypp/ResPool.h"
+#include "zypp/base/SerialNumber.h"
+#include "zypp/ProblemTypes.h"
+#include "zypp/ResolverProblem.h"
+#include "zypp/ProblemSolution.h"
+#include "zypp/Capability.h"
+extern "C" {
+#include "satsolver/solver.h"
+#include "satsolver/pool.h"
+}
+
+
+/////////////////////////////////////////////////////////////////////////
+namespace zypp
+{ ///////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////
+ namespace solver
+ { /////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////
+ namespace detail
+ { ///////////////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////////////////
+//
+// CLASS NAME : SATResolver
+
+class SATResolver : public base::ReferenceCounted, private base::NonCopyable {
+
+ private:
+ ResPool _pool;
+ Pool *_SATPool;
+ Solver *_solv;
+ Queue _jobQueue;
+
+ // list populated by calls to addPoolItemTo*()
+ PoolItemList _items_to_install;
+ PoolItemList _items_to_update;
+ PoolItemList _items_to_remove;
+ PoolItemList _items_to_lock;
+ PoolItemList _items_to_keep;
+
+ bool _fixsystem; // repair errors in rpm dependency graph
+ bool _allowdowngrade; // allow to downgrade installed solvable
+ bool _allowarchchange; // allow to change architecture of installed solvables
+ bool _allowvendorchange; // allow to change vendor of installed solvables
+ bool _allowuninstall; // allow removal of installed solvables
+ bool _updatesystem; // distupgrade
+ bool _allowvirtualconflicts; // false: conflicts on package name, true: conflicts on package provides
+ bool _noupdateprovide; // true: update packages needs not to provide old package
+ bool _dosplitprovides; // true: consider legacy split provides
+ bool _onlyRequires; // true: consider required packages only
+
+ // ---------------------------------- methods
+ std::string SATprobleminfoString (Id problem, std::string &detail);
+ void resetItemTransaction (PoolItem item);
+
+ public:
+
+ SATResolver (const ResPool & pool, Pool *SATPool);
+ virtual ~SATResolver();
+
+ // ---------------------------------- I/O
+
+ virtual std::ostream & dumpOn( std::ostream & str ) const;
+ friend std::ostream& operator<<(std::ostream& str, const SATResolver & obj)
+ { return obj.dumpOn (str); }
+
+ ResPool pool (void) const;
+ void setPool (const ResPool & pool) { _pool = pool; }
+
+ bool resolvePool(const CapabilitySet & requires_caps,
+ const CapabilitySet & conflict_caps);
+ bool doUpdate();
+
+ ResolverProblemList problems ();
+ void applySolutions (const ProblemSolutionList &solutions);
+
+ void addPoolItemToInstall (PoolItem item);
+ void addPoolItemsToInstallFromList (PoolItemList & rl);
+
+ void addPoolItemToLock (PoolItem item);
+ void addPoolItemToKeep (PoolItem item);
+
+ void addPoolItemToRemove (PoolItem item);
+ void addPoolItemsToRemoveFromList (PoolItemList & rl);
+
+ bool fixsystem () const {return _fixsystem;}
+ void setFixsystem ( const bool fixsystem) { _fixsystem = fixsystem;}
+
+ bool allowdowngrade () const {return _allowdowngrade;}
+ void setAllowdowngrade ( const bool allowdowngrade) { _allowdowngrade = allowdowngrade;}
+
+ bool allowarchchange () const {return _allowarchchange;}
+ void setAllowarchchange ( const bool allowarchchange) { _allowarchchange = allowarchchange;}
+
+ bool allowvendorchange () const {return _allowvendorchange;}
+ void setAllowvendorchange ( const bool allowvendorchange) { _allowvendorchange = allowvendorchange;}
+
+ bool allowuninstall () const {return _allowuninstall;}
+ void setAllowuninstall ( const bool allowuninstall) { _allowuninstall = allowuninstall;}
+
+ bool updatesystem () const {return _updatesystem;}
+ void setUpdatesystem ( const bool updatesystem) { _updatesystem = updatesystem;}
+
+ bool allowvirtualconflicts () const {return _allowvirtualconflicts;}
+ void setAllowvirtualconflicts ( const bool allowvirtualconflicts) { _allowvirtualconflicts = allowvirtualconflicts;}
+
+ bool noupdateprovide () const {return _noupdateprovide;}
+ void setNoupdateprovide ( const bool noupdateprovide) { _noupdateprovide = noupdateprovide;}
+
+ bool dosplitprovides () const {return _dosplitprovides;}
+ void setDosplitprovides ( const bool dosplitprovides) { _dosplitprovides = dosplitprovides;}
+
+ bool onlyRequires () const {return _onlyRequires;}
+ void setOnlyRequires ( const bool onlyRequires) { _onlyRequires = onlyRequires;}
+
+ bool doesObsoleteItem (PoolItem candidate, PoolItem installed);
+};
+
+///////////////////////////////////////////////////////////////////
+ };// namespace detail
+ /////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////
+ };// namespace solver
+ ///////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////
+};// namespace zypp
+/////////////////////////////////////////////////////////////////////////
+
+#endif // ZYPP_SOLVER_DETAIL_SAT_RESOLVER_H