Date: Tue, 2 Jul 2013 00:30:55 GMT From: mattbw@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r253825 - soc2013/mattbw/backend Message-ID: <201307020030.r620UtP9020334@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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_ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201307020030.r620UtP9020334>
