[Spice-devel] [spice-gtk v3 04/16] file-xfer: introduce file-info signal
Jonathon Jongsma
jjongsma at redhat.com
Thu Jun 2 22:14:57 UTC 2016
On Mon, 2016-05-30 at 11:55 +0200, Victor Toso wrote:
> In order to avoid sending the agent message on
> file_xfer_info_async_cb, we can provide the "file-info" signal to
> SpiceFileTransferTask.
>
> In order to this signal be significant to applications, we request all
> standard attributes to g_file_query_info_async.
>
I'd like to see some explanation for why this signal is useful, or is an
improvement from the previous behavior. For instance, *why* do we want to avoid
sending the agent message on file_xfer_info_async_cb()? I assume that it's
because after we split this into a different file, we will no longer have
access to agent_msg_queue_many(), but I'd like to have it in the commit log.
That said, I have to admit that this change feels a bit strange to me. For
example, when SpiceFileTransferTask is split out to its own self-contained
object, I would expect that if I called spice_file_transfer_task_start_task(),
it would start transferring the file. However, after this change, the only
thing it does is open the file stream and query the file info and then emit the
"file-info" signal. The MainChannel is required to handle the file-info signal
and start sending agent messages. But there's nothing about the function name
spice_file_transfer_task_start() that makes you think that this is how to use
this function. I understand that this is internal API, so it doesn't
necessarily need to be as polished as external API would be, but I wonder if it
could be improved.
I can think of a couple of possible options:
- rename spice_file_transfer_task_start_task() to something that makes it a
little bit more obvious what to expect. Maybe
spice_file_transfer_task_prepare(), or spice_file_transfer_task_query_info(),
or ???
- expose the agent_msg_queue() function (as
main_channel_queue_agent_message()?) in a (private?) header so that
SpiceFileTransferTask can initiate the agent communication itself
Thoughts?
Reviewed-by: Jonathon Jongsma <jjongsma at redhat.com>
>
> This change is related to split SpiceFileTransferTask from
> channel-main.
> ---
> src/channel-main.c | 96 ++++++++++++++++++++++++++++++++++++++---------------
> -
> 1 file changed, 68 insertions(+), 28 deletions(-)
>
> diff --git a/src/channel-main.c b/src/channel-main.c
> index 7843aeb..0ed322e 100644
> --- a/src/channel-main.c
> +++ b/src/channel-main.c
> @@ -136,6 +136,7 @@ enum {
>
> enum {
> SIGNAL_FINISHED,
> + SIGNAL_FILE_INFO,
> LAST_TASK_SIGNAL
> };
>
> @@ -3001,11 +3002,6 @@ static void file_xfer_info_async_cb(GObject *obj,
> GAsyncResult *res, gpointer da
> GFileInfo *info;
> GFile *file = G_FILE(obj);
> GError *error = NULL;
> - GKeyFile *keyfile = NULL;
> - gchar *basename = NULL;
> - VDAgentFileXferStartMessage msg;
> - gsize /*msg_size*/ data_len;
> - gchar *string;
> SpiceFileTransferTask *self = SPICE_FILE_TRANSFER_TASK(data);
>
> self->pending = FALSE;
> @@ -3015,33 +3011,14 @@ static void file_xfer_info_async_cb(GObject *obj,
> GAsyncResult *res, gpointer da
>
> self->file_size =
> g_file_info_get_attribute_uint64(info,
> G_FILE_ATTRIBUTE_STANDARD_SIZE);
> + g_signal_emit(self, task_signals[SIGNAL_FILE_INFO], 0, info);
> g_object_notify(G_OBJECT(self), "progress");
> - keyfile = g_key_file_new();
> + g_clear_object(&info);
>
> - /* File name */
> - basename = g_file_get_basename(file);
> - g_key_file_set_string(keyfile, "vdagent-file-xfer", "name", basename);
> - g_free(basename);
> - /* File size */
> - g_key_file_set_uint64(keyfile, "vdagent-file-xfer", "size", self-
> >file_size);
> -
> - /* Save keyfile content to memory. TODO: more file attributions
> - need to be sent to guest */
> - string = g_key_file_to_data(keyfile, &data_len, &error);
> - g_key_file_free(keyfile);
> - if (error)
> - goto failed;
> -
> - /* Create file-xfer start message */
> - msg.id = self->id;
> - agent_msg_queue_many(self->channel, VD_AGENT_FILE_XFER_START,
> - &msg, sizeof(msg),
> - string, data_len + 1, NULL);
> - g_free(string);
> - spice_channel_wakeup(SPICE_CHANNEL(self->channel), FALSE);
> return;
>
> failed:
> + g_clear_object(&info);
> spice_file_transfer_task_completed(self, error);
> }
>
> @@ -3059,7 +3036,7 @@ static void file_xfer_read_async_cb(GObject *obj,
> GAsyncResult *res, gpointer da
> }
>
> g_file_query_info_async(self->file,
> - G_FILE_ATTRIBUTE_STANDARD_SIZE,
> + "standard::*",
> G_FILE_QUERY_INFO_NONE,
> G_PRIORITY_DEFAULT,
> self->cancellable,
> @@ -3071,6 +3048,50 @@ static void file_xfer_read_async_cb(GObject *obj,
> GAsyncResult *res, gpointer da
> static SpiceFileTransferTask *spice_file_transfer_task_new(SpiceMainChannel
> *channel,
> GFile *file,
> GCancellable
> *cancellable);
> +static void file_xfer_on_file_info(SpiceFileTransferTask *xfer_task,
> + GFileInfo *info,
> + gpointer data)
> +{
> + SpiceMainChannel *channel;
> + GKeyFile *keyfile;
> + VDAgentFileXferStartMessage msg;
> + gchar *string, *basename;
> + guint64 file_size;
> + gsize data_len;
> + GError *error = NULL;
> +
> + g_return_if_fail(info != NULL);
> +
> + channel = SPICE_MAIN_CHANNEL(data);
> +
> + basename = g_file_info_get_attribute_as_string(info,
> G_FILE_ATTRIBUTE_STANDARD_NAME);
> + file_size = g_file_info_get_attribute_uint64(info,
> G_FILE_ATTRIBUTE_STANDARD_SIZE);
> +
> + keyfile = g_key_file_new();
> + g_key_file_set_string(keyfile, "vdagent-file-xfer", "name", basename);
> + g_key_file_set_uint64(keyfile, "vdagent-file-xfer", "size", file_size);
> +
> + g_free(basename);
> +
> + /* Save keyfile content to memory. TODO: more file attributions
> + need to be sent to guest */
> + string = g_key_file_to_data(keyfile, &data_len, &error);
> + g_key_file_free(keyfile);
> + if (error)
> + goto failed;
> +
> + /* Create file-xfer start message */
> + msg.id = spice_file_transfer_task_get_id(xfer_task);
> + agent_msg_queue_many(channel, VD_AGENT_FILE_XFER_START,
> + &msg, sizeof(msg),
> + string, data_len + 1, NULL);
> + g_free(string);
> + spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE);
> + return;
> +
> +failed:
> + spice_file_transfer_task_completed(xfer_task, error);
> +}
>
> static void task_finished(SpiceFileTransferTask *task,
> GError *error,
> @@ -3157,6 +3178,7 @@ void spice_main_file_copy_async(SpiceMainChannel
> *channel,
> guint32 task_id = spice_file_transfer_task_get_id(task);
>
> g_hash_table_insert(c->file_xfer_tasks, GUINT_TO_POINTER(task_id),
> task);
> + g_signal_connect(task, "file-info",
> G_CALLBACK(file_xfer_on_file_info), channel);
> g_signal_connect(task, "finished", G_CALLBACK(task_finished),
> channel);
> g_signal_emit(channel, signals[SPICE_MAIN_NEW_FILE_TRANSFER], 0,
> task);
> spice_file_transfer_task_start_task(task);
> @@ -3483,6 +3505,24 @@
> spice_file_transfer_task_class_init(SpiceFileTransferTaskClass *klass)
> G_PARAM_STATIC_STRING
> S));
>
> /**
> + * SpiceFileTransferTask::file-info
> + * @task: the file transfer task that emitted the signal
> + * @file_info: (transfer none): A GFileInfo object to retrieve file
> + * information. Only keys from standard namespace are supported.
> + *
> + * The #SpiceFileTransferTask::file-info signal is emitted just before
> the file
> + * transfer effectively starts.
> + *
> + * Since: 0.32
> + **/
> + task_signals[SIGNAL_FILE_INFO] = g_signal_new("file-info",
> SPICE_TYPE_FILE_TRANSFER_TASK,
> + G_SIGNAL_RUN_FIRST,
> + 0, NULL, NULL,
> + g_cclosure_marshal_VOID__BOXED,
> + G_TYPE_NONE, 1,
> + G_TYPE_FILE_INFO);
> +
> + /**
> * SpiceFileTransferTask::finished:
> * @task: the file transfer task that emitted the signal
> * @error: (transfer none): the error state of the transfer. Will be
> %NULL
More information about the Spice-devel
mailing list