From owner-svn-soc-all@FreeBSD.ORG Sun Aug 11 09:01:31 2013 Return-Path: Delivered-To: svn-soc-all@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id D20947FD for ; Sun, 11 Aug 2013 09:01:31 +0000 (UTC) (envelope-from mattbw@FreeBSD.org) Received: from socsvn.freebsd.org (socsvn.freebsd.org [IPv6:2001:1900:2254:206a::50:2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id BD2CA2AAF for ; Sun, 11 Aug 2013 09:01:31 +0000 (UTC) Received: from socsvn.freebsd.org ([127.0.1.124]) by socsvn.freebsd.org (8.14.7/8.14.7) with ESMTP id r7B91V8d046259 for ; Sun, 11 Aug 2013 09:01:31 GMT (envelope-from mattbw@FreeBSD.org) Received: (from www@localhost) by socsvn.freebsd.org (8.14.7/8.14.6/Submit) id r7B91V8X046248 for svn-soc-all@FreeBSD.org; Sun, 11 Aug 2013 09:01:31 GMT (envelope-from mattbw@FreeBSD.org) Date: Sun, 11 Aug 2013 09:01:31 GMT Message-Id: <201308110901.r7B91V8X046248@socsvn.freebsd.org> X-Authentication-Warning: socsvn.freebsd.org: www set sender to mattbw@FreeBSD.org using -f From: mattbw@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r255800 - in soc2013/mattbw/backend: . query MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 11 Aug 2013 09:01:31 -0000 Author: mattbw Date: Sun Aug 11 09:01:31 2013 New Revision: 255800 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=255800 Log: Clean up query code a bit. After a week of mostly shuffling around jobs, query/core.c has now received a bit of love. The initial query routing to local and remote querying has received the most changes, mainly because it was horrifically duplicated code previously. It's becoming obvious that query/core.c might need splitting, as it is now getting unfathomably long. Some space/indent errors elsewhere were fixed, but the code is long overdue an indent(1). Modified: soc2013/mattbw/backend/jobs.c soc2013/mattbw/backend/pkgutils.c soc2013/mattbw/backend/query/core.c soc2013/mattbw/backend/query/do.c Modified: soc2013/mattbw/backend/jobs.c ============================================================================== --- soc2013/mattbw/backend/jobs.c Sun Aug 11 08:38:10 2013 (r255799) +++ soc2013/mattbw/backend/jobs.c Sun Aug 11 09:01:31 2013 (r255800) @@ -131,17 +131,17 @@ jobs_emit_packages(struct pkg_jobs *jobs, PkBackend *backend, pkg_info_ptr info) { - struct pkg *pkg; + struct pkg *pkg; - assert(jobs != NULL); - assert(backend != NULL); - assert(info != NULL); - - pkg = NULL; - while (pkg_jobs(jobs, &pkg) == EPKG_OK) { - assert(pkg != NULL); - pkgutils_emit(pkg, backend, info(pkg)); - } + assert(jobs != NULL); + assert(backend != NULL); + assert(info != NULL); + + pkg = NULL; + while (pkg_jobs(jobs, &pkg) == EPKG_OK) { + assert(pkg != NULL); + pkgutils_emit(pkg, backend, info(pkg)); + } } void @@ -210,5 +210,3 @@ return namevers; } - - Modified: soc2013/mattbw/backend/pkgutils.c ============================================================================== --- soc2013/mattbw/backend/pkgutils.c Sun Aug 11 08:38:10 2013 (r255799) +++ soc2013/mattbw/backend/pkgutils.c Sun Aug 11 09:01:31 2013 (r255800) @@ -27,6 +27,7 @@ #include "pkgutils.h" /* Prototypes */ #include "utils.h" /* INTENTIONALLY_IGNORE */ +static bool pkg_matches_filters(struct pkg *pkg, PkBitfield filters); static const char *repo_of_remote(struct pkg *pkg); /* @@ -36,7 +37,7 @@ pkgutils_pkg_current_state(struct pkg *pkg) { PkInfoEnum info; - + assert(pkg != NULL); /* If the package is local, then it's installed. If it is remote, then @@ -178,7 +179,7 @@ */ gchar * pkgutils_pkg_match_id(struct pkg *pkg, gchar **split_id) -{ +{ bool success; int i; gchar *match_id; @@ -192,37 +193,45 @@ match_id = NULL; pkg_id_bits = calloc(4, sizeof(const char *)); - if (pkg_id_bits == NULL) - goto cleanup; + if (pkg_id_bits != NULL) { + match_id = pkgutils_pkg_to_id_through(pkg, pkg_id_bits); + } - match_id = pkgutils_pkg_to_id_through(pkg, pkg_id_bits); - if (match_id == NULL) - goto cleanup; + if (match_id != NULL) { + bool match_failed; - /* - * Succeed if this package's PackageID fields match the - * original PackageID. Of course, the original ID might have - * missing fields (NULLs), so we treat a comparison involving - * one as a success. This means using our "weak strcmp" - * instead of normal strcmp or even g_strcmp0. - */ - for (success = true, i = PK_PACKAGE_ID_NAME; - success && i <= PK_PACKAGE_ID_DATA; - i++) - success = string_match(split_id[i], pkg_id_bits[i]); - -cleanup: - if (!success) { - if (match_id != NULL) { + assert(pkg_id_bits != NULL); + + /* + * Succeed if this package's PackageID fields match the + * original PackageID. Of course, the original ID might have + * missing fields (NULLs), so we treat a comparison involving + * one as a success. This means using our "weak strcmp" + * instead of normal strcmp or even g_strcmp0. + */ + match_failed = false; + for (i = PK_PACKAGE_ID_NAME; i <= PK_PACKAGE_ID_DATA; i++) { + if (!string_match(split_id[i], pkg_id_bits[i])) { + match_failed = true; + break; + } + } + + if (match_failed) { g_free(match_id); match_id = NULL; + } else { + success = true; } + } + + free(pkg_id_bits); + assert (success || match_id == NULL); assert (!success || match_id != NULL); /* The strings inside this are owned by 'pkg'. Don't free them */ - free(pkg_id_bits); return match_id; } @@ -339,31 +348,45 @@ pkgutils_emit_filtered(struct pkg *pkg, PkBackend *backend, PkBitfield filters, PkInfoEnum info) { - gboolean should_emit; assert(pkg != NULL); assert(backend != NULL); - should_emit = TRUE; + if (pkg_matches_filters(pkg, filters)) { + pkgutils_emit(pkg, backend, info); + } +} + +static bool +pkg_matches_filters(struct pkg *pkg, PkBitfield filters) +{ + bool matches_filters; + PkFilterEnum wrong_filter; + + assert(pkg != NULL); + + matches_filters = true; + + if (pkgutils_pkg_current_state(pkg) == PK_INFO_ENUM_INSTALLED) { + wrong_filter = PK_FILTER_ENUM_NOT_INSTALLED; + } else { + wrong_filter = PK_FILTER_ENUM_INSTALLED; + } - if (pkgutils_pkg_current_state(pkg) == PK_INFO_ENUM_INSTALLED) - should_emit = pk_bitfield_contain(filters, - PK_FILTER_ENUM_NOT_INSTALLED) ? FALSE : should_emit; - else - should_emit = pk_bitfield_contain(filters, - PK_FILTER_ENUM_INSTALLED) ? FALSE : should_emit; - /* TODO: more filters? */ - if (should_emit) - pkgutils_emit(pkg, backend, info); + if (pk_bitfield_contain(filters, wrong_filter) == TRUE) { + matches_filters = false; + } + + return matches_filters; } /* * Gets the PackageKit repository name for the (remote) package. - * + * * Currently this is actually the pkgng repository ident. This might change. - * + * * This does not need to be freed (possibly, TODO: check). */ static const char * Modified: soc2013/mattbw/backend/query/core.c ============================================================================== --- soc2013/mattbw/backend/query/core.c Sun Aug 11 08:38:10 2013 (r255799) +++ soc2013/mattbw/backend/query/core.c Sun Aug 11 09:01:31 2013 (r255800) @@ -50,11 +50,17 @@ struct query_target *t; }; +typedef struct pkgdb_it * (*query_func_ptr) (struct query *q); + static bool can_remote_iterate(struct query *q); static enum repo_type type_of_repo_name(const char *name); static gchar *match_pkg(struct pkg *pkg, struct query *q); static gchar **init_unpack_source(PkBackend *backend, struct query_source *s); +static gchar **make_fake_id_split(const char *name); static struct pkg *match_iterator(struct pkgdb_it *it, struct query *q, gchar **match_id_p); +static struct pkg *query_find_from(query_func_ptr function, struct query *q, gchar **match_id_p); +static struct pkgdb_it *local_query(struct query *q); +static struct pkgdb_it *remote_query(struct query *q); /* * Returns the backend stored inside the given query. @@ -78,24 +84,15 @@ bool success; bool try_local; bool try_remote; - match_t match; PkBitfield filters; - const char *name; - const char *repo; gchar *match_id; struct pkg *pkg; - struct pkgdb *db; - struct pkgdb_it *it; assert(q != NULL); success = false; - match = MATCH_EXACT; match_id = NULL; pkg = NULL; - db = q->db; - name = q->id_strv[PK_PACKAGE_ID_NAME]; - repo = query_repo(q); /* * If we're not given a specific repository in the PackageID, we want @@ -112,35 +109,54 @@ if (pk_bitfield_contain(filters, PK_FILTER_ENUM_NOT_INSTALLED)) try_local = false; - /* Try a local search first, if applicable. */ - it = (try_local ? pkgdb_query(db, name, match) : NULL); - if (it != NULL) - pkg = match_iterator(it, q, &match_id); - pkgdb_it_free(it); - - /* No point trying remote if we got a local match */ - if (pkg != NULL) - try_remote = false; - - /* Next, try a remote search, again only if applicable. */ - it = (try_remote ? pkgdb_rquery(db, name, match, repo) : NULL); - if (it != NULL && can_remote_iterate(q)) - pkg = match_iterator(it, q, &match_id); - pkgdb_it_free(it); + if (try_local) { + pkg = query_find_from(local_query, q, &match_id); + } + if (pkg == NULL && try_remote) { + pkg = query_find_from(remote_query, q, &match_id); + } + if (pkg == NULL) { + assert(match_id == NULL); - if (pkg == NULL) ERR(q->backend, PK_ERROR_ENUM_PACKAGE_NOT_FOUND, "package not found"); - else - success = q->t->f(pkg, match_id, q); + } else { + assert(match_id != NULL); - pkg_free(pkg); - g_free(match_id); + success = q->t->f(pkg, match_id, q); + pkg_free(pkg); + g_free(match_id); + } return success; } +static struct pkg * +query_find_from(query_func_ptr function, struct query *q, gchar **match_id_p) +{ + struct pkg *result; + struct pkgdb_it *iterator; + + assert(function != NULL); + assert(q != NULL); + assert(match_id_p != NULL); + + result = NULL; + + iterator = function(q); + if (iterator != NULL) { + result = match_iterator(iterator, q, match_id_p); + pkgdb_it_free(iterator); + } + + /* Match ID if and only if result. */ + assert(result == NULL || *(match_id_p) != NULL); + assert(result != NULL || *(match_id_p) == NULL); + + return result; +} + /* * Retrieves the repository for the query, or NULL if none is specified (or * the query is using the local database only). @@ -148,13 +164,13 @@ const char * query_repo(struct query *q) { - + assert(q != NULL); return (q->rtype == REPO_REMOTE ? q->id_strv[PK_PACKAGE_ID_DATA] : NULL); } - + /* * Returns the database stored inside the given query. */ @@ -170,7 +186,7 @@ /* * Creates a struct query for the given backend, database, source and target. - * + * * Usually you'll want to use "query_do" instead of calling this directly. */ struct query * @@ -251,11 +267,12 @@ assert(q != NULL); - if (percent == PK_BACKEND_PERCENTAGE_INVALID) + if (percent == PK_BACKEND_PERCENTAGE_INVALID) { scaled_percent = PK_BACKEND_PERCENTAGE_INVALID; - else { - if (percent > 100) + } else { + if (100 < percent) { percent = 100; + } scaled_percent = (((100 * q->s->position) + percent) / (q->s->total)); @@ -324,8 +341,6 @@ assert(pkg != NULL); assert(q != NULL); - - /* No need to do a PackageID match if we're looking for a name. */ if (q->s->type == QUERY_SINGLE_NAME) match_id = pkgutils_pkg_to_id(pkg); @@ -367,38 +382,78 @@ return pkg; } +static struct pkgdb_it * +local_query(struct query *q) +{ + + return pkgdb_query(q->db, q->id_strv[PK_PACKAGE_ID_NAME], MATCH_EXACT); +} + +static struct pkgdb_it * +remote_query(struct query *q) +{ + struct pkgdb_it *iterator; + + iterator = pkgdb_rquery(q->db, q->id_strv[PK_PACKAGE_ID_NAME], + MATCH_EXACT, query_repo(q)); + + /* + * Make sure we can use this iterator. (We only check now so that + * the case of there being no remote matches is properly handled.) + */ + if (iterator != NULL && !can_remote_iterate(q)) { + pkgdb_it_free(iterator); + iterator = NULL; + } + + return iterator; +} + /* Unpacks a query source into name/version/arch/data pointers. */ static gchar ** init_unpack_source(PkBackend *backend, struct query_source *s) { - gchar **id_strv; + gchar **id_strv; assert(backend != NULL); assert(s != NULL); id_strv = NULL; if (s->type == QUERY_SINGLE_NAME) { - /* - * Make a snake-oil ID vector; we won't be doing rigid - * checking against it so it doesn't matter that the version - * might be in the name column etc. - */ - id_strv = g_malloc0_n(5, (gsize) sizeof(gchar *)); - - id_strv[PK_PACKAGE_ID_NAME] = g_strdup(s->single); - id_strv[PK_PACKAGE_ID_VERSION] = g_strdup(""); - id_strv[PK_PACKAGE_ID_ARCH] = g_strdup(""); - id_strv[PK_PACKAGE_ID_DATA] = g_strdup(""); + id_strv = make_fake_id_split(s->single); } else if (s->type == QUERY_SINGLE_ID) { id_strv = pk_package_id_split(s->single); if (id_strv == NULL) ERR(backend, PK_ERROR_ENUM_PACKAGE_ID_INVALID, "invalid package id"); - } else + } else { ERR(backend, PK_ERROR_ENUM_INTERNAL_ERROR, "init_unpack_source given silly source type"); + } + + return id_strv; +} + +static gchar ** +make_fake_id_split(const char *name) +{ + gchar **id_strv; + + assert(name != NULL); + + /* + * Make a snake-oil ID vector; we won't be doing rigid + * checking against it so it doesn't matter that the version + * might be in the name column etc. + */ + id_strv = g_malloc0_n(5, (gsize) sizeof(gchar *)); + + id_strv[PK_PACKAGE_ID_NAME] = g_strdup(name); + id_strv[PK_PACKAGE_ID_VERSION] = g_strdup(""); + id_strv[PK_PACKAGE_ID_ARCH] = g_strdup(""); + id_strv[PK_PACKAGE_ID_DATA] = g_strdup(""); return id_strv; } Modified: soc2013/mattbw/backend/query/do.c ============================================================================== --- soc2013/mattbw/backend/query/do.c Sun Aug 11 08:38:10 2013 (r255799) +++ soc2013/mattbw/backend/query/do.c Sun Aug 11 09:01:31 2013 (r255800) @@ -86,6 +86,10 @@ for (new_s.position = 0; new_s.position < new_s.total && success; (new_s.position)++) { + if (!success) { + break; + } + new_s.single = package_ids[new_s.position]; /* Treat non-PackageIDs as pkgng package names, if allowed */