[ostree] pull: Stage metadata objects asynchronously
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ostree] pull: Stage metadata objects asynchronously
- Date: Fri, 5 Oct 2012 00:03:03 +0000 (UTC)
commit 5b8e8333517743ad35d514f58d3adfd950dd6d45
Author: Colin Walters <walters verbum org>
Date: Thu Oct 4 18:24:37 2012 -0400
pull: Stage metadata objects asynchronously
This avoids the main thread being blocked on fdatasync(); also as a
bonus we checksum metadata in a separate thread too.
src/libostree/ostree-repo.c | 95 +++++++++++++++++++++++++++++++++++++++++++
src/libostree/ostree-repo.h | 13 ++++++
src/ostree/ostree-pull.c | 48 ++++++++++++++-------
3 files changed, 140 insertions(+), 16 deletions(-)
---
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index 44f0905..8840887 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -1383,6 +1383,101 @@ ostree_repo_stage_metadata_trusted (OstreeRepo *self,
cancellable, error);
}
+typedef struct {
+ OstreeRepo *repo;
+ OstreeObjectType objtype;
+ char *expected_checksum;
+ GVariant *object;
+ GCancellable *cancellable;
+ GSimpleAsyncResult *result;
+
+ guchar *result_csum;
+} StageMetadataAsyncData;
+
+static void
+stage_metadata_async_data_free (gpointer user_data)
+{
+ StageMetadataAsyncData *data = user_data;
+
+ g_clear_object (&data->repo);
+ g_clear_object (&data->cancellable);
+ g_variant_unref (data->object);
+ g_free (data->result_csum);
+ g_free (data->expected_checksum);
+ g_free (data);
+}
+
+static void
+stage_metadata_thread (GSimpleAsyncResult *res,
+ GObject *object,
+ GCancellable *cancellable)
+{
+ GError *error = NULL;
+ StageMetadataAsyncData *data;
+
+ data = g_simple_async_result_get_op_res_gpointer (res);
+ if (!ostree_repo_stage_metadata (data->repo, data->objtype, data->expected_checksum,
+ data->object,
+ &data->result_csum,
+ cancellable, &error))
+ g_simple_async_result_take_error (res, error);
+}
+
+/**
+ * ostree_repo_stage_metadata_async:
+ *
+ * Asynchronously store the metadata object @variant. If provided,
+ * the checksum @expected_checksum will be verified.
+ */
+void
+ostree_repo_stage_metadata_async (OstreeRepo *self,
+ OstreeObjectType objtype,
+ const char *expected_checksum,
+ GVariant *object,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ StageMetadataAsyncData *asyncdata;
+
+ asyncdata = g_new0 (StageMetadataAsyncData, 1);
+ asyncdata->repo = g_object_ref (self);
+ asyncdata->objtype = objtype;
+ asyncdata->expected_checksum = g_strdup (expected_checksum);
+ asyncdata->object = g_variant_ref (object);
+ asyncdata->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+
+ asyncdata->result = g_simple_async_result_new ((GObject*) self,
+ callback, user_data,
+ ostree_repo_stage_metadata_async);
+
+ g_simple_async_result_set_op_res_gpointer (asyncdata->result, asyncdata,
+ stage_metadata_async_data_free);
+ g_simple_async_result_run_in_thread (asyncdata->result, stage_metadata_thread, G_PRIORITY_DEFAULT, cancellable);
+ g_object_unref (asyncdata->result);
+}
+
+gboolean
+ostree_repo_stage_metadata_finish (OstreeRepo *self,
+ GAsyncResult *result,
+ guchar **out_csum,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+ StageMetadataAsyncData *data;
+
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == ostree_repo_stage_metadata_async);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ data = g_simple_async_result_get_op_res_gpointer (simple);
+ /* Transfer ownership */
+ *out_csum = data->result_csum;
+ data->result_csum = NULL;
+ return TRUE;
+}
+
static gboolean
stage_directory_meta (OstreeRepo *self,
GFileInfo *file_info,
diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h
index 3e57d24..62f51d3 100644
--- a/src/libostree/ostree-repo.h
+++ b/src/libostree/ostree-repo.h
@@ -103,6 +103,19 @@ gboolean ostree_repo_stage_metadata (OstreeRepo *self,
GCancellable *cancellable,
GError **error);
+void ostree_repo_stage_metadata_async (OstreeRepo *self,
+ OstreeObjectType objtype,
+ const char *expected_checksum,
+ GVariant *object,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean ostree_repo_stage_metadata_finish (OstreeRepo *self,
+ GAsyncResult *result,
+ guchar **out_checksum,
+ GError **error);
+
gboolean ostree_repo_stage_content (OstreeRepo *self,
const char *expected_checksum,
GInputStream *content,
diff --git a/src/ostree/ostree-pull.c b/src/ostree/ostree-pull.c
index 78b540c..b189c0b 100644
--- a/src/ostree/ostree-pull.c
+++ b/src/ostree/ostree-pull.c
@@ -760,47 +760,63 @@ idle_queue_content_request (gpointer user_data)
typedef struct {
OtPullData *pull_data;
GVariant *object;
+ GFile *temp_path;
} IdleFetchMetadataObjectData;
static void
+on_metadata_staged (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ IdleFetchMetadataObjectData *fetch_data = user_data;
+ OtPullData *pull_data = fetch_data->pull_data;
+
+ pull_data->n_fetched_metadata++;
+
+ ot_worker_queue_push (pull_data->metadata_objects_to_scan,
+ g_variant_ref (fetch_data->object));
+ ot_worker_queue_release (pull_data->metadata_objects_to_scan);
+
+ (void) ot_gfile_unlink (fetch_data->temp_path, NULL, NULL);
+ g_object_unref (fetch_data->temp_path);
+ g_variant_unref (fetch_data->object);
+ g_free (fetch_data);
+}
+
+static void
meta_fetch_on_complete (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
IdleFetchMetadataObjectData *fetch_data = user_data;
OtPullData *pull_data = fetch_data->pull_data;
- ot_lobj GFile *temp_path = NULL;
ot_lvariant GVariant *metadata = NULL;
const char *checksum;
OstreeObjectType objtype;
GError *local_error = NULL;
GError **error = &local_error;
- temp_path = ostree_fetcher_request_uri_finish ((OstreeFetcher*)object, result, error);
- if (!temp_path)
+ fetch_data->temp_path = ostree_fetcher_request_uri_finish ((OstreeFetcher*)object, result, error);
+ if (!fetch_data->temp_path)
goto out;
ostree_object_name_deserialize (fetch_data->object, &checksum, &objtype);
- if (!ot_util_variant_map (temp_path, ostree_metadata_variant_type (objtype),
+ if (!ot_util_variant_map (fetch_data->temp_path, ostree_metadata_variant_type (objtype),
FALSE, &metadata, error))
goto out;
- if (!ostree_repo_stage_metadata (pull_data->repo, objtype, checksum, metadata, (guchar**)NULL,
- pull_data->cancellable, error))
- goto out;
-
- pull_data->n_fetched_metadata++;
-
- ot_worker_queue_push (pull_data->metadata_objects_to_scan,
- g_variant_ref (fetch_data->object));
- ot_worker_queue_release (pull_data->metadata_objects_to_scan);
+ ostree_repo_stage_metadata_async (pull_data->repo, objtype, checksum, metadata,
+ pull_data->cancellable,
+ on_metadata_staged, fetch_data);
out:
- (void) ot_gfile_unlink (temp_path, NULL, NULL);
throw_async_error (pull_data, local_error);
- g_variant_unref (fetch_data->object);
- g_free (fetch_data);
+ if (local_error)
+ {
+ g_variant_unref (fetch_data->object);
+ g_free (fetch_data);
+ }
}
static gboolean
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]