[Spice-devel] [spice-gtk v5 04/23] file-xfer: introduce functions to init task async
Victor Toso
victortoso at redhat.com
Tue Jul 5 13:07:11 UTC 2016
Introduced functions (private):
* void spice_file_transfer_task_init_task_async()
* GFileInfo *spice_file_transfer_task_init_task_finish()
The init process of SpiceFileTransferTask does initialize its
GFileInputStream (for reading the file) and also its GFileInfo
(necessary to protocol in order to start the file-transfer with agent)
Due the logic changed involved, some functions were renamed to better
match its place and purpose:
* file_xfer_info_async_cb -> file_xfer_init_task_async_cb
It is channel-main's callback for each _init_task_async()
* file_xfer_read_async_cb -> spice_file_transfer_task_read_file_cb
* file_xfer_info_async_cb -> spice_file_transfer_task_query_info_cb
Both should be private to SpiceFileTransferTask now.
As the _init_task_async() uses GTask, some error handling was moved to
channel-main's after _init_task_finish() is called.
This change is related to split SpiceFileTransferTask from
channel-main.
Acked-by: Jonathon Jongsma <jjongsma at redhat.com>
---
src/channel-main.c | 184 +++++++++++++++++++++++++++++++++++++----------------
1 file changed, 130 insertions(+), 54 deletions(-)
diff --git a/src/channel-main.c b/src/channel-main.c
index d85e27f..d721852 100644
--- a/src/channel-main.c
+++ b/src/channel-main.c
@@ -65,6 +65,12 @@ static GHashTable *spice_file_transfer_task_create_tasks(GFile **files,
gpointer progress_callback_data,
GAsyncReadyCallback callback,
gpointer user_data);
+static void spice_file_transfer_task_init_task_async(SpiceFileTransferTask *self,
+ GAsyncReadyCallback callback,
+ gpointer userdata);
+static GFileInfo *spice_file_transfer_task_init_task_finish(SpiceFileTransferTask *xfer_task,
+ GAsyncResult *result,
+ GError **error);
/**
* SECTION:file-transfer-task
@@ -3024,34 +3030,32 @@ signal:
}
-static void file_xfer_info_async_cb(GObject *obj, GAsyncResult *res, gpointer data)
+static void file_xfer_init_task_async_cb(GObject *obj, GAsyncResult *res, gpointer data)
{
GFileInfo *info;
- GFile *file = G_FILE(obj);
- GError *error = NULL;
- GKeyFile *keyfile = NULL;
- gchar *basename = NULL;
+ SpiceFileTransferTask *xfer_task;
+ SpiceMainChannel *channel;
+ gchar *string, *basename;
+ GKeyFile *keyfile;
VDAgentFileXferStartMessage msg;
- gsize /*msg_size*/ data_len;
- gchar *string;
- SpiceFileTransferTask *self = SPICE_FILE_TRANSFER_TASK(data);
+ guint64 file_size;
+ gsize data_len;
+ GError *error = NULL;
- self->pending = FALSE;
- info = g_file_query_info_finish(file, res, &error);
- if (error || self->error)
+ xfer_task = SPICE_FILE_TRANSFER_TASK(obj);
+
+ info = spice_file_transfer_task_init_task_finish(xfer_task, res, &error);
+ if (info == NULL)
goto failed;
- self->file_size =
- g_file_info_get_attribute_uint64(info, G_FILE_ATTRIBUTE_STANDARD_SIZE);
- g_object_notify(G_OBJECT(self), "progress");
- keyfile = g_key_file_new();
+ channel = spice_file_transfer_task_get_channel(xfer_task);
+ 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);
- /* File name */
- basename = g_file_get_basename(file);
+ 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);
- /* 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 */
@@ -3061,39 +3065,18 @@ static void file_xfer_info_async_cb(GObject *obj, GAsyncResult *res, gpointer da
goto failed;
/* Create file-xfer start message */
- msg.id = self->id;
- agent_msg_queue_many(self->channel, VD_AGENT_FILE_XFER_START,
+ 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(self->channel), FALSE);
+ spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE);
+ g_object_unref(info);
return;
failed:
- spice_file_transfer_task_completed(self, error);
-}
-
-static void file_xfer_read_async_cb(GObject *obj, GAsyncResult *res, gpointer data)
-{
- GFile *file = G_FILE(obj);
- SpiceFileTransferTask *self = SPICE_FILE_TRANSFER_TASK(data);
- GError *error = NULL;
-
- self->pending = FALSE;
- self->file_stream = g_file_read_finish(file, res, &error);
- if (error || self->error) {
- spice_file_transfer_task_completed(self, error);
- return;
- }
-
- g_file_query_info_async(self->file,
- G_FILE_ATTRIBUTE_STANDARD_SIZE,
- G_FILE_QUERY_INFO_NONE,
- G_PRIORITY_DEFAULT,
- self->cancellable,
- file_xfer_info_async_cb,
- self);
- self->pending = TRUE;
+ g_clear_object(&info);
+ spice_file_transfer_task_completed(xfer_task, error);
}
static SpiceFileTransferTask *spice_file_transfer_task_new(SpiceMainChannel *channel,
@@ -3182,11 +3165,9 @@ void spice_main_file_copy_async(SpiceMainChannel *channel,
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 = value;
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);
@@ -3194,12 +3175,9 @@ void spice_main_file_copy_async(SpiceMainChannel *channel,
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;
+ spice_file_transfer_task_init_task_async(xfer_task,
+ file_xfer_init_task_async_cb,
+ NULL);
}
g_hash_table_unref(xfer_ht);
}
@@ -3294,6 +3272,104 @@ static GHashTable *spice_file_transfer_task_create_tasks(GFile **files,
return xfer_ht;
}
+static void spice_file_transfer_task_query_info_cb(GObject *obj,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ SpiceFileTransferTask *self;
+ GFileInfo *info;
+ GTask *task;
+ GError *error = NULL;
+
+ task = G_TASK(user_data);
+ self = g_task_get_source_object(task);
+
+ g_return_if_fail(self->pending == TRUE);
+ self->pending = FALSE;
+
+ info = g_file_query_info_finish(G_FILE(obj), res, &error);
+ if (self->error) {
+ /* Return error previously reported */
+ g_task_return_error(task, self->error);
+ return;
+ } else if (error) {
+ g_task_return_error(task, error);
+ return;
+ }
+
+ self->file_size =
+ g_file_info_get_attribute_uint64(info, G_FILE_ATTRIBUTE_STANDARD_SIZE);
+
+ /* SpiceFileTransferTask's init is done, handshake for file-trasfer will
+ * start soon. First "progress" can be emitted ~ 0% */
+ g_object_notify(G_OBJECT(self), "progress");
+
+ g_task_return_pointer(task, info, g_object_unref);
+}
+
+static void spice_file_transfer_task_read_file_cb(GObject *obj,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ SpiceFileTransferTask *self;
+ GTask *task;
+ GError *error = NULL;
+
+ task = G_TASK(user_data);
+ self = g_task_get_source_object(task);
+
+ g_return_if_fail(self->pending == TRUE);
+
+ self->file_stream = g_file_read_finish(G_FILE(obj), res, &error);
+ if (self->error) {
+ /* Return error previously reported */
+ self->pending = FALSE;
+ g_task_return_error(task, self->error);
+ return;
+ } else if (error) {
+ self->pending = FALSE;
+ g_task_return_error(task, error);
+ return;
+ }
+
+ g_file_query_info_async(self->file,
+ "standard::*",
+ G_FILE_QUERY_INFO_NONE,
+ G_PRIORITY_DEFAULT,
+ self->cancellable,
+ spice_file_transfer_task_query_info_cb,
+ task);
+}
+
+static void spice_file_transfer_task_init_task_async(SpiceFileTransferTask *self,
+ GAsyncReadyCallback callback,
+ gpointer userdata)
+{
+ GTask *task;
+
+ g_return_if_fail(self != NULL);
+ g_return_if_fail(self->pending == FALSE);
+
+ task = g_task_new(self, self->cancellable, callback, userdata);
+
+ self->pending = TRUE;
+ g_file_read_async(self->file,
+ G_PRIORITY_DEFAULT,
+ self->cancellable,
+ spice_file_transfer_task_read_file_cb,
+ task);
+}
+
+static GFileInfo *spice_file_transfer_task_init_task_finish(SpiceFileTransferTask *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ GTask *task = G_TASK(result);
+
+ g_return_val_if_fail(self != NULL, NULL);
+ return g_task_propagate_pointer(task, error);
+}
+
static void
spice_file_transfer_task_get_property(GObject *object,
guint property_id,
--
2.7.4
More information about the Spice-devel
mailing list