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() )
72 , _forceResolve(false)
75 , _onlyRequires(indeterminate)
78 sat::Pool satPool( sat::Pool::instance() );
79 _satResolver = new SATResolver(_pool, satPool.get());
87 //---------------------------------------------------------------------------
90 Resolver::pool (void) const
96 Resolver::reset (bool keepExtras )
101 _extra_requires.clear();
102 _extra_conflicts.clear();
110 return _satResolver->doUpdate();
112 ERR << "SAT solver has not been initialized." << endl;
118 Resolver::addExtraRequire (const Capability & capability)
120 _extra_requires.insert (capability);
124 Resolver::removeExtraRequire (const Capability & capability)
126 _extra_requires.erase (capability);
130 Resolver::addExtraConflict (const Capability & capability)
132 _extra_conflicts.insert (capability);
136 Resolver::removeExtraConflict (const Capability & capability)
138 _extra_conflicts.erase (capability);
142 Resolver::addWeak (const PoolItem item)
144 _addWeak.push_back (item);
147 //---------------------------------------------------------------------------
149 struct UndoTransact : public resfilter::PoolItemFilterFunctor
151 ResStatus::TransactByValue resStatus;
152 UndoTransact ( const ResStatus::TransactByValue &status)
156 bool operator()( PoolItem item ) // only transacts() items go here
158 item.status().resetTransact( resStatus );// clear any solver/establish transactions
164 struct DoTransact : public resfilter::PoolItemFilterFunctor
166 ResStatus::TransactByValue resStatus;
167 DoTransact ( const ResStatus::TransactByValue &status)
171 bool operator()( PoolItem item ) // only transacts() items go here
173 item.status().setTransact( true, resStatus );
180 Resolver::verifySystem ()
182 UndoTransact resetting (ResStatus::APPL_HIGH);
184 _DEBUG ("Resolver::verifySystem() ");
188 invokeOnEach ( _pool.begin(), _pool.end(),
189 resfilter::ByTransact( ), // Resetting all transcations
190 functor::functorRef<bool,PoolItem>(resetting) );
192 return resolvePool();
196 //----------------------------------------------------------------------------
202 UndoTransact info(ResStatus::APPL_LOW);
203 MIL << "*** undo ***" << endl;
204 invokeOnEach ( _pool.begin(), _pool.end(),
205 resfilter::ByTransact( ), // collect transacts from Pool to resolver queue
206 functor::functorRef<bool,PoolItem>(info) );
207 // Regard dependencies of the item weak onl
214 Resolver::solverInit()
216 // Solving with the satsolver
217 static bool poolDumped = false;
218 MIL << "-------------- Calling SAT Solver -------------------" << endl;
219 if ( getenv("ZYPP_FULLLOG") ) {
220 Testcase testcase("/var/log/YaST2/autoTestcase");
222 testcase.createTestcase (*this, true, false); // dump pool
225 testcase.createTestcase (*this, false, false); // write control file only
229 _satResolver->setFixsystem(false);
230 _satResolver->setAllowdowngrade(false);
231 _satResolver->setAllowarchchange(false);
232 _satResolver->setAllowvendorchange(false);
233 _satResolver->setAllowuninstall(false);
234 _satResolver->setUpdatesystem(false);
235 _satResolver->setAllowvirtualconflicts(false);
236 _satResolver->setNoupdateprovide(true);
237 _satResolver->setDosplitprovides(false);
240 _satResolver->setAllowdowngrade(true);
241 _satResolver->setAllowarchchange(true);
242 _satResolver->setUpdatesystem(true);
243 _satResolver->setDosplitprovides(true);
247 _satResolver->setAllowuninstall(true);
249 if (_onlyRequires == indeterminate)
250 _satResolver->setOnlyRequires(ZConfig::instance().solver_onlyRequires());
251 else if (_onlyRequires)
252 _satResolver->setOnlyRequires(true);
254 _satResolver->setOnlyRequires(false);
257 _satResolver->setFixsystem(true);
261 Resolver::resolvePool()
264 return _satResolver->resolvePool(_extra_requires, _extra_conflicts);
268 Resolver::resolveQueue(solver::detail::SolverQueueItemList & queue)
271 return _satResolver->resolveQueue(queue);
276 ///////////////////////////////////////////////////////////////////
279 // METHOD NAME : Resolver::checkUnmaintainedItems
282 // DESCRIPTION : Unmaintained packages which does not fit to
283 // the updated system (broken dependencies) will be
286 void Resolver::checkUnmaintainedItems () {
288 MIL << "Checking unmaintained items....." << endl;
290 while (!resolvePool() && solverRuns++ < MAXSOLVERRUNS) {
291 ResolverProblemList problemList = problems();
292 ProblemSolutionList solutionList;
293 PoolItemList problemItemList;
295 for (ResolverProblemList::iterator iter = problemList.begin(); iter != problemList.end(); ++iter) {
296 ResolverProblem problem = **iter;
297 DBG << "Problem:" << endl;
298 DBG << problem.description() << endl;
299 DBG << problem.details() << endl;
301 ProblemSolutionList solutions = problem.solutions();
302 for (ProblemSolutionList::const_iterator iterSolution = solutions.begin();
303 iterSolution != solutions.end(); ++iterSolution) {
304 ProblemSolution_Ptr solution = *iterSolution;
305 DBG << " Solution:" << endl;
306 DBG << " " << solution->description() << endl;
307 DBG << " " << solution->details() << endl;
308 solver::detail::CSolutionActionList actionList = solution->actions();
309 bool fitUnmaintained = false;
310 PoolItemList deletedItems;
311 for (CSolutionActionList::const_iterator iterActions = actionList.begin();
312 iterActions != actionList.end(); ++iterActions) {
313 TransactionSolutionAction_constPtr transactionAction = dynamic_pointer_cast<const TransactionSolutionAction>(*iterActions);
314 if (transactionAction &&
315 transactionAction->action() == REMOVE
316 && _unmaintained_items.find(transactionAction->item()) != _unmaintained_items.end()) {
317 // The solution contains unmaintained items ONLY which will be deleted. So take this solution
318 fitUnmaintained = true;
319 deletedItems.push_back (transactionAction->item());
321 fitUnmaintained = false;
324 if (fitUnmaintained) {
325 MIL << "Problem:" << endl;
326 MIL << problem.description() << endl;
327 MIL << problem.details() << endl;
328 MIL << "Will be solved by removing unmaintained package(s)............" << endl;
329 MIL << " Solution:" << endl;
330 MIL << " " << solution->description() << endl;
331 MIL << " " << solution->details() << endl;
332 solutionList.push_back (solution);
333 problemItemList.insert (problemItemList.end(), deletedItems.begin(), deletedItems.end() );
334 break; // not regarding the other solutions
339 if (!solutionList.empty()) {
340 applySolutions (solutionList);
341 // list of problematic items after doUpgrade() which is show to the user
342 _problem_items.insert (_problem_items.end(), problemItemList.begin(), problemItemList.end());
343 _problem_items.unique();
345 // break cause there is no other solution available by the next run
346 solverRuns = MAXSOLVERRUNS;
352 ///////////////////////////////////////////////////////////////////
353 };// namespace detail
354 /////////////////////////////////////////////////////////////////////
355 /////////////////////////////////////////////////////////////////////
356 };// namespace solver
357 ///////////////////////////////////////////////////////////////////////
358 ///////////////////////////////////////////////////////////////////////
360 /////////////////////////////////////////////////////////////////////////