[ostree] deltas: Flesh out the open/write/close opcodes



commit 7900c82a36b74760357817ca9f33607be471d520
Author: Colin Walters <walters verbum org>
Date:   Thu Jan 29 22:32:44 2015 -0500

    deltas: Flesh out the open/write/close opcodes
    
    Refactor open-splice-and-close to call open/close.  We can't just call
    write as that would require duplicating the object size parameter.

 .../ostree-repo-static-delta-processing.c          |  183 +++++++++++++-------
 1 files changed, 122 insertions(+), 61 deletions(-)
---
diff --git a/src/libostree/ostree-repo-static-delta-processing.c 
b/src/libostree/ostree-repo-static-delta-processing.c
index cd77adb..10372a0 100644
--- a/src/libostree/ostree-repo-static-delta-processing.c
+++ b/src/libostree/ostree-repo-static-delta-processing.c
@@ -54,6 +54,16 @@ typedef struct {
   GError        **async_error;
 
   OstreeObjectType output_objtype;
+  OstreeRepoTrustedContentBareCommit barecommitstate;
+  guint64          content_size;
+  GOutputStream   *content_out;
+  char             checksum[65];
+  gboolean        have_obj;
+  guint32         uid;
+  guint32         gid;
+  guint32         mode;
+  GVariant       *xattrs;
+  
   const guint8   *output_target;
   const guint8   *input_target_csum;
 
@@ -113,7 +123,6 @@ open_output_target (StaticDeltaExecutionState   *state,
 {
   gboolean ret = FALSE;
   guint8 *objcsum;
-  char checksum[65];
 
   g_assert (state->checksums != NULL);
   g_assert (state->output_target == NULL);
@@ -127,7 +136,7 @@ open_output_target (StaticDeltaExecutionState   *state,
   state->output_objtype = (OstreeObjectType) *objcsum;
   state->output_target = objcsum + 1;
 
-  ostree_checksum_inplace_from_bytes (state->output_target, checksum);
+  ostree_checksum_inplace_from_bytes (state->output_target, state->checksum);
 
   ret = TRUE;
  out:
@@ -439,19 +448,48 @@ validate_ofs (StaticDeltaExecutionState  *state,
 }
 
 static gboolean
+do_content_open_generic (OstreeRepo                 *repo,
+                         StaticDeltaExecutionState  *state,
+                         GCancellable               *cancellable,  
+                         GError                    **error)
+{
+  gboolean ret = FALSE;
+  gs_unref_variant GVariant *modev;
+  guint64 mode_offset;
+  guint64 xattr_offset;
+  guint32 uid, gid, mode;
+
+  if (!read_varuint64 (state, &mode_offset, error))
+    goto out;
+  if (!read_varuint64 (state, &xattr_offset, error))
+    goto out;
+
+  state->barecommitstate.fd = -1;
+
+  modev = g_variant_get_child_value (state->mode_dict, mode_offset);
+  g_variant_get (modev, "(uuu)", &uid, &gid, &mode);
+  state->uid = GUINT32_FROM_BE (uid);
+  state->gid = GUINT32_FROM_BE (gid);
+  state->mode = GUINT32_FROM_BE (mode);
+
+  state->xattrs = g_variant_get_child_value (state->xattr_dict, xattr_offset);
+
+  ret = TRUE;
+ out:
+  return ret;
+}
+
+static gboolean
 dispatch_open_splice_and_close (OstreeRepo                 *repo,
                                 StaticDeltaExecutionState  *state,
                                 GCancellable               *cancellable,  
                                 GError                    **error)
 {
   gboolean ret = FALSE;
-  char checksum[65];
 
   if (!open_output_target (state, cancellable, error))
     goto out;
-
-  ostree_checksum_inplace_from_bytes (state->output_target, checksum);
-
+  
   if (OSTREE_OBJECT_TYPE_IS_META (state->output_objtype))
     {
       gs_unref_variant GVariant *metadata = NULL;
@@ -469,7 +507,7 @@ dispatch_open_splice_and_close (OstreeRepo                 *repo,
                                           state->payload_data + offset, length, TRUE, NULL, NULL);
       
       if (!ostree_repo_write_metadata_trusted (state->repo, state->output_objtype,
-                                               checksum,
+                                               state->checksum,
                                                metadata,
                                                cancellable,
                                                error))
@@ -477,81 +515,54 @@ dispatch_open_splice_and_close (OstreeRepo                 *repo,
     }
   else
     {
-      guint64 mode_offset;
-      guint64 xattr_offset;
-      guint64 content_size;
       guint64 content_offset;
       guint64 objlen;
+      guint64 content_size;
+      gsize bytes_written;
       gs_unref_object GInputStream *object_input = NULL;
       gs_unref_object GInputStream *memin = NULL;
-      gs_unref_variant GVariant *xattrs_buf = NULL;
-      GVariant *modev;
-      GVariant *xattrs;
-      guint32 uid, gid, mode;
-
-      if (!read_varuint64 (state, &mode_offset, error))
-        goto out;
-      if (!read_varuint64 (state, &xattr_offset, error))
+      
+      if (!do_content_open_generic (repo, state, cancellable, error))
         goto out;
+
       if (!read_varuint64 (state, &content_size, error))
         goto out;
       if (!read_varuint64 (state, &content_offset, error))
         goto out;
-
       if (!validate_ofs (state, content_offset, content_size, error))
         goto out;
-
-      modev = g_variant_get_child_value (state->mode_dict, mode_offset);
-      g_variant_get (modev, "(uuu)", &uid, &gid, &mode);
-      uid = GUINT32_FROM_BE (uid);
-      gid = GUINT32_FROM_BE (gid);
-      mode = GUINT32_FROM_BE (mode);
-
-      xattrs = g_variant_get_child_value (state->xattr_dict, xattr_offset);
-
+      
       /* Fast path for regular files to bare repositories */
-      if (S_ISREG (mode) && 
+      if (S_ISREG (state->mode) && 
           (repo->mode == OSTREE_REPO_MODE_BARE ||
            repo->mode == OSTREE_REPO_MODE_BARE_USER))
         {
-          OstreeRepoTrustedContentBareCommit barecommitstate = { -1 };
-          gs_unref_object GOutputStream *outstream = NULL;
-          gsize bytes_written;
-          gboolean have_obj;
-
-          if (!_ostree_repo_open_trusted_content_bare (repo, checksum,
-                                                       content_size,
-                                                       &barecommitstate,
-                                                       &outstream,
-                                                       &have_obj,
+          if (!_ostree_repo_open_trusted_content_bare (repo, state->checksum,
+                                                       state->content_size,
+                                                       &state->barecommitstate,
+                                                       &state->content_out,
+                                                       &state->have_obj,
                                                        cancellable, error))
             goto out;
-          
-          if (!have_obj)
+
+          if (!state->have_obj)
             {
-              if (!g_output_stream_write_all (outstream, state->payload_data + content_offset,
+              if (!g_output_stream_write_all (state->content_out,
+                                              state->payload_data + content_offset,
                                               content_size,
                                               &bytes_written,
                                               cancellable, error))
                 goto out;
-
-              if (!g_output_stream_flush (outstream, cancellable, error))
-                goto out;
             }
-
-          if (!_ostree_repo_commit_trusted_content_bare (repo, checksum, &barecommitstate,
-                                                         uid, gid, mode, xattrs,
-                                                         cancellable, error))
-            goto out;
         }
       else
         {
           /* Slower path, for symlinks and unpacking deltas into archive-z2 */
           gs_unref_object GFileInfo *finfo = NULL;
       
-          finfo = _ostree_header_gfile_info_new (mode, uid, gid);
+          finfo = _ostree_header_gfile_info_new (state->mode, state->uid, state->gid);
 
-          if (S_ISLNK (mode))
+          if (S_ISLNK (state->mode))
             {
               gs_free char *nulterminated_target =
                 g_strndup ((char*)state->payload_data + content_offset, content_size);
@@ -559,18 +570,18 @@ dispatch_open_splice_and_close (OstreeRepo                 *repo,
             }
           else
             {
-              g_assert (S_ISREG (mode));
+              g_assert (S_ISREG (state->mode));
               g_file_info_set_size (finfo, content_size);
               memin = g_memory_input_stream_new_from_data (state->payload_data + content_offset, 
content_size, NULL);
             }
 
-          if (!ostree_raw_file_to_content_stream (memin, finfo, xattrs,
+          if (!ostree_raw_file_to_content_stream (memin, finfo, state->xattrs,
                                                   &object_input, &objlen,
                                                   cancellable, error))
             goto out;
           
           if (!ostree_repo_write_content_trusted (state->repo,
-                                                  checksum,
+                                                  state->checksum,
                                                   object_input,
                                                   objlen,
                                                   cancellable,
@@ -579,8 +590,8 @@ dispatch_open_splice_and_close (OstreeRepo                 *repo,
         }
     }
 
-  state->checksum_index++;
-  state->output_target = NULL;
+  if (!dispatch_close (repo, state, cancellable, error))
+    goto out;
 
   ret = TRUE;
  out:
@@ -597,9 +608,25 @@ dispatch_open (OstreeRepo                 *repo,
 {
   gboolean ret = FALSE;
 
+  g_assert (state->output_target == NULL);
+  /* FIXME - lift this restriction */
+  g_assert (repo->mode == OSTREE_REPO_MODE_BARE ||
+            repo->mode == OSTREE_REPO_MODE_BARE_USER);
+  
   if (!open_output_target (state, cancellable, error))
     goto out;
 
+  if (!do_content_open_generic (repo, state, cancellable, error))
+    goto out;
+
+  if (!_ostree_repo_open_trusted_content_bare (repo, state->checksum,
+                                               state->content_size,
+                                               &state->barecommitstate,
+                                               &state->content_out,
+                                               &state->have_obj,
+                                               cancellable, error))
+    goto out;
+
   ret = TRUE;
  out:
   if (!ret)
@@ -614,11 +641,29 @@ dispatch_write (OstreeRepo                 *repo,
                GError                    **error)
 {
   gboolean ret = FALSE;
+  guint64 content_size;
+  guint64 content_offset;
+  gsize bytes_written;
+      
+  if (!read_varuint64 (state, &content_size, error))
+    goto out;
+  if (!read_varuint64 (state, &content_offset, error))
+    goto out;
+  if (!validate_ofs (state, content_offset, content_size, error))
+    goto out;
 
-  g_assert_not_reached ();
+  if (!state->have_obj)
+    {
+      if (!g_output_stream_write_all (state->content_out,
+                                      state->payload_data + content_offset,
+                                      content_size,
+                                      &bytes_written,
+                                      cancellable, error))
+        goto out;
+    }
   
   ret = TRUE;
-  /* out: */
+ out:
   if (!ret)
     g_prefix_error (error, "opcode open-splice-and-close: ");
   return ret;
@@ -648,11 +693,27 @@ dispatch_close (OstreeRepo                 *repo,
                 GError                    **error)
 {
   gboolean ret = FALSE;
+  
+  if (state->content_out)
+    {
+      if (!g_output_stream_flush (state->content_out, cancellable, error))
+        goto out;
 
-  g_assert_not_reached ();
+      if (!_ostree_repo_commit_trusted_content_bare (repo, state->checksum, &state->barecommitstate,
+                                                     state->uid, state->gid, state->mode,
+                                                     state->xattrs,
+                                                     cancellable, error))
+        goto out;
+    }
+      
+  g_clear_pointer (&state->xattrs, g_variant_unref);
+  g_clear_object (&state->content_out);
   
+  state->checksum_index++;
+  state->output_target = NULL;
+
   ret = TRUE;
-  /* out: */
+ out:
   if (!ret)
     g_prefix_error (error, "opcode open-splice-and-close: ");
   return ret;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]