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();
109 return _satResolver->doUpdate();
113 Resolver::addExtraRequire (const Capability & capability)
115 _extra_requires.insert (capability);
119 Resolver::removeExtraRequire (const Capability & capability)
121 _extra_requires.erase (capability);
125 Resolver::addExtraConflict (const Capability & capability)
127 _extra_conflicts.insert (capability);
131 Resolver::removeExtraConflict (const Capability & capability)
133 _extra_conflicts.erase (capability);
137 Resolver::addWeak (const PoolItem item)
139 _addWeak.push_back (item);
142 //---------------------------------------------------------------------------
144 struct UndoTransact : public resfilter::PoolItemFilterFunctor
146 ResStatus::TransactByValue resStatus;
147 UndoTransact ( const ResStatus::TransactByValue &status)
151 bool operator()( PoolItem item ) // only transacts() items go here
153 item.status().resetTransact( resStatus );// clear any solver/establish transactions
159 struct DoTransact : public resfilter::PoolItemFilterFunctor
161 ResStatus::TransactByValue resStatus;
162 DoTransact ( const ResStatus::TransactByValue &status)
166 bool operator()( PoolItem item ) // only transacts() items go here
168 item.status().setTransact( true, resStatus );
175 Resolver::verifySystem ()
177 UndoTransact resetting (ResStatus::APPL_HIGH);
179 _DEBUG ("Resolver::verifySystem() ");
183 invokeOnEach ( _pool.begin(), _pool.end(),
184 resfilter::ByTransact( ), // Resetting all transcations
185 functor::functorRef<bool,PoolItem>(resetting) );
187 return resolvePool();
191 //----------------------------------------------------------------------------
197 UndoTransact info(ResStatus::APPL_LOW);
198 MIL << "*** undo ***" << endl;
199 invokeOnEach ( _pool.begin(), _pool.end(),
200 resfilter::ByTransact( ), // collect transacts from Pool to resolver queue
201 functor::functorRef<bool,PoolItem>(info) );
202 // Regard dependencies of the item weak onl
209 Resolver::solverInit()
211 // Solving with the satsolver
212 static bool poolDumped = false;
213 MIL << "-------------- Calling SAT Solver -------------------" << endl;
214 if ( getenv("ZYPP_FULLLOG") ) {
215 Testcase testcase("/var/log/YaST2/autoTestcase");
217 testcase.createTestcase (*this, true, false); // dump pool
220 testcase.createTestcase (*this, false, false); // write control file only
224 _satResolver->setFixsystem(false);
225 _satResolver->setAllowdowngrade(false);
226 _satResolver->setAllowarchchange(false);
227 _satResolver->setAllowvendorchange(false);
228 _satResolver->setAllowuninstall(false);
229 _satResolver->setUpdatesystem(false);
230 _satResolver->setAllowvirtualconflicts(false);
231 _satResolver->setNoupdateprovide(true);
232 _satResolver->setDosplitprovides(false);
235 _satResolver->setAllowdowngrade(true);
236 _satResolver->setUpdatesystem(true);
237 _satResolver->setDosplitprovides(true);
241 _satResolver->setAllowuninstall(true);
243 if (_onlyRequires == indeterminate)
244 _satResolver->setOnlyRequires(ZConfig::instance().solver_onlyRequires());
245 else if (_onlyRequires)
246 _satResolver->setOnlyRequires(true);
248 _satResolver->setOnlyRequires(false);
251 _satResolver->setFixsystem(true);
255 Resolver::resolvePool()
258 return _satResolver->resolvePool(_extra_requires, _extra_conflicts, _addWeak);
262 Resolver::resolveQueue(solver::detail::SolverQueueItemList & queue)
265 return _satResolver->resolveQueue(queue, _addWeak);
270 ///////////////////////////////////////////////////////////////////
273 // METHOD NAME : Resolver::checkUnmaintainedItems
276 // DESCRIPTION : Unmaintained packages which does not fit to
277 // the updated system (broken dependencies) will be
279 // returns true if solving was successful
281 bool Resolver::checkUnmaintainedItems () {
283 bool solverRet = resolvePool();
284 MIL << "Checking unmaintained items....." << endl;
286 while (!solverRet && solverRuns++ < MAXSOLVERRUNS) {
287 ResolverProblemList problemList = problems();
288 ProblemSolutionList solutionList;
289 PoolItemList problemItemList;
291 for (ResolverProblemList::iterator iter = problemList.begin(); iter != problemList.end(); ++iter) {
292 ResolverProblem problem = **iter;
293 DBG << "Problem:" << endl;
294 DBG << problem.description() << endl;
295 DBG << problem.details() << endl;
297 ProblemSolutionList solutions = problem.solutions();
298 for (ProblemSolutionList::const_iterator iterSolution = solutions.begin();
299 iterSolution != solutions.end(); ++iterSolution) {
300 ProblemSolution_Ptr solution = *iterSolution;
301 DBG << " Solution:" << endl;
302 DBG << " " << solution->description() << endl;
303 DBG << " " << solution->details() << endl;
304 solver::detail::CSolutionActionList actionList = solution->actions();
305 bool fitUnmaintained = false;
306 PoolItemList deletedItems;
307 for (CSolutionActionList::const_iterator iterActions = actionList.begin();
308 iterActions != actionList.end(); ++iterActions) {
309 TransactionSolutionAction_constPtr transactionAction = dynamic_pointer_cast<const TransactionSolutionAction>(*iterActions);
310 if (transactionAction &&
311 transactionAction->action() == REMOVE
312 && _unmaintained_items.find(transactionAction->item()) != _unmaintained_items.end()) {
313 // The solution contains unmaintained items ONLY which will be deleted. So take this solution
314 fitUnmaintained = true;
315 deletedItems.push_back (transactionAction->item());
317 fitUnmaintained = false;
320 if (fitUnmaintained) {
321 MIL << "Problem:" << endl;
322 MIL << problem.description() << endl;
323 MIL << problem.details() << endl;
324 MIL << "Will be solved by removing unmaintained package(s)............" << endl;
325 MIL << " Solution:" << endl;
326 MIL << " " << solution->description() << endl;
327 MIL << " " << solution->details() << endl;
328 solutionList.push_back (solution);
329 problemItemList.insert (problemItemList.end(), deletedItems.begin(), deletedItems.end() );
330 break; // not regarding the other solutions
335 if (!solutionList.empty()) {
336 applySolutions (solutionList);
337 // list of problematic items after doUpgrade() which is show to the user
338 _problem_items.insert (_problem_items.end(), problemItemList.begin(), problemItemList.end());
339 _problem_items.unique();
341 // break cause there is no other solution available by the next run
342 solverRuns = MAXSOLVERRUNS;
345 solverRet = resolvePool();
350 ///////////////////////////////////////////////////////////////////
351 };// namespace detail
352 /////////////////////////////////////////////////////////////////////
353 /////////////////////////////////////////////////////////////////////
354 };// namespace solver
355 ///////////////////////////////////////////////////////////////////////
356 ///////////////////////////////////////////////////////////////////////
358 /////////////////////////////////////////////////////////////////////////