From 4254c8305c1f7d48cf92eeff63434f1618542260 Mon Sep 17 00:00:00 2001 From: "Eduardo Lima (Etrunko)" Date: Tue, 17 Jan 2017 18:14:15 -0200 Subject: [PATCH 07/26] ovirt-foreign-menu: Fetch ISO names using GTask API Similar to the previous commit, the ISO dialog will fetch the result asynchronously, rather than relying on the "notify::files" signal from OvirtForeignMenu object. It also enables error to be shown if anything goes wrong. Signed-off-by: Eduardo Lima (Etrunko) --- src/ovirt-foreign-menu.c | 182 ++++++++++++++++++++++++++++------------------- src/ovirt-foreign-menu.h | 9 ++- src/remote-viewer.c | 45 ++++++++++-- 3 files changed, 156 insertions(+), 80 deletions(-) diff --git a/src/ovirt-foreign-menu.c b/src/ovirt-foreign-menu.c index a422ebb..8a99665 100644 --- a/src/ovirt-foreign-menu.c +++ b/src/ovirt-foreign-menu.c @@ -40,13 +40,13 @@ typedef enum { STATE_ISOS } OvirtForeignMenuState; -static void ovirt_foreign_menu_next_async_step(OvirtForeignMenu *menu, OvirtForeignMenuState state); -static void ovirt_foreign_menu_fetch_api_async(OvirtForeignMenu *menu); -static void ovirt_foreign_menu_fetch_vm_async(OvirtForeignMenu *menu); -static void ovirt_foreign_menu_fetch_storage_domain_async(OvirtForeignMenu *menu); -static void ovirt_foreign_menu_fetch_vm_cdrom_async(OvirtForeignMenu *menu); -static void ovirt_foreign_menu_refresh_cdrom_file_async(OvirtForeignMenu *menu); -static gboolean ovirt_foreign_menu_refresh_iso_list(gpointer user_data); +static void ovirt_foreign_menu_next_async_step(OvirtForeignMenu *menu, GTask *task, OvirtForeignMenuState state); +static void ovirt_foreign_menu_fetch_api_async(OvirtForeignMenu *menu, GTask *task); +static void ovirt_foreign_menu_fetch_vm_async(OvirtForeignMenu *menu, GTask *task); +static void ovirt_foreign_menu_fetch_storage_domain_async(OvirtForeignMenu *menu, GTask *task); +static void ovirt_foreign_menu_fetch_vm_cdrom_async(OvirtForeignMenu *menu, GTask *task); +static void ovirt_foreign_menu_refresh_cdrom_file_async(OvirtForeignMenu *menu, GTask *task); +static void ovirt_foreign_menu_fetch_iso_list_async(OvirtForeignMenu *menu, GTask *task); G_DEFINE_TYPE (OvirtForeignMenu, ovirt_foreign_menu, G_TYPE_OBJECT) @@ -273,11 +273,9 @@ OvirtForeignMenu* ovirt_foreign_menu_new(OvirtProxy *proxy) static void ovirt_foreign_menu_next_async_step(OvirtForeignMenu *menu, + GTask *task, OvirtForeignMenuState current_state) { - g_return_if_fail(current_state >= STATE_0); - g_return_if_fail(current_state < STATE_ISOS); - /* Each state will check if the member is initialized, falling directly to * the next one if so. If not, the callback for the asynchronous call will * be responsible for calling is function again with the next state as @@ -286,26 +284,26 @@ ovirt_foreign_menu_next_async_step(OvirtForeignMenu *menu, switch (current_state + 1) { case STATE_API: if (menu->priv->api == NULL) { - ovirt_foreign_menu_fetch_api_async(menu); + ovirt_foreign_menu_fetch_api_async(menu, task); break; } case STATE_VM: if (menu->priv->vm == NULL) { - ovirt_foreign_menu_fetch_vm_async(menu); + ovirt_foreign_menu_fetch_vm_async(menu, task); break; } case STATE_STORAGE_DOMAIN: if (menu->priv->files == NULL) { - ovirt_foreign_menu_fetch_storage_domain_async(menu); + ovirt_foreign_menu_fetch_storage_domain_async(menu, task); break; } case STATE_VM_CDROM: if (menu->priv->cdrom == NULL) { - ovirt_foreign_menu_fetch_vm_cdrom_async(menu); + ovirt_foreign_menu_fetch_vm_cdrom_async(menu, task); break; } case STATE_CDROM_FILE: - ovirt_foreign_menu_refresh_cdrom_file_async(menu); + ovirt_foreign_menu_refresh_cdrom_file_async(menu, task); break; case STATE_ISOS: g_warn_if_fail(menu->priv->api != NULL); @@ -313,18 +311,35 @@ ovirt_foreign_menu_next_async_step(OvirtForeignMenu *menu, g_warn_if_fail(menu->priv->files != NULL); g_warn_if_fail(menu->priv->cdrom != NULL); - ovirt_foreign_menu_refresh_iso_list(menu); + ovirt_foreign_menu_fetch_iso_list_async(menu, task); break; default: g_warn_if_reached(); + g_task_return_new_error(task, OVIRT_ERROR, OVIRT_ERROR_FAILED, + "Invalid state: %d", current_state); + g_object_unref(task); } } void -ovirt_foreign_menu_start(OvirtForeignMenu *menu) +ovirt_foreign_menu_fetch_iso_names_async(OvirtForeignMenu *menu, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GTask *task = g_task_new(menu, cancellable, callback, user_data); + ovirt_foreign_menu_next_async_step(menu, task, STATE_0); +} + + +GList * +ovirt_foreign_menu_fetch_iso_names_finish(OvirtForeignMenu *foreign_menu, + GAsyncResult *result, + GError **error) { - ovirt_foreign_menu_next_async_step(menu, STATE_0); + g_return_val_if_fail(OVIRT_IS_FOREIGN_MENU(foreign_menu), NULL); + return g_task_propagate_pointer(G_TASK(result), error); } @@ -545,7 +560,6 @@ static void ovirt_foreign_menu_set_files(OvirtForeignMenu *menu, g_list_free_full(menu->priv->iso_names, (GDestroyNotify)g_free); menu->priv->iso_names = sorted_files; - g_object_notify(G_OBJECT(menu), "files"); } @@ -553,14 +567,16 @@ static void cdrom_file_refreshed_cb(GObject *source_object, GAsyncResult *result, gpointer user_data) { + GTask *task = G_TASK(user_data); + OvirtForeignMenu *menu = OVIRT_FOREIGN_MENU(g_task_get_source_object(task)); OvirtResource *cdrom = OVIRT_RESOURCE(source_object); - OvirtForeignMenu *menu = OVIRT_FOREIGN_MENU(user_data); GError *error = NULL; ovirt_resource_refresh_finish(cdrom, result, &error); if (error != NULL) { g_warning("failed to refresh cdrom content: %s", error->message); - g_clear_error(&error); + g_task_return_error(task, error); + g_object_unref(task); return; } @@ -573,20 +589,24 @@ static void cdrom_file_refreshed_cb(GObject *source_object, } g_object_notify(G_OBJECT(menu), "file"); if (menu->priv->cdrom != NULL) { - ovirt_foreign_menu_next_async_step(menu, STATE_CDROM_FILE); + ovirt_foreign_menu_next_async_step(menu, task, STATE_CDROM_FILE); } else { g_debug("Could not find VM cdrom through oVirt REST API"); + g_task_return_new_error(task, OVIRT_ERROR, OVIRT_ERROR_FAILED, + "Could not find VM cdrom through oVirt REST API"); + g_object_unref(task); } } -static void ovirt_foreign_menu_refresh_cdrom_file_async(OvirtForeignMenu *menu) +static void ovirt_foreign_menu_refresh_cdrom_file_async(OvirtForeignMenu *menu, + GTask *task) { g_return_if_fail(OVIRT_IS_RESOURCE(menu->priv->cdrom)); ovirt_resource_refresh_async(OVIRT_RESOURCE(menu->priv->cdrom), - menu->priv->proxy, NULL, - cdrom_file_refreshed_cb, menu); + menu->priv->proxy, g_task_get_cancellable(task), + cdrom_file_refreshed_cb, task); } @@ -596,7 +616,8 @@ static void cdroms_fetched_cb(GObject *source_object, { GHashTable *cdroms; OvirtCollection *cdrom_collection = OVIRT_COLLECTION(source_object); - OvirtForeignMenu *menu = OVIRT_FOREIGN_MENU(user_data); + GTask *task = G_TASK(user_data); + OvirtForeignMenu *menu = OVIRT_FOREIGN_MENU(g_task_get_source_object(task)); GHashTableIter iter; OvirtCdrom *cdrom; GError *error = NULL; @@ -604,7 +625,8 @@ static void cdroms_fetched_cb(GObject *source_object, ovirt_collection_fetch_finish(cdrom_collection, result, &error); if (error != NULL) { g_warning("failed to fetch cdrom collection: %s", error->message); - g_clear_error(&error); + g_task_return_error(task, error); + g_object_unref(task); return; } @@ -626,20 +648,25 @@ static void cdroms_fetched_cb(GObject *source_object, } if (menu->priv->cdrom != NULL) { - ovirt_foreign_menu_next_async_step(menu, STATE_VM_CDROM); + ovirt_foreign_menu_next_async_step(menu, task, STATE_VM_CDROM); } else { g_debug("Could not find VM cdrom through oVirt REST API"); + g_task_return_new_error(task, OVIRT_ERROR, OVIRT_ERROR_FAILED, + "Could not find VM cdrom through oVirt REST API"); + g_object_unref(task); } } -static void ovirt_foreign_menu_fetch_vm_cdrom_async(OvirtForeignMenu *menu) +static void ovirt_foreign_menu_fetch_vm_cdrom_async(OvirtForeignMenu *menu, + GTask *task) { OvirtCollection *cdrom_collection; cdrom_collection = ovirt_vm_get_cdroms(menu->priv->vm); - ovirt_collection_fetch_async(cdrom_collection, menu->priv->proxy, NULL, - cdroms_fetched_cb, menu); + ovirt_collection_fetch_async(cdrom_collection, menu->priv->proxy, + g_task_get_cancellable(task), + cdroms_fetched_cb, task); } @@ -648,7 +675,8 @@ static void storage_domains_fetched_cb(GObject *source_object, gpointer user_data) { GError *error = NULL; - OvirtForeignMenu *menu = OVIRT_FOREIGN_MENU(user_data); + GTask *task = G_TASK(user_data); + OvirtForeignMenu *menu = OVIRT_FOREIGN_MENU(g_task_get_source_object(task)); OvirtCollection *collection = OVIRT_COLLECTION(source_object); GHashTableIter iter; OvirtStorageDomain *domain; @@ -656,7 +684,8 @@ static void storage_domains_fetched_cb(GObject *source_object, ovirt_collection_fetch_finish(collection, result, &error); if (error != NULL) { g_warning("failed to fetch storage domains: %s", error->message); - g_clear_error(&error); + g_task_return_error(task, error); + g_object_unref(task); return; } @@ -687,21 +716,25 @@ static void storage_domains_fetched_cb(GObject *source_object, } if (menu->priv->files != NULL) { - ovirt_foreign_menu_next_async_step(menu, STATE_STORAGE_DOMAIN); + ovirt_foreign_menu_next_async_step(menu, task, STATE_STORAGE_DOMAIN); } else { g_debug("Could not find iso file collection"); + g_task_return_new_error(task, OVIRT_ERROR, OVIRT_ERROR_FAILED, + "Could not find ISO file collection"); + g_object_unref(task); } } -static void ovirt_foreign_menu_fetch_storage_domain_async(OvirtForeignMenu *menu) +static void ovirt_foreign_menu_fetch_storage_domain_async(OvirtForeignMenu *menu, + GTask *task) { - OvirtCollection *collection; + OvirtCollection *collection = ovirt_api_get_storage_domains(menu->priv->api); g_debug("Start fetching oVirt REST collection"); - collection = ovirt_api_get_storage_domains(menu->priv->api); - ovirt_collection_fetch_async(collection, menu->priv->proxy, NULL, - storage_domains_fetched_cb, menu); + ovirt_collection_fetch_async(collection, menu->priv->proxy, + g_task_get_cancellable(task), + storage_domains_fetched_cb, task); } @@ -710,16 +743,17 @@ static void vms_fetched_cb(GObject *source_object, gpointer user_data) { GError *error = NULL; - OvirtForeignMenu *menu = OVIRT_FOREIGN_MENU(user_data); - OvirtCollection *collection; + GTask *task = G_TASK(user_data); + OvirtForeignMenu *menu = OVIRT_FOREIGN_MENU(g_task_get_source_object(task)); + OvirtCollection *collection = OVIRT_COLLECTION(source_object); GHashTableIter iter; OvirtVm *vm; - collection = OVIRT_COLLECTION(source_object); ovirt_collection_fetch_finish(collection, result, &error); if (error != NULL) { g_debug("failed to fetch VM list: %s", error->message); - g_clear_error(&error); + g_task_return_error(task, error); + g_object_unref(task); return; } @@ -736,14 +770,18 @@ static void vms_fetched_cb(GObject *source_object, g_free(guid); } if (menu->priv->vm != NULL) { - ovirt_foreign_menu_next_async_step(menu, STATE_VM); + ovirt_foreign_menu_next_async_step(menu, task, STATE_VM); } else { g_warning("failed to find a VM with guid \"%s\"", menu->priv->vm_guid); + g_task_return_new_error(task, OVIRT_ERROR, OVIRT_ERROR_FAILED, + "Could not find a VM with guid \"%s\"", menu->priv->vm_guid); + g_object_unref(task); } } -static void ovirt_foreign_menu_fetch_vm_async(OvirtForeignMenu *menu) +static void ovirt_foreign_menu_fetch_vm_async(OvirtForeignMenu *menu, + GTask *task) { OvirtCollection *vms; @@ -753,7 +791,8 @@ static void ovirt_foreign_menu_fetch_vm_async(OvirtForeignMenu *menu) vms = ovirt_api_get_vms(menu->priv->api); ovirt_collection_fetch_async(vms, menu->priv->proxy, - NULL, vms_fetched_cb, menu); + g_task_get_cancellable(task), + vms_fetched_cb, task); } @@ -762,31 +801,35 @@ static void api_fetched_cb(GObject *source_object, gpointer user_data) { GError *error = NULL; - OvirtProxy *proxy; - OvirtForeignMenu *menu = OVIRT_FOREIGN_MENU(user_data); + GTask *task = G_TASK(user_data); + OvirtForeignMenu *menu = OVIRT_FOREIGN_MENU(g_task_get_source_object(task)); + OvirtProxy *proxy = OVIRT_PROXY(source_object); - proxy = OVIRT_PROXY(source_object); menu->priv->api = ovirt_proxy_fetch_api_finish(proxy, result, &error); if (error != NULL) { g_debug("failed to fetch toplevel API object: %s", error->message); - g_clear_error(&error); + g_task_return_error(task, error); + g_object_unref(task); return; } g_return_if_fail(OVIRT_IS_API(menu->priv->api)); g_object_ref(menu->priv->api); - ovirt_foreign_menu_next_async_step(menu, STATE_API); + ovirt_foreign_menu_next_async_step(menu, task, STATE_API); } -static void ovirt_foreign_menu_fetch_api_async(OvirtForeignMenu *menu) +static void ovirt_foreign_menu_fetch_api_async(OvirtForeignMenu *menu, + GTask *task) { g_debug("Start fetching oVirt main entry point"); g_return_if_fail(OVIRT_IS_FOREIGN_MENU(menu)); g_return_if_fail(OVIRT_IS_PROXY(menu->priv->proxy)); - ovirt_proxy_fetch_api_async(menu->priv->proxy, NULL, api_fetched_cb, menu); + ovirt_proxy_fetch_api_async(menu->priv->proxy, + g_task_get_cancellable(task), + api_fetched_cb, task); } @@ -794,6 +837,8 @@ static void iso_list_fetched_cb(GObject *source_object, GAsyncResult *result, gpointer user_data) { + GTask *task = G_TASK(user_data); + OvirtForeignMenu *menu = OVIRT_FOREIGN_MENU(g_task_get_source_object(task)); OvirtCollection *collection = OVIRT_COLLECTION(source_object); GError *error = NULL; GList *files; @@ -802,42 +847,29 @@ static void iso_list_fetched_cb(GObject *source_object, if (error != NULL) { g_warning("failed to fetch files for ISO storage domain: %s", error->message); - g_clear_error(&error); + g_task_return_error(task, error); + g_object_unref(task); return; } files = g_hash_table_get_values(ovirt_collection_get_resources(collection)); - ovirt_foreign_menu_set_files(OVIRT_FOREIGN_MENU(user_data), files); + ovirt_foreign_menu_set_files(menu, files); g_list_free(files); - - g_timeout_add_seconds(300, ovirt_foreign_menu_refresh_iso_list, user_data); + g_task_return_pointer(task, menu->priv->iso_names, NULL); + g_object_unref(task); } -static void ovirt_foreign_menu_fetch_iso_list_async(OvirtForeignMenu *menu) +static void ovirt_foreign_menu_fetch_iso_list_async(OvirtForeignMenu *menu, + GTask *task) { if (menu->priv->files == NULL) { return; } ovirt_collection_fetch_async(menu->priv->files, menu->priv->proxy, - NULL, iso_list_fetched_cb, menu); -} - - -static gboolean ovirt_foreign_menu_refresh_iso_list(gpointer user_data) -{ - OvirtForeignMenu *menu; - - g_debug("Refreshing foreign menu iso list"); - menu = OVIRT_FOREIGN_MENU(user_data); - ovirt_foreign_menu_fetch_iso_list_async(menu); - - /* ovirt_foreign_menu_fetch_iso_list_async() will schedule a new call to - * that function through iso_list_fetched_cb() when it has finished - * fetching the iso list - */ - return G_SOURCE_REMOVE; + g_task_get_cancellable(task), + iso_list_fetched_cb, task); } diff --git a/src/ovirt-foreign-menu.h b/src/ovirt-foreign-menu.h index 791d0f3..a864a60 100644 --- a/src/ovirt-foreign-menu.h +++ b/src/ovirt-foreign-menu.h @@ -68,7 +68,14 @@ GType ovirt_foreign_menu_get_type(void); OvirtForeignMenu* ovirt_foreign_menu_new(OvirtProxy *proxy); OvirtForeignMenu *ovirt_foreign_menu_new_from_file(VirtViewerFile *self); -void ovirt_foreign_menu_start(OvirtForeignMenu *menu); + +void ovirt_foreign_menu_fetch_iso_names_async(OvirtForeignMenu *menu, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GList *ovirt_foreign_menu_fetch_iso_names_finish(OvirtForeignMenu *foreign_menu, + GAsyncResult *result, + GError **error); void ovirt_foreign_menu_set_current_iso_name_async(OvirtForeignMenu *foreign_menu, const char *name, diff --git a/src/remote-viewer.c b/src/remote-viewer.c index 13c6e7c..c84a35b 100644 --- a/src/remote-viewer.c +++ b/src/remote-viewer.c @@ -72,6 +72,7 @@ static OvirtVm * choose_vm(GtkWindow *main_window, char **vm_name, OvirtCollection *vms, GError **error); +static gboolean remote_viewer_refresh_ovirt_foreign_menu(gpointer user_data); #endif static gboolean remote_viewer_start(VirtViewerApp *self, GError **error); @@ -783,6 +784,43 @@ ovirt_foreign_menu_updated(RemoteViewer *self) } static void +ovirt_foreign_menu_fetch_iso_names_cb(GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + OvirtForeignMenu *foreign_menu = OVIRT_FOREIGN_MENU(source_object); + RemoteViewer *self = REMOTE_VIEWER(user_data); + VirtViewerApp *app = VIRT_VIEWER_APP(user_data); + GError *error = NULL; + GList *iso_list; + + iso_list = ovirt_foreign_menu_fetch_iso_names_finish(foreign_menu, result, &error); + + if (!iso_list) { + virt_viewer_app_simple_message_dialog(app, error ? error->message : _("Failed to fetch CD names")); + g_clear_error(&error); + return; + } + + ovirt_foreign_menu_updated(self); + g_timeout_add_seconds(300, remote_viewer_refresh_ovirt_foreign_menu, self); +} + +static gboolean +remote_viewer_refresh_ovirt_foreign_menu(gpointer user_data) +{ + VirtViewerApp *app = VIRT_VIEWER_APP(user_data); + RemoteViewer *self = REMOTE_VIEWER(user_data); + + g_debug("Refreshing foreign menu iso list"); + ovirt_foreign_menu_fetch_iso_names_async(self->priv->ovirt_foreign_menu, + NULL, + ovirt_foreign_menu_fetch_iso_names_cb, + app); + return G_SOURCE_REMOVE; +} + +static void ovirt_foreign_menu_changed(OvirtForeignMenu *foreign_menu G_GNUC_UNUSED, GParamSpec *pspec G_GNUC_UNUSED, VirtViewerApp *app) @@ -806,13 +844,12 @@ virt_viewer_app_set_ovirt_foreign_menu(VirtViewerApp *app, self->priv->ovirt_foreign_menu = foreign_menu; g_signal_connect(G_OBJECT(foreign_menu), "notify::file", (GCallback)ovirt_foreign_menu_changed, app); - g_signal_connect(G_OBJECT(foreign_menu), "notify::files", - (GCallback)ovirt_foreign_menu_changed, app); + g_signal_connect(G_OBJECT(app), "window-added", (GCallback)ovirt_foreign_menu_update, NULL); - ovirt_foreign_menu_start(foreign_menu); -} + remote_viewer_refresh_ovirt_foreign_menu(self); +} static gboolean create_ovirt_session(VirtViewerApp *app, const char *uri, GError **err) -- 2.12.0