summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/apk_database.h22
-rw-r--r--src/apk_provider_data.h27
-rw-r--r--src/apk_solver.h3
-rw-r--r--src/apk_solver_data.h45
-rw-r--r--src/solver.c359
5 files changed, 220 insertions, 236 deletions
diff --git a/src/apk_database.h b/src/apk_database.h
index 137063b..7b1d20d 100644
--- a/src/apk_database.h
+++ b/src/apk_database.h
@@ -18,6 +18,9 @@
#include "apk_package.h"
#include "apk_io.h"
+#include "apk_provider_data.h"
+#include "apk_solver_data.h"
+
extern const char * const apk_index_gz;
extern const char * const apkindex_tar_gz;
@@ -78,25 +81,18 @@ struct apk_db_dir_instance {
gid_t gid;
};
-#define PROVIDER_FMT "%s%s"BLOB_FMT
-#define PROVIDER_PRINTF(n,p) (n)->name, (p)->version->len ? "-" : "", BLOB_PRINTF(*(p)->version)
-
-struct apk_provider {
- struct apk_package *pkg;
- apk_blob_t *version;
-};
-APK_ARRAY(apk_provider_array, struct apk_provider);
-
struct apk_name {
apk_hash_node hash_node;
- union {
- int state_int;
- void *state_ptr;
- };
char *name;
struct apk_provider_array *providers;
struct apk_name_array *rdepends;
struct apk_name_array *rinstall_if;
+
+ union {
+ struct apk_solver_name_state ss;
+ void *state_ptr;
+ int state_int;
+ };
};
struct apk_repository {
diff --git a/src/apk_provider_data.h b/src/apk_provider_data.h
new file mode 100644
index 0000000..15fba5c
--- /dev/null
+++ b/src/apk_provider_data.h
@@ -0,0 +1,27 @@
+/* apk_provider_data.h - Alpine Package Keeper (APK)
+ *
+ * Copyright (C) 2005-2008 Natanael Copa <n@tanael.org>
+ * Copyright (C) 2008-2012 Timo Teräs <timo.teras@iki.fi>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation. See http://www.gnu.org/ for details.
+ */
+
+#ifndef APK_PROVIDER_DATA_H
+#define APK_PROVIDER_DATA_H
+
+#include "apk_defines.h"
+#include "apk_blob.h"
+
+struct apk_provider {
+ struct apk_package *pkg;
+ apk_blob_t *version;
+};
+APK_ARRAY(apk_provider_array, struct apk_provider);
+
+#define PROVIDER_FMT "%s%s"BLOB_FMT
+#define PROVIDER_PRINTF(n,p) (n)->name, (p)->version->len ? "-" : "", BLOB_PRINTF(*(p)->version)
+
+#endif
diff --git a/src/apk_solver.h b/src/apk_solver.h
index 4ecb9a7..c839f7b 100644
--- a/src/apk_solver.h
+++ b/src/apk_solver.h
@@ -12,6 +12,9 @@
#ifndef APK_SOLVER_H
#define APK_SOLVER_H
+struct apk_name;
+struct apk_package;
+
struct apk_solution_entry {
struct apk_package *pkg;
unsigned short repository_tag : 15;
diff --git a/src/apk_solver_data.h b/src/apk_solver_data.h
new file mode 100644
index 0000000..fd79e65
--- /dev/null
+++ b/src/apk_solver_data.h
@@ -0,0 +1,45 @@
+/* apk_solver_data.h - Alpine Package Keeper (APK)
+ *
+ * Copyright (C) 2005-2008 Natanael Copa <n@tanael.org>
+ * Copyright (C) 2008-2012 Timo Teräs <timo.teras@iki.fi>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation. See http://www.gnu.org/ for details.
+ */
+
+#ifndef APK_SOLVER_DATA_H
+#define APK_SOLVER_DATA_H
+
+#include "apk_defines.h"
+#include "apk_provider_data.h"
+
+struct apk_solver_name_state {
+ /* dynamic */
+ struct list_head unsolved_list;
+ struct apk_provider chosen;
+
+ unsigned int last_touched_decision;
+ unsigned short requirers;
+ unsigned short install_ifs;
+ unsigned short preferred_pinning;
+ unsigned short locked;
+
+ /* one time prepare/finish flags */
+ unsigned solver_flags_local : 4;
+ unsigned solver_flags_inheritable : 4;
+
+ unsigned decision_counted : 1;
+ unsigned originally_installed : 1;
+ unsigned has_available_pkgs : 1;
+ unsigned in_changeset : 1;
+ unsigned in_world_dependency : 1;
+
+ /* dynamic state flags */
+ unsigned none_excluded : 1;
+ unsigned name_touched : 1;
+ unsigned preferred_chosen : 1;
+};
+
+#endif
diff --git a/src/solver.c b/src/solver.c
index 7420359..3da4286 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -109,34 +109,6 @@ struct apk_package_state {
#define CHOSEN_NONE (struct apk_provider) { .pkg = NULL, .version = NULL }
-struct apk_name_state {
- /* dynamic */
- struct list_head unsolved_list;
- struct apk_name *name;
- struct apk_provider chosen;
-
- unsigned int last_touched_decision;
- unsigned short requirers;
- unsigned short install_ifs;
- unsigned short preferred_pinning;
- unsigned short locked;
-
- /* one time prepare/finish flags */
- unsigned solver_flags_local : 4;
- unsigned solver_flags_inheritable : 4;
-
- unsigned decision_counted : 1;
- unsigned originally_installed : 1;
- unsigned has_available_pkgs : 1;
- unsigned in_changeset : 1;
- unsigned in_world_dependency : 1;
-
- /* dynamic state flags */
- unsigned none_excluded : 1;
- unsigned name_touched : 1;
- unsigned preferred_chosen : 1;
-};
-
struct apk_solver_state {
struct apk_database *db;
struct apk_decision *decisions;
@@ -247,32 +219,6 @@ static struct apk_package_state *pkg_to_ps_alloc(struct apk_package *pkg)
return pkg_to_ps(pkg);
}
-static struct apk_name_state *name_to_ns(struct apk_name *name)
-{
- return (struct apk_name_state*) name->state_ptr;
-}
-
-static struct apk_name_state *name_to_ns_alloc(struct apk_name *name)
-{
- struct apk_name_state *ns;
- int i;
-
- if (name->state_ptr == NULL) {
- ns = calloc(1, sizeof(struct apk_name_state));
- ns->name = name;
- for (i = 0; i < name->providers->num; i++) {
- if (name->providers->item[i].pkg->repos != 0) {
- ns->has_available_pkgs = 1;
- break;
- }
- }
- name->state_ptr = ns;
- } else {
- ns = (struct apk_name_state*) name->state_ptr;
- }
- return ns;
-}
-
static inline int pkg_available(struct apk_database *db, struct apk_package *pkg)
{
/* virtual packages - only deps used; no real .apk */
@@ -358,10 +304,10 @@ static unsigned int get_pinning_mask_repos(struct apk_database *db, unsigned sho
static int get_topology_score(
struct apk_solver_state *ss,
- struct apk_name_state *ns,
struct apk_package *pkg,
struct apk_score *_score)
{
+ struct apk_name *name = pkg->name;
struct apk_package_state *ps = pkg_to_ps(pkg);
struct apk_score score;
unsigned int repos;
@@ -376,21 +322,21 @@ static int get_topology_score(
if (ss->solver_flags & APK_SOLVERF_AVAILABLE) {
/* available preferred */
- if ((pkg->repos == 0) && ns->has_available_pkgs)
+ if ((pkg->repos == 0) && name->ss.has_available_pkgs)
score.non_preferred_actions++;
} else if (ps->inherited_reinstall ||
- (((ns->solver_flags_local|ss->solver_flags) & APK_SOLVERF_REINSTALL))) {
+ (((name->ss.solver_flags_local|ss->solver_flags) & APK_SOLVERF_REINSTALL))) {
/* reinstall requested, but not available */
if (!pkg_available(ss->db, pkg))
score.non_preferred_actions++;
} else if (ps->inherited_upgrade ||
- ((ns->solver_flags_local|ss->solver_flags) & APK_SOLVERF_UPGRADE)) {
+ ((name->ss.solver_flags_local|ss->solver_flags) & APK_SOLVERF_UPGRADE)) {
/* upgrading - score is just locked here */
} else if ((ps->inherited_upgrade == 0) &&
- ((ns->solver_flags_local|ss->solver_flags) & APK_SOLVERF_UPGRADE) == 0 &&
+ ((name->ss.solver_flags_local|ss->solver_flags) & APK_SOLVERF_UPGRADE) == 0 &&
((ps->solver_flags_maybe & APK_SOLVERF_UPGRADE) == 0 || (ps->locked))) {
/* not upgrading: it is not preferred to change package */
- if (pkg->ipkg == NULL && ns->originally_installed)
+ if (pkg->ipkg == NULL && name->ss.originally_installed)
score.non_preferred_actions++;
else
sticky_installed = TRUE;
@@ -399,7 +345,7 @@ static int get_topology_score(
}
repos = pkg->repos | (pkg->ipkg ? ss->db->repo_tags[pkg->ipkg->repository_tag].allowed_repos : 0);
- preferred_pinning = ns->preferred_pinning ?: APK_DEFAULT_PINNING_MASK;
+ preferred_pinning = name->ss.preferred_pinning ?: APK_DEFAULT_PINNING_MASK;
preferred_repos = get_pinning_mask_repos(ss->db, preferred_pinning);
if (!(repos & preferred_repos))
@@ -483,11 +429,9 @@ static void calculate_pkg_preference(struct apk_package *pkg)
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 (!name->ss.decision_counted) {
ss->max_decisions++;
- ns->decision_counted = 1;
+ name->ss.decision_counted = 1;
}
}
@@ -495,6 +439,7 @@ static void sort_hard_dependencies(struct apk_solver_state *ss,
struct apk_package *pkg,
struct apk_package *parent_pkg)
{
+ struct apk_name *name = pkg->name;
struct apk_package_state *ps;
int i;
@@ -511,9 +456,12 @@ static void sort_hard_dependencies(struct apk_solver_state *ss,
foreach_dependency_pkg(ss, pkg, pkg->install_if, sort_hard_dependencies);
ss->max_decisions++;
- count_name(ss, pkg->name);
- for (i = 0; i < pkg->provides->num; i++)
+ name->ss.has_available_pkgs = 1;
+ count_name(ss, name);
+ for (i = 0; i < pkg->provides->num; i++) {
+ pkg->provides->item[i].name->ss.has_available_pkgs = 1;
count_name(ss, pkg->provides->item[i].name);
+ }
ps->topology_soft = pkg->topology_hard = ++ss->num_topology_positions;
dbg_printf(PKG_VER_FMT ": topology_hard=%d\n",
@@ -560,7 +508,6 @@ static void update_allowed(struct apk_database *db, struct apk_package *pkg)
static void sort_name(struct apk_solver_state *ss, struct apk_name *name)
{
- struct apk_name_state *ns = name_to_ns_alloc(name);
int i, j;
for (i = 0; i < name->providers->num; i++) {
@@ -568,8 +515,8 @@ static void sort_name(struct apk_solver_state *ss, struct apk_name *name)
struct apk_package_state *ps = pkg_to_ps_alloc(pkg);
unsigned short allowed_pinning;
- ps->allowed_pinning |= ns->preferred_pinning;
- ps->allowed_pinning_maybe |= ns->preferred_pinning;
+ ps->allowed_pinning |= name->ss.preferred_pinning;
+ ps->allowed_pinning_maybe |= name->ss.preferred_pinning;
allowed_pinning = ps->allowed_pinning;
for (j = 0; allowed_pinning; j++) {
@@ -593,18 +540,13 @@ static void foreach_dependency(struct apk_solver_state *ss, struct apk_dependenc
static int install_if_missing(struct apk_solver_state *ss, struct apk_package *pkg)
{
- struct apk_name_state *ns;
int i, missing = 0;
for (i = 0; i < pkg->install_if->num; i++) {
struct apk_dependency *dep = &pkg->install_if->item[i];
+ struct apk_name *name = dep->name;
- ns = name_to_ns(dep->name);
-
- /* ns can be NULL, if the install_if has a name with
- * no packages */
- if (ns == NULL || !ns->locked ||
- !apk_dep_is_provided(dep, &ns->chosen))
+ if (!name->ss.locked || !apk_dep_is_provided(dep, &name->ss.chosen))
missing++;
}
@@ -613,45 +555,39 @@ static int install_if_missing(struct apk_solver_state *ss, struct apk_package *p
static void get_unassigned_score(struct apk_name *name, struct apk_score *score)
{
- struct apk_name_state *ns = name_to_ns(name);
-
*score = (struct apk_score){
- .conflicts = ns->requirers,
+ .conflicts = name->ss.requirers,
.preference = name->providers->num,
};
}
static void promote_name(struct apk_solver_state *ss, struct apk_name *name)
{
- struct apk_name_state *ns = name_to_ns(name);
-
- if (ns->locked)
+ if (name->ss.locked)
return;
/* queue for handling if needed */
- if (!list_hashed(&ns->unsolved_list))
- list_add_tail(&ns->unsolved_list, &ss->unsolved_list_head);
+ if (!list_hashed(&name->ss.unsolved_list))
+ list_add_tail(&name->ss.unsolved_list, &ss->unsolved_list_head);
/* update info, but no cached information flush is required, as
* minimum_penalty can only go up */
- ns->name_touched = 1;
+ name->ss.name_touched = 1;
}
static void demote_name(struct apk_solver_state *ss, struct apk_name *name)
{
- struct apk_name_state *ns = name_to_ns(name);
-
- if (ns->locked)
+ if (name->ss.locked)
return;
/* remove cached information */
- ns->chosen = CHOSEN_NONE;
+ name->ss.chosen = CHOSEN_NONE;
/* and remove list, or request refresh */
- if (ns->requirers == 0 && ns->install_ifs == 0) {
- if (list_hashed(&ns->unsolved_list)) {
- list_del(&ns->unsolved_list);
- list_init(&ns->unsolved_list);
+ if (name->ss.requirers == 0 && name->ss.install_ifs == 0) {
+ if (list_hashed(&name->ss.unsolved_list)) {
+ list_del(&name->ss.unsolved_list);
+ list_init(&name->ss.unsolved_list);
dbg_printf("%s: not required\n", name->name);
}
} else {
@@ -662,18 +598,18 @@ static void demote_name(struct apk_solver_state *ss, struct apk_name *name)
static int inherit_package_state(struct apk_database *db, struct apk_package *to, struct apk_package *from)
{
+ struct apk_name *fname = from->name;
struct apk_package_state *tps = pkg_to_ps(to);
- struct apk_name_state *fns = name_to_ns(from->name);
struct apk_package_state *fps = pkg_to_ps(from);
int i, changed = 0;
- if ((fns->solver_flags_inheritable & APK_SOLVERF_REINSTALL) ||
+ if ((fname->ss.solver_flags_inheritable & APK_SOLVERF_REINSTALL) ||
fps->inherited_reinstall) {
tps->inherited_reinstall++;
changed = 1;
}
- if ((fns->solver_flags_inheritable & APK_SOLVERF_UPGRADE) ||
+ if ((fname->ss.solver_flags_inheritable & APK_SOLVERF_UPGRADE) ||
fps->inherited_upgrade) {
tps->inherited_upgrade++;
changed = 1;
@@ -699,16 +635,16 @@ static int inherit_package_state(struct apk_database *db, struct apk_package *to
static void uninherit_package_state(struct apk_database *db, struct apk_package *to, struct apk_package *from)
{
+ struct apk_name *fname = from->name;
struct apk_package_state *tps = pkg_to_ps(to);
- struct apk_name_state *fns = name_to_ns(from->name);
struct apk_package_state *fps = pkg_to_ps(from);
int i, changed = 0;
- if ((fns->solver_flags_inheritable & APK_SOLVERF_REINSTALL) ||
+ if ((fname->ss.solver_flags_inheritable & APK_SOLVERF_REINSTALL) ||
fps->inherited_reinstall)
tps->inherited_reinstall--;
- if ((fns->solver_flags_inheritable & APK_SOLVERF_UPGRADE) ||
+ if ((fname->ss.solver_flags_inheritable & APK_SOLVERF_UPGRADE) ||
fps->inherited_upgrade)
tps->inherited_upgrade--;
@@ -732,14 +668,14 @@ static void trigger_install_if(struct apk_solver_state *ss,
struct apk_package *pkg,
struct apk_package *parent_pkg)
{
- if (install_if_missing(ss, pkg) == 0) {
- struct apk_name_state *ns = name_to_ns(pkg->name);
+ struct apk_name *name = pkg->name;
+ if (install_if_missing(ss, pkg) == 0) {
dbg_printf("trigger_install_if: " PKG_VER_FMT " triggered\n",
PKG_VER_PRINTF(pkg));
- ns->install_ifs++;
+ name->ss.install_ifs++;
inherit_package_state(ss->db, pkg, parent_pkg);
- promote_name(ss, pkg->name);
+ promote_name(ss, name);
}
}
@@ -747,45 +683,41 @@ static void untrigger_install_if(struct apk_solver_state *ss,
struct apk_package *pkg,
struct apk_package *parent_pkg)
{
- if (install_if_missing(ss, pkg) != 1) {
- struct apk_name_state *ns = name_to_ns(pkg->name);
+ struct apk_name *name = pkg->name;
+ if (install_if_missing(ss, pkg) != 1) {
dbg_printf("untrigger_install_if: " PKG_VER_FMT " no longer triggered\n",
PKG_VER_PRINTF(pkg));
- ns->install_ifs--;
+ name->ss.install_ifs--;
uninherit_package_state(ss->db, pkg, parent_pkg);
- demote_name(ss, pkg->name);
+ demote_name(ss, name);
}
}
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);
-
if (p.version == &apk_null_blob) {
- ASSERT(!ns->locked || ns->chosen.version == &apk_null_blob,
+ ASSERT(!name->ss.locked || name->ss.chosen.version == &apk_null_blob,
"Assigning locked name with version");
} else {
- ASSERT(!ns->locked, "Assigning locked name");
+ ASSERT(!name->ss.locked, "Assigning locked name");
}
- ns->chosen = p;
- ns->locked++;
- if (list_hashed(&ns->unsolved_list)) {
- list_del(&ns->unsolved_list);
- list_init(&ns->unsolved_list);
+ name->ss.chosen = p;
+ name->ss.locked++;
+ if (list_hashed(&name->ss.unsolved_list)) {
+ list_del(&name->ss.unsolved_list);
+ list_init(&name->ss.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--;
- if (ns->locked == 0) {
- ns->chosen = CHOSEN_NONE;
- ns->name_touched = 1;
+ ASSERT(name->ss.locked, "Unassigning unlocked name");
+ name->ss.locked--;
+ if (name->ss.locked == 0) {
+ name->ss.chosen = CHOSEN_NONE;
+ name->ss.name_touched = 1;
demote_name(ss, name);
}
}
@@ -794,13 +726,12 @@ static solver_result_t apply_decision(struct apk_solver_state *ss,
struct apk_decision *d)
{
struct apk_name *name = decision_to_name(d);
- struct apk_name_state *ns = name_to_ns(name);
struct apk_package *pkg = decision_to_pkg(d);
struct apk_score score;
int i;
ss->impossible_state = 0;
- ns->name_touched = 1;
+ name->ss.name_touched = 1;
if (pkg != NULL) {
struct apk_package_state *ps = pkg_to_ps(pkg);
@@ -809,7 +740,7 @@ static solver_result_t apply_decision(struct apk_solver_state *ss,
(d->type == DECISION_ASSIGN) ? "ASSIGN" : "EXCLUDE");
for (i = 0; i < pkg->provides->num; i++)
- name_to_ns(pkg->provides->item[i].name)->name_touched = 1;
+ pkg->provides->item[i].name->ss.name_touched = 1;
ps->locked = 1;
ps->handle_install_if = 0;
@@ -828,7 +759,7 @@ static solver_result_t apply_decision(struct apk_solver_state *ss,
}
if (d->type == DECISION_ASSIGN) {
- get_topology_score(ss, ns, pkg, &score);
+ get_topology_score(ss, pkg, &score);
addscore(&ss->score, &score);
ss->assigned_names++;
@@ -850,12 +781,12 @@ static solver_result_t apply_decision(struct apk_solver_state *ss,
get_unassigned_score(name, &score);
addscore(&ss->score, &score);
- ns->chosen = CHOSEN_NONE;
- ns->locked = 1;
- list_del(&ns->unsolved_list);
- list_init(&ns->unsolved_list);
+ name->ss.chosen = CHOSEN_NONE;
+ name->ss.locked = 1;
+ list_del(&name->ss.unsolved_list);
+ list_init(&name->ss.unsolved_list);
} else {
- ns->none_excluded = 1;
+ name->ss.none_excluded = 1;
}
}
@@ -882,12 +813,11 @@ static void undo_decision(struct apk_solver_state *ss,
struct apk_decision *d)
{
struct apk_name *name = decision_to_name(d);
- struct apk_name_state *ns = name_to_ns(name);
struct apk_package *pkg = decision_to_pkg(d);
struct apk_score score;
int i;
- ns->name_touched = 1;
+ name->ss.name_touched = 1;
if (pkg != NULL) {
struct apk_package_state *ps = pkg_to_ps(pkg);
@@ -904,13 +834,13 @@ static void undo_decision(struct apk_solver_state *ss,
}
for (i = 0; i < pkg->provides->num; i++)
- name_to_ns(pkg->provides->item[i].name)->name_touched = 1;
+ pkg->provides->item[i].name->ss.name_touched = 1;
- if (ns->locked) {
+ if (name->ss.locked) {
foreach_rinstall_if_pkg(ss, pkg, untrigger_install_if);
foreach_dependency(ss, pkg->depends, undo_constraint);
- get_topology_score(ss, ns, pkg, &score);
+ get_topology_score(ss, pkg, &score);
subscore(&ss->score, &score);
unassign_name(ss, name);
@@ -930,11 +860,11 @@ static void undo_decision(struct apk_solver_state *ss,
get_unassigned_score(name, &score);
subscore(&ss->score, &score);
} else {
- ns->none_excluded = 0;
+ name->ss.none_excluded = 0;
}
/* Put back the name to unsolved list */
- ns->locked = 0;
+ name->ss.locked = 0;
promote_name(ss, name);
}
}
@@ -956,7 +886,7 @@ static solver_result_t push_decision(struct apk_solver_state *ss,
#ifdef DEBUG_CHECKS
d->saved_score = ss->score;
- d->saved_requirers = name_to_ns(name)->requirers;
+ d->saved_requirers = name->ss.requirers;
#endif
d->type = primary_decision;
d->branching_point = branching_point;
@@ -980,7 +910,6 @@ static int next_branch(struct apk_solver_state *ss)
while (ss->num_decisions > 0) {
struct apk_decision *d = &ss->decisions[ss->num_decisions];
struct apk_name *name = decision_to_name(d);
- struct apk_name_state *ns = name_to_ns(name);
undo_decision(ss, d);
@@ -989,7 +918,7 @@ static int next_branch(struct apk_solver_state *ss)
"ERROR! saved_score "SCORE_FMT" != score "SCORE_FMT,
SCORE_PRINTF(&d->saved_score),
SCORE_PRINTF(&ss->score));
- ASSERT(d->saved_requirers == ns->requirers,
+ ASSERT(d->saved_requirers == name->ss.requirers,
"ERROR! requirers not restored between decisions");
#endif
@@ -1001,8 +930,8 @@ static int next_branch(struct apk_solver_state *ss)
}
if (d->no_package && !d->found_solution) {
- if (ns->last_touched_decision < backup_until)
- backup_until = ns->last_touched_decision;
+ if (name->ss.last_touched_decision < backup_until)
+ backup_until = name->ss.last_touched_decision;
}
ss->num_decisions--;
@@ -1016,26 +945,24 @@ static void apply_constraint(struct apk_solver_state *ss, struct apk_dependency
{
struct apk_package *requirer_pkg = NULL;
struct apk_name *name = dep->name, *requirer_name = NULL;
- struct apk_name_state *ns = name_to_ns(name), *requirer_ns = NULL;
int i, strength, changed = 0;
if (ss->num_decisions > 0) {
requirer_name = decision_to_name(&ss->decisions[ss->num_decisions]);
requirer_pkg = decision_to_pkg(&ss->decisions[ss->num_decisions]);
- requirer_ns = name_to_ns(requirer_name);
- strength = requirer_ns->requirers ?: 1;
+ strength = requirer_name->ss.requirers ?: 1;
} else {
strength = 1;
}
- if (ns->locked) {
- if (ns->chosen.pkg)
+ if (name->ss.locked) {
+ if (name->ss.chosen.pkg)
dbg_printf("%s: locked to " PKG_VER_FMT " already\n",
- name->name, PKG_VER_PRINTF(ns->chosen.pkg));
+ name->name, PKG_VER_PRINTF(name->ss.chosen.pkg));
else
dbg_printf("%s: locked to empty\n",
name->name);
- if (!apk_dep_is_provided(dep, &ns->chosen)) {
+ if (!apk_dep_is_provided(dep, &name->ss.chosen)) {
dbg_printf("%s: constraint violation %d\n",
name->name, strength);
ss->score.conflicts += strength;
@@ -1079,10 +1006,10 @@ static void apply_constraint(struct apk_solver_state *ss, struct apk_dependency
}
if (changed)
- ns->last_touched_decision = ss->num_decisions;
+ name->ss.last_touched_decision = ss->num_decisions;
if (!dep->conflict)
- ns->requirers += strength;
+ name->ss.requirers += strength;
promote_name(ss, name);
}
@@ -1090,28 +1017,26 @@ static void apply_constraint(struct apk_solver_state *ss, struct apk_dependency
static void undo_constraint(struct apk_solver_state *ss, struct apk_dependency *dep)
{
struct apk_name *name = dep->name, *requirer_name = NULL;
- struct apk_name_state *ns = name_to_ns(name), *requirer_ns = NULL;
struct apk_package *requirer_pkg = NULL;
int i, strength;
if (ss->num_decisions > 0) {
requirer_name = decision_to_name(&ss->decisions[ss->num_decisions]);
requirer_pkg = decision_to_pkg(&ss->decisions[ss->num_decisions]);
- requirer_ns = name_to_ns(requirer_name);
- strength = requirer_ns->requirers ?: 1;
+ strength = requirer_name->ss.requirers ?: 1;
} else {
strength = 1;
}
- if (ns->locked) {
- if (ns->chosen.pkg != NULL) {
+ if (name->ss.locked) {
+ if (name->ss.chosen.pkg != NULL) {
dbg_printf(PKG_VER_FMT " selected already for %s\n",
- PKG_VER_PRINTF(ns->chosen.pkg), name->name);
+ PKG_VER_PRINTF(name->ss.chosen.pkg), name->name);
} else {
dbg_printf("%s selected to not be satisfied\n",
name->name);
}
- if (!apk_dep_is_provided(dep, &ns->chosen))
+ if (!apk_dep_is_provided(dep, &name->ss.chosen))
ss->score.conflicts -= strength;
return;
}
@@ -1150,24 +1075,23 @@ static void undo_constraint(struct apk_solver_state *ss, struct apk_dependency *
* *previous* value, but that'd require keeping track
* of it which would require dynamic memory allocations.
* in practice this is good enough. */
- if (ns->last_touched_decision > ss->num_decisions)
- ns->last_touched_decision = ss->num_decisions;
+ if (name->ss.last_touched_decision > ss->num_decisions)
+ name->ss.last_touched_decision = ss->num_decisions;
if (!dep->conflict)
- ns->requirers -= strength;
+ name->ss.requirers -= strength;
demote_name(ss, name);
}
static int reconsider_name(struct apk_solver_state *ss, struct apk_name *name)
{
- struct apk_name_state *ns = name_to_ns(name);
struct apk_provider *next_p = NULL, *best_p = NULL;
unsigned int next_topology = 0, options = 0;
int i, j, score_locked = FALSE;
struct apk_score best_score = (struct apk_score) { .conflicts = -1 };
- if (!ns->none_excluded) {
+ if (!name->ss.none_excluded) {
struct apk_score minscore;
get_unassigned_score(name, &minscore);
if (cmpscore2(&ss->score, &minscore, &ss->best_score) >= 0) {
@@ -1193,16 +1117,16 @@ static int reconsider_name(struct apk_solver_state *ss, struct apk_name *name)
for (j = 0; j < pkg0->provides->num; j++) {
struct apk_dependency *p00 = &pkg0->provides->item[j];
- if (!name_to_ns(p00->name)->locked)
+ if (!p00->name->ss.locked)
continue;
- if (name_to_ns(p00->name)->chosen.version != &apk_null_blob ||
+ if (p00->name->ss.chosen.version != &apk_null_blob ||
p00->version != &apk_null_blob)
break;
}
if (j < pkg0->provides->num)
continue;
- score_locked = get_topology_score(ss, ns, pkg0, &pkg0_score);
+ score_locked = get_topology_score(ss, pkg0, &pkg0_score);
/* viable alternative? */
if (cmpscore2(&ss->score, &pkg0_score, &ss->best_score) >= 0)
@@ -1227,63 +1151,66 @@ static int reconsider_name(struct apk_solver_state *ss, struct apk_name *name)
if (options == 0) {
dbg_printf("reconsider_name: %s: no options locking none\n",
name->name);
- if (ns->none_excluded)
+ if (name->ss.none_excluded)
return SOLVERR_PRUNED;
return push_decision(ss, name, NULL, DECISION_ASSIGN, BRANCH_NO, FALSE);
- } else if (options == 1 && score_locked && ns->none_excluded && name == next_p->pkg->name) {
+ } else if (options == 1 && score_locked && name->ss.none_excluded && name == next_p->pkg->name) {
dbg_printf("reconsider_name: %s: only one choice left with known score, locking.\n",
name->name);
return push_decision(ss, name, next_p->pkg, DECISION_ASSIGN, BRANCH_NO, FALSE);
}
- ns->chosen = *next_p;
- ns->preferred_chosen = (best_p == next_p);
+ name->ss.chosen = *next_p;
+ name->ss.preferred_chosen = (best_p == next_p);
dbg_printf("reconsider_name: %s: next_pkg=%p [ version="BLOB_FMT" ]\n",
- name->name, next_p->pkg, BLOB_PRINTF(*ns->chosen.version));
+ name->name, next_p->pkg, BLOB_PRINTF(*name->ss.chosen.version));
return SOLVERR_SOLUTION;
}
static int expand_branch(struct apk_solver_state *ss)
{
- struct apk_name *name0, *name;
- struct apk_name_state *ns;
+ struct apk_name *name0 = NULL, *name;
struct apk_package *pkg0 = NULL;
struct apk_package_state *ps0;
unsigned int r, topology0 = 0;
int primary_decision, branching_point;
int can_install = FALSE;
- list_for_each_entry(ns, &ss->unsolved_list_head, unsolved_list) {
- name = ns->name;
- if (ns->name_touched) {
+ list_for_each_entry(name, &ss->unsolved_list_head, ss.unsolved_list) {
+ struct apk_package *cpkg;
+ struct apk_package_state *cps;
+
+ if (name->ss.name_touched) {
dbg_printf("%s: reconsidering things\n",
name->name);
r = reconsider_name(ss, name);
if (r != SOLVERR_SOLUTION)
return r;
- ns->name_touched = 0;
+ name->ss.name_touched = 0;
}
- if (pkg_to_ps(ns->chosen.pkg)->topology_soft < ss->topology_position &&
- pkg_to_ps(ns->chosen.pkg)->topology_soft >= topology0) {
- topology0 = pkg_to_ps(ns->chosen.pkg)->topology_soft;
- } else if (ns->chosen.pkg->topology_hard >= topology0) {
- topology0 = ns->chosen.pkg->topology_hard;
+ cpkg = name->ss.chosen.pkg;
+ cps = pkg_to_ps(cpkg);
+ if (cps->topology_soft < ss->topology_position &&
+ cps->topology_soft >= topology0) {
+ topology0 = cps->topology_soft;
+ } else if (cpkg->topology_hard >= topology0) {
+ topology0 = cpkg->topology_hard;
} else {
continue;
}
- if (pkg0 != ns->chosen.pkg) {
+ if (pkg0 != cpkg) {
can_install = FALSE;
name0 = name;
}
- pkg0 = ns->chosen.pkg;
- if (ns->chosen.version != &apk_null_blob) {
+ pkg0 = cpkg;
+ if (name->ss.chosen.version != &apk_null_blob) {
can_install |= TRUE;
name0 = name;
}
}
- if (pkg0 == NULL) {
+ if (name0 == NULL || pkg0 == NULL) {
dbg_printf("expand_branch: solution with score "SCORE_FMT"\n",
SCORE_PRINTF(&ss->score));
return SOLVERR_SOLUTION;
@@ -1293,11 +1220,10 @@ static int expand_branch(struct apk_solver_state *ss)
* provider candidate */
ps0 = pkg_to_ps(pkg0);
name = name0;
- ns = name_to_ns(name);
- if (!ns->none_excluded) {
+ if (!name->ss.none_excluded) {
struct apk_package_state *ps0 = pkg_to_ps(pkg0);
- if (ps0->incompat_dep > ns->requirers)
+ if (ps0->incompat_dep > name->ss.requirers)
primary_decision = DECISION_ASSIGN;
else
primary_decision = DECISION_EXCLUDE;
@@ -1322,13 +1248,13 @@ static int expand_branch(struct apk_solver_state *ss)
branching_point = BRANCH_NO;
else
branching_point = BRANCH_YES;
- } else if (ns->requirers == 0 && ns->install_ifs != 0 &&
+ } else if (name->ss.requirers == 0 && name->ss.install_ifs != 0 &&
install_if_missing(ss, pkg0)) {
/* not directly required, and package specific
* install_if never triggered */
primary_decision = DECISION_EXCLUDE;
branching_point = BRANCH_NO;
- } else if (ns->preferred_chosen) {
+ } else if (name->ss.preferred_chosen) {
primary_decision = DECISION_ASSIGN;
branching_point = BRANCH_YES;
} else {
@@ -1356,7 +1282,6 @@ static int get_tag(struct apk_database *db, unsigned short pinning_mask, unsigne
static void record_solution(struct apk_solver_state *ss)
{
struct apk_database *db = ss->db;
- struct apk_name_state *ns;
int i, n;
apk_solution_array_resize(&ss->best_solution, ss->assigned_names);
@@ -1364,6 +1289,7 @@ static void record_solution(struct apk_solver_state *ss)
n = 0;
for (i = ss->num_decisions; i > 0; i--) {
struct apk_decision *d = &ss->decisions[i];
+ struct apk_name *name = decision_to_name(d);
struct apk_package *pkg = decision_to_pkg(d);
struct apk_package_state *ps;
unsigned short pinning;
@@ -1384,16 +1310,15 @@ static void record_solution(struct apk_solver_state *ss)
if (d->type != DECISION_ASSIGN)
continue;
- ns = name_to_ns(pkg->name);
ps = pkg_to_ps(pkg);
- pinning = ps->allowed_pinning | ns->preferred_pinning | APK_DEFAULT_PINNING_MASK;
+ pinning = ps->allowed_pinning | name->ss.preferred_pinning | APK_DEFAULT_PINNING_MASK;
repos = pkg->repos | (pkg->ipkg ? db->repo_tags[pkg->ipkg->repository_tag].allowed_repos : 0);
ASSERT(n < ss->assigned_names, "Name assignment overflow");
ss->best_solution->item[n++] = (struct apk_solution_entry){
.pkg = pkg,
.reinstall = ps->inherited_reinstall ||
- ((ns->solver_flags_local | ss->solver_flags) & APK_SOLVERF_REINSTALL),
+ ((name->ss.solver_flags_local | ss->solver_flags) & APK_SOLVERF_REINSTALL),
.repository_tag = get_tag(db, pinning, repos),
};
}
@@ -1437,7 +1362,6 @@ static int generate_changeset(struct apk_database *db,
unsigned short solver_flags)
{
struct apk_name *name;
- struct apk_name_state *ns;
struct apk_package *pkg;
struct apk_installed_package *ipkg;
int i, num_installs = 0, num_removed = 0, ci = 0;
@@ -1445,9 +1369,9 @@ static int generate_changeset(struct apk_database *db,
/* calculate change set size */
for (i = 0; i < solution->num; i++) {
pkg = solution->item[i].pkg;
- ns = name_to_ns(pkg->name);
- ns->chosen = APK_PROVIDER_FROM_PACKAGE(pkg);
- ns->in_changeset = 1;
+ name = pkg->name;
+ name->ss.chosen = APK_PROVIDER_FROM_PACKAGE(pkg);
+ name->ss.in_changeset = 1;
if ((pkg->ipkg == NULL) ||
solution->item[i].reinstall ||
solution->item[i].repository_tag != pkg->ipkg->repository_tag)
@@ -1455,8 +1379,7 @@ static int generate_changeset(struct apk_database *db,
}
list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
name = ipkg->pkg->name;
- ns = name_to_ns(name);
- if ((ns->chosen.pkg == NULL) || !ns->in_changeset)
+ if ((name->ss.chosen.pkg == NULL) || !name->ss.in_changeset)
num_removed++;
}
@@ -1464,8 +1387,7 @@ static int generate_changeset(struct apk_database *db,
apk_change_array_resize(&changeset->changes, num_installs + num_removed);
list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
name = ipkg->pkg->name;
- ns = name_to_ns(name);
- if ((ns->chosen.pkg == NULL) || !ns->in_changeset) {
+ if ((name->ss.chosen.pkg == NULL) || !name->ss.in_changeset) {
changeset->changes->item[ci].oldpkg = ipkg->pkg;
ci++;
}
@@ -1473,7 +1395,6 @@ static int generate_changeset(struct apk_database *db,
for (i = 0; i < solution->num; i++) {
pkg = solution->item[i].pkg;
name = pkg->name;
- ns = name_to_ns(name);
if ((pkg->ipkg == NULL) ||
solution->item[i].reinstall ||
@@ -1496,15 +1417,10 @@ static int generate_changeset(struct apk_database *db,
static int free_state(apk_hash_item item, void *ctx)
{
struct apk_name *name = (struct apk_name *) item;
- struct apk_name_state *ns = (struct apk_name_state *) name->state_ptr;
- if (ns != NULL) {
-#ifdef DEBUG_CHECKS
- ASSERT(ns->requirers == 0, "Requirers is not zero after cleanup");
-#endif
- free(ns);
- name->state_ptr = NULL;
- }
+ ASSERT(name->ss.requirers == 0, "Requirers is not zero after cleanup");
+ memset(&name->ss, 0, sizeof(name->ss));
+
return 0;
}
@@ -1523,9 +1439,8 @@ void apk_solver_set_name_flags(struct apk_name *name,
unsigned short solver_flags,
unsigned short solver_flags_inheritable)
{
- struct apk_name_state *ns = name_to_ns_alloc(name);
- ns->solver_flags_local = solver_flags;
- ns->solver_flags_inheritable = solver_flags & solver_flags_inheritable;
+ name->ss.solver_flags_local = solver_flags;
+ name->ss.solver_flags_inheritable = solver_flags & solver_flags_inheritable;
}
static void apk_solver_free(struct apk_database *db)
@@ -1555,18 +1470,16 @@ int apk_solver_solve(struct apk_database *db,
for (i = 0; i < world->num; i++) {
struct apk_dependency *dep = &world->item[i];
struct apk_name *name = dep->name;
- struct apk_name_state *ns = name_to_ns_alloc(name);
-
- ns->in_world_dependency = 1;
dbg_printf("%s: adding pinnings %d\n", name->name, dep->repository_tag);
- ns->preferred_pinning = BIT(dep->repository_tag);
+ name->ss.in_world_dependency = 1;
+ name->ss.preferred_pinning = BIT(dep->repository_tag);
sort_name(ss, name);
}
list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
sort_name(ss, ipkg->pkg->name);
- name_to_ns(ipkg->pkg->name)->originally_installed = 1;
+ ipkg->pkg->name->ss.originally_installed = 1;
}
ss->max_decisions ++;