package kit: Add data structures for problem solutions

... and add the problem solutions in LibsolvSolver.
This commit is contained in:
Ingo Weinhold 2013-04-09 17:24:27 +02:00
parent 1047e84f39
commit 5e01af3199
7 changed files with 539 additions and 6 deletions

View File

@ -6,6 +6,7 @@
#define _PACKAGE__SOLVER_PROBLEM_H_
#include <ObjectList.h>
#include <package/PackageResolvableExpression.h>
@ -13,6 +14,7 @@ namespace BPackageKit {
class BSolverPackage;
class BSolverProblemSolution;
class BSolverProblem {
@ -53,13 +55,23 @@ public:
BSolverPackage* TargetPackage() const;
const BPackageResolvableExpression& Dependency() const;
int32 CountSolutions() const;
const BSolverProblemSolution* SolutionAt(int32 index) const;
bool AppendSolution(
BSolverProblemSolution* solution);
BString ToString() const;
private:
typedef BObjectList<BSolverProblemSolution> SolutionList;
private:
BType fType;
BSolverPackage* fSourcePackage;
BSolverPackage* fTargetPackage;
BPackageResolvableExpression fDependency;
SolutionList fSolutions;
};

View File

@ -0,0 +1,90 @@
/*
* Copyright 2013, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _PACKAGE__SOLVER_PROBLEM_SOLUTION_H_
#define _PACKAGE__SOLVER_PROBLEM_SOLUTION_H_
#include <ObjectList.h>
#include <String.h>
namespace BPackageKit {
class BSolverPackage;
class BSolverProblemSolutionElement {
public:
enum BType {
B_UNSPECIFIED,
B_DONT_KEEP,
B_DONT_INSTALL,
B_DONT_INSTALL_MOST_RECENT,
B_DONT_FORBID_INSTALLATION,
B_DONT_DEINSTALL,
B_DONT_DEINSTALL_ALL,
B_DONT_LOCK,
B_KEEP_INFERIOR_ARCHITECTURE,
B_KEEP_EXCLUDED,
B_KEEP_OLD,
B_INSTALL_INFERIOR_ARCHITECTURE,
B_INSTALL_EXCLUDED,
B_INSTALL_OLD,
B_ALLOW_DOWNGRADE,
B_ALLOW_NAME_CHANGE,
B_ALLOW_ARCHITECTURE_CHANGE,
B_ALLOW_VENDOR_CHANGE,
B_ALLOW_REPLACEMENT,
B_ALLOW_DEINSTALLATION
};
public:
BSolverProblemSolutionElement(BType type,
BSolverPackage* sourcePackage,
BSolverPackage* targetPackage,
const BString& selection);
~BSolverProblemSolutionElement();
BType Type() const;
BSolverPackage* SourcePackage() const;
BSolverPackage* TargetPackage() const;
const BString& Selection() const;
BString ToString() const;
private:
BType fType;
BSolverPackage* fSourcePackage;
BSolverPackage* fTargetPackage;
BString fSelection;
};
class BSolverProblemSolution {
public:
typedef BSolverProblemSolutionElement Element;
public:
BSolverProblemSolution();
~BSolverProblemSolution();
int32 CountElements() const;
const Element* ElementAt(int32 index) const;
bool AppendElement(const Element& element);
private:
typedef BObjectList<Element> ElementList;
private:
ElementList fElements;
};
} // namespace BPackageKit
#endif // _PACKAGE__SOLVER_PROBLEM_SOLUTION_H_

View File

@ -83,6 +83,7 @@ SharedLibrary libpackage.so
SolverPackageSpecifier.cpp
SolverPackageSpecifierList.cpp
SolverProblem.cpp
SolverProblemSolution.cpp
SolverRepository.cpp
SolverResult.cpp
:

View File

@ -13,6 +13,7 @@
#include <new>
#include <solv/policy.h>
#include <solv/poolarch.h>
#include <solv/repo.h>
#include <solv/repo_haiku.h>
@ -85,6 +86,46 @@ private:
};
struct LibsolvSolver::Problem : public BSolverProblem {
Problem(::Id id, BType type, BSolverPackage* sourcePackage,
BSolverPackage* targetPackage,
const BPackageResolvableExpression& dependency)
:
BSolverProblem(type, sourcePackage, targetPackage, dependency),
fId(id)
{
}
::Id Id() const
{
return fId;
}
private:
::Id fId;
};
struct LibsolvSolver::Solution : public BSolverProblemSolution {
Solution(::Id id, Problem* problem)
:
BSolverProblemSolution(),
fId(id),
fProblem(problem)
{
}
::Id Id() const
{
return fId;
}
private:
::Id fId;
Problem* fProblem;
};
// #pragma mark - LibsolvSolver
@ -546,13 +587,212 @@ LibsolvSolver::_AddProblem(Id problemId)
return error;
}
BSolverProblem* problem = new(std::nothrow) BSolverProblem(problemType,
Problem* problem = new(std::nothrow) Problem(problemId, problemType,
sourcePackage, targetPackage, dependency);
if (problem == NULL || !fProblems.AddItem(problem)) {
delete problem;
return B_NO_MEMORY;
}
int solutionCount = solver_solution_count(fSolver, problemId);
for (Id solutionId = 1; solutionId <= solutionCount; solutionId++) {
status_t error = _AddSolution(problem, solutionId);
if (error != B_OK)
return error;
}
return B_OK;
}
status_t
LibsolvSolver::_AddSolution(Problem* problem, Id solutionId)
{
Solution* solution = new(std::nothrow) Solution(solutionId, problem);
if (solution == NULL || !problem->AppendSolution(solution)) {
delete solution;
return B_NO_MEMORY;
}
Id elementId = 0;
for (;;) {
Id sourceId;
Id targetId;
elementId = solver_next_solutionelement(fSolver, problem->Id(),
solutionId, elementId, &sourceId, &targetId);
if (elementId == 0)
break;
status_t error = _AddSolutionElement(solution, sourceId, targetId);
if (error != B_OK)
return error;
}
return B_OK;
}
status_t
LibsolvSolver::_AddSolutionElement(Solution* solution, Id sourceId, Id targetId)
{
typedef BSolverProblemSolutionElement Element;
if (sourceId == SOLVER_SOLUTION_JOB
|| sourceId == SOLVER_SOLUTION_POOLJOB) {
// targetId is an index into the job queue
if (sourceId == SOLVER_SOLUTION_JOB)
targetId += fSolver->pooljobcnt;
Id how = fSolver->job.elements[targetId - 1];
Id what = fSolver->job.elements[targetId];
Id select = how & SOLVER_SELECTMASK;
switch (how & SOLVER_JOBMASK) {
case SOLVER_INSTALL:
if (select == SOLVER_SOLVABLE && fInstalledRepository != NULL
&& fPool->solvables[what].repo
== fInstalledRepository->SolvRepo()) {
return _AddSolutionElement(solution, Element::B_DONT_KEEP,
fPool->solvables + what, NULL, NULL);
}
return _AddSolutionElement(solution,
Element::B_DONT_INSTALL, NULL, NULL,
solver_select2str(fPool, select, what));
case SOLVER_ERASE:
{
if (select == SOLVER_SOLVABLE
&& (fInstalledRepository == NULL
|| fPool->solvables[what].repo
!= fInstalledRepository->SolvRepo())) {
return _AddSolutionElement(solution,
Element::B_DONT_FORBID_INSTALLATION,
fPool->solvables + what, NULL, NULL);
}
Element::BType type = select == SOLVER_SOLVABLE_PROVIDES
? Element::B_DONT_DEINSTALL_ALL : Element::B_DONT_DEINSTALL;
return _AddSolutionElement(solution, type, NULL, NULL,
solver_select2str(fPool, select, what));
}
case SOLVER_UPDATE:
return _AddSolutionElement(solution,
Element::B_DONT_INSTALL_MOST_RECENT, NULL, NULL,
solver_select2str(fPool, select, what));
case SOLVER_LOCK:
return _AddSolutionElement(solution, Element::B_DONT_LOCK, NULL,
NULL, solver_select2str(fPool, select, what));
default:
return _AddSolutionElement(solution, Element::B_UNSPECIFIED,
NULL, NULL, NULL);
}
}
Solvable* target = targetId != 0 ? fPool->solvables + targetId : NULL;
bool targetInstalled = target && fInstalledRepository
&& target->repo == fInstalledRepository->SolvRepo();
if (sourceId == SOLVER_SOLUTION_INFARCH) {
return _AddSolutionElement(solution,
targetInstalled
? Element::B_KEEP_INFERIOR_ARCHITECTURE
: Element::B_INSTALL_INFERIOR_ARCHITECTURE,
target, NULL, NULL);
}
if (sourceId == SOLVER_SOLUTION_DISTUPGRADE) {
return _AddSolutionElement(solution,
targetInstalled
? Element::B_KEEP_EXCLUDED : Element::B_INSTALL_EXCLUDED,
target, NULL, NULL);
}
if (sourceId == SOLVER_SOLUTION_BEST) {
return _AddSolutionElement(solution,
targetInstalled ? Element::B_KEEP_OLD : Element::B_INSTALL_OLD,
target, NULL, NULL);
}
// replace source with target
Solvable* source = fPool->solvables + sourceId;
if (target == NULL) {
return _AddSolutionElement(solution, Element::B_ALLOW_DEINSTALLATION,
source, NULL, NULL);
}
int illegalMask = policy_is_illegal(fSolver, source, target, 0);
if ((illegalMask & POLICY_ILLEGAL_DOWNGRADE) != 0) {
status_t error = _AddSolutionElement(solution,
Element::B_ALLOW_DOWNGRADE, source, target, NULL);
if (error != B_OK)
return error;
}
if ((illegalMask & POLICY_ILLEGAL_NAMECHANGE) != 0) {
status_t error = _AddSolutionElement(solution,
Element::B_ALLOW_NAME_CHANGE, source, target, NULL);
if (error != B_OK)
return error;
}
if ((illegalMask & POLICY_ILLEGAL_ARCHCHANGE) != 0) {
status_t error = _AddSolutionElement(solution,
Element::B_ALLOW_ARCHITECTURE_CHANGE, source, target, NULL);
if (error != B_OK)
return error;
}
if ((illegalMask & POLICY_ILLEGAL_VENDORCHANGE) != 0) {
status_t error = _AddSolutionElement(solution,
Element::B_ALLOW_VENDOR_CHANGE, source, target, NULL);
if (error != B_OK)
return error;
}
if (illegalMask == 0) {
return _AddSolutionElement(solution, Element::B_ALLOW_REPLACEMENT,
source, target, NULL);
}
return B_OK;
}
status_t
LibsolvSolver::_AddSolutionElement(Solution* solution,
BSolverProblemSolutionElement::BType type, Solvable* sourceSolvable,
Solvable* targetSolvable, const char* selectionString)
{
BSolverPackage* sourcePackage = NULL;
if (sourceSolvable != NULL) {
sourcePackage = _GetPackage(sourceSolvable);
if (sourcePackage == NULL)
return B_ERROR;
}
BSolverPackage* targetPackage = NULL;
if (targetSolvable != NULL) {
targetPackage = _GetPackage(targetSolvable);
if (targetPackage == NULL)
return B_ERROR;
}
BString selection;
if (selectionString != NULL && selectionString[0] != '\0') {
selection = selectionString;
if (selection.IsEmpty())
return B_NO_MEMORY;
}
if (!solution->AppendElement(BSolverProblemSolutionElement(
type, sourcePackage, targetPackage, selection))) {
return B_NO_MEMORY;
}
return B_OK;
}

View File

@ -10,6 +10,7 @@
#include <ObjectList.h>
#include <package/solver/Solver.h>
#include <package/solver/SolverProblemSolution.h>
#include <solv/pool.h>
#include <solv/solver.h>
@ -46,9 +47,11 @@ public:
private:
struct SolvQueue;
struct RepositoryInfo;
struct Problem;
struct Solution;
typedef BObjectList<RepositoryInfo> RepositoryInfoList;
typedef BObjectList<BSolverProblem> ProblemList;
typedef BObjectList<Problem> ProblemList;
typedef std::map<Solvable*, BSolverPackage*> SolvableMap;
private:
@ -61,6 +64,14 @@ private:
BSolverPackage* _GetPackage(Id solvableId) const;
status_t _AddProblem(Id problemId);
status_t _AddSolution(Problem* problem, Id solutionId);
status_t _AddSolutionElement(Solution* solution,
Id sourceId, Id targetId);
status_t _AddSolutionElement(Solution* solution,
BSolverProblemSolutionElement::BType type,
Solvable* sourceSolvable,
Solvable* targetSolvable,
const char* selectionString);
status_t _GetResolvableExpression(Id id,
BPackageResolvableExpression& _expression)
const;

View File

@ -9,9 +9,8 @@
#include <package/solver/SolverProblem.h>
#include <stdio.h>
#include <package/solver/SolverPackage.h>
#include <package/solver/SolverProblemSolution.h>
static const char* const kToStringTexts[] = {
@ -45,7 +44,8 @@ BSolverProblem::BSolverProblem(BType type, BSolverPackage* sourcePackage,
fType(type),
fSourcePackage(sourcePackage),
fTargetPackage(targetPackage),
fDependency()
fDependency(),
fSolutions(10, true)
{
}
@ -57,7 +57,8 @@ BSolverProblem::BSolverProblem(BType type, BSolverPackage* sourcePackage,
fType(type),
fSourcePackage(sourcePackage),
fTargetPackage(targetPackage),
fDependency(dependency)
fDependency(dependency),
fSolutions(10, true)
{
}
@ -95,6 +96,27 @@ BSolverProblem::Dependency() const
}
int32
BSolverProblem::CountSolutions() const
{
return fSolutions.CountItems();
}
const BSolverProblemSolution*
BSolverProblem::SolutionAt(int32 index) const
{
return fSolutions.ItemAt(index);
}
bool
BSolverProblem::AppendSolution(BSolverProblemSolution* solution)
{
return fSolutions.AddItem(solution);
}
BString
BSolverProblem::ToString() const
{

View File

@ -0,0 +1,157 @@
/*
* Copyright 2013, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <ingo_weinhold@gmx.de>
*/
#include <package/solver/SolverProblemSolution.h>
#include <package/solver/SolverPackage.h>
static const char* const kToStringTexts[] = {
"do something",
"do not keep %source% installed",
"do not install \"%selection%\"",
"do not install the most recent version of \"%selection%\"",
"do not forbid installation of %source%",
"do not deinstall \"%selection%\"",
"do not deinstall all resolvables \"%s\"",
"do not lock \"%selection%\"",
"keep %source% despite its inferior architecture",
"keep %source% from excluded repository",
"keep old %source%",
"install %source% despite its inferior architecture",
"install %source% from excluded repository",
"install %s despite its old version",
"allow downgrade of %source% to %target%",
"allow name change of %source% to %target%",
"allow architecture change of %source% to %target%",
"allow vendor change from \"%sourceVendor%\" (%source%) to "
"\"%targetVendor%\" (%target%)",
"allow replacement of %source% with %target%",
"allow deinstallation of %source%"
};
namespace BPackageKit {
// #pragma mark - BSolverProblemSolutionElement
BSolverProblemSolutionElement::BSolverProblemSolutionElement(BType type,
BSolverPackage* sourcePackage, BSolverPackage* targetPackage,
const BString& selection)
:
fType(type),
fSourcePackage(sourcePackage),
fTargetPackage(targetPackage),
fSelection(selection)
{
}
BSolverProblemSolutionElement::~BSolverProblemSolutionElement()
{
}
BSolverProblemSolutionElement::BType
BSolverProblemSolutionElement::Type() const
{
return fType;
}
BSolverPackage*
BSolverProblemSolutionElement::SourcePackage() const
{
return fSourcePackage;
}
BSolverPackage*
BSolverProblemSolutionElement::TargetPackage() const
{
return fTargetPackage;
}
const BString&
BSolverProblemSolutionElement::Selection() const
{
return fSelection;
}
BString
BSolverProblemSolutionElement::ToString() const
{
size_t index = fType;
if (index >= sizeof(kToStringTexts) / sizeof(kToStringTexts[0]))
index = 0;
return BString(kToStringTexts[index])
.ReplaceAll("%source%",
fSourcePackage != NULL
? fSourcePackage->VersionedName().String() : "?")
.ReplaceAll("%target%",
fTargetPackage != NULL
? fTargetPackage->VersionedName().String() : "?")
.ReplaceAll("%selection%", fSelection)
.ReplaceAll("%sourceVendor%",
fSourcePackage != NULL
? fSourcePackage->Info().Vendor().String() : "?")
.ReplaceAll("%targetVendor%",
fTargetPackage != NULL
? fTargetPackage->Info().Vendor().String() : "?");
}
// #pragma mark - BSolverProblemSolution
BSolverProblemSolution::BSolverProblemSolution()
:
fElements(10, true)
{
}
BSolverProblemSolution::~BSolverProblemSolution()
{
}
int32
BSolverProblemSolution::CountElements() const
{
return fElements.CountItems();
}
const BSolverProblemSolution::Element*
BSolverProblemSolution::ElementAt(int32 index) const
{
return fElements.ItemAt(index);
}
bool
BSolverProblemSolution::AppendElement(const Element& element)
{
Element* newElement = new(std::nothrow) Element(element);
if (newElement == NULL || !fElements.AddItem(newElement)) {
delete newElement;
return false;
}
return true;
}
} // namespace BPackageKit