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_dictionary_t dict, curdict;
prop_array_t array, rundeps_array, reqby_array; prop_array_t array, rundeps_array, reqby_array;
prop_string_t reqbystr; prop_string_t reqbystr;
uint32_t prio = 0;
size_t len = 0, dirdepscnt = 0, indirdepscnt = 0; size_t len = 0, dirdepscnt = 0, indirdepscnt = 0;
const char *pkgname, *version, *reqbyname, *reqbyver, *arch; const char *pkgname, *version, *reqbyname, *reqbyver, *arch;
const char *repoloc, *binfile, *originpkg, *short_desc; 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, "short_desc", &short_desc);
prop_dictionary_get_cstring_nocopy(depd, "architecture", &arch); prop_dictionary_get_cstring_nocopy(depd, "architecture", &arch);
prop_dictionary_get_cstring_nocopy(depd, "filename-sha256", &sha256); 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, "pkgname", &reqbyname);
prop_dictionary_get_cstring_nocopy(origind, "version", &reqbyver); prop_dictionary_get_cstring_nocopy(origind, "version", &reqbyver);
prop_dictionary_get_cstring_nocopy(repod, "location-local", &repoloc); 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); prop_dictionary_get_cstring_nocopy(chaindeps, "origin", &originpkg);
curdict = xbps_find_pkg_in_dict(chaindeps, "unsorted_deps", pkgname); curdict = xbps_find_pkg_in_dict(chaindeps, "unsorted_deps", pkgname);
/* /*
* Update priority and required_by objects. * Update equired_by objects.
*/ */
if (curdict) { if (curdict) {
prop_dictionary_get_uint32(curdict, "priority", &prio);
prop_dictionary_set_uint32(curdict, "priority", ++prio);
reqby_array = prop_dictionary_get(curdict, "required_by"); reqby_array = prop_dictionary_get(curdict, "required_by");
if (!xbps_find_string_in_array(reqby_array, reqby)) if (!xbps_find_string_in_array(reqby_array, reqby))
prop_array_add(reqby_array, reqbystr); 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(dict, "required_by", reqby_array);
prop_dictionary_set_cstring(dict, "repository", repoloc); prop_dictionary_set_cstring(dict, "repository", repoloc);
prop_dictionary_set_cstring(dict, "filename", binfile); 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_cstring(dict, "short_desc", short_desc);
prop_dictionary_set_bool(dict, "indirect_dep", indirectdep); prop_dictionary_set_bool(dict, "indirect_dep", indirectdep);
prop_dictionary_set_cstring(dict, "architecture", arch); prop_dictionary_set_cstring(dict, "architecture", arch);

View file

@ -35,78 +35,15 @@
struct sorted_dependency { struct sorted_dependency {
SIMPLEQ_ENTRY(sorted_dependency) chain; SIMPLEQ_ENTRY(sorted_dependency) chain;
prop_dictionary_t dict; prop_dictionary_t dict;
prop_array_t reqby;
size_t idx;
size_t prio;
}; };
static SIMPLEQ_HEAD(sdep_head, sorted_dependency) sdep_list = static SIMPLEQ_HEAD(sdep_head, sorted_dependency) sdep_list =
SIMPLEQ_HEAD_INITIALIZER(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 * static struct sorted_dependency *
find_sorteddep_by_name(const char *pkgname) find_sorteddep_by_name(const char *pkgname)
{ {
struct sorted_dependency *sdep; struct sorted_dependency *sdep = NULL;
const char *curname; const char *curname;
SIMPLEQ_FOREACH(sdep, &sdep_list, chain) { SIMPLEQ_FOREACH(sdep, &sdep_list, chain) {
@ -122,16 +59,13 @@ find_sorteddep_by_name(const char *pkgname)
int int
xbps_sort_pkg_deps(prop_dictionary_t chaindeps) xbps_sort_pkg_deps(prop_dictionary_t chaindeps)
{ {
prop_array_t sorted, unsorted, rundeps_array, reqby; prop_array_t sorted, unsorted, rundeps;
prop_dictionary_t dict; prop_object_t obj, obj2;
prop_object_t obj; prop_object_iterator_t iter, iter2;
prop_object_iterator_t iter; struct sorted_dependency *sdep;
struct sorted_dependency *sdep, *sdep2; size_t indirdepscnt = 0, dirdepscnt = 0, rundepscnt = 0, cnt = 0;
uint32_t maxprio = 0; const char *pkgname;
size_t indirdepscnt = 0, dirdepscnt = 0, cnt = 0; char *curpkgnamedep;
ssize_t curidx = 0;
const char *curpkg, *rundep;
char *pkgname;
int rv = 0; int rv = 0;
assert(chaindeps != NULL); assert(chaindeps != NULL);
@ -154,113 +88,89 @@ xbps_sort_pkg_deps(prop_dictionary_t chaindeps)
prop_dictionary_get_uint32(chaindeps, "directdeps_count", prop_dictionary_get_uint32(chaindeps, "directdeps_count",
&dirdepscnt); &dirdepscnt);
unsorted = prop_dictionary_get(chaindeps, "unsorted_deps"); 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) { while ((obj = prop_object_iterator_next(iter)) != NULL) {
curidx = find_pkgdict_with_highest_prio(unsorted, &maxprio); prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
if (curidx == -1) { if (find_sorteddep_by_name(pkgname) != NULL)
rv = errno; continue;
goto out;
}
dict = prop_array_get(unsorted, curidx);
if (dict == NULL) {
rv = errno;
goto out;
}
sdep = calloc(1, sizeof(*sdep)); sdep = calloc(1, sizeof(*sdep));
if (sdep == NULL) { if (sdep == NULL) {
rv = ENOMEM; rv = ENOMEM;
goto out; goto out;
} }
sdep->dict = prop_dictionary_copy(dict); /*
sdep->idx = cnt; * Packages that don't have deps go unsorted, because
prop_dictionary_get_uint32(dict, "priority", &sdep->prio); * it doesn't matter.
reqby = prop_dictionary_get(dict, "required_by"); */
if (reqby && prop_array_count(reqby) > 0) rundeps = prop_dictionary_get(obj, "run_depends");
sdep->reqby = prop_array_copy(reqby); if (rundeps == NULL || prop_array_count(rundeps) == 0) {
SIMPLEQ_INSERT_TAIL(&sdep_list, sdep, chain); sdep->dict = prop_dictionary_copy(obj);
prop_array_remove(unsorted, curidx); SIMPLEQ_INSERT_TAIL(&sdep_list, sdep, chain);
maxprio = 0; cnt++;
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;
continue; continue;
} }
iter2 = prop_array_iterator(rundeps);
iter = prop_array_iterator(rundeps_array); if (iter2 == NULL) {
if (iter == NULL) { free(sdep);
rv = ENOMEM; rv = ENOMEM;
goto out; goto out;
} }
/*
while ((obj = prop_object_iterator_next(iter)) != NULL) { * Iterate over the run_depends array, and find out if they
rundep = prop_string_cstring_nocopy(obj); * were already added in the sorted list.
pkgname = xbps_get_pkg_name(rundep); */
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) { if (xbps_check_is_installed_pkgname(curpkgnamedep))
free(pkgname); rundepscnt++;
continue; else if (find_sorteddep_by_name(curpkgnamedep) != NULL)
} rundepscnt++;
/* Ignore itself */
if (strcmp(curpkg, pkgname) == 0) {
free(pkgname);
continue;
}
sdep2 = find_sorteddep_by_name(pkgname); free(curpkgnamedep);
free(pkgname);
sdep2->prio++;
} }
prop_object_iterator_release(iter); prop_object_iterator_release(iter2);
}
prop_dictionary_remove(chaindeps, "unsorted_deps");
/* /* Add dependency if all its required deps are already added */
* Pass 3: increase priority of a package, by looking at if (rundepscnt != 0 && (prop_array_count(rundeps) == rundepscnt)) {
* its required_by array member's priority. sdep->dict = prop_dictionary_copy(obj);
*/ SIMPLEQ_INSERT_TAIL(&sdep_list, sdep, chain);
SIMPLEQ_FOREACH(sdep, &sdep_list, chain) { rundepscnt = 0;
iter = prop_array_iterator(sdep->reqby); cnt++;
if (iter == NULL)
continue; 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 * Add all sorted dependencies into the sorted deps array.
* correct index position for all dependencies and release
* resources used by the sorting passes.
*/ */
while ((sdep = find_sorteddep_with_highest_prio()) != NULL) { while ((sdep = SIMPLEQ_FIRST(&sdep_list)) != NULL) {
prop_array_add(sorted, sdep->dict); prop_array_add(sorted, sdep->dict);
SIMPLEQ_REMOVE(&sdep_list, sdep, sorted_dependency, chain); SIMPLEQ_REMOVE(&sdep_list, sdep, sorted_dependency, chain);
prop_object_release(sdep->dict); prop_object_release(sdep->dict);
prop_object_release(sdep->reqby);
free(sdep); free(sdep);
} }
@ -284,7 +194,6 @@ out:
while ((sdep = SIMPLEQ_FIRST(&sdep_list)) != NULL) { while ((sdep = SIMPLEQ_FIRST(&sdep_list)) != NULL) {
SIMPLEQ_REMOVE(&sdep_list, sdep, sorted_dependency, chain); SIMPLEQ_REMOVE(&sdep_list, sdep, sorted_dependency, chain);
prop_object_release(sdep->dict); prop_object_release(sdep->dict);
prop_object_release(sdep->reqby);
free(sdep); free(sdep);
} }