baf615
From 42bd3bd41d69100308a22df43482569f6ab53dbe Mon Sep 17 00:00:00 2001
baf615
From: Ray Strode <rstrode@redhat.com>
baf615
Date: Wed, 27 Sep 2017 14:44:48 -0400
baf615
Subject: [PATCH 05/13] lib: consolidate change notification
baf615
baf615
if the daemon sends out multiple change notifications for a user
baf615
because several properties changed in quick succession, try to
baf615
batch them up, and only update info at the end.
baf615
---
baf615
 src/libaccountsservice/act-user.c | 20 +++++++++++++++++++-
baf615
 1 file changed, 19 insertions(+), 1 deletion(-)
baf615
baf615
diff --git a/src/libaccountsservice/act-user.c b/src/libaccountsservice/act-user.c
baf615
index dbb9b53..17acacb 100644
baf615
--- a/src/libaccountsservice/act-user.c
baf615
+++ b/src/libaccountsservice/act-user.c
baf615
@@ -113,60 +113,62 @@ struct _ActUser {
baf615
         char            *object_path;
baf615
 
baf615
         uid_t           uid;
baf615
         char           *user_name;
baf615
         char           *real_name;
baf615
         char           *password_hint;
baf615
         char           *home_dir;
baf615
         char           *shell;
baf615
         char           *email;
baf615
         char           *location;
baf615
         char           *icon_file;
baf615
         char           *language;
baf615
         char           *x_session;
baf615
         GList          *our_sessions;
baf615
         GList          *other_sessions;
baf615
         int             login_frequency;
baf615
         gint64          login_time;
baf615
         GVariant       *login_history;
baf615
 
baf615
         ActUserAccountType  account_type;
baf615
         ActUserPasswordMode password_mode;
baf615
 
baf615
         guint           uid_set : 1;
baf615
 
baf615
         guint           is_loaded : 1;
baf615
         guint           locked : 1;
baf615
         guint           automatic_login : 1;
baf615
         guint           system_account : 1;
baf615
         guint           local_account : 1;
baf615
         guint           nonexistent : 1;
baf615
+
baf615
+        guint           update_info_timeout_id;
baf615
 };
baf615
 
baf615
 struct _ActUserClass
baf615
 {
baf615
         GObjectClass parent_class;
baf615
 };
baf615
 
baf615
 static void act_user_finalize     (GObject      *object);
baf615
 
baf615
 static guint signals[LAST_SIGNAL] = { 0 };
baf615
 
baf615
 G_DEFINE_TYPE (ActUser, act_user, G_TYPE_OBJECT)
baf615
 
baf615
 static int
baf615
 session_compare (const char *a,
baf615
                  const char *b)
baf615
 {
baf615
         if (a == NULL) {
baf615
                 return 1;
baf615
         } else if (b == NULL) {
baf615
                 return -1;
baf615
         }
baf615
 
baf615
         return strcmp (a, b);
baf615
 }
baf615
 
baf615
 void
baf615
 _act_user_add_session (ActUser    *user,
baf615
                        const char *ssid,
baf615
                        gboolean    is_ours)
baf615
@@ -573,60 +575,64 @@ act_user_finalize (GObject *object)
baf615
 
baf615
         g_free (user->user_name);
baf615
         g_free (user->real_name);
baf615
         g_free (user->icon_file);
baf615
         g_free (user->language);
baf615
         g_free (user->object_path);
baf615
         g_free (user->password_hint);
baf615
         g_free (user->home_dir);
baf615
         g_free (user->shell);
baf615
         g_free (user->email);
baf615
         g_free (user->location);
baf615
         if (user->login_history)
baf615
           g_variant_unref (user->login_history);
baf615
 
baf615
         if (user->accounts_proxy != NULL) {
baf615
                 g_object_unref (user->accounts_proxy);
baf615
         }
baf615
 
baf615
         if (user->object_proxy != NULL) {
baf615
                 g_object_unref (user->object_proxy);
baf615
         }
baf615
 
baf615
         if (user->get_all_cancellable != NULL) {
baf615
                 g_object_unref (user->get_all_cancellable);
baf615
         }
baf615
 
baf615
         if (user->connection != NULL) {
baf615
                 g_object_unref (user->connection);
baf615
         }
baf615
 
baf615
+        if (user->update_info_timeout_id != 0) {
baf615
+                g_source_remove (user->update_info_timeout_id);
baf615
+        }
baf615
+
baf615
         if (G_OBJECT_CLASS (act_user_parent_class)->finalize)
baf615
                 (*G_OBJECT_CLASS (act_user_parent_class)->finalize) (object);
baf615
 }
baf615
 
baf615
 static void
baf615
 set_is_loaded (ActUser  *user,
baf615
                gboolean  is_loaded)
baf615
 {
baf615
         if (user->is_loaded != is_loaded) {
baf615
                 user->is_loaded = is_loaded;
baf615
                 g_object_notify (G_OBJECT (user), "is-loaded");
baf615
         }
baf615
 }
baf615
 
baf615
 /**
baf615
  * act_user_get_uid:
baf615
  * @user: the user object to examine.
baf615
  *
baf615
  * Retrieves the ID of @user.
baf615
  *
baf615
  * Returns: (transfer none): a pointer to an array of characters which must not be modified or
baf615
  *  freed, or %NULL.
baf615
  **/
baf615
 
baf615
 uid_t
baf615
 act_user_get_uid (ActUser *user)
baf615
 {
baf615
         g_return_val_if_fail (ACT_IS_USER (user), -1);
baf615
 
baf615
         return user->uid;
baf615
@@ -1339,67 +1345,79 @@ on_get_all_finished (GObject        *object,
baf615
         g_variant_unref (res);
baf615
 
baf615
         if (!user->is_loaded) {
baf615
                 set_is_loaded (user, TRUE);
baf615
         }
baf615
 
baf615
         g_signal_emit (user, signals[CHANGED], 0);
baf615
 }
baf615
 
baf615
 static void
baf615
 update_info (ActUser *user)
baf615
 {
baf615
         g_assert (G_IS_DBUS_PROXY (user->object_proxy));
baf615
 
baf615
         if (user->get_all_cancellable != NULL) {
baf615
                 g_cancellable_cancel (user->get_all_cancellable);
baf615
                 g_clear_object (&user->get_all_cancellable);
baf615
         }
baf615
 
baf615
         user->get_all_cancellable = g_cancellable_new ();
baf615
         g_dbus_proxy_call (user->object_proxy,
baf615
                            "GetAll",
baf615
                            g_variant_new ("(s)", ACCOUNTS_USER_INTERFACE),
baf615
                            G_DBUS_CALL_FLAGS_NONE,
baf615
                            -1,
baf615
                            user->get_all_cancellable,
baf615
                            on_get_all_finished,
baf615
                            user);
baf615
 }
baf615
 
baf615
+static gboolean
baf615
+on_timeout_update_info (ActUser *user)
baf615
+{
baf615
+        update_info (user);
baf615
+        user->update_info_timeout_id = 0;
baf615
+
baf615
+        return G_SOURCE_REMOVE;
baf615
+}
baf615
+
baf615
 static void
baf615
 changed_handler (AccountsUser *object,
baf615
                  gpointer   *data)
baf615
 {
baf615
         ActUser *user = ACT_USER (data);
baf615
 
baf615
-        update_info (user);
baf615
+        if (user->update_info_timeout_id != 0)
baf615
+                return;
baf615
+
baf615
+        user->update_info_timeout_id = g_timeout_add (250, (GSourceFunc) on_timeout_update_info, user);
baf615
 }
baf615
 
baf615
 /**
baf615
  * _act_user_update_as_nonexistent:
baf615
  * @user: the user object to update.
baf615
  *
baf615
  * Set's the 'non-existent' property of @user to #TRUE
baf615
  * Can only be called before the user is loaded.
baf615
  **/
baf615
 void
baf615
 _act_user_update_as_nonexistent (ActUser *user)
baf615
 {
baf615
         g_return_if_fail (ACT_IS_USER (user));
baf615
         g_return_if_fail (!act_user_is_loaded (user));
baf615
         g_return_if_fail (user->object_path == NULL);
baf615
 
baf615
         user->nonexistent = TRUE;
baf615
         g_object_notify (G_OBJECT (user), "nonexistent");
baf615
 
baf615
         set_is_loaded (user, TRUE);
baf615
 }
baf615
 
baf615
 /**
baf615
  * _act_user_update_from_object_path:
baf615
  * @user: the user object to update.
baf615
  * @object_path: the object path of the user to use.
baf615
  *
baf615
  * Updates the properties of @user from the accounts service via
baf615
  * the object path in @object_path.
baf615
  **/
baf615
-- 
baf615
2.14.1
baf615