pidgin: 04463c42: Make purple_find_buddies(account, NULL) ...
darkrain42 at pidgin.im
darkrain42 at pidgin.im
Fri May 1 12:30:27 EDT 2009
-----------------------------------------------------------------
Revision: 04463c4228e4760066ef026178e08886db366915
Ancestor: 05d010cd0d7eb6dffadd96bffd5396665ab43174
Author: hanzz at soc.pidgin.im
Date: 2009-05-01T08:07:12
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/04463c4228e4760066ef026178e08886db366915
Modified files:
COPYRIGHT libpurple/blist.c
libpurple/protocols/oscar/oscar.c
ChangeLog:
Make purple_find_buddies(account, NULL) O(# buddies in the account) and rewrite purple_ssi_parselist to take advantage of said efficiency.
Applied HanzZ's patch with a few tweaks, mostly making the hash table local
to blist.c and using the signals from the previous commit.
-------------- next part --------------
============================================================
--- COPYRIGHT bac12f27148815ea9f9a1db78e251dcf739aa28d
+++ COPYRIGHT 959c9373c75774296ee7cf2f3d6ed5c60aeac0ff
@@ -215,6 +215,7 @@ Benjamin Kahn
David Jedelsky
Henry Jen
Benjamin Kahn
+Jan Kaluza
Anders Kaseorg
Praveen Karadakal
Jarom?r Karmaz?n
============================================================
--- libpurple/blist.c 2d9d4bb68fb8a3209be1d8952f50e8207553f862
+++ libpurple/blist.c 30522a639b649fbb0276288c11086b244fdd6354
@@ -40,6 +40,14 @@ static PurpleBuddyList *purplebuddylist
static PurpleBlistUiOps *blist_ui_ops = NULL;
static PurpleBuddyList *purplebuddylist = NULL;
+
+/**
+ * A hash table used for efficient lookups of buddies by name.
+ * PurpleAccount* => GHashTable*, with the inner hash table being
+ * struct _purple_hbuddy => PurpleBuddy*
+ */
+static GHashTable *buddies_cache = NULL;
+
static guint save_timer = 0;
static gboolean blist_loaded = FALSE;
@@ -91,7 +99,22 @@ static void _purple_blist_hbuddy_free_ke
g_free(hb);
}
+static void
+purple_blist_buddies_cache_add_account(PurpleAccount *account)
+{
+ GHashTable *account_buddies = g_hash_table_new_full((GHashFunc)_purple_blist_hbuddy_hash,
+ (GEqualFunc)_purple_blist_hbuddy_equal,
+ (GDestroyNotify)_purple_blist_hbuddy_free_key, NULL);
+ g_hash_table_insert(buddies_cache, account, account_buddies);
+}
+static void
+purple_blist_buddies_cache_remove_account(const PurpleAccount *account)
+{
+ g_hash_table_remove(buddies_cache, account);
+}
+
+
/*********************************************************************
* Writing to disk *
*********************************************************************/
@@ -666,6 +689,7 @@ PurpleBuddyList *purple_blist_new()
PurpleBuddyList *purple_blist_new()
{
PurpleBlistUiOps *ui_ops;
+ GList *account;
PurpleBuddyList *gbl = g_new0(PurpleBuddyList, 1);
PURPLE_DBUS_REGISTER_POINTER(gbl, PurpleBuddyList);
@@ -675,6 +699,14 @@ PurpleBuddyList *purple_blist_new()
(GEqualFunc)_purple_blist_hbuddy_equal,
(GDestroyNotify)_purple_blist_hbuddy_free_key, NULL);
+ buddies_cache = g_hash_table_new_full(g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify)g_hash_table_destroy);
+
+ for (account = purple_accounts_get_all(); account != NULL; account = account->next)
+ {
+ purple_blist_buddies_cache_add_account(account->data);
+ }
+
if (ui_ops != NULL && ui_ops->new_list != NULL)
ui_ops->new_list(gbl);
@@ -898,7 +930,8 @@ void purple_blist_rename_buddy(PurpleBud
void purple_blist_rename_buddy(PurpleBuddy *buddy, const char *name)
{
PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
- struct _purple_hbuddy *hb;
+ struct _purple_hbuddy *hb, *hb2;
+ GHashTable *account_buddies;
g_return_if_fail(buddy != NULL);
@@ -907,11 +940,21 @@ void purple_blist_rename_buddy(PurpleBud
hb->account = buddy->account;
hb->group = ((PurpleBlistNode *)buddy)->parent->parent;
g_hash_table_remove(purplebuddylist->buddies, hb);
+
+ account_buddies = g_hash_table_lookup(buddies_cache, buddy->account);
+ g_hash_table_remove(account_buddies, hb);
g_free(hb->name);
hb->name = g_strdup(purple_normalize(buddy->account, name));
g_hash_table_replace(purplebuddylist->buddies, hb, buddy);
+ hb2 = g_new(struct _purple_hbuddy, 1);
+ hb2->name = g_strdup(hb->name);
+ hb2->account = buddy->account;
+ hb2->group = ((PurpleBlistNode *)buddy)->parent->parent;
+
+ g_hash_table_replace(account_buddies, hb2, buddy);
+
g_free(buddy->name);
buddy->name = g_strdup(name);
@@ -1433,7 +1476,8 @@ void purple_blist_add_buddy(PurpleBuddy
PurpleGroup *g;
PurpleContact *c;
PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
- struct _purple_hbuddy *hb;
+ struct _purple_hbuddy *hb, *hb2;
+ GHashTable *account_buddies;
g_return_if_fail(buddy != NULL);
g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY((PurpleBlistNode*)buddy));
@@ -1503,6 +1547,10 @@ void purple_blist_add_buddy(PurpleBuddy
hb->account = buddy->account;
hb->group = bnode->parent->parent;
g_hash_table_remove(purplebuddylist->buddies, hb);
+
+ account_buddies = g_hash_table_lookup(buddies_cache, buddy->account);
+ g_hash_table_remove(account_buddies, hb);
+
g_free(hb->name);
g_free(hb);
}
@@ -1549,6 +1597,15 @@ void purple_blist_add_buddy(PurpleBuddy
g_hash_table_replace(purplebuddylist->buddies, hb, buddy);
+ account_buddies = g_hash_table_lookup(buddies_cache, buddy->account);
+
+ hb2 = g_new(struct _purple_hbuddy, 1);
+ hb2->name = g_strdup(hb->name);
+ hb2->account = buddy->account;
+ hb2->group = ((PurpleBlistNode*)buddy)->parent->parent;
+
+ g_hash_table_replace(account_buddies, hb2, buddy);
+
purple_contact_invalidate_priority_buddy(purple_buddy_get_contact(buddy));
purple_blist_schedule_save();
@@ -1707,18 +1764,31 @@ void purple_blist_add_contact(PurpleCont
while (bnode) {
PurpleBlistNode *next_bnode = bnode->next;
PurpleBuddy *b = (PurpleBuddy*)bnode;
+ GHashTable *account_buddies;
- struct _purple_hbuddy *hb = g_new(struct _purple_hbuddy, 1);
+ struct _purple_hbuddy *hb, *hb2;
+
+ hb = g_new(struct _purple_hbuddy, 1);
hb->name = g_strdup(purple_normalize(b->account, b->name));
hb->account = b->account;
hb->group = cnode->parent;
g_hash_table_remove(purplebuddylist->buddies, hb);
+ account_buddies = g_hash_table_lookup(buddies_cache, b->account);
+ g_hash_table_remove(account_buddies, hb);
+
if (!purple_find_buddy_in_group(b->account, b->name, g)) {
hb->group = gnode;
g_hash_table_replace(purplebuddylist->buddies, hb, b);
+ hb2 = g_new(struct _purple_hbuddy, 1);
+ hb2->name = g_strdup(hb->name);
+ hb2->account = b->account;
+ hb2->group = gnode;
+
+ g_hash_table_replace(account_buddies, hb2, b);
+
if (purple_account_get_connection(b->account))
serv_move_buddy(b, (PurpleGroup *)cnode->parent, g);
} else {
@@ -1936,6 +2006,7 @@ void purple_blist_remove_buddy(PurpleBud
PurpleContact *contact;
PurpleGroup *group;
struct _purple_hbuddy hb;
+ GHashTable *account_buddies;
g_return_if_fail(buddy != NULL);
@@ -1982,6 +2053,10 @@ void purple_blist_remove_buddy(PurpleBud
hb.account = buddy->account;
hb.group = gnode;
g_hash_table_remove(purplebuddylist->buddies, &hb);
+
+ account_buddies = g_hash_table_lookup(buddies_cache, buddy->account);
+ g_hash_table_remove(account_buddies, &hb);
+
g_free(hb.name);
/* Update the UI */
@@ -2256,13 +2331,10 @@ static void find_acct_buddies(gpointer k
static void find_acct_buddies(gpointer key, gpointer value, gpointer data)
{
- struct _purple_hbuddy *hb = key;
PurpleBuddy *buddy = value;
- struct _list_account_buddies *ab = data;
+ GSList **list = data;
- if (hb->account == ab->account) {
- ab->list = g_slist_prepend(ab->list, buddy);
- }
+ *list = g_slist_prepend(*list, buddy);
}
GSList *purple_find_buddies(PurpleAccount *account, const char *name)
@@ -2274,7 +2346,6 @@ GSList *purple_find_buddies(PurpleAccoun
g_return_val_if_fail(purplebuddylist != NULL, NULL);
g_return_val_if_fail(account != NULL, NULL);
-
if ((name != NULL) && (*name != '\0')) {
struct _purple_hbuddy hb;
@@ -2288,11 +2359,10 @@ GSList *purple_find_buddies(PurpleAccoun
}
g_free(hb.name);
} else {
- struct _list_account_buddies *ab = g_new0(struct _list_account_buddies, 1);
- ab->account = account;
- g_hash_table_foreach(purplebuddylist->buddies, find_acct_buddies, ab);
- ret = ab->list;
- g_free(ab);
+ GSList *list = NULL;
+ GHashTable *buddies = g_hash_table_lookup(buddies_cache, account);
+ g_hash_table_foreach(buddies, find_acct_buddies, &list);
+ ret = list;
}
return ret;
@@ -2931,6 +3001,16 @@ purple_blist_init(void)
purple_value_new(PURPLE_TYPE_SUBTYPE,
PURPLE_SUBTYPE_BLIST_NODE),
purple_value_new(PURPLE_TYPE_STRING));
+
+ purple_signal_connect(purple_accounts_get_handle(), "account-created",
+ handle,
+ PURPLE_CALLBACK(purple_blist_buddies_cache_add_account),
+ NULL);
+
+ purple_signal_connect(purple_accounts_get_handle(), "account-destroying",
+ handle,
+ PURPLE_CALLBACK(purple_blist_buddies_cache_remove_account),
+ NULL);
}
void
@@ -2951,6 +3031,10 @@ purple_blist_uninit(void)
node = next_node;
}
purplebuddylist->root = NULL;
+
+ g_hash_table_destroy(purplebuddylist->buddies);
+ g_hash_table_destroy(buddies_cache);
+ purple_signals_disconnect_by_handle(purple_blist_get_handle());
purple_signals_unregister_by_instance(purple_blist_get_handle());
}
============================================================
--- libpurple/protocols/oscar/oscar.c e3417606a52adddf004513f448a98fba1a2823f0
+++ libpurple/protocols/oscar/oscar.c c2eb89efb14f60dbcff5483db0e8113d075317bf
@@ -5122,58 +5122,43 @@ static int purple_ssi_parselist(OscarDat
aim_ssi_cleanlist(od);
{ /* If not in server list then prune from local list */
- PurpleBlistNode *gnode, *cnode, *bnode;
- PurpleBuddyList *blist;
GSList *cur, *next;
-
+ GSList *buddies = purple_find_buddies(account, NULL);
+
/* Buddies */
cur = NULL;
- if ((blist = purple_get_blist()) != NULL) {
- for (gnode = purple_blist_get_root(); gnode;
- gnode = purple_blist_node_get_sibling_next(gnode)) {
- const char *gname;
- if(!PURPLE_BLIST_NODE_IS_GROUP(gnode))
- continue;
- g = (PurpleGroup *)gnode;
- gname = purple_group_get_name(g);
- for (cnode = purple_blist_node_get_first_child(gnode);
- cnode;
- cnode = purple_blist_node_get_sibling_next(cnode)) {
- if(!PURPLE_BLIST_NODE_IS_CONTACT(cnode))
- continue;
- for (bnode = purple_blist_node_get_first_child(cnode);
- bnode;
- bnode = purple_blist_node_get_sibling_next(bnode)) {
- const char *bname;
- if(!PURPLE_BLIST_NODE_IS_BUDDY(bnode))
- continue;
- b = (PurpleBuddy *)bnode;
- bname = purple_buddy_get_name(b);
- if (purple_buddy_get_account(b) == account) {
- if (aim_ssi_itemlist_exists(od->ssi.local, bname)) {
- /* If the buddy is an ICQ user then load his nickname */
- const char *servernick = purple_blist_node_get_string((PurpleBlistNode*)b, "servernick");
- char *alias;
- const char *balias;
- if (servernick)
- serv_got_alias(gc, bname, servernick);
- /* Store local alias on server */
- alias = aim_ssi_getalias(od->ssi.local, gname, bname);
- balias = purple_buddy_get_local_buddy_alias(b);
- if (!alias && balias && *balias)
- aim_ssi_aliasbuddy(od, gname, bname, balias);
- g_free(alias);
- } else {
- purple_debug_info("oscar",
- "ssi: removing buddy %s from local list\n", bname);
- /* We can't actually remove now because it will screw up our looping */
- cur = g_slist_prepend(cur, b);
- }
- }
- }
- }
+ while(buddies) {
+ PurpleGroup *g;
+ const char *gname;
+ const char *bname;
+
+ b = buddies->data;
+ g = purple_buddy_get_group(b);
+ gname = purple_group_get_name(g);
+ bname = purple_buddy_get_name(b);
+
+ if (aim_ssi_itemlist_exists(od->ssi.local, bname)) {
+ /* If the buddy is an ICQ user then load his nickname */
+ const char *servernick = purple_blist_node_get_string((PurpleBlistNode*)b, "servernick");
+ char *alias;
+ const char *balias;
+ if (servernick)
+ serv_got_alias(gc, bname, servernick);
+
+ /* Store local alias on server */
+ alias = aim_ssi_getalias(od->ssi.local, gname, bname);
+ balias = purple_buddy_get_local_buddy_alias(b);
+ if (!alias && balias && *balias)
+ aim_ssi_aliasbuddy(od, gname, bname, balias);
+ g_free(alias);
+ } else {
+ purple_debug_info("oscar",
+ "ssi: removing buddy %s from local list\n", bname);
+ /* We can't actually remove now because it will screw up our looping */
+ cur = g_slist_prepend(cur, b);
}
+ buddies = g_slist_delete_link(buddies, buddies);
}
while (cur != NULL) {
More information about the Commits
mailing list