From da1cfa2cf2b8fafe4053f5216a92c02ee584d7c0 Mon Sep 17 00:00:00 2001 From: Juan RP Date: Thu, 26 Mar 2009 09:26:07 +0100 Subject: [PATCH] New dependency sorting code that doesn't use priorities. This new code correctly sorts all dependencies without needing to look at required_by or priority objects. --HG-- extra : convert_revision : 3aa07372ae07e6938b9120d560a49efdaeac0a4e --- lib/depends.c | 7 +- lib/sortdeps.c | 221 +++++++++++++++---------------------------------- 2 files changed, 66 insertions(+), 162 deletions(-) diff --git a/lib/depends.c b/lib/depends.c index 56425217f19..74dfa1b1fb1 100644 --- a/lib/depends.c +++ b/lib/depends.c @@ -94,7 +94,6 @@ store_dependency(prop_dictionary_t origind, prop_dictionary_t depd, prop_dictionary_t dict, curdict; prop_array_t array, rundeps_array, reqby_array; prop_string_t reqbystr; - uint32_t prio = 0; size_t len = 0, dirdepscnt = 0, indirdepscnt = 0; const char *pkgname, *version, *reqbyname, *reqbyver, *arch; const char *repoloc, *binfile, *originpkg, *short_desc; @@ -116,7 +115,6 @@ store_dependency(prop_dictionary_t origind, prop_dictionary_t depd, prop_dictionary_get_cstring_nocopy(depd, "short_desc", &short_desc); prop_dictionary_get_cstring_nocopy(depd, "architecture", &arch); prop_dictionary_get_cstring_nocopy(depd, "filename-sha256", &sha256); - prop_dictionary_get_uint32(depd, "priority", &prio); prop_dictionary_get_cstring_nocopy(origind, "pkgname", &reqbyname); prop_dictionary_get_cstring_nocopy(origind, "version", &reqbyver); prop_dictionary_get_cstring_nocopy(repod, "location-local", &repoloc); @@ -145,11 +143,9 @@ store_dependency(prop_dictionary_t origind, prop_dictionary_t depd, prop_dictionary_get_cstring_nocopy(chaindeps, "origin", &originpkg); curdict = xbps_find_pkg_in_dict(chaindeps, "unsorted_deps", pkgname); /* - * Update priority and required_by objects. + * Update equired_by objects. */ if (curdict) { - prop_dictionary_get_uint32(curdict, "priority", &prio); - prop_dictionary_set_uint32(curdict, "priority", ++prio); reqby_array = prop_dictionary_get(curdict, "required_by"); if (!xbps_find_string_in_array(reqby_array, reqby)) prop_array_add(reqby_array, reqbystr); @@ -203,7 +199,6 @@ store_dependency(prop_dictionary_t origind, prop_dictionary_t depd, prop_dictionary_set(dict, "required_by", reqby_array); prop_dictionary_set_cstring(dict, "repository", repoloc); prop_dictionary_set_cstring(dict, "filename", binfile); - prop_dictionary_set_uint32(dict, "priority", prio); prop_dictionary_set_cstring(dict, "short_desc", short_desc); prop_dictionary_set_bool(dict, "indirect_dep", indirectdep); prop_dictionary_set_cstring(dict, "architecture", arch); diff --git a/lib/sortdeps.c b/lib/sortdeps.c index 14b55f21044..8419dc48b9f 100644 --- a/lib/sortdeps.c +++ b/lib/sortdeps.c @@ -35,78 +35,15 @@ struct sorted_dependency { SIMPLEQ_ENTRY(sorted_dependency) chain; prop_dictionary_t dict; - prop_array_t reqby; - size_t idx; - size_t prio; }; static SIMPLEQ_HEAD(sdep_head, sorted_dependency) sdep_list = SIMPLEQ_HEAD_INITIALIZER(sdep_list); -static ssize_t -find_pkgdict_with_highest_prio(prop_array_t array, uint32_t *maxprio) -{ - prop_object_t obj; - prop_object_iterator_t iter; - uint32_t prio = 0; - size_t idx = 0; - ssize_t curidx = -1; - - assert(array != NULL); - - iter = prop_array_iterator(array); - if (iter == NULL) { - errno = ENOMEM; - return -1; - } - /* - * Finds the index of a package with the highest priority. - */ - while ((obj = prop_object_iterator_next(iter)) != NULL) { - prop_dictionary_get_uint32(obj, "priority", &prio); - if (*maxprio <= prio) { - curidx = idx; - *maxprio = prio; - } - idx++; - } - prop_object_iterator_release(iter); - - if (curidx == -1) - errno = ENOENT; - - return curidx; -} - -static struct sorted_dependency * -find_sorteddep_with_highest_prio(void) -{ - struct sorted_dependency *sdep; - size_t maxprio = 0; - size_t curidx = 0, idx = 0; - - SIMPLEQ_FOREACH(sdep, &sdep_list, chain) { - if (maxprio <= sdep->prio) { - curidx = idx; - maxprio = sdep->prio; - } - idx++; - } - - idx = 0; - SIMPLEQ_FOREACH(sdep, &sdep_list, chain) { - if (idx == curidx) - break; - idx++; - } - - return sdep; -} - static struct sorted_dependency * find_sorteddep_by_name(const char *pkgname) { - struct sorted_dependency *sdep; + struct sorted_dependency *sdep = NULL; const char *curname; SIMPLEQ_FOREACH(sdep, &sdep_list, chain) { @@ -122,16 +59,13 @@ find_sorteddep_by_name(const char *pkgname) int xbps_sort_pkg_deps(prop_dictionary_t chaindeps) { - prop_array_t sorted, unsorted, rundeps_array, reqby; - prop_dictionary_t dict; - prop_object_t obj; - prop_object_iterator_t iter; - struct sorted_dependency *sdep, *sdep2; - uint32_t maxprio = 0; - size_t indirdepscnt = 0, dirdepscnt = 0, cnt = 0; - ssize_t curidx = 0; - const char *curpkg, *rundep; - char *pkgname; + prop_array_t sorted, unsorted, rundeps; + prop_object_t obj, obj2; + prop_object_iterator_t iter, iter2; + struct sorted_dependency *sdep; + size_t indirdepscnt = 0, dirdepscnt = 0, rundepscnt = 0, cnt = 0; + const char *pkgname; + char *curpkgnamedep; int rv = 0; assert(chaindeps != NULL); @@ -154,113 +88,89 @@ xbps_sort_pkg_deps(prop_dictionary_t chaindeps) prop_dictionary_get_uint32(chaindeps, "directdeps_count", &dirdepscnt); unsorted = prop_dictionary_get(chaindeps, "unsorted_deps"); + + iter = prop_array_iterator(unsorted); + if (iter == NULL) { + prop_object_release(sorted); + return ENOMEM; + } +again: /* - * Pass 1: order all deps (direct/indirect) by priority. + * Order all deps by looking at its run_depends array. */ - while (cnt < dirdepscnt + indirdepscnt) { - curidx = find_pkgdict_with_highest_prio(unsorted, &maxprio); - if (curidx == -1) { - rv = errno; - goto out; - } - dict = prop_array_get(unsorted, curidx); - if (dict == NULL) { - rv = errno; - goto out; - } + while ((obj = prop_object_iterator_next(iter)) != NULL) { + prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); + if (find_sorteddep_by_name(pkgname) != NULL) + continue; + sdep = calloc(1, sizeof(*sdep)); if (sdep == NULL) { rv = ENOMEM; goto out; } - sdep->dict = prop_dictionary_copy(dict); - sdep->idx = cnt; - prop_dictionary_get_uint32(dict, "priority", &sdep->prio); - reqby = prop_dictionary_get(dict, "required_by"); - if (reqby && prop_array_count(reqby) > 0) - sdep->reqby = prop_array_copy(reqby); - SIMPLEQ_INSERT_TAIL(&sdep_list, sdep, chain); - prop_array_remove(unsorted, curidx); - maxprio = 0; - cnt++; - } - - /* - * Pass 2: increase priority of dependencies any time - * a package requires them. - */ - SIMPLEQ_FOREACH(sdep, &sdep_list, chain) { - prop_dictionary_get_cstring_nocopy(sdep->dict, - "pkgname", &curpkg); - rundeps_array = prop_dictionary_get(sdep->dict, "run_depends"); - if (rundeps_array == NULL) { - sdep->prio += 4; + /* + * Packages that don't have deps go unsorted, because + * it doesn't matter. + */ + rundeps = prop_dictionary_get(obj, "run_depends"); + if (rundeps == NULL || prop_array_count(rundeps) == 0) { + sdep->dict = prop_dictionary_copy(obj); + SIMPLEQ_INSERT_TAIL(&sdep_list, sdep, chain); + cnt++; continue; } - - iter = prop_array_iterator(rundeps_array); - if (iter == NULL) { + iter2 = prop_array_iterator(rundeps); + if (iter2 == NULL) { + free(sdep); rv = ENOMEM; goto out; } - - while ((obj = prop_object_iterator_next(iter)) != NULL) { - rundep = prop_string_cstring_nocopy(obj); - pkgname = xbps_get_pkg_name(rundep); + /* + * Iterate over the run_depends array, and find out if they + * were already added in the sorted list. + */ + while ((obj2 = prop_object_iterator_next(iter2)) != NULL) { + curpkgnamedep = + xbps_get_pkg_name(prop_string_cstring_nocopy(obj2)); /* - * If package is installed, pass to the next one. + * If dependency is already installed or queued, + * pass to the next one. */ - if (xbps_check_is_installed_pkg(rundep) >= 0) { - free(pkgname); - continue; - } - /* Ignore itself */ - if (strcmp(curpkg, pkgname) == 0) { - free(pkgname); - continue; - } + if (xbps_check_is_installed_pkgname(curpkgnamedep)) + rundepscnt++; + else if (find_sorteddep_by_name(curpkgnamedep) != NULL) + rundepscnt++; - sdep2 = find_sorteddep_by_name(pkgname); - free(pkgname); - sdep2->prio++; + free(curpkgnamedep); } - prop_object_iterator_release(iter); - } - prop_dictionary_remove(chaindeps, "unsorted_deps"); + prop_object_iterator_release(iter2); - /* - * Pass 3: increase priority of a package, by looking at - * its required_by array member's priority. - */ - SIMPLEQ_FOREACH(sdep, &sdep_list, chain) { - iter = prop_array_iterator(sdep->reqby); - if (iter == NULL) + /* Add dependency if all its required deps are already added */ + if (rundepscnt != 0 && (prop_array_count(rundeps) == rundepscnt)) { + sdep->dict = prop_dictionary_copy(obj); + SIMPLEQ_INSERT_TAIL(&sdep_list, sdep, chain); + rundepscnt = 0; + cnt++; continue; - - while ((obj = prop_object_iterator_next(iter))) { - rundep = prop_string_cstring_nocopy(obj); - pkgname = xbps_get_pkg_name(rundep); - sdep2 = find_sorteddep_by_name(pkgname); - if (sdep2 == NULL) { - free(pkgname); - continue; - } - free(pkgname); - sdep->prio += sdep2->prio + 1; } - prop_object_iterator_release(iter); + free(sdep); + rundepscnt = 0; } + /* Iterate until all deps are processed. */ + if (cnt < dirdepscnt + indirdepscnt) { + prop_object_iterator_reset(iter); + goto again; + } + prop_object_iterator_release(iter); + /* - * Pass 4: copy dictionaries into the final array with the - * correct index position for all dependencies and release - * resources used by the sorting passes. + * Add all sorted dependencies into the sorted deps array. */ - while ((sdep = find_sorteddep_with_highest_prio()) != NULL) { + while ((sdep = SIMPLEQ_FIRST(&sdep_list)) != NULL) { prop_array_add(sorted, sdep->dict); SIMPLEQ_REMOVE(&sdep_list, sdep, sorted_dependency, chain); prop_object_release(sdep->dict); - prop_object_release(sdep->reqby); free(sdep); } @@ -284,7 +194,6 @@ out: while ((sdep = SIMPLEQ_FIRST(&sdep_list)) != NULL) { SIMPLEQ_REMOVE(&sdep_list, sdep, sorted_dependency, chain); prop_object_release(sdep->dict); - prop_object_release(sdep->reqby); free(sdep); }