Imported Upstream version 14.45.0
[platform/upstream/libzypp.git] / zypp / solver / detail / Resolver.cc
index 3e063e4..8fd3f31 100644 (file)
 #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/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/sat/Pool.h"
 #include "zypp/sat/Solvable.h"
-#include "zypp/sat/SATResolver.h"
+#include "zypp/sat/Transaction.h"
+#include "zypp/ResolverProblem.h"
 
 #define MAXSOLVERRUNS 5
 
@@ -56,10 +58,21 @@ IMPL_PTR_TYPE(Resolver);
 //---------------------------------------------------------------------------
 
 
-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/>";
 }
 
 
@@ -69,9 +82,15 @@ Resolver::Resolver (const ResPool & pool)
     : _pool(pool)
     , _satResolver(NULL)
     , _poolchanged(_pool.serial() )
-    , _forceResolve(false)
-    , _upgradeMode(false)
-    , _verifying(false)
+    , _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() );
@@ -81,90 +100,125 @@ Resolver::Resolver (const ResPool & pool)
 
 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,    true )
+ZOLV_FLAG_TRIBOOL( dupSetAllowNameChange,      dupAllowNameChange,     _dup_allownamechange,   true )
+ZOLV_FLAG_TRIBOOL( dupSetAllowArchChange,      dupAllowArchChange,     _dup_allowarchchange,   true )
+ZOLV_FLAG_TRIBOOL( dupSetAllowVendorChange,    dupAllowVendorChange,   _dup_allowvendorchange, true )
+
+#undef ZOLV_FLAG_TRIBOOL
+//---------------------------------------------------------------------------
+
+void Resolver::setAllowVendorChange( TriBool state_r )
+{
+  _allowVendorChange = indeterminate(state_r) ? ZConfig::instance().solver_allowVendorChange() : bool(state_r);
+}
+
+void Resolver::setOnlyRequires( TriBool state_r )
+{
+  _onlyRequires = indeterminate(state_r) ? ZConfig::instance().solver_onlyRequires() : bool(state_r);
+}
 
-ResPool
-Resolver::pool (void) const
+void Resolver::setCleandepsOnRemove( TriBool state_r )
 {
-    return _pool;
+  _cleandepsOnRemove = indeterminate(state_r) ? ZConfig::instance().solver_cleandepsOnRemove() : bool(state_r);
 }
 
-void
-Resolver::reset (bool keepExtras )
+//---------------------------------------------------------------------------
+
+ResPool Resolver::pool() const
+{ return _pool; }
+
+void Resolver::reset( bool keepExtras )
 {
-    _verifying = false;    
+    _verifying = false;
 
     if (!keepExtras) {
       _extra_requires.clear();
       _extra_conflicts.clear();
     }
-}
 
-void
-Resolver::addExtraRequire (const Capability & capability)
-{
-    _extra_requires.insert (capability);
+    _isInstalledBy.clear();
+    _installs.clear();
+    _satifiedByInstalled.clear();
+    _installedSatisfied.clear();
 }
 
-void
-Resolver::removeExtraRequire (const Capability & capability)
+bool Resolver::doUpgrade()
 {
-    _extra_requires.erase (capability);
+  // Setting Resolver to upgrade mode. SAT solver will do the update
+  _upgradeMode = true;
+  return resolvePool();
 }
 
-void
-Resolver::addExtraConflict (const Capability & capability)
+void Resolver::doUpdate()
 {
-    _extra_conflicts.insert (capability);
+    _updateMode = true;
+    return _satResolver->doUpdate();
 }
 
-void
-Resolver::removeExtraConflict (const Capability & capability)
-{
-    _extra_conflicts.erase (capability);
-}
+PoolItemList Resolver::problematicUpdateItems() const
+{ return _satResolver->problematicUpdateItems(); }
 
-void
-Resolver::addIgnoreConflict (const PoolItem item,
-                  const Capability & capability)
-{
-    _ignoreConflicts.insert(make_pair(item, capability));
-}
+void Resolver::addExtraRequire( const Capability & capability )
+{ _extra_requires.insert (capability); }
 
-void
-Resolver::addIgnoreRequires (const PoolItem item,
-                            const Capability & capability)
-{
-    _ignoreRequires.insert(make_pair(item, capability));
-}
+void Resolver::removeExtraRequire( const Capability & capability )
+{ _extra_requires.erase (capability); }
 
-void
-Resolver::addIgnoreObsoletes (const PoolItem item,
-                             const Capability & capability)
-{
-    _ignoreObsoletes.insert(make_pair(item, capability));
-}
+void Resolver::addExtraConflict( const Capability & capability )
+{ _extra_conflicts.insert (capability); }
 
-void
-Resolver::addIgnoreInstalledItem (const PoolItem item)
-{
-    _ignoreInstalledItem.push_back (item);
-}
+void Resolver::removeExtraConflict( const Capability & capability )
+{ _extra_conflicts.erase (capability); }
 
