[gnome-software/mwleeds/hardcoded-pwa-list] gs-plugin-job-refine: Respect plugin order



commit 5bee52b1eda0c341c2674e95e9c5347b563dc6a5
Author: Phaedrus Leeds <mwleeds protonmail com>
Date:   Tue Mar 22 15:45:11 2022 -0700

    gs-plugin-job-refine: Respect plugin order
    
    Instead of starting each plugin's refine in series, do batches in
    parallel of plugins that have the same order number, just as we do in
    gs_plugin_loader_setup_async() and other GsPluginJob classes.

 lib/gs-plugin-job-refine.c | 71 ++++++++++++++++++++++++----------------------
 1 file changed, 37 insertions(+), 34 deletions(-)
---
diff --git a/lib/gs-plugin-job-refine.c b/lib/gs-plugin-job-refine.c
index dabc8de42..af3a5d557 100644
--- a/lib/gs-plugin-job-refine.c
+++ b/lib/gs-plugin-job-refine.c
@@ -40,11 +40,6 @@
  * components for all the components in the input #GsAppList. The refine job is
  * complete once all these recursive calls complete.
  *
- * FIXME: Ideally, the #GsPluginClass.refine_async() calls would happen in
- * parallel, but this cannot be the case until the results of the refine_async()
- * call in one plugin don’t depend on the results of refine_async() in another.
- * This still happens with several pairs of plugins.
- *
  * ```
  *                                    run_async()
  *                                         |
@@ -89,6 +84,7 @@
 #include "gs-enums.h"
 #include "gs-plugin-job-private.h"
 #include "gs-plugin-job-refine.h"
+#include "gs-plugin-private.h"
 #include "gs-utils.h"
 
 struct _GsPluginJobRefine
@@ -237,8 +233,9 @@ typedef struct {
 
        /* In-progress data. */
        guint n_pending_ops;
+       guint current_batch;
+       gboolean odrs_refine_done;
        guint n_pending_recursions;
-       guint next_plugin_index;
 
        /* Output data. */
        GError *error;  /* (nullable) (owned) */
@@ -288,44 +285,36 @@ run_refine_internal_async (GsPluginJobRefine   *self,
        /* try to adopt each application with a plugin */
        gs_plugin_loader_run_adopt (plugin_loader, list);
 
-       data->n_pending_ops = 0;
+       data->n_pending_ops = 1;
+       data->current_batch = G_MAXUINT;
+       data->odrs_refine_done = FALSE;
 
-       /* run each plugin
-        *
-        * FIXME: For now, we have to run these vfuncs sequentially rather than
-        * all in parallel. This is because there are still dependencies between
-        * some of the plugins, where the code to refine an app in one plugin
-        * depends on the results of refining it in another plugin first.
-        *
-        * Eventually, the plugins should all be changed/removed so that they
-        * can operate independently. At that point, this code can be reverted
-        * so that the refine_async() vfuncs are called in parallel. */
+       /* run the first batch of plugins, based on the order set with
+        * gs_plugin_set_order()
+        */
        plugins = gs_plugin_loader_get_plugins (plugin_loader);
 
        for (guint i = 0; i < plugins->len; i++) {
                GsPlugin *plugin = g_ptr_array_index (plugins, i);
                GsPluginClass *plugin_class = GS_PLUGIN_GET_CLASS (plugin);
+               guint plugin_order = gs_plugin_get_order (plugin);
 
                if (!gs_plugin_get_enabled (plugin))
                        continue;
                if (plugin_class->refine_async == NULL)
                        continue;
 
-               /* FIXME: The next refine_async() call is made in
-                * finish_refine_internal_op(). */
-               data->next_plugin_index = i + 1;
+               if (data->current_batch == G_MAXUINT)
+                       data->current_batch = plugin_order;
+               else if (data->current_batch != plugin_order)
+                       break;
 
                /* run the batched plugin symbol */
                data->n_pending_ops++;
                plugin_class->refine_async (plugin, list, flags,
                                            cancellable, plugin_refine_cb, g_object_ref (task));
-
-               /* FIXME: The next refine_async() call is made in
-                * finish_refine_internal_op(). */
-               return;
        }
 
-       data->n_pending_ops++;
        finish_refine_internal_op (task, NULL);
 }
 
@@ -377,6 +366,7 @@ finish_refine_internal_op (GTask  *task,
        GsOdrsProvider *odrs_provider;
        GsOdrsProviderRefineFlags odrs_refine_flags = 0;
        GPtrArray *plugins;  /* (element-type GsPlugin) */
+       guint prev_batch = data->current_batch;
 
        if (data->error == NULL && error_owned != NULL) {
                data->error = g_steal_pointer (&error_owned);
@@ -387,34 +377,47 @@ finish_refine_internal_op (GTask  *task,
        g_assert (data->n_pending_ops > 0);
        data->n_pending_ops--;
 
+       if (data->n_pending_ops > 0)
+               return;
+
+       data->n_pending_ops = 1; /* increment while starting the batch */
+       data->current_batch = G_MAXUINT;
        plugins = gs_plugin_loader_get_plugins (plugin_loader);
 
-       for (guint i = data->next_plugin_index; i < plugins->len; i++) {
+       /* Check if there's another batch of plugins to run */
+       for (guint i = 0; i < plugins->len; i++) {
                GsPlugin *plugin = g_ptr_array_index (plugins, i);
                GsPluginClass *plugin_class = GS_PLUGIN_GET_CLASS (plugin);
+               guint plugin_order = gs_plugin_get_order (plugin);
 
                if (!gs_plugin_get_enabled (plugin))
                        continue;
                if (plugin_class->refine_async == NULL)
                        continue;
 
-               /* FIXME: The next refine_async() call is made in
-                * finish_refine_internal_op(). */
-               data->next_plugin_index = i + 1;
+               if (plugin_order <= prev_batch)
+                       continue;
+
+               if (data->current_batch == G_MAXUINT)
+                       data->current_batch = plugin_order;
+               else if (plugin_order > data->current_batch)
+                       break;
 
                /* run the batched plugin symbol */
                data->n_pending_ops++;
                plugin_class->refine_async (plugin, list, flags,
                                            cancellable, plugin_refine_cb, g_object_ref (task));
+       }
 
-               /* FIXME: The next refine_async() call is made in
-                * finish_refine_internal_op(). */
+       g_assert (data->n_pending_ops > 0);
+       data->n_pending_ops--;
+
+       if (data->n_pending_ops > 0)
                return;
-       }
 
-       if (data->next_plugin_index == plugins->len) {
+       if (!data->odrs_refine_done) {
                /* Avoid the ODRS refine being run multiple times. */
-               data->next_plugin_index++;
+               data->odrs_refine_done = TRUE;
 
                /* Add ODRS data if needed */
                odrs_provider = gs_plugin_loader_get_odrs_provider (plugin_loader);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]