diff options
author | Ondrej Holy <oholy@redhat.com> | 2020-10-05 11:20:06 +0200 |
---|---|---|
committer | Ondrej Holy <oholy@redhat.com> | 2020-12-01 09:21:56 +0000 |
commit | 552a2b77b3f64365c947d53133eb100793834fa3 (patch) | |
tree | 29ee5fb54f1db2677f27031f4b9340cc2200070a /daemon | |
parent | bb5eca84884924c3b507d767cb2d36eceda3fb60 (diff) | |
download | gvfs-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
Diffstat (limited to 'daemon')
-rw-r--r-- | daemon/gvfsbackendgoogle.c | 20 | ||||
-rw-r--r-- | daemon/gvfsdaemonutils.c | 74 | ||||
-rw-r--r-- | 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__ */ |