[ostree] pull: Stage metadata objects asynchronously



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]