pidgin: 7624afb1: More efficient purple_find_conversation_...
darkrain42 at pidgin.im
darkrain42 at pidgin.im
Mon Jul 27 00:15:22 EDT 2009
-----------------------------------------------------------------
Revision: 7624afb13d9554cac3283113c46ff21a2438f2ae
Ancestor: f13df1588429b04546887dfb2f68cb983c6a3eab
Author: aman at tmm1.net
Date: 2009-07-27T04:12:06
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/7624afb13d9554cac3283113c46ff21a2438f2ae
Modified files:
ChangeLog ChangeLog.API libpurple/conversation.c
ChangeLog:
More efficient purple_find_conversation_with_account. Closes #9703.
Patch mostly from Aman "tmm1" Gupta; I added the g_list_prepend calls.
The functionality is going to get whacky when dealing with chats that
share the same name ("MSN Chat"), but purple_find_conversation_with_account
doesn't work for those in any sense of the word 'work', so...
-------------- next part --------------
============================================================
--- ChangeLog 3217daab4aefa0877a7cfdd64a19fa85d7875de4
+++ ChangeLog aa39c52c1e75241640066444a6227e87e97a6ff0
@@ -36,7 +36,7 @@ version 2.6.0 (??/??/2009):
(Aman Gupta)
* Don't fork a DNS resolver process to resolve IP addresses. (Aman Gupta)
* Better handling of corrupt certificates in the TLS Peers cache.
- * More efficient purple_find_buddies() and purple_find_group() functions.
+ * More efficient buddy list and conversation search functions.
(Jan Kaluza and Aman Gupta)
* Internationalized Domain Names are supported when libpurple is compiled
against the GNU IDN library.
============================================================
--- ChangeLog.API 43295ef22881c6bc5790ce74edb5244eba598df1
+++ ChangeLog.API 57e08d2fc212efd8446f2a1e13bf18091cbaffe1
@@ -85,6 +85,8 @@ version 2.6.0 (??/??/2009):
* 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.
+ * purple_find_conversation_with_account is more efficient for large
+ numbers of concurrent conversations.
* All DNS routines support internationalized domain names (IDNs) when
libpurple is compiled with GNU libidn.
* status is set before emitting signals in purple_xfer_set_status.
============================================================
--- libpurple/conversation.c 3635f430eaa4701abeb4d6b6bcc6797ed7c41c23
+++ libpurple/conversation.c 8bf4d1875ad9dac9cddb2984f73218813569046a
@@ -40,6 +40,36 @@ static PurpleConversationUiOps *default_
static GList *chats = NULL;
static PurpleConversationUiOps *default_ops = NULL;
+/**
+ * A hash table used for efficient lookups of conversations by name.
+ * struct _purple_hconv => PurpleConversation*
+ */
+static GHashTable *conversation_cache = NULL;
+
+struct _purple_hconv {
+ PurpleConversationType type;
+ char *name;
+ const PurpleAccount *account;
+};
+
+static guint _purple_conversations_hconv_hash(struct _purple_hconv *hc)
+{
+ return g_str_hash(hc->name) ^ hc->type ^ g_direct_hash(hc->account);
+}
+
+static guint _purple_conversations_hconv_equal(struct _purple_hconv *hc1, struct _purple_hconv *hc2)
+{
+ return (hc1->type == hc2->type &&
+ hc1->account == hc2->account &&
+ g_str_equal(hc1->name, hc2->name));
+}
+
+static void _purple_conversations_hconv_free_key(struct _purple_hconv *hc)
+{
+ g_free(hc->name);
+ g_free(hc);
+}
+
void
purple_conversations_set_ui_ops(PurpleConversationUiOps *ops)
{
@@ -287,6 +317,7 @@ purple_conversation_new(PurpleConversati
PurpleConversation *conv;
PurpleConnection *gc;
PurpleConversationUiOps *ops;
+ struct _purple_hconv *hc;
g_return_val_if_fail(type != PURPLE_CONV_TYPE_UNKNOWN, NULL);
g_return_val_if_fail(account != NULL, NULL);
@@ -342,7 +373,7 @@ purple_conversation_new(PurpleConversati
conv->u.im->conv = conv;
PURPLE_DBUS_REGISTER_POINTER(conv->u.im, PurpleConvIm);
- ims = g_list_append(ims, conv);
+ ims = g_list_prepend(ims, conv);
if ((icon = purple_buddy_icons_find(account, name)))
{
purple_conv_im_set_icon(conv->u.im, icon);
@@ -364,7 +395,7 @@ purple_conversation_new(PurpleConversati
conv->u.chat->conv = conv;
PURPLE_DBUS_REGISTER_POINTER(conv->u.chat, PurpleConvChat);
- chats = g_list_append(chats, conv);
+ chats = g_list_prepend(chats, conv);
if ((disp = purple_connection_get_display_name(account->gc)))
purple_conv_chat_set_nick(conv->u.chat, disp);
@@ -379,8 +410,15 @@ purple_conversation_new(PurpleConversati
}
}
- conversations = g_list_append(conversations, conv);
+ conversations = g_list_prepend(conversations, conv);
+ hc = g_new(struct _purple_hconv, 1);
+ hc->name = g_strdup(purple_normalize(account, conv->name));
+ hc->account = account;
+ hc->type = type;
+
+ g_hash_table_insert(conversation_cache, hc, conv);
+
/* Auto-set the title. */
purple_conversation_autoset_title(conv);
@@ -405,6 +443,7 @@ purple_conversation_destroy(PurpleConver
PurpleConversationUiOps *ops;
PurpleConnection *gc;
const char *name;
+ struct _purple_hconv hc;
g_return_if_fail(conv != NULL);
@@ -481,6 +520,12 @@ purple_conversation_destroy(PurpleConver
else if(conv->type==PURPLE_CONV_TYPE_CHAT)
chats = g_list_remove(chats, conv);
+ hc.name = (gchar *)purple_normalize(conv->account, conv->name);
+ hc.account = conv->account;
+ hc.type = conv->type;
+
+ g_hash_table_remove(conversation_cache, &hc);
+
purple_signal_emit(purple_conversations_get_handle(),
"deleting-conversation", conv);
@@ -707,10 +752,20 @@ purple_conversation_set_name(PurpleConve
void
purple_conversation_set_name(PurpleConversation *conv, const char *name)
{
+ struct _purple_hconv *hc;
g_return_if_fail(conv != NULL);
+ hc = g_new(struct _purple_hconv, 1);
+ hc->type = conv->type;
+ hc->account = conv->account;
+ hc->name = (gchar *)purple_normalize(conv->account, conv->name);
+
+ g_hash_table_remove(conversation_cache, hc);
g_free(conv->name);
+
conv->name = g_strdup(name);
+ hc->name = g_strdup(purple_normalize(conv->account, conv->name));
+ g_hash_table_insert(conversation_cache, hc, conv);
purple_conversation_autoset_title(conv);
}
@@ -819,43 +874,31 @@ purple_find_conversation_with_account(Pu
const PurpleAccount *account)
{
PurpleConversation *c = NULL;
- gchar *name1;
- const gchar *name2;
- GList *cnv;
+ struct _purple_hconv hc;
g_return_val_if_fail(name != NULL, NULL);
+ hc.name = (gchar *)purple_normalize(account, name);
+ hc.account = account;
+ hc.type = type;
+
switch (type) {
case PURPLE_CONV_TYPE_IM:
- cnv = purple_get_ims();
- break;
case PURPLE_CONV_TYPE_CHAT:
- cnv = purple_get_chats();
+ c = g_hash_table_lookup(conversation_cache, &hc);
break;
case PURPLE_CONV_TYPE_ANY:
- cnv = purple_get_conversations();
+ hc.type = PURPLE_CONV_TYPE_IM;
+ c = g_hash_table_lookup(conversation_cache, &hc);
+ if (!c) {
+ hc.type = PURPLE_CONV_TYPE_CHAT;
+ c = g_hash_table_lookup(conversation_cache, &hc);
+ }
break;
default:
g_return_val_if_reached(NULL);
}
- name1 = g_strdup(purple_normalize(account, name));
-
- for (; cnv != NULL; cnv = cnv->next) {
- c = (PurpleConversation *)cnv->data;
- name2 = purple_normalize(account, purple_conversation_get_name(c));
-
- if ((account == purple_conversation_get_account(c)) &&
- !purple_utf8_strcasecmp(name1, name2)) {
-
- break;
- }
-
- c = NULL;
- }
-
- g_free(name1);
-
return c;
}
@@ -2215,6 +2258,10 @@ purple_conversations_init(void)
{
void *handle = purple_conversations_get_handle();
+ conversation_cache = g_hash_table_new_full((GHashFunc)_purple_conversations_hconv_hash,
+ (GEqualFunc)_purple_conversations_hconv_equal,
+ (GDestroyNotify)_purple_conversations_hconv_free_key, NULL);
+
/**********************************************************************
* Register preferences
**********************************************************************/
@@ -2504,6 +2551,7 @@ purple_conversations_uninit(void)
{
while (conversations)
purple_conversation_destroy((PurpleConversation*)conversations->data);
+ g_hash_table_destroy(conversation_cache);
purple_signals_unregister_by_instance(purple_conversations_get_handle());
}
More information about the Commits
mailing list