changeset 27645:36aa9ed8cd39

Use a hash table for looking up PurpleGroup:s. Apparently Aman "tmm1" Gupta has a lot of groups in his buddy list, so he wrote this patch. committer: Paul Aurich <paul@darkrain42.org>
author aman@tmm1.net
date Thu, 16 Jul 2009 04:40:08 +0000
parents 2d541e194416
children 29e85d424701 ccb1f1777df7
files ChangeLog ChangeLog.API libpurple/blist.c
diffstat 3 files changed, 45 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Jul 16 03:55:24 2009 +0000
+++ b/ChangeLog	Thu Jul 16 04:40:08 2009 +0000
@@ -7,7 +7,7 @@
 	* Voice & Video framework in libpurple, thanks to Mike Ruprecht's summer
 	  of code project in 2008.
 	* It should no longer be possible to end up with duplicates of buddies
-	  in a group on the buddy list. (Paul Aurich)
+	  in a group on the buddy list.
 	* Removed the unmaintained and unneeded toc protocol plugin.
 	* Fixed NTLM authentication on big-endian systems.
 	* Various memory cleanups when unloading libpurple. (Nick Hebner)
@@ -35,7 +35,9 @@
 	  from you on MSN.
 	* Support sending an invite message to buddies when requesting authorization
 	  from them on MSN.
-	* Better handle corrupt certificates in the TLS Peers cache.
+	* Better handling of corrupt certificates in the TLS Peers cache.
+	* More efficient purple_find_buddies() and purple_find_group() functions.
+	  (Jan Kaluza and Aman Gupta)
 
 	AIM and ICQ:
 	* Preliminary support for a new authentication scheme called
--- a/ChangeLog.API	Thu Jul 16 03:55:24 2009 +0000
+++ b/ChangeLog.API	Thu Jul 16 04:40:08 2009 +0000
@@ -80,6 +80,9 @@
 		* Added a client_type field in the get_ui_info core UI op. See
 		  core.h for details.
 		* Added introspection of signals exposed via the D-Bus API.
+		* purple_find_buddies is now more efficient in the case where
+		  it is enumerating all the buddies for an account.
+		* purple_find_group is now more efficient for large numbers of groups.
 
 		Deprecated:
 		* buddy-added and buddy-removed blist signals
--- a/libpurple/blist.c	Thu Jul 16 03:55:24 2009 +0000
+++ b/libpurple/blist.c	Thu Jul 16 04:40:08 2009 +0000
@@ -48,6 +48,12 @@
  */
 static GHashTable *buddies_cache = NULL;
 
+/**
+ * A hash table used for efficient lookups of groups by name.
+ * UTF-8 collate-key => PurpleGroup*.
+ */
+static GHashTable *groups_cache = NULL;
+
 static guint          save_timer = 0;
 static gboolean       blist_loaded = FALSE;
 
@@ -704,6 +710,10 @@
 	buddies_cache = g_hash_table_new_full(g_direct_hash, g_direct_equal,
 					 NULL, (GDestroyNotify)g_hash_table_destroy);
 
+	groups_cache = g_hash_table_new_full((GHashFunc)g_str_hash,
+					 (GEqualFunc)g_str_equal,
+					 (GDestroyNotify)g_free, NULL);
+
 	for (account = purple_accounts_get_all(); account != NULL; account = account->next)
 	{
 		purple_blist_buddies_cache_add_account(account->data);
@@ -1203,6 +1213,7 @@
 	} else {
 		/* A simple rename */
 		PurpleBlistNode *cnode, *bnode;
+		gchar* key;
 
 		/* Build a GList of all buddies in this group */
 		for (cnode = ((PurpleBlistNode *)source)->child; cnode != NULL; cnode = cnode->next) {
@@ -1213,6 +1224,13 @@
 
 		old_name = source->name;
 		source->name = new_name;
+
+		key = g_utf8_collate_key(old_name, -1);
+		g_hash_table_remove(groups_cache, key);
+		g_free(key);
+
+		key = g_utf8_collate_key(new_name, -1);
+		g_hash_table_insert(groups_cache, key, source);
 	}
 
 	/* Save our changes */
@@ -1946,6 +1964,7 @@
 {
 	PurpleBlistUiOps *ops;
 	PurpleBlistNode *gnode = (PurpleBlistNode*)group;
+	gchar* key;
 
 	g_return_if_fail(group != NULL);
 	g_return_if_fail(PURPLE_BLIST_NODE_IS_GROUP((PurpleBlistNode *)group));
@@ -1989,6 +2008,9 @@
 		purplebuddylist->root = gnode;
 	}
 
+	key = g_utf8_collate_key(group->name, -1);
+	g_hash_table_insert(groups_cache, key, group);
+
 	purple_blist_schedule_save();
 
 	if (ops && ops->update) {
@@ -2174,6 +2196,7 @@
 	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
 	PurpleBlistNode *node;
 	GList *l;
+	gchar* key;
 
 	g_return_if_fail(group != NULL);
 
@@ -2191,6 +2214,10 @@
 	if (node->next)
 		node->next->prev = node->prev;
 
+	key = g_utf8_collate_key(group->name, -1);
+	g_hash_table_remove(groups_cache, key);
+	g_free(key);
+
 	purple_blist_schedule_save();
 
 	/* Update the UI */
@@ -2427,17 +2454,17 @@
 
 PurpleGroup *purple_find_group(const char *name)
 {
-	PurpleBlistNode *node;
+	gchar* key;
+	PurpleGroup *group;
 
 	g_return_val_if_fail(purplebuddylist != NULL, NULL);
 	g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL);
 
-	for (node = purplebuddylist->root; node != NULL; node = node->next) {
-		if (!purple_utf8_strcasecmp(((PurpleGroup *)node)->name, name))
-			return (PurpleGroup *)node;
-	}
-
-	return NULL;
+	key = g_utf8_collate_key(name, -1);
+	group = g_hash_table_lookup(groups_cache, key);
+	g_free(key);
+
+	return group;
 }
 
 PurpleChat *
@@ -3117,6 +3144,10 @@
 
 	g_hash_table_destroy(purplebuddylist->buddies);
 	g_hash_table_destroy(buddies_cache);
+	g_hash_table_destroy(groups_cache);
+
+	buddies_cache = NULL;
+	groups_cache = NULL;
 
 	PURPLE_DBUS_UNREGISTER_POINTER(purplebuddylist);
 	g_free(purplebuddylist);