BSolver/LibsolvSolver: Add problem solution selection support

... and re-solving.
This commit is contained in:
Ingo Weinhold
2013-04-21 02:48:52 +02:00
parent ec41ff587f
commit 8e6c3631a3
3 changed files with 129 additions and 24 deletions
+6
View File
@@ -17,6 +17,7 @@ class BSolverPackage;
class BSolverPackageSpecifier; class BSolverPackageSpecifier;
class BSolverPackageSpecifierList; class BSolverPackageSpecifierList;
class BSolverProblem; class BSolverProblem;
class BSolverProblemSolution;
class BSolverRepository; class BSolverRepository;
class BSolverResult; class BSolverResult;
@@ -58,6 +59,11 @@ public:
virtual int32 CountProblems() const = 0; virtual int32 CountProblems() const = 0;
virtual BSolverProblem* ProblemAt(int32 index) 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; virtual status_t GetResult(BSolverResult& _result) = 0;
protected: protected:
+114 -23
View File
@@ -118,7 +118,8 @@ struct LibsolvSolver::Problem : public BSolverProblem {
const BPackageResolvableExpression& dependency) const BPackageResolvableExpression& dependency)
: :
BSolverProblem(type, sourcePackage, targetPackage, dependency), BSolverProblem(type, sourcePackage, targetPackage, dependency),
fId(id) fId(id),
fSelectedSolution(NULL)
{ {
} }
@@ -127,13 +128,24 @@ struct LibsolvSolver::Problem : public BSolverProblem {
return fId; return fId;
} }
const Solution* SelectedSolution() const
{
return fSelectedSolution;
}
void SetSelectedSolution(const Solution* solution)
{
fSelectedSolution = solution;
}
private: private:
::Id fId; ::Id fId;
const Solution* fSelectedSolution;
}; };
struct LibsolvSolver::Solution : public BSolverProblemSolution { struct LibsolvSolver::Solution : public BSolverProblemSolution {
Solution(::Id id, Problem* problem) Solution(::Id id, LibsolvSolver::Problem* problem)
: :
BSolverProblemSolution(), BSolverProblemSolution(),
fId(id), fId(id),
@@ -146,9 +158,14 @@ struct LibsolvSolver::Solution : public BSolverProblemSolution {
return fId; return fId;
} }
LibsolvSolver::Problem* Problem() const
{
return fProblem;
}
private: private:
::Id fId; ::Id fId;
Problem* fProblem; LibsolvSolver::Problem* fProblem;
}; };
@@ -159,6 +176,7 @@ LibsolvSolver::LibsolvSolver()
: :
fPool(NULL), fPool(NULL),
fSolver(NULL), fSolver(NULL),
fJobs(NULL),
fRepositoryInfos(10, true), fRepositoryInfos(10, true),
fInstalledRepository(NULL), fInstalledRepository(NULL),
fSolvablePackages(), fSolvablePackages(),
@@ -299,7 +317,9 @@ LibsolvSolver::Install(const BSolverPackageSpecifierList& packages,
return error; return error;
// add the packages to install to the job queue // add the packages to install to the job queue
SolvQueue jobs; error = _InitJobQueue();
if (error != B_OK)
return error;
int32 packageCount = packages.CountSpecifiers(); int32 packageCount = packages.CountSpecifiers();
for (int32 i = 0; i < packageCount; i++) { for (int32 i = 0; i < packageCount; i++) {
@@ -317,7 +337,7 @@ LibsolvSolver::Install(const BSolverPackageSpecifierList& packages,
return B_BAD_VALUE; return B_BAD_VALUE;
} }
queue_push2(&jobs, SOLVER_SOLVABLE, queue_push2(fJobs, SOLVER_SOLVABLE,
solvable - fPool->solvables); solvable - fPool->solvables);
break; break;
} }
@@ -359,15 +379,15 @@ LibsolvSolver::Install(const BSolverPackageSpecifierList& packages,
#endif #endif
for (int j = 0; j < matchingPackages.count; j++) 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 // 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; return error;
// add the verify job to the job queue // add the verify job to the job queue
SolvQueue jobs; error = _InitJobQueue();
queue_push2(&jobs, SOLVER_SOLVABLE_ALL, 0); if (error != B_OK)
return error;
queue_push2(fJobs, SOLVER_SOLVABLE_ALL, 0);
// set jobs' solver mode and solve // 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 void
LibsolvSolver::_Cleanup() LibsolvSolver::_Cleanup()
{ {
@@ -532,8 +605,8 @@ LibsolvSolver::_Cleanup()
void void
LibsolvSolver::_CleanupPool() LibsolvSolver::_CleanupPool()
{ {
// clean up solver data // clean up jobs and solver data
_CleanupSolver(); _CleanupJobQueue();
// clean up our data structures that depend on/refer to libsolv pool data // clean up our data structures that depend on/refer to libsolv pool data
fSolvablePackages.clear(); fSolvablePackages.clear();
@@ -551,6 +624,16 @@ LibsolvSolver::_CleanupPool()
} }
void
LibsolvSolver::_CleanupJobQueue()
{
_CleanupSolver();
delete fJobs;
fJobs = NULL;
}
void void
LibsolvSolver::_CleanupSolver() LibsolvSolver::_CleanupSolver()
{ {
@@ -1055,16 +1138,24 @@ LibsolvSolver::_GetResolvableExpression(Id id,
status_t status_t
LibsolvSolver::_Solve(Queue& jobs) LibsolvSolver::_Solve(bool solveAgain)
{ {
_CleanupSolver(); if (fJobs == NULL)
return B_BAD_VALUE;
// create the solver and solve if (solveAgain) {
fSolver = solver_create(fPool); if (fSolver == NULL)
solver_set_flag(fSolver, SOLVER_FLAG_SPLITPROVIDES, 1); return B_BAD_VALUE;
solver_set_flag(fSolver, SOLVER_FLAG_BEST_OBEY_POLICY, 1); } 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) // get the problems (if any)
fProblems.MakeEmpty(); fProblems.MakeEmpty();
+9 -1
View File
@@ -48,6 +48,11 @@ public:
virtual int32 CountProblems() const; virtual int32 CountProblems() const;
virtual BSolverProblem* ProblemAt(int32 index) 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); virtual status_t GetResult(BSolverResult& _result);
private: private:
@@ -64,8 +69,10 @@ private:
private: private:
status_t _InitPool(); status_t _InitPool();
status_t _InitJobQueue();
void _Cleanup(); void _Cleanup();
void _CleanupPool(); void _CleanupPool();
void _CleanupJobQueue();
void _CleanupSolver(); void _CleanupSolver();
bool _HaveRepositoriesChanged() const; bool _HaveRepositoriesChanged() const;
@@ -89,12 +96,13 @@ private:
BPackageResolvableExpression& _expression) BPackageResolvableExpression& _expression)
const; const;
status_t _Solve(Queue& jobs); status_t _Solve(bool solveAgain);
void _SetJobsSolverMode(Queue& jobs, int solverMode); void _SetJobsSolverMode(Queue& jobs, int solverMode);
private: private:
Pool* fPool; Pool* fPool;
Solver* fSolver; Solver* fSolver;
SolvQueue* fJobs;
RepositoryInfoList fRepositoryInfos; RepositoryInfoList fRepositoryInfos;
RepositoryInfo* fInstalledRepository; RepositoryInfo* fInstalledRepository;
SolvableMap fSolvablePackages; SolvableMap fSolvablePackages;