diff options
author | Ray Strode <rstrode@redhat.com> | 2023-03-27 11:24:02 -0400 |
---|---|---|
committer | Ray Strode <rstrode@redhat.com> | 2023-03-27 15:27:39 -0400 |
commit | ff58f16bd5c75bea47939fed41716845cd427208 (patch) | |
tree | 882b0e0859bb09ddc33a9288a26097db3c83e238 | |
parent | a6e627bf5797a812aebe90ad840b20a4950f064f (diff) | |
download | accountsservice-ff58f16bd5c75bea47939fed41716845cd427208.tar.gz |
user-manager: Deduplicate ActUser objects when possible
If act_user_manager_get_user_by_id is called twice in a row
for the same user, two ActUser objects get generated, each
ultimately representing the same user.
That is less than ideal since the ActUser objects are owned
by the user manager, not by the callers.
This commit tries to minimize the amount of duplicate ActUser
objects that can get put in the wild, by checking for
existig in-flight requests and consolidating them.
Note there can still be duplicated users if there is a
act_user_manager_get_user and act_user_manager_get_user_by_id call
for the same user at the same time. There's no way to deduplicate
the objects in that case.
-rw-r--r-- | src/libaccountsservice/act-user-manager.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/src/libaccountsservice/act-user-manager.c b/src/libaccountsservice/act-user-manager.c index fe042a1..ac59729 100644 --- a/src/libaccountsservice/act-user-manager.c +++ b/src/libaccountsservice/act-user-manager.c @@ -1921,6 +1921,32 @@ fetch_user_with_id_from_accounts_service (ActUserManager *manager, fetch_user_incrementally (request); } +static ActUser * +check_fetch_user_requests_for_user (ActUserManager *manager, + const char *username) +{ + ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager); + GSList *node; + + node = priv->fetch_user_requests; + while (node != NULL) { + ActUserManagerFetchUserRequest *request; + GSList *next_node; + + request = node->data; + next_node = node->next; + + if (request->type == ACT_USER_MANAGER_FETCH_USER_FROM_USERNAME_REQUEST) { + if (g_strcmp0 (request->username, username) == 0) + return request->user; + } + + node = next_node; + } + + return NULL; +} + /** * act_user_manager_get_user: * @manager: the manager to query. @@ -1945,6 +1971,14 @@ act_user_manager_get_user (ActUserManager *manager, user = lookup_user_by_name (manager, username); + if (user == NULL) { + user = check_fetch_user_requests_for_user (manager, username); + + if (user != NULL) { + g_debug ("ActUserManager: User with username '%s' fetched by username more than once before it loaded", username); + } + } + /* if we don't have it loaded try to load it now */ if (user == NULL) { g_debug ("ActUserManager: trying to track new user with username %s", username); @@ -2004,6 +2038,32 @@ load_user (ActUserManager *manager, _act_user_update_from_object_path (user, object_path); } +static ActUser * +check_fetch_user_requests_for_user_with_id (ActUserManager *manager, + uid_t id) +{ + ActUserManagerPrivate *priv = act_user_manager_get_instance_private (manager); + GSList *node; + + node = priv->fetch_user_requests; + while (node != NULL) { + ActUserManagerFetchUserRequest *request; + GSList *next_node; + + request = node->data; + next_node = node->next; + + if (request->type == ACT_USER_MANAGER_FETCH_USER_FROM_ID_REQUEST) { + if (request->uid == id) + return request->user; + } + + node = next_node; + } + + return NULL; +} + /** * act_user_manager_get_user_by_id: * @manager: the manager to query. @@ -2029,6 +2089,14 @@ act_user_manager_get_user_by_id (ActUserManager *manager, object_path = g_strdup_printf ("/org/freedesktop/Accounts/User%lu", (gulong) id); user = g_hash_table_lookup (priv->users_by_object_path, object_path); + if (user == NULL) { + user = check_fetch_user_requests_for_user_with_id (manager, id); + + if (user != NULL) { + g_debug ("ActUserManager: User with UID %d fetched more than once before it loaded", (int) id); + } + } + if (user != NULL) { return user; } else { |