[ostree] core: Avoid reading regular file data twice when archiving



commit 0d4df5b3fea31daec2b0b772cb1f0b0fab594cc8
Author: Colin Walters <walters verbum org>
Date:   Fri Dec 2 14:23:01 2011 -0500

    core: Avoid reading regular file data twice when archiving

 src/libostree/ostree-core.c |   17 +++++++--
 src/libostree/ostree-repo.c |   82 ++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 90 insertions(+), 9 deletions(-)
---
diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c
index 8e6b854..93db356 100644
--- a/src/libostree/ostree-core.c
+++ b/src/libostree/ostree-core.c
@@ -650,10 +650,16 @@ ostree_pack_file_for_input (GOutputStream     *output,
     g_assert_not_reached ();
 
   ret = TRUE;
+  if (out_checksum)
+    {
+      *out_checksum = ret_checksum;
+      ret_checksum = NULL;
+    }
  out:
   if (pack_builder_initialized)
     g_variant_builder_clear (&pack_builder);
   ot_clear_gvariant (&pack_variant);
+  ot_clear_checksum (&ret_checksum);
   return ret;
 }
 
@@ -911,10 +917,13 @@ ostree_create_file_from_input (GFile            *dest_file,
       if (!out)
         goto out;
 
-      if (!ot_gio_splice_and_checksum ((GOutputStream*)out, input,
-                                       out_checksum ? &ret_checksum : NULL,
-                                       cancellable, error))
-        goto out;
+      if (input)
+        {
+          if (!ot_gio_splice_and_checksum ((GOutputStream*)out, input,
+                                           out_checksum ? &ret_checksum : NULL,
+                                           cancellable, error))
+            goto out;
+        }
 
       if (!g_output_stream_close ((GOutputStream*)out, NULL, error))
         goto out;
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index 0beef27..5470c1e 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -936,6 +936,81 @@ ostree_repo_store_object_trusted (OstreeRepo   *self,
     return link_object_trusted (self, file, checksum, objtype, overwrite, did_exist, cancellable, error);
 }
 
+static gboolean
+ostree_repo_store_file (OstreeRepo         *self,
+                        GFile              *file,
+                        GFileInfo          *file_info,
+                        GChecksum         **out_checksum,
+                        gboolean           *did_exist,
+                        GCancellable       *cancellable,
+                        GError            **error)
+{
+  gboolean ret = FALSE;
+  OstreeRepoPrivate *priv = GET_PRIVATE (self);
+  GVariant *xattrs = NULL;
+  GInputStream *input = NULL;
+  GOutputStream *temp_out = NULL;
+  GChecksum *ret_checksum = NULL;
+  GFile *temp_file = NULL;
+
+  if (priv->archive && g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR)
+    {
+       /* Avoid reading the input data twice for regular files in the
+          archive case */
+      input = (GInputStream*)g_file_read (file, cancellable, error);
+      if (input == NULL)
+        goto out;
+
+      xattrs = ostree_get_xattrs_for_file (file, error);
+      if (!xattrs)
+        goto out;
+      
+      if (!ostree_create_temp_regular_file (priv->tmp_dir,
+                                            "archive-tmp-", NULL,
+                                            &temp_file, &temp_out,
+                                            cancellable, error))
+        goto out;
+      
+      if (!ostree_pack_file_for_input (temp_out, file_info, input, xattrs,
+                                       &ret_checksum, cancellable, error))
+        goto out;
+
+      if (!g_output_stream_close (temp_out, cancellable, error))
+        goto out;
+
+      if (!link_object_trusted (self, temp_file,
+                                g_checksum_get_string (ret_checksum),
+                                OSTREE_OBJECT_TYPE_FILE, FALSE, did_exist,
+                                cancellable, error))
+        goto out;
+    }
+  else
+    {
+      /* If we're not an archive, we just need to checksum the input,
+         then call link() */
+      if (!ostree_checksum_file (file, OSTREE_OBJECT_TYPE_FILE, &ret_checksum, cancellable, error))
+        goto out;
+      
+      if (!link_object_trusted (self, file, g_checksum_get_string (ret_checksum),
+                                OSTREE_OBJECT_TYPE_FILE, FALSE, did_exist,
+                                cancellable, error))
+        goto out;
+    }
+
+  ret = TRUE;
+  *out_checksum = ret_checksum;
+  ret_checksum = NULL;
+ out:
+  if (temp_file)
+    (void) g_file_delete (temp_file, NULL, NULL);
+  g_clear_object (&temp_file);
+  g_clear_object (&temp_out);
+  g_clear_object (&input);
+  ot_clear_checksum (&ret_checksum);
+  ot_clear_gvariant (&xattrs);
+  return ret;
+}
+
 gboolean
 ostree_repo_store_packfile (OstreeRepo       *self,
                             const char       *expected_checksum,
@@ -1155,11 +1230,8 @@ import_directory_recurse (OstreeRepo           *self,
       else
         {
           ot_clear_checksum (&child_file_checksum);
-          if (!ostree_checksum_file (child, OSTREE_OBJECT_TYPE_FILE, &child_file_checksum, cancellable, error))
-            goto out;
-          
-          if (!ostree_repo_store_object_trusted (self, child, g_checksum_get_string (child_file_checksum),
-                                                 OSTREE_OBJECT_TYPE_FILE, FALSE, &did_exist, cancellable, error))
+
+          if (!ostree_repo_store_file (self, child, child_info, &child_file_checksum, &did_exist, cancellable, error))
             goto out;
 
           g_hash_table_replace (file_checksums, g_strdup (name),



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