Okay, I've hacked together a very rough patch that will do negative
caching on GConf entries. This means if it doesn't find a key in cache
that should've been covered by a previous add_dir, it will consider that
authoritative and not do a roundtrip to the server. This drastically
reduces the total number of roundtrips during Gnome login.
This is definitely not intended for inclusion, I'm just looking for
feedback.
-Ryan
diff -u gconf-orig/gconf2-2.18.0.1/gconf/gconf-client.c gconf-negative-cache/gconf2-2.18.0.1/gconf/gconf-client.c --- gconf-orig/gconf2-2.18.0.1/gconf/gconf-client.c 2007-03-02 14:10:13.000000000 -0800 +++ gconf-negative-cache/gconf2-2.18.0.1/gconf/gconf-client.c 2007-04-24 12:52:47.000000000 -0700 @@ -233,6 +233,7 @@ client->error_mode = GCONF_CLIENT_HANDLE_UNRETURNED; client->dir_hash = g_hash_table_new (g_str_hash, g_str_equal); client->cache_hash = g_hash_table_new (g_str_hash, g_str_equal); + client->cache_complete = TRUE; /* We create the listeners only if they're actually used */ client->listeners = NULL; client->notify_list = NULL; @@ -808,7 +809,8 @@ g_hash_table_foreach_remove (client->cache_hash, (GHRFunc)clear_cache_foreach, client); - + + client->cache_complete = FALSE; g_assert (g_hash_table_size(client->cache_hash) == 0); } @@ -1223,7 +1225,8 @@ { trace ("%s was in the client-side cache\n", key); - g_assert (entry != NULL); + if (entry == NULL) + return NULL; if (gconf_entry_get_is_default (entry) && !use_default) return NULL; @@ -1957,6 +1960,26 @@ } } +typedef struct { + gboolean is_added; + char *dirname; +} DirIsAddedData; + + +static void +foreach_dir_is_added(gpointer key, gpointer value, gpointer dir_data_pointer) +{ + DirIsAddedData *dir_data = dir_data_pointer; + + if (dir_data->is_added == TRUE) + return; + + if (gconf_key_is_below (key, dir_data->dirname)) + { + dir_data->is_added = TRUE; + } +} + static gboolean gconf_client_lookup (GConfClient *client, const char *key, @@ -1970,7 +1993,22 @@ entry = g_hash_table_lookup (client->cache_hash, key); *entryp = entry; - + + if (!entry && client->cache_complete) + { + DirIsAddedData dir_data; + + dir_data.dirname = key; + dir_data.is_added = FALSE; + + g_hash_table_foreach(client->dir_hash, foreach_dir_is_added, &dir_data); + if (dir_data.is_added) + { + trace ("Negative cache hit on %s\n", key); + return TRUE; + } + } + return entry != NULL; } diff -u gconf-orig/gconf2-2.18.0.1/gconf/gconf-client.h gconf-negative-cache/gconf2-2.18.0.1/gconf/gconf-client.h --- gconf-orig/gconf2-2.18.0.1/gconf/gconf-client.h 2007-03-02 14:10:13.000000000 -0800 +++ gconf-negative-cache/gconf2-2.18.0.1/gconf/gconf-client.h 2007-04-24 09:23:22.000000000 -0700 @@ -101,7 +101,7 @@ guint notify_handler; int pending_notify_count; gpointer pad1; - int pad2; + gboolean cache_complete; }; struct _GConfClientClass