From e34d2ed5fdec628936711517612a0fe643ed6d33 Mon Sep 17 00:00:00 2001 From: Timo Teräs Date: Wed, 14 Sep 2011 11:30:02 +0300 Subject: solver, db: run triggers in dependency order fixes #738 --- src/apk_database.h | 2 +- src/apk_solver.h | 2 ++ src/database.c | 13 +++++-------- src/del.c | 4 +++- src/solver.c | 49 +++++++++++++++++++++++++++++++++++++++++++++---- src/upgrade.c | 5 ++++- 6 files changed, 60 insertions(+), 15 deletions(-) diff --git a/src/apk_database.h b/src/apk_database.h index e8acda5..d7c4f5b 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -183,8 +183,8 @@ struct apk_db_file *apk_db_file_query(struct apk_database *db, int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts); void apk_db_close(struct apk_database *db); int apk_db_write_config(struct apk_database *db); -int apk_db_run_triggers(struct apk_database *db); int apk_db_permanent(struct apk_database *db); +struct apk_package_array *apk_db_get_pending_triggers(struct apk_database *db); struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package *pkg); struct apk_package *apk_db_get_pkg(struct apk_database *db, struct apk_checksum *csum); diff --git a/src/apk_solver.h b/src/apk_solver.h index 29961d0..3c14094 100644 --- a/src/apk_solver.h +++ b/src/apk_solver.h @@ -25,6 +25,7 @@ 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); @@ -33,6 +34,7 @@ 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/database.c b/src/database.c index 2b5b687..135f6b4 100644 --- a/src/database.c +++ b/src/database.c @@ -1458,23 +1458,20 @@ static int fire_triggers(apk_hash_item item, void *ctx) return 0; } -int apk_db_run_triggers(struct apk_database *db) +struct apk_package_array *apk_db_get_pending_triggers(struct apk_database *db) { struct apk_installed_package *ipkg; + struct apk_package_array *pkgs = NULL; + apk_package_array_init(&pkgs); apk_hash_foreach(&db->installed.dirs, fire_triggers, db); - list_for_each_entry(ipkg, &db->installed.triggers, trigger_pkgs_list) { if (ipkg->pending_triggers->num == 0) continue; - - *apk_string_array_add(&ipkg->pending_triggers) = NULL; - apk_ipkg_run_script(ipkg, db, APK_SCRIPT_TRIGGER, - ipkg->pending_triggers->item); - apk_string_array_free(&ipkg->pending_triggers); + *apk_package_array_add(&pkgs) = ipkg->pkg; } - return 0; + return pkgs; } int apk_db_cache_active(struct apk_database *db) diff --git a/src/del.c b/src/del.c index 3d7ffe7..dff4356 100644 --- a/src/del.c +++ b/src/del.c @@ -142,7 +142,8 @@ static int del_main(void *pctx, struct apk_database *db, int argc, char **argv) delete_from_world, ctx); } - r = apk_solver_solve(db, 0, ctx->world, &solution, &changeset); + r = apk_solver_solve(db, APK_SOLVERF_KEEP_STATE, + ctx->world, &solution, &changeset); if (r == 0 || (apk_flags & APK_FORCE)) { /* check for non-deleted package names */ for (i = 0; i < solution->num; i++) { @@ -166,6 +167,7 @@ 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 48ba846..349035a 100644 --- a/src/solver.c +++ b/src/solver.c @@ -826,13 +826,20 @@ int apk_solver_solve(struct apk_database *db, else apk_package_array_free(&ss->best_solution); - apk_hash_foreach(&db->available.names, free_state, NULL); - apk_hash_foreach(&db->available.packages, free_package, NULL); + if (!(solver_flags & APK_SOLVERF_KEEP_STATE)) + 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) @@ -1001,6 +1008,38 @@ static int cmp_upgrade(struct apk_change *change) return 0; } +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; +} + +static void run_triggers(struct apk_database *db) +{ + struct apk_package_array *pkgs; + int i; + + pkgs = apk_db_get_pending_triggers(db); + if (pkgs == NULL || pkgs->num == 0) + return; + + qsort(pkgs->item, pkgs->num, sizeof(struct apk_package *), + compare_package); + + for (i = 0; i < pkgs->num; i++) { + struct apk_package *pkg = pkgs->item[i]; + struct apk_installed_package *ipkg = pkg->ipkg; + + *apk_string_array_add(&ipkg->pending_triggers) = NULL; + apk_ipkg_run_script(ipkg, db, APK_SCRIPT_TRIGGER, + ipkg->pending_triggers->item); + apk_string_array_free(&ipkg->pending_triggers); + } + apk_package_array_free(&pkgs); +} + int apk_solver_commit_changeset(struct apk_database *db, struct apk_changeset *changeset, struct apk_dependency_array *world) @@ -1072,7 +1111,7 @@ int apk_solver_commit_changeset(struct apk_database *db, if (apk_flags & APK_PROGRESS) draw_progress(100); - apk_db_run_triggers(db); + run_triggers(db); all_done: apk_dependency_array_copy(&db->world, world); @@ -1147,7 +1186,8 @@ int apk_solver_commit(struct apk_database *db, struct apk_package_array *solution = NULL; int r; - r = apk_solver_solve(db, solver_flags, world, &solution, &changeset); + r = apk_solver_solve(db, APK_SOLVERF_KEEP_STATE | solver_flags, + world, &solution, &changeset); if (r < 0) return r; @@ -1160,6 +1200,7 @@ 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 dd53c19..541fbf3 100644 --- a/src/upgrade.c +++ b/src/upgrade.c @@ -52,7 +52,8 @@ 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, 0, db->world, &solution, &changeset); + r = apk_solver_solve(db, APK_SOLVERF_KEEP_STATE, + db->world, &solution, &changeset); if (r != 0) { if (apk_flags & APK_FORCE) r = 0; @@ -71,6 +72,7 @@ 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:"); @@ -83,6 +85,7 @@ 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