Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Move priorities management to pkg_universe.
Vsevolod Stakhov committed 11 years ago
commit 5390b201df1d705a0f7705fe15f45385c2bdc24d
parent 07ea0f2
4 files changed +225 -155
modified libpkg/Makefile.am
@@ -29,6 +29,7 @@ libpkg_la_SOURCES= pkg.c \
			pkg_elf.c \
			pkg_event.c \
			pkg_jobs.c \
+
			pkg_jobs_universe.c \
			pkg_manifest.c \
			pkg_object.c \
			pkg_ports.c \
modified libpkg/pkg_jobs.c
@@ -315,155 +315,7 @@ pkg_jobs_add_req(struct pkg_jobs *j, const char *uid,
	HASH_ADD_KEYPTR(hh, *head, uid, strlen(uid), req);
}

-
enum pkg_priority_update_type {
-
	PKG_PRIORITY_UPDATE_REQUEST = 0,
-
	PKG_PRIORITY_UPDATE_UNIVERSE,
-
	PKG_PRIORITY_UPDATE_CONFLICT,
-
	PKG_PRIORITY_UPDATE_DELETE
-
};
-

-
#define RECURSION_LIMIT 1024
-

-
static void
-
pkg_jobs_update_universe_priority(struct pkg_jobs *j,
-
		struct pkg_job_universe_item *item, int priority,
-
		enum pkg_priority_update_type type)
-
{
-
	const char *uid, *digest;
-
	struct pkg_dep *d = NULL;
-
	struct pkg_conflict *c = NULL;
-
	struct pkg_job_universe_item *found, *cur, *it;
-
	const char *is_local;
-
	int maxpri;

-
	int (*deps_func)(const struct pkg *pkg, struct pkg_dep **d);
-
	int (*rdeps_func)(const struct pkg *pkg, struct pkg_dep **d);
-

-
	if (priority > RECURSION_LIMIT) {
-
		pkg_debug(1, "recursion limit has been reached, something is bad"
-
					" with dependencies/conflicts graph");
-
		return;
-
	}
-
	else if (priority + 10 > RECURSION_LIMIT) {
-
		pkg_get(item->pkg, PKG_UNIQUEID, &uid);
-
		pkg_debug(2, "approaching recursion limit at %d, while processing of"
-
					" package %s", priority, uid);
-
	}
-

-
	LL_FOREACH(item, it) {
-

-
		pkg_get(it->pkg, PKG_UNIQUEID, &uid, PKG_DIGEST, &digest);
-
		if ((item->next != NULL || item->prev != NULL) &&
-
				it->pkg->type != PKG_INSTALLED &&
-
				(type == PKG_PRIORITY_UPDATE_CONFLICT ||
-
				 type == PKG_PRIORITY_UPDATE_DELETE)) {
-
			/*
-
			 * We do not update priority of a remote part of conflict, as we know
-
			 * that remote packages should not contain conflicts (they should be
-
			 * resolved in request prior to calling of this function)
-
			 */
-
			pkg_debug(4, "skip update priority for %s-%s", uid, digest);
-
			continue;
-
		}
-
		if (it->priority > priority)
-
			continue;
-

-
		is_local = it->pkg->type == PKG_INSTALLED ? "local" : "remote";
-
		pkg_debug(2, "universe: update %s priority of %s(%s): %d -> %d, reason: %d",
-
				is_local, uid, digest, it->priority, priority, type);
-
		it->priority = priority;
-

-
		if (type == PKG_PRIORITY_UPDATE_DELETE) {
-
			/*
-
			 * For delete requests we inverse deps and rdeps logic
-
			 */
-
			deps_func = pkg_rdeps;
-
			rdeps_func = pkg_deps;
-
		}
-
		else {
-
			deps_func = pkg_deps;
-
			rdeps_func = pkg_rdeps;
-
		}
-

-
		while (deps_func(it->pkg, &d) == EPKG_OK) {
-
			HASH_FIND_STR(j->universe, d->uid, found);
-
			if (found != NULL) {
-
				LL_FOREACH(found, cur) {
-
					if (cur->priority < priority + 1)
-
						pkg_jobs_update_universe_priority(j, cur,
-
								priority + 1, type);
-
				}
-
			}
-
		}
-

-
		d = NULL;
-
		maxpri = priority;
-
		while (rdeps_func(it->pkg, &d) == EPKG_OK) {
-
			HASH_FIND_STR(j->universe, d->uid, found);
-
			if (found != NULL) {
-
				LL_FOREACH(found, cur) {
-
					if (cur->priority >= maxpri) {
-
						maxpri = cur->priority + 1;
-
					}
-
				}
-
			}
-
		}
-
		if (maxpri != priority) {
-
			pkg_jobs_update_universe_priority(j, it,
-
					maxpri, type);
-
			return;
-
		}
-
		if (it->pkg->type != PKG_INSTALLED) {
-
			while (pkg_conflicts(it->pkg, &c) == EPKG_OK) {
-
				HASH_FIND_STR(j->universe, pkg_conflict_uniqueid(c), found);
-
				if (found != NULL) {
-
					LL_FOREACH(found, cur) {
-
						if (cur->pkg->type == PKG_INSTALLED) {
-
							/*
-
							 * Move delete requests to be done before installing
-
							 */
-
							if (cur->priority <= it->priority)
-
								pkg_jobs_update_universe_priority(j, cur,
-
									it->priority + 1, PKG_PRIORITY_UPDATE_CONFLICT);
-
						}
-
					}
-
				}
-
			}
-
		}
-
	}
-
}
-

-
static void
-
pkg_jobs_update_conflict_priority(struct pkg_jobs *j, struct pkg_solved *req)
-
{
-
	struct pkg_conflict *c = NULL;
-
	struct pkg *lp = req->items[1]->pkg;
-
	struct pkg_job_universe_item *found, *cur, *rit = NULL;
-

-
	while (pkg_conflicts(lp, &c) == EPKG_OK) {
-
		rit = NULL;
-
		HASH_FIND_STR(j->universe, pkg_conflict_uniqueid(c), found);
-
		assert(found != NULL);
-

-
		LL_FOREACH(found, cur) {
-
			if (cur->pkg->type != PKG_INSTALLED) {
-
				rit = cur;
-
				break;
-
			}
-
		}
-

-
		assert(rit != NULL);
-
		if (rit->priority >= req->items[1]->priority) {
-
			pkg_jobs_update_universe_priority(j, req->items[1],
-
					rit->priority + 1, PKG_PRIORITY_UPDATE_CONFLICT);
-
			/*
-
			 * Update priorities for a remote part as well
-
			 */
-
			pkg_jobs_update_universe_priority(j, req->items[0],
-
					req->items[0]->priority, PKG_PRIORITY_UPDATE_REQUEST);
-
		}
-
	}
-
}

static int
pkg_jobs_set_request_priority(struct pkg_jobs *j, struct pkg_solved *req)
@@ -478,7 +330,7 @@ pkg_jobs_set_request_priority(struct pkg_jobs *j, struct pkg_solved *req)
		 * update priorities of local packages and try to update priorities of remote ones
		 */
		if (req->items[0]->priority == 0)
-
			pkg_jobs_update_conflict_priority(j, req);
+
			pkg_jobs_update_conflict_priority(j->universe, req);

		if (req->items[1]->priority > req->items[0]->priority &&
				!req->already_deleted) {
@@ -503,12 +355,12 @@ pkg_jobs_set_request_priority(struct pkg_jobs *j, struct pkg_solved *req)
	}
	else if (req->type == PKG_SOLVED_DELETE) {
		if (req->items[0]->priority == 0)
-
			pkg_jobs_update_universe_priority(j, req->items[0], 0,
+
			pkg_jobs_update_universe_priority(j->universe, req->items[0],
					PKG_PRIORITY_UPDATE_DELETE);
	}
	else {
		if (req->items[0]->priority == 0)
-
			pkg_jobs_update_universe_priority(j, req->items[0], 0,
+
			pkg_jobs_update_universe_priority(j->universe, req->items[0],
					PKG_PRIORITY_UPDATE_REQUEST);
	}

added libpkg/pkg_jobs_universe.c
@@ -0,0 +1,191 @@
+
/* Copyright (c) 2014, Vsevolod Stakhov
+
 * All rights reserved.
+
 *
+
 * Redistribution and use in source and binary forms, with or without
+
 * modification, are permitted provided that the following conditions are met:
+
 *       * Redistributions of source code must retain the above copyright
+
 *         notice, this list of conditions and the following disclaimer.
+
 *       * Redistributions in binary form must reproduce the above copyright
+
 *         notice, this list of conditions and the following disclaimer in the
+
 *         documentation and/or other materials provided with the distribution.
+
 *
+
 * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
+
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+
 * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
+
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
 */
+

+
#include <sys/param.h>
+
#include <sys/types.h>
+

+
#include <assert.h>
+
#include <errno.h>
+
#include <libutil.h>
+
#include <stdbool.h>
+
#include <stdlib.h>
+
#include <string.h>
+
#include <ctype.h>
+

+
#include "pkg.h"
+
#include "private/event.h"
+
#include "private/pkg.h"
+
#include "private/pkgdb.h"
+
#include "private/pkg_jobs.h"
+

+
#define RECURSION_LIMIT 1024
+

+
static void
+
pkg_jobs_update_universe_item_priority(struct pkg_jobs_universe *universe,
+
		struct pkg_job_universe_item *item, int priority,
+
		enum pkg_priority_update_type type)
+
{
+
	const char *uid, *digest;
+
	struct pkg_dep *d = NULL;
+
	struct pkg_conflict *c = NULL;
+
	struct pkg_job_universe_item *found, *cur, *it;
+
	const char *is_local;
+
	int maxpri;
+

+
	int (*deps_func)(const struct pkg *pkg, struct pkg_dep **d);
+
	int (*rdeps_func)(const struct pkg *pkg, struct pkg_dep **d);
+

+
	if (priority > RECURSION_LIMIT) {
+
		pkg_debug(1, "recursion limit has been reached, something is bad"
+
					" with dependencies/conflicts graph");
+
		return;
+
	}
+
	else if (priority + 10 > RECURSION_LIMIT) {
+
		pkg_get(item->pkg, PKG_UNIQUEID, &uid);
+
		pkg_debug(2, "approaching recursion limit at %d, while processing of"
+
					" package %s", priority, uid);
+
	}
+

+
	LL_FOREACH(item, it) {
+

+
		pkg_get(it->pkg, PKG_UNIQUEID, &uid, PKG_DIGEST, &digest);
+
		if ((item->next != NULL || item->prev != NULL) &&
+
				it->pkg->type != PKG_INSTALLED &&
+
				(type == PKG_PRIORITY_UPDATE_CONFLICT ||
+
				 type == PKG_PRIORITY_UPDATE_DELETE)) {
+
			/*
+
			 * We do not update priority of a remote part of conflict, as we know
+
			 * that remote packages should not contain conflicts (they should be
+
			 * resolved in request prior to calling of this function)
+
			 */
+
			pkg_debug(4, "skip update priority for %s-%s", uid, digest);
+
			continue;
+
		}
+
		if (it->priority > priority)
+
			continue;
+

+
		is_local = it->pkg->type == PKG_INSTALLED ? "local" : "remote";
+
		pkg_debug(2, "universe: update %s priority of %s(%s): %d -> %d, reason: %d",
+
				is_local, uid, digest, it->priority, priority, type);
+
		it->priority = priority;
+

+
		if (type == PKG_PRIORITY_UPDATE_DELETE) {
+
			/*
+
			 * For delete requests we inverse deps and rdeps logic
+
			 */
+
			deps_func = pkg_rdeps;
+
			rdeps_func = pkg_deps;
+
		}
+
		else {
+
			deps_func = pkg_deps;
+
			rdeps_func = pkg_rdeps;
+
		}
+

+
		while (deps_func(it->pkg, &d) == EPKG_OK) {
+
			HASH_FIND_STR(universe->items, d->uid, found);
+
			if (found != NULL) {
+
				LL_FOREACH(found, cur) {
+
					if (cur->priority < priority + 1)
+
						pkg_jobs_update_universe_item_priority(universe, cur,
+
								priority + 1, type);
+
				}
+
			}
+
		}
+

+
		d = NULL;
+
		maxpri = priority;
+
		while (rdeps_func(it->pkg, &d) == EPKG_OK) {
+
			HASH_FIND_STR(universe->items, d->uid, found);
+
			if (found != NULL) {
+
				LL_FOREACH(found, cur) {
+
					if (cur->priority >= maxpri) {
+
						maxpri = cur->priority + 1;
+
					}
+
				}
+
			}
+
		}
+
		if (maxpri != priority) {
+
			pkg_jobs_update_universe_item_priority(universe, it,
+
					maxpri, type);
+
			return;
+
		}
+
		if (it->pkg->type != PKG_INSTALLED) {
+
			while (pkg_conflicts(it->pkg, &c) == EPKG_OK) {
+
				HASH_FIND_STR(universe->items, pkg_conflict_uniqueid(c), found);
+
				if (found != NULL) {
+
					LL_FOREACH(found, cur) {
+
						if (cur->pkg->type == PKG_INSTALLED) {
+
							/*
+
							 * Move delete requests to be done before installing
+
							 */
+
							if (cur->priority <= it->priority)
+
								pkg_jobs_update_universe_item_priority(j, cur,
+
									it->priority + 1, PKG_PRIORITY_UPDATE_CONFLICT);
+
						}
+
					}
+
				}
+
			}
+
		}
+
	}
+
}
+

+
void
+
pkg_jobs_update_conflict_priority(struct pkg_jobs_universe *universe,
+
	struct pkg_solved *req)
+
{
+
	struct pkg_conflict *c = NULL;
+
	struct pkg *lp = req->items[1]->pkg;
+
	struct pkg_job_universe_item *found, *cur, *rit = NULL;
+

+
	while (pkg_conflicts(lp, &c) == EPKG_OK) {
+
		rit = NULL;
+
		HASH_FIND_STR(universe->items, pkg_conflict_uniqueid(c), found);
+
		assert(found != NULL);
+

+
		LL_FOREACH(found, cur) {
+
			if (cur->pkg->type != PKG_INSTALLED) {
+
				rit = cur;
+
				break;
+
			}
+
		}
+

+
		assert(rit != NULL);
+
		if (rit->priority >= req->items[1]->priority) {
+
			pkg_jobs_update_universe_item_priority(universe, req->items[1],
+
					rit->priority + 1, PKG_PRIORITY_UPDATE_CONFLICT);
+
			/*
+
			 * Update priorities for a remote part as well
+
			 */
+
			pkg_jobs_update_universe_item_priority(universe, req->items[0],
+
					req->items[0]->priority, PKG_PRIORITY_UPDATE_REQUEST);
+
		}
+
	}
+
}
+

+

+
void
+
pkg_jobs_update_universe_priority(struct pkg_jobs_universe *universe,
+
	struct pkg_job_universe_item *it, enum pkg_priority_update_type type)
+
{
+
	pkg_jobs_update_universe_item_priority(universe, it, 0, type);
+
}
modified libpkg/private/pkg_jobs.h
@@ -36,6 +36,9 @@
#include "private/pkg.h"
#include "pkg.h"

+
struct pkg_jobs;
+
struct job_pattern;
+

struct pkg_job_universe_item {
	struct pkg *pkg;
	struct job_pattern *jp;
@@ -77,15 +80,21 @@ struct pkg_job_replace {
	struct pkg_job_replace *next;
};

+

+
struct pkg_jobs_universe {
+
	struct pkg_job_universe_item *items;
+
	struct pkg_job_seen *seen;
+
	struct pkg_job_provide *provides;
+
	struct pkg_job_replace *uid_replaces;
+
	struct pkg_jobs *j;
+
};
+

struct pkg_jobs {
-
	struct pkg_job_universe_item *universe;
+
	struct pkg_jobs_universe *universe;
	struct pkg_job_request	*request_add;
	struct pkg_job_request	*request_delete;
	struct pkg_solved *jobs;
-
	struct pkg_job_seen *seen;
	struct pkgdb	*db;
-
	struct pkg_job_provide *provides;
-
	struct pkg_job_replace *uid_replaces;
	pkg_jobs_t	 type;
	pkg_flags	 flags;
	int		 solved;
@@ -106,5 +115,22 @@ struct job_pattern {
	UT_hash_handle hh;
};

+
enum pkg_priority_update_type {
+
	PKG_PRIORITY_UPDATE_REQUEST = 0,
+
	PKG_PRIORITY_UPDATE_UNIVERSE,
+
	PKG_PRIORITY_UPDATE_CONFLICT,
+
	PKG_PRIORITY_UPDATE_DELETE
+
};
+

+
/*
+
 * Update priorities for all items related with the specified item
+
 */
+
void pkg_jobs_update_universe_priority(struct pkg_jobs_universe *universe,
+
	struct pkg_job_universe_item *it, enum pkg_priority_update_type type);
+
/*
+
 * Update priority as the conflict was found
+
 */
+
void pkg_jobs_update_conflict_priority(struct pkg_jobs_universe *universe,
+
	struct pkg_solved *req);

#endif /* PKG_JOBS_H_ */