-void
-Resolver::addIgnoreArchitectureItem (const PoolItem item)
+void Resolver::removeQueueItem( SolverQueueItem_Ptr item )
 {
-    _ignoreArchitectureItem.push_back (item);
+    bool found = false;
+    for (SolverQueueItemList::const_iterator iter = _added_queue_items.begin();
+        iter != _added_queue_items.end(); iter++) {
+       if (*iter == item) {
+           _added_queue_items.remove(*iter);
+           found = true;
+           break;
+       }
+    }
+    if (!found) {
+       _removed_queue_items.push_back (item);
+       _removed_queue_items.unique ();
+    }
 }
 
-void
-Resolver::addIgnoreVendorItem (const PoolItem item)
+void Resolver::addQueueItem( SolverQueueItem_Ptr item )
 {
-    _ignoreVendorItem.push_back (item);
+    bool found = false;
+    for (SolverQueueItemList::const_iterator iter = _removed_queue_items.begin();
+        iter != _removed_queue_items.end(); iter++) {
+       if (*iter == item) {
+           _removed_queue_items.remove(*iter);
+           found = true;
+           break;
+       }
+    }
+    if (!found) {
+       _added_queue_items.push_back (item);
+       _added_queue_items.unique ();
+    }
 }
 
+void Resolver::addWeak( const PoolItem & item )
+{ _addWeak.push_back( item ); }
+
 //---------------------------------------------------------------------------
 
 struct UndoTransact : public resfilter::PoolItemFilterFunctor
@@ -197,14 +251,13 @@ struct DoTransact : public resfilter::PoolItemFilterFunctor
 };
 
 
-bool
-Resolver::verifySystem ()
+bool Resolver::verifySystem()
 {
     UndoTransact resetting (ResStatus::APPL_HIGH);
 
     _DEBUG ("Resolver::verifySystem() ");
-    
-    _verifying = true;    
+
+    _verifying = true;
 
     invokeOnEach ( _pool.begin(), _pool.end(),
                   resfilter::ByTransact( ),                    // Resetting all transcations
@@ -216,159 +269,359 @@ Resolver::verifySystem ()
 
 //----------------------------------------------------------------------------
 // undo
-
-void
-Resolver::undo(void)
+void Resolver::undo()
 {
     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();
+    //  Regard dependencies of the item weak onl
+    _addWeak.clear();
 
+    // Additional QueueItems which has to be regarded by the solver
+    _removed_queue_items.clear();
+    _added_queue_items.clear();
 
     return;
 }
 
+void Resolver::solverInit()
+{
+    // 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
+       }
+    }
 
-bool
-Resolver::resolvePool()
+    _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() );
+
+    _satResolver->setDistupgrade               (_upgradeMode);
+    if (_upgradeMode) {
+      // may overwrite some settings
+      _satResolver->setDistupgrade_removeunsupported   (false);
+    }
+
+    // Resetting additional solver information
+    _isInstalledBy.clear();
+    _installs.clear();
+    _satifiedByInstalled.clear();
+    _installedSatisfied.clear();
+}
+
+bool Resolver::resolvePool()
 {
+    solverInit();
+    return _satResolver->resolvePool(_extra_requires, _extra_conflicts, _addWeak, _upgradeRepos );
+}
 
-    // Solving with the satsolver
-        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
+bool Resolver::resolveQueue( solver::detail::SolverQueueItemList & queue )
+{
+    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;
            }
        }
-#if 0
-       MIL << "------SAT-Pool------" << endl;
-       for (sat::Pool::SolvableIterator i = satPool.solvablesBegin();
-            i != satPool.solvablesEnd(); i++ ) {
-           MIL << *i << " ID: " << i->id() << endl;
+    }
+
+    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;
+           }
        }
-       MIL << "------SAT-Pool end------" << endl;
-#endif
-       _satResolver->setFixsystem(false);
-       _satResolver->setAllowdowngrade(false);
-       _satResolver->setAllowarchchange(false);
-       _satResolver->setAllowvendorchange(false);
-       _satResolver->setAllowuninstall(false);
-       _satResolver->setUpdatesystem(false);
-       _satResolver->setAllowvirtualconflicts(false);
-       _satResolver->setNoupdateprovide(true);
-       _satResolver->setDosplitprovides(false);
-       
-       if (_upgradeMode) {
-           _satResolver->setAllowdowngrade(true);
-           _satResolver->setAllowarchchange(true);
-           _satResolver->setUpdatesystem(true);
-           _satResolver->setDosplitprovides(true);   
+       if (!found) {
+           MIL << "add to queue" << *iter;
+           queue.push_back(*iter);
        }
+    }
+
+    // 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 (_forceResolve)
-           _satResolver->setAllowuninstall(true);
+    return _satResolver->resolveQueue(queue, _addWeak);
+}
 
-       if (_verifying)
-           _satResolver->setFixsystem(true);
-       
-       return _satResolver->resolvePool(_extra_requires, _extra_conflicts);
+sat::Transaction Resolver::getTransaction()
+{
+  // FIXME: That's an ugly way of pushing autoInstalled into the transaction.
+  sat::Transaction ret( sat::Transaction::loadFromPool );
+  ret.autoInstalled( _satResolver->autoInstalled() );
+  return ret;
 }
 
 
-///////////////////////////////////////////////////////////////////
-//
-//
-//     METHOD NAME : Resolver::checkUnmaintainedItems
-//     METHOD TYPE : 
-//
-//     DESCRIPTION : Unmaintained packages which does not fit to 
-//                    the updated system (broken dependencies) will be
-//                    deleted.
-//
-void Resolver::checkUnmaintainedItems () {
-    int solverRuns = 1;
-    MIL << "Checking unmaintained items....." << endl;
-
-    while (!resolvePool() && solverRuns++ < MAXSOLVERRUNS) {
-       ResolverProblemList problemList = problems();
-       ProblemSolutionList solutionList;
-       PoolItemList problemItemList;   
-
-       for (ResolverProblemList::iterator iter = problemList.begin(); iter != problemList.end(); ++iter) {
-           ResolverProblem problem = **iter;
-           DBG << "Problem:" << endl;
-           DBG << problem.description() << endl;
-           DBG << problem.details() << endl;
-
-           ProblemSolutionList solutions = problem.solutions();
-           for (ProblemSolutionList::const_iterator iterSolution = solutions.begin();
-                iterSolution != solutions.end(); ++iter) {
-               ProblemSolution_Ptr solution = *iterSolution;
-               DBG << "   Solution:" << endl;
-               DBG << "      " << solution->description() << endl;
-               DBG << "      " << solution->details() << endl;         
-               solver::detail::CSolutionActionList actionList = solution->actions();
-               bool fitUnmaintained = false;
-               PoolItemList deletedItems;
-               for (CSolutionActionList::const_iterator iterActions = actionList.begin();
-                    iterActions != actionList.end(); ++iterActions) {
-                   TransactionSolutionAction_constPtr transactionAction = dynamic_pointer_cast<const TransactionSolutionAction>(*iterActions);
-                   if (transactionAction &&
-                       transactionAction->action() == REMOVE
-                       && _unmaintained_items.find(transactionAction->item()) != _unmaintained_items.end()) {
-                       // The solution contains unmaintained items ONLY which will be deleted. So take this solution
-                       fitUnmaintained = true;
-                       deletedItems.push_back (transactionAction->item());
-                   } else {
-                       fitUnmaintained = false;
+//----------------------------------------------------------------------------
+// Getting more information about the solve results
+
+ResolverProblemList Resolver::problems() const
+{
+  MIL << "Resolver::problems()" << endl;
+  return _satResolver->problems();
+}
+
+void Resolver::applySolutions( const ProblemSolutionList & solutions )
+{
+  for_( iter, solutions.begin(), solutions.end() )
+  {
+    ProblemSolution_Ptr solution = *iter;
+    if ( !solution->apply( *this ) )
+      break;
+  }
+}
+
+void Resolver::collectResolverInfo()
+{
+    if ( _satResolver
+        && _isInstalledBy.empty()
+        && _installs.empty()) {
+
+       // generating new
+       PoolItemList itemsToInstall = _satResolver->resultItemsToInstall();
+
+       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)
+           {
+               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));
                    }
-               }
-               if (fitUnmaintained) {
-                   MIL << "Problem:" << endl;
-                   MIL << problem.description() << endl;
-                   MIL << problem.details() << endl;
-                   MIL << "Will be solved by removing unmaintained package(s)............" << endl;
-                   MIL << "   Solution:" << endl;
-                   MIL << "      " << solution->description() << endl;
-                   MIL << "      " << solution->details() << endl;                                 
-                   solutionList.push_back (solution);
-                   problemItemList.insert (problemItemList.end(), deletedItems.begin(), deletedItems.end() );
-                   break; // not regarding the other solutions
                }
            }
+
+           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));
+                       }
+                   }
+               }
+
+               //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));
+                       }
+                   }
+               }
+           }
+       }
+    }
+}
+
+
+ItemCapKindList Resolver::isInstalledBy( const PoolItem & item )
+{
+    ItemCapKindList ret;
+    collectResolverInfo();
+
+    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();
        }
+    }
+    return ret;
+}
 
-       if (!solutionList.empty()) {
-           applySolutions (solutionList);
-           // list of problematic items after doUpgrade() which is show to the user
-           _problem_items.insert (_problem_items.end(), problemItemList.begin(), problemItemList.end());
-           _problem_items.unique();
+ItemCapKindList Resolver::installs( const PoolItem & item )
+{
+    ItemCapKindList ret;
+    collectResolverInfo();
+
+    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();
+       }
+    }
+    return ret;
+}
+
+ItemCapKindList Resolver::satifiedByInstalled( const PoolItem & item )
+{
+    ItemCapKindList ret;
+    collectResolverInfo();
+
+    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;
+}
+
+ItemCapKindList Resolver::installedSatisfied( const PoolItem & item )
+{
+    ItemCapKindList ret;
+    collectResolverInfo();
+
+    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 {
-           // break cause there is no other solution available by the next run
-           solverRuns = MAXSOLVERRUNS;
+           // exit
+           iter = _installedSatisfied.end();
        }
     }
+    return ret;
 }