BSolver/LibsolvSolver: Add problem solution selection support

... and re-solving.
This commit is contained in:
Ingo Weinhold 2013-04-21 02:46:26 +02:00
parent ec41ff587f
commit 8e6c3631a3
3 changed files with 129 additions and 24 deletions

View File

@ -17,6 +17,7 @@ class BSolverPackage;
class BSolverPackageSpecifier;
class BSolverPackageSpecifierList;
class BSolverProblem;
class BSolverProblemSolution;
class BSolverRepository;
class BSolverResult;
@ -58,6 +59,11 @@ public:
virtual int32 CountProblems() const = 0;
virtual BSolverProblem* ProblemAt(int32 index) const = 0;
virtual status_t SelectProblemSolution(
BSolverProblem* problem,
const BSolverProblemSolution* solution) = 0;
virtual status_t SolveAgain() = 0;
virtual status_t GetResult(BSolverResult& _result) = 0;
protected:

View File

@ -118,7 +118,8 @@ struct LibsolvSolver::Problem : public BSolverProblem {
const BPackageResolvableExpression& dependency)
:
BSolverProblem(type, sourcePackage, targetPackage, dependency),
fId(id)
fId(id),
fSelectedSolution(NULL)
{
}
@ -127,13 +128,24 @@ struct LibsolvSolver::Problem : public BSolverProblem {
return fId;
}
const Solution* SelectedSolution() const
{
return fSelectedSolution;
}
void SetSelectedSolution(const Solution* solution)
{
fSelectedSolution = solution;
}
private:
::Id fId;
::Id fId;
const Solution* fSelectedSolution;
};
struct LibsolvSolver::Solution : public BSolverProblemSolution {
Solution(::Id id, Problem* problem)
Solution(::Id id, LibsolvSolver::Problem* problem)
:
BSolverProblemSolution(),
fId(id),
@ -146,9 +158,14 @@ struct LibsolvSolver::Solution : public BSolverProblemSolution {
return fId;
}
LibsolvSolver::Problem* Problem() const
{
return fProblem;
}
private:
::Id fId;
Problem* fProblem;
::Id fId;
LibsolvSolver::Problem* fProblem;
};
@ -159,6 +176,7 @@ LibsolvSolver::LibsolvSolver()
:
fPool(NULL),
fSolver(NULL),
fJobs(NULL),
fRepositoryInfos(10, true),
fInstalledRepository(NULL),
fSolvablePackages(),
@ -299,7 +317,9 @@ LibsolvSolver::Install(const BSolverPackageSpecifierList& packages,
return error;
// add the packages to install to the job queue
SolvQueue jobs;
error = _InitJobQueue();
if (error != B_OK)
return error;
int32 packageCount = packages.CountSpecifiers();
for (int32 i = 0; i < packageCount; i++) {
@ -317,7 +337,7 @@ LibsolvSolver::Install(const BSolverPackageSpecifierList& packages,
return B_BAD_VALUE;
}
queue_push2(&jobs, SOLVER_SOLVABLE,
queue_push2(fJobs, SOLVER_SOLVABLE,
solvable - fPool->solvables);
break;
}
@ -359,15 +379,15 @@ LibsolvSolver::Install(const BSolverPackageSpecifierList& packages,
#endif
for (int j = 0; j < matchingPackages.count; j++)
queue_push(&jobs, matchingPackages.elements[j]);
queue_push(fJobs, matchingPackages.elements[j]);
}
}
}
// set jobs' solver mode and solve
_SetJobsSolverMode(jobs, SOLVER_INSTALL);
_SetJobsSolverMode(*fJobs, SOLVER_INSTALL);
return _Solve(jobs);
return _Solve(false);
}
@ -383,13 +403,56 @@ LibsolvSolver::VerifyInstallation()
return error;
// add the verify job to the job queue
SolvQueue jobs;
queue_push2(&jobs, SOLVER_SOLVABLE_ALL, 0);
error = _InitJobQueue();
if (error != B_OK)
return error;
queue_push2(fJobs, SOLVER_SOLVABLE_ALL, 0);
// set jobs' solver mode and solve
_SetJobsSolverMode(jobs, SOLVER_VERIFY);
_SetJobsSolverMode(*fJobs, SOLVER_VERIFY);
return _Solve(jobs);
return _Solve(false);
}
status_t
LibsolvSolver::SelectProblemSolution(BSolverProblem* _problem,
const BSolverProblemSolution* _solution)
{
if (_problem == NULL)
return B_BAD_VALUE;
Problem* problem = static_cast<Problem*>(_problem);
if (_solution == NULL) {
problem->SetSelectedSolution(NULL);
return B_OK;
}
const Solution* solution = static_cast<const Solution*>(_solution);
if (solution->Problem() != problem)
return B_BAD_VALUE;
problem->SetSelectedSolution(solution);
return B_OK;
}
status_t
LibsolvSolver::SolveAgain()
{
if (fSolver == NULL || fJobs == NULL)
return B_BAD_VALUE;
// iterate through all problems and propagate the selected solutions
int32 problemCount = fProblems.CountItems();
for (int32 i = 0; i < problemCount; i++) {
Problem* problem = fProblems.ItemAt(i);
if (const Solution* solution = problem->SelectedSolution())
solver_take_solution(fSolver, problem->Id(), solution->Id(), fJobs);
}
return _Solve(true);
}
@ -518,6 +581,16 @@ LibsolvSolver::_InitPool()
}
status_t
LibsolvSolver::_InitJobQueue()
{
_CleanupJobQueue();
fJobs = new(std::nothrow) SolvQueue;
return fJobs != NULL ? B_OK : B_NO_MEMORY;;
}
void
LibsolvSolver::_Cleanup()
{
@ -532,8 +605,8 @@ LibsolvSolver::_Cleanup()
void
LibsolvSolver::_CleanupPool()
{
// clean up solver data
_CleanupSolver();
// clean up jobs and solver data
_CleanupJobQueue();
// clean up our data structures that depend on/refer to libsolv pool data
fSolvablePackages.clear();
@ -551,6 +624,16 @@ LibsolvSolver::_CleanupPool()
}
void
LibsolvSolver::_CleanupJobQueue()
{
_CleanupSolver();
delete fJobs;
fJobs = NULL;
}
void
LibsolvSolver::_CleanupSolver()
{
@ -1055,16 +1138,24 @@ LibsolvSolver::_GetResolvableExpression(Id id,
status_t
LibsolvSolver::_Solve(Queue& jobs)
LibsolvSolver::_Solve(bool solveAgain)
{
_CleanupSolver();
if (fJobs == NULL)
return B_BAD_VALUE;
// create the solver and solve
fSolver = solver_create(fPool);
solver_set_flag(fSolver, SOLVER_FLAG_SPLITPROVIDES, 1);
solver_set_flag(fSolver, SOLVER_FLAG_BEST_OBEY_POLICY, 1);
if (solveAgain) {
if (fSolver == NULL)
return B_BAD_VALUE;
} else {
_CleanupSolver();
int problemCount = solver_solve(fSolver, &jobs);
// create the solver and solve
fSolver = solver_create(fPool);
solver_set_flag(fSolver, SOLVER_FLAG_SPLITPROVIDES, 1);
solver_set_flag(fSolver, SOLVER_FLAG_BEST_OBEY_POLICY, 1);
}
int problemCount = solver_solve(fSolver, fJobs);
// get the problems (if any)
fProblems.MakeEmpty();

View File

@ -48,6 +48,11 @@ public:
virtual int32 CountProblems() const;
virtual BSolverProblem* ProblemAt(int32 index) const;
virtual status_t SelectProblemSolution(
BSolverProblem* problem,
const BSolverProblemSolution* solution);
virtual status_t SolveAgain();
virtual status_t GetResult(BSolverResult& _result);
private:
@ -64,8 +69,10 @@ private:
private:
status_t _InitPool();
status_t _InitJobQueue();
void _Cleanup();
void _CleanupPool();
void _CleanupJobQueue();
void _CleanupSolver();
bool _HaveRepositoriesChanged() const;
@ -89,12 +96,13 @@ private:
BPackageResolvableExpression& _expression)
const;
status_t _Solve(Queue& jobs);
status_t _Solve(bool solveAgain);
void _SetJobsSolverMode(Queue& jobs, int solverMode);
private:
Pool* fPool;
Solver* fSolver;
SolvQueue* fJobs;
RepositoryInfoList fRepositoryInfos;
RepositoryInfo* fInstalledRepository;
SolvableMap fSolvablePackages;