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