[gvfs/wip/oholy/google-progress: 9/11] google: Report progress for file transfers from local filesystem




commit 552a2b77b3f64365c947d53133eb100793834fa3
Author: Ondrej Holy <oholy redhat com>
Date:   Mon Oct 5 11:20:06 2020 +0200

    google: Report progress for file transfers from local filesystem
    
    Google backend doesn't report progress from push job. As a consequence,
    Nautilus shows wierd time estimations when moving/copying file from
    local filesystem. Let's add custom splice function and report progress
    from it.
    
    Fixes: https://gitlab.gnome.org/GNOME/gvfs/-/issues/463

 daemon/gvfsbackendgoogle.c | 20 +++++++------
 daemon/gvfsdaemonutils.c   | 74 ++++++++++++++++++++++++++++++++++++++++++++++
 daemon/gvfsdaemonutils.h   |  9 ++++++
 3 files changed, 94 insertions(+), 9 deletions(-)
---
diff --git a/daemon/gvfsbackendgoogle.c b/daemon/gvfsbackendgoogle.c
index d3333281..f4459781 100644
--- a/daemon/gvfsbackendgoogle.c
+++ b/daemon/gvfsbackendgoogle.c
@@ -49,6 +49,7 @@
 #include "gvfsjobsetdisplayname.h"
 #include "gvfsjobwrite.h"
 #include "gvfsmonitor.h"
+#include "gvfsdaemonutils.h"
 
 struct _GVfsBackendGoogle
 {
@@ -2778,7 +2779,6 @@ g_vfs_backend_google_push (GVfsBackend           *_self,
   gchar *entry_path = NULL;
   gchar *parent_path = NULL;
   gchar *local_file_title = NULL;
-  goffset size;
 
   g_rec_mutex_lock (&self->mutex);
   g_debug ("+ push: %s -> %s, %d\n", local_path, destination, flags);
@@ -2805,7 +2805,8 @@ g_vfs_backend_google_push (GVfsBackend           *_self,
   info = g_file_query_info (local_file,
                             G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE","
                             G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME","
-                            G_FILE_ATTRIBUTE_STANDARD_TYPE,
+                            G_FILE_ATTRIBUTE_STANDARD_TYPE","
+                            G_FILE_ATTRIBUTE_STANDARD_SIZE,
                             G_FILE_QUERY_INFO_NONE,
                             cancellable,
                             &error);
@@ -2981,11 +2982,14 @@ g_vfs_backend_google_push (GVfsBackend           *_self,
     }
 
   error = NULL;
-  g_output_stream_splice (G_OUTPUT_STREAM (ostream),
-                          G_INPUT_STREAM (istream),
-                          G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
-                          cancellable,
-                          &error);
+  gvfs_output_stream_splice (G_OUTPUT_STREAM (ostream),
+                             G_INPUT_STREAM (istream),
+                             G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
+                             g_file_info_get_size (info),
+                             progress_callback,
+                             progress_callback_data,
+                             cancellable,
+                             &error);
   if (error != NULL)
     {
       g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
@@ -3024,8 +3028,6 @@ g_vfs_backend_google_push (GVfsBackend           *_self,
         }
     }
 
-  size = gdata_documents_entry_get_file_size (GDATA_DOCUMENTS_ENTRY (new_document));
-  g_vfs_job_progress_callback (size, size, job);
   g_vfs_job_succeeded (G_VFS_JOB (job));
 
  out:
diff --git a/daemon/gvfsdaemonutils.c b/daemon/gvfsdaemonutils.c
index 5292ba4a..3337d22a 100644
--- a/daemon/gvfsdaemonutils.c
+++ b/daemon/gvfsdaemonutils.c
@@ -361,3 +361,77 @@ gvfs_accept_certificate (GMountSource *mount_source,
   return FALSE;
 }
 #endif
+
+gssize
+gvfs_output_stream_splice (GOutputStream *stream,
+                           GInputStream *source,
+                           GOutputStreamSpliceFlags flags,
+                           goffset total_size,
+                           GFileProgressCallback progress_callback,
+                           gpointer progress_callback_data,
+                           GCancellable *cancellable,
+                           GError **error)
+{
+  gssize n_read, n_written;
+  gsize bytes_copied;
+  char buffer[8192], *p;
+  gboolean res;
+
+  bytes_copied = 0;
+  res = TRUE;
+  do
+    {
+      n_read = g_input_stream_read (source, buffer, sizeof (buffer), cancellable, error);
+      if (n_read == -1)
+        {
+          res = FALSE;
+          break;
+        }
+
+      if (n_read == 0)
+        break;
+
+      p = buffer;
+      while (n_read > 0)
+        {
+          n_written = g_output_stream_write (stream, p, n_read, cancellable, error);
+          if (n_written == -1)
+            {
+              res = FALSE;
+              break;
+            }
+
+          p += n_written;
+          n_read -= n_written;
+          bytes_copied += n_written;
+
+          if (progress_callback)
+            progress_callback (bytes_copied, total_size, progress_callback_data);
+        }
+
+      if (bytes_copied > G_MAXSSIZE)
+        bytes_copied = G_MAXSSIZE;
+    }
+  while (res);
+
+  if (!res)
+    error = NULL; /* Ignore further errors */
+
+  if (flags & G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE)
+    {
+      /* Don't care about errors in source here */
+      g_input_stream_close (source, cancellable, NULL);
+    }
+
+  if (flags & G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET)
+    {
+      /* But write errors on close are bad! */
+      if (!g_output_stream_close (stream, cancellable, error))
+        res = FALSE;
+    }
+
+  if (res)
+    return bytes_copied;
+
+  return -1;
+}
diff --git a/daemon/gvfsdaemonutils.h b/daemon/gvfsdaemonutils.h
index 73ec0c0c..1256a615 100644
--- a/daemon/gvfsdaemonutils.h
+++ b/daemon/gvfsdaemonutils.h
@@ -47,6 +47,15 @@ gboolean     gvfs_accept_certificate                (GMountSource *mount_source,
                                                      GTlsCertificate *certificate,
                                                      GTlsCertificateFlags errors);
 
+gssize       gvfs_output_stream_splice              (GOutputStream *stream,
+                                                     GInputStream *source,
+                                                     GOutputStreamSpliceFlags flags,
+                                                     goffset total_size,
+                                                     GFileProgressCallback progress_callback,
+                                                     gpointer progress_callback_data,
+                                                     GCancellable *cancellable,
+                                                     GError **error);
+
 G_END_DECLS
 
 #endif /* __G_VFS_DAEMON_UTILS_H__ */


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