[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