mirror of
https://github.com/evennia/evennia.git
synced 2026-03-28 02:36:32 +01:00
Added aggressive caching for common typeclassed variables.
This commit is contained in:
parent
b99db98191
commit
1fa5791e19
3 changed files with 56 additions and 69 deletions
|
|
@ -22,7 +22,8 @@ except ImportError:
|
|||
from twisted.protocols import amp
|
||||
from twisted.internet import protocol, defer
|
||||
from django.conf import settings
|
||||
from src.utils import utils
|
||||
from src.utils.utils import to_str
|
||||
|
||||
from src.server.models import ServerConfig
|
||||
from src.scripts.models import ScriptDB
|
||||
from src.players.models import PlayerDB
|
||||
|
|
@ -77,8 +78,6 @@ class AmpServerFactory(protocol.ServerFactory):
|
|||
self.server.amp_protocol.factory = self
|
||||
return self.server.amp_protocol
|
||||
|
||||
|
||||
|
||||
class AmpClientFactory(protocol.ReconnectingClientFactory):
|
||||
"""
|
||||
This factory creates new AMPProtocol protocol instances to use to connect
|
||||
|
|
@ -193,8 +192,8 @@ class PortalAdmin(amp.Command):
|
|||
errors = [(Exception, 'EXCEPTION')]
|
||||
response = []
|
||||
|
||||
dumps = lambda data: utils.to_str(pickle.dumps(data, pickle.HIGHEST_PROTOCOL))
|
||||
loads = lambda data: pickle.loads(utils.to_str(data))
|
||||
dumps = lambda data: to_str(pickle.dumps(data, pickle.HIGHEST_PROTOCOL))
|
||||
loads = lambda data: pickle.loads(to_str(data))
|
||||
|
||||
#------------------------------------------------------------
|
||||
# Core AMP protocol for communication Server <-> Portal
|
||||
|
|
@ -279,7 +278,7 @@ class AMPProtocol(amp.AMP):
|
|||
#print "msg server->portal (server side):", sessid, msg, data
|
||||
self.callRemote(MsgServer2Portal,
|
||||
sessid=sessid,
|
||||
msg=utils.to_str(msg),
|
||||
msg=to_str(msg),
|
||||
data=dumps(data)).addErrback(self.errback, "OOBServer2Portal")
|
||||
|
||||
# OOB Portal -> Server
|
||||
|
|
@ -367,7 +366,7 @@ class AMPProtocol(amp.AMP):
|
|||
sesslist.append(sess)
|
||||
# replace sessions on server
|
||||
server_sessionhandler.portal_session_sync(sesslist)
|
||||
# after sync is complete we force-validate all scripts (this starts everthing)
|
||||
# after sync is complete we force-validate all scripts (this starts everything)
|
||||
init_mode = ServerConfig.objects.conf("server_restart_mode", default=None)
|
||||
ScriptDB.objects.validate(init_mode=init_mode)
|
||||
ServerConfig.objects.conf("server_restart_mode", delete=True)
|
||||
|
|
|
|||
|
|
@ -52,17 +52,14 @@ DA = object.__delattr__
|
|||
PLOADS = pickle.loads
|
||||
PDUMPS = pickle.dumps
|
||||
|
||||
|
||||
# # used by Attribute to efficiently identify stored object types.
|
||||
# # Note that these have to be updated if directory structure changes.
|
||||
# PARENTS = {
|
||||
# "typeclass":"src.typeclasses.typeclass.TypeClass",
|
||||
# "objectdb":"src.objects.models.ObjectDB",
|
||||
# "playerdb":"src.players.models.PlayerDB",
|
||||
# "scriptdb":"src.scripts.models.ScriptDB",
|
||||
# "msg":"src.comms.models.Msg",
|
||||
# "channel":"src.comms.models.Channel",
|
||||
# "helpentry":"src.help.models.HelpEntry"}
|
||||
def get_cache(obj, name):
|
||||
"On-model Cache handler."
|
||||
try:
|
||||
return GA(obj, "_cached_db_%s" % name)
|
||||
except AttributeError:
|
||||
val = GA(obj, "db_%s" % name)
|
||||
SA(obj, "_cached_db_%s" % name, val)
|
||||
return val
|
||||
|
||||
#------------------------------------------------------------
|
||||
#
|
||||
|
|
@ -280,8 +277,8 @@ class Attribute(SharedMemoryModel):
|
|||
# key property (wraps db_key)
|
||||
#@property
|
||||
def key_get(self):
|
||||
"Getter. Allows for value = self.key"
|
||||
return self.db_key
|
||||
"Getter. Allows for value = self.key"
|
||||
return get_cache(self, "key")
|
||||
#@key.setter
|
||||
def key_set(self, value):
|
||||
"Setter. Allows for self.key = value"
|
||||
|
|
@ -297,7 +294,7 @@ class Attribute(SharedMemoryModel):
|
|||
#@property
|
||||
def obj_get(self):
|
||||
"Getter. Allows for value = self.obj"
|
||||
return self.db_obj
|
||||
return get_cache(self, "db_obj")
|
||||
#@obj.setter
|
||||
def obj_set(self, value):
|
||||
"Setter. Allows for self.obj = value"
|
||||
|
|
@ -314,7 +311,7 @@ class Attribute(SharedMemoryModel):
|
|||
#@property
|
||||
def date_created_get(self):
|
||||
"Getter. Allows for value = self.date_created"
|
||||
return self.db_date_created
|
||||
return get_cache(self, "db_date_created")
|
||||
#@date_created.setter
|
||||
def date_created_set(self, value):
|
||||
"Setter. Allows for self.date_created = value"
|
||||
|
|
@ -364,7 +361,7 @@ class Attribute(SharedMemoryModel):
|
|||
#@property
|
||||
def lock_storage_get(self):
|
||||
"Getter. Allows for value = self.lock_storage"
|
||||
return self.db_lock_storage
|
||||
return get_cache(self, "lock_storage")
|
||||
#@lock_storage.setter
|
||||
def lock_storage_set(self, value):
|
||||
"""Saves the lock_storage. This is usually not called directly, but through self.lock()"""
|
||||
|
|
@ -669,8 +666,7 @@ class TypedObject(SharedMemoryModel):
|
|||
objects = managers.TypedObjectManager()
|
||||
|
||||
# object cache and flags
|
||||
cached_typeclass_path = ""
|
||||
cached_typeclass = None
|
||||
_cached_typeclass = None
|
||||
|
||||
# lock handler self.locks
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
|
@ -698,12 +694,12 @@ class TypedObject(SharedMemoryModel):
|
|||
#@property
|
||||
def key_get(self):
|
||||
"Getter. Allows for value = self.key"
|
||||
return self.db_key
|
||||
return get_cache(self, "key")
|
||||
#@key.setter
|
||||
def key_set(self, value):
|
||||
"Setter. Allows for self.key = value"
|
||||
self.db_key = value
|
||||
self.save()
|
||||
SA(self, "db_key", value)
|
||||
GA(self, "save")()
|
||||
#@key.deleter
|
||||
def key_del(self):
|
||||
"Deleter. Allows for del self.key"
|
||||
|
|
@ -714,12 +710,12 @@ class TypedObject(SharedMemoryModel):
|
|||
#@property
|
||||
def name_get(self):
|
||||
"Getter. Allows for value = self.name"
|
||||
return self.db_key
|
||||
return get_cache(self, "key")
|
||||
#@name.setter
|
||||
def name_set(self, value):
|
||||
"Setter. Allows for self.name = value"
|
||||
self.db_key = value
|
||||
self.save()
|
||||
SA(self, "db_key", value)
|
||||
GA(self, "save")()
|
||||
#@name.deleter
|
||||
def name_del(self):
|
||||
"Deleter. Allows for del self.name"
|
||||
|
|
@ -729,30 +725,27 @@ class TypedObject(SharedMemoryModel):
|
|||
# typeclass_path property
|
||||
#@property
|
||||
def typeclass_path_get(self):
|
||||
"Getter. Allows for value = self.typeclass_path"
|
||||
typeclass_path = GA(self, 'cached_typeclass_path')
|
||||
if typeclass_path:
|
||||
return typeclass_path
|
||||
return self.db_typeclass_path
|
||||
"Getter. Allows for value = self.typeclass_path"
|
||||
return get_cache(self, "typeclass_path")
|
||||
#@typeclass_path.setter
|
||||
def typeclass_path_set(self, value):
|
||||
"Setter. Allows for self.typeclass_path = value"
|
||||
self.db_typeclass_path = value
|
||||
self.save()
|
||||
SA(self, 'cached_typeclass_path', value)
|
||||
SA(self, '_cached_db_typeclass_path', value)
|
||||
#@typeclass_path.deleter
|
||||
def typeclass_path_del(self):
|
||||
"Deleter. Allows for del self.typeclass_path"
|
||||
self.db_typeclass_path = ""
|
||||
self.save()
|
||||
self.cached_typeclass_path = ""
|
||||
DA(self, "_cached_db_typeclass_path")
|
||||
typeclass_path = property(typeclass_path_get, typeclass_path_set, typeclass_path_del)
|
||||
|
||||
# date_created property
|
||||
#@property
|
||||
def date_created_get(self):
|
||||
"Getter. Allows for value = self.date_created"
|
||||
return self.db_date_created
|
||||
return get_cache(self, "date_created")
|
||||
#@date_created.setter
|
||||
def date_created_set(self, value):
|
||||
"Setter. Allows for self.date_created = value"
|
||||
|
|
@ -767,8 +760,9 @@ class TypedObject(SharedMemoryModel):
|
|||
#@property
|
||||
def permissions_get(self):
|
||||
"Getter. Allows for value = self.name. Returns a list of permissions."
|
||||
if self.db_permissions:
|
||||
return [perm.strip() for perm in self.db_permissions.split(',')]
|
||||
perms = get_cache(self, "permissions")
|
||||
if perms:
|
||||
return [perm.strip() for perm in perms.split(',')]
|
||||
return []
|
||||
#@permissions.setter
|
||||
def permissions_set(self, value):
|
||||
|
|
@ -788,7 +782,7 @@ class TypedObject(SharedMemoryModel):
|
|||
#@property
|
||||
def lock_storage_get(self):
|
||||
"Getter. Allows for value = self.lock_storage"
|
||||
return self.db_lock_storage
|
||||
return get_cache(self, "lock_storage")
|
||||
#@lock_storage.setter
|
||||
def lock_storage_set(self, value):
|
||||
"""Saves the lock_storagetodate. This is usually not called directly, but through self.lock()"""
|
||||
|
|
@ -808,10 +802,7 @@ class TypedObject(SharedMemoryModel):
|
|||
#
|
||||
#
|
||||
|
||||
# Each subclass should set this property to their respective
|
||||
# attribute model (ObjAttribute, PlayerAttribute etc).
|
||||
#attribute_model_path = "src.typeclasses.models"
|
||||
#attribute_model_name = "Attribute"
|
||||
# these are identifiers for fast Attribute access and caching
|
||||
typeclass_paths = settings.OBJECT_TYPECLASS_PATHS
|
||||
attribute_class = Attribute # replaced by relevant attribute class for child
|
||||
db_model_name = "typeclass" # used by attributes to safely store objects
|
||||
|
|
@ -853,7 +844,7 @@ class TypedObject(SharedMemoryModel):
|
|||
Alternetively, use obj.id directly to get dbref
|
||||
without any #.
|
||||
"""
|
||||
return "#%s" % str(self.id)
|
||||
return "#%s" % str(GA(self, "id"))
|
||||
dbref = property(dbref_get)
|
||||
|
||||
# typeclass property
|
||||
|
|
@ -871,10 +862,8 @@ class TypedObject(SharedMemoryModel):
|
|||
the custom self.__getattribute__ more than necessary.
|
||||
"""
|
||||
|
||||
path = GA(self, "cached_typeclass_path")
|
||||
if not path:
|
||||
path = GA(self, 'db_typeclass_path')
|
||||
typeclass = GA(self, "cached_typeclass")
|
||||
path = GA(self, "typeclass_path")
|
||||
typeclass = GA(self, "_cached_typeclass")
|
||||
try:
|
||||
if typeclass and GA(typeclass, "path") == path:
|
||||
# don't call at_init() when returning from cache
|
||||
|
|
@ -901,9 +890,9 @@ class TypedObject(SharedMemoryModel):
|
|||
# we succeeded to import. Cache and return.
|
||||
SA(self, 'db_typeclass_path', tpath)
|
||||
GA(self, 'save')()
|
||||
SA(self, "cached_typeclass_path", tpath)
|
||||
SA(self, "_cached_db_typeclass_path", tpath)
|
||||
typeclass = typeclass(self)
|
||||
SA(self, "cached_typeclass", typeclass)
|
||||
SA(self, "_cached_typeclass", typeclass)
|
||||
try:
|
||||
typeclass.at_init()
|
||||
except Exception:
|
||||
|
|
@ -1017,9 +1006,9 @@ class TypedObject(SharedMemoryModel):
|
|||
SA(self, 'db_typeclass_path', defpath)
|
||||
GA(self, 'save')()
|
||||
if cache:
|
||||
SA(self, "cached_typeclass_path", defpath)
|
||||
SA(self, "_cached_db_typeclass_path", defpath)
|
||||
|
||||
SA(self, "cached_typeclass", typeclass)
|
||||
SA(self, "_cached_typeclass", typeclass)
|
||||
try:
|
||||
typeclass.at_init()
|
||||
except Exception:
|
||||
|
|
@ -1040,17 +1029,17 @@ class TypedObject(SharedMemoryModel):
|
|||
parents.
|
||||
"""
|
||||
try:
|
||||
typeclass = typeclass.path
|
||||
typeclass = GA(typeclass, "path")
|
||||
except AttributeError:
|
||||
pass
|
||||
typeclasses = [typeclass] + ["%s.%s" % (path, typeclass) for path in self.typeclass_paths]
|
||||
typeclasses = [typeclass] + ["%s.%s" % (path, typeclass) for path in GA(self, "typeclass_paths")]
|
||||
if exact:
|
||||
current_path = GA(self, "cached_typeclass_path")
|
||||
return typeclass and any([current_path == typec for typec in typeclasses])
|
||||
current_path = GA(self, "_cached_db_typeclass_path")
|
||||
return typeclass and any((current_path == typec for typec in typeclasses))
|
||||
else:
|
||||
# check parent chain
|
||||
return any([cls for cls in self.typeclass.__class__.mro()
|
||||
if any(["%s.%s" % (cls.__module__, cls.__name__) == typec for typec in typeclasses])])
|
||||
return any((cls for cls in self.typeclass.__class__.mro()
|
||||
if any(("%s.%s" % (GA(cls,"__module__"), GA(cls,"__name__")) == typec for typec in typeclasses))))
|
||||
|
||||
#
|
||||
# Object manipulation methods
|
||||
|
|
@ -1101,13 +1090,13 @@ class TypedObject(SharedMemoryModel):
|
|||
new_typeclass = self.typeclass
|
||||
if self.typeclass_path == new_typeclass.path:
|
||||
# the typeclass loading worked as expected
|
||||
self.cached_typeclass_path = None
|
||||
self.cached_typeclass = None
|
||||
SA(self, "_cached_db_typeclass_path", None)
|
||||
SA(self, "_cached_typeclass", None)
|
||||
elif no_default:
|
||||
# something went wrong; the default was loaded instead,
|
||||
# and we don't allow that; instead we return to previous.
|
||||
self.typeclass_path = old_typeclass_path
|
||||
self.cached_typeclass = None
|
||||
SA(self, "typeclass_path", old_typeclass_path)
|
||||
SA(self, "_cached_typeclass", None)
|
||||
return False
|
||||
|
||||
if clean_attributes:
|
||||
|
|
@ -1147,7 +1136,7 @@ class TypedObject(SharedMemoryModel):
|
|||
|
||||
attribute_name: (str) The attribute's name.
|
||||
"""
|
||||
return self.attribute_class.objects.filter(db_obj=self).filter(
|
||||
return GA(self, "attribute_class").objects.filter(db_obj=self).filter(
|
||||
db_key__iexact=attribute_name).count()
|
||||
|
||||
def set_attribute(self, attribute_name, new_value=None):
|
||||
|
|
@ -1160,7 +1149,7 @@ class TypedObject(SharedMemoryModel):
|
|||
a str, the object will be stored as a pickle.
|
||||
"""
|
||||
attrib_obj = None
|
||||
attrclass = self.attribute_class
|
||||
attrclass = GA(self, "attribute_class")
|
||||
try:
|
||||
# use old attribute
|
||||
attrib_obj = attrclass.objects.filter(
|
||||
|
|
|
|||
|
|
@ -26,8 +26,7 @@ def is_iter(iterable):
|
|||
|
||||
def make_iter(obj):
|
||||
"Makes sure that the object is always iterable."
|
||||
if not hasattr(iterable, '__iter__'):
|
||||
return [obj]
|
||||
if not hasattr(obj, '__iter__'): return [obj]
|
||||
return obj
|
||||
|
||||
def fill(text, width=78, indent=0):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue