Imported Upstream version 16.3.2
[platform/upstream/libzypp.git] / zypp / solver / detail / Resolver.cc
index 99ec099..7801a50 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  * 02111-1307, USA.
  */
+#include <boost/static_assert.hpp>
 
-#include "zypp/solver/detail/Resolver.h"
-#include "zypp/solver/detail/Helper.h"
+#define ZYPP_USE_RESOLVER_INTERNALS
 
-#include "zypp/CapSet.h"
+#include "zypp/solver/detail/Resolver.h"
+#include "zypp/solver/detail/Testcase.h"
+#include "zypp/solver/detail/SATResolver.h"
+#include "zypp/solver/detail/ItemCapKind.h"
+#include "zypp/solver/detail/SolutionAction.h"
+#include "zypp/solver/detail/SolverQueueItem.h"
+
+#include "zypp/Capabilities.h"
+#include "zypp/ZConfig.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/CapFilters.h"
-#include "zypp/ZYppFactory.h"
-#include "zypp/SystemResObject.h"
-#include "zypp/solver/detail/ResolverInfoNeededBy.h"
-#include "zypp/capability/FilesystemCap.h"
 #include "zypp/sat/Pool.h"
-#include "zypp/sat/SATResolver.h"
+#include "zypp/sat/Solvable.h"
+#include "zypp/sat/Transaction.h"
+#include "zypp/ResolverProblem.h"
+
+#define MAXSOLVERRUNS 5
 
+using std::endl;
+using std::make_pair;
 
 /////////////////////////////////////////////////////////////////////////
 namespace zypp
 { ///////////////////////////////////////////////////////////////////////
-  ///////////////////////////////////////////////////////////////////
-  namespace zypp_detail
-  { /////////////////////////////////////////////////////////////////
-    Arch defaultArchitecture();
-    /////////////////////////////////////////////////////////////////
-  } // namespace zypp_detail
-  ///////////////////////////////////////////////////////////////////
-
   ///////////////////////////////////////////////////////////////////////
   namespace solver
   { /////////////////////////////////////////////////////////////////////
@@ -57,434 +57,171 @@ namespace zypp
     namespace detail
     { ///////////////////////////////////////////////////////////////////
 
-using namespace std;
-
-IMPL_PTR_TYPE(Resolver);
-
-static const unsigned MAX_SECOND_RUNS( 3 );
-static const unsigned MAX_VALID_SOLUTIONS( 10 );
-static const unsigned TIMOUT_SECOND_RUN( 30 );
-
-static PoolItemSet triggeredSolution;   // only the latest state of an item is interesting
-                                        // for the pool. Documents already inserted items.
+      //using namespace std;
 
 //---------------------------------------------------------------------------
 
-class compare_items {
-public:
-    int operator() (PoolItem_Ref p1,
-                    PoolItem_Ref p2) const
-        { return compareByNVRA(p1.resolvable(),p2.resolvable()) < 0; }
-};
-
 
-std::ostream &
-Resolver::dumpOn( std::ostream & os ) const
+std::ostream & Resolver::dumpOn( std::ostream & os ) const
 {
-    return os << "<resolver/>";
+  os << "<resolver>" << endl;
+  #define OUTS(t) os << "  " << #t << ":\t" << t << endl;
+  OUTS( _forceResolve );
+  OUTS( _upgradeMode );
+  OUTS( _updateMode );
+  OUTS( _verifying );
+  OUTS( _onlyRequires );
+  OUTS( _allowVendorChange );
+  OUTS( _solveSrcPackages );
+  OUTS( _cleandepsOnRemove );
+  OUTS( _ignoreAlreadyRecommended );
+  #undef OUT
+  return os << "<resolver/>";
 }
 
-// Generating a system resolvable in the pool in order to trigger
-// modaliases and hals
-void assertSystemResObjectInPool()
-{
-  ResPool pool( getZYpp()->pool() );
-  if ( pool.byKindBegin<SystemResObject>()
-       == pool.byKindEnd<SystemResObject>() )
-    {
-      // SystemResObject is missing in the pool ==> insert
-      ResStore store;
-      store.insert( SystemResObject::instance() );
-      getZYpp()->addResolvables( store, true ); // true = is installed
-    }
-
-  // set lock
-  if ( ! pool.byKindBegin<SystemResObject>()
-         ->status().setLock( true, ResStatus::USER ) )
-    {
-      WAR << "Unable to set SystemResObject to lock" << endl;
-    }
-}
 
 //---------------------------------------------------------------------------
 
 Resolver::Resolver (const ResPool & pool)
-    : _pool (pool)
-    , _poolchanged( _pool.serial() )
-    , _timeout_seconds (0)
-    , _maxSolverPasses (0)
-    , _verifying (false)
-    , _testing (false)
-    , _tryAllPossibilities (false)
-    , _valid_solution_count (0)
-    , _best_context (NULL)
-    , _establish_context (NULL)
-    , _timed_out (false)
-    , _architecture( zypp_detail::defaultArchitecture() )
-    , _forceResolve (false)
-    , _upgradeMode (false)
-    , _preferHighestVersion (true)
+    : _pool(pool)
+    , _satResolver(NULL)
+    , _poolchanged(_pool.serial() )
+    , _forceResolve            (false)
+    , _upgradeMode             (false)
+    , _updateMode              (false)
+    , _verifying               (false)
+    , _onlyRequires            ( ZConfig::instance().solver_onlyRequires() )
+    , _allowVendorChange       ( ZConfig::instance().solver_allowVendorChange() )
+    , _solveSrcPackages                ( false )
+    , _cleandepsOnRemove       ( ZConfig::instance().solver_cleandepsOnRemove() )
+    , _ignoreAlreadyRecommended        ( true )
 
 {
-
+    sat::Pool satPool( sat::Pool::instance() );
+    _satResolver = new SATResolver(_pool, satPool.get());
 }
 
 
 Resolver::~Resolver()
 {
+  delete _satResolver;
 }
 
 //---------------------------------------------------------------------------
+// forward flags too SATResolver
+#define ZOLV_FLAG_TRIBOOL( ZSETTER, ZGETTER, ZVARNAME, ZVARDEFAULT )                   \
+    void Resolver::ZSETTER( TriBool state_r )                                          \
+    { _satResolver->ZVARNAME = indeterminate(state_r) ? ZVARDEFAULT : bool(state_r); } \
+    bool Resolver::ZGETTER() const                                                     \
+    { return _satResolver->ZVARNAME; }                                                 \
+
+ZOLV_FLAG_TRIBOOL( dupSetAllowDowngrade,       dupAllowDowngrade,      _dup_allowdowngrade,    ZConfig::instance().solver_dupAllowDowngrade() )
+ZOLV_FLAG_TRIBOOL( dupSetAllowNameChange,      dupAllowNameChange,     _dup_allownamechange,   ZConfig::instance().solver_dupAllowNameChange() )
+ZOLV_FLAG_TRIBOOL( dupSetAllowArchChange,      dupAllowArchChange,     _dup_allowarchchange,   ZConfig::instance().solver_dupAllowArchChange() )
+ZOLV_FLAG_TRIBOOL( dupSetAllowVendorChange,    dupAllowVendorChange,   _dup_allowvendorchange, ZConfig::instance().solver_dupAllowVendorChange() )
+
+#undef ZOLV_FLAG_TRIBOOL
+//---------------------------------------------------------------------------
 
-ResPool
-Resolver::pool (void) const
+void Resolver::setAllowVendorChange( TriBool state_r )
 {
-    return _pool;
+  _allowVendorChange = indeterminate(state_r) ? ZConfig::instance().solver_allowVendorChange() : bool(state_r);
 }
 
-void
-Resolver::reset (bool resetValidResults, bool keepExtras )
+void Resolver::setOnlyRequires( TriBool state_r )
 {
-    _verifying = false;
+  _onlyRequires = indeterminate(state_r) ? ZConfig::instance().solver_onlyRequires() : bool(state_r);
+}
 
-    _initial_items.clear();
+void Resolver::setCleandepsOnRemove( TriBool state_r )
+{
+  _cleandepsOnRemove = indeterminate(state_r) ? ZConfig::instance().solver_cleandepsOnRemove() : bool(state_r);
+}
 
-    _items_to_install.clear();
-    _items_to_remove.clear();
-    _items_to_verify.clear();
-    _items_to_establish.clear();
-    _items_to_keep.clear();
+//---------------------------------------------------------------------------
+
+ResPool Resolver::pool() const
+{ return _pool; }
+
+void Resolver::reset( bool keepExtras )
+{
+    _verifying = false;
 
     if (!keepExtras) {
-      _extra_caps.clear();
+      _extra_requires.clear();
       _extra_conflicts.clear();
     }
 
-    _pending_queues.clear();
-    _pruned_queues.clear();
-    _complete_queues.clear();
-    _deferred_queues.clear();
-    _invalid_queues.clear();
-
-    _valid_solution_count = 0;
-
-    _best_context = NULL;
-    _timed_out = false;
-
     _isInstalledBy.clear();
     _installs.clear();
-
-    if (resetValidResults)
-       contextPool.reset();
-
+    _satifiedByInstalled.clear();
+    _installedSatisfied.clear();
 }
 
-//--------------------------------------------------------------------------------------------------
-// Get more information about the solverrun
-// Which item will be installed by another item or triggers an item for installation
-typedef struct {
-    ItemCapKindMap isInstalledBy;
-    ItemCapKindMap installs;
-} Collector;
-
-
-static void
-collector_cb_needed (ResolverInfo_Ptr info, void *data)
+bool Resolver::doUpgrade()
 {
-    Collector *collector = (Collector *)data;
-    if (info->type() == RESOLVER_INFO_TYPE_NEEDED_BY) {
-       ResolverInfoNeededBy_constPtr needed_by = dynamic_pointer_cast<const ResolverInfoNeededBy>(info);
-       if (needed_by->items().size() >= 1) {
-           PoolItem_Ref item = info->affected();
-           PoolItemList itemList = needed_by->items();
-
-           for (PoolItemList::const_iterator iter = itemList.begin();
-                iter != itemList.end(); iter++) {
-               bool found = false;
-               ItemCapKindMap::const_iterator pos = collector->isInstalledBy.find(item);
-               while (pos != collector->isInstalledBy.end()
-                      && pos->first == item
-                      && !found) {
-                          ItemCapKind capKind = pos->second;
-                          if (capKind.item == *iter) found = true;
-                          pos++;
-                      }
-               if (!found) {
-                   ItemCapKind capKind( *iter, needed_by->capability(), needed_by->capKind(), needed_by->initialInstallation() );
-                   collector->isInstalledBy.insert (make_pair( item, capKind));
-               }
-               found = false;
-               pos = collector->installs.find (*iter);
-               while (pos != collector->installs.end()
-                      && pos->first == *iter
-                      && !found) {
-                          ItemCapKind capKind = pos->second;
-                          if (capKind.item == item) found = true;
-                          pos++;
-                      }
-               if (!found) {
-                   ItemCapKind capKindReverse( item, needed_by->capability(), needed_by->capKind(), needed_by->initialInstallation() );
-                   collector->installs.insert (make_pair( *iter, capKindReverse));
-               }
-           }
-
-       }
-    }
+  // Setting Resolver to upgrade mode. SAT solver will do the update
+  _upgradeMode = true;
+  return resolvePool();
 }
 
-void
-Resolver::collectResolverInfo(void)
+void Resolver::doUpdate()
 {
-    ResolverContext_Ptr collectContext = context(); // best context or failed context
-    if ( collectContext != NULL
-        && _isInstalledBy.empty()
-        && _installs.empty()) {
-       Collector collector;
-       collectContext->foreachInfo (PoolItem(), RESOLVER_INFO_PRIORITY_VERBOSE, collector_cb_needed, &collector, false); // do not merge information
-       _isInstalledBy = collector.isInstalledBy;
-       _installs = collector.installs;
-    }
-}
-
-
-const ItemCapKindList Resolver::isInstalledBy (const PoolItem_Ref item) {
-    ItemCapKindList ret;
-    collectResolverInfo();
-
-    for (ItemCapKindMap::const_iterator iter = _isInstalledBy.find(item); iter != _isInstalledBy.end();) {
-       ItemCapKind info = iter->second;
-       PoolItem_Ref iterItem = iter->first;
-       if (iterItem == item) {
-           ret.push_back(info);
-           iter++;
-       } else {
-           // exit
-           iter = _isInstalledBy.end();
-       }
-    }
-    return ret;
+    _updateMode = true;
+    return _satResolver->doUpdate();
 }
 
-const ItemCapKindList Resolver::installs (const PoolItem_Ref item) {
-    ItemCapKindList ret;
-    collectResolverInfo();
+PoolItemList Resolver::problematicUpdateItems() const
+{ return _satResolver->problematicUpdateItems(); }
 
-    for (ItemCapKindMap::const_iterator iter = _installs.find(item); iter != _installs.end();) {
-       ItemCapKind info = iter->second;
-       PoolItem_Ref iterItem = iter->first;
-       if (iterItem == item) {
-           ret.push_back(info);
-           iter++;
-       } else {
-           // exit
-           iter = _installs.end();
-       }
-    }
-    return ret;
-}
+void Resolver::addExtraRequire( const Capability & capability )
+{ _extra_requires.insert (capability); }
 
+void Resolver::removeExtraRequire( const Capability & capability )
+{ _extra_requires.erase (capability); }
 
-//----------------------------------------------------------------------------------------------------
-ResolverContext_Ptr
-Resolver::context (void) const
-{
-    if (_best_context) return _best_context;
-    if (_invalid_queues.empty()) return NULL;
-    ResolverQueue_Ptr invalid = _invalid_queues.front();
-    return invalid->context();
-}
+void Resolver::addExtraConflict( const Capability & capability )
+{ _extra_conflicts.insert (capability); }
 
-void  Resolver::dumpTaskList(const PoolItemList &install, const PoolItemList &remove )
-{
-    for (PoolItemList::const_iterator iter = install.begin();
-         iter != install.end(); iter++) {
-        XXX << "    to_install " << *iter << endl;
-    }
-    for (PoolItemList::const_iterator iter = remove.begin();
-         iter != remove.end(); iter++) {
-        XXX << "    to_remove " << *iter << endl;
-    }
-}
+void Resolver::removeExtraConflict( const Capability & capability )
+{ _extra_conflicts.erase (capability); }
 
-
-//---------------------------------------------------------------------------
-
-void
-Resolver::addSubscribedSource (Repository repo)
-{
-    _subscribed.insert(repo);
-}
-
-void
-Resolver::addPoolItemToInstall (PoolItem_Ref item)
+void Resolver::removeQueueItem( SolverQueueItem_Ptr item )
 {
     bool found = false;
-    for (PoolItemList::const_iterator iter = _items_to_remove.begin();
-        iter != _items_to_remove.end(); iter++) {
+    for (SolverQueueItemList::const_iterator iter = _added_queue_items.begin();
+        iter != _added_queue_items.end(); iter++) {
        if (*iter == item) {
-           _items_to_remove.remove(*iter);
+           _added_queue_items.remove(*iter);
            found = true;
            break;
        }
     }
     if (!found) {
-       _items_to_install.push_back (item);
-       _items_to_install.unique ();
+       _removed_queue_items.push_back (item);
+       _removed_queue_items.unique ();
     }
 }
 
-
-void
-Resolver::addPoolItemsToInstallFromList (PoolItemList & rl)
-{
-    for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
-       addPoolItemToInstall (*iter);
-    }
-}
-
-
-void
-Resolver::addPoolItemToRemove (PoolItem_Ref item)
+void Resolver::addQueueItem( SolverQueueItem_Ptr item )
 {
     bool found = false;
-    for (PoolItemList::const_iterator iter = _items_to_install.begin();
-        iter != _items_to_install.end(); iter++) {
+    for (SolverQueueItemList::const_iterator iter = _removed_queue_items.begin();
+        iter != _removed_queue_items.end(); iter++) {
        if (*iter == item) {
-           _items_to_install.remove(*iter);
+           _removed_queue_items.remove(*iter);
            found = true;
            break;
        }
     }
     if (!found) {
-       _items_to_remove.push_back (item);
-       _items_to_remove.unique ();
-    }
-}
-
-
-void
-Resolver::addPoolItemsToRemoveFromList (PoolItemList & rl)
-{
-    for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
-       addPoolItemToRemove (*iter);
-    }
-}
-
-void
-Resolver::addPoolItemToLockUninstalled (PoolItem_Ref item)
-{
-    _items_to_lockUninstalled.push_back (item);
-    _items_to_lockUninstalled.unique ();
-}
-
-void
-Resolver::addPoolItemToKepp (PoolItem_Ref item)
-{
-    _items_to_keep.push_back (item);
-    _items_to_keep.unique ();          
-}
-
-void
-Resolver::addPoolItemToEstablish (PoolItem_Ref item)
-{
-    _items_to_establish.push_back (item);
-}
-
-
-void
-Resolver::addPoolItemsToEstablishFromList (PoolItemList & rl)
-{
-    for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
-       addPoolItemToEstablish (*iter);
+       _added_queue_items.push_back (item);
+       _added_queue_items.unique ();
     }
 }
 
-
-void
-Resolver::addPoolItemToVerify (PoolItem_Ref item)
-{
-#if 0
-  /** Order PoolItems based on name and edition only. */
-  struct {
-    /** 'less then' based on name and edition */
-    bool operator()( PoolItem_Ref lhs, PoolItem_Ref rhs ) const
-    {
-      int res = lhs->name().compare( rhs->name() );
-      if ( res )
-        return res == -1; // lhs < rhs ?
-      // here: lhs == rhs, so compare edition:
-      return lhs->edition() < rhs->edition();
-    }
-  } order;
-#endif
-
-    _items_to_verify.push_back (item);
-
-#warning Should order by name (and probably edition since with zypp we could have multiple editions installed in parallel)
-//    _items_to_verify.sort (order);                   //(GCompareFunc) rc_item_compare_name);
-}
-
-
-void
-Resolver::addExtraCapability (const Capability & capability)
-{
-    _extra_caps.insert (capability);
-}
-
-void
-Resolver::removeExtraCapability (const Capability & capability)
-{
-    _extra_caps.erase (capability);
-}
-
-
-
-void
-Resolver::addExtraConflict (const Capability & capability)
-{
-    _extra_conflicts.insert (capability);
-}
-
-
-void
-Resolver::addIgnoreConflict (const PoolItem_Ref item,
-                  const Capability & capability)
-{
-    _ignoreConflicts.insert(make_pair(item, capability));
-}
-
-
-void
-Resolver::addIgnoreRequires (const PoolItem_Ref item,
-                            const Capability & capability)
-{
-    _ignoreRequires.insert(make_pair(item, capability));
-}
-
-void
-Resolver::addIgnoreObsoletes (const PoolItem_Ref item,
-                             const Capability & capability)
-{
-    _ignoreObsoletes.insert(make_pair(item, capability));
-}
-
-void
-Resolver::addIgnoreInstalledItem (const PoolItem_Ref item)
-{
-    _ignoreInstalledItem.push_back (item);
-}
-
-void
-Resolver::addIgnoreArchitectureItem (const PoolItem_Ref item)
-{
-    _ignoreArchitectureItem.push_back (item);
-}
-
-void
-Resolver::addIgnoreVendorItem (const PoolItem_Ref item)
-{
-    _ignoreVendorItem.push_back (item);
-}
+void Resolver::addWeak( const PoolItem & item )
+{ _addWeak.push_back( item ); }
 
 //---------------------------------------------------------------------------
 
@@ -495,7 +232,7 @@ struct UndoTransact : public resfilter::PoolItemFilterFunctor
        :resStatus(status)
     { }
 
-    bool operator()( PoolItem_Ref item )               // only transacts() items go here
+    bool operator()( PoolItem item )           // only transacts() items go here
     {
        item.status().resetTransact( resStatus );// clear any solver/establish transactions
        return true;
@@ -510,7 +247,7 @@ struct DoTransact : public resfilter::PoolItemFilterFunctor
        :resStatus(status)
     { }
 
-    bool operator()( PoolItem_Ref item )               // only transacts() items go here
+    bool operator()( PoolItem item )           // only transacts() items go here
     {
        item.status().setTransact( true, resStatus );
        return true;
@@ -518,950 +255,397 @@ struct DoTransact : public resfilter::PoolItemFilterFunctor
 };
 
 
-struct VerifySystem : public resfilter::PoolItemFilterFunctor
-{
-    Resolver & resolver;
-
-    VerifySystem (Resolver & r)
-       : resolver (r)
-    { }
-
-    bool operator()( PoolItem_Ref provider )
-    {
-       resolver.addPoolItemToVerify (provider);
-       return true;
-    }
-};
-
-bool
-Resolver::verifySystem (bool considerNewHardware)
+bool Resolver::verifySystem()
 {
     UndoTransact resetting (ResStatus::APPL_HIGH);
 
-    _DEBUG ("Resolver::verifySystem() " << (considerNewHardware ? "consider new hardware":""));
-
-    invokeOnEach ( _pool.begin(), _pool.end(),
-                  resfilter::ByTransact( ),                    // Resetting all transcations
-                  functor::functorRef<bool,PoolItem>(resetting) );
-
-    VerifySystem info (*this);
-
-    invokeOnEach( pool().byKindBegin( ResTraits<Package>::kind ),
-                 pool().byKindEnd( ResTraits<Package>::kind ),
-                 resfilter::ByInstalled ( ),
-                 functor::functorRef<bool,PoolItem>(info) );
-
-    invokeOnEach( pool().byKindBegin( ResTraits<Pattern>::kind ),
-                 pool().byKindEnd( ResTraits<Pattern>::kind ),
-                 resfilter::ByInstalled ( ),
-                 functor::functorRef<bool,PoolItem>(info) );
-
+    DBG << "Resolver::verifySystem()" << endl;
 
     _verifying = true;
 
-    bool success = false;
-
-    if (considerNewHardware) {
-       // evaluate all Freshens/Supplements and solve
-       success = freshenPool(false) && bestContext() && bestContext()->isValid();
-    }
-    else {
-       success = resolveDependencies (); // do solve only
-    }
-
-    DoTransact setting (ResStatus::APPL_HIGH);
-
     invokeOnEach ( _pool.begin(), _pool.end(),
-                  resfilter::ByTransact( ),
-                  functor::functorRef<bool,PoolItem>(setting) );
+                  resfilter::ByTransact( ),                    // Resetting all transcations
+                  functor::functorRef<bool,PoolItem>(resetting) );
 
-    return success;
+    return resolvePool();
 }
 
 
-//---------------------------------------------------------------------------
-
-// copy marked item from solution back to pool
-// if data != NULL, set as APPL_LOW (from establishPool())
-
-static void
-solution_to_pool (PoolItem_Ref item, const ResStatus & status, void *data)
+//----------------------------------------------------------------------------
+// undo
+void Resolver::undo()
 {
-    if (triggeredSolution.find(item) != triggeredSolution.end()) {
-        _XDEBUG("solution_to_pool(" << item << ") is already in the pool --> skip");
-        return;
-    }
-
-    triggeredSolution.insert(item);
-
-    // resetting transaction only
-    item.status().resetTransact((data != NULL) ? ResStatus::APPL_LOW : ResStatus::SOLVER );
+    UndoTransact info(ResStatus::APPL_LOW);
+    MIL << "*** undo ***" << endl;
+    invokeOnEach ( _pool.begin(), _pool.end(),
+                  resfilter::ByTransact( ),                    // collect transacts from Pool to resolver queue
+                  functor::functorRef<bool,PoolItem>(info) );
+    //  Regard dependencies of the item weak onl
+    _addWeak.clear();
 
-    bool r;
+    // Additional QueueItems which has to be regarded by the solver
+    _removed_queue_items.clear();
+    _added_queue_items.clear();
 
-    if (status.isToBeInstalled()) {
-       r = item.status().setToBeInstalled( (data != NULL) ? ResStatus::APPL_LOW : ResStatus::SOLVER );
-       _XDEBUG("solution_to_pool(" << item << ", " << status << ") install !" << r);
-    }
-    else if (status.isToBeUninstalledDueToUpgrade()) {
-       r = item.status().setToBeUninstalledDueToUpgrade( (data != NULL) ? ResStatus::APPL_LOW : ResStatus::SOLVER );
-       _XDEBUG("solution_to_pool(" << item << ", " << status << ") upgrade !" << r);
-    }
-    else if (status.isToBeUninstalled()) {
-       r = item.status().setToBeUninstalled( (data != NULL) ? ResStatus::APPL_LOW : ResStatus::SOLVER );
-       _XDEBUG("solution_to_pool(" << item << ", " << status << ") remove !" << r);
-    }
-    else if (status.isIncomplete()
-            || status.isNeeded()) {
-       r = item.status().setIncomplete();
-       _XDEBUG("solution_to_pool(" << item << ", " << status << ") incomplete !" << r);
-    }
-    else if (status.isUnneeded()) {
-       r = item.status().setUnneeded();
-       _XDEBUG("solution_to_pool(" << item << ", " << status << ") unneeded !" << r);
-    }
-    else if (status.isSatisfied()) {
-       r = item.status().setSatisfied();
-       _XDEBUG("solution_to_pool(" << item << ", " << status << ") satisfied !" << r);
-    } else {
-       _XDEBUG("solution_to_pool(" << item << ", " << status << ") unchanged !");
-    }
     return;
 }
 
-
-//---------------------------------------------------------------------------
-// establish state
-
-struct EstablishState
-{
-    Resolver & resolver;
-
-    EstablishState (Resolver & r)
-       : resolver (r)
-    { }
-
-    bool operator()( PoolItem_Ref provider )
-    {
-       resolver.addPoolItemToEstablish (provider);
-       return true;
-    }
-};
-
-
-void
-Resolver::establishState( ResolverContext_Ptr context )
+void Resolver::solverInit()
 {
-    _DEBUG( "Resolver::establishState ()" );
-    typedef list<Resolvable::Kind> KindList;
-    static KindList ordered;
-    if (ordered.empty()) {
-       ordered.push_back (ResTraits<zypp::Atom>::kind);
-       ordered.push_back (ResTraits<zypp::Message>::kind);
-       ordered.push_back (ResTraits<zypp::Script>::kind);
-       ordered.push_back (ResTraits<zypp::Patch>::kind);
-       ordered.push_back (ResTraits<zypp::Pattern>::kind);
-       ordered.push_back (ResTraits<zypp::Product>::kind);
+    // Solving with libsolv
+    static bool poolDumped = false;
+    MIL << "-------------- Calling SAT Solver -------------------" << endl;
+    if ( getenv("ZYPP_FULLLOG") ) {
+       Testcase testcase("/var/log/YaST2/autoTestcase");
+       if (!poolDumped) {
+           testcase.createTestcase (*this, true, false); // dump pool
+           poolDumped = true;
+       } else {
+           testcase.createTestcase (*this, false, false); // write control file only
+       }
     }
 
-    if (context == NULL)
-       context = new ResolverContext(_pool, _architecture);
-
-    context->setEstablishing (true);
-    context->setIgnoreCababilities (_ignoreConflicts,
-                                   _ignoreRequires,
-                                   _ignoreObsoletes,
-                                   _ignoreInstalledItem,
-                                   _ignoreArchitectureItem,
-                                   _ignoreVendorItem);
-    context->setForceResolve( _forceResolve );
-    context->setEstablishContext( _establish_context );
-    context->setPreferHighestVersion ( _preferHighestVersion );
-    context->setUpgradeMode( _upgradeMode );
-
-    for (KindList::const_iterator iter = ordered.begin(); iter != ordered.end(); iter++) {
-       const Resolvable::Kind kind = *iter;
-
-       _XDEBUG( "establishing state for kind " << kind.asString() );
-
-       //world()->foreachResItemByKind (kind, trial_establish_cb, this);
+    _satResolver->setFixsystem                 ( isVerifyingMode() );
+    _satResolver->setIgnorealreadyrecommended  ( ignoreAlreadyRecommended() );
+    _satResolver->setOnlyRequires              ( onlyRequires() );
+    _satResolver->setAllowdowngrade            (false);
+    _satResolver->setAllowarchchange           (false);
+    _satResolver->setAllowvendorchange         ( allowVendorChange() );
+    _satResolver->setAllowuninstall            ( forceResolve() );
+    _satResolver->setUpdatesystem              (false);
+    _satResolver->setNoupdateprovide           (false);
+    _satResolver->setDosplitprovides           (true);
+    _satResolver->setSolveSrcPackages          ( solveSrcPackages() );
+    _satResolver->setCleandepsOnRemove         ( cleandepsOnRemove() );
 
-       EstablishState info (*this);
-
-       invokeOnEach( pool().byKindBegin( kind ),
-                     pool().byKindEnd( kind ),
-                     functor::functorRef<bool,PoolItem>(info) );
-
-       // process the queue
-       resolveDependencies( context );
-       reset( false, true ); //resetValidResults,keepExtras
+    _satResolver->setDistupgrade               (_upgradeMode);
+    if (_upgradeMode) {
+      // may overwrite some settings
+      _satResolver->setDistupgrade_removeunsupported   (false);
     }
 
-    context->setEstablishing (false);
-
-    _best_context = context;
-    _establish_context = context;
-
-    return;
+    // Resetting additional solver information
+    _isInstalledBy.clear();
+    _installs.clear();
+    _satifiedByInstalled.clear();
+    _installedSatisfied.clear();
 }
 
-
-bool
-Resolver::establishPool ()
+bool Resolver::resolvePool()
 {
-    MIL << "Resolver::establishPool()" << endl;
-
-    establishState ();                                         // establish !
-    ResolverContext_Ptr solution = bestContext();
-
-    if (solution) {                                            // copy solution back to pool
-       triggeredSolution.clear();
-       solution->foreachMarked (solution_to_pool, (void *)1);  // as APPL_LOW
-    }
-    else {
-       ERR << "establishState did not return a bestContext" << endl;
-       return false;
-    }
-
-    return true;
+    solverInit();
+    return _satResolver->resolvePool(_extra_requires, _extra_conflicts, _addWeak, _upgradeRepos );
 }
 
-
-//---------------------------------------------------------------------------
-// freshen state
-
-typedef map<string, PoolItem_Ref> FreshenMap;
-
-// add item to itemmap
-//  check for item with same name and only keep
-//  best architecture, best version
-
-static void
-addToFreshen( PoolItem_Ref item, FreshenMap & itemmap )
+bool Resolver::resolveQueue( solver::detail::SolverQueueItemList & queue )
 {
-    FreshenMap::iterator it = itemmap.find( item->name() );
-    if (it != itemmap.end()) {                                 // item with same name found
-       int cmp = it->second->arch().compare( item->arch() );
-       if (cmp < 0) {                                          // new item has better arch
-           it->second = item;
-       }
-       else if (cmp == 0) {                                    // new item has equal arch
-           if (it->second->edition().compare( item->edition() ) < 0) {
-               it->second = item;                              // new item has better edition
+    solverInit();
+
+    // add/remove additional SolverQueueItems
+    for (SolverQueueItemList::const_iterator iter = _removed_queue_items.begin();
+        iter != _removed_queue_items.end(); iter++) {
+       for (SolverQueueItemList::const_iterator iterQueue = queue.begin(); iterQueue != queue.end(); iterQueue++) {
+           if ( (*iterQueue)->cmp(*iter) == 0) {
+               MIL << "remove from queue" << *iter;
+               queue.remove(*iterQueue);
+               break;
            }
        }
     }
-    else {
-       itemmap[item->name()] = item;
-    }
-    return;
-}
-
-
-struct FreshenState
-{
-    FreshenMap itemmap;
 
-    FreshenState()
-    { }
-
-    bool operator()( PoolItem_Ref item)
-    {
-       CapSet freshens( item->dep( Dep::FRESHENS ) );
-       if (!freshens.empty()) {
-           addToFreshen( item, itemmap );
-       }
-       else {                                  // if no freshens, look at supplements
-           // Also regarding supplements e.g. in order to recognize
-           // modalias dependencies. Bug #163140
-           CapSet supplements( item->dep( Dep::SUPPLEMENTS ) );
-           if (!supplements.empty()) {
-               addToFreshen( item, itemmap );
+    for (SolverQueueItemList::const_iterator iter = _added_queue_items.begin();
+        iter != _added_queue_items.end(); iter++) {
+       bool found = false;
+       for (SolverQueueItemList::const_iterator iterQueue = queue.begin(); iterQueue != queue.end(); iterQueue++) {
+           if ( (*iterQueue)->cmp(*iter) == 0) {
+               found = true;
+               break;
            }
        }
-       return true;
-    }
-};
-
-
-void
-Resolver::freshenState( ResolverContext_Ptr context,
-                       bool resetAfterSolve )
-{
-    _DEBUG( "Resolver::freshenState ()" );
-
-    if (context == NULL)
-       context = new ResolverContext( _pool, _architecture );
-
-    context->setEstablishing( true );
-    context->setIgnoreCababilities( _ignoreConflicts,
-                                   _ignoreRequires,
-                                   _ignoreObsoletes,
-                                   _ignoreInstalledItem,
-                                   _ignoreArchitectureItem,
-                                   _ignoreVendorItem);
-    context->setForceResolve( _forceResolve );
-    context->setEstablishContext( _establish_context );
-    context->setPreferHighestVersion( _preferHighestVersion );
-    context->setUpgradeMode( _upgradeMode );
-
-    FreshenState info;
-
-    // collect items to be established
-
-    invokeOnEach( pool().byKindBegin( ResTraits<zypp::Package>::kind ),
-                     pool().byKindEnd( ResTraits<zypp::Package>::kind ),
-                     functor::functorRef<bool,PoolItem>(info) );
-
-    // schedule all collected items for establish
-
-    for (FreshenMap::iterator it = info.itemmap.begin(); it != info.itemmap.end(); ++it) {
-       addPoolItemToEstablish( it->second );
+       if (!found) {
+           MIL << "add to queue" << *iter;
+           queue.push_back(*iter);
+       }
     }
 
-    // process the queue
-    resolveDependencies( context );
+    // The application has to take care to write these solutions back to e.g. selectables in order
+    // give the user a chance for changing these decisions again.
+    _removed_queue_items.clear();
+    _added_queue_items.clear();
 
-    if (resetAfterSolve) {
-       reset( false, true ); //resetValidResults,keepExtras
-       context->setEstablishing( false );
-       _best_context = context;
-    }
-
-    return;
+    return _satResolver->resolveQueue(queue, _addWeak);
 }
 
-
-bool
-Resolver::freshenPool (bool resetAfterSolve)
+sat::Transaction Resolver::getTransaction()
 {
-    MIL << "Resolver::freshenPool()" << endl;
+  // FIXME: That's an ugly way of pushing autoInstalled into the transaction.
+  sat::Transaction ret( sat::Transaction::loadFromPool );
+  ret.autoInstalled( _satResolver->autoInstalled() );
+  return ret;
+}
 
-    freshenState (NULL, resetAfterSolve);      // establish all packages with freshens; (NULL)= no initial context
-    ResolverContext_Ptr solution = bestContext();
 
-    if (solution) {                                            // copy solution back to pool
-       triggeredSolution.clear();
-       solution->foreachMarked (solution_to_pool, (void *)1);  // as APPL_LOW
-    }
-    else {
-       ERR << "freshenState did not return a bestContext" << endl;
-       return false;
-    }
+//----------------------------------------------------------------------------
+// Getting more information about the solve results
 
-    return true;
+ResolverProblemList Resolver::problems() const
+{
+  MIL << "Resolver::problems()" << endl;
+  return _satResolver->problems();
 }
 
-//---------------------------------------------------------------------------
-
-struct FileSystemEstablishItem
+void Resolver::applySolutions( const ProblemSolutionList & solutions )
 {
-    Resolver & resolver;
-    
-    FileSystemEstablishItem (Resolver & r)
-       : resolver (r)
-    { }
-
-    // items with filecaps has to be evaluate again via establish
+  for ( ProblemSolution_Ptr solution : solutions )
+  {
+    if ( ! applySolution( *solution ) )
+      break;
+  }
+}
 
-    bool operator()( const CapAndItem & cai )
+bool Resolver::applySolution( const ProblemSolution & solution )
+{
+  bool ret = true;
+  DBG << "apply solution " << solution << endl;
+  for ( SolutionAction_Ptr action : solution.actions() )
+  {
+    if ( ! action->execute( *this ) )
     {
-       _XDEBUG( "QueueItemInstall::FileSystemEstablishItem (" << cai.item << ", " << cai.cap << ")");
-       resolver.addPoolItemToEstablish (cai.item);
-       return true;
+      WAR << "apply solution action failed: " << action << endl;
+      ret = false;
+      break;
     }
-};
-
+  }
+  return ret;
+}
 
+//----------------------------------------------------------------------------
 
-bool
-Resolver::resolveDependencies (const ResolverContext_Ptr context)
+void Resolver::collectResolverInfo()
 {
+    if ( _satResolver
+        && _isInstalledBy.empty()
+        && _installs.empty()) {
 
-    time_t t_start, t_now;
-
-    MIL << "Resolver::resolveDependencies()" << endl;
-
-    _pending_queues.clear();
-    _pruned_queues.clear();
-    _complete_queues.clear();
-    _deferred_queues.clear();
-    _invalid_queues.clear();
-    _valid_solution_count = 0;
-    _best_context = NULL;
-
-#warning local items disabled
-#if 0
-    bool have_local_items = false;
-
-    /* Walk through are list of to-be-installed packages and see if any of them are local. */
-
-    for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) {
-       if ((*iter)->local()) {
-           have_local_items = true;
-           break;
-       }
-    }
-
-    World_Ptr the_world = world();
-    StoreWorld_Ptr local_world = NULL;
-    MultiWorld_Ptr local_multiworld = NULL;
-
-    Channel_Ptr local_channel = NULL;
-
-    if (have_local_items) {
-       local_multiworld = new MultiWorld();
-       local_world = new StoreWorld();
-
-       local_channel = new Channel ("", "Local ResItems", "@local", "");
-
-       local_world->addChannel (local_channel);
-
-       local_multiworld->addSubworld (local_world);
-       local_multiworld->addSubworld (the_world);
-
-       the_world = local_multiworld;
-    }
-#endif    
-
-    // Checking if we have to make additional establish concerning filesystem capabilities
-    FileSystemEstablishItem establish(*this);
-    Dep dep( Dep::SUPPLEMENTS);
-    invokeOnEach( pool().byCapabilityIndexBegin( "filesystem()", dep ), // begin()
-                         pool().byCapabilityIndexEnd( "filesystem()", dep ),   // end()
-                         functor::functorRef<bool,CapAndItem>( establish ) );
-
-    // create initial_queue
-
-    ResolverQueue_Ptr initial_queue = new ResolverQueue(_pool, _architecture, context);
-
-    // adding "external" provides, the the requirements will be ignored
-    IgnoreMap ignoreRequires = _ignoreRequires;
-    ResPool::AdditionalCapSet additionalCapSet = pool().additionaProvide();
-    for (ResPool::AdditionalCapSet::const_iterator it = additionalCapSet.begin();
-        it != additionalCapSet.end(); it++) {
-       CapSet cset = it->second;
-       for (CapSet::const_iterator cit = cset.begin(); cit != cset.end(); ++cit) {
-           ignoreRequires.insert(make_pair(PoolItem_Ref(), *cit));
-       }
-    }
-
-    // Initialize all ignoring dependencies
-    initial_queue->context()->setIgnoreCababilities (_ignoreConflicts,
-                                                    ignoreRequires,
-                                                    _ignoreObsoletes,
-                                                    _ignoreInstalledItem,
-                                                    _ignoreArchitectureItem,
-                                                    _ignoreVendorItem);
-    initial_queue->context()->setForceResolve( _forceResolve );
-    initial_queue->context()->setEstablishContext( _establish_context );
-    initial_queue->context()->setPreferHighestVersion( _preferHighestVersion );
-    initial_queue->context()->setUpgradeMode( _upgradeMode );
-    initial_queue->context()->setTryAllPossibilities( _tryAllPossibilities );
-
-    /* If this is a verify, we do a "soft resolution" */
-
-    initial_queue->context()->setVerifying( _verifying );
-
-    /* Add extra items. */
-
-    for (QueueItemList::const_iterator iter = _initial_items.begin(); iter != _initial_items.end(); iter++) {
-       initial_queue->addItem (*iter);
-    }
-
-    for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) {
-       PoolItem_Ref r = *iter;
-
-#warning local items disabled
-#if 0
-       /* Add local packages to our dummy channel. */
-       if (r->local()) {
-           assert (local_channel != NULL);
-           ResItem_Ptr r1 = const_pointer_cast<ResItem>(r);
-           r1->setChannel (local_channel);
-           local_world->addPoolItem_Ref (r);
-       }
-#endif
-       initial_queue->addPoolItemToInstall (r);
-    }
-
-    for (PoolItemList::const_iterator iter = _items_to_remove.begin(); iter != _items_to_remove.end(); iter++) {
-       if (!_upgradeMode)
-           initial_queue->addPoolItemToRemove (*iter, true /* remove-only mode */);
-       else
-           //   Checking old dependencies for packages which will be updated.
-           //   E.g. foo provides a dependecy which foo-new does not provides anymore.
-           //   So check, if there is a packages installed which requires foo.
-           //   Testcase exercise-bug150844-test.xml
-           //   Testcase Bug156439-test.xml
-           initial_queue->addPoolItemToRemove (*iter, false /* no remove-only mode */);
-    }
-
-    for (PoolItemList::const_iterator iter = _items_to_verify.begin(); iter != _items_to_verify.end(); iter++) {
-       initial_queue->addPoolItemToVerify (*iter);
-    }
-
-    for (PoolItemList::const_iterator iter = _items_to_establish.begin(); iter != _items_to_establish.end(); iter++) {
-       initial_queue->addPoolItemToEstablish (*iter);
-    }
-
-    for (CapSet::const_iterator iter = _extra_caps.begin(); iter != _extra_caps.end(); iter++) {
-       initial_queue->addExtraCapability (*iter);
-    }
-
-    // adding "external" requires
-    additionalCapSet = pool().additionalRequire();
-    for (ResPool::AdditionalCapSet::const_iterator it = additionalCapSet.begin();
-        it != additionalCapSet.end(); it++) {
-       CapSet cset = it->second;
-       for (CapSet::const_iterator cit = cset.begin(); cit != cset.end(); ++cit) {
-           initial_queue->addExtraCapability (*cit);
-       }
-    }
-
-    for (CapSet::const_iterator iter = _extra_conflicts.begin(); iter != _extra_conflicts.end(); iter++) {
-       initial_queue->addExtraConflict (*iter);
-    }
-
-    // adding "external" conflicts
-    additionalCapSet = pool().additionaConflict();
-    for (ResPool::AdditionalCapSet::const_iterator it = additionalCapSet.begin();
-        it != additionalCapSet.end(); it++) {
-       CapSet cset = it->second;
-       for (CapSet::const_iterator cit = cset.begin(); cit != cset.end(); ++cit) {
-           initial_queue->addExtraConflict (*cit);
-       }
-    }
-
-    // Adding System resolvable
-    assertSystemResObjectInPool();
-
-    _XDEBUG( "Initial Queue: [" << *initial_queue << "]" );
-
-    if (initial_queue->isEmpty()) {
-       INT << "Empty Queue, nothing to resolve" << endl;
-       _best_context = context; // Taking old context
-       return true;
-    }
-
-    _best_context = NULL;
-
-    _pending_queues.push_front (initial_queue);
-
-    time (&t_start);
-
-    while (!_pending_queues.empty()) {
-
-       _DEBUG( "Pend " << (long) _pending_queues.size()
-               << " / Cmpl " << (long) _complete_queues.size()
-               << " / Prun " << (long) _pruned_queues.size()
-               << " / Defr " << (long) _deferred_queues.size()
-               << " / Invl " << (long) _invalid_queues.size() );
-
-       if (_timeout_seconds > 0) {
-           time (&t_now);
-           if (difftime (t_now, t_start) > _timeout_seconds) {
-               _timed_out = true;
-               MIL << "Timeout " << _timeout_seconds << " seconds reached"
-                   << " -> exit" << endl;
-               break;
-           }
-       }
-       if (_maxSolverPasses > 0) {
-           if (_maxSolverPasses <= _complete_queues.size() +
-               _pruned_queues.size() +
-               _deferred_queues.size() +
-               _invalid_queues.size()) {
-               _timed_out = true;
-               MIL << "Max solver runs ( " << _maxSolverPasses
-                   << " ) reached -> exit" << endl;
-               break;
-           }
-       }
-
-       if (_best_context != NULL
-           && _complete_queues.size() >= MAX_VALID_SOLUTIONS) {
-               MIL << "Max VALID solver runs ( " << MAX_VALID_SOLUTIONS
-                   << " ) reached -> exit" << endl;
-               break;
-       }
-
-       ResolverQueue_Ptr queue = _pending_queues.front();
-       _pending_queues.pop_front();
-       ResolverContext_Ptr context = queue->context();
-
-       queue->process();
-
-       if (queue->isInvalid ()) {
-
-           _XDEBUG( "Invalid Queue\n" );
-           _invalid_queues.push_back(queue);
-
-       } else if (queue->isEmpty ()) {
-
-           _XDEBUG( "Empty Queue\n" );
-
-           _complete_queues.push_back(queue);
-
-           ++_valid_solution_count;
-
-           /* Compare this solution to our previous favorite.  In the case of a tie,
-              the first solution wins --- yeah, I know this is lame, but it shouldn't
-              be an issue too much of the time. */
+       // generating new
+       PoolItemList itemsToInstall = _satResolver->resultItemsToInstall();
 
-           if (_best_context == NULL
-               || _best_context->compare (context) < 0)
+       for (PoolItemList::const_iterator instIter = itemsToInstall.begin();
+            instIter != itemsToInstall.end(); instIter++) {
+           // Requires
+           for (Capabilities::const_iterator capIt = (*instIter)->dep (Dep::REQUIRES).begin(); capIt != (*instIter)->dep (Dep::REQUIRES).end(); ++capIt)
            {
-               _best_context = context;
+               sat::WhatProvides possibleProviders(*capIt);
+               for_( iter, possibleProviders.begin(), possibleProviders.end() ) {
+                   PoolItem provider = ResPool::instance().find( *iter );
+
+                   // searching if this provider will already be installed
+                   bool found = false;
+                   bool alreadySetForInstallation = false;
+                   ItemCapKindMap::const_iterator pos = _isInstalledBy.find(provider);
+                   while (pos != _isInstalledBy.end()
+                          && pos->first == provider
+                          && !found) {
+                       alreadySetForInstallation = true;
+                       ItemCapKind capKind = pos->second;
+                       if (capKind.item() == *instIter)  found = true;
+                       pos++;
+                   }
+
+                   if (!found
+                       && provider.status().isToBeInstalled()) {
+                       if (provider.status().isBySolver()) {
+                           ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::REQUIRES, !alreadySetForInstallation );
+                           _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));
+                       } else {
+                           // no initial installation cause it has been set be e.g. user
+                           ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::REQUIRES, false );
+                           _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));
+                       }
+                       ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::REQUIRES, !alreadySetForInstallation );
+                       _installs.insert (make_pair( *instIter, capKindisInstalledBy));
+                   }
+
+                   if (provider.status().staysInstalled()) { // Is already satisfied by an item which is installed
+                       ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::REQUIRES, false );
+                       _satifiedByInstalled.insert (make_pair( *instIter, capKindisInstalledBy));
+
+                       ItemCapKind installedSatisfied( *instIter, *capIt, Dep::REQUIRES, false );
+                       _installedSatisfied.insert (make_pair( provider, installedSatisfied));
+                   }
+               }
            }
 
-       } else if (_best_context != NULL
-                  && _best_context->partialCompare (context) > 0) {
-
-           /* If we aren't currently as good as our previous best complete solution,
-              this solution gets pruned. */
-
-           _XDEBUG( "PRUNED!" );
-
-           _pruned_queues.push_back(queue);
-
-       } else {
-
-           /* If our queue is isn't empty and isn't invalid, that can only mean
-              one thing: we are down to nothing but branches. */
-
-           queue->splitFirstBranch (_pending_queues, _deferred_queues);
-       }
-
-       /* If we have run out of pending queues w/o finding any solutions,
-          and if we have deferred queues, make the first deferred queue
-          pending. */
+           if (!(_satResolver->onlyRequires())) {
+               //Recommends
+               for (Capabilities::const_iterator capIt = (*instIter)->dep (Dep::RECOMMENDS).begin(); capIt != (*instIter)->dep (Dep::RECOMMENDS).end(); ++capIt)
+               {
+                   sat::WhatProvides possibleProviders(*capIt);
+                   for_( iter, possibleProviders.begin(), possibleProviders.end() ) {
+                       PoolItem provider = ResPool::instance().find( *iter );
+
+                       // searching if this provider will already be installed
+                       bool found = false;
+                       bool alreadySetForInstallation = false;
+                       ItemCapKindMap::const_iterator pos = _isInstalledBy.find(provider);
+                       while (pos != _isInstalledBy.end()
+                              && pos->first == provider
+                              && !found) {
+                           alreadySetForInstallation = true;
+                           ItemCapKind capKind = pos->second;
+                           if (capKind.item() == *instIter)  found = true;
+                           pos++;
+                       }
+
+                       if (!found
+                           && provider.status().isToBeInstalled()) {
+                           if (provider.status().isBySolver()) {
+                               ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::RECOMMENDS, !alreadySetForInstallation );
+                               _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));
+                           } else {
+                               // no initial installation cause it has been set be e.g. user
+                               ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::RECOMMENDS, false );
+                               _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));
+                           }
+                           ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::RECOMMENDS, !alreadySetForInstallation );
+                           _installs.insert (make_pair( *instIter, capKindisInstalledBy));
+                       }
+
+                       if (provider.status().staysInstalled()) { // Is already satisfied by an item which is installed
+                           ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::RECOMMENDS, false );
+                           _satifiedByInstalled.insert (make_pair( *instIter, capKindisInstalledBy));
+
+                           ItemCapKind installedSatisfied( *instIter, *capIt, Dep::RECOMMENDS, false );
+                           _installedSatisfied.insert (make_pair( provider, installedSatisfied));
+                       }
+                   }
+               }
 
-       if (_pending_queues.empty()
-           && _complete_queues.empty()
-           && !_deferred_queues.empty()) {
-           _pending_queues.push_back(_deferred_queues.front());
+               //Supplements
+               for (Capabilities::const_iterator capIt = (*instIter)->dep (Dep::SUPPLEMENTS).begin(); capIt != (*instIter)->dep (Dep::SUPPLEMENTS).end(); ++capIt)
+               {
+                   sat::WhatProvides possibleProviders(*capIt);
+                   for_( iter, possibleProviders.begin(), possibleProviders.end() ) {
+                       PoolItem provider = ResPool::instance().find( *iter );
+                       // searching if this item will already be installed
+                       bool found = false;
+                       bool alreadySetForInstallation = false;
+                       ItemCapKindMap::const_iterator pos = _isInstalledBy.find(*instIter);
+                       while (pos != _isInstalledBy.end()
+                              && pos->first == *instIter
+                              && !found) {
+                           alreadySetForInstallation = true;
+                           ItemCapKind capKind = pos->second;
+                           if (capKind.item() == provider)  found = true;
+                           pos++;
+                       }
+
+                       if (!found
+                           && instIter->status().isToBeInstalled()) {
+                           if (instIter->status().isBySolver()) {
+                               ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::SUPPLEMENTS, !alreadySetForInstallation );
+                               _isInstalledBy.insert (make_pair( *instIter, capKindisInstalledBy));
+                           } else {
+                               // no initial installation cause it has been set be e.g. user
+                               ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::SUPPLEMENTS, false );
+                               _isInstalledBy.insert (make_pair( *instIter, capKindisInstalledBy));
+                           }
+                           ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::SUPPLEMENTS, !alreadySetForInstallation );
+                           _installs.insert (make_pair( provider, capKindisInstalledBy));
+                       }
+
+                       if (instIter->status().staysInstalled()) { // Is already satisfied by an item which is installed
+                           ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::SUPPLEMENTS, !alreadySetForInstallation );
+                           _satifiedByInstalled.insert (make_pair( provider, capKindisInstalledBy));
+
+                           ItemCapKind installedSatisfied( provider, *capIt, Dep::SUPPLEMENTS, false );
+                           _installedSatisfied.insert (make_pair( *instIter, installedSatisfied));
+                       }
+                   }
+               }
+           }
        }
     }
-    _DEBUG("Pend " << (long) _pending_queues.size()
-          << " / Cmpl " << (long) _complete_queues.size()
-          << " / Prun " << (long) _pruned_queues.size()
-          << " / Defr " << (long) _deferred_queues.size()
-          << " / Invl " << (long) _invalid_queues.size() );
-
-    return _best_context && _best_context->isValid();
 }
 
 
-//----------------------------------------------------------------------------
-// undo
-
-void
-Resolver::undo(void)
+ItemCapKindList Resolver::isInstalledBy( const PoolItem & item )
 {
-    UndoTransact info(ResStatus::APPL_LOW);
-    MIL << "*** undo ***" << endl;
-    invokeOnEach ( _pool.begin(), _pool.end(),
-                  resfilter::ByTransact( ),                    // collect transacts from Pool to resolver queue
-                  functor::functorRef<bool,PoolItem>(info) );
-    // These conflict should be ignored of the concering item
-    _ignoreConflicts.clear();
-    // These requires should be ignored of the concering item
-    _ignoreRequires.clear();
-    // These obsoletes should be ignored of the concering item
-    _ignoreObsoletes.clear();
-    // Ignore architecture of the item
-    _ignoreArchitecture.clear();
-    // Ignore the status "installed" of the item
-    _ignoreInstalledItem.clear();
-    // Ignore the architecture of the item
-    _ignoreArchitectureItem.clear();
-    // Ignore the vendor of the item
-    _ignoreVendorItem.clear();
-
-
-    return;
-}
-
-//----------------------------------------------------------------------------
-// resolvePool
-
-struct CollectTransact : public resfilter::PoolItemFilterFunctor
-{
-    Resolver & resolver;
-
-    CollectTransact (Resolver & r)
-       : resolver (r)
-    { }
-
-    bool operator()( PoolItem_Ref item )               // only transacts() items go here
-    {
-       ResStatus status = item.status();
-       _XDEBUG( "CollectTransact(" << item << ")" );
-       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!
-       }
-       if (status.isToBeUninstalled()) {
-           resolver.addPoolItemToRemove(item);         // -> remove !
-       }
-       if (status.isIncomplete()) {                    // incomplete (re-install needed)
-           PoolItem_Ref reinstall = Helper::findReinstallItem (resolver.pool(), item);
-           if (reinstall) {
-               MIL << "Reinstall " << reinstall << " for incomplete " << item << endl;
-               resolver.addPoolItemToInstall(reinstall);       // -> install!
-           }
-           else {
-               WAR << "Can't find " << item << " for re-installation" << endl;
-           }
-       }
-
-        if (status.isLocked()
-            && status.isUninstalled()) {
-            // This item could be selected by solver in a former run. Now it
-            // is locked. So we will have to evaluate a new solver run.
-            resolver.addPoolItemToLockUninstalled (item);
-        }
-
-        if (status.isKept()
-            && !by_solver) {
-           // collecting all keep states
-           resolver.addPoolItemToKepp (item);
-       }
-
-       return true;
-    }
-};
-
+    ItemCapKindList ret;
+    collectResolverInfo();
 
