Mercurial > projects > package-update-indicator
diff pui-get-updates.c @ 0:6884bb8130ca
Initial revision
author | Guido Berhoerster <guido+pui@berhoerster.name> |
---|---|
date | Sun, 20 May 2018 11:32:57 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pui-get-updates.c Sun May 20 11:32:57 2018 +0200 @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2018 Guido Berhoerster <guido+pui@berhoerster.name> + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "pui-get-updates.h" + +typedef struct { + PkControl *pk_control; + PkTask *pk_task; + guint refresh_interval; +} PuiGetUpdates; + +GQuark +pui_get_updates_error_quark(void) +{ + return (g_quark_from_static_string("pui-get-updates-error-quark")); +} + +static void +on_get_updates_finished(GObject *source_object, GAsyncResult *async_result, + gpointer user_data) +{ + GTask *task = user_data; + PuiGetUpdates *get_updates; + PkResults *results = NULL; + PkError *pk_error = NULL; + GError *error = NULL; + gint error_code; + GPtrArray *package_list; + + get_updates = g_task_get_task_data(task); + + g_debug("get updates transaction finished"); + results = pk_client_generic_finish(PK_CLIENT(get_updates->pk_task), + async_result, &error); + if (results == NULL) { + /* pass the error on */ + g_task_return_error(task, error); + goto out; + } + + pk_error = pk_results_get_error_code(results); + if (pk_error != NULL) { + /* transaction failed, return error */ + g_debug("failed to refresh the cache: %s", + pk_error_get_details(pk_error)); + if (pk_error_get_code(pk_error) == + PK_ERROR_ENUM_TRANSACTION_CANCELLED) { + error_code = PUI_GET_UPDATES_ERROR_CANCELLED; + } else { + error_code = + PUI_GET_UPDATES_ERROR_GET_UPDATES_FAILED; + } + error = g_error_new(PUI_GET_UPDATES_ERROR, error_code, + "Failed to get package updates: %s", + pk_error_get_details(pk_error)); + g_task_return_error(task, error); + g_object_unref(pk_error); + goto out; + } + + /* return results */ + package_list = pk_results_get_package_array(results); + g_assert(package_list != NULL); + g_task_return_pointer(task, package_list, + (GDestroyNotify)g_ptr_array_unref); + +out: + if (results != NULL) { + g_object_unref(results); + } + g_object_unref(task); +} + +static void +on_refresh_cache_finished(GObject *source_object, GAsyncResult *async_result, + gpointer user_data) +{ + GTask *task = user_data; + PuiGetUpdates *get_updates; + PkResults *results = NULL; + PkClient *pk_client; + GError *error = NULL; + PkError *pk_error = NULL; + gint error_code; + + get_updates = g_task_get_task_data(task); + pk_client = PK_CLIENT(get_updates->pk_task); + + g_debug("refresh cache transaction finished"); + results = pk_client_generic_finish(pk_client, async_result, &error); + if (results == NULL) { + g_task_return_error(task, error); + goto out; + } + + pk_error = pk_results_get_error_code(results); + if (pk_error != NULL) { + /* transaction failed, return error */ + g_debug("failed to refresh the cache: %s", + pk_error_get_details(pk_error)); + if (pk_error_get_code(pk_error) == + PK_ERROR_ENUM_TRANSACTION_CANCELLED) { + error_code = PUI_GET_UPDATES_ERROR_CANCELLED; + } else { + error_code = PUI_GET_UPDATES_ERROR_REFRESH_FAILED; + } + error = g_error_new(PUI_GET_UPDATES_ERROR, error_code, + "Failed to refresh the cache: %s", + pk_error_get_details(pk_error)); + g_task_return_error(task, error); + g_object_unref(pk_error); + goto out; + } + + /* cache is up to date, get updates */ + pk_client_get_updates_async(pk_client, + pk_bitfield_value(PK_FILTER_ENUM_NONE), + g_task_get_cancellable(task), NULL, NULL, on_get_updates_finished, + task); + +out: + if (results != NULL) { + g_object_unref(results); + } +} + +static void +on_get_time_since_refresh_finished(GObject *source_object, + GAsyncResult *async_result, gpointer user_data) +{ + GTask *task = user_data; + PuiGetUpdates *get_updates; + guint last_refresh; + GError *error = NULL; + PkClient *pk_client; + + get_updates = g_task_get_task_data(task); + pk_client = PK_CLIENT(get_updates->pk_task); + + last_refresh = + pk_control_get_time_since_action_finish(get_updates->pk_control, + async_result, &error); + if (last_refresh == 0) { + g_task_return_error(task, error); + g_object_unref(task); + return; + } + g_debug("time since last cache refresh: %us", last_refresh); + + if (last_refresh > get_updates->refresh_interval) { + /* cache is out of date, refresh first */ + g_debug("refreshing the cache"); + pk_client_refresh_cache_async(pk_client, FALSE, + g_task_get_cancellable(task), NULL, NULL, + on_refresh_cache_finished, task); + } else { + /* cache is up to date, get updates */ + g_debug("getting updates"); + pk_client_get_updates_async(pk_client, + pk_bitfield_value(PK_FILTER_ENUM_NONE), + g_task_get_cancellable(task), NULL, NULL, + on_get_updates_finished, task); + } +} + +static void +pui_get_updates_free(gpointer data) +{ + PuiGetUpdates *get_updates = data; + + g_object_unref(get_updates->pk_control); + g_object_unref(get_updates->pk_task); + g_slice_free(PuiGetUpdates, data); +} + +void +pui_get_updates_async(PkControl *pk_control, guint refresh_interval, + GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) +{ + PuiGetUpdates *get_updates; + GTask *task; + PkClient *pk_client; + + get_updates = g_slice_new0(PuiGetUpdates); + get_updates->pk_control = g_object_ref(pk_control); + get_updates->pk_task = pk_task_new(); + get_updates->refresh_interval = refresh_interval; + + pk_client = PK_CLIENT(get_updates->pk_task); + pk_client_set_cache_age(pk_client, refresh_interval); + pk_client_set_background(pk_client, TRUE); + + task = g_task_new(NULL, cancellable, callback, user_data); + g_task_set_task_data(task, get_updates, pui_get_updates_free); + + /* check whether to refresh the cache before checking for updates */ + g_debug("getting the time since the cache was last refreshed"); + pk_control_get_time_since_action_async(pk_control, + PK_ROLE_ENUM_REFRESH_CACHE, cancellable, + on_get_time_since_refresh_finished, task); +} + +GPtrArray * +pui_get_updates_finish(GAsyncResult *result, GError **errorp) +{ + return (g_task_propagate_pointer(G_TASK(result), errorp)); +}