Made the contents cache mechanism use the idmapper cache directly. This should hopefully avoid isses like #745 in the future.

This commit is contained in:
Griatch 2015-05-14 17:57:49 +02:00
parent 30e9bfddf9
commit 3410499313
6 changed files with 51 additions and 35 deletions

View file

@ -1136,7 +1136,7 @@ class CmdName(ObjManipCommand):
astring = " (%s)" % (", ".join(aliases))
# fix for exits - we need their exit-command to change name too
if obj.destination:
obj.flush_from_cache()
obj.flush_from_cache(force=True)
caller.msg("Object's name changed to '%s'%s." % (newname, astring))

View file

@ -42,7 +42,8 @@ class ContentsHandler(object):
"""
self.obj = obj
self._cache = {}
self._pkcache = {}
self._idcache = obj.__class__.__instance_cache__
self.init()
def init(self):
@ -50,7 +51,7 @@ class ContentsHandler(object):
Re-initialize the content cache
"""
self._cache.update(dict((obj.pk, obj) for obj in
self._pkcache.update(dict((obj.pk, None) for obj in
ObjectDB.objects.filter(db_location=self.obj)))
def get(self, exclude=None):
@ -64,10 +65,16 @@ class ContentsHandler(object):
objects (list): the Objects inside this location
"""
pks = self._pkcache.keys()
if exclude:
exclude = [excl.pk for excl in make_iter(exclude)]
return [obj for key, obj in self._cache.items() if key not in exclude]
return self._cache.values()
pks = [pk for pk in pks if pk not in [excl.pk for excl in make_iter(exclude)]]
try:
return [self._idcache[pk] for pk in pks]
except KeyError:
# this can happen if the idmapper cache was cleared for an object
# in the contents cache. If so we need to re-initialize and try again.
self.init()
return self.get(exclude=exclude)
def add(self, obj):
"""
@ -77,7 +84,7 @@ class ContentsHandler(object):
obj (Object): object to add
"""
self._cache[obj.pk] = obj
self._pkcache[obj.pk] = None
def remove(self, obj):
"""
@ -87,14 +94,14 @@ class ContentsHandler(object):
obj (Object): object to remove
"""
self._cache.pop(obj.pk, None)
self._pkcache.pop(obj.pk, None)
def clear(self):
"""
Clear the contents cache and re-initialize
"""
self._cache = {}
self._pkcache = {}
self._init()
#------------------------------------------------------------

View file

@ -1524,6 +1524,7 @@ class DefaultExit(DefaultObject):
exit_cmdset.add(cmd)
return exit_cmdset
# Command hooks
def basetype_setup(self):
"""
@ -1562,6 +1563,13 @@ class DefaultExit(DefaultObject):
# we are resetting, or no exit-cmdset was set. Create one dynamically.
self.cmdset.add_default(self.create_exit_cmdset(self), permanent=False)
def at_init(self):
"""
This is called when this objects is re-loaded from cache. When
that happens, we make sure to remove any old _exitset cmdset
(this most commonly occurs when renaming an existing exit)
"""
self.cmdset.remove_default()
def at_traverse(self, traversing_object, target_location):
"""

View file

@ -245,16 +245,16 @@ def c_moves_s(client):
# #(0.1, c_creates_button),
# #(0.4, c_moves))
# "inactive player" definition
ACTIONS = (c_login_nodig,
c_logout,
(1.0, c_idles))
#ACTIONS = (c_login_nodig,
# c_logout,
# (1.0, c_idles))
## "normal player" definition
#ACTIONS = ( c_login,
# c_logout,
# (0.01, c_digs),
# (0.39, c_looks),
# (0.2, c_help),
# (0.4, c_moves))
ACTIONS = ( c_login,
c_logout,
(0.01, c_digs),
(0.39, c_looks),
(0.2, c_help),
(0.4, c_moves))
# walking tester. This requires a pre-made
# "loop" of multiple rooms that ties back
# to limbo (using @tunnel and @open)

View file

@ -528,13 +528,13 @@ class TypedObject(SharedMemoryModel):
# Memory management
#
def flush_from_cache(self):
"""
Flush this object instance from cache, forcing an object reload.
Note that this will kill all temporary attributes on this object
since it will be recreated as a new Typeclass instance.
"""
self.__class__.flush_cached_instance(self)
#def flush_from_cache(self):
# """
# Flush this object instance from cache, forcing an object reload.
# Note that this will kill all temporary attributes on this object
# since it will be recreated as a new Typeclass instance.
# """
# self.__class__.flush_cached_instance(self)
#
# Attribute storage

View file

@ -17,7 +17,7 @@ from django.db.models.signals import post_save
from django.db.models.base import Model, ModelBase
from django.db.models.signals import pre_delete, post_syncdb
from evennia.utils import logger
from evennia.utils.utils import dbref, get_evennia_pids, to_str
from evennia.utils.utils import dbref, get_evennia_pids, to_str,calledby
from manager import SharedMemoryManager
@ -59,10 +59,12 @@ class SharedMemoryModelBase(ModelBase):
instance_key = cls._get_cache_key(args, kwargs)
# depending on the arguments, we might not be able to infer the PK, so in that case we create a new instance
#print "SharedMemoryModelBase.__call__ 1: calledby:", calledby(3)
#print "SharedMemoryModelBase.__call__ 2: instance_key:", instance_key
if instance_key is None:
return new_instance()
cached_instance = cls.get_cached_instance(instance_key)
#print "SharedMemoryModelBase.__call__ 3: cached_instance:", cached_instance
if cached_instance is None:
cached_instance = new_instance()
cls.cache_instance(cached_instance, new=True)
@ -242,9 +244,6 @@ class SharedMemoryModel(Model):
# if the pk value happens to be a model instance (which can happen wich a FK), we'd rather use its own pk as the key
result = result._get_pk_val()
return result
#_get_cache_key = classmethod(_get_cache_key)
@classmethod
def get_cached_instance(cls, id):
@ -264,11 +263,12 @@ class SharedMemoryModel(Model):
instance (Class instance): the instance to cache.
new (bool, optional): this is the first time this
instance is cached (i.e. this is not an update
operation).
operation like after a db save).
"""
if instance._get_pk_val() is not None:
cls.__dbclass__.__instance_cache__[instance._get_pk_val()] = instance
pk = instance._get_pk_val()
if pk is not None:
cls.__dbclass__.__instance_cache__[pk] = instance
if new:
try:
# trigger the at_init hook only
@ -327,8 +327,9 @@ class SharedMemoryModel(Model):
Flush this instance from the instance cache. Use
`force` to override recache_protection for the object.
"""
if self.pk and (force or not self._idmapper_recache_protection):
self.__class__.__dbclass__.__instance_cache__.pop(self.pk, None)
pk = self._get_pk_val()
if pk and (force or not self._idmapper_recache_protection):
self.__class__.__dbclass__.__instance_cache__.pop(pk, None)
def set_recache_protection(self, mode=True):
"""