-static void
-show_pool( ResPool pool )
-{
-    int count = 1;
-    static bool full_pool_shown = true;
-
-    _XDEBUG( "---------------------------------------" );
-    for (ResPool::const_iterator it = pool.begin(); it != pool.end(); ++it, ++count) {
-
-       if (!full_pool_shown                                    // show item if not shown all before
-           || it->status().transacts()                         // or transacts
-           || it->status().isKept()
-           || it->status().isLocked()
-           || !it->status().isUndetermined())                  // or established status
-       {
-           _XDEBUG( count << ": " << *it );
+    for (ItemCapKindMap::const_iterator iter = _isInstalledBy.find(item); iter != _isInstalledBy.end();) {
+       ItemCapKind info = iter->second;
+       PoolItem iterItem = iter->first;
+       if (iterItem == item) {
+           ret.push_back(info);
+           iter++;
+       } else {
+           // exit
+           iter = _isInstalledBy.end();
        }
     }
-    _XDEBUG( "---------------------------------------" );
-    full_pool_shown = true;
+    return ret;
 }
 
-//  This function loops over the pool and grabs
-//  all item.status().transacts() and item.status().byUser()
-//  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()
-//
-//  Then zypp::solver:detail::Resolver.resolveDependencies() is called.
-//
-//  zypp::solver:detail::Resolver then returns a ResolverContext via bestContext() which
-//  describes the best solution. If bestContext() is NULL, no solution was found.
-//
-//  ResolverContext has a foreachMarked() iterator function which loops over all
-//  items of the solutions. These must be written back to the pool.
-
-
-bool
-Resolver::resolvePool( bool tryAllPossibilities )
+ItemCapKindList Resolver::installs( const PoolItem & item )
 {
+    ItemCapKindList ret;
+    collectResolverInfo();
 
-    // Solving with the satsolver
-    if ( getenv("ZYPP_SAT_SOLVER") ) {
-       MIL << "-------------- Calling SAT Solver -------------------" << endl; 
-       // syncing with sat pool
-       sat::Pool satPool( sat::Pool::instance() );
-       _pool.satSync();
-       
-       SATResolver satResolver(_pool, satPool.get());
-       return satResolver.resolvePool();
-    }
-    
-    ResolverContext_Ptr saveContext = _best_context;
-    CollectTransact info (*this);
-
-    // cleanup before next run
-    if ( _poolchanged.remember( _pool.serial() ) )
-    {
-       MIL << "pool has been CHANGED --> resetting solverresults" << endl;
-       reset( true, true ); //resetValidResults,keepExtras     
-    } else {
-       reset( false, true ); //resetValidResults,keepExtras
-    }
-    
-    bool saveTryAllPossibilities = _tryAllPossibilities;
-
-    if (tryAllPossibilities) {
-       _tryAllPossibilities = tryAllPossibilities;
-    }
-
-    if (_tryAllPossibilities) {
-       MIL << "================================================================"
-           << endl;
-       MIL << "Solver run with ALL possibilities"
-           << endl;
-       if (_maxSolverPasses <= 0)
-           _maxSolverPasses = MAX_SECOND_RUNS;
-       if (_timeout_seconds <= 0)
-           _timeout_seconds = TIMOUT_SECOND_RUN;
-
-       MIL << "But no longer than " << MAX_SECOND_RUNS << " runs or "
-           << TIMOUT_SECOND_RUN << " seconds" << endl;
-       MIL << "================================================================" << endl;
-    }
-
-#if 1
-
-    MIL << "Resolver::resolvePool()" << endl;
-    _XDEBUG( "Pool before resolve" );
-    show_pool( _pool );
-
-#endif
-    invokeOnEach ( _pool.begin(), _pool.end(),
-                  resfilter::ByTransact( ),                    // collect transacts from Pool to resolver queue
-                  functor::functorRef<bool,PoolItem>(info) );
-
-    invokeOnEach ( _pool.begin(), _pool.end(),
-                   resfilter::ByLock( ),                        // collect locks from Pool to resolver queue
-                   functor::functorRef<bool,PoolItem>(info) );
-
-    invokeOnEach ( _pool.begin(), _pool.end(),
-                   resfilter::ByKeep( ),                        // collect keeps from Pool to resolver queue
-                   functor::functorRef<bool,PoolItem>(info) );    
-    
-    // List of installing/removing items of the complete run (not regarding a recycled solver run)
-    PoolItemList _completeItems_to_install = _items_to_install;
-    PoolItemList _completeItems_to_remove = _items_to_remove;
-    PoolItemList _completeItems_to_lockUninstalled = _items_to_lockUninstalled;
-    PoolItemList _completeItems_to_keep = _items_to_keep;
-
-    // We have to find a valid context in order to recycle it.
-    saveContext = contextPool.findContext (_items_to_install, _items_to_remove, _items_to_lockUninstalled, _items_to_keep);
-    // _items_to_install, _items_to_remove contains addition items which has been selected but are
-    // not solved with that context. They will be solved now.
-    // If we have not found any former fitting context, saveContext is NULL. So the solver
-    // make a complete run
-
-    if (saveContext != NULL) {
-        // create a new context in order not overwriting the old
-        saveContext = new ResolverContext (saveContext->pool(), saveContext->architecture(), saveContext);
-       saveContext->setTryAllPossibilities( true );
-    }
-
-    bool have_solution = resolveDependencies (saveContext);             // resolve !
-
-    if (have_solution) {                                       // copy solution back to pool
-       MIL << "Have solution, copying back to pool" << endl;
-       ResolverContext_Ptr solution = bestContext();
-       triggeredSolution.clear();
-       solution->foreachMarked (solution_to_pool, NULL);
-#if 1
-       _XDEBUG( "Pool after resolve" );
-       show_pool( _pool );
-#endif
-        // insert best_context in ContextPool for further solver runs
-        contextPool.addContext( solution,_completeItems_to_install, _completeItems_to_remove,
-                               _completeItems_to_lockUninstalled,
-                               _completeItems_to_keep);
-
-    }
-    else {
-       MIL << "!!! Have NO solution !!!" << endl;      
-#if 0 // It takes too much memory for logging. Do not use it !
-       MIL << "!!! Have NO solution !!! Additional solver information:" << endl;
-       int counter = 0;
-       for (ResolverQueueList::iterator iter = _invalid_queues.begin();
-            iter != _invalid_queues.end(); iter++) {
-           counter++;
-           MIL << "-----------------------------------------------------------------" << endl;
-           MIL << counter++ << ". failed queue:" << endl;
-           ResolverQueue_Ptr invalid = *iter;
-           invalid->context()->spewInfo (); No additional information needed here
-           MIL << *invalid->context() << endl;
-           MIL << "-----------------------------------------------------------------" << endl;
+    for (ItemCapKindMap::const_iterator iter = _installs.find(item); iter != _installs.end();) {
+       ItemCapKind info = iter->second;
+       PoolItem iterItem = iter->first;
+       if (iterItem == item) {
+           ret.push_back(info);
+           iter++;
+       } else {
+           // exit
+           iter = _installs.end();
        }
-#endif
-    }
-
-    if (tryAllPossibilities) {
-       _tryAllPossibilities = saveTryAllPossibilities; // reset to old value
     }
-
-    return have_solution;
-}
-
-
-static void
-get_info_foreach_cb (ResolverInfo_Ptr info, void *data)
-{
-    list<string> *stringList = (list<string> *)data;
-    stringList->push_back (info->message());
-}
-
-
-// returns a string list of ResolverInfo of the LAST not valid solution
-std::list<std::string> Resolver::problemDescription( void ) const
-{
-    list<string> retList;
-    if (_invalid_queues.empty()) return retList;
-    ResolverQueue_Ptr invalid = _invalid_queues.front();
-    invalid->context()->foreachInfo (PoolItem_Ref(), -1, get_info_foreach_cb, (void *)&retList);;
-    return retList;
+    return ret;
 }
 
-
-//
-// transact a single object
-// -> do a 'single step' resolving either installing or removing
-//    required and recommended PoolItems
-
-bool
-Resolver::transactResObject( ResObject::constPtr robj, bool install,
-                            bool recursive)
+ItemCapKindList Resolver::satifiedByInstalled( const PoolItem & item )
 {
-    MIL << "transactResObject()" << endl;
-    MIL << "is obsolete; use resolvePool() instead" << endl;
+    ItemCapKindList ret;
+    collectResolverInfo();
 
-    return true;
+    for (ItemCapKindMap::const_iterator iter = _satifiedByInstalled.find(item); iter != _satifiedByInstalled.end();) {
+       ItemCapKind info = iter->second;
+       PoolItem iterItem = iter->first;
+       if (iterItem == item) {
+           ret.push_back(info);
+           iter++;
+       } else {
+           // exit
+           iter = _satifiedByInstalled.end();
+       }
+    }
+    return ret;
 }
 
-
-bool
-Resolver::transactResKind( Resolvable::Kind kind )
+ItemCapKindList Resolver::installedSatisfied( const PoolItem & item )
 {
-    MIL << "transactResKind(" << kind << ")" << endl;
-    MIL << "is obsolete; use resolvePool() instead" << endl;
+    ItemCapKindList ret;
+    collectResolverInfo();
 
-    return true;
+    for (ItemCapKindMap::const_iterator iter = _installedSatisfied.find(item); iter != _installedSatisfied.end();) {
+       ItemCapKind info = iter->second;
+       PoolItem iterItem = iter->first;
+       if (iterItem == item) {
+           ret.push_back(info);
+           iter++;
+       } else {
+           // exit
+           iter = _installedSatisfied.end();
+       }
+    }
+    return ret;
 }
 
 
-void
-Resolver::transactReset( ResStatus::TransactByValue causer )
-{
-    MIL << "transactReset(" << causer << ")" << endl;
-    MIL << "is obsolete; use resolvePool() instead" << endl;
-
-    return;
-}
-
 ///////////////////////////////////////////////////////////////////
     };// namespace detail
     /////////////////////////////////////////////////////////////////////