[libsoup/wip/nacho/request-file-async] request-file: avoid using a thread to request the file in async mode



commit bdf7dce4776677c822f94f036f2e0d39f4e93221
Author: Ignacio Casal Quinteiro <qignacio amazon com>
Date:   Fri Feb 1 17:06:43 2019 +0100

    request-file: avoid using a thread to request the file in async mode

 libsoup/soup-request-file.c | 110 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 99 insertions(+), 11 deletions(-)
---
diff --git a/libsoup/soup-request-file.c b/libsoup/soup-request-file.c
index 61fc712d..c402a5b4 100644
--- a/libsoup/soup-request-file.c
+++ b/libsoup/soup-request-file.c
@@ -116,6 +116,7 @@ windowsify_file_uri_path (char *path)
 }
 #endif
 
+/* Does not do I/O */
 static gboolean
 soup_request_file_ensure_file (SoupRequestFile  *file,
                               GCancellable     *cancellable,
@@ -198,20 +199,95 @@ soup_request_file_send (SoupRequest          *request,
 }
 
 static void
-soup_request_file_send_async_thread (GTask        *task,
-                                    gpointer      source_object,
-                                    gpointer      task_data,
-                                    GCancellable *cancellable)
+on_enumerate_children_ready (GObject      *source,
+                             GAsyncResult *result,
+                             gpointer      user_data)
 {
-       SoupRequest *request = source_object;
-       GInputStream *stream;
+       GTask *task = G_TASK (user_data);
+       SoupRequestFile *file = SOUP_REQUEST_FILE (g_task_get_source_object (task));
+       GFileEnumerator *enumerator;
        GError *error = NULL;
 
-       stream = soup_request_file_send (request, cancellable, &error);
-       if (stream == NULL)
+       enumerator = g_file_enumerate_children_finish (G_FILE (source), result, &error);
+       if (enumerator == NULL) {
                g_task_return_error (task, error);
-       else
+       } else {
+               GInputStream *stream;
+
+               stream = soup_directory_input_stream_new (enumerator,
+                                                         soup_request_get_uri (SOUP_REQUEST (file)));
+               g_object_unref (enumerator);
+               file->priv->mime_type = g_strdup ("text/html");
+
                g_task_return_pointer (task, stream, g_object_unref);
+       }
+
+       g_object_unref (task);
+}
+
+static void
+on_query_info_ready (GObject      *source,
+                     GAsyncResult *result,
+                     gpointer      user_data)
+{
+       GTask *task = G_TASK (user_data);
+       SoupRequestFile *file = SOUP_REQUEST_FILE (g_task_get_source_object (task));
+       GInputStream *stream = G_INPUT_STREAM (g_task_get_task_data (task));
+       GFileInfo *info;
+       GError *error = NULL;
+
+       info = g_file_query_info_finish (G_FILE (source), result, &error);
+       if (info) {
+               const char *content_type;
+
+               file->priv->size = g_file_info_get_size (info);
+               content_type = g_file_info_get_content_type (info);
+
+               if (content_type)
+                       file->priv->mime_type = g_content_type_get_mime_type (content_type);
+               g_object_unref (info);
+       }
+
+       g_task_return_pointer (task, g_object_ref (stream), g_object_unref);
+       g_object_unref (task);
+}
+
+static void
+on_read_file_ready (GObject      *source,
+                    GAsyncResult *result,
+                    gpointer      user_data)
+{
+       GTask *task = G_TASK (user_data);
+       SoupRequestFile *file = SOUP_REQUEST_FILE (g_task_get_source_object (task));
+       GInputStream *stream;
+       GError *error = NULL;
+
+       stream = G_INPUT_STREAM (g_file_read_finish (G_FILE (source), result, &error));
+       if (stream == NULL) {
+               if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY)) {
+                       g_file_enumerate_children_async (file->priv->gfile,
+                                                        "*",
+                                                        G_FILE_QUERY_INFO_NONE,
+                                                        G_PRIORITY_DEFAULT,
+                                                        g_task_get_cancellable (task),
+                                                        on_enumerate_children_ready,
+                                                        task);
+                       g_error_free (error);
+               } else {
+                       g_task_return_error (task, error);
+                       g_object_unref (task);
+               }
+       } else {
+               g_task_set_task_data (task, stream, g_object_unref);
+               g_file_query_info_async (file->priv->gfile,
+                                        G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
+                                        G_FILE_ATTRIBUTE_STANDARD_SIZE,
+                                        0,
+                                        G_PRIORITY_DEFAULT,
+                                        g_task_get_cancellable (task),
+                                        on_query_info_ready,
+                                        task);
+       }
 }
 
 static void
@@ -220,11 +296,23 @@ soup_request_file_send_async (SoupRequest          *request,
                              GAsyncReadyCallback   callback,
                              gpointer              user_data)
 {
+       SoupRequestFile *file = SOUP_REQUEST_FILE (request);
        GTask *task;
+       GError *error = NULL;
 
        task = g_task_new (request, cancellable, callback, user_data);
-       g_task_run_in_thread (task, soup_request_file_send_async_thread);
-       g_object_unref (task);
+
+       if (!soup_request_file_ensure_file (file, cancellable, &error)) {
+               g_task_return_error (task, error);
+               g_object_unref (task);
+               return;
+       }
+
+       g_file_read_async (file->priv->gfile,
+                          G_PRIORITY_DEFAULT,
+                          cancellable,
+                          on_read_file_ready,
+                          task);
 }
 
 static GInputStream *


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