Mercurial > libervia-backend
diff src/core/xmpp.py @ 466:448ce3c9e2ac
core: Roster cache refactoring: cache is now managed by client's SatRosterProtocol instance.
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 26 Mar 2012 00:22:49 +0200 |
parents | 4e361d295bca |
children | 47af60767013 |
line wrap: on
line diff
--- a/src/core/xmpp.py Sat Mar 24 17:48:12 2012 +0100 +++ b/src/core/xmpp.py Mon Mar 26 00:22:49 2012 +0200 @@ -120,7 +120,9 @@ def __init__(self, host): xmppim.RosterClientProtocol.__init__(self) self.host = host - self._groups=set() + #XXX: the two following dicts keep a local copy of the roster + self._groups = {} #map from groups to bare jids: key=group value=set of bare jids + self._jids = {} #map from bare jids to RosterItem: key=jid value=RosterItem def rosterCb(self, roster): for raw_jid, item in roster.iteritems(): @@ -157,6 +159,18 @@ for group in roster_item.groups: item.addElement('group', content=group) return iq.send() + + def getAttributes(self, item): + """Return dictionary of attributes as used in bridge from a RosterItem + @param item: RosterItem + @return: dictionary of attributes""" + item_attr = {'to': str(item.subscriptionTo), + 'from': str(item.subscriptionFrom), + 'ask': str(item.ask) + } + if item.name: + item_attr['name'] = item.name + return item_attr def onRosterSet(self, item): """Called when a new/update roster item is received""" @@ -167,26 +181,53 @@ #may change in the future self.removeItem(item.jid) return - item_attr = {'to': str(item.subscriptionTo), - 'from': str(item.subscriptionFrom), - 'ask': str(item.ask) - } - if item.name: - item_attr['name'] = item.name info (_("new contact in roster list: %s"), item.jid.full()) - self.host.memory.addContact(item.jid, item_attr, item.groups, self.parent.profile) - self.host.bridge.newContact(item.jid.full(), item_attr, item.groups, self.parent.profile) - self._groups.update(item.groups) + #self.host.memory.addContact(item.jid, item_attr, item.groups, self.parent.profile) + + bare_jid = item.jid.userhost() + self._jids[bare_jid] = item + for group in item.groups: + self._groups.get(group,set()).add(bare_jid) + self.host.bridge.newContact(item.jid.full(), self.getAttributes(item), item.groups, self.parent.profile) def onRosterRemove(self, entity): """Called when a roster removal event is received""" print _("removing %s from roster list") % entity.full() - self.host.memory.delContact(entity, self.parent.profile) + bare_jid = entity.userhost() + + #we first remove item from local cache (self._groups and self._jids) + try: + item = self._jids.pop(bare_jid) + except KeyError: + log.warning("Received a roster remove event for an item not in cache") + return + for group in item.groups: + try: + jids_set = self._groups[group] + jids_set.remove(bare_jid) + if not jids_set: + del self._groups[group] + except KeyError: + log.warning("there is not cache for the group [%(groups)s] of the removed roster item [%(jid)s]" % + {"group": group, "jid": bare_jid}) + + #then we send the bridge signal self.host.bridge.contactDeleted(entity.userhost(), self.parent.profile) def getGroups(self): - """Return a set of groups""" - return self._groups + """Return a list of groups""" + return self._groups.keys() + + def getItem(self, jid): + """Return RosterItem for a given jid + @param jid: jid of the contact + @return: RosterItem or None if contact is not in cache""" + return self._jids.get(jid.userhost(), None) + + def getItems(self): + """Return all items of the roster""" + return self._jids + class SatPresenceProtocol(xmppim.PresenceClientProtocol): @@ -243,8 +284,8 @@ def subscribed(self, entity): xmppim.PresenceClientProtocol.subscribed(self, entity) self.host.memory.delWaitingSub(entity.userhost(), self.parent.profile) - contact = self.host.memory.getContact(entity, self.parent.profile) - if not contact or contact[0]['to'] == 'False': #we automatically subscribe to 'to' presence + item = self.parent.roster.getItem(entity) + if not item or not item.subscriptionTo: #we automatically subscribe to 'to' presence debug(_('sending automatic "from" subscription request')) self.subscribe(entity) @@ -262,8 +303,8 @@ def subscribeReceived(self, entity): debug (_("subscription request from [%s]") % entity.userhost()) - contact = self.host.memory.getContact(entity, self.parent.profile) - if contact and contact[0]['to'] == 'True': + item = self.parent.roster.getItem(entity) + if item and item.subscriptionTo: #We automatically accept subscription if we are already subscribed to contact presence debug(_('sending automatic subscription acceptance')) self.subscribed(entity) @@ -273,8 +314,8 @@ def unsubscribeReceived(self, entity): debug (_("unsubscription asked for [%s]") % entity.userhost()) - contact = self.host.memory.getContact(entity, self.parent.profile) - if contact and contact[0]['from'] == 'True': #we automatically remove contact + item = self.parent.roster.getItem(entity) + if item and item.subscriptionFrom: #we automatically remove contact debug(_('automatic contact deletion')) self.host.delContact(entity.userhost(), self.parent.profile) self.host.bridge.subscribe('unsubscribe', entity.userhost(), self.parent.profile)