From 803f55ece50bea9f0f8120dbcfe8068f689d3703 Mon Sep 17 00:00:00 2001 From: Timo Teräs Date: Wed, 14 Sep 2011 16:48:28 +0300 Subject: solver: make state pointers completely internal the only bit of information needed in solver commit is the "hard" topology sorting information for trigger ordering. fixes a bug in "apk del" which uses the state pointers to do intermediate calculations between solution solving and commit. --- src/apk_package.h | 1 + src/apk_solver.h | 2 -- src/del.c | 4 +--- src/solver.c | 61 ++++++++++++++++++++++++++----------------------------- src/upgrade.c | 5 +---- 5 files changed, 32 insertions(+), 41 deletions(-) diff --git a/src/apk_package.h b/src/apk_package.h index f752c87..b6bcffd 100644 --- a/src/apk_package.h +++ b/src/apk_package.h @@ -94,6 +94,7 @@ struct apk_package { size_t installed_size, size; time_t build_time; unsigned repos; + unsigned int topology_hard; struct apk_checksum csum; }; APK_ARRAY(apk_package_array, struct apk_package *); diff --git a/src/apk_solver.h b/src/apk_solver.h index 3c14094..29961d0 100644 --- a/src/apk_solver.h +++ b/src/apk_solver.h @@ -25,7 +25,6 @@ struct apk_changeset { #define APK_SOLVERF_UPGRADE 0x0001 #define APK_SOLVERF_AVAILABLE 0x0002 #define APK_SOLVERF_REINSTALL 0x0004 -#define APK_SOLVERF_KEEP_STATE 0x8000 void apk_solver_set_name_flags(struct apk_name *name, unsigned short solver_flags); @@ -34,7 +33,6 @@ int apk_solver_solve(struct apk_database *db, struct apk_dependency_array *world, struct apk_package_array **solution, struct apk_changeset *changeset); -void apk_solver_free(struct apk_database *db); int apk_solver_commit_changeset(struct apk_database *db, struct apk_changeset *changeset, struct apk_dependency_array *world); diff --git a/src/del.c b/src/del.c index dff4356..3d7ffe7 100644 --- a/src/del.c +++ b/src/del.c @@ -142,8 +142,7 @@ static int del_main(void *pctx, struct apk_database *db, int argc, char **argv) delete_from_world, ctx); } - r = apk_solver_solve(db, APK_SOLVERF_KEEP_STATE, - ctx->world, &solution, &changeset); + r = apk_solver_solve(db, 0, ctx->world, &solution, &changeset); if (r == 0 || (apk_flags & APK_FORCE)) { /* check for non-deleted package names */ for (i = 0; i < solution->num; i++) { @@ -167,7 +166,6 @@ static int del_main(void *pctx, struct apk_database *db, int argc, char **argv) } else { apk_solver_print_errors(db, solution, ctx->world, r); } - apk_solver_free(db); apk_package_array_free(&solution); apk_dependency_array_free(&ctx->world); diff --git a/src/solver.c b/src/solver.c index 349035a..b8dcc62 100644 --- a/src/solver.c +++ b/src/solver.c @@ -33,7 +33,7 @@ struct apk_package_state { struct apk_package *backtrack; - unsigned int topology_hard, topology_soft; + unsigned int topology_soft; unsigned short flags; unsigned short conflicts; unsigned short cur_unsatisfiable; @@ -158,17 +158,17 @@ static void sort_hard_dependencies(struct apk_solver_state *ss, struct apk_packa pkg->state_ptr = calloc(1, sizeof(struct apk_package_state)); ps = pkg_to_ps(pkg); - if (ps->topology_hard) + if (pkg->topology_hard) return; - ps->topology_hard = -1; + pkg->topology_hard = -1; /* Consider hard dependencies only */ foreach_dependency_pkg(ss, pkg->depends, sort_hard_dependencies); foreach_dependency_pkg(ss, pkg->install_if, sort_hard_dependencies); - ps->topology_soft = ps->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", - PKG_VER_PRINTF(pkg), ps->topology_hard); + PKG_VER_PRINTF(pkg), pkg->topology_hard); } static void sort_soft_dependencies(struct apk_solver_state *ss, struct apk_package *pkg) @@ -178,7 +178,7 @@ static void sort_soft_dependencies(struct apk_solver_state *ss, struct apk_packa sort_hard_dependencies(ss, pkg); ps = pkg_to_ps(pkg); - if (ps->topology_soft != ps->topology_hard) + if (ps->topology_soft != pkg->topology_hard) return; ps->topology_soft = -1; @@ -246,7 +246,7 @@ static int get_pkg_expansion_flags(struct apk_solver_state *ss, struct apk_packa struct apk_package_state *ps0 = pkg_to_ps(pkg0); if (pkg0 == pkg || ps0 == NULL || - ps0->topology_hard > ss->topology_position || + pkg0->topology_hard > ss->topology_position || (ps0->flags & APK_PKGSTF_DECIDED) || ps0->conflicts != 0) continue; @@ -318,7 +318,7 @@ static int update_name_state(struct apk_solver_state *ss, struct apk_package_state *ps0 = pkg_to_ps(pkg0); if (ps0 == NULL || - ps0->topology_hard >= ss->topology_position || + pkg0->topology_hard >= ss->topology_position || (ps0->flags & APK_PKGSTF_DECIDED)) continue; @@ -332,8 +332,8 @@ static int update_name_state(struct apk_solver_state *ss, if (ps0->topology_soft < ss->topology_position && ps0->topology_soft > best_topology) best_pkg = pkg0, best_topology = ps0->topology_soft; - else if (ps0->topology_hard > best_topology) - best_pkg = pkg0, best_topology = ps0->topology_hard; + else if (pkg0->topology_hard > best_topology) + best_pkg = pkg0, best_topology = pkg0->topology_hard; } if (options == 0 && skipped_options == 0) { @@ -434,7 +434,7 @@ static void undo_decision(struct apk_solver_state *ss, if (ps->flags & APK_PKGSTF_INSTALLIF) ss->topology_position = ps->topology_soft; else - ss->topology_position = ps->topology_hard; + ss->topology_position = pkg->topology_hard; if (ps->flags & APK_PKGSTF_INSTALL) { ss->assigned_names--; @@ -465,7 +465,7 @@ static void push_decision(struct apk_solver_state *ss, struct apk_package *pkg, ss->topology_position = ps->topology_soft; } else { ps->flags &= ~APK_PKGSTF_INSTALLIF; - ss->topology_position = ps->topology_hard; + ss->topology_position = pkg->topology_hard; } ss->latest_decision = pkg; @@ -534,7 +534,7 @@ static void apply_constraint(struct apk_solver_state *ss, struct apk_dependency struct apk_package_state *ps0 = pkg_to_ps(pkg0); if (ps0 == NULL || - ps0->topology_hard >= ss->topology_position) + pkg0->topology_hard >= ss->topology_position) continue; if (!apk_dep_is_satisfied(dep, pkg0)) { @@ -565,7 +565,7 @@ static void undo_constraint(struct apk_solver_state *ss, struct apk_dependency * struct apk_package *pkg0 = name->pkgs->item[i]; struct apk_package_state *ps0 = pkg_to_ps(pkg0); - if (ps0->topology_hard >= ss->topology_position) + if (pkg0->topology_hard >= ss->topology_position) continue; if (!apk_dep_is_satisfied(dep, pkg0)) { @@ -597,8 +597,8 @@ static int expand_branch(struct apk_solver_state *ss) if (pkg_to_ps(ns->chosen)->topology_soft < ss->topology_position && pkg_to_ps(ns->chosen)->topology_soft > topology0) pkg0 = ns->chosen, topology0 = pkg_to_ps(pkg0)->topology_soft; - else if (pkg_to_ps(ns->chosen)->topology_hard > topology0) - pkg0 = ns->chosen, topology0 = pkg_to_ps(pkg0)->topology_hard; + else if (ns->chosen->topology_hard > topology0) + pkg0 = ns->chosen, topology0 = pkg0->topology_hard; } if (pkg0 == NULL) { dbg_printf("expand_branch: list is empty (%d unsatisfied)\n", @@ -660,8 +660,8 @@ static int compare_change(const void *p1, const void *p2) if (c1->newpkg == NULL) { if (c2->newpkg == NULL) /* both deleted - reverse topology order */ - return pkg_to_ps(c2->oldpkg)->topology_hard - - pkg_to_ps(c1->oldpkg)->topology_hard; + return c2->oldpkg->topology_hard - + c1->oldpkg->topology_hard; /* c1 deleted, c2 installed -> c2 first*/ return -1; @@ -670,8 +670,8 @@ static int compare_change(const void *p1, const void *p2) /* c1 installed, c2 deleted -> c1 first*/ return 1; - return pkg_to_ps(c1->newpkg)->topology_hard - - pkg_to_ps(c2->newpkg)->topology_hard; + return c1->newpkg->topology_hard - + c2->newpkg->topology_hard; } static int generate_changeset(struct apk_database *db, @@ -763,6 +763,12 @@ void apk_solver_set_name_flags(struct apk_name *name, ns->solver_flags = solver_flags; } +static void apk_solver_free(struct apk_database *db) +{ + apk_hash_foreach(&db->available.names, free_state, NULL); + apk_hash_foreach(&db->available.packages, free_package, NULL); +} + int apk_solver_solve(struct apk_database *db, unsigned short solver_flags, struct apk_dependency_array *world, @@ -826,20 +832,12 @@ int apk_solver_solve(struct apk_database *db, else apk_package_array_free(&ss->best_solution); - if (!(solver_flags & APK_SOLVERF_KEEP_STATE)) - apk_solver_free(db); - + apk_solver_free(db); free(ss); return r; } -void apk_solver_free(struct apk_database *db) -{ - apk_hash_foreach(&db->available.names, free_state, NULL); - apk_hash_foreach(&db->available.packages, free_package, NULL); -} - static void print_change(struct apk_database *db, struct apk_change *change, int cur, int total) @@ -1013,7 +1011,7 @@ static int compare_package(const void *p1, const void *p2) struct apk_package *pkg1 = *(struct apk_package **) p1; struct apk_package *pkg2 = *(struct apk_package **) p2; - return pkg_to_ps(pkg1)->topology_hard - pkg_to_ps(pkg2)->topology_hard; + return pkg1->topology_hard - pkg2->topology_hard; } static void run_triggers(struct apk_database *db) @@ -1186,7 +1184,7 @@ int apk_solver_commit(struct apk_database *db, struct apk_package_array *solution = NULL; int r; - r = apk_solver_solve(db, APK_SOLVERF_KEEP_STATE | solver_flags, + r = apk_solver_solve(db, solver_flags, world, &solution, &changeset); if (r < 0) return r; @@ -1200,7 +1198,6 @@ int apk_solver_commit(struct apk_database *db, apk_solver_print_errors(db, solution, world, r); } apk_package_array_free(&solution); - apk_solver_free(db); return r; } diff --git a/src/upgrade.c b/src/upgrade.c index 541fbf3..dd53c19 100644 --- a/src/upgrade.c +++ b/src/upgrade.c @@ -52,8 +52,7 @@ int apk_do_self_upgrade(struct apk_database *db, unsigned short solver_flags) apk_solver_set_name_flags(name, solver_flags); db->performing_self_update = 1; - r = apk_solver_solve(db, APK_SOLVERF_KEEP_STATE, - db->world, &solution, &changeset); + r = apk_solver_solve(db, 0, db->world, &solution, &changeset); if (r != 0) { if (apk_flags & APK_FORCE) r = 0; @@ -72,7 +71,6 @@ int apk_do_self_upgrade(struct apk_database *db, unsigned short solver_flags) apk_message("Upgrading critical system libraries and apk-tools:"); apk_solver_commit_changeset(db, &changeset, db->world); - apk_solver_free(db); apk_db_close(db); apk_message("Continuing the upgrade transaction with new apk-tools:"); @@ -85,7 +83,6 @@ int apk_do_self_upgrade(struct apk_database *db, unsigned short solver_flags) exit(1); ret: - apk_solver_free(db); apk_package_array_free(&solution); apk_change_array_free(&changeset.changes); db->performing_self_update = 0; -- cgit v1.2.3-70-g09d2