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
This commit is contained in:
Juan RP 2009-03-26 09:26:07 +01:00
parent 6bfaa75f3e
commit da1cfa2cf2
2 changed files with 66 additions and 162 deletions

View File

@ -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);

View File

@ -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);
}