core: presence status + last resource refactored and kept in entitiesCache in memory.py, profile cache is purged on disconnection

This commit is contained in:
Goffi 2012-08-15 15:50:46 +02:00
commit 8f622601c6
5 changed files with 63 additions and 45 deletions

View file

@ -256,6 +256,7 @@ class SAT(service.Service):
return current.getConnectionDeferred()
self.memory.startProfileSession(profile)
return self.memory.loadIndividualParams(profile).addCallback(afterMemoryInit)
def disconnect(self, profile_key):
@ -290,7 +291,7 @@ class SAT(service.Service):
del self.profiles[profile]
except KeyError:
error(_("Trying to remove reference to a client not referenced"))
self.memory.purgeProfile(profile)
self.memory.purgeProfileSession(profile)
def startService(self):
info("Salut à toi ô mon frère !")

View file

@ -249,7 +249,7 @@ class SatPresenceProtocol(xmppim.PresenceClientProtocol):
statuses["default"] = statuses[None]
del statuses[None]
self.host.memory.addPresenceStatus(entity, show or "",
self.host.memory.setPresenceStatus(entity, show or "",
int(priority), statuses, self.parent.profile)
#now it's time to notify frontends
@ -265,7 +265,7 @@ class SatPresenceProtocol(xmppim.PresenceClientProtocol):
if statuses.has_key(None): #we only want string keys
statuses["default"] = statuses[None]
del statuses[None]
self.host.memory.addPresenceStatus(entity, "unavailable", 0, statuses, self.parent.profile)
self.host.memory.setPresenceStatus(entity, "unavailable", 0, statuses, self.parent.profile)
#now it's time to notify frontends
self.host.bridge.presenceUpdate(entity.full(), "unavailable", 0, statuses, self.parent.profile)

View file

@ -299,7 +299,7 @@ class Params():
d = self.storage.getIndParam(category, name, profile)
return d.addCallback(lambda value: value if value!=None else default)
def __getParam(self, profile, category, name, type='individual', cache=None):
def __getParam(self, profile, category, name, _type='individual', cache=None):
"""Return the param, or None if it doesn't exist
@param profile: the profile name (not profile key, i.e. name and not something like @DEFAULT@)
@param category: param category
@ -308,11 +308,11 @@ class Params():
@param cache: temporary cache, to use when profile is not logged
@return: param value or None if it doesn't exist
"""
if type == 'general':
if _type == 'general':
if self.params_gen.has_key((category, name)):
return self.params_gen[(category, name)]
return None #This general param has the default value
assert (type == 'individual')
assert (_type == 'individual')
if self.params.has_key(profile):
cache = self.params[profile] # if profile is in main cache, we use it,
# ignoring the temporary cache
@ -420,19 +420,19 @@ class Params():
d = self.__constructProfileXml(profile)
return d.addCallback(returnCategoryXml)
def __getParamNode(self, name, category, type="@ALL@"): #FIXME: is type useful ?
def __getParamNode(self, name, category, _type="@ALL@"): #FIXME: is _type useful ?
"""Return a node from the param_xml
@param name: name of the node
@param category: category of the node
@type: keyword for search:
@_type: keyword for search:
@ALL@ search everywhere
@GENERAL@ only search in general type
@INDIVIDUAL@ only search in individual type
@return: a tuple with the node type and the the node, or None if not found"""
for type_node in self.dom.documentElement.childNodes:
if ( ((type == "@ALL@" or type == "@GENERAL@") and type_node.nodeName == 'general')
or ( (type == "@ALL@" or type == "@INDIVIDUAL@") and type_node.nodeName == 'individual') ):
if ( ((_type == "@ALL@" or _type == "@GENERAL@") and type_node.nodeName == 'general')
or ( (_type == "@ALL@" or _type == "@INDIVIDUAL@") and type_node.nodeName == 'individual') ):
for node in type_node.getElementsByTagName('category'):
if node.getAttribute("name") == category:
params = node.getElementsByTagName("param")
@ -475,8 +475,8 @@ class Params():
assert (node[0] == 'individual')
assert (profile_key != "@NONE@")
type = node[1].getAttribute("type")
if type=="button":
_type = node[1].getAttribute("type")
if _type=="button":
print "clique",node.toxml()
else:
if self.host.isConnected(profile): #key can not exists if profile is not connected
@ -491,8 +491,8 @@ class Memory:
info (_("Memory manager init"))
self.initialized = defer.Deferred()
self.host = host
self.presenceStatus={}
self.lastResource={} #tmp, will be refactored with bdd integration
self.entitiesCache={} #XXX: keep presence/last resource/other data in cache
# /!\ an entity is not necessarily in roster
self.subscriptions={}
self.server_features={} #used to store discovery's informations
self.server_identities={}
@ -562,10 +562,22 @@ class Memory:
@param profile: %(doc_profile)s"""
return self.params.loadIndParams(profile)
def purgeProfile(self, profile):
def startProfileSession(self, profile):
""""Iniatialise session for a profile
@param profile: %(doc_profile)s"""
info(_("[%s] Profile session started" % profile))
self.entitiesCache[profile] = {}
def purgeProfileSession(self, profile):
"""Delete cache of data of profile
@param profile: %(doc_profile)s"""
info(_("[%s] Profile session purge" % profile))
self.params.purgeProfile(profile)
try:
del self.entitiesCache[profile]
except KeyError:
error(_("Trying to purge roster status cache for a profile not in memory: [%s]") % profile)
def save(self):
"""Save parameters and all memory things to file/db"""
@ -618,29 +630,29 @@ class Memory:
self.server_features[profile] = []
self.server_features[profile].append(feature)
def addServerIdentity(self, category, type, entity, profile):
def addServerIdentity(self, category, _type, entity, profile):
"""Add an identity discovered from server
@param feature: string of the feature
@param profile: which profile is using this server ?"""
if not self.server_identities.has_key(profile):
self.server_identities[profile] = {}
if not self.server_identities[profile].has_key((category, type)):
self.server_identities[profile][(category, type)]=set()
self.server_identities[profile][(category, type)].add(entity)
if not self.server_identities[profile].has_key((category, _type)):
self.server_identities[profile][(category, _type)]=set()
self.server_identities[profile][(category, _type)].add(entity)
def getServerServiceEntities(self, category, type, profile):
def getServerServiceEntities(self, category, _type, profile):
"""Return all available entities for a service"""
if self.server_identities.has_key(profile):
return self.server_identities[profile].get((category, type), set())
return self.server_identities[profile].get((category, _type), set())
else:
return None
def getServerServiceEntity(self, category, type, profile):
def getServerServiceEntity(self, category, _type, profile):
"""Helper method to get first available entity for a service"""
entities = self.getServerServiceEntities(category, type, profile)
entities = self.getServerServiceEntities(category, _type, profile)
if entities == None:
warning(_("Entities (%(category)s/%(type)s) not available, maybe they haven't been asked to server yet ?") % {"category":category,
"type":type})
"type":_type})
return None
else:
return list(entities)[0] if entities else None
@ -659,38 +671,40 @@ class Memory:
@param contact: contact jid (unicode)
@param profile_key: %(doc_profile_key)s"""
profile = self.getProfileName(profile_key)
if not profile:
error(_('Asking contacts for a non-existant profile'))
if not profile or not self.host.isConnected(profile):
error(_('Asking contacts for a non-existant or not connected profile'))
return ""
entity = jid.JID(contact).userhost()
if not entity in self.entitiesCache[profile]:
info(_("Entity not in cache"))
return ""
try:
return self.lastResource[profile][jid.JID(contact).userhost()]
except:
return self.entitiesCache[profile][entity]["last_resource"]
except KeyError:
return ""
def addPresenceStatus(self, contact_jid, show, priority, statuses, profile_key):
def setPresenceStatus(self, contact_jid, show, priority, statuses, profile_key):
"""Change the presence status of an entity"""
profile = self.getProfileName(profile_key)
if not profile:
error(_('Trying to add presence status to a non-existant profile'))
return
if not self.presenceStatus.has_key(profile):
self.presenceStatus[profile] = {}
if not self.lastResource.has_key(profile):
self.lastResource[profile] = {}
if not self.presenceStatus[profile].has_key(contact_jid.userhost()):
self.presenceStatus[profile][contact_jid.userhost()] = {}
entity_data = self.entitiesCache[profile].setdefault(contact_jid.userhost(),{})
resource = jid.parse(contact_jid.full())[2] or ''
if resource:
self.lastResource[profile][contact_jid.userhost()] = resource
entity_data["last_resource"] = resource
if not "last_resource" in entity_data:
entity_data["last_resource"] = ''
self.presenceStatus[profile][contact_jid.userhost()][resource] = (show, priority, statuses)
entity_data.setdefault("presence",{})[resource] = (show, priority, statuses)
def addWaitingSub(self, type, contact_jid, profile_key):
def addWaitingSub(self, _type, contact_jid, profile_key):
"""Called when a subcription request is received"""
profile = self.getProfileName(profile_key)
assert(profile)
if not self.subscriptions.has_key(profile):
self.subscriptions[profile] = {}
self.subscriptions[profile][contact_jid] = type
self.subscriptions[profile][contact_jid] = _type
def delWaitingSub(self, contact_jid, profile_key):
"""Called when a subcription request is finished"""
@ -715,10 +729,13 @@ class Memory:
if not profile:
error(_('Asking contacts for a non-existant profile'))
return {}
if not self.presenceStatus.has_key(profile):
self.presenceStatus[profile] = {}
debug ("Memory getPresenceStatus (%s)", self.presenceStatus[profile])
return self.presenceStatus[profile]
entities_presence = {}
for entity in self.entitiesCache[profile]:
# if entity exists, "presence" key must exist
entities_presence[entity] = self.entitiesCache[profile][entity]["presence"]
debug ("Memory getPresenceStatus (%s)", entities_presence)
return entities_presence
def getParamA(self, name, category, attr="value", profile_key='@DEFAULT@'):
return self.params.getParamA(name, category, attr, profile_key)

View file

@ -92,7 +92,7 @@ class XEP_0277():
microblog_data['author'] = _entry.authors[0].name.text
microblog_data['timestamp'] = str(int(_entry.updated.tf))
microblog_data['id'] = item['id']
except AttributeError, KeyError:
except (AttributeError, KeyError):
error(_('Error while parsing atom entry for microblogging event'))
return {}

View file

@ -66,7 +66,7 @@ class FakeMemory(object):
def addContact(self, contact_jid, attributes, groups, profile_key='@DEFAULT@'):
pass
def addPresenceStatus(self, contact_jid, show, priority, statuses, profile_key='@DEFAULT@'):
def setPresenceStatus(self, contact_jid, show, priority, statuses, profile_key='@DEFAULT@'):
pass
def addWaitingSub(self, type, contact_jid, profile_key):