[gvfs/ftp-reorg: 15/15] [FTP] make the pull callback emit progress callbacks
- From: Benjamin Otte <otte src gnome org>
- To: svn-commits-list gnome org
- Subject: [gvfs/ftp-reorg: 15/15] [FTP] make the pull callback emit progress callbacks
- Date: Mon, 8 Jun 2009 15:23:24 -0400 (EDT)
commit e9e1c28afc72a26a40dd39e2acecfb4953acad97
Author: Benjamin Otte <otte gnome org>
Date: Mon Jun 8 21:15:46 2009 +0200
[FTP] make the pull callback emit progress callbacks
The progress callbacks are throttled to at most once per second to not
overload dbus for very fast connections. This is implemented somewhat
ugly using a cancellable that interrupts once per second to ensure
progress updates are sent.
If someone knows a saner approach, please tell me (or better: provide a
patch).
---
daemon/gvfsbackendftp.c | 87 +++++++++++++++++++++++++++++++++++++++++------
1 files changed, 76 insertions(+), 11 deletions(-)
diff --git a/daemon/gvfsbackendftp.c b/daemon/gvfsbackendftp.c
index 9a0f08a..63bb7d0 100644
--- a/daemon/gvfsbackendftp.c
+++ b/daemon/gvfsbackendftp.c
@@ -1162,6 +1162,19 @@ out:
g_vfs_ftp_task_done (&task);
}
+static void
+cancel_timer_cb (GCancellable *orig, GCancellable *to_cancel)
+{
+ g_cancellable_cancel (to_cancel);
+}
+
+static gboolean
+cancel_cancellable (gpointer cancellable)
+{
+ g_cancellable_cancel (cancellable);
+ return FALSE;
+}
+
static gssize
ftp_output_stream_splice (GOutputStream *output,
GInputStream *input,
@@ -1174,36 +1187,88 @@ ftp_output_stream_splice (GOutputStream *output,
gssize n_read, n_written;
gssize bytes_copied;
char buffer[8192], *p;
- gboolean res;
+ GCancellable *timer_cancel;
+ gulong cancel_cb_id;
bytes_copied = 0;
+ timer_cancel = NULL;
+
for (;;)
{
- n_read = g_input_stream_read (input, buffer, sizeof (buffer), cancellable, error);
+ n_read = g_input_stream_read (input, buffer, sizeof (buffer), timer_cancel ? timer_cancel : cancellable, error);
if (n_read == -1)
- return -1;
-
+ {
+ if (g_cancellable_is_cancelled (timer_cancel) &&
+ !g_cancellable_is_cancelled (cancellable))
+ {
+ g_cancellable_disconnect (cancellable, cancel_cb_id);
+ g_object_unref (timer_cancel);
+ timer_cancel = NULL;
+ g_clear_error (error);
+ progress_callback (bytes_copied, total_size, progress_callback_data);
+ }
+ else
+ {
+ bytes_copied = -1;
+ break;
+ }
+ }
if (n_read == 0)
- return bytes_copied;
+ break;
p = buffer;
while (n_read > 0)
{
- n_written = g_output_stream_write (output, p, n_read, cancellable, error);
+ n_written = g_output_stream_write (output, p, n_read, timer_cancel ? timer_cancel : cancellable, error);
if (n_written == -1)
- return -1;
+ {
+ if (g_cancellable_is_cancelled (timer_cancel) &&
+ !g_cancellable_is_cancelled (cancellable))
+ {
+ g_cancellable_disconnect (cancellable, cancel_cb_id);
+ g_object_unref (timer_cancel);
+ timer_cancel = NULL;
+ g_clear_error (error);
+ progress_callback (bytes_copied + n_written, total_size, progress_callback_data);
+ }
+ else
+ {
+ bytes_copied = -1;
+ break;
+ }
+ }
p += n_written;
n_read -= n_written;
bytes_copied += n_written;
+ if (progress_callback && timer_cancel == NULL)
+ {
+ timer_cancel = g_cancellable_new ();
+ cancel_cb_id = g_cancellable_connect (cancellable,
+ G_CALLBACK (cancel_timer_cb),
+ timer_cancel,
+ NULL);
+ g_object_ref (timer_cancel);
+ g_timeout_add_seconds_full (G_PRIORITY_DEFAULT,
+ 1,
+ cancel_cancellable,
+ timer_cancel,
+ g_object_unref);
+ }
}
}
- while (res);
- if (res)
- return bytes_copied;
+ if (timer_cancel != NULL)
+ {
+ /* no need to remove the timeout, it'll remove itself fine and we
+ * don't get into races that way */
+ g_cancellable_disconnect (cancellable, cancel_cb_id);
+ g_object_unref (timer_cancel);
+ }
+ if (bytes_copied >= 0 && progress_callback)
+ progress_callback (bytes_copied, total_size, progress_callback_data);
- return -1;
+ return bytes_copied;
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]