Added fix to object.contents cache as well as reworked the extent of cache hooks on location modification.
This commit is contained in:
parent
07af616b67
commit
06a0bea8d6
11 changed files with 125 additions and 653 deletions
|
|
@ -145,265 +145,14 @@ class ObjectDB(TypedObject):
|
|||
_SA(self, "aliases", AliasHandler(self, category_prefix="object_"))
|
||||
_SA(self, "nicks", NickHandler(self))
|
||||
# make sure to sync the contents cache when initializing
|
||||
_GA(self, "contents_update")()
|
||||
#_GA(self, "contents_update")()
|
||||
|
||||
# Wrapper properties to easily set database fields. These are
|
||||
# @property decorators that allows to access these fields using
|
||||
# normal python operations (without having to remember to save()
|
||||
# etc). So e.g. a property 'attr' has a get/set/del decorator
|
||||
# defined that allows the user to do self.attr = value,
|
||||
# value = self.attr and del self.attr respectively (where self
|
||||
# is the object in question).
|
||||
|
||||
|
||||
## player property (wraps db_player)
|
||||
##@property
|
||||
#def __player_get(self):
|
||||
# """
|
||||
# Getter. Allows for value = self.player.
|
||||
# We have to be careful here since Player is also
|
||||
# a TypedObject, so as to not create a loop.
|
||||
# """
|
||||
# player = _GA(self, "db_player")
|
||||
# #player = get_field_cache(self, "player")
|
||||
# if player:
|
||||
# try:
|
||||
# return player.typeclass
|
||||
# except Exception,e:
|
||||
# print "player_get:", e
|
||||
# return player
|
||||
|
||||
##@player.setter
|
||||
#def __player_set(self, player):
|
||||
# "Setter. Allows for self.player = value"
|
||||
# if inherits_from(player, TypeClass):
|
||||
# player = player.dbobj
|
||||
# _SA(self, "db_player", player)
|
||||
# _GA(self, "save")()
|
||||
# #set_field_cache(self, "player", player)
|
||||
# # we must set this here or superusers won't be able to
|
||||
# # bypass lockchecks unless they start the game connected
|
||||
# # to the character in question.
|
||||
# self.locks.cache_lock_bypass(self)
|
||||
|
||||
##@player.deleter
|
||||
#def __player_del(self):
|
||||
# "Deleter. Allows for del self.player"
|
||||
# _SA(self, "db_player", None)
|
||||
# _GA(self, "save")()
|
||||
# #del_field_cache(self, "player")
|
||||
#player = property(__player_get, __player_set, __player_del)
|
||||
|
||||
#sessid property (wraps db_sessid)
|
||||
#@property
|
||||
#def __sessid_get(self):
|
||||
# """
|
||||
# Getter. Allows for value = self.sessid. Since sessid
|
||||
# is directly related to self.player, we cannot have
|
||||
# a sessid without a player being connected (but the
|
||||
# opposite could be true).
|
||||
# """
|
||||
# return _GA(self, "db_sessid")
|
||||
# #if not get_field_cache(self, "sessid"):
|
||||
# # del_field_cache(self, "sessid")
|
||||
# #return get_field_cache(self, "sessid")
|
||||
##@sessid.setter
|
||||
#def __sessid_set(self, sessid):
|
||||
# "Setter. Allows for self.player = value"
|
||||
# _SA(self, "db_sessid", sessid)
|
||||
# _GA(self, "save")()
|
||||
# #set_field_cache(self, "sessid", sessid)
|
||||
##@sessid.deleter
|
||||
#def __sessid_del(self):
|
||||
# "Deleter. Allows for del self.player"
|
||||
# _SA(self, "db_sessid", None)
|
||||
# _GA(self, "save")()
|
||||
# #del_field_cache(self, "sessid")
|
||||
#sessid = property(__sessid_get, __sessid_set, __sessid_del)
|
||||
|
||||
def _at_db_player_save(self, new_value, old_value=None):
|
||||
def _at_db_player_presave(self):
|
||||
"""
|
||||
This is called automatically just before a new player is saved.
|
||||
This hook is called automatically just before the player field is saved.
|
||||
"""
|
||||
# we need to re-cache this for superusers to bypass.
|
||||
self.locks.cache_lock_bypass(self)
|
||||
return new_value
|
||||
|
||||
def _at_db_location_save(self, new_value, old_value=None):
|
||||
"""
|
||||
This is called automatically just before a new location is saved.
|
||||
"""
|
||||
loc = new_value
|
||||
try:
|
||||
old_loc = old_value
|
||||
# recursive location check
|
||||
def is_loc_loop(loc, depth=0):
|
||||
"Recursively traverse the target location to make sure we are not in it."
|
||||
if depth > 10: return
|
||||
elif loc == self: raise RuntimeError
|
||||
elif loc == None: raise RuntimeWarning # just to quickly get out
|
||||
return is_loc_loop(_GA(loc, "db_location"), depth+1)
|
||||
# check so we don't create a location loop - if so, RuntimeError will be raised.
|
||||
try: is_loc_loop(loc)
|
||||
except RuntimeWarning: pass
|
||||
|
||||
# update the contents of each location
|
||||
if old_loc:
|
||||
_GA(_GA(old_loc, "dbobj"), "contents_update")()
|
||||
#print "after contents_update for old_loc:", old_loc.key, old_loc.contents
|
||||
if loc:
|
||||
_GA(_GA(loc, "dbobj"), "contents_update")()
|
||||
#print "after contents_update for loc:", loc.key, loc.contents
|
||||
return loc
|
||||
except RuntimeError:
|
||||
string = "Cannot set location, "
|
||||
string += "%s.location = %s would create a location-loop." % (self.key, loc)
|
||||
_GA(self, "msg")(_(string))
|
||||
logger.log_trace(string)
|
||||
raise RuntimeError(string)
|
||||
except Exception, e:
|
||||
string = "Cannot set location (%s): " % str(e)
|
||||
string += "%s is not a valid location." % loc
|
||||
_GA(self, "msg")(_(string))
|
||||
logger.log_trace(string)
|
||||
raise Exception(string)
|
||||
|
||||
## location property (wraps db_location)
|
||||
##@property
|
||||
#def __location_get(self):
|
||||
# "Getter. Allows for value = self.location."
|
||||
# loc = get_field_cache(self, "location")
|
||||
# if loc:
|
||||
# return _GA(loc, "typeclass")
|
||||
# return None
|
||||
##@location.setter
|
||||
#def __location_set(self, location):
|
||||
# "Setter. Allows for self.location = location"
|
||||
# try:
|
||||
# old_loc = _GA(self, "location")
|
||||
# if ObjectDB.objects.dbref(location):
|
||||
# # dbref search
|
||||
# loc = ObjectDB.objects.dbref_search(location)
|
||||
# loc = loc and _GA(loc, "dbobj")
|
||||
# elif location and type(location) != ObjectDB:
|
||||
# loc = _GA(location, "dbobj")
|
||||
# else:
|
||||
# loc = location
|
||||
|
||||
# # recursive location check
|
||||
# def is_loc_loop(loc, depth=0):
|
||||
# "Recursively traverse the target location to make sure we are not in it."
|
||||
# if depth > 10: return
|
||||
# elif loc == self: raise RuntimeError
|
||||
# elif loc == None: raise RuntimeWarning # just to quickly get out
|
||||
# return is_loc_loop(_GA(loc, "db_location"), depth+1)
|
||||
# # check so we don't create a location loop - if so, RuntimeError will be raised.
|
||||
# try: is_loc_loop(loc)
|
||||
# except RuntimeWarning: pass
|
||||
|
||||
# # set the location
|
||||
# set_field_cache(self, "location", loc)
|
||||
# # update the contents of each location
|
||||
# if old_loc:
|
||||
# _GA(_GA(old_loc, "dbobj"), "contents_update")()
|
||||
# if loc:
|
||||
# _GA(loc, "contents_update")()
|
||||
# except RuntimeError:
|
||||
# string = "Cannot set location, "
|
||||
# string += "%s.location = %s would create a location-loop." % (self.key, loc)
|
||||
# _GA(self, "msg")(_(string))
|
||||
# logger.log_trace(string)
|
||||
# raise RuntimeError(string)
|
||||
# except Exception, e:
|
||||
# string = "Cannot set location (%s): " % str(e)
|
||||
# string += "%s is not a valid location." % location
|
||||
# _GA(self, "msg")(_(string))
|
||||
# logger.log_trace(string)
|
||||
# raise Exception(string)
|
||||
##@location.deleter
|
||||
#def __location_del(self):
|
||||
# "Deleter. Allows for del self.location"
|
||||
# _GA(self, "location").contents_update()
|
||||
# _SA(self, "db_location", None)
|
||||
# _GA(self, "save")()
|
||||
# del_field_cache(self, "location")
|
||||
#location = property(__location_get, __location_set, __location_del)
|
||||
|
||||
# home property (wraps db_home)
|
||||
#@property
|
||||
#def __home_get(self):
|
||||
# "Getter. Allows for value = self.home"
|
||||
# home = get_field_cache(self, "home")
|
||||
# if home:
|
||||
# return _GA(home, "typeclass")
|
||||
# return None
|
||||
##@home.setter
|
||||
#def __home_set(self, home):
|
||||
# "Setter. Allows for self.home = value"
|
||||
# try:
|
||||
# if home == None or type(home) == ObjectDB:
|
||||
# hom = home
|
||||
# elif ObjectDB.objects.dbref(home):
|
||||
# hom = ObjectDB.objects.dbref_search(home)
|
||||
# if hom and hasattr(hom,'dbobj'):
|
||||
# hom = _GA(hom, "dbobj")
|
||||
# else:
|
||||
# hom = _GA(home, "dbobj")
|
||||
# else:
|
||||
# hom = _GA(home, "dbobj")
|
||||
# set_field_cache(self, "home", hom)
|
||||
# except Exception:
|
||||
# string = "Cannot set home: "
|
||||
# string += "%s is not a valid home."
|
||||
# _GA(self, "msg")(_(string) % home)
|
||||
# logger.log_trace(string)
|
||||
# #raise
|
||||
##@home.deleter
|
||||
#def __home_del(self):
|
||||
# "Deleter. Allows for del self.home."
|
||||
# _SA(self, "db_home", None)
|
||||
# _GA(self, "save")()
|
||||
# del_field_cache(self, "home")
|
||||
#home = property(__home_get, __home_set, __home_del)
|
||||
|
||||
# destination property (wraps db_destination)
|
||||
#@property
|
||||
#def __destination_get(self):
|
||||
# "Getter. Allows for value = self.destination."
|
||||
# dest = get_field_cache(self, "destination")
|
||||
# if dest:
|
||||
# return _GA(dest, "typeclass")
|
||||
# return None
|
||||
##@destination.setter
|
||||
#def __destination_set(self, destination):
|
||||
# "Setter. Allows for self.destination = destination"
|
||||
# try:
|
||||
# if destination == None or type(destination) == ObjectDB:
|
||||
# # destination is None or a valid object
|
||||
# dest = destination
|
||||
# elif ObjectDB.objects.dbref(destination):
|
||||
# # destination is a dbref; search
|
||||
# dest = ObjectDB.objects.dbref_search(destination)
|
||||
# if dest and _GA(self, "_hasattr")(dest,'dbobj'):
|
||||
# dest = _GA(dest, "dbobj")
|
||||
# else:
|
||||
# dest = _GA(destination, "dbobj")
|
||||
# else:
|
||||
# dest = destination.dbobj
|
||||
# set_field_cache(self, "destination", dest)
|
||||
# except Exception:
|
||||
# string = "Cannot set destination: "
|
||||
# string += "%s is not a valid destination." % destination
|
||||
# _GA(self, "msg")(string)
|
||||
# logger.log_trace(string)
|
||||
# raise
|
||||
##@destination.deleter
|
||||
#def __destination_del(self):
|
||||
# "Deleter. Allows for del self.destination"
|
||||
# _SA(self, "db_destination", None)
|
||||
# _GA(self, "save")()
|
||||
# del_field_cache(self, "destination")
|
||||
#destination = property(__destination_get, __destination_set, __destination_del)
|
||||
|
||||
# cmdset_storage property. We use a custom wrapper to manage this. This also
|
||||
# seems very sensitive to caching, so leaving it be for now. /Griatch
|
||||
|
|
@ -434,7 +183,6 @@ class ObjectDB(TypedObject):
|
|||
# ObjectDB class access methods/properties
|
||||
#
|
||||
|
||||
|
||||
#@property
|
||||
def __sessions_get(self):
|
||||
"""
|
||||
|
|
@ -473,23 +221,11 @@ class ObjectDB(TypedObject):
|
|||
|
||||
exclude is one or more objects to not return
|
||||
"""
|
||||
contents = get_prop_cache(self, "_contents")
|
||||
if contents == None:
|
||||
# this is the case if this is the first call
|
||||
contents = _GA(self, "contents_update")()
|
||||
if exclude:
|
||||
exclude = [obj.typeclass for obj in make_iter(exclude)]
|
||||
return [obj for obj in contents if obj not in exclude]
|
||||
else:
|
||||
return contents
|
||||
return ObjectDB.objects.get_contents(self, excludeobj=exclude)
|
||||
return ObjectDB.objects.get_contents(self)
|
||||
contents = property(contents_get)
|
||||
|
||||
def contents_update(self):
|
||||
"Re-sync the contents cache"
|
||||
contents = ObjectDB.objects.get_contents(self)
|
||||
set_prop_cache(self, "_contents", contents)
|
||||
return contents
|
||||
|
||||
#@property
|
||||
def __exits_get(self):
|
||||
"""
|
||||
|
|
@ -972,6 +708,6 @@ class ObjectDB(TypedObject):
|
|||
# Perform the deletion of the object
|
||||
super(ObjectDB, self).delete()
|
||||
# clear object's old location's content cache of this object
|
||||
if old_loc:
|
||||
_GA(old_loc.dbobj, "contents_update")()
|
||||
#if old_loc:
|
||||
# _GA(old_loc.dbobj, "contents_update")()
|
||||
return True
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue