[Spice-devel] [spice-gtk v4 03/24] file-xfer: introduce _create_tasks()
Victor Toso
lists at victortoso.com
Fri Jun 24 12:22:54 UTC 2016
Hi,
On Thu, Jun 23, 2016 at 02:31:47PM -0500, Jonathon Jongsma wrote:
> On Thu, 2016-06-23 at 19:37 +0200, Victor Toso wrote:
> > We can split from file_xfer_send_start_msg_async() the logic in
> > creating the SpiceFileTransferTasks; The rest of the function can be
> > handled at spice_main_file_copy_async().
> >
> > The new function, spice_file_transfer_task_create_tasks() returns a
> > GHashTable to optimize the access to a SpiceFileTransferTask from its
> > task-id, which is what we receive from the agent.
> >
> > This change is related to split SpiceFileTransferTask from
> > channel-main.
> > ---
> > src/channel-main.c | 147 +++++++++++++++++++++++++++++++++-------------------
> > -
> > 1 file changed, 91 insertions(+), 56 deletions(-)
> >
> > diff --git a/src/channel-main.c b/src/channel-main.c
> > index 7c67fa2..2bacfb2 100644
> > --- a/src/channel-main.c
> > +++ b/src/channel-main.c
> > @@ -57,6 +57,14 @@ typedef struct spice_migrate spice_migrate;
> > static guint32 spice_file_transfer_task_get_id(SpiceFileTransferTask *self);
> > static SpiceMainChannel
> > *spice_file_transfer_task_get_channel(SpiceFileTransferTask *self);
> > static GCancellable
> > *spice_file_transfer_task_get_cancellable(SpiceFileTransferTask *self);
> > +static GHashTable *spice_file_transfer_task_create_tasks(GFile **files,
> > + SpiceMainChannel
> > *channel,
> > + GFileCopyFlags
> > flags,
> > + GCancellable
> > *cancellable,
> > + GFileProgressCallbac
> > k progress_callback,
> > + gpointer
> > progress_callback_data,
> > + GAsyncReadyCallback
> > callback,
> > + gpointer user_data);
> >
> > /**
> > * SECTION:file-transfer-task
> > @@ -3100,54 +3108,6 @@ static void task_finished(SpiceFileTransferTask *task,
> > g_hash_table_remove(channel->priv->file_xfer_tasks,
> > GUINT_TO_POINTER(task->id));
> > }
> >
> > -static void file_xfer_send_start_msg_async(SpiceMainChannel *channel,
> > - GFile **files,
> > - GFileCopyFlags flags,
> > - GCancellable *cancellable,
> > - GFileProgressCallback
> > progress_callback,
> > - gpointer progress_callback_data,
> > - GAsyncReadyCallback callback,
> > - gpointer user_data)
> > -{
> > - SpiceMainChannelPrivate *c = channel->priv;
> > - SpiceFileTransferTask *task;
> > - gint i;
> > -
> > - for (i = 0; files[i] != NULL && !g_cancellable_is_cancelled(cancellable);
> > i++) {
> > - GCancellable *task_cancellable = cancellable;
> > - /* if a cancellable object was not provided for the overall
> > operation,
> > - * create a separate object for each file so that they can be
> > cancelled
> > - * separately */
> > - if (!task_cancellable)
> > - task_cancellable = g_cancellable_new();
> > -
> > - task = spice_file_transfer_task_new(channel, files[i],
> > task_cancellable);
> > - task->flags = flags;
> > - task->progress_callback = progress_callback;
> > - task->progress_callback_data = progress_callback_data;
> > - task->callback = callback;
> > - task->user_data = user_data;
> > -
> > - CHANNEL_DEBUG(channel, "Insert a xfer task:%u to task list", task-
> > >id);
> > - g_hash_table_insert(c->file_xfer_tasks,
> > - GUINT_TO_POINTER(task->id),
> > - g_object_ref(task));
> > - g_signal_connect(task, "finished", G_CALLBACK(task_finished),
> > channel);
> > - g_signal_emit(channel, signals[SPICE_MAIN_NEW_FILE_TRANSFER], 0,
> > task);
> > -
> > - g_file_read_async(files[i],
> > - G_PRIORITY_DEFAULT,
> > - cancellable,
> > - file_xfer_read_async_cb,
> > - task);
> > - task->pending = TRUE;
> > -
> > - /* if we created a per-task cancellable above, free it */
> > - if (!cancellable)
> > - g_object_unref(task_cancellable);
> > - }
> > -}
> > -
> > /**
> > * spice_main_file_copy_async:
> > * @channel: a #SpiceMainChannel
> > @@ -3191,6 +3151,9 @@ void spice_main_file_copy_async(SpiceMainChannel
> > *channel,
> > gpointer user_data)
> > {
> > SpiceMainChannelPrivate *c;
> > + GHashTable *xfer_ht;
> > + GHashTableIter iter;
> > + gpointer key, value;
> >
> > g_return_if_fail(channel != NULL);
> > g_return_if_fail(SPICE_IS_MAIN_CHANNEL(channel));
> > @@ -3208,14 +3171,38 @@ void spice_main_file_copy_async(SpiceMainChannel
> > *channel,
> > return;
> > }
> >
> > - file_xfer_send_start_msg_async(channel,
> > - sources,
> > - flags,
> > - cancellable,
> > - progress_callback,
> > - progress_callback_data,
> > - callback,
> > - user_data);
> > + xfer_ht = spice_file_transfer_task_create_tasks(sources,
> > + channel,
> > + flags,
> > + cancellable,
> > + progress_callback,
> > + progress_callback_data,
> > + callback,
> > + user_data);
> > + g_hash_table_iter_init(&iter, xfer_ht);
> > + while (g_hash_table_iter_next(&iter, &key, &value)) {
> > + guint32 task_id;
> > + GFile *file;
> > + SpiceFileTransferTask *xfer_task;
> > +
> > + xfer_task = value;
>
> I'd just initialize this above where it's declared. Personal preference.
Sure
>
> > + task_id = spice_file_transfer_task_get_id(xfer_task);
> > + g_object_get(xfer_task, "file", &file, NULL);
> > +
> > + SPICE_DEBUG("Insert a xfer task:%u to task list", task_id);
> > +
> > + g_hash_table_insert(c->file_xfer_tasks, key,
> > g_object_ref(xfer_task));
> > + g_signal_connect(xfer_task, "finished", G_CALLBACK(task_finished),
> > channel);
> > + g_signal_emit(channel, signals[SPICE_MAIN_NEW_FILE_TRANSFER], 0,
> > xfer_task);
> > +
> > + g_file_read_async(file,
> > + G_PRIORITY_DEFAULT,
> > + cancellable,
> > + file_xfer_read_async_cb,
> > + xfer_task);
> > + xfer_task->pending = TRUE;
> > + }
> > + g_hash_table_unref(xfer_ht);
> > }
> >
> > /**
> > @@ -3259,6 +3246,54 @@ static GCancellable
> > *spice_file_transfer_task_get_cancellable(SpiceFileTransferT
> > return self->cancellable;
> > }
> >
> > +/* Helper function which only creates a SpiceFileTransferTask per GFile
> > + * in @files and returns a HashTable mapping task-id to the task itself
> > + * Note that the HashTable does not free its values uppon destruction:
>
> typo: uppon -> upon
>
> > + * The reference created here should be freed by
>
> "The reference" is just slightly unclear. It could refer to the reference of the
> GHashTable, or the SpiceFileTransferTask. Would be nice to be more explicit.
Changed to:
* The SpiceFileTransferTask reference created here should be freed by
* spice_file_transfer_task_completed */
>
> > + * spice_file_transfer_task_completed */
> > +static GHashTable *spice_file_transfer_task_create_tasks(GFile **files,
> > + SpiceMainChannel
> > *channel,
> > + GFileCopyFlags
> > flags,
> > + GCancellable
> > *cancellable,
> > + GFileProgressCallbac
> > k progress_callback,
> > + gpointer
> > progress_callback_data,
> > + GAsyncReadyCallback
> > callback,
> > + gpointer user_data)
> > +{
> > + GHashTable *xfer_ht;
> > + gint i;
> > +
> > + g_return_val_if_fail(files != NULL && files[0] != NULL, NULL);
> > +
> > + xfer_ht = g_hash_table_new(g_direct_hash, g_direct_equal);
> > + for (i = 0; files[i] != NULL && !g_cancellable_is_cancelled(cancellable);
> > i++) {
> > + SpiceFileTransferTask *xfer_task;
> > + guint32 task_id;
> > + GCancellable *task_cancellable = cancellable;
> > +
> > + /* if a cancellable object was not provided for the overall
> > operation,
> > + * create a separate object for each file so that they can be
> > cancelled
> > + * separately */
> > + if (!task_cancellable)
> > + task_cancellable = g_cancellable_new();
> > +
> > + xfer_task = spice_file_transfer_task_new(channel, files[i],
> > task_cancellable);
> > + xfer_task->flags = flags;
> > + xfer_task->progress_callback = progress_callback;
> > + xfer_task->progress_callback_data = progress_callback_data;
> > + xfer_task->callback = callback;
> > + xfer_task->user_data = user_data;
>
> Perhaps we should add a FIXME to initialize these values as part of
> spice_file_transfer_task_new()? I know some of them will be removed in future
> patches in this series, but not all, I think.
Right! To reduce the amount of conflicts, I'll include a FIXME and later
on we can move the remaining values to the _task_new() function.
>
> > +
> > + task_id = spice_file_transfer_task_get_id(xfer_task);
> > + g_hash_table_insert(xfer_ht, GUINT_TO_POINTER(task_id), xfer_task);
> > +
> > + /* if we created a per-task cancellable above, free it */
>
> Probably more accurate to say "unref" instead of "free" here.
Agreed
>
> > + if (!cancellable)
> > + g_object_unref(task_cancellable);
> > + }
> > + return xfer_ht;
> > +}
> > +
> > static void
> > spice_file_transfer_task_get_property(GObject *object,
> > guint property_id,
>
> comments above are all minor
>
> Acked-by: Jonathon Jongsma <jjongsma at redhat.com>
Thanks,
toso
>
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/spice-devel
More information about the Spice-devel
mailing list