# HG changeset patch # User Goffi # Date 1424793693 -3600 # Node ID 6dbeb2ef966c654a42c2e762ab55cb4a9429cba4 # Parent 91e72da1d093af857fe9ad1a91b0b7a6a30162fe plugin XEP-0054: "nick" is now keeped in cache: - cache now manage different kind of data (instead of only avatar) - PeristentBinaryDict is used to keep cache (because we now store a dict, not just strings) - CACHED_DATA is a set of data kept in cache (only nick and avatar so far) - a signal update flag is put on "nick" - data in cache are reset if they are not present in cache (this avoid to keep the old value) diff -r 91e72da1d093 -r 6dbeb2ef966c src/plugins/plugin_xep_0054.py --- a/src/plugins/plugin_xep_0054.py Tue Feb 24 16:54:28 2015 +0100 +++ b/src/plugins/plugin_xep_0054.py Tue Feb 24 17:01:33 2015 +0100 @@ -36,7 +36,7 @@ from base64 import b64decode, b64encode from hashlib import sha1 from sat.core import exceptions -from sat.memory.persistent import PersistentDict +from sat.memory import persistent from PIL import Image from cStringIO import StringIO @@ -56,6 +56,8 @@ NS_VCARD_UPDATE = 'vcard-temp:x:update' VCARD_UPDATE = PRESENCE + '/x[@xmlns="' + NS_VCARD_UPDATE + '"]' +CACHED_DATA = {'avatar', 'nick'} + PLUGIN_INFO = { "name": "XEP 0054 Plugin", "import_name": "XEP-0054", @@ -79,20 +81,21 @@ self.avatar_path = os.path.join(self.host.memory.getConfig('', 'local_dir'), AVATAR_PATH) if not os.path.exists(self.avatar_path): os.makedirs(self.avatar_path) - self.avatars_cache = {} + self.cache = {} host.bridge.addMethod("getCard", ".plugin", in_sign='ss', out_sign='s', method=self._getCard) host.bridge.addMethod("getAvatarFile", ".plugin", in_sign='s', out_sign='s', method=self.getAvatarFile) host.bridge.addMethod("setAvatar", ".plugin", in_sign='ss', out_sign='', method=self.setAvatar, async=True) host.trigger.add("presence_available", self.presenceTrigger) host.memory.setSignalOnUpdate("avatar") + host.memory.setSignalOnUpdate("nick") def getHandler(self, profile): return XEP_0054_handler(self) def presenceTrigger(self, presence_elt, client): - if client.jid.userhost() in self.avatars_cache[client.profile]: + if client.jid.userhost() in self.cache[client.profile]: x_elt = domish.Element((NS_VCARD_UPDATE, 'x')) - x_elt.addElement('photo', content=self.avatars_cache[client.profile][client.jid.userhost()]) + x_elt.addElement('photo', content=self.cache[client.profile][client.jid.userhost()]['avatar']) presence_elt.addChild(x_elt) return True @@ -102,19 +105,23 @@ # the current naive approach keeps a map between all jids of all profiles # in persistent cache, then put avatar # hashs in memory. Hashed should be shared between profiles - for jid_s, avatar_hash in self.avatars_cache[profile].iteritems(): + for jid_s, data in self.cache[profile].iteritems(): jid_ = jid.JID(jid_s) - self.host.memory.updateEntityData(jid_, "avatar", avatar_hash, silent=True, profile_key=profile) + for name in CACHED_DATA: + try: + self.host.memory.updateEntityData(jid_, name, data[name], silent=True, profile_key=profile) + except KeyError: + pass @defer.inlineCallbacks def profileConnecting(self, profile): - self.avatars_cache[profile] = PersistentDict(NS_VCARD, profile) - yield self.avatars_cache[profile].load() + self.cache[profile] = persistent.PersistentBinaryDict(NS_VCARD, profile) + yield self.cache[profile].load() self._fillCachedValues(profile) def profileDisconnected(self, profile): log.debug(u"Deleting profile cache for avatars") - del self.avatars_cache[profile] + del self.cache[profile] def updateCache(self, jid_, name, value, profile): """update cache value @@ -127,8 +134,10 @@ """ assert not jid_.resource # VCard are retrieved with bare jid self.host.memory.updateEntityData(jid_, name, value, profile_key=profile) - if name == "avatar": - self.avatars_cache[profile][jid_.userhost()] = value + if name in CACHED_DATA: + jid_s = jid_.userhost() + self.cache[profile].setdefault(jid_s, {})[name] = value + self.cache[profile].force(jid_s) def getCache(self, entity_jid, name, profile): """return cached value for jid @@ -205,6 +214,13 @@ else: log.info(_('FIXME: [%s] VCard tag is not managed yet') % elem.name) + # if a data in cache doesn't exist anymore, we need to reset it + # so we check CACHED_DATA no gotten (i.e. not in dictionary keys) + # and we reset them + for datum in CACHED_DATA.difference(dictionary.keys()): + log.debug(u"reseting vcard datum [{datum}] for {entity}".format(datum=datum, entity=target.full())) + self.updateCache(target, datum, '', profile) + defer.returnValue(dictionary) def _VCardCb(self, answer, profile):