From 2ed34f69d4400f863835c4149be4ecb82ffe1c72 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 7 Aug 2009 01:19:18 +0200 Subject: consolekit: cache ckit database file Speed up ckit database checks a little by keeping the parsed database in memory and mantaining an extra hashtable-based cache. --- dbus/dbus-userdb-util.c | 107 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 98 insertions(+), 9 deletions(-) (limited to 'dbus/dbus-userdb-util.c') diff --git a/dbus/dbus-userdb-util.c b/dbus/dbus-userdb-util.c index 8361fcf3..f4d1f0c9 100644 --- a/dbus/dbus-userdb-util.c +++ b/dbus/dbus-userdb-util.c @@ -35,6 +35,28 @@ * @{ */ +#if defined(HAVE_CONSOLEKIT_DATABASE) +static DBusDesktopFile *ckit_database = NULL; +static DBusHashTable *ckit_cache = NULL; + +static void +ckit_cleanup(void *data) +{ + if (ckit_database) + { + _dbus_desktop_file_free(ckit_database); + ckit_database = NULL; + } + + if (ckit_cache) + { + _dbus_hash_table_unref(ckit_cache); + ckit_cache = NULL; + } +} + +#endif + /** * Checks to see if the UID sent in is the console user * @@ -49,19 +71,68 @@ _dbus_is_console_user (dbus_uid_t uid, #if defined(HAVE_CONSOLEKIT_DATABASE) - DBusDesktopFile *f; + const char *section; dbus_bool_t found = FALSE; DBusString fn; unsigned i = 0; + void *e; _dbus_string_init_const(&fn, DBUS_CONSOLEKIT_DATABASE); - f = _dbus_desktop_file_load(&fn, error); - if (!f) - return FALSE; + _dbus_user_database_lock_system (); + + /* Flush database if it changed */ + if (ckit_database && + _dbus_desktop_file_changed(ckit_database, &fn)) + { + _dbus_desktop_file_free(ckit_database); + ckit_database = NULL; + + if (ckit_cache) + _dbus_hash_table_remove_all(ckit_cache); + } + + /* Initialize cache */ + if (!ckit_cache) + { + ckit_cache = _dbus_hash_table_new(DBUS_HASH_ULONG, NULL, NULL); + if (!ckit_cache) + { + _dbus_user_database_unlock_system (); + _DBUS_SET_OOM(error); + return FALSE; + } + + if (!_dbus_register_shutdown_func(ckit_cleanup, NULL)) + { + ckit_cleanup(NULL); + _dbus_user_database_unlock_system (); + _DBUS_SET_OOM(error); + return FALSE; + } + } + + /* Load database */ + if (!ckit_database) + { + ckit_database = _dbus_desktop_file_load(&fn, error); + if (!ckit_database) + { + _dbus_user_database_unlock_system (); + return FALSE; + } + } + + /* Check cache first */ + e = _dbus_hash_table_lookup_ulong(ckit_cache, (unsigned long) uid); + if (e) + { + _dbus_user_database_unlock_system (); + return _DBUS_POINTER_TO_INT(e) > 0; + } - while ((section = _dbus_desktop_file_get_section(f, i++))) + while ((section = _dbus_desktop_file_get_section(ckit_database, i++))) { const char *val; char *e = NULL; @@ -70,7 +141,7 @@ _dbus_is_console_user (dbus_uid_t uid, if (strncmp(section, "Session ", 8)) continue; - if (!_dbus_desktop_file_get_raw(f, section, "uid", &val)) + if (!_dbus_desktop_file_get_raw(ckit_database, section, "uid", &val)) continue; errno = 0; @@ -85,7 +156,11 @@ _dbus_is_console_user (dbus_uid_t uid, } } - _dbus_desktop_file_free(f); + /* Cache for later. We don't care if that worked. If it didn't the + only price we pay is that we have to recheck next time */ + _dbus_hash_table_insert_ulong(ckit_cache, (unsigned long) uid, _DBUS_INT_TO_POINTER(found ? 1 : -1)); + + _dbus_user_database_unlock_system (); return found; #elif defined(HAVE_CONSOLE_OWNER_FILE) @@ -486,8 +561,22 @@ _dbus_userdb_test (const char *test_data_dir) printf ("\n"); dbus_error_init(&error); - printf ("Is Console user: %i\n", - _dbus_is_console_user(uid, &error)); + printf ("1000 is Console user: %i\n", _dbus_is_console_user(1000, &error)); + printf ("Invocation was OK: %s\n", error.message ? error.message : "yes"); + dbus_error_free(&error); + + dbus_error_init(&error); + printf ("0 is Console user: %i\n", _dbus_is_console_user(0, &error)); + printf ("Invocation was OK: %s\n", error.message ? error.message : "yes"); + dbus_error_free(&error); + + dbus_error_init(&error); + printf ("1001 is Console user: %i\n", _dbus_is_console_user(1001, &error)); + printf ("Invocation was OK: %s\n", error.message ? error.message : "yes"); + dbus_error_free(&error); + + dbus_error_init(&error); + printf ("1000 is Console user: %i\n", _dbus_is_console_user(1000, &error)); printf ("Invocation was OK: %s\n", error.message ? error.message : "yes"); dbus_error_free(&error); -- cgit