[ostree] fetcher: Only open files when we are ready to write to them



commit 95a78542e9a2cb081719d3a2884e3d3e71e83e55
Author: Colin Walters <walters verbum org>
Date:   Sat Aug 31 10:51:14 2013 -0400

    fetcher: Only open files when we are ready to write to them
    
    Otherwise we quickly run out of file descriptors when doing large
    requests.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=707157

 src/libostree/ostree-fetcher.c |   65 +++++++++++++++++++---------------------
 1 files changed, 31 insertions(+), 34 deletions(-)
---
diff --git a/src/libostree/ostree-fetcher.c b/src/libostree/ostree-fetcher.c
index 9c2ee4a..697ea8e 100644
--- a/src/libostree/ostree-fetcher.c
+++ b/src/libostree/ostree-fetcher.c
@@ -42,6 +42,7 @@ typedef struct {
 
   SoupRequest *request;
 
+  gboolean is_partial;
   GFile *tmpfile;
   GInputStream *request_body;
   GOutputStream *out_stream;
@@ -213,16 +214,12 @@ on_request_sent (GObject        *object,
   gs_unref_object SoupMessage *msg = NULL;
   GOutputStreamSpliceFlags flags = G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET;
 
+  pending->state = OSTREE_FETCHER_STATE_COMPLETE;
   pending->request_body = soup_request_send_finish ((SoupRequest*) object,
                                                    result, &local_error);
 
   if (!pending->request_body)
-    {
-      pending->state = OSTREE_FETCHER_STATE_COMPLETE;
-      g_simple_async_result_take_error (pending->result, local_error);
-      g_simple_async_result_complete (pending->result);
-      return;
-    }
+    goto out;
   
   if (SOUP_IS_REQUEST_HTTP (object))
     {
@@ -231,6 +228,7 @@ on_request_sent (GObject        *object,
         {
           // We already have the whole file, so just use it.
           pending->state = OSTREE_FETCHER_STATE_COMPLETE;
+          (void) g_input_stream_close (pending->request_body, NULL, NULL);
           g_simple_async_result_complete (pending->result);
           g_object_unref (pending->result);
           return;
@@ -250,23 +248,38 @@ on_request_sent (GObject        *object,
           g_set_error (&local_error, G_IO_ERROR, code,
                        "Server returned status %u: %s",
                        msg->status_code, soup_status_get_phrase (msg->status_code));
-          g_simple_async_result_take_error (pending->result, local_error);
-          g_simple_async_result_complete (pending->result);
-          return;
+          goto out;
         }
     }
 
   pending->state = OSTREE_FETCHER_STATE_DOWNLOADING;
   
   pending->content_length = soup_request_get_content_length (pending->request);
+
+  if (pending->is_partial)
+    pending->out_stream = G_OUTPUT_STREAM (g_file_append_to (pending->tmpfile, G_FILE_CREATE_NONE,
+                                                             pending->cancellable, &local_error));
+  else
+    pending->out_stream = G_OUTPUT_STREAM (g_file_replace (pending->tmpfile, NULL, FALSE,
+                                                           G_FILE_CREATE_REPLACE_DESTINATION,
+                                                           pending->cancellable, &local_error));
+  if (!pending->out_stream)
+    goto out;
   
   g_output_stream_splice_async (pending->out_stream, pending->request_body, flags, G_PRIORITY_DEFAULT,
                                 pending->cancellable, on_splice_complete, pending);
+ out:
+  if (local_error)
+    {
+      g_simple_async_result_take_error (pending->result, local_error);
+      g_simple_async_result_complete (pending->result);
+    }
 }
 
 static OstreeFetcherPendingURI *
 ostree_fetcher_request_uri_internal (OstreeFetcher         *self,
                                      SoupURI               *uri,
+                                     gboolean               is_partial,
                                      GCancellable          *cancellable,
                                      GAsyncReadyCallback    callback,
                                      gpointer               user_data,
@@ -281,6 +294,7 @@ ostree_fetcher_request_uri_internal (OstreeFetcher         *self,
   pending->refcount = 1;
   pending->self = g_object_ref (self);
   pending->uri = soup_uri_copy (uri);
+  pending->is_partial = is_partial;
   pending->tmpfile = g_file_get_child (self->tmpdir, hash);
   pending->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
   pending->request = soup_requester_request_uri (self->requester, uri, &local_error);
@@ -307,29 +321,26 @@ ostree_fetcher_request_uri_with_partial_async (OstreeFetcher         *self,
                                                gpointer               user_data)
 {
   OstreeFetcherPendingURI *pending;
+  gs_unref_object GFileInfo *file_info = NULL;
   GError *local_error = NULL;
 
   self->total_requests++;
 
-  pending = ostree_fetcher_request_uri_internal (self, uri, cancellable,
+  pending = ostree_fetcher_request_uri_internal (self, uri, TRUE, cancellable,
                                                  callback, user_data,
                                                  ostree_fetcher_request_uri_with_partial_async);
-  pending->out_stream = G_OUTPUT_STREAM (g_file_append_to (pending->tmpfile, G_FILE_CREATE_NONE, NULL, 
&local_error));
-  if (!pending->out_stream)
+
+  if (!ot_gfile_query_info_allow_noent (pending->tmpfile, OSTREE_GIO_FAST_QUERYINFO,
+                                        G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+                                        &file_info, cancellable, &local_error))
     goto out;
 
   if (SOUP_IS_REQUEST_HTTP (pending->request))
     {
       SoupMessage *msg;
-      gs_unref_object GFileInfo *file_info = 
-        g_file_query_info (pending->tmpfile, OSTREE_GIO_FAST_QUERYINFO,
-                           G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
-                           NULL, &local_error);
-      if (!file_info)
-        goto out;
 
       msg = soup_request_http_get_message ((SoupRequestHTTP*) pending->request);
-      if (g_file_info_get_size (file_info) > 0)
+      if (file_info && g_file_info_get_size (file_info) > 0)
         soup_message_headers_set_range (msg->request_headers, g_file_info_get_size (file_info), -1);
       g_hash_table_insert (self->message_to_request,
                            soup_request_http_get_message ((SoupRequestHTTP*)pending->request),
@@ -373,20 +384,13 @@ ostree_fetcher_request_uri_async (OstreeFetcher         *self,
                                   gpointer               user_data)
 {
   OstreeFetcherPendingURI *pending;
-  GError *local_error = NULL;
 
   self->total_requests++;
 
-  pending = ostree_fetcher_request_uri_internal (self, uri, cancellable,
+  pending = ostree_fetcher_request_uri_internal (self, uri, FALSE, cancellable,
                                                  callback, user_data,
                                                  ostree_fetcher_request_uri_async);
 
-  pending->out_stream = G_OUTPUT_STREAM (g_file_replace (pending->tmpfile, NULL, FALSE,
-                                                         G_FILE_CREATE_REPLACE_DESTINATION,
-                                                         cancellable, &local_error));
-  if (!pending->out_stream)
-    goto out;
-
   if (SOUP_IS_REQUEST_HTTP (pending->request))
     {
       g_hash_table_insert (self->message_to_request,
@@ -396,13 +400,6 @@ ostree_fetcher_request_uri_async (OstreeFetcher         *self,
   
   soup_request_send_async (pending->request, cancellable,
                            on_request_sent, pending);
-
- out:
-  if (local_error)
-    {
-      g_simple_async_result_take_error (pending->result, local_error);
-      g_simple_async_result_complete (pending->result);
-    }
 }
 
 GFile *


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