11a4d020dSIngo Weinhold/*
21a4d020dSIngo Weinhold * Copyright 2013, Haiku, Inc. All Rights Reserved.
31a4d020dSIngo Weinhold * Distributed under the terms of the MIT License.
41a4d020dSIngo Weinhold *
51a4d020dSIngo Weinhold * Authors:
61a4d020dSIngo Weinhold *		Ingo Weinhold <ingo_weinhold@gmx.de>
71a4d020dSIngo Weinhold */
81a4d020dSIngo Weinhold
91a4d020dSIngo Weinhold
101a4d020dSIngo Weinhold#include "LibsolvSolver.h"
111a4d020dSIngo Weinhold
121a4d020dSIngo Weinhold#include <errno.h>
13001e9064SIngo Weinhold#include <sys/utsname.h>
141a4d020dSIngo Weinhold
151a4d020dSIngo Weinhold#include <new>
161a4d020dSIngo Weinhold
175e01af31SIngo Weinhold#include <solv/policy.h>
181a4d020dSIngo Weinhold#include <solv/poolarch.h>
191a4d020dSIngo Weinhold#include <solv/repo.h>
201a4d020dSIngo Weinhold#include <solv/repo_haiku.h>
211a4d020dSIngo Weinhold#include <solv/selection.h>
221a4d020dSIngo Weinhold#include <solv/solverdebug.h>
231a4d020dSIngo Weinhold
241a4d020dSIngo Weinhold#include <package/PackageResolvableExpression.h>
251a4d020dSIngo Weinhold#include <package/RepositoryCache.h>
261a4d020dSIngo Weinhold#include <package/solver/SolverPackage.h>
271a4d020dSIngo Weinhold#include <package/solver/SolverPackageSpecifier.h>
281a4d020dSIngo Weinhold#include <package/solver/SolverPackageSpecifierList.h>
291a4d020dSIngo Weinhold#include <package/solver/SolverProblem.h>
301a4d020dSIngo Weinhold#include <package/solver/SolverRepository.h>
311a4d020dSIngo Weinhold#include <package/solver/SolverResult.h>
321a4d020dSIngo Weinhold
331a4d020dSIngo Weinhold#include <AutoDeleter.h>
341a4d020dSIngo Weinhold#include <ObjectList.h>
351a4d020dSIngo Weinhold
361a4d020dSIngo Weinhold
371a4d020dSIngo Weinhold// TODO: libsolv doesn't have any helpful out-of-memory handling. It just just
381a4d020dSIngo Weinhold// abort()s. Obviously that isn't good behavior for a library.
391a4d020dSIngo Weinhold
401a4d020dSIngo Weinhold
411a4d020dSIngo WeinholdBSolver*
421a4d020dSIngo WeinholdBPackageKit::create_solver()
431a4d020dSIngo Weinhold{
441a4d020dSIngo Weinhold	return new(std::nothrow) LibsolvSolver;
451a4d020dSIngo Weinhold}
461a4d020dSIngo Weinhold
471a4d020dSIngo Weinhold
481a4d020dSIngo Weinholdstruct LibsolvSolver::SolvQueue : Queue {
491a4d020dSIngo Weinhold	SolvQueue()
501a4d020dSIngo Weinhold	{
511a4d020dSIngo Weinhold		queue_init(this);
521a4d020dSIngo Weinhold	}
531a4d020dSIngo Weinhold
541a4d020dSIngo Weinhold	~SolvQueue()
551a4d020dSIngo Weinhold	{
561a4d020dSIngo Weinhold		queue_free(this);
571a4d020dSIngo Weinhold	}
581a4d020dSIngo Weinhold};
591a4d020dSIngo Weinhold
601a4d020dSIngo Weinhold
61fc57db48SIngo Weinholdstruct LibsolvSolver::SolvDataIterator : Dataiterator {
62fc57db48SIngo Weinhold	SolvDataIterator(Pool* pool, Repo* repo, Id solvableId, Id keyname,
63fc57db48SIngo Weinhold		const char* match, int flags)
64fc57db48SIngo Weinhold	{
65fc57db48SIngo Weinhold		dataiterator_init(this, pool, repo, solvableId, keyname, match, flags);
66fc57db48SIngo Weinhold	}
67fc57db48SIngo Weinhold
68fc57db48SIngo Weinhold	~SolvDataIterator()
69fc57db48SIngo Weinhold	{
70fc57db48SIngo Weinhold		dataiterator_free(this);
71fc57db48SIngo Weinhold	}
72fc57db48SIngo Weinhold};
73fc57db48SIngo Weinhold
74fc57db48SIngo Weinhold
751a4d020dSIngo Weinholdstruct LibsolvSolver::RepositoryInfo {
761a4d020dSIngo Weinhold	RepositoryInfo(BSolverRepository* repository)
771a4d020dSIngo Weinhold		:
781a4d020dSIngo Weinhold		fRepository(repository),
79483d4996SIngo Weinhold		fSolvRepo(NULL),
80a78a2540SIngo Weinhold		fChangeCount(repository->ChangeCount())
811a4d020dSIngo Weinhold	{
821a4d020dSIngo Weinhold	}
831a4d020dSIngo Weinhold
841a4d020dSIngo Weinhold	BSolverRepository* Repository() const
851a4d020dSIngo Weinhold	{
861a4d020dSIngo Weinhold		return fRepository;
871a4d020dSIngo Weinhold	}
881a4d020dSIngo Weinhold
891a4d020dSIngo Weinhold	Repo* SolvRepo()
901a4d020dSIngo Weinhold	{
911a4d020dSIngo Weinhold		return fSolvRepo;
921a4d020dSIngo Weinhold	}
931a4d020dSIngo Weinhold
941a4d020dSIngo Weinhold	void SetSolvRepo(Repo* repo)
951a4d020dSIngo Weinhold	{
961a4d020dSIngo Weinhold		fSolvRepo = repo;
971a4d020dSIngo Weinhold	}
981a4d020dSIngo Weinhold
99483d4996SIngo Weinhold	bool HasChanged() const
100483d4996SIngo Weinhold	{
101a78a2540SIngo Weinhold		return fChangeCount != fRepository->ChangeCount() || fSolvRepo == NULL;
102483d4996SIngo Weinhold	}
103483d4996SIngo Weinhold
104483d4996SIngo Weinhold	void SetUnchanged()
105483d4996SIngo Weinhold	{
106483d4996SIngo Weinhold		fChangeCount = fRepository->ChangeCount();
107483d4996SIngo Weinhold	}
108483d4996SIngo Weinhold
1091a4d020dSIngo Weinholdprivate:
1101a4d020dSIngo Weinhold	BSolverRepository*	fRepository;
1111a4d020dSIngo Weinhold	Repo*				fSolvRepo;
112483d4996SIngo Weinhold	uint64				fChangeCount;
1131a4d020dSIngo Weinhold};
1141a4d020dSIngo Weinhold
1151a4d020dSIngo Weinhold
1165e01af31SIngo Weinholdstruct LibsolvSolver::Problem : public BSolverProblem {
1175e01af31SIngo Weinhold	Problem(::Id id, BType type, BSolverPackage* sourcePackage,
1185e01af31SIngo Weinhold		BSolverPackage* targetPackage,
1195e01af31SIngo Weinhold		const BPackageResolvableExpression& dependency)
1205e01af31SIngo Weinhold		:
1215e01af31SIngo Weinhold		BSolverProblem(type, sourcePackage, targetPackage, dependency),
1228e6c3631SIngo Weinhold		fId(id),
1238e6c3631SIngo Weinhold		fSelectedSolution(NULL)
1245e01af31SIngo Weinhold	{
1255e01af31SIngo Weinhold	}
1265e01af31SIngo Weinhold
1275e01af31SIngo Weinhold	::Id Id() const
1285e01af31SIngo Weinhold	{
1295e01af31SIngo Weinhold		return fId;
1305e01af31SIngo Weinhold	}
1315e01af31SIngo Weinhold
1328e6c3631SIngo Weinhold	const Solution* SelectedSolution() const
1338e6c3631SIngo Weinhold	{
1348e6c3631SIngo Weinhold		return fSelectedSolution;
1358e6c3631SIngo Weinhold	}
1368e6c3631SIngo Weinhold
1378e6c3631SIngo Weinhold	void SetSelectedSolution(const Solution* solution)
1388e6c3631SIngo Weinhold	{
1398e6c3631SIngo Weinhold		fSelectedSolution = solution;
1408e6c3631SIngo Weinhold	}
1418e6c3631SIngo Weinhold
1425e01af31SIngo Weinholdprivate:
1438e6c3631SIngo Weinhold	::Id			fId;
1448e6c3631SIngo Weinhold	const Solution*	fSelectedSolution;
1455e01af31SIngo Weinhold};
1465e01af31SIngo Weinhold
1475e01af31SIngo Weinhold
1485e01af31SIngo Weinholdstruct LibsolvSolver::Solution : public BSolverProblemSolution {
1498e6c3631SIngo Weinhold	Solution(::Id id, LibsolvSolver::Problem* problem)
1505e01af31SIngo Weinhold		:
1515e01af31SIngo Weinhold		BSolverProblemSolution(),
1525e01af31SIngo Weinhold		fId(id),
1535e01af31SIngo Weinhold		fProblem(problem)
1545e01af31SIngo Weinhold	{
1555e01af31SIngo Weinhold	}
1565e01af31SIngo Weinhold
1575e01af31SIngo Weinhold	::Id Id() const
1585e01af31SIngo Weinhold	{
1595e01af31SIngo Weinhold		return fId;
1605e01af31SIngo Weinhold	}
1615e01af31SIngo Weinhold
1628e6c3631SIngo Weinhold	LibsolvSolver::Problem* Problem() const
1638e6c3631SIngo Weinhold	{
1648e6c3631SIngo Weinhold		return fProblem;
1658e6c3631SIngo Weinhold	}
1668e6c3631SIngo Weinhold
1675e01af31SIngo Weinholdprivate:
1688e6c3631SIngo Weinhold	::Id					fId;
1698e6c3631SIngo Weinhold	LibsolvSolver::Problem*	fProblem;
1705e01af31SIngo Weinhold};
1715e01af31SIngo Weinhold
1725e01af31SIngo Weinhold
1731a4d020dSIngo Weinhold// #pragma mark - LibsolvSolver
1741a4d020dSIngo Weinhold
1751a4d020dSIngo Weinhold
1761a4d020dSIngo WeinholdLibsolvSolver::LibsolvSolver()
1771a4d020dSIngo Weinhold	:
1781a4d020dSIngo Weinhold	fPool(NULL),
1791a4d020dSIngo Weinhold	fSolver(NULL),
1808e6c3631SIngo Weinhold	fJobs(NULL),
1811a4d020dSIngo Weinhold	fRepositoryInfos(10, true),
1821a4d020dSIngo Weinhold	fInstalledRepository(NULL),
183483d4996SIngo Weinhold	fSolvablePackages(),
18401758ed3SIngo Weinhold	fPackageSolvables(),
18574b582a4SIngo Weinhold	fProblems(10, true),
18674b582a4SIngo Weinhold	fDebugLevel(0)
1871a4d020dSIngo Weinhold{
1881a4d020dSIngo Weinhold}
1891a4d020dSIngo Weinhold
1901a4d020dSIngo Weinhold
1911a4d020dSIngo WeinholdLibsolvSolver::~LibsolvSolver()
1921a4d020dSIngo Weinhold{
1931a4d020dSIngo Weinhold	_Cleanup();
1941a4d020dSIngo Weinhold}
1951a4d020dSIngo Weinhold
1961a4d020dSIngo Weinhold
1971a4d020dSIngo Weinholdstatus_t
1981a4d020dSIngo WeinholdLibsolvSolver::Init()
1991a4d020dSIngo Weinhold{
200a78a2540SIngo Weinhold	_Cleanup();
201a78a2540SIngo Weinhold
202483d4996SIngo Weinhold	// We do all initialization lazily.
2031a4d020dSIngo Weinhold	return B_OK;
2041a4d020dSIngo Weinhold}
2051a4d020dSIngo Weinhold
2061a4d020dSIngo Weinhold
20774b582a4SIngo Weinholdvoid
20874b582a4SIngo WeinholdLibsolvSolver::SetDebugLevel(int32 level)
20974b582a4SIngo Weinhold{
21074b582a4SIngo Weinhold	fDebugLevel = level;
21174b582a4SIngo Weinhold
21274b582a4SIngo Weinhold	if (fPool != NULL)
21374b582a4SIngo Weinhold		pool_setdebuglevel(fPool, fDebugLevel);
21474b582a4SIngo Weinhold}
21574b582a4SIngo Weinhold
21674b582a4SIngo Weinhold
2171a4d020dSIngo Weinholdstatus_t
2181a4d020dSIngo WeinholdLibsolvSolver::AddRepository(BSolverRepository* repository)
2191a4d020dSIngo Weinhold{
2201a4d020dSIngo Weinhold	if (repository == NULL || repository->InitCheck() != B_OK)
2211a4d020dSIngo Weinhold		return B_BAD_VALUE;
2221a4d020dSIngo Weinhold
2231a4d020dSIngo Weinhold	// If the repository represents installed packages, check, if we already
2241a4d020dSIngo Weinhold	// have such a repository.
2257af664c9SIngo Weinhold	if (repository->IsInstalled() && _InstalledRepository() != NULL)
2261a4d020dSIngo Weinhold		return B_BAD_VALUE;
2271a4d020dSIngo Weinhold
2281a4d020dSIngo Weinhold	// add the repository info
2291a4d020dSIngo Weinhold	RepositoryInfo* info = new(std::nothrow) RepositoryInfo(repository);
2301a4d020dSIngo Weinhold	if (info == NULL)
2311a4d020dSIngo Weinhold		return B_NO_MEMORY;
2321a4d020dSIngo Weinhold
2331a4d020dSIngo Weinhold	if (!fRepositoryInfos.AddItem(info)) {
2341a4d020dSIngo Weinhold		delete info;
2351a4d020dSIngo Weinhold		return B_NO_MEMORY;
2361a4d020dSIngo Weinhold	}
2371a4d020dSIngo Weinhold
2381a4d020dSIngo Weinhold	return B_OK;
2391a4d020dSIngo Weinhold}
2401a4d020dSIngo Weinhold
2411a4d020dSIngo Weinhold
242fc57db48SIngo Weinholdstatus_t
243fc57db48SIngo WeinholdLibsolvSolver::FindPackages(const char* searchString, uint32 flags,
244fc57db48SIngo Weinhold	BObjectList<BSolverPackage>& _packages)
245fc57db48SIngo Weinhold{
246fc57db48SIngo Weinhold	// add repositories to pool
247fc57db48SIngo Weinhold	status_t error = _AddRepositories();
248fc57db48SIngo Weinhold	if (error != B_OK)
249fc57db48SIngo Weinhold		return error;
250fc57db48SIngo Weinhold
251fc57db48SIngo Weinhold	// create data iterator
252fc57db48SIngo Weinhold	int iteratorFlags = SEARCH_SUBSTRING;
253fc57db48SIngo Weinhold	if ((flags & B_FIND_CASE_INSENSITIVE) != 0)
254fc57db48SIngo Weinhold		iteratorFlags |= SEARCH_NOCASE;
255fc57db48SIngo Weinhold
256fc57db48SIngo Weinhold	SolvDataIterator iterator(fPool, 0, 0, 0, searchString, iteratorFlags);
257663e351cSIngo Weinhold	SolvQueue selection;
258fc57db48SIngo Weinhold
259fc57db48SIngo Weinhold	// search package names
260663e351cSIngo Weinhold	if ((flags & B_FIND_IN_NAME) != 0) {
261663e351cSIngo Weinhold		dataiterator_set_keyname(&iterator, SOLVABLE_NAME);
262663e351cSIngo Weinhold		dataiterator_set_search(&iterator, 0, 0);
263fc57db48SIngo Weinhold
264663e351cSIngo Weinhold		while (dataiterator_step(&iterator))
265663e351cSIngo Weinhold			queue_push2(&selection, SOLVER_SOLVABLE, iterator.solvid);
266663e351cSIngo Weinhold	}
267fc57db48SIngo Weinhold
268fc57db48SIngo Weinhold	// search package summaries
269fc57db48SIngo Weinhold	if ((flags & B_FIND_IN_SUMMARY) != 0) {
270fc57db48SIngo Weinhold		dataiterator_set_keyname(&iterator, SOLVABLE_SUMMARY);
271fc57db48SIngo Weinhold		dataiterator_set_search(&iterator, 0, 0);
272fc57db48SIngo Weinhold
273fc57db48SIngo Weinhold		while (dataiterator_step(&iterator))
274fc57db48SIngo Weinhold			queue_push2(&selection, SOLVER_SOLVABLE, iterator.solvid);
275fc57db48SIngo Weinhold	}
276fc57db48SIngo Weinhold
277fc57db48SIngo Weinhold	// search package description
278fc57db48SIngo Weinhold	if ((flags & B_FIND_IN_DESCRIPTION) != 0) {
279fc57db48SIngo Weinhold		dataiterator_set_keyname(&iterator, SOLVABLE_DESCRIPTION);
280fc57db48SIngo Weinhold		dataiterator_set_search(&iterator, 0, 0);
281fc57db48SIngo Weinhold
282fc57db48SIngo Weinhold		while (dataiterator_step(&iterator))
283fc57db48SIngo Weinhold			queue_push2(&selection, SOLVER_SOLVABLE, iterator.solvid);
284fc57db48SIngo Weinhold	}
285fc57db48SIngo Weinhold
286663e351cSIngo Weinhold	// search package provides
287663e351cSIngo Weinhold	if ((flags & B_FIND_IN_PROVIDES) != 0) {
288663e351cSIngo Weinhold		dataiterator_set_keyname(&iterator, SOLVABLE_PROVIDES);
289663e351cSIngo Weinhold		dataiterator_set_search(&iterator, 0, 0);
290663e351cSIngo Weinhold
291663e351cSIngo Weinhold		while (dataiterator_step(&iterator))
292663e351cSIngo Weinhold			queue_push2(&selection, SOLVER_SOLVABLE, iterator.solvid);
293663e351cSIngo Weinhold	}
294663e351cSIngo Weinhold
295af585d03SJérôme Duval	// search package requires
296af585d03SJérôme Duval	if ((flags & B_FIND_IN_REQUIRES) != 0) {
297af585d03SJérôme Duval		dataiterator_set_keyname(&iterator, SOLVABLE_REQUIRES);
298af585d03SJérôme Duval		dataiterator_set_search(&iterator, 0, 0);
299af585d03SJérôme Duval
300af585d03SJérôme Duval		while (dataiterator_step(&iterator))
301af585d03SJérôme Duval			queue_push2(&selection, SOLVER_SOLVABLE, iterator.solvid);
302af585d03SJérôme Duval	}
303af585d03SJérôme Duval
30475d15eb4SIngo Weinhold	return _GetFoundPackages(selection, flags, _packages);
30575d15eb4SIngo Weinhold}
306fc57db48SIngo Weinhold
307fc57db48SIngo Weinhold
30875d15eb4SIngo Weinholdstatus_t
30975d15eb4SIngo WeinholdLibsolvSolver::FindPackages(const BSolverPackageSpecifierList& packages,
31075d15eb4SIngo Weinhold	uint32 flags, BObjectList<BSolverPackage>& _packages,
31175d15eb4SIngo Weinhold	const BSolverPackageSpecifier** _unmatched)
31275d15eb4SIngo Weinhold{
31375d15eb4SIngo Weinhold	if (_unmatched != NULL)
31475d15eb4SIngo Weinhold		*_unmatched = NULL;
315fc57db48SIngo Weinhold
3167af664c9SIngo Weinhold	if ((flags & B_FIND_INSTALLED_ONLY) != 0 && _InstalledRepository() == NULL)
31775d15eb4SIngo Weinhold		return B_BAD_VALUE;
31875d15eb4SIngo Weinhold
31975d15eb4SIngo Weinhold	// add repositories to pool
32075d15eb4SIngo Weinhold	status_t error = _AddRepositories();
32175d15eb4SIngo Weinhold	if (error != B_OK)
32275d15eb4SIngo Weinhold		return error;
32375d15eb4SIngo Weinhold
32475d15eb4SIngo Weinhold	error = _InitJobQueue();
32575d15eb4SIngo Weinhold	if (error != B_OK)
32675d15eb4SIngo Weinhold		return error;
32775d15eb4SIngo Weinhold
32875d15eb4SIngo Weinhold	// add the package specifies to the job queue
32975d15eb4SIngo Weinhold	error = _AddSpecifiedPackages(packages, _unmatched,
33075d15eb4SIngo Weinhold		(flags & B_FIND_INSTALLED_ONLY) != 0 ? SELECTION_INSTALLED_ONLY : 0);
33175d15eb4SIngo Weinhold	if (error != B_OK)
33275d15eb4SIngo Weinhold		return error;
33375d15eb4SIngo Weinhold
33475d15eb4SIngo Weinhold	return _GetFoundPackages(*fJobs, flags, _packages);
335fc57db48SIngo Weinhold}
336fc57db48SIngo Weinhold
337fc57db48SIngo Weinhold
3381a4d020dSIngo Weinholdstatus_t
3390d8ed3f2SIngo WeinholdLibsolvSolver::Install(const BSolverPackageSpecifierList& packages,
3400d8ed3f2SIngo Weinhold	const BSolverPackageSpecifier** _unmatched)
3411a4d020dSIngo Weinhold{
3420d8ed3f2SIngo Weinhold	if (_unmatched != NULL)
3430d8ed3f2SIngo Weinhold		*_unmatched = NULL;
3440d8ed3f2SIngo Weinhold
3451a4d020dSIngo Weinhold	if (packages.IsEmpty())
3461a4d020dSIngo Weinhold		return B_BAD_VALUE;
3471a4d020dSIngo Weinhold
3481a4d020dSIngo Weinhold	// add repositories to pool
3491a4d020dSIngo Weinhold	status_t error = _AddRepositories();
3501a4d020dSIngo Weinhold	if (error != B_OK)
3511a4d020dSIngo Weinhold		return error;
3521a4d020dSIngo Weinhold
3531a4d020dSIngo Weinhold	// add the packages to install to the job queue
3548e6c3631SIngo Weinhold	error = _InitJobQueue();
3558e6c3631SIngo Weinhold	if (error != B_OK)
3568e6c3631SIngo Weinhold		return error;
3571a4d020dSIngo Weinhold
358212c636fSIngo Weinhold	error = _AddSpecifiedPackages(packages, _unmatched, 0);
359212c636fSIngo Weinhold	if (error != B_OK)
360212c636fSIngo Weinhold		return error;
3611a4d020dSIngo Weinhold
36265502bbeSIngo Weinhold	// set jobs' solver mode and solve
363212c636fSIngo Weinhold	_SetJobsSolverMode(SOLVER_INSTALL);
3641a4d020dSIngo Weinhold
365de62d761SIngo Weinhold	_InitSolver();
366de62d761SIngo Weinhold	return _Solve();
367de62d761SIngo Weinhold}
368de62d761SIngo Weinhold
369de62d761SIngo Weinhold
370de62d761SIngo Weinholdstatus_t
371de62d761SIngo WeinholdLibsolvSolver::Uninstall(const BSolverPackageSpecifierList& packages,
372de62d761SIngo Weinhold	const BSolverPackageSpecifier** _unmatched)
373de62d761SIngo Weinhold{
374de62d761SIngo Weinhold	if (_unmatched != NULL)
375de62d761SIngo Weinhold		*_unmatched = NULL;
376de62d761SIngo Weinhold
3777af664c9SIngo Weinhold	if (_InstalledRepository() == NULL || packages.IsEmpty())
378de62d761SIngo Weinhold		return B_BAD_VALUE;
379de62d761SIngo Weinhold
380de62d761SIngo Weinhold	// add repositories to pool
381de62d761SIngo Weinhold	status_t error = _AddRepositories();
382de62d761SIngo Weinhold	if (error != B_OK)
383de62d761SIngo Weinhold		return error;
384de62d761SIngo Weinhold
385de62d761SIngo Weinhold	// add the packages to uninstall to the job queue
386de62d761SIngo Weinhold	error = _InitJobQueue();
387de62d761SIngo Weinhold	if (error != B_OK)
388de62d761SIngo Weinhold		return error;
389de62d761SIngo Weinhold
390212c636fSIngo Weinhold	error = _AddSpecifiedPackages(packages, _unmatched,
391212c636fSIngo Weinhold		SELECTION_INSTALLED_ONLY);
392212c636fSIngo Weinhold	if (error != B_OK)
393212c636fSIngo Weinhold		return error;
394de62d761SIngo Weinhold
395212c636fSIngo Weinhold	// set jobs' solver mode and solve
396212c636fSIngo Weinhold	_SetJobsSolverMode(SOLVER_ERASE);
397de62d761SIngo Weinhold
398212c636fSIngo Weinhold	_InitSolver();
399212c636fSIngo Weinhold	solver_set_flag(fSolver, SOLVER_FLAG_ALLOW_UNINSTALL, 1);
400212c636fSIngo Weinhold	return _Solve();
401212c636fSIngo Weinhold}
402de62d761SIngo Weinhold
403212c636fSIngo Weinhold
404212c636fSIngo Weinholdstatus_t
405212c636fSIngo WeinholdLibsolvSolver::Update(const BSolverPackageSpecifierList& packages,
406212c636fSIngo Weinhold	bool installNotYetInstalled, const BSolverPackageSpecifier** _unmatched)
407212c636fSIngo Weinhold{
408212c636fSIngo Weinhold	if (_unmatched != NULL)
409212c636fSIngo Weinhold		*_unmatched = NULL;
410212c636fSIngo Weinhold
411212c636fSIngo Weinhold	// add repositories to pool
412212c636fSIngo Weinhold	status_t error = _AddRepositories();
413212c636fSIngo Weinhold	if (error != B_OK)
414212c636fSIngo Weinhold		return error;
415212c636fSIngo Weinhold
416212c636fSIngo Weinhold	// add the packages to update to the job queue -- if none are specified,
417212c636fSIngo Weinhold	// update all
418212c636fSIngo Weinhold	error = _InitJobQueue();
419212c636fSIngo Weinhold	if (error != B_OK)
420212c636fSIngo Weinhold		return error;
421212c636fSIngo Weinhold
422212c636fSIngo Weinhold	if (packages.IsEmpty()) {
423212c636fSIngo Weinhold		queue_push2(fJobs, SOLVER_SOLVABLE_ALL, 0);
424212c636fSIngo Weinhold	} else {
425212c636fSIngo Weinhold		error = _AddSpecifiedPackages(packages, _unmatched, 0);
426212c636fSIngo Weinhold		if (error != B_OK)
427212c636fSIngo Weinhold			return error;
428de62d761SIngo Weinhold	}
429de62d761SIngo Weinhold
430de62d761SIngo Weinhold	// set jobs' solver mode and solve
431212c636fSIngo Weinhold	_SetJobsSolverMode(SOLVER_UPDATE);
432212c636fSIngo Weinhold
433212c636fSIngo Weinhold	if (installNotYetInstalled) {
434212c636fSIngo Weinhold		for (int i = 0; i < fJobs->count; i += 2) {
435212c636fSIngo Weinhold			// change solver mode to SOLVER_INSTALL for empty update jobs
436212c636fSIngo Weinhold			if (pool_isemptyupdatejob(fPool, fJobs->elements[i],
437212c636fSIngo Weinhold					fJobs->elements[i + 1])) {
438212c636fSIngo Weinhold				fJobs->elements[i] &= ~SOLVER_JOBMASK;
439212c636fSIngo Weinhold				fJobs->elements[i] |= SOLVER_INSTALL;
440212c636fSIngo Weinhold			}
441212c636fSIngo Weinhold		}
442212c636fSIngo Weinhold	}
443de62d761SIngo Weinhold
444de62d761SIngo Weinhold	_InitSolver();
445de62d761SIngo Weinhold	return _Solve();
44665502bbeSIngo Weinhold}
4471a4d020dSIngo Weinhold
4481a4d020dSIngo Weinhold
4496ef57ae2SIngo Weinholdstatus_t
4506ef57ae2SIngo WeinholdLibsolvSolver::FullSync()
4516ef57ae2SIngo Weinhold{
4526ef57ae2SIngo Weinhold	// add repositories to pool
4536ef57ae2SIngo Weinhold	status_t error = _AddRepositories();
4546ef57ae2SIngo Weinhold	if (error != B_OK)
4556ef57ae2SIngo Weinhold		return error;
4566ef57ae2SIngo Weinhold
4576ef57ae2SIngo Weinhold	// Init the job queue and specify that all packages shall be updated.
4586ef57ae2SIngo Weinhold	error = _InitJobQueue();
4596ef57ae2SIngo Weinhold	if (error != B_OK)
4606ef57ae2SIngo Weinhold		return error;
4616ef57ae2SIngo Weinhold
4626ef57ae2SIngo Weinhold	queue_push2(fJobs, SOLVER_SOLVABLE_ALL, 0);
4636ef57ae2SIngo Weinhold
4646ef57ae2SIngo Weinhold	// set jobs' solver mode and solve
4656ef57ae2SIngo Weinhold	_SetJobsSolverMode(SOLVER_DISTUPGRADE);
4666ef57ae2SIngo Weinhold
4676ef57ae2SIngo Weinhold	_InitSolver();
4686ef57ae2SIngo Weinhold	return _Solve();
4696ef57ae2SIngo Weinhold}
4706ef57ae2SIngo Weinhold
4716ef57ae2SIngo Weinhold
47265502bbeSIngo Weinholdstatus_t
47389cb0015SIngo WeinholdLibsolvSolver::VerifyInstallation(uint32 flags)
47465502bbeSIngo Weinhold{
4757af664c9SIngo Weinhold	if (_InstalledRepository() == NULL)
47665502bbeSIngo Weinhold		return B_BAD_VALUE;
4771a4d020dSIngo Weinhold
47865502bbeSIngo Weinhold	// add repositories to pool
47965502bbeSIngo Weinhold	status_t error = _AddRepositories();
48065502bbeSIngo Weinhold	if (error != B_OK)
48165502bbeSIngo Weinhold		return error;
48265502bbeSIngo Weinhold
48365502bbeSIngo Weinhold	// add the verify job to the job queue
4848e6c3631SIngo Weinhold	error = _InitJobQueue();
4858e6c3631SIngo Weinhold	if (error != B_OK)
4868e6c3631SIngo Weinhold		return error;
4878e6c3631SIngo Weinhold
4888e6c3631SIngo Weinhold	queue_push2(fJobs, SOLVER_SOLVABLE_ALL, 0);
48965502bbeSIngo Weinhold
49065502bbeSIngo Weinhold	// set jobs' solver mode and solve
491212c636fSIngo Weinhold	_SetJobsSolverMode(SOLVER_VERIFY);
4928e6c3631SIngo Weinhold
493de62d761SIngo Weinhold	_InitSolver();
49489cb0015SIngo Weinhold	if ((flags & B_VERIFY_ALLOW_UNINSTALL) != 0)
49589cb0015SIngo Weinhold		solver_set_flag(fSolver, SOLVER_FLAG_ALLOW_UNINSTALL, 1);
496de62d761SIngo Weinhold	return _Solve();
4978e6c3631SIngo Weinhold}
4988e6c3631SIngo Weinhold
4998e6c3631SIngo Weinhold
5008e6c3631SIngo Weinholdstatus_t
5018e6c3631SIngo WeinholdLibsolvSolver::SelectProblemSolution(BSolverProblem* _problem,
5028e6c3631SIngo Weinhold	const BSolverProblemSolution* _solution)
5038e6c3631SIngo Weinhold{
5048e6c3631SIngo Weinhold	if (_problem == NULL)
5058e6c3631SIngo Weinhold		return B_BAD_VALUE;
5068e6c3631SIngo Weinhold
5078e6c3631SIngo Weinhold	Problem* problem = static_cast<Problem*>(_problem);
5088e6c3631SIngo Weinhold	if (_solution == NULL) {
5098e6c3631SIngo Weinhold		problem->SetSelectedSolution(NULL);
5108e6c3631SIngo Weinhold		return B_OK;
5118e6c3631SIngo Weinhold	}
51265502bbeSIngo Weinhold
5138e6c3631SIngo Weinhold	const Solution* solution = static_cast<const Solution*>(_solution);
5148e6c3631SIngo Weinhold	if (solution->Problem() != problem)
5158e6c3631SIngo Weinhold		return B_BAD_VALUE;
5168e6c3631SIngo Weinhold
5178e6c3631SIngo Weinhold	problem->SetSelectedSolution(solution);
5188e6c3631SIngo Weinhold	return B_OK;
5198e6c3631SIngo Weinhold}
5208e6c3631SIngo Weinhold
5218e6c3631SIngo Weinhold
5228e6c3631SIngo Weinholdstatus_t
5238e6c3631SIngo WeinholdLibsolvSolver::SolveAgain()
5248e6c3631SIngo Weinhold{
5258e6c3631SIngo Weinhold	if (fSolver == NULL || fJobs == NULL)
5268e6c3631SIngo Weinhold		return B_BAD_VALUE;
5278e6c3631SIngo Weinhold
5288e6c3631SIngo Weinhold	// iterate through all problems and propagate the selected solutions
5298e6c3631SIngo Weinhold	int32 problemCount = fProblems.CountItems();
5308e6c3631SIngo Weinhold	for (int32 i = 0; i < problemCount; i++) {
5318e6c3631SIngo Weinhold		Problem* problem = fProblems.ItemAt(i);
5328e6c3631SIngo Weinhold		if (const Solution* solution = problem->SelectedSolution())
5338e6c3631SIngo Weinhold			solver_take_solution(fSolver, problem->Id(), solution->Id(), fJobs);
5348e6c3631SIngo Weinhold	}
5358e6c3631SIngo Weinhold
536de62d761SIngo Weinhold	return _Solve();
5371a4d020dSIngo Weinhold}
5381a4d020dSIngo Weinhold
5391a4d020dSIngo Weinhold
5401a4d020dSIngo Weinholdint32
5411a4d020dSIngo WeinholdLibsolvSolver::CountProblems() const
5421a4d020dSIngo Weinhold{
5431a4d020dSIngo Weinhold	return fProblems.CountItems();
5441a4d020dSIngo Weinhold}
5451a4d020dSIngo Weinhold
5461a4d020dSIngo Weinhold
5471a4d020dSIngo WeinholdBSolverProblem*
5481a4d020dSIngo WeinholdLibsolvSolver::ProblemAt(int32 index) const
5491a4d020dSIngo Weinhold{
5501a4d020dSIngo Weinhold	return fProblems.ItemAt(index);
5511a4d020dSIngo Weinhold}
5521a4d020dSIngo Weinhold
5531a4d020dSIngo Weinhold
5541a4d020dSIngo Weinholdstatus_t
5551a4d020dSIngo WeinholdLibsolvSolver::GetResult(BSolverResult& _result)
5561a4d020dSIngo Weinhold{
557483d4996SIngo Weinhold	if (fSolver == NULL || HasProblems())
5581a4d020dSIngo Weinhold		return B_BAD_VALUE;
5591a4d020dSIngo Weinhold
5601a4d020dSIngo Weinhold	_result.MakeEmpty();
5611a4d020dSIngo Weinhold
5621a4d020dSIngo Weinhold	Transaction* transaction = solver_create_transaction(fSolver);
5631a4d020dSIngo Weinhold	CObjectDeleter<Transaction> transactionDeleter(transaction,
5641a4d020dSIngo Weinhold		&transaction_free);
5651a4d020dSIngo Weinhold
5661a4d020dSIngo Weinhold	if (transaction->steps.count == 0)
5671a4d020dSIngo Weinhold		return B_OK;
5681a4d020dSIngo Weinhold
5691a4d020dSIngo Weinhold	transaction_order(transaction, 0);
5701a4d020dSIngo Weinhold
5711a4d020dSIngo Weinhold	for (int i = 0; i < transaction->steps.count; i++) {
5721a4d020dSIngo Weinhold		Id solvableId = transaction->steps.elements[i];
573d5ed97cdSIngo Weinhold		if (fPool->installed
574d5ed97cdSIngo Weinhold			&& fPool->solvables[solvableId].repo == fPool->installed) {
575d5ed97cdSIngo Weinhold			BSolverPackage* package = _GetPackage(solvableId);
576d5ed97cdSIngo Weinhold			if (package == NULL)
577d5ed97cdSIngo Weinhold				return B_ERROR;
578d5ed97cdSIngo Weinhold
579d5ed97cdSIngo Weinhold			if (!_result.AppendElement(
580d5ed97cdSIngo Weinhold					BSolverResultElement(
581d5ed97cdSIngo Weinhold						BSolverResultElement::B_TYPE_UNINSTALL, package))) {
582d5ed97cdSIngo Weinhold				return B_NO_MEMORY;
5831a4d020dSIngo Weinhold			}
584d5ed97cdSIngo Weinhold		} else {
585d5ed97cdSIngo Weinhold			BSolverPackage* package = _GetPackage(solvableId);
586d5ed97cdSIngo Weinhold			if (package == NULL)
587d5ed97cdSIngo Weinhold				return B_ERROR;
588d5ed97cdSIngo Weinhold
589d5ed97cdSIngo Weinhold			if (!_result.AppendElement(
590d5ed97cdSIngo Weinhold					BSolverResultElement(
591d5ed97cdSIngo Weinhold						BSolverResultElement::B_TYPE_INSTALL, package))) {
592d5ed97cdSIngo Weinhold				return B_NO_MEMORY;
5931a4d020dSIngo Weinhold			}
5941a4d020dSIngo Weinhold		}
5951a4d020dSIngo Weinhold	}
5961a4d020dSIngo Weinhold
5971a4d020dSIngo Weinhold	return B_OK;
5981a4d020dSIngo Weinhold}
5991a4d020dSIngo Weinhold
6001a4d020dSIngo Weinhold
601483d4996SIngo Weinholdstatus_t
602a78a2540SIngo WeinholdLibsolvSolver::_InitPool()
603483d4996SIngo Weinhold{
604a78a2540SIngo Weinhold	_CleanupPool();
605483d4996SIngo Weinhold
606483d4996SIngo Weinhold	fPool = pool_create();
607483d4996SIngo Weinhold
60874b582a4SIngo Weinhold	pool_setdebuglevel(fPool, fDebugLevel);
60974b582a4SIngo Weinhold
610483d4996SIngo Weinhold	// Set the system architecture. We use what uname() returns unless we're on
611483d4996SIngo Weinhold	// x86 gcc2.
612483d4996SIngo Weinhold	{
613483d4996SIngo Weinhold		const char* arch;
61498c6dfa4SIngo Weinhold		#ifdef HAIKU_TARGET_PLATFORM_HAIKU
61598c6dfa4SIngo Weinhold			#ifdef __HAIKU_ARCH_X86
61698c6dfa4SIngo Weinhold				#if (B_HAIKU_ABI & B_HAIKU_ABI_MAJOR) == B_HAIKU_ABI_GCC_2
61798c6dfa4SIngo Weinhold					arch = "x86_gcc2";
61898c6dfa4SIngo Weinhold				#else
61998c6dfa4SIngo Weinhold					arch = "x86";
62098c6dfa4SIngo Weinhold				#endif
621483d4996SIngo Weinhold			#else
62298c6dfa4SIngo Weinhold				struct utsname info;
62398c6dfa4SIngo Weinhold				if (uname(&info) != 0)
62498c6dfa4SIngo Weinhold					return errno;
62598c6dfa4SIngo Weinhold				arch = info.machine;
626483d4996SIngo Weinhold			#endif
627483d4996SIngo Weinhold		#else
62898c6dfa4SIngo Weinhold			arch = HAIKU_PACKAGING_ARCH;
629483d4996SIngo Weinhold		#endif
630483d4996SIngo Weinhold
631483d4996SIngo Weinhold		pool_setarchpolicy(fPool, arch);
632483d4996SIngo Weinhold	}
633483d4996SIngo Weinhold
634483d4996SIngo Weinhold	return B_OK;
635483d4996SIngo Weinhold}
636483d4996SIngo Weinhold
637483d4996SIngo Weinhold
6388e6c3631SIngo Weinholdstatus_t
6398e6c3631SIngo WeinholdLibsolvSolver::_InitJobQueue()
6408e6c3631SIngo Weinhold{
6418e6c3631SIngo Weinhold	_CleanupJobQueue();
6428e6c3631SIngo Weinhold
6438e6c3631SIngo Weinhold	fJobs = new(std::nothrow) SolvQueue;
6448e6c3631SIngo Weinhold	return fJobs != NULL ? B_OK : B_NO_MEMORY;;
6458e6c3631SIngo Weinhold}
6468e6c3631SIngo Weinhold
6478e6c3631SIngo Weinhold
648de62d761SIngo Weinholdvoid
649de62d761SIngo WeinholdLibsolvSolver::_InitSolver()
650de62d761SIngo Weinhold{
651de62d761SIngo Weinhold	_CleanupSolver();
652de62d761SIngo Weinhold
653de62d761SIngo Weinhold	fSolver = solver_create(fPool);
654de62d761SIngo Weinhold	solver_set_flag(fSolver, SOLVER_FLAG_SPLITPROVIDES, 1);
655de62d761SIngo Weinhold	solver_set_flag(fSolver, SOLVER_FLAG_BEST_OBEY_POLICY, 1);
656de62d761SIngo Weinhold}
657de62d761SIngo Weinhold
658de62d761SIngo Weinhold
6591a4d020dSIngo Weinholdvoid
6601a4d020dSIngo WeinholdLibsolvSolver::_Cleanup()
6611a4d020dSIngo Weinhold{
662a78a2540SIngo Weinhold	_CleanupPool();
663483d4996SIngo Weinhold
6641a4d020dSIngo Weinhold	fInstalledRepository = NULL;
6651a4d020dSIngo Weinhold	fRepositoryInfos.MakeEmpty();
6661a4d020dSIngo Weinhold
667a78a2540SIngo Weinhold}
668a78a2540SIngo Weinhold
669