services/presence/presenceservice: weakly reference Buddy objects in _buddies

This makes sure we re-use an existing Buddy object if it's still referenced
somewhere, rather than trying to make another and fighting over the object path.
This commit is contained in:
Simon McVittie 2007-05-30 17:40:31 +01:00
parent fd4e514e21
commit f90de752f6

View File

@ -15,23 +15,24 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import gobject
import logging
from weakref import WeakValueDictionary
import dbus
import dbus.service
import gobject
from dbus.gobject_service import ExportedGObject
from dbus.mainloop.glib import DBusGMainLoop
import logging
from telepathy.client import ManagerRegistry, Connection
from telepathy.interfaces import (CONN_MGR_INTERFACE, CONN_INTERFACE)
from telepathy.constants import (CONNECTION_STATUS_CONNECTING,
CONNECTION_STATUS_CONNECTED,
CONNECTION_STATUS_DISCONNECTED)
from server_plugin import ServerPlugin
from linklocal_plugin import LinkLocalPlugin
from sugar import util
from server_plugin import ServerPlugin
from linklocal_plugin import LinkLocalPlugin
from buddy import Buddy, ShellOwner
from activity import Activity
from psutils import pubkey_to_keyid
@ -65,11 +66,20 @@ class PresenceService(ExportedGObject):
self._next_object_id = 0
self._connected = False
self._buddies = {} # identifier -> Buddy
self._buddies_by_pubkey = {} # base64 public key -> Buddy
self._handles_buddies = {} # tp client -> (handle -> Buddy)
# all Buddy objects
# identifier -> Buddy, GC'd when no more refs exist
self._buddies = WeakValueDictionary()
self._activities = {} # activity id -> Activity
# the online buddies for whom we know the full public key
# base64 public key -> Buddy
self._buddies_by_pubkey = {}
# The online buddies (those who're available via some CM)
# TP plugin -> (handle -> Buddy)
self._handles_buddies = {}
# activity id -> Activity
self._activities = {}
self._session_bus = dbus.SessionBus()
self._session_bus.add_signal_receiver(self._connection_disconnected_cb,
@ -174,11 +184,7 @@ class PresenceService(ExportedGObject):
def _buddy_disappeared_cb(self, buddy):
if buddy.props.valid:
self.BuddyDisappeared(buddy.object_path())
_logger.debug('Buddy left: %s (%s)', buddy.props.nick,
buddy.props.color)
self._buddies_by_pubkey.pop(buddy.props.key, None)
self._buddies.pop(buddy.props.objid, None)
self._buddy_validity_changed_cb(buddy, False)
def _contact_offline(self, tp, handle):
if not self._handles_buddies[tp].has_key(handle):
@ -325,10 +331,18 @@ class PresenceService(ExportedGObject):
@dbus.service.method(_PRESENCE_INTERFACE, in_signature='',
out_signature="ao")
def GetBuddies(self):
ret = []
for buddy in self._buddies.values():
if buddy.props.valid:
ret.append(buddy.object_path())
# in the presence of an out_signature, dbus-python will convert
# this set into an Array automatically (because it's iterable),
# so it's easy to use for uniquification (we want to avoid returning
# buddies who're visible on both Salut and Gabble twice)
# always include myself even if I have no handles
ret = set((self._owner,))
for handles_buddies in self._handles_buddies.itervalues():
for buddy in handles_buddies.itervalues():
if buddy.props.valid:
ret.add(buddy.object_path())
return ret
@dbus.service.method(_PRESENCE_INTERFACE,