Added aggressive caching for common typeclassed variables.

This commit is contained in:
Griatch 2012-02-25 23:37:50 +01:00
parent b99db98191
commit 1fa5791e19
3 changed files with 56 additions and 69 deletions

View file

@ -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)

View file

@ -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(

View file

@ -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):