From: Michael Tremer Date: Tue, 27 Apr 2021 16:41:04 +0000 (+0000) Subject: transactions: Refactor dumping transactions & steps X-Git-Tag: 0.9.28~1285^2~214 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=40fd1f3fefae44b4de353e5f335e831781453585;p=pakfire.git transactions: Refactor dumping transactions & steps Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/include/pakfire/step.h b/src/libpakfire/include/pakfire/step.h index bc588d5b3..f8bb59ff0 100644 --- a/src/libpakfire/include/pakfire/step.h +++ b/src/libpakfire/include/pakfire/step.h @@ -23,7 +23,7 @@ #include -PakfireStep pakfire_step_create(PakfireTransaction transaction, +int pakfire_step_create(PakfireStep* step, Pakfire pakfire, pakfire_step_type_t type, PakfirePackage pkg); PakfireStep pakfire_step_ref(PakfireStep step); PakfireStep pakfire_step_unref(PakfireStep step); diff --git a/src/libpakfire/include/pakfire/transaction.h b/src/libpakfire/include/pakfire/transaction.h index 6a182d591..a544a58c7 100644 --- a/src/libpakfire/include/pakfire/transaction.h +++ b/src/libpakfire/include/pakfire/transaction.h @@ -21,11 +21,8 @@ #ifndef PAKFIRE_TRANSACTION_H #define PAKFIRE_TRANSACTION_H -#include - #include -PakfireTransaction pakfire_transaction_create(Pakfire pakfire, Transaction* trans); PakfireTransaction pakfire_transaction_ref(PakfireTransaction transaction); PakfireTransaction pakfire_transaction_unref(PakfireTransaction transaction); @@ -45,7 +42,9 @@ int pakfire_transaction_download(PakfireTransaction transaction); #ifdef PAKFIRE_PRIVATE -Transaction* pakfire_transaction_get_transaction(PakfireTransaction transaction); +#include + +int pakfire_transaction_create(PakfireTransaction* transaction, Pakfire pakfire, Transaction* trans); #endif diff --git a/src/libpakfire/request.c b/src/libpakfire/request.c index 83f024b50..38d95ac02 100644 --- a/src/libpakfire/request.c +++ b/src/libpakfire/request.c @@ -227,7 +227,12 @@ PAKFIRE_EXPORT PakfireTransaction pakfire_request_get_transaction(struct pakfire if (!request->transaction) return NULL; - return pakfire_transaction_create(request->pakfire, request->transaction); + PakfireTransaction transaction; + int r = pakfire_transaction_create(&transaction, request->pakfire, request->transaction); + if (r) + return NULL; + + return transaction; } static int pakfire_request_is_file(const char* what) { diff --git a/src/libpakfire/step.c b/src/libpakfire/step.c index 764ca040e..8dfdef6aa 100644 --- a/src/libpakfire/step.c +++ b/src/libpakfire/step.c @@ -49,24 +49,26 @@ struct _PakfireStep { int nrefs; }; -PAKFIRE_EXPORT PakfireStep pakfire_step_create(PakfireTransaction transaction, +PAKFIRE_EXPORT int pakfire_step_create(PakfireStep* step, Pakfire pakfire, pakfire_step_type_t type, PakfirePackage pkg) { - Pakfire pakfire = pakfire_transaction_get_pakfire(transaction); + PakfireStep s = calloc(1, sizeof(*s)); + if (!s) + return ENOMEM; - PakfireStep step = calloc(1, sizeof(*step)); - if (step) { - DEBUG(pakfire, "Allocated Step at %p\n", step); - step->pakfire = pakfire_ref(pakfire); - step->nrefs = 1; + // Store a reference to Pakfire + s->pakfire = pakfire_ref(pakfire); - // Save everything - step->type = type; - step->package = pakfire_package_ref(pkg); - } + // Initialize the reference counter + s->nrefs = 1; - pakfire_unref(pakfire); + // Store a reference to the package + s->package = pakfire_package_ref(pkg); - return step; + // Store type + s->type = type; + + *step = s; + return 0; } PAKFIRE_EXPORT PakfireStep pakfire_step_ref(PakfireStep step) { @@ -86,9 +88,6 @@ static void pakfire_step_free(PakfireStep step) { } PAKFIRE_EXPORT PakfireStep pakfire_step_unref(PakfireStep step) { - if (!step) - return NULL; - if (--step->nrefs > 0) return step; diff --git a/src/libpakfire/transaction.c b/src/libpakfire/transaction.c index 9b8d57ffd..7e01b48eb 100644 --- a/src/libpakfire/transaction.c +++ b/src/libpakfire/transaction.c @@ -39,15 +39,16 @@ struct _PakfireTransaction { Pakfire pakfire; + int nrefs; + Transaction* transaction; + PakfireStep* steps; size_t num_steps; - int nrefs; }; -static pakfire_step_type_t transaction_get_step_type(Transaction* transaction, Id id) { - int type = transaction_type(transaction, id, - SOLVER_TRANSACTION_SHOW_ACTIVE|SOLVER_TRANSACTION_CHANGE_IS_REINSTALL); +static pakfire_step_type_t transaction_get_step_type(PakfireTransaction transaction, Id id) { + int type = transaction_type(transaction->transaction, id, 0); // Translate solver types into our own types switch (type) { @@ -80,63 +81,94 @@ static pakfire_step_type_t transaction_get_step_type(Transaction* transaction, I } } -PAKFIRE_EXPORT PakfireTransaction pakfire_transaction_create(Pakfire pakfire, Transaction* trans) { - PakfireTransaction transaction = calloc(1, sizeof(*transaction)); - if (transaction) { - DEBUG(pakfire, "Allocated Transaction at %p\n", transaction); - transaction->nrefs = 1; +static void pakfire_transaction_free(PakfireTransaction transaction) { + // Release all steps + if (transaction->steps) { + for (unsigned int i = 0; i < transaction->num_steps; i++) + pakfire_step_unref(transaction->steps[i]); + free(transaction->steps); + } - transaction->pakfire = pakfire_ref(pakfire); + transaction_free(transaction->transaction); - // Clone the transaction, so we get independent from what ever called this. - if (trans) { - transaction->transaction = transaction_create_clone(trans); - transaction_order(transaction->transaction, 0); - } else { - transaction->transaction = transaction_create(trans->pool); - } + pakfire_unref(transaction->pakfire); + free(transaction); +} - // Save total number of steps - transaction->num_steps = transaction->transaction->steps.count; +static int pakfire_transaction_add_step(PakfireTransaction transaction, Id id) { + int type = transaction_get_step_type(transaction, id); - // Import all steps - PakfireStep* steps = transaction->steps = calloc(transaction->num_steps + 1, sizeof(*steps)); - for (unsigned int i = 0; i < transaction->num_steps; i++) { - Id id = transaction->transaction->steps.elements[i]; + // Do not add ignored steps + if (type == PAKFIRE_STEP_IGNORE) + return 0; - // Get the type - pakfire_step_type_t type = transaction_get_step_type(transaction->transaction, id); + // Allocate more space + transaction->steps = reallocarray(transaction->steps, sizeof(*transaction->steps), + transaction->num_steps + 1); + if (!transaction->steps) + return 1; - // Fetch the package - PakfirePackage pkg = pakfire_package_create_from_solvable(pakfire, id); + PakfirePackage pkg = pakfire_package_create_from_solvable(transaction->pakfire, id); + if (!pkg) + return 1; - // Append a new step - *steps++ = pakfire_step_create(transaction, type, pkg); + PakfireStep step; + int r = pakfire_step_create(&step, transaction->pakfire, type, pkg); + if (r) + goto ERROR; - pakfire_package_unref(pkg); - } - } + transaction->steps[transaction->num_steps++] = step; - return transaction; -} + // Success + r = 0; -PAKFIRE_EXPORT PakfireTransaction pakfire_transaction_ref(PakfireTransaction transaction) { - transaction->nrefs++; +ERROR: + if (pkg) + pakfire_package_unref(pkg); - return transaction; + return r; } -void pakfire_transaction_free(PakfireTransaction transaction) { - DEBUG(transaction->pakfire, "Releasing Transaction at %p\n", transaction); +int pakfire_transaction_create(PakfireTransaction* transaction, + Pakfire pakfire, Transaction* trans) { + PakfireTransaction t = calloc(1, sizeof(*t)); + if (!t) + return ENOMEM; - // Release all steps - while (*transaction->steps) - pakfire_step_unref(*transaction->steps++); + // Store reference to Pakfire + t->pakfire = pakfire_ref(pakfire); - transaction_free(transaction->transaction); + // Initialize the reference counter + t->nrefs = 1; - pakfire_unref(transaction->pakfire); - free(transaction); + // Clone the transaction to keep a copy of it + t->transaction = transaction_create_clone(trans); + if (!t->transaction) + goto ERROR; + + // Order the transaction + transaction_order(t->transaction, 0); + + // Import steps + for (int i = 0; i < t->transaction->steps.count; i++) { + int r = pakfire_transaction_add_step(t, t->transaction->steps.elements[i]); + if (r) + goto ERROR; + } + + *transaction = t; + return 0; + +ERROR: + pakfire_transaction_free(t); + + return 1; +} + +PAKFIRE_EXPORT PakfireTransaction pakfire_transaction_ref(PakfireTransaction transaction) { + transaction->nrefs++; + + return transaction; } PAKFIRE_EXPORT PakfireTransaction pakfire_transaction_unref(PakfireTransaction transaction) { @@ -151,10 +183,6 @@ PAKFIRE_EXPORT Pakfire pakfire_transaction_get_pakfire(PakfireTransaction transa return pakfire_ref(transaction->pakfire); } -Transaction* pakfire_transaction_get_transaction(PakfireTransaction transaction) { - return transaction->transaction; -} - PAKFIRE_EXPORT size_t pakfire_transaction_count(PakfireTransaction transaction) { return transaction->num_steps; } @@ -169,8 +197,8 @@ PAKFIRE_EXPORT ssize_t pakfire_transaction_installsizechange(PakfireTransaction PAKFIRE_EXPORT ssize_t pakfire_transaction_downloadsize(PakfireTransaction transaction) { ssize_t size = 0; - for (PakfireStep* step = transaction->steps; *step; step++) - size += pakfire_step_get_downloadsize(*step); + for (unsigned int i = 0; i < transaction->num_steps; i++) + size += pakfire_step_get_downloadsize(transaction->steps[i]); return size; } @@ -235,6 +263,14 @@ static void pakfire_transaction_add_package(char** str, size_t width, PakfirePac pakfire_repo_unref(repo); } +static void pakfire_transaction_add_package_change(char** str, size_t width, + PakfirePackage pkg1, PakfirePackage pkg2) { + // Print the new package first + pakfire_transaction_add_package(str, width, pkg1); + + asprintf(str, "%s --> %s\n", *str, pakfire_package_get_nevra(pkg2)); +} + static void pakfire_transaction_add_separator(char** str, size_t width) { while (width-- > 0) asprintf(str, "%s=", *str); @@ -243,39 +279,6 @@ static void pakfire_transaction_add_separator(char** str, size_t width) { asprintf(str, "%s\n", *str); } -static size_t pakfire_transaction_add_section(char** str, size_t width, PakfireTransaction transaction, - const char* headline, pakfire_step_type_t type) { - PakfirePackageList list = pakfire_transaction_get_packages(transaction, type); - - // Nothing to do if there are no packages in this stage - size_t c = pakfire_packagelist_count(list); - if (c == 0) - goto END; - - // Headline - pakfire_transaction_add_headline(str, width, headline); - - // List each package - for (unsigned int i = 0; i < c; i++) { - PakfirePackage pkg = pakfire_packagelist_get(list, i); - pakfire_transaction_add_package(str, width, pkg); - pakfire_package_unref(pkg); - } - - // newline - pakfire_transaction_add_newline(str, width); - -END: - pakfire_packagelist_unref(list); - - return c; -} - -static void pakfire_transaction_add_summary_line(char** str, size_t width, const char* headline, size_t pkgs) { - if (pkgs > 0) - asprintf(str, "%s%-20s %-4zu %s\n", *str, headline, pkgs, _("package(s)")); -} - static void pakfire_transaction_add_usage_line(char** str, size_t width, const char* headline, ssize_t size) { char buffer[128]; pakfire_format_size(buffer, sizeof(buffer) - 1, size); @@ -284,8 +287,14 @@ static void pakfire_transaction_add_usage_line(char** str, size_t width, const c } PAKFIRE_EXPORT char* pakfire_transaction_dump(PakfireTransaction transaction, size_t width) { + char headline[1024]; char* string = ""; + Pool* pool = transaction->transaction->pool; + const int mode = + SOLVER_TRANSACTION_SHOW_OBSOLETES | + SOLVER_TRANSACTION_OBSOLETE_IS_UPGRADE; + // Header pakfire_transaction_add_separator(&string, width); pakfire_transaction_add_line(&string, width, @@ -297,40 +306,146 @@ PAKFIRE_EXPORT char* pakfire_transaction_dump(PakfireTransaction transaction, si ); pakfire_transaction_add_separator(&string, width); - // Show what we are doing - size_t installing = pakfire_transaction_add_section(&string, width, transaction, - _("Installing:"), PAKFIRE_STEP_INSTALL); - size_t reinstalling = pakfire_transaction_add_section(&string, width, transaction, - _("Reinstalling:"), PAKFIRE_STEP_REINSTALL); - size_t updating = pakfire_transaction_add_section(&string, width, transaction, - _("Updating:"), PAKFIRE_STEP_UPGRADE); - size_t downgrading = pakfire_transaction_add_section(&string, width, transaction, - _("Downgrading:"), PAKFIRE_STEP_DOWNGRADE); - size_t removing = pakfire_transaction_add_section(&string, width, transaction, - _("Removing:"), PAKFIRE_STEP_ERASE); - size_t obsoleting = pakfire_transaction_add_section(&string, width, transaction, - _("Obsoleting:"), PAKFIRE_STEP_OBSOLETE); + Queue classes; + queue_init(&classes); + + // Get all classes + transaction_classify(transaction->transaction, mode, &classes); + + Queue pkgs; + queue_init(&pkgs); + + /* + The classes queue now contains a list of all classes as a tuple of: + * The class type + * The number of packages in this class + * The from ID (for arch/vendor change) + * The to ID (for arch/vendor change) + */ + for (int i = 0; i < classes.count; i += 4) { + Id class = classes.elements[i]; + unsigned int count = classes.elements[i+1]; + + const char* from = pool_id2str(pool, classes.elements[i+2]); + const char* to = pool_id2str(pool, classes.elements[i+3]); + + switch (class) { + case SOLVER_TRANSACTION_INSTALL: + if (count) + pakfire_string_format(headline, _("Installing %u packages:"), count); + else + pakfire_string_set(headline, _("Installing one package:")); + break; + + case SOLVER_TRANSACTION_REINSTALLED: + if (count) + pakfire_string_format(headline, _("Reinstalling %u packages:"), count); + else + pakfire_string_set(headline, _("Reinstalling one package:")); + break; + + case SOLVER_TRANSACTION_ERASE: + if (count) + pakfire_string_format(headline, _("Removing %u packages:"), count); + else + pakfire_string_set(headline, _("Removing one package:")); + break; + + case SOLVER_TRANSACTION_UPGRADED: + if (count) + pakfire_string_format(headline, _("Updating %u packages:"), count); + else + pakfire_string_set(headline, _("Updating one package:")); + break; + + case SOLVER_TRANSACTION_DOWNGRADED: + if (count) + pakfire_string_format(headline, _("Downgrading %u packages:"), count); + else + pakfire_string_set(headline, _("Downgrading one package:")); + break; + + case SOLVER_TRANSACTION_CHANGED: + if (count) + pakfire_string_format(headline, _("Changing %u packages:"), count); + else + pakfire_string_set(headline, _("Changing one package:")); + break; + + case SOLVER_TRANSACTION_ARCHCHANGE: + if (count) + pakfire_string_format(headline, + _("%u architecture changes from '%s' to '%s':"), count, from, to); + else + pakfire_string_format(headline, + _("One architecture change from '%s' to '%s':"), from, to); + break; + + case SOLVER_TRANSACTION_VENDORCHANGE: + if (count) + pakfire_string_format(headline, + _("%u vendor changes from '%s' to '%s':"), count, from, to); + else + pakfire_string_format(headline, + _("One vendor change from '%s' to '%s':"), from, to); + break; + + case SOLVER_TRANSACTION_IGNORE: + continue; + } + + // Show what we are doing + pakfire_transaction_add_headline(&string, width, headline); + + // Fetch packages in this class + transaction_classify_pkgs(transaction->transaction, mode, class, + classes.elements[i+2], classes.elements[i+3], &pkgs); + + // List all packages + for (int j = 0; j < pkgs.count; j++) { + PakfirePackage pkg1 = pakfire_package_create_from_solvable( + transaction->pakfire, pkgs.elements[j]); + PakfirePackage pkg2 = NULL; + + switch (class) { + case SOLVER_TRANSACTION_UPGRADED: + case SOLVER_TRANSACTION_DOWNGRADED: + pkg2 = pakfire_package_create_from_solvable(transaction->pakfire, + transaction_obs_pkg(transaction->transaction, pkgs.elements[j])); + + pakfire_transaction_add_package_change(&string, width, pkg1, pkg2); + break; + + default: + pakfire_transaction_add_package(&string, width, pkg1); + break; + } + + pakfire_package_unref(pkg1); + if (pkg2) + pakfire_package_unref(pkg2); + } + + // Newline + pakfire_transaction_add_newline(&string, width); + } + + queue_free(&classes); + queue_free(&pkgs); // Summary pakfire_transaction_add_headline(&string, width, _("Transaction Summary")); pakfire_transaction_add_separator(&string, width); - pakfire_transaction_add_summary_line(&string, width, _("Installing:"), installing); - pakfire_transaction_add_summary_line(&string, width, _("Reinstalling:"), reinstalling); - pakfire_transaction_add_summary_line(&string, width, _("Updating:"), updating); - pakfire_transaction_add_summary_line(&string, width, _("Downgrading:"), downgrading); - pakfire_transaction_add_summary_line(&string, width, _("Removing:"), removing); - pakfire_transaction_add_summary_line(&string, width, _("Obsoleting:"), obsoleting); - // How much do we need to download? size_t downloadsize = pakfire_transaction_downloadsize(transaction); + if (downloadsize > 0) pakfire_transaction_add_usage_line(&string, width, _("Total Download Size"), downloadsize); // How much more space do we need? ssize_t sizechange = pakfire_transaction_installsizechange(transaction); - pakfire_transaction_add_usage_line(&string, width, (sizechange >= 0) ? _("Installed Size") : _("Freed Size"), sizechange); @@ -347,9 +462,8 @@ static int pakfire_transaction_run_steps(PakfireTransaction transaction, int r = 0; // Walk through all steps - PakfireStep* steps = transaction->steps; - while (*steps) { - PakfireStep step = *steps++; + for (unsigned int i = 0; i < transaction->num_steps; i++) { + PakfireStep step = transaction->steps[i]; // Verify the step r = pakfire_step_run(step, db, action); @@ -410,7 +524,6 @@ static int pakfire_transaction_download_package(PakfireTransaction transaction, int r = 1; PakfireRepo repo = NULL; struct pakfire_mirrorlist* mirrorlist = NULL; - char* nevra = NULL; // Fetch the repository to download from repo = pakfire_package_get_repo(pkg); @@ -433,7 +546,7 @@ static int pakfire_transaction_download_package(PakfireTransaction transaction, if (!filename) goto ERROR; - nevra = pakfire_package_get_nevra(pkg); + const char* nevra = pakfire_package_get_nevra(pkg); if (!nevra) goto ERROR; @@ -442,8 +555,6 @@ static int pakfire_transaction_download_package(PakfireTransaction transaction, nevra, filename, path, 0); ERROR: - if (nevra) - free(nevra); if (mirrorlist) pakfire_mirrorlist_unref(mirrorlist); if (repo)