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