Commit 12bdec38 authored by Timo Teräs's avatar Timo Teräs

solver, dot: elementary provides fixes

implementation is still not near finished, but now at least it
can handle it to a minimum degree. many cases are not done right
yet, though. ref #574.
parent 99145e2c
...@@ -78,8 +78,8 @@ struct apk_db_dir_instance { ...@@ -78,8 +78,8 @@ struct apk_db_dir_instance {
gid_t gid; gid_t gid;
}; };
#define PROVIDER_FMT "%s-"BLOB_FMT #define PROVIDER_FMT "%s%s"BLOB_FMT
#define PROVIDER_PRINTF(p) (p)->pkg->name->name, BLOB_PRINTF(*(p)->version) #define PROVIDER_PRINTF(n,p) (n)->name, (p)->version->len ? "-" : "", BLOB_PRINTF(*(p)->version)
struct apk_provider { struct apk_provider {
struct apk_package *pkg; struct apk_package *pkg;
......
...@@ -518,9 +518,15 @@ riif_done: ...@@ -518,9 +518,15 @@ riif_done:
return; return;
} }
static inline void add_provider(struct apk_name *name, struct apk_provider p)
{
*apk_provider_array_add(&name->providers) = p;
}
struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package *pkg) struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package *pkg)
{ {
struct apk_package *idb; struct apk_package *idb;
int i;
if (pkg->license == NULL) if (pkg->license == NULL)
pkg->license = apk_blob_atomize(APK_BLOB_NULL); pkg->license = apk_blob_atomize(APK_BLOB_NULL);
...@@ -529,8 +535,11 @@ struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package * ...@@ -529,8 +535,11 @@ struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package *
if (idb == NULL) { if (idb == NULL) {
idb = pkg; idb = pkg;
apk_hash_insert(&db->available.packages, pkg); apk_hash_insert(&db->available.packages, pkg);
*apk_provider_array_add(&pkg->name->providers) = add_provider(pkg->name, APK_PROVIDER_FROM_PACKAGE(pkg));
APK_PROVIDER_FROM_PACKAGE(pkg); for (i = 0; i < pkg->provides->num; i++) {
struct apk_dependency *dep = &pkg->provides->item[i];
add_provider(dep->name, APK_PROVIDER_FROM_PROVIDES(pkg, dep));
}
apk_db_pkg_rdepends(db, pkg); apk_db_pkg_rdepends(db, pkg);
} else { } else {
idb->repos |= pkg->repos; idb->repos |= pkg->repos;
......
...@@ -49,6 +49,19 @@ static void start_graph(struct dot_ctx *ctx) ...@@ -49,6 +49,19 @@ static void start_graph(struct dot_ctx *ctx)
" node [shape=box];\n"); " node [shape=box];\n");
} }
static void dump_name(struct dot_ctx *ctx, struct apk_name *name)
{
if (name->state_int)
return;
name->state_int = 1;
if (name->providers->num == 0) {
start_graph(ctx);
printf(" \"%s\" [style=dashed, color=red, fontcolor=red, shape=octagon];\n",
name->name);
}
}
static int dump_pkg(struct dot_ctx *ctx, struct apk_package *pkg) static int dump_pkg(struct dot_ctx *ctx, struct apk_package *pkg)
{ {
int i, j, r, ret = 0; int i, j, r, ret = 0;
...@@ -66,40 +79,33 @@ static int dump_pkg(struct dot_ctx *ctx, struct apk_package *pkg) ...@@ -66,40 +79,33 @@ static int dump_pkg(struct dot_ctx *ctx, struct apk_package *pkg)
struct apk_dependency *dep = &pkg->depends->item[i]; struct apk_dependency *dep = &pkg->depends->item[i];
struct apk_name *name = dep->name; struct apk_name *name = dep->name;
dump_name(ctx, name);
if (name->providers->num == 0) { if (name->providers->num == 0) {
start_graph(ctx);
printf(" \"" PKG_VER_FMT "\" -> \"%s\" [color=red];\n", printf(" \"" PKG_VER_FMT "\" -> \"%s\" [color=red];\n",
PKG_VER_PRINTF(pkg), PKG_VER_PRINTF(pkg), name->name);
name->name); continue;
if (!name->state_int) { }
printf(" \"%s\" [style=dashed, color=red, fontcolor=red, shape=octagon];\n",
name->name); for (j = 0; j < name->providers->num; j++) {
name->state_int = 1; struct apk_provider *p0 = &name->providers->item[j];
}
} else { if (!apk_dep_is_provided(dep, p0))
for (j = 0; j < name->providers->num; j++) { continue;
struct apk_provider *p0 = &name->providers->item[j];
r = dump_pkg(ctx, p0->pkg);
if (!apk_dep_is_provided(dep, p0)) ret += r;
continue; if (r || (!ctx->errors_only)) {
start_graph(ctx);
r = dump_pkg(ctx, p0->pkg);
ret += r; printf(" \"" PKG_VER_FMT "\" -> \"" PKG_VER_FMT "\"[",
if (r || (!ctx->errors_only)) { PKG_VER_PRINTF(pkg),
start_graph(ctx); PKG_VER_PRINTF(p0->pkg));
if (r)
if (p0->pkg->name != dep->name) { printf("color=red,");
/* provided package */ if (p0->pkg->name != dep->name)
printf(" \"" PROVIDER_FMT "\" -> \"" PKG_VER_FMT "\"[arrowhead=inv,color=green];\n", printf("arrowhead=inv,label=\"%s\",", dep->name->name);
PROVIDER_PRINTF(p0), printf("];\n");
PKG_VER_PRINTF(p0->pkg));
}
printf(" \"" PKG_VER_FMT "\" -> \"" PROVIDER_FMT "\"%s;\n",
PKG_VER_PRINTF(pkg),
PROVIDER_PRINTF(p0),
r ? "[color=red]" : "");
}
} }
} }
} }
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include "apk_print.h" #include "apk_print.h"
//#define DEBUG_PRINT //#define DEBUG_PRINT
//#define DEBUG_CHECKS #define DEBUG_CHECKS
#ifdef DEBUG_PRINT #ifdef DEBUG_PRINT
#include <stdio.h> #include <stdio.h>
...@@ -391,7 +391,7 @@ static int get_topology_score( ...@@ -391,7 +391,7 @@ static int get_topology_score(
if (!(repos & preferred_repos)) if (!(repos & preferred_repos))
score.non_preferred_pinnings++; score.non_preferred_pinnings++;
if (ns->locked || (ns->allowed_pinning | ns->maybe_pinning) == ns->allowed_pinning) { if (ps->locked || (ns->allowed_pinning | ns->maybe_pinning) == ns->allowed_pinning) {
allowed_pinning = ns->allowed_pinning | preferred_pinning | APK_DEFAULT_PINNING_MASK; allowed_pinning = ns->allowed_pinning | preferred_pinning | APK_DEFAULT_PINNING_MASK;
allowed_repos = get_pinning_mask_repos(ss->db, allowed_pinning); allowed_repos = get_pinning_mask_repos(ss->db, allowed_pinning);
if (!(repos & allowed_repos)) { if (!(repos & allowed_repos)) {
...@@ -485,8 +485,10 @@ static void calculate_pkg_preference(struct apk_package *pkg) ...@@ -485,8 +485,10 @@ static void calculate_pkg_preference(struct apk_package *pkg)
/* FIXME: consider all provided names too */ /* FIXME: consider all provided names too */
} }
static void count_name(struct apk_solver_state *ss, struct apk_name_state *ns) static void count_name(struct apk_solver_state *ss, struct apk_name *name)
{ {
struct apk_name_state *ns = name_to_ns_alloc(name);
if (!ns->decision_counted) { if (!ns->decision_counted) {
ss->max_decisions++; ss->max_decisions++;
ns->decision_counted = 1; ns->decision_counted = 1;
...@@ -496,7 +498,7 @@ static void count_name(struct apk_solver_state *ss, struct apk_name_state *ns) ...@@ -496,7 +498,7 @@ static void count_name(struct apk_solver_state *ss, struct apk_name_state *ns)
static void sort_hard_dependencies(struct apk_solver_state *ss, struct apk_package *pkg) static void sort_hard_dependencies(struct apk_solver_state *ss, struct apk_package *pkg)
{ {
struct apk_package_state *ps; struct apk_package_state *ps;
struct apk_name_state *ns; int i;
if (pkg->state_ptr == NULL) if (pkg->state_ptr == NULL)
pkg->state_ptr = calloc(1, sizeof(struct apk_package_state)); pkg->state_ptr = calloc(1, sizeof(struct apk_package_state));
...@@ -513,8 +515,9 @@ static void sort_hard_dependencies(struct apk_solver_state *ss, struct apk_packa ...@@ -513,8 +515,9 @@ static void sort_hard_dependencies(struct apk_solver_state *ss, struct apk_packa
foreach_dependency_pkg(ss, pkg->install_if, sort_hard_dependencies); foreach_dependency_pkg(ss, pkg->install_if, sort_hard_dependencies);
ss->max_decisions++; ss->max_decisions++;
ns = name_to_ns_alloc(pkg->name); count_name(ss, pkg->name);
count_name(ss, ns); for (i = 0; i < pkg->provides->num; i++)
count_name(ss, pkg->provides->item[i].name);
ps->topology_soft = pkg->topology_hard = ++ss->num_topology_positions; ps->topology_soft = pkg->topology_hard = ++ss->num_topology_positions;
dbg_printf(PKG_VER_FMT ": topology_hard=%d\n", dbg_printf(PKG_VER_FMT ": topology_hard=%d\n",
...@@ -584,7 +587,7 @@ static void sort_name(struct apk_solver_state *ss, struct apk_name *name) ...@@ -584,7 +587,7 @@ static void sort_name(struct apk_solver_state *ss, struct apk_name *name)
for (i = 0; i < name->providers->num; i++) for (i = 0; i < name->providers->num; i++)
sort_soft_dependencies(ss, name->providers->item[i].pkg); sort_soft_dependencies(ss, name->providers->item[i].pkg);
count_name(ss, ns); count_name(ss, name);
recalculate_maybe(ss, name, recalculate_maybe(ss, name,
ns->solver_flags_local & ns->solver_flags_local_mask, ns->solver_flags_local & ns->solver_flags_local_mask,
ns->maybe_pinning); ns->maybe_pinning);
...@@ -664,7 +667,8 @@ static void demote_name(struct apk_solver_state *ss, struct apk_name *name) ...@@ -664,7 +667,8 @@ static void demote_name(struct apk_solver_state *ss, struct apk_name *name)
dbg_printf("%s: not required\n", name->name); dbg_printf("%s: not required\n", name->name);
} }
} else { } else {
ns->name_touched = 1; /* still needed, put back to list */
promote_name(ss, name);
} }
} }
...@@ -746,6 +750,33 @@ static void untrigger_install_if(struct apk_solver_state *ss, ...@@ -746,6 +750,33 @@ static void untrigger_install_if(struct apk_solver_state *ss,
} }
} }
static inline void assign_name(
struct apk_solver_state *ss, struct apk_name *name, struct apk_provider p)
{
struct apk_name_state *ns = name_to_ns(name);
ASSERT(!ns->locked, "Assigning locked name");
ns->locked = 1;
ns->chosen = p;
if (list_hashed(&ns->unsolved_list)) {
list_del(&ns->unsolved_list);
list_init(&ns->unsolved_list);
}
}
static inline void unassign_name(struct apk_solver_state *ss, struct apk_name *name)
{
struct apk_name_state *ns = name_to_ns(name);
ASSERT(ns->locked, "Unassigning unlocked name");
ns->locked = 0;
ns->chosen = CHOSEN_NONE;
ns->name_touched = 1;
demote_name(ss, name);
}
static solver_result_t apply_decision(struct apk_solver_state *ss, static solver_result_t apply_decision(struct apk_solver_state *ss,
struct apk_decision *d) struct apk_decision *d)
{ {
...@@ -753,6 +784,7 @@ static solver_result_t apply_decision(struct apk_solver_state *ss, ...@@ -753,6 +784,7 @@ static solver_result_t apply_decision(struct apk_solver_state *ss,
struct apk_name_state *ns = name_to_ns(name); struct apk_name_state *ns = name_to_ns(name);
struct apk_package *pkg = decision_to_pkg(d); struct apk_package *pkg = decision_to_pkg(d);
struct apk_score score; struct apk_score score;
int i;
ns->name_touched = 1; ns->name_touched = 1;
if (pkg != NULL) { if (pkg != NULL) {
...@@ -782,7 +814,6 @@ static solver_result_t apply_decision(struct apk_solver_state *ss, ...@@ -782,7 +814,6 @@ static solver_result_t apply_decision(struct apk_solver_state *ss,
subscore(&ss->minimum_penalty, &ns->minimum_penalty); subscore(&ss->minimum_penalty, &ns->minimum_penalty);
ns->minimum_penalty = (struct apk_score) { .score = 0 }; ns->minimum_penalty = (struct apk_score) { .score = 0 };
ns->locked = 1;
get_topology_score(ss, ns, pkg, &score); get_topology_score(ss, ns, pkg, &score);
addscore(&ss->score, &score); addscore(&ss->score, &score);
...@@ -794,16 +825,16 @@ static solver_result_t apply_decision(struct apk_solver_state *ss, ...@@ -794,16 +825,16 @@ static solver_result_t apply_decision(struct apk_solver_state *ss,
SCORE_PRINTF(&ss->best_score)); SCORE_PRINTF(&ss->best_score));
subscore(&ss->score, &score); subscore(&ss->score, &score);
ns->locked = 0;
return SOLVERR_PRUNED; return SOLVERR_PRUNED;
} }
ss->assigned_names++; ss->assigned_names++;
ns->chosen = APK_PROVIDER_FROM_PACKAGE(pkg); assign_name(ss, name, APK_PROVIDER_FROM_PACKAGE(pkg));
for (i = 0; i < pkg->provides->num; i++) {
list_del(&ns->unsolved_list); struct apk_dependency *p = &pkg->provides->item[i];
list_init(&ns->unsolved_list); assign_name(ss, p->name, APK_PROVIDER_FROM_PROVIDES(pkg, p));
}
foreach_dependency(ss, pkg->depends, apply_constraint); foreach_dependency(ss, pkg->depends, apply_constraint);
foreach_rinstall_if_pkg(ss, pkg, trigger_install_if); foreach_rinstall_if_pkg(ss, pkg, trigger_install_if);
...@@ -849,6 +880,7 @@ static void undo_decision(struct apk_solver_state *ss, ...@@ -849,6 +880,7 @@ static void undo_decision(struct apk_solver_state *ss,
struct apk_name_state *ns = name_to_ns(name); struct apk_name_state *ns = name_to_ns(name);
struct apk_package *pkg = decision_to_pkg(d); struct apk_package *pkg = decision_to_pkg(d);
struct apk_score score; struct apk_score score;
int i;
ns->name_touched = 1; ns->name_touched = 1;
...@@ -867,12 +899,18 @@ static void undo_decision(struct apk_solver_state *ss, ...@@ -867,12 +899,18 @@ static void undo_decision(struct apk_solver_state *ss,
} }
if (ns->locked) { if (ns->locked) {
ss->assigned_names--;
foreach_rinstall_if_pkg(ss, pkg, untrigger_install_if); foreach_rinstall_if_pkg(ss, pkg, untrigger_install_if);
foreach_dependency(ss, pkg->depends, undo_constraint); foreach_dependency(ss, pkg->depends, undo_constraint);
get_topology_score(ss, ns, pkg, &score); get_topology_score(ss, ns, pkg, &score);
subscore(&ss->score, &score); subscore(&ss->score, &score);
unassign_name(ss, name);
for (i = 0; i < pkg->provides->num; i++) {
struct apk_dependency *p = &pkg->provides->item[i];
unassign_name(ss, p->name);
}
ss->assigned_names--;
} }
ps->locked = 0; ps->locked = 0;
} else { } else {
...@@ -886,13 +924,11 @@ static void undo_decision(struct apk_solver_state *ss, ...@@ -886,13 +924,11 @@ static void undo_decision(struct apk_solver_state *ss,
} else { } else {
ns->none_excluded = 0; ns->none_excluded = 0;
} }
}
ns->locked = 0; /* Put back the name to unsolved list */
ns->chosen = CHOSEN_NONE; ns->locked = 0;
promote_name(ss, name);
/* Put back the name to unsolved list */ }
promote_name(ss, name);
} }
static solver_result_t push_decision(struct apk_solver_state *ss, static solver_result_t push_decision(struct apk_solver_state *ss,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment