[gdm] Load user properties from account service asynchronously



commit 37a4edafbc79bbd76f49f4d3cdc1abffe062a511
Author: Ray Strode <rstrode redhat com>
Date:   Tue Aug 17 15:04:30 2010 -0400

    Load user properties from account service asynchronously
    
    Previously, we would do a blocking GetAll() call when a new
    user was reported by the accounts daemon.
    
    Now, we initiate a non-blocking GetAll() call defer processing
    the user until the GetAll call finishes.

 gui/simple-greeter/gdm-user-manager.c |   53 ++++++++++++++++---
 gui/simple-greeter/gdm-user.c         |   90 ++++++++++++++++++++++++---------
 2 files changed, 110 insertions(+), 33 deletions(-)
---
diff --git a/gui/simple-greeter/gdm-user-manager.c b/gui/simple-greeter/gdm-user-manager.c
index 92a0421..4dbfcbe 100644
--- a/gui/simple-greeter/gdm-user-manager.c
+++ b/gui/simple-greeter/gdm-user-manager.c
@@ -144,6 +144,7 @@ struct GdmUserManagerPrivate
         GdmUserManagerSeat     seat;
 
         GSList                *new_sessions;
+        GSList                *new_users;
 
         GFileMonitor          *passwd_monitor;
         GFileMonitor          *shells_monitor;
@@ -757,22 +758,21 @@ remove_user (GdmUserManager *manager,
 }
 
 static void
-add_new_user_for_object_path (const char     *object_path,
-                              GdmUserManager *manager)
+on_new_user_changed (GdmUser        *user,
+                     GdmUserManager *manager)
 {
-        GdmUser *user;
         const char *username;
 
-        if (g_hash_table_lookup (manager->priv->users_by_object_path, object_path)) {
-                return;
-        }
-        user = gdm_user_new_from_object_path (object_path);
+        username = gdm_user_get_user_name (user);
 
-        if (user == NULL) {
+        if (username == NULL) {
                 return;
         }
 
-        username = gdm_user_get_user_name (user);
+        g_signal_handlers_disconnect_by_func (user, on_new_user_changed, manager);
+        manager->priv->new_users = g_slist_remove (manager->priv->new_users,
+                                                   user);
+
         if (username_in_exclude_list (manager, username)) {
                 g_debug ("GdmUserManager: excluding user '%s'", username);
                 g_object_unref (user);
@@ -784,6 +784,26 @@ add_new_user_for_object_path (const char     *object_path,
 }
 
 static void
+add_new_user_for_object_path (const char     *object_path,
+                              GdmUserManager *manager)
+{
+        GdmUser *user;
+
+        if (g_hash_table_lookup (manager->priv->users_by_object_path, object_path)) {
+                return;
+        }
+        user = gdm_user_new_from_object_path (object_path);
+
+        if (user == NULL) {
+                return;
+        }
+
+        manager->priv->new_users = g_slist_prepend (manager->priv->new_users, user);
+
+        g_signal_connect (user, "changed", G_CALLBACK (on_new_user_changed), manager);
+}
+
+static void
 on_new_user_in_accounts_service (DBusGProxy *proxy,
                                  const char *object_path,
                                  gpointer    user_data)
@@ -2710,6 +2730,7 @@ static void
 gdm_user_manager_finalize (GObject *object)
 {
         GdmUserManager *manager;
+        GSList         *node;
 
         g_return_if_fail (object != NULL);
         g_return_if_fail (GDM_IS_USER_MANAGER (object));
@@ -2727,6 +2748,20 @@ gdm_user_manager_finalize (GObject *object)
                          (GFunc) unload_new_session, NULL);
         g_slist_free (manager->priv->new_sessions);
 
+        node = manager->priv->new_users;
+        while (node != NULL) {
+                GdmUser *user;
+                GSList  *next_node;
+
+                user = GDM_USER (node->data);
+                next_node = node->next;
+
+                g_signal_handlers_disconnect_by_func (user, on_new_user_changed, manager);
+                g_object_unref (user);
+                manager->priv->new_users = g_slist_delete_link (manager->priv->new_users, node);
+                node = next_node;
+        }
+
         unload_seat (manager);
 
         if (manager->priv->exclude_usernames != NULL) {
diff --git a/gui/simple-greeter/gdm-user.c b/gui/simple-greeter/gdm-user.c
index 8227ff8..037b7e7 100644
--- a/gui/simple-greeter/gdm-user.c
+++ b/gui/simple-greeter/gdm-user.c
@@ -56,6 +56,8 @@ struct _GdmUser {
 
         DBusGConnection *connection;
         DBusGProxy      *accounts_proxy;
+        DBusGProxy      *object_proxy;
+        DBusGProxyCall  *get_all_call;
         char            *object_path;
 
         uid_t           uid;
@@ -195,6 +197,10 @@ gdm_user_finalize (GObject *object)
                 g_object_unref (user->accounts_proxy);
         }
 
+        if (user->object_proxy != NULL) {
+                g_object_unref (user->object_proxy);
+        }
+
         if (user->connection != NULL) {
                 dbus_g_connection_unref (user->connection);
         }
@@ -840,41 +846,77 @@ collect_props (const gchar    *key,
         }
 }
 
-static gboolean
-update_info (GdmUser *user)
+static void
+on_get_all_finished (DBusGProxy     *proxy,
+                     DBusGProxyCall *call,
+                     GdmUser        *user)
 {
-        GError *error;
-        DBusGProxy *proxy;
-        GHashTable *hash_table;
-        gboolean retval;
+        GError      *error;
+        GHashTable  *hash_table;
+        gboolean     res;
 
-        proxy = dbus_g_proxy_new_for_name (user->connection,
-                                           USER_ACCOUNTS_NAME,
-                                           user->object_path,
-                                           DBUS_INTERFACE_PROPERTIES);
+        g_assert (user->get_all_call == call);
+        g_assert (user->object_proxy == proxy);
 
         error = NULL;
-        if (!dbus_g_proxy_call (proxy,
-                                "GetAll",
-                                &error,
-                                G_TYPE_STRING,
-                                USER_ACCOUNTS_INTERFACE,
-                                G_TYPE_INVALID,
-                                dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
-                                &hash_table,
-                                G_TYPE_INVALID)) {
-                g_debug ("Error calling GetAll() when retrieving properties for %s: %s", user->object_path, error->message);
+        res = dbus_g_proxy_end_call (proxy,
+                                     call,
+                                     &error,
+                                     dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+                                     &hash_table,
+                                     G_TYPE_INVALID);
+        user->get_all_call = NULL;
+        user->object_proxy = NULL;
+
+        if (! res) {
+                g_debug ("Error calling GetAll() when retrieving properties for %s: %s",
+                         user->object_path, error->message);
                 g_error_free (error);
-                retval = FALSE;
                 goto out;
         }
         g_hash_table_foreach (hash_table, (GHFunc) collect_props, user);
         g_hash_table_unref (hash_table);
 
-        retval = TRUE;
- out:
+out:
         g_object_unref (proxy);
-        return retval;
+}
+
+static gboolean
+update_info (GdmUser *user)
+{
+        DBusGProxy     *proxy;
+        DBusGProxyCall *call;
+
+        proxy = dbus_g_proxy_new_for_name (user->connection,
+                                           USER_ACCOUNTS_NAME,
+                                           user->object_path,
+                                           DBUS_INTERFACE_PROPERTIES);
+
+        call = dbus_g_proxy_begin_call (proxy,
+                                        "GetAll",
+                                        (DBusGProxyCallNotify)
+                                        on_get_all_finished,
+                                        user,
+                                        NULL,
+                                        G_TYPE_STRING,
+                                        USER_ACCOUNTS_INTERFACE,
+                                        G_TYPE_INVALID);
+
+        if (call == NULL) {
+                g_warning ("GdmUser: failed to make GetAll call");
+                goto failed;
+        }
+
+        user->get_all_call = call;
+        user->object_proxy = proxy;
+        return TRUE;
+
+failed:
+        if (proxy != NULL) {
+                g_object_unref (proxy);
+        }
+
+        return FALSE;
 }
 
 static void



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