[ostree/wip/metalinks: 2/2] More metalink work, plus a test case
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ostree/wip/metalinks: 2/2] More metalink work, plus a test case
- Date: Tue, 19 Aug 2014 18:57:12 +0000 (UTC)
commit b8ba2402a16ca39243f343a79f2da2aab716cc80
Author: Colin Walters <walters verbum org>
Date: Tue Aug 19 14:56:38 2014 -0400
More metalink work, plus a test case
src/libostree/ostree-core.h | 6 +-
src/libostree/ostree-metalink.c | 13 +++-
src/libostree/ostree-repo-pull.c | 143 ++++++++++++++++++++++++++-----------
src/libostree/ostree-repo.c | 15 +++-
src/libotutil/ot-variant-utils.c | 121 ++++++++++++++++++++++++++++++++
src/libotutil/ot-variant-utils.h | 10 +++
src/ostree/ot-builtin-summary.c | 1 -
tests/test-pull-metalink.sh | 1 +
8 files changed, 257 insertions(+), 53 deletions(-)
---
diff --git a/src/libostree/ostree-core.h b/src/libostree/ostree-core.h
index 8ed8d2d..c1b81d7 100644
--- a/src/libostree/ostree-core.h
+++ b/src/libostree/ostree-core.h
@@ -120,10 +120,10 @@ typedef enum {
/**
* OSTREE_SUMMARY_GVARIANT_FORMAT:
*
- * a(ayay) - Array of (checksum, commit data)
- * refs: a{s(aya{sv})} - Map of ref name -> (latest commit, additional metadata)
+ * a(ayay) - Array of (checksum, commit data), sorted by checksum
+ * refs: a(s(aya{sv})) - Map of ref name -> (latest commit, additional metadata), sorted by ref name
*/
-#define OSTREE_SUMMARY_GVARIANT_STRING "(a(ayay)a{s(aya{sv})})"
+#define OSTREE_SUMMARY_GVARIANT_STRING "(a(ayay)a(s(aya{sv})))"
#define OSTREE_SUMMARY_GVARIANT_FORMAT G_VARIANT_TYPE (OSTREE_SUMMARY_GVARIANT_STRING)
/**
diff --git a/src/libostree/ostree-metalink.c b/src/libostree/ostree-metalink.c
index 2c0541e..94057d7 100644
--- a/src/libostree/ostree-metalink.c
+++ b/src/libostree/ostree-metalink.c
@@ -327,8 +327,9 @@ _ostree_metalink_finalize (GObject *object)
self = OSTREE_METALINK (object);
+ g_object_unref (self->fetcher);
g_free (self->requested_file);
- g_clear_object (&self->uri);
+ soup_uri_free (self->uri);
G_OBJECT_CLASS (_ostree_metalink_parent_class)->finalize (object);
}
@@ -354,9 +355,10 @@ _ostree_metalink_new (OstreeFetcher *fetcher,
{
OstreeMetalink *self = (OstreeMetalink*)g_object_new (OSTREE_TYPE_METALINK, NULL);
+ self->fetcher = g_object_ref (fetcher);
self->requested_file = g_strdup (requested_file);
self->max_size = max_size;
- self->uri = g_object_ref (uri);
+ self->uri = soup_uri_copy (uri);
return self;
}
@@ -685,12 +687,19 @@ _ostree_metalink_request_sync (OstreeMetalink *self,
gboolean ret = FALSE;
GMainContext *sync_context = g_main_context_new ();
MetalinkSyncCallState state = { 0, };
+
+ state.error = error;
+ state.running = TRUE;
+
+ g_main_context_push_thread_default (sync_context);
_ostree_metalink_request_async (self, cancellable, on_async_result, &state);
while (state.running)
g_main_context_iteration (sync_context, TRUE);
+ g_main_context_pop_thread_default (sync_context);
+
ret = state.success;
if (sync_context)
g_main_context_unref (sync_context);
diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c
index 6df3688..ba906cb 100644
--- a/src/libostree/ostree-repo-pull.c
+++ b/src/libostree/ostree-repo-pull.c
@@ -52,6 +52,7 @@ typedef struct {
gboolean gpg_verify;
+ GVariant *summary;
GPtrArray *static_delta_metas;
GHashTable *scanned_metadata; /* Maps object name to itself */
GHashTable *requested_metadata; /* Maps object name to itself */
@@ -480,6 +481,41 @@ fetch_ref_contents (OtPullData *pull_data,
return ret;
}
+static gboolean
+lookup_commit_checksum_from_summary (OtPullData *pull_data,
+ const char *ref,
+ char **out_checksum,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ gs_unref_variant GVariant *commits = g_variant_get_child_value (pull_data->summary, 0);
+ gs_unref_variant GVariant *refs = g_variant_get_child_value (pull_data->summary, 1);
+ gs_unref_variant GVariant *refdata = NULL;
+ gs_unref_variant GVariant *commit_data = NULL;
+ gs_unref_variant GVariant *commit_csum_v = NULL;
+ gs_unref_bytes GBytes *commit_bytes = NULL;
+ int i;
+
+ if (!ot_variant_bsearch_str (refs, ref, &i))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "No such branch '%s' in repository summary",
+ ref);
+ goto out;
+ }
+
+ refdata = g_variant_get_child_value (refs, i);
+ commit_csum_v = g_variant_get_child_value (refdata, 0);
+
+ if (!ostree_validate_structureof_csum_v (commit_csum_v, error))
+ goto out;
+
+ ret = TRUE;
+ *out_checksum = ostree_checksum_from_bytes_v (commit_csum_v);
+ out:
+ return ret;
+}
+
static void
content_fetch_on_write_complete (GObject *object,
GAsyncResult *result,
@@ -1030,7 +1066,7 @@ ostree_repo_pull (OstreeRepo *self,
gs_free char *remote_key = NULL;
gs_free char *path = NULL;
gs_free char *baseurl = NULL;
- gs_free char *metalink_url = NULL;
+ gs_free char *metalink_url_str = NULL;
gs_unref_hashtable GHashTable *requested_refs_to_fetch = NULL;
gs_unref_hashtable GHashTable *commits_to_fetch = NULL;
gs_free char *remote_mode_str = NULL;
@@ -1073,38 +1109,6 @@ ostree_repo_pull (OstreeRepo *self,
goto out;
}
- if (!repo_get_string_key_inherit (self, remote_key, "metalink", &metalink_url, error))
- goto out;
-
- if (!metalink_url)
- {
- if (!repo_get_string_key_inherit (self, remote_key, "url", &baseurl, error))
- goto out;
-
- pull_data->base_uri = soup_uri_new (baseurl);
-
- if (!pull_data->base_uri)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Failed to parse url '%s'", baseurl);
- goto out;
- }
- }
- else
- {
- gs_unref_object GFile *metalink_data = NULL;
- SoupURI *metalink_uri = soup_uri_new (metalink_url);
- metalink = _ostree_metalink_new (pull_data->fetcher, metalink_url, OSTREE_MAX_METADATA_SIZE,
metalink_uri);
- g_object_unref (metalink_uri);
-
- if (!_ostree_metalink_request_sync (metalink, &pull_data->base_uri,
- &metalink_data,
- cancellable, error))
- goto out;
-
-
- }
-
#ifdef HAVE_GPGME
if (!ot_keyfile_get_boolean_with_default (config, remote_key, "gpg-verify",
TRUE, &pull_data->gpg_verify, error))
@@ -1178,6 +1182,48 @@ ostree_repo_pull (OstreeRepo *self,
}
}
+ if (!repo_get_string_key_inherit (self, remote_key, "metalink", &metalink_url_str, error))
+ goto out;
+
+ if (!metalink_url_str)
+ {
+ if (!repo_get_string_key_inherit (self, remote_key, "url", &baseurl, error))
+ goto out;
+
+ pull_data->base_uri = soup_uri_new (baseurl);
+
+ if (!pull_data->base_uri)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Failed to parse url '%s'", baseurl);
+ goto out;
+ }
+ }
+ else
+ {
+ gs_unref_object GFile *metalink_data = NULL;
+ SoupURI *metalink_uri = soup_uri_new (metalink_url_str);
+
+ if (!metalink_uri)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Invalid metalink URL: %s", metalink_url_str);
+ goto out;
+ }
+
+ metalink = _ostree_metalink_new (pull_data->fetcher, "summary", OSTREE_MAX_METADATA_SIZE,
metalink_uri);
+ soup_uri_free (metalink_uri);
+
+ if (!_ostree_metalink_request_sync (metalink, &pull_data->base_uri,
+ &metalink_data,
+ cancellable, error))
+ goto out;
+
+ if (!ot_util_variant_map (metalink_data, OSTREE_SUMMARY_GVARIANT_FORMAT, FALSE,
+ &pull_data->summary, error))
+ goto out;
+ }
+
if (!load_remote_repo_config (pull_data, &remote_config, cancellable, error))
goto out;
@@ -1207,7 +1253,6 @@ ostree_repo_pull (OstreeRepo *self,
for (strviter = refs_to_fetch; *strviter; strviter++)
{
const char *branch = *strviter;
- char *contents;
if (ostree_validate_checksum_string (branch, NULL))
{
@@ -1216,11 +1261,7 @@ ostree_repo_pull (OstreeRepo *self,
}
else
{
- if (!fetch_ref_contents (pull_data, branch, &contents, cancellable, error))
- goto out;
-
- /* Transfer ownership of contents */
- g_hash_table_insert (requested_refs_to_fetch, g_strdup (branch), contents);
+ g_hash_table_insert (requested_refs_to_fetch, g_strdup (branch), NULL);
}
}
}
@@ -1240,14 +1281,29 @@ ostree_repo_pull (OstreeRepo *self,
for (;branches_iter && *branches_iter; branches_iter++)
{
const char *branch = *branches_iter;
- char *contents;
+ g_hash_table_insert (requested_refs_to_fetch, g_strdup (branch), NULL);
+ }
+ }
+
+ while (g_hash_table_iter_next (&hash_iter, &key, &value))
+ {
+ const char *branch = key;
+ char *contents;
+
+ if (pull_data->summary)
+ {
+ if (!lookup_commit_checksum_from_summary (pull_data, branch, &contents, error))
+ goto out;
+ }
+ else
+ {
if (!fetch_ref_contents (pull_data, branch, &contents, cancellable, error))
goto out;
-
- /* Transfer ownership of contents */
- g_hash_table_insert (requested_refs_to_fetch, g_strdup (branch), contents);
}
+
+ /* Transfer ownership of contents */
+ g_hash_table_replace (requested_refs_to_fetch, g_strdup (branch), contents);
}
pull_data->phase = OSTREE_PULL_PHASE_FETCHING_OBJECTS;
@@ -1348,6 +1404,7 @@ ostree_repo_pull (OstreeRepo *self,
g_free (pull_data->remote_name);
if (pull_data->base_uri)
soup_uri_free (pull_data->base_uri);
+ g_clear_pointer (&pull_data->summary, (GDestroyNotify) g_variant_unref);
g_clear_pointer (&pull_data->static_delta_metas, (GDestroyNotify) g_ptr_array_unref);
g_clear_pointer (&pull_data->scanned_metadata, (GDestroyNotify) g_hash_table_unref);
g_clear_pointer (&pull_data->requested_content, (GDestroyNotify) g_hash_table_unref);
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index 6ef5397..f642bd5 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -2282,6 +2282,7 @@ ostree_repo_regenerate_summary (OstreeRepo *self,
GError **error)
{
gboolean ret = FALSE;
+ gs_unref_object GFile *summary_path = NULL;
gs_unref_hashtable GHashTable *refs = NULL;
gs_unref_hashtable GHashTable *commits = NULL;
gs_unref_variant_builder GVariantBuilder *refs_builder = NULL;
@@ -2289,7 +2290,6 @@ ostree_repo_regenerate_summary (OstreeRepo *self,
gs_unref_variant GVariant *summary = NULL;
GList *ordered_keys = NULL;
GList *iter = NULL;
- GHashTableIter hashiter;
if (!ostree_repo_list_refs (self, NULL, &refs, cancellable, error))
goto out;
@@ -2320,7 +2320,7 @@ ostree_repo_regenerate_summary (OstreeRepo *self,
g_hash_table_insert (commits, g_strdup (commit), g_variant_ref (commit_content));
}
- csum_v = ostree_checksum_to_bytes_v (commit);
+ csum_v = g_variant_ref_sink (ostree_checksum_to_bytes_v (commit));
g_variant_builder_add_value (refs_builder,
g_variant_new ("(s(@ay a{sv}))", ref, csum_v,
@@ -2343,9 +2343,9 @@ ostree_repo_regenerate_summary (OstreeRepo *self,
g_assert (commit_content);
- csum_v = ostree_checksum_to_bytes_v (commit);
+ csum_v = g_variant_ref_sink (ostree_checksum_to_bytes_v (commit));
commit_data = g_variant_get_data_as_bytes (commit_content);
- commit_data_v = g_variant_new_from_bytes (G_VARIANT_TYPE ("ay"), commit_data, TRUE);
+ commit_data_v = g_variant_ref_sink (g_variant_new_from_bytes (G_VARIANT_TYPE ("ay"), commit_data,
TRUE));
g_variant_builder_add_value (commits_builder,
g_variant_new ("(@ay ay)", csum_v, commit_data_v));
@@ -2354,11 +2354,18 @@ ostree_repo_regenerate_summary (OstreeRepo *self,
{
gs_unref_variant_builder GVariantBuilder *summary_builder =
g_variant_builder_new (OSTREE_SUMMARY_GVARIANT_FORMAT);
+
g_variant_builder_add_value (summary_builder, g_variant_builder_end (commits_builder));
g_variant_builder_add_value (summary_builder, g_variant_builder_end (refs_builder));
summary = g_variant_builder_end (summary_builder);
+ g_variant_ref_sink (summary);
}
+ summary_path = g_file_get_child (self->repodir, "summary");
+
+ if (!ot_util_variant_save (summary_path, summary, cancellable, error))
+ goto out;
+
ret = TRUE;
out:
if (ordered_keys)
diff --git a/src/libotutil/ot-variant-utils.c b/src/libotutil/ot-variant-utils.c
index db79616..031be2a 100644
--- a/src/libotutil/ot-variant-utils.c
+++ b/src/libotutil/ot-variant-utils.c
@@ -288,3 +288,124 @@ ot_variant_new_from_bytes (const GVariantType *type,
(GDestroyNotify)g_bytes_unref, bytes);
#endif
}
+
+/**
+ * ot_variant_bsearch_str:
+ * @array: A GVariant array whose first element must be a string
+ * @str: Search for this string
+ * @out_pos: Output position
+ *
+ *
+ * Binary search in a GVariant array, which must be of the form 'a(s...)',
+ * where '...' may be anything. The array elements must be sorted.
+ *
+ * Returns: %TRUE if found, %FALSE otherwise
+ */
+gboolean
+ot_variant_bsearch_str (GVariant *array,
+ const char *str,
+ int *out_pos)
+{
+ gsize imax, imin;
+ gsize imid;
+ gsize n;
+
+ n = g_variant_n_children (array);
+ if (n == 0)
+ return FALSE;
+
+ imax = n - 1;
+ imin = 0;
+ while (imax >= imin)
+ {
+ gs_unref_variant GVariant *child = NULL;
+ const char *cur;
+ int cmp;
+
+ imid = (imin + imax) / 2;
+
+ child = g_variant_get_child_value (array, imid);
+ g_variant_get_child (child, 0, "&s", &cur, NULL);
+
+ cmp = strcmp (cur, str);
+ if (cmp < 0)
+ imin = imid + 1;
+ else if (cmp > 0)
+ {
+ if (imid == 0)
+ break;
+ imax = imid - 1;
+ }
+ else
+ {
+ *out_pos = imid;
+ return TRUE;
+ }
+ }
+
+ *out_pos = imid;
+ return FALSE;
+}
+
+/**
+ * ot_variant_bsearch_bytes:
+ *
+ * Like ot_variant_bsearch, but with binary data like checksums.
+ */
+gboolean
+ot_variant_bsearch_bytes (GVariant *array,
+ GBytes *bytes,
+ int *out_pos)
+{
+ gsize imax, imin;
+ gsize imid;
+ gsize n;
+ const guint8 *bytes_data;
+ gsize bytes_len;
+
+ bytes_data = g_bytes_get_data (bytes, &bytes_len);
+
+ n = g_variant_n_children (array);
+ if (n == 0)
+ return FALSE;
+
+ imax = n - 1;
+ imin = 0;
+ while (imax >= imin)
+ {
+ gs_unref_variant GVariant *child = NULL;
+ gs_unref_variant GVariant *child_first = NULL;
+ const guint8 *variant_data;
+ gsize variant_size;
+ int cmp;
+
+ imid = (imin + imax) / 2;
+
+ child = g_variant_get_child_value (array, imid);
+ child_first = g_variant_get_child_value (child, 0);
+
+ variant_data = g_variant_get_data (child_first);
+ variant_size = g_variant_get_size (child_first);
+
+ if (variant_size != bytes_len)
+ cmp = 1;
+ else
+ cmp = memcmp (variant_data, bytes_data, bytes_len);
+ if (cmp < 0)
+ imin = imid + 1;
+ else if (cmp > 0)
+ {
+ if (imid == 0)
+ break;
+ imax = imid - 1;
+ }
+ else
+ {
+ *out_pos = imid;
+ return TRUE;
+ }
+ }
+
+ *out_pos = imid;
+ return FALSE;
+}
diff --git a/src/libotutil/ot-variant-utils.h b/src/libotutil/ot-variant-utils.h
index 429bceb..28f4096 100644
--- a/src/libotutil/ot-variant-utils.h
+++ b/src/libotutil/ot-variant-utils.h
@@ -72,5 +72,15 @@ ot_variant_new_from_bytes (const GVariantType *type,
GBytes *bytes,
gboolean trusted);
+gboolean
+ot_variant_bsearch_str (GVariant *array,
+ const char *str,
+ int *out_pos);
+
+gboolean
+ot_variant_bsearch_bytes (GVariant *array,
+ GBytes *bytes,
+ int *out_pos);
+
G_END_DECLS
diff --git a/src/ostree/ot-builtin-summary.c b/src/ostree/ot-builtin-summary.c
index 17feb34..667d6fe 100644
--- a/src/ostree/ot-builtin-summary.c
+++ b/src/ostree/ot-builtin-summary.c
@@ -36,7 +36,6 @@ ostree_builtin_summary (int argc, char **argv, OstreeRepo *repo, GCancellable *c
{
gboolean ret = FALSE;
GOptionContext *context;
- gs_unref_ptrarray GPtrArray *delta_names = NULL;
context = g_option_context_new ("Manage summary metadata");
g_option_context_add_main_entries (context, options, NULL);
diff --git a/tests/test-pull-metalink.sh b/tests/test-pull-metalink.sh
index 56769b5..ccd17b7 100755
--- a/tests/test-pull-metalink.sh
+++ b/tests/test-pull-metalink.sh
@@ -62,5 +62,6 @@ mkdir repo
${CMD_PREFIX} ostree --repo=repo init
${CMD_PREFIX} ostree --repo=repo remote add --set=gpg-verify=false origin metalink=$(cat
metalink-httpd-address)/metalink.xml
${CMD_PREFIX} ostree --repo=repo pull origin:main
+${CMD_PREFIX} ostree --repo=repo rev-parse origin:main
${CMD_PREFIX} ostree --repo=repo fsck
echo "ok pull via metalink"
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]