summaryrefslogtreecommitdiffstats
path: root/lib/gs-plugin-job.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gs-plugin-job.c')
-rw-r--r--lib/gs-plugin-job.c618
1 files changed, 618 insertions, 0 deletions
diff --git a/lib/gs-plugin-job.c b/lib/gs-plugin-job.c
new file mode 100644
index 0000000..1ce320f
--- /dev/null
+++ b/lib/gs-plugin-job.c
@@ -0,0 +1,618 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2017-2018 Richard Hughes <richard@hughsie.com>
+ * Copyright (C) 2018 Kalev Lember <klember@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "config.h"
+
+#include <glib.h>
+
+#include "gs-plugin-private.h"
+#include "gs-plugin-job-private.h"
+
+struct _GsPluginJob
+{
+ GObject parent_instance;
+ GsPluginRefineFlags refine_flags;
+ GsPluginRefineFlags filter_flags;
+ GsAppListFilterFlags dedupe_flags;
+ gboolean interactive;
+ guint max_results;
+ guint timeout;
+ guint64 age;
+ GsPlugin *plugin;
+ GsPluginAction action;
+ GsAppListSortFunc sort_func;
+ gpointer sort_func_data;
+ gchar *search;
+ GsApp *app;
+ GsAppList *list;
+ GFile *file;
+ GsCategory *category;
+ AsReview *review;
+ gint64 time_created;
+};
+
+enum {
+ PROP_0,
+ PROP_ACTION,
+ PROP_AGE,
+ PROP_SEARCH,
+ PROP_REFINE_FLAGS,
+ PROP_FILTER_FLAGS,
+ PROP_DEDUPE_FLAGS,
+ PROP_INTERACTIVE,
+ PROP_APP,
+ PROP_LIST,
+ PROP_FILE,
+ PROP_CATEGORY,
+ PROP_REVIEW,
+ PROP_MAX_RESULTS,
+ PROP_TIMEOUT,
+ PROP_LAST
+};
+
+G_DEFINE_TYPE (GsPluginJob, gs_plugin_job, G_TYPE_OBJECT)
+
+gchar *
+gs_plugin_job_to_string (GsPluginJob *self)
+{
+ GString *str = g_string_new (NULL);
+ gint64 time_now = g_get_monotonic_time ();
+ g_string_append_printf (str, "running %s",
+ gs_plugin_action_to_string (self->action));
+ if (self->plugin != NULL) {
+ g_string_append_printf (str, " on plugin=%s",
+ gs_plugin_get_name (self->plugin));
+ }
+ if (self->filter_flags > 0) {
+ g_autofree gchar *tmp = gs_plugin_refine_flags_to_string (self->filter_flags);
+ g_string_append_printf (str, " with filter-flags=%s", tmp);
+ }
+ if (self->dedupe_flags > 0)
+ g_string_append_printf (str, " with dedupe-flags=%" G_GUINT64_FORMAT, self->dedupe_flags);
+ if (self->refine_flags > 0) {
+ g_autofree gchar *tmp = gs_plugin_refine_flags_to_string (self->refine_flags);
+ g_string_append_printf (str, " with refine-flags=%s", tmp);
+ }
+ if (self->interactive)
+ g_string_append_printf (str, " with interactive=True");
+ if (self->timeout > 0)
+ g_string_append_printf (str, " with timeout=%u", self->timeout);
+ if (self->max_results > 0)
+ g_string_append_printf (str, " with max-results=%u", self->max_results);
+ if (self->age != 0) {
+ if (self->age == G_MAXUINT) {
+ g_string_append (str, " with cache age=any");
+ } else {
+ g_string_append_printf (str, " with cache age=%" G_GUINT64_FORMAT,
+ self->age);
+ }
+ }
+ if (self->search != NULL) {
+ g_string_append_printf (str, " with search=%s",
+ self->search);
+ }
+ if (self->category != NULL) {
+ GsCategory *parent = gs_category_get_parent (self->category);
+ if (parent != NULL) {
+ g_string_append_printf (str, " with category=%s/%s",
+ gs_category_get_id (parent),
+ gs_category_get_id (self->category));
+ } else {
+ g_string_append_printf (str, " with category=%s",
+ gs_category_get_id (self->category));
+ }
+ }
+ if (self->review != NULL) {
+ g_string_append_printf (str, " with review=%s",
+ as_review_get_id (self->review));
+ }
+ if (self->file != NULL) {
+ g_autofree gchar *path = g_file_get_path (self->file);
+ g_string_append_printf (str, " with file=%s", path);
+ }
+ if (self->list != NULL && gs_app_list_length (self->list) > 0) {
+ g_autofree const gchar **unique_ids = NULL;
+ g_autofree gchar *unique_ids_str = NULL;
+ unique_ids = g_new0 (const gchar *, gs_app_list_length (self->list) + 1);
+ for (guint i = 0; i < gs_app_list_length (self->list); i++) {
+ GsApp *app = gs_app_list_index (self->list, i);
+ unique_ids[i] = gs_app_get_unique_id (app);
+ }
+ unique_ids_str = g_strjoinv (",", (gchar**) unique_ids);
+ g_string_append_printf (str, " on apps %s", unique_ids_str);
+ }
+ if (time_now - self->time_created > 1000) {
+ g_string_append_printf (str, ", elapsed time since creation %" G_GINT64_FORMAT "ms",
+ (time_now - self->time_created) / 1000);
+ }
+ return g_string_free (str, FALSE);
+}
+
+void
+gs_plugin_job_set_refine_flags (GsPluginJob *self, GsPluginRefineFlags refine_flags)
+{
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ self->refine_flags = refine_flags;
+}
+
+void
+gs_plugin_job_set_filter_flags (GsPluginJob *self, GsPluginRefineFlags filter_flags)
+{
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ self->filter_flags = filter_flags;
+}
+
+void
+gs_plugin_job_set_dedupe_flags (GsPluginJob *self, GsAppListFilterFlags dedupe_flags)
+{
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ self->dedupe_flags = dedupe_flags;
+}
+
+GsPluginRefineFlags
+gs_plugin_job_get_refine_flags (GsPluginJob *self)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), 0);
+ return self->refine_flags;
+}
+
+GsPluginRefineFlags
+gs_plugin_job_get_filter_flags (GsPluginJob *self)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), 0);
+ return self->filter_flags;
+}
+
+GsAppListFilterFlags
+gs_plugin_job_get_dedupe_flags (GsPluginJob *self)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), 0);
+ return self->dedupe_flags;
+}
+
+gboolean
+gs_plugin_job_has_refine_flags (GsPluginJob *self, GsPluginRefineFlags refine_flags)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), FALSE);
+ return (self->refine_flags & refine_flags) > 0;
+}
+
+void
+gs_plugin_job_add_refine_flags (GsPluginJob *self, GsPluginRefineFlags refine_flags)
+{
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ self->refine_flags |= refine_flags;
+}
+
+void
+gs_plugin_job_remove_refine_flags (GsPluginJob *self, GsPluginRefineFlags refine_flags)
+{
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ self->refine_flags &= ~refine_flags;
+}
+
+void
+gs_plugin_job_set_interactive (GsPluginJob *self, gboolean interactive)
+{
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ self->interactive = interactive;
+}
+
+gboolean
+gs_plugin_job_get_interactive (GsPluginJob *self)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), FALSE);
+ return self->interactive;
+}
+
+void
+gs_plugin_job_set_max_results (GsPluginJob *self, guint max_results)
+{
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ self->max_results = max_results;
+}
+
+guint
+gs_plugin_job_get_max_results (GsPluginJob *self)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), 0);
+ return self->max_results;
+}
+
+void
+gs_plugin_job_set_timeout (GsPluginJob *self, guint timeout)
+{
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ self->timeout = timeout;
+}
+
+guint
+gs_plugin_job_get_timeout (GsPluginJob *self)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), 0);
+ return self->timeout;
+}
+
+void
+gs_plugin_job_set_age (GsPluginJob *self, guint64 age)
+{
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ self->age = age;
+}
+
+guint64
+gs_plugin_job_get_age (GsPluginJob *self)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), 0);
+ return self->age;
+}
+
+void
+gs_plugin_job_set_action (GsPluginJob *self, GsPluginAction action)
+{
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ self->action = action;
+}
+
+GsPluginAction
+gs_plugin_job_get_action (GsPluginJob *self)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), 0);
+ return self->action;
+}
+
+void
+gs_plugin_job_set_sort_func (GsPluginJob *self, GsAppListSortFunc sort_func)
+{
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ self->sort_func = sort_func;
+}
+
+GsAppListSortFunc
+gs_plugin_job_get_sort_func (GsPluginJob *self)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), 0);
+ return self->sort_func;
+}
+
+void
+gs_plugin_job_set_sort_func_data (GsPluginJob *self, gpointer sort_func_data)
+{
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ self->sort_func_data = sort_func_data;
+}
+
+gpointer
+gs_plugin_job_get_sort_func_data (GsPluginJob *self)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), NULL);
+ return self->sort_func_data;
+}
+
+void
+gs_plugin_job_set_search (GsPluginJob *self, const gchar *search)
+{
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ g_free (self->search);
+ self->search = g_strdup (search);
+}
+
+const gchar *
+gs_plugin_job_get_search (GsPluginJob *self)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), NULL);
+ return self->search;
+}
+
+void
+gs_plugin_job_set_app (GsPluginJob *self, GsApp *app)
+{
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ g_set_object (&self->app, app);
+
+ /* ensure we can always operate on a list object */
+ if (self->list != NULL && app != NULL && gs_app_list_length (self->list) == 0)
+ gs_app_list_add (self->list, self->app);
+}
+
+GsApp *
+gs_plugin_job_get_app (GsPluginJob *self)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), NULL);
+ return self->app;
+}
+
+void
+gs_plugin_job_set_list (GsPluginJob *self, GsAppList *list)
+{
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ if (list == NULL)
+ g_warning ("trying to set list to NULL, not a good idea");
+ g_set_object (&self->list, list);
+}
+
+GsAppList *
+gs_plugin_job_get_list (GsPluginJob *self)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), NULL);
+ return self->list;
+}
+
+void
+gs_plugin_job_set_file (GsPluginJob *self, GFile *file)
+{
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ g_set_object (&self->file, file);
+}
+
+GFile *
+gs_plugin_job_get_file (GsPluginJob *self)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), NULL);
+ return self->file;
+}
+
+void
+gs_plugin_job_set_plugin (GsPluginJob *self, GsPlugin *plugin)
+{
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ g_set_object (&self->plugin, plugin);
+}
+
+GsPlugin *
+gs_plugin_job_get_plugin (GsPluginJob *self)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), NULL);
+ return self->plugin;
+}
+
+void
+gs_plugin_job_set_category (GsPluginJob *self, GsCategory *category)
+{
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ g_set_object (&self->category, category);
+}
+
+GsCategory *
+gs_plugin_job_get_category (GsPluginJob *self)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), NULL);
+ return self->category;
+}
+
+void
+gs_plugin_job_set_review (GsPluginJob *self, AsReview *review)
+{
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ g_set_object (&self->review, review);
+}
+
+AsReview *
+gs_plugin_job_get_review (GsPluginJob *self)
+{
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), NULL);
+ return self->review;
+}
+
+static void
+gs_plugin_job_get_property (GObject *obj, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GsPluginJob *self = GS_PLUGIN_JOB (obj);
+
+ switch (prop_id) {
+ case PROP_ACTION:
+ g_value_set_uint (value, self->action);
+ break;
+ case PROP_AGE:
+ g_value_set_uint64 (value, self->age);
+ break;
+ case PROP_REFINE_FLAGS:
+ g_value_set_uint64 (value, self->refine_flags);
+ break;
+ case PROP_FILTER_FLAGS:
+ g_value_set_uint64 (value, self->filter_flags);
+ break;
+ case PROP_DEDUPE_FLAGS:
+ g_value_set_uint64 (value, self->dedupe_flags);
+ break;
+ case PROP_INTERACTIVE:
+ g_value_set_boolean (value, self->interactive);
+ break;
+ case PROP_SEARCH:
+ g_value_set_string (value, self->search);
+ break;
+ case PROP_APP:
+ g_value_set_object (value, self->app);
+ break;
+ case PROP_LIST:
+ g_value_set_object (value, self->list);
+ break;
+ case PROP_FILE:
+ g_value_set_object (value, self->file);
+ break;
+ case PROP_CATEGORY:
+ g_value_set_object (value, self->category);
+ break;
+ case PROP_REVIEW:
+ g_value_set_object (value, self->review);
+ break;
+ case PROP_MAX_RESULTS:
+ g_value_set_uint (value, self->max_results);
+ break;
+ case PROP_TIMEOUT:
+ g_value_set_uint (value, self->timeout);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gs_plugin_job_set_property (GObject *obj, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ GsPluginJob *self = GS_PLUGIN_JOB (obj);
+
+ switch (prop_id) {
+ case PROP_ACTION:
+ gs_plugin_job_set_action (self, g_value_get_uint (value));
+ break;
+ case PROP_AGE:
+ gs_plugin_job_set_age (self, g_value_get_uint64 (value));
+ break;
+ case PROP_REFINE_FLAGS:
+ gs_plugin_job_set_refine_flags (self, g_value_get_uint64 (value));
+ break;
+ case PROP_FILTER_FLAGS:
+ gs_plugin_job_set_filter_flags (self, g_value_get_uint64 (value));
+ break;
+ case PROP_DEDUPE_FLAGS:
+ gs_plugin_job_set_dedupe_flags (self, g_value_get_uint64 (value));
+ break;
+ case PROP_INTERACTIVE:
+ gs_plugin_job_set_interactive (self, g_value_get_boolean (value));
+ break;
+ case PROP_SEARCH:
+ gs_plugin_job_set_search (self, g_value_get_string (value));
+ break;
+ case PROP_APP:
+ gs_plugin_job_set_app (self, g_value_get_object (value));
+ break;
+ case PROP_LIST:
+ gs_plugin_job_set_list (self, g_value_get_object (value));
+ break;
+ case PROP_FILE:
+ gs_plugin_job_set_file (self, g_value_get_object (value));
+ break;
+ case PROP_CATEGORY:
+ gs_plugin_job_set_category (self, g_value_get_object (value));
+ break;
+ case PROP_REVIEW:
+ gs_plugin_job_set_review (self, g_value_get_object (value));
+ break;
+ case PROP_MAX_RESULTS:
+ gs_plugin_job_set_max_results (self, g_value_get_uint (value));
+ break;
+ case PROP_TIMEOUT:
+ gs_plugin_job_set_timeout (self, g_value_get_uint (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gs_plugin_job_finalize (GObject *obj)
+{
+ GsPluginJob *self = GS_PLUGIN_JOB (obj);
+ g_free (self->search);
+ g_clear_object (&self->app);
+ g_clear_object (&self->list);
+ g_clear_object (&self->file);
+ g_clear_object (&self->plugin);
+ g_clear_object (&self->category);
+ g_clear_object (&self->review);
+ G_OBJECT_CLASS (gs_plugin_job_parent_class)->finalize (obj);
+}
+
+static void
+gs_plugin_job_class_init (GsPluginJobClass *klass)
+{
+ GParamSpec *pspec;
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = gs_plugin_job_finalize;
+ object_class->get_property = gs_plugin_job_get_property;
+ object_class->set_property = gs_plugin_job_set_property;
+
+ pspec = g_param_spec_uint ("action", NULL, NULL,
+ GS_PLUGIN_ACTION_UNKNOWN,
+ GS_PLUGIN_ACTION_LAST,
+ GS_PLUGIN_ACTION_UNKNOWN,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_ACTION, pspec);
+
+ pspec = g_param_spec_uint64 ("age", NULL, NULL,
+ 0, G_MAXUINT64, 0,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_AGE, pspec);
+
+ pspec = g_param_spec_uint64 ("refine-flags", NULL, NULL,
+ 0, G_MAXUINT64, 0,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_REFINE_FLAGS, pspec);
+
+ pspec = g_param_spec_uint64 ("filter-flags", NULL, NULL,
+ 0, G_MAXUINT64, 0,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_FILTER_FLAGS, pspec);
+
+ pspec = g_param_spec_uint64 ("dedupe-flags", NULL, NULL,
+ 0, G_MAXUINT64, 0,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_DEDUPE_FLAGS, pspec);
+
+ pspec = g_param_spec_boolean ("interactive", NULL, NULL,
+ FALSE,
+ G_PARAM_READWRITE);
+
+ g_object_class_install_property (object_class, PROP_INTERACTIVE, pspec);
+
+ pspec = g_param_spec_string ("search", NULL, NULL,
+ NULL,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_SEARCH, pspec);
+
+ pspec = g_param_spec_object ("app", NULL, NULL,
+ GS_TYPE_APP,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_APP, pspec);
+
+ pspec = g_param_spec_object ("list", NULL, NULL,
+ GS_TYPE_APP_LIST,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_LIST, pspec);
+
+ pspec = g_param_spec_object ("file", NULL, NULL,
+ G_TYPE_FILE,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_FILE, pspec);
+
+ pspec = g_param_spec_object ("category", NULL, NULL,
+ GS_TYPE_CATEGORY,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_CATEGORY, pspec);
+
+ pspec = g_param_spec_object ("review", NULL, NULL,
+ AS_TYPE_REVIEW,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_REVIEW, pspec);
+
+ pspec = g_param_spec_uint ("max-results", NULL, NULL,
+ 0, G_MAXUINT, 0,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_MAX_RESULTS, pspec);
+
+ pspec = g_param_spec_uint ("timeout", NULL, NULL,
+ 0, G_MAXUINT, 60,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
+ g_object_class_install_property (object_class, PROP_TIMEOUT, pspec);
+}
+
+static void
+gs_plugin_job_init (GsPluginJob *self)
+{
+ self->refine_flags = GS_PLUGIN_REFINE_FLAGS_DEFAULT;
+ self->filter_flags = GS_PLUGIN_REFINE_FLAGS_DEFAULT;
+ self->dedupe_flags = GS_APP_LIST_FILTER_FLAG_KEY_ID |
+ GS_APP_LIST_FILTER_FLAG_KEY_SOURCE |
+ GS_APP_LIST_FILTER_FLAG_KEY_VERSION;
+ self->list = gs_app_list_new ();
+ self->time_created = g_get_monotonic_time ();
+}