socsvn commit: r253825 - soc2013/mattbw/backend
mattbw at FreeBSD.org
mattbw at FreeBSD.org
Tue Jul 2 00:30:56 UTC 2013
Author: mattbw
Date: Tue Jul 2 00:30:55 2013
New Revision: 253825
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=253825
Log:
(segfaults) large-scale rehashing of query, currently builds but not working
Modified:
soc2013/mattbw/backend/query.c
soc2013/mattbw/backend/query.h
Modified: soc2013/mattbw/backend/query.c
==============================================================================
--- soc2013/mattbw/backend/query.c Mon Jul 1 23:53:22 2013 (r253824)
+++ soc2013/mattbw/backend/query.c Tue Jul 2 00:30:55 2013 (r253825)
@@ -29,70 +29,46 @@
#include "hash_traverse.h" /* HASH_FOR */
#include "utils.h" /* string_match */
+struct query {
+ int load_flags;
+ const gchar *name;
+ const gchar *version;
+ const gchar *arch;
+ const gchar *data;
+ gchar **strv;
+ PkBackend *backend;
+ struct pkgdb *db;
+
+ gboolean any_repo;
+ gboolean local_repo;
+};
+
+
static const char *get_repo_of(struct pkg *pkg);
static const char *get_repo_of_remote(struct pkg *pkg);
-static gboolean
-try_id_match(struct pkg *pkg, const gchar *name, const gchar *version, const
- gchar *arch, const gchar *data, gchar **match_id);
-static gboolean
-query_split(const gchar *name,
- const gchar *version,
- const gchar *arch,
- const gchar *reponame,
- PkBackend *backend,
- struct pkgdb *db,
- int load_flags,
- gchar **match_id_p,
- struct pkg **match_pkg_p);
-static gboolean
-match(const gchar *id,
- PkBackend *backend,
- struct pkgdb *db,
- int load_flags,
- gchar **match_id_p,
- struct pkg **match_pkg_p);
+static gboolean try_id_match(struct pkg *pkg, struct query *state, gchar **match_id);
+static gboolean match(struct query *state, gchar **match_id_p, struct pkg **match_pkg_p);
gboolean
-match_id_in_it(struct pkgdb_it *iterator,
- PkBackend *backend,
- const char *name,
- const char *version,
- const char *arch,
- const char *data,
- int load_flags,
+match_id_in_it(struct pkgdb_it *it,
+ struct query *state,
gchar **match_id_p,
struct pkg **match_pkg_p)
{
/* TODO: Filters */
gboolean found;
int err;
+ int load_flags;
found = FALSE;
*match_pkg_p = NULL;
*match_id_p = NULL;
+ load_flags = state->load_flags;
- /*
- * Stop pkg from catching fire if we try to load files from
- * non-installed packages.
- */
- if ((load_flags & PKG_LOAD_FILES) && g_strcmp0(data,
- "installed") != 0) {
- pk_backend_error_code(backend,
- PK_ERROR_ENUM_CANNOT_GET_FILELIST,
- "Cannot get files for non-installed package."
- );
- err = EPKG_FATAL;
- } else {
- for (HASH_FOR(err, pkgdb_it_next, iterator, match_pkg_p, load_flags)) {
- if (try_id_match(*match_pkg_p,
- name,
- version,
- arch,
- data,
- match_id_p) == TRUE) {
- found = TRUE;
- break;
- }
+ for (HASH_FOR(err, pkgdb_it_next, it, match_pkg_p, load_flags)) {
+ if (try_id_match(*match_pkg_p, state, match_id_p) == TRUE) {
+ found = TRUE;
+ break;
}
}
@@ -155,8 +131,7 @@
}
static gboolean
-try_id_match(struct pkg *pkg, const char *name, const char *version, const
- char *arch, const char *data, char **match_id)
+try_id_match(struct pkg *pkg, struct query *state, char **match_id)
{
const char *p_arch;
const char *p_data;
@@ -179,10 +154,10 @@
* PackageID. Of course, the original ID might have missing fields
* (NULLs), so we treat a comparison involving one as a success.
*/
- return (string_match(name, p_name) &&
- string_match(version, p_version) &&
- string_match(arch, p_arch) &&
- string_match(data, p_data)) ? TRUE : FALSE;
+ return (string_match(state->name, p_name) &&
+ string_match(state->version, p_version) &&
+ string_match(state->arch, p_arch) &&
+ string_match(state->data, p_data)) ? TRUE : FALSE;
}
/*
@@ -225,19 +200,15 @@
* matching result to an emitter function.
*/
gboolean
-query_emit_match(const gchar *id,
- PkBackend *backend,
- struct pkgdb *db,
- int load_flags,
- emit_ptr emitter)
+query_emit_match(struct query *state, int load_flags, emit_ptr emitter)
{
gboolean success;
gchar *match_id;
struct pkg *match_pkg;
- success = match(id, backend, db, load_flags, &match_id, &match_pkg);
+ success = match(state, &match_id, &match_pkg);
if (success == TRUE && match_id != NULL && match_pkg != NULL)
- emitter(match_pkg, match_id, backend);
+ emitter(match_pkg, match_id, state->backend);
pkg_free(match_pkg);
g_free(match_id);
@@ -256,16 +227,14 @@
* TODO: do something about the redundancy in both this and the emitter variant.
*/
gboolean
-query_job_match(const gchar *id,
- PkBackend *backend,
- struct pkgdb *db,
- struct pkg_jobs *jobs)
+query_job_match(struct query *state, struct pkg_jobs *jobs)
{
gboolean success;
gchar *match_id;
struct pkg *match_pkg;
- success = match(id, backend, db, PKG_LOAD_BASIC, &match_id, &match_pkg);
+ state->load_flags = PKG_LOAD_BASIC;
+ success = match(state, &match_id, &match_pkg);
if (success == TRUE && match_id != NULL && match_pkg != NULL) {
gchar *name[1];
@@ -287,119 +256,130 @@
* The exact type of query depends on the repository given.
*/
static gboolean
-match(const gchar *id,
- PkBackend *backend,
- struct pkgdb *db,
- int load_flags,
- gchar **match_id_p,
- struct pkg **match_pkg_p)
+match(struct query *state, gchar **match_id_p, struct pkg **match_pkg_p)
{
- gboolean query_success;
- gboolean split_success;
- const gchar *arch;
- const gchar *data;
- const gchar *name;
- const gchar *version;
- gchar **strv;
+ gboolean success;
+ gboolean try_local;
+ gboolean try_remote;
+ struct pkgdb *db;
+ struct pkgdb_it *it;
- query_success = FALSE;
- split_success = FALSE;
- strv = NULL;
+ success = FALSE;
+ db = state->db;
- split_success = split_id(id, &strv, &name, &version, &arch, &data);
- if (split_success == FALSE)
- pk_backend_error_code(backend,
- PK_ERROR_ENUM_PACKAGE_ID_INVALID,
- "invalid package id");
+ /*
+ * If we're not given a specific repository in the PackageID, we want
+ * to try searching locally first and then remotely; otherwise which
+ * database we query depends on the repository we have been given.
+ */
+ if (state->any_repo == TRUE)
+ try_local = try_remote = TRUE;
else {
- /*
- * If the PackageID has a repository specified (even if it's
- * "installed" i.e. currently installed package), running
- * "get_details_query" directly should handle remote/local
- * queries properly.
- *
- * If there is no repository specified, however (data is NULL),
- * we may need to check both the local and (all) remote
- * repositories, in that order. (TODO: local packages?)
- */
- if (data == NULL)
- /* Try local database first. */
- query_success = query_split(name,
- version,
- arch,
- "installed",
- backend,
- db,
- load_flags,
- match_id_p,
- match_pkg_p);
- if (query_success == FALSE)
- query_success = query_split(name, version, arch, data,
- backend, db, load_flags, match_id_p,
- match_pkg_p);
- /*
- * Assume any error is due to not finding packages. At time
- * of writing this is true, but may change.
- */
- if (query_success == FALSE)
- pk_backend_error_code(backend,
- PK_ERROR_ENUM_PACKAGE_NOT_FOUND,
- "package not found");
- g_strfreev(strv);
+ try_local = (state->local_repo == TRUE);
+ try_remote = (state->local_repo == FALSE);
}
- return query_success;
+ /* Try a local search first, if applicable. */
+ if (try_local == TRUE)
+ it = pkgdb_query(db, state->name, MATCH_EXACT);
+ else
+ it = NULL;
+ if (it != NULL)
+ success = match_id_in_it(it, state, match_id_p, match_pkg_p);
+
+ /* Next, try a remote search, again only if applicable. */
+ if (success == FALSE && (try_remote == TRUE))
+ it = pkgdb_rquery(db, state->name, MATCH_EXACT, state->data);
+ else
+ it = NULL;
+ if (it != NULL)
+ success = match_id_in_it(it, state, match_id_p, match_pkg_p);
+
+ /*
+ * Assume any error is due to not finding packages. At time of
+ * writing this is true, but may change.
+ */
+ if (success == FALSE)
+ pk_backend_error_code(state->backend,
+ PK_ERROR_ENUM_PACKAGE_NOT_FOUND,
+ "package not found");
+
+ return success;
}
-/*
- * Looks the split PackageID up in the package databases.
- *
- * Usually, a remote query will be done on the repository named by "reponame".
- * If reponame is NULL, a remote check will be done against all repostories.
- * If it is "installed", a local check will be done. (This is in keeping
- * with the special meaning of the "installed" repository in PackageIDs).
- */
-static gboolean
-query_split(const gchar *name,
- const gchar *version,
- const gchar *arch,
- const gchar *reponame,
- PkBackend *backend,
- struct pkgdb *db,
- int load_flags,
- gchar **match_id_p,
- struct pkg **match_pkg_p)
+/* Creates a struct query for the given backend and target ID. */
+gboolean
+query_init(const gchar *id, PkBackend *backend, int load_flags,
+ struct query **state_p)
{
- struct pkgdb_it *it;
gboolean success;
+ gboolean loading_files;
+ struct query *state;
- success = FALSE;
- it = NULL;
-
- /* Are we doing a local query? */
+ state = *state_p;
+ if (state == NULL)
+ state = g_new0(struct query, 1);
+
+ state->backend = backend;
+ state->load_flags = load_flags;
+
+ success = open_remote_db(&(state->db), backend);
+ if (success == TRUE) {
+ success = split_id(id,
+ &(state->strv),
+ &(state->name),
+ &(state->version),
+ &(state->arch),
+ &(state->data));
+ if (success == FALSE)
+ pk_backend_error_code(backend,
+ PK_ERROR_ENUM_PACKAGE_ID_INVALID,
+ "invalid package id");
+ }
/*
- * If we got a repository name, then we want to make sure it
- * corresponds to a real repository.
+ * Check the repository to make sure it's sane, and populate the repo
+ * type flags in the state for later consumption.
*/
- if (g_strcmp0(reponame, "installed") == 0)
- it = pkgdb_query(db, name, MATCH_EXACT);
- else if (pkg_repo_find_ident(reponame) != NULL)
- it = pkgdb_rquery(db, name, MATCH_EXACT, reponame);
- else
+ if (success == TRUE) {
+ if (state->data != NULL)
+ state->any_repo = TRUE;
+ else if (strcmp(state->data, "installed") == 0)
+ state->local_repo = TRUE;
+ else if (pkg_repo_find_ident(state->data) != NULL) {
+ pk_backend_error_code(backend,
+ PK_ERROR_ENUM_PACKAGE_ID_INVALID,
+ "no such repository");
+ success = FALSE;
+ }
+ }
+ /*
+ * Stop pkg from catching fire if we try to load files from
+ * non-installed packages.
+ */
+ loading_files = (load_flags & PKG_LOAD_FILES) ? TRUE : FALSE;
+ if (success == TRUE && state->local_repo == FALSE && loading_files) {
pk_backend_error_code(backend,
- PK_ERROR_ENUM_PACKAGE_NOT_FOUND,
- "no such repository");
-
-
- if (it != NULL)
- success = match_id_in_it(it,
- backend,
- name,
- version,
- arch,
- reponame,
- load_flags,
- match_id_p,
- match_pkg_p);
+ PK_ERROR_ENUM_CANNOT_GET_FILELIST,
+ "cannot get files for remote package");
+ success = FALSE;
+ }
+ if (success == FALSE) {
+ query_free(state);
+ state = NULL;
+ }
+ *state_p = state;
return success;
}
+
+void
+query_free(struct query *state)
+{
+ if (state != NULL) {
+ if (state->db != NULL)
+ pkgdb_close(state->db);
+ if (state->strv != NULL)
+ g_strfreev(state->strv);
+ /* This should free the other split ID pointer targets. */
+ g_free(state);
+ }
+}
Modified: soc2013/mattbw/backend/query.h
==============================================================================
--- soc2013/mattbw/backend/query.h Mon Jul 1 23:53:22 2013 (r253824)
+++ soc2013/mattbw/backend/query.h Tue Jul 2 00:30:55 2013 (r253825)
@@ -30,17 +30,14 @@
PkBackend *backend);
typedef gboolean (*ids_func_ptr) (const gchar *id, PkBackend *backend, struct pkgdb *db);
-gboolean
-query_emit_match(const gchar *id,
- PkBackend *backend,
- struct pkgdb *db,
- int load_flags,
- emit_ptr emitter);
-gboolean
-query_job_match(const gchar *id,
- PkBackend *backend,
- struct pkgdb *db,
- struct pkg_jobs *jobs);
+struct query;
+
+gboolean query_emit_match(struct query *state, int load_flags, emit_ptr emitter);
+gboolean query_job_match(struct query *state, struct pkg_jobs *jobs);
gboolean iterate_ids(PkBackend *backend, ids_func_ptr iterate_f);
+/* Creates a struct query for the given backend and target ID. */
+gboolean query_init(const gchar *id, PkBackend *backend, int load_flags, struct query **state_p);
+void query_free(struct query *state);
+
#endif /* !_PKGNG_BACKEND_QUERY_H_ */
More information about the svn-soc-all
mailing list