Blame SOURCES/0004-account-don-t-poll-more-frequently-than-notification.patch

f1fb32
From 3db673bf5f53ee2963e7b21d01062b93630670c5 Mon Sep 17 00:00:00 2001
f1fb32
From: Ray Strode <rstrode@redhat.com>
f1fb32
Date: Fri, 9 Nov 2018 10:39:11 -0500
f1fb32
Subject: [PATCH] account: don't poll more frequently than notification period
f1fb32
f1fb32
At the moment, if an account has no reason to receive a notification,
f1fb32
the account plugin ends up polling continuously, desperately,
f1fb32
and unsuccessfully trying to find a reason to notify. That leads
f1fb32
to unnecessary CPU utilization.
f1fb32
f1fb32
The reason is an apparent think-o in the code.  The code tracks
f1fb32
the last time a notification was shown, so it knows when to show
f1fb32
the next notification later, even if the notification period, or
f1fb32
account policy is updated by the admin in the interim.
f1fb32
f1fb32
The problem is that it's wrong to look at the last notification
f1fb32
time if there's no reason to show a notification.  In that case
f1fb32
the wakeup is merely to poll updates on the account policy.
f1fb32
f1fb32
This commit addresses the problem by only looking at the previous
f1fb32
notification time, if it was within the current notification period.
f1fb32
---
f1fb32
 plugins/account/gsd-account-manager.c | 14 +++++++++++---
f1fb32
 1 file changed, 11 insertions(+), 3 deletions(-)
f1fb32
f1fb32
diff --git a/plugins/account/gsd-account-manager.c b/plugins/account/gsd-account-manager.c
f1fb32
index ff054edd..b48c0fe8 100644
f1fb32
--- a/plugins/account/gsd-account-manager.c
f1fb32
+++ b/plugins/account/gsd-account-manager.c
f1fb32
@@ -207,65 +207,73 @@ out:
f1fb32
 }
f1fb32
 
f1fb32
 static gboolean
f1fb32
 set_policy_number (gint64 *destination,
f1fb32
                    gint64  source)
f1fb32
 {
f1fb32
         if (*destination == source)
f1fb32
                 return FALSE;
f1fb32
 
f1fb32
         *destination = source;
f1fb32
         return TRUE;
f1fb32
 }
f1fb32
 
f1fb32
 static gboolean
f1fb32
 on_notify_period_elapsed (GsdAccountManager *manager)
f1fb32
 {
f1fb32
         manager->priv->notify_period_timeout_id = 0;
f1fb32
         fetch_password_expiration_policy (manager);
f1fb32
         return G_SOURCE_REMOVE;
f1fb32
 }
f1fb32
 
f1fb32
 static void
f1fb32
 queue_periodic_timeout (GsdAccountManager *manager)
f1fb32
 {
f1fb32
         if (manager->priv->notify_period_timeout_id != 0) {
f1fb32
                 g_source_remove (manager->priv->notify_period_timeout_id);
f1fb32
                 manager->priv->notify_period_timeout_id = 0;
f1fb32
         }
f1fb32
 
f1fb32
         if (manager->priv->notify_period > 0) {
f1fb32
-                gint64 already_elapsed_time;
f1fb32
+                gint64 seconds_since_last_notification;
f1fb32
+                guint seconds_between_notifications;
f1fb32
+                guint seconds_until_next_notification;
f1fb32
 
f1fb32
-                already_elapsed_time = MAX (0, (g_get_monotonic_time () - manager->priv->last_notify_time) / G_USEC_PER_SEC);
f1fb32
+                seconds_since_last_notification = MAX (0, (g_get_monotonic_time () - manager->priv->last_notify_time) / G_USEC_PER_SEC);
f1fb32
+                seconds_between_notifications = manager->priv->notify_period * 60;
f1fb32
 
f1fb32
-                manager->priv->notify_period_timeout_id = g_timeout_add_seconds (MAX (0, manager->priv->notify_period * 60 - already_elapsed_time),
f1fb32
+                if (seconds_since_last_notification > seconds_between_notifications)
f1fb32
+                        seconds_until_next_notification = seconds_between_notifications;
f1fb32
+                else
f1fb32
+                        seconds_until_next_notification = seconds_between_notifications - seconds_since_last_notification;
f1fb32
+
f1fb32
+                manager->priv->notify_period_timeout_id = g_timeout_add_seconds (seconds_until_next_notification,
f1fb32
                                                                                  (GSourceFunc) on_notify_period_elapsed,
f1fb32
                                                                                  manager);
f1fb32
         }
f1fb32
 }
f1fb32
 
f1fb32
 static void
f1fb32
 on_got_password_expiration_policy (GsdAccountsUser *accounts_user_proxy,
f1fb32
                                    GAsyncResult    *res,
f1fb32
                                    gpointer         user_data)
f1fb32
 {
f1fb32
         GsdAccountManager *manager = user_data;
f1fb32
         g_autoptr(GError)  error = NULL;
f1fb32
         gboolean           succeeded;
f1fb32
         gint64             expiration_time;
f1fb32
         gint64             last_change_time;
f1fb32
         gint64             min_days_between_changes;
f1fb32
         gint64             max_days_between_changes;
f1fb32
         gint64             days_to_warn;
f1fb32
         gint64             days_after_expiration_until_lock;
f1fb32
 
f1fb32
         gnome_settings_profile_start (NULL);
f1fb32
         succeeded = gsd_accounts_user_call_get_password_expiration_policy_finish (accounts_user_proxy,
f1fb32
                                                                                   &expiration_time,
f1fb32
                                                                                   &last_change_time,
f1fb32
                                                                                   &min_days_between_changes,
f1fb32
                                                                                   &max_days_between_changes,
f1fb32
                                                                                   &days_to_warn,
f1fb32
                                                                                   &days_after_expiration_until_lock,
f1fb32
                                                                                   res,
f1fb32
                                                                                   &error);
f1fb32
-- 
f1fb32
2.17.1
f1fb32