1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
4 * Copyright (C) 2000-2002 Ximian, Inc.
5 * Copyright (C) 2005 SUSE Linux Products GmbH
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 #include <boost/static_assert.hpp>
23 #include "zypp/solver/detail/Resolver.h"
24 #include "zypp/solver/detail/Helper.h"
25 #include "zypp/solver/detail/Testcase.h"
26 #include "zypp/solver/detail/SATResolver.h"
28 #include "zypp/Capabilities.h"
29 #include "zypp/ZConfig.h"
30 #include "zypp/base/Logger.h"
31 #include "zypp/base/String.h"
32 #include "zypp/base/Gettext.h"
33 #include "zypp/base/Algorithm.h"
34 #include "zypp/ResPool.h"
35 #include "zypp/ResFilters.h"
36 #include "zypp/sat/Pool.h"
37 #include "zypp/sat/Solvable.h"
39 #define MAXSOLVERRUNS 5
41 /////////////////////////////////////////////////////////////////////////
43 { ///////////////////////////////////////////////////////////////////////
44 ///////////////////////////////////////////////////////////////////////
46 { /////////////////////////////////////////////////////////////////////
47 /////////////////////////////////////////////////////////////////////
49 { ///////////////////////////////////////////////////////////////////
53 IMPL_PTR_TYPE(Resolver);
56 //---------------------------------------------------------------------------
60 Resolver::dumpOn( std::ostream & os ) const
62 return os << "<resolver/>";
66 //---------------------------------------------------------------------------
68 Resolver::Resolver (const ResPool & pool)
71 , _poolchanged(_pool.serial() )
73 , _forceResolve(false)
77 , _onlyRequires(indeterminate)
78 , _solveSrcPackages( false )
79 , _ignorealreadyrecommended(false)
82 sat::Pool satPool( sat::Pool::instance() );
83 _satResolver = new SATResolver(_pool, satPool.get());
92 //---------------------------------------------------------------------------
95 Resolver::pool (void) const
101 Resolver::reset (bool keepExtras )
106 _extra_requires.clear();
107 _extra_conflicts.clear();
110 _isInstalledBy.clear();
112 _satifiedByInstalled.clear();
113 _installedSatisfied.clear();
120 return _satResolver->doUpdate();
123 PoolItemList Resolver::problematicUpdateItems() const
124 { return _satResolver->problematicUpdateItems(); }
127 Resolver::addExtraRequire (const Capability & capability)
129 _extra_requires.insert (capability);
133 Resolver::removeExtraRequire (const Capability & capability)
135 _extra_requires.erase (capability);
139 Resolver::addExtraConflict (const Capability & capability)
141 _extra_conflicts.insert (capability);
145 Resolver::removeExtraConflict (const Capability & capability)
147 _extra_conflicts.erase (capability);
150 void Resolver::removeQueueItem (const SolverQueueItem_Ptr item)
153 for (SolverQueueItemList::const_iterator iter = _added_queue_items.begin();
154 iter != _added_queue_items.end(); iter++) {
156 _added_queue_items.remove(*iter);
162 _removed_queue_items.push_back (item);
163 _removed_queue_items.unique ();
166 void Resolver::addQueueItem (const SolverQueueItem_Ptr item)
169 for (SolverQueueItemList::const_iterator iter = _removed_queue_items.begin();
170 iter != _removed_queue_items.end(); iter++) {
172 _removed_queue_items.remove(*iter);
178 _added_queue_items.push_back (item);
179 _added_queue_items.unique ();
184 Resolver::addWeak (const PoolItem item)
186 _addWeak.push_back (item);
189 //---------------------------------------------------------------------------
191 struct UndoTransact : public resfilter::PoolItemFilterFunctor
193 ResStatus::TransactByValue resStatus;
194 UndoTransact ( const ResStatus::TransactByValue &status)
198 bool operator()( PoolItem item ) // only transacts() items go here
200 item.status().resetTransact( resStatus );// clear any solver/establish transactions
206 struct DoTransact : public resfilter::PoolItemFilterFunctor
208 ResStatus::TransactByValue resStatus;
209 DoTransact ( const ResStatus::TransactByValue &status)
213 bool operator()( PoolItem item ) // only transacts() items go here
215 item.status().setTransact( true, resStatus );
222 Resolver::verifySystem ()
224 UndoTransact resetting (ResStatus::APPL_HIGH);
226 _DEBUG ("Resolver::verifySystem() ");
230 invokeOnEach ( _pool.begin(), _pool.end(),
231 resfilter::ByTransact( ), // Resetting all transcations
232 functor::functorRef<bool,PoolItem>(resetting) );
234 return resolvePool();
238 //----------------------------------------------------------------------------
244 UndoTransact info(ResStatus::APPL_LOW);
245 MIL << "*** undo ***" << endl;
246 invokeOnEach ( _pool.begin(), _pool.end(),
247 resfilter::ByTransact( ), // collect transacts from Pool to resolver queue
248 functor::functorRef<bool,PoolItem>(info) );
249 // Regard dependencies of the item weak onl
252 // Additional QueueItems which has to be regarded by the solver
253 _removed_queue_items.clear();
254 _added_queue_items.clear();
260 Resolver::solverInit()
262 // Solving with the satsolver
263 static bool poolDumped = false;
264 MIL << "-------------- Calling SAT Solver -------------------" << endl;
265 if ( getenv("ZYPP_FULLLOG") ) {
266 Testcase testcase("/var/log/YaST2/autoTestcase");
268 testcase.createTestcase (*this, true, false); // dump pool
271 testcase.createTestcase (*this, false, false); // write control file only
275 _satResolver->setFixsystem(false);
276 _satResolver->setIgnorealreadyrecommended(false);
277 _satResolver->setAllowdowngrade(false);
278 _satResolver->setAllowarchchange(false);
279 _satResolver->setAllowvendorchange(false);
280 _satResolver->setAllowuninstall(false);
281 _satResolver->setUpdatesystem(false);
282 _satResolver->setAllowvirtualconflicts(false);
283 _satResolver->setNoupdateprovide(false);
284 _satResolver->setDosplitprovides(false);
285 _satResolver->setSolveSrcPackages( solveSrcPackages() );
288 _satResolver->setAllowdowngrade(true);
289 _satResolver->setUpdatesystem(false); // not needed cause packages has already been evaluteted by distupgrade
290 _satResolver->setDosplitprovides(true);
291 if ( !getenv("ZYPP_NO_SAT_UPDATE") ) {
292 MIL << "-------------- Calling SAT Solver in distupgrade mode -------------------" << endl;
293 // SAT solver will do the dist update
294 _satResolver->setAllowarchchange(true);
295 _satResolver->setAllowvendorchange(true);
296 _satResolver->setUpdatesystem(true);
297 _satResolver->setDistupgrade(true);
298 _satResolver->setDistupgrade_removeunsupported(false);
303 _satResolver->setAllowuninstall(true);
305 if (indeterminate(_onlyRequires))
306 _satResolver->setOnlyRequires(ZConfig::instance().solver_onlyRequires());
307 else if (_onlyRequires)
308 _satResolver->setOnlyRequires(true);
310 _satResolver->setOnlyRequires(false);
313 _satResolver->setFixsystem(true);
315 if (_ignorealreadyrecommended)
316 _satResolver->setIgnorealreadyrecommended(true);
318 // Resetting additional solver information
319 _isInstalledBy.clear();
321 _satifiedByInstalled.clear();
322 _installedSatisfied.clear();
326 Resolver::resolvePool()
329 return _satResolver->resolvePool(_extra_requires, _extra_conflicts, _addWeak);
333 Resolver::resolveQueue(solver::detail::SolverQueueItemList & queue)
337 // add/remove additional SolverQueueItems
338 for (SolverQueueItemList::const_iterator iter = _removed_queue_items.begin();
339 iter != _removed_queue_items.end(); iter++) {
340 for (SolverQueueItemList::const_iterator iterQueue = queue.begin(); iterQueue != queue.end(); iterQueue++) {
341 if ( (*iterQueue)->cmp(*iter) == 0) {
342 MIL << "remove from queue" << *iter;
343 queue.remove(*iterQueue);
349 for (SolverQueueItemList::const_iterator iter = _added_queue_items.begin();
350 iter != _added_queue_items.end(); iter++) {
352 for (SolverQueueItemList::const_iterator iterQueue = queue.begin(); iterQueue != queue.end(); iterQueue++) {
353 if ( (*iterQueue)->cmp(*iter) == 0) {
359 MIL << "add to queue" << *iter;
360 queue.push_back(*iter);
364 // The application has to take care to write these solutions back to e.g. selectables in order
365 // give the user a chance for changing these decisions again.
366 _removed_queue_items.clear();
367 _added_queue_items.clear();
369 return _satResolver->resolveQueue(queue, _addWeak);
373 //----------------------------------------------------------------------------
374 // Getting more information about the solve results
378 Resolver::collectResolverInfo(void)
381 && _isInstalledBy.empty()
382 && _installs.empty()) {
385 PoolItemList itemsToInstall = _satResolver->resultItemsToInstall();
387 for (PoolItemList::const_iterator instIter = itemsToInstall.begin();
388 instIter != itemsToInstall.end(); instIter++) {
390 for (Capabilities::const_iterator capIt = (*instIter)->dep (Dep::REQUIRES).begin(); capIt != (*instIter)->dep (Dep::REQUIRES).end(); ++capIt)
392 sat::WhatProvides possibleProviders(*capIt);
393 for_( iter, possibleProviders.begin(), possibleProviders.end() ) {
394 PoolItem provider = ResPool::instance().find( *iter );
396 // searching if this provider will already be installed
398 bool alreadySetForInstallation = false;
399 ItemCapKindMap::const_iterator pos = _isInstalledBy.find(provider);
400 while (pos != _isInstalledBy.end()
401 && pos->first == provider
403 alreadySetForInstallation = true;
404 ItemCapKind capKind = pos->second;
405 if (capKind.item == *instIter) found = true;
410 && provider.status().isToBeInstalled()) {
411 if (provider.status().isBySolver()) {
412 ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::REQUIRES, !alreadySetForInstallation );
413 _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));
415 // no initial installation cause it has been set be e.g. user
416 ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::REQUIRES, false );
417 _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));
419 ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::REQUIRES, !alreadySetForInstallation );
420 _installs.insert (make_pair( *instIter, capKindisInstalledBy));
423 if (provider.status().staysInstalled()) { // Is already satisfied by an item which is installed
424 ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::REQUIRES, false );
425 _satifiedByInstalled.insert (make_pair( *instIter, capKindisInstalledBy));
427 ItemCapKind installedSatisfied( *instIter, *capIt, Dep::REQUIRES, false );
428 _installedSatisfied.insert (make_pair( provider, installedSatisfied));
433 if (!(_satResolver->onlyRequires())) {
435 for (Capabilities::const_iterator capIt = (*instIter)->dep (Dep::RECOMMENDS).begin(); capIt != (*instIter)->dep (Dep::RECOMMENDS).end(); ++capIt)
437 sat::WhatProvides possibleProviders(*capIt);
438 for_( iter, possibleProviders.begin(), possibleProviders.end() ) {
439 PoolItem provider = ResPool::instance().find( *iter );
441 // searching if this provider will already be installed
443 bool alreadySetForInstallation = false;
444 ItemCapKindMap::const_iterator pos = _isInstalledBy.find(provider);
445 while (pos != _isInstalledBy.end()
446 && pos->first == provider
448 alreadySetForInstallation = true;
449 ItemCapKind capKind = pos->second;
450 if (capKind.item == *instIter) found = true;
455 && provider.status().isToBeInstalled()) {
456 if (provider.status().isBySolver()) {
457 ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::RECOMMENDS, !alreadySetForInstallation );
458 _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));
460 // no initial installation cause it has been set be e.g. user
461 ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::RECOMMENDS, false );
462 _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy));
464 ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::RECOMMENDS, !alreadySetForInstallation );
465 _installs.insert (make_pair( *instIter, capKindisInstalledBy));
468 if (provider.status().staysInstalled()) { // Is already satisfied by an item which is installed
469 ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::RECOMMENDS, false );
470 _satifiedByInstalled.insert (make_pair( *instIter, capKindisInstalledBy));
472 ItemCapKind installedSatisfied( *instIter, *capIt, Dep::RECOMMENDS, false );
473 _installedSatisfied.insert (make_pair( provider, installedSatisfied));
479 for (Capabilities::const_iterator capIt = (*instIter)->dep (Dep::SUPPLEMENTS).begin(); capIt != (*instIter)->dep (Dep::SUPPLEMENTS).end(); ++capIt)
481 sat::WhatProvides possibleProviders(*capIt);
482 for_( iter, possibleProviders.begin(), possibleProviders.end() ) {
483 PoolItem provider = ResPool::instance().find( *iter );
484 // searching if this item will already be installed
486 bool alreadySetForInstallation = false;
487 ItemCapKindMap::const_iterator pos = _isInstalledBy.find(*instIter);
488 while (pos != _isInstalledBy.end()
489 && pos->first == *instIter
491 alreadySetForInstallation = true;
492 ItemCapKind capKind = pos->second;
493 if (capKind.item == provider) found = true;
498 && instIter->status().isToBeInstalled()) {
499 if (instIter->status().isBySolver()) {
500 ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::SUPPLEMENTS, !alreadySetForInstallation );
501 _isInstalledBy.insert (make_pair( *instIter, capKindisInstalledBy));
503 // no initial installation cause it has been set be e.g. user
504 ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::SUPPLEMENTS, false );
505 _isInstalledBy.insert (make_pair( *instIter, capKindisInstalledBy));
507 ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::SUPPLEMENTS, !alreadySetForInstallation );
508 _installs.insert (make_pair( provider, capKindisInstalledBy));
511 if (instIter->status().staysInstalled()) { // Is already satisfied by an item which is installed
512 ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::SUPPLEMENTS, !alreadySetForInstallation );
513 _satifiedByInstalled.insert (make_pair( provider, capKindisInstalledBy));
515 ItemCapKind installedSatisfied( provider, *capIt, Dep::SUPPLEMENTS, false );
516 _installedSatisfied.insert (make_pair( *instIter, installedSatisfied));
526 const ItemCapKindList Resolver::isInstalledBy (const PoolItem item) {
528 collectResolverInfo();
530 for (ItemCapKindMap::const_iterator iter = _isInstalledBy.find(item); iter != _isInstalledBy.end();) {
531 ItemCapKind info = iter->second;
532 PoolItem iterItem = iter->first;
533 if (iterItem == item) {
538 iter = _isInstalledBy.end();
544 const ItemCapKindList Resolver::installs (const PoolItem item) {
546 collectResolverInfo();
548 for (ItemCapKindMap::const_iterator iter = _installs.find(item); iter != _installs.end();) {
549 ItemCapKind info = iter->second;
550 PoolItem iterItem = iter->first;
551 if (iterItem == item) {
556 iter = _installs.end();
562 const ItemCapKindList Resolver::satifiedByInstalled (const PoolItem item) {
564 collectResolverInfo();
566 for (ItemCapKindMap::const_iterator iter = _satifiedByInstalled.find(item); iter != _satifiedByInstalled.end();) {
567 ItemCapKind info = iter->second;
568 PoolItem iterItem = iter->first;
569 if (iterItem == item) {
574 iter = _satifiedByInstalled.end();
580 const ItemCapKindList Resolver::installedSatisfied (const PoolItem item) {
582 collectResolverInfo();
584 for (ItemCapKindMap::const_iterator iter = _installedSatisfied.find(item); iter != _installedSatisfied.end();) {
585 ItemCapKind info = iter->second;
586 PoolItem iterItem = iter->first;
587 if (iterItem == item) {
592 iter = _installedSatisfied.end();
599 ///////////////////////////////////////////////////////////////////
600 };// namespace detail
601 /////////////////////////////////////////////////////////////////////
602 /////////////////////////////////////////////////////////////////////
603 };// namespace solver
604 ///////////////////////////////////////////////////////////////////////
605 ///////////////////////////////////////////////////////////////////////
607 /////////////////////////////////////////////////////////////////////////