summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndrej Holy <oholy@redhat.com>2020-10-05 11:20:06 +0200
committerOndrej Holy <oholy@redhat.com>2020-12-01 09:21:56 +0000
commit552a2b77b3f64365c947d53133eb100793834fa3 (patch)
tree29ee5fb54f1db2677f27031f4b9340cc2200070a
parentbb5eca84884924c3b507d767cb2d36eceda3fb60 (diff)
downloadgvfs-552a2b77b3f64365c947d53133eb100793834fa3.tar.gz
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
-rw-r--r--daemon/gvfsbackendgoogle.c20
-rw-r--r--daemon/gvfsdaemonutils.c74
-rw-r--r--daemon/gvfsdaemonutils.h9
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__ */