Commit b048769a authored by Jean-Paul Smets's avatar Jean-Paul Smets

moved global vars for cache to class vars


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@2724 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 5825c1e6
...@@ -26,7 +26,8 @@ ...@@ -26,7 +26,8 @@
# #
############################################################################## ##############################################################################
from Globals import InitializeClass, DTMLFile import ExtensionClass
from Globals import InitializeClass, DTMLFile, PersistentMapping
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from AccessControl.Permission import pname from AccessControl.Permission import pname
from Acquisition import aq_base, aq_inner, aq_acquire, aq_chain from Acquisition import aq_base, aq_inner, aq_acquire, aq_chain
...@@ -38,7 +39,6 @@ from Products.CMFCore.Expression import Expression ...@@ -38,7 +39,6 @@ from Products.CMFCore.Expression import Expression
from Products.DCWorkflow.Transitions import TRIGGER_WORKFLOW_METHOD from Products.DCWorkflow.Transitions import TRIGGER_WORKFLOW_METHOD
from Products.ERP5Type import _dtmldir from Products.ERP5Type import _dtmldir
from Products.ERP5Type import PropertySheet from Products.ERP5Type import PropertySheet
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
...@@ -71,16 +71,10 @@ import random ...@@ -71,16 +71,10 @@ import random
from zLOG import LOG, INFO, ERROR, WARNING from zLOG import LOG, INFO, ERROR, WARNING
# Dynamic method acquisition system (code generation)
aq_method_generated = {}
aq_portal_type = {}
aq_related_generated = 0
def _aq_reset(): def _aq_reset():
global aq_portal_type, aq_method_generated, aq_related_generated Base.aq_method_generated = PersistentMapping()
aq_method_generated = {} Base.aq_portal_type = PersistentMapping()
aq_portal_type = {} Base.aq_related_generated = 0
aq_related_generated = 0
class PropertyHolder: class PropertyHolder:
isRADContent = 1 isRADContent = 1
...@@ -98,9 +92,9 @@ def getClassPropertyList(klass): ...@@ -98,9 +92,9 @@ def getClassPropertyList(klass):
def initializeClassDynamicProperties(self, klass, recursive=0): def initializeClassDynamicProperties(self, klass, recursive=0):
id = '' id = ''
#LOG('before aq_method_generated %s' % id, 0, str(klass.__name__)) #LOG('before aq_method_generated %s' % id, 0, str(klass.__name__))
if not aq_method_generated.has_key(klass): if not Base.aq_method_generated.has_key(klass):
# Mark as generated # Mark as generated
aq_method_generated[klass] = 1 Base.aq_method_generated[klass] = 1
# Recurse to superclasses # Recurse to superclasses
for super_klass in klass.__bases__: for super_klass in klass.__bases__:
if getattr(super_klass, 'isRADContent', 0): initializeClassDynamicProperties(self, super_klass, recursive=1) if getattr(super_klass, 'isRADContent', 0): initializeClassDynamicProperties(self, super_klass, recursive=1)
...@@ -113,10 +107,9 @@ def initializeClassDynamicProperties(self, klass, recursive=0): ...@@ -113,10 +107,9 @@ def initializeClassDynamicProperties(self, klass, recursive=0):
def initializePortalTypeDynamicProperties(self, klass, ptype, recursive=0): def initializePortalTypeDynamicProperties(self, klass, ptype, recursive=0):
id = '' id = ''
#LOG('before aq_portal_type %s' % id, 0, str(ptype)) #LOG('before aq_portal_type %s' % id, 0, str(ptype))
if not aq_portal_type.has_key(ptype): if not Base.aq_portal_type.has_key(ptype):
# Mark as generated # Mark as generated
aq_portal_type[ptype] = PropertyHolder() prop_holder = Base.aq_portal_type[ptype] = PropertyHolder()
prop_holder = aq_portal_type[ptype]
# Recurse to parent object # Recurse to parent object
parent_object = self.aq_parent parent_object = self.aq_parent
parent_klass = parent_object.__class__ parent_klass = parent_object.__class__
...@@ -161,7 +154,12 @@ def initializePortalTypeDynamicProperties(self, klass, ptype, recursive=0): ...@@ -161,7 +154,12 @@ def initializePortalTypeDynamicProperties(self, klass, ptype, recursive=0):
prop_holder.security = ClassSecurityInfo() # Is this OK for security XXX ? prop_holder.security = ClassSecurityInfo() # Is this OK for security XXX ?
from Utils import initializeDefaultProperties from Utils import initializeDefaultProperties
#LOG('initializeDefaultProperties: %s' % ptype, 0, str(prop_holder.__dict__)) #LOG('initializeDefaultProperties: %s' % ptype, 0, str(prop_holder.__dict__))
try:
initializeDefaultProperties([prop_holder], object=self) initializeDefaultProperties([prop_holder], object=self)
except:
LOG('Base', ERROR,
'Could not generate default properties on portal type %s.' % ptype,
error=sys.exc_info())
#LOG('initializeDefaultProperties: %s' % ptype, 0, str(prop_holder.__dict__)) #LOG('initializeDefaultProperties: %s' % ptype, 0, str(prop_holder.__dict__))
# We should now make sure workflow methods are defined # We should now make sure workflow methods are defined
# and also make sure simulation state is defined # and also make sure simulation state is defined
...@@ -262,6 +260,11 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ): ...@@ -262,6 +260,11 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ):
isIndexable = 1 # If set to 0, reindexing will not happen (useful for optimization) isIndexable = 1 # If set to 0, reindexing will not happen (useful for optimization)
is_predicate = 0 # is_predicate = 0 #
# Dynamic method acquisition system (code generation)
aq_method_generated = PersistentMapping()
aq_portal_type = PersistentMapping()
aq_related_generated = 0
# Declarative security # Declarative security
security = ClassSecurityInfo() security = ClassSecurityInfo()
...@@ -280,34 +283,31 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ): ...@@ -280,34 +283,31 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ):
def _propertyMap(self): def _propertyMap(self):
""" Method overload - properties are now defined on the ptype """ """ Method overload - properties are now defined on the ptype """
global aq_portal_type
ptype = self.portal_type ptype = self.portal_type
#LOG('_propertyMap',0,ptype) #LOG('_propertyMap',0,ptype)
self._aq_dynamic('id') # Make sure aq_dynamic has been called once self._aq_dynamic('id') # Make sure aq_dynamic has been called once
if aq_portal_type.has_key(ptype): if Base.aq_portal_type.has_key(ptype):
#LOG('_propertyMap ptype',0,list(getattr(aq_portal_type[ptype], '_properties', ()))) #LOG('_propertyMap ptype',0,list(getattr(aq_portal_type[ptype], '_properties', ())))
return tuple(list(getattr(aq_portal_type[ptype], '_properties', ())) + return tuple(list(getattr(Base.aq_portal_type[ptype], '_properties', ())) +
list(getattr(self, '_local_properties', ()))) list(getattr(self, '_local_properties', ())))
return ERP5PropertyManager._propertyMap(self) return ERP5PropertyManager._propertyMap(self)
def _aq_dynamic(self, id): def _aq_dynamic(self, id):
global aq_portal_type
ptype = self.portal_type ptype = self.portal_type
#LOG("In _aq_dynamic", 0, str((id, ptype, self))) #LOG("In _aq_dynamic", 0, str((id, ptype, self)))
# If this is a portal_type property and everything is already defined # If this is a portal_type property and everything is already defined
# for that portal_type, try to return a value ASAP # for that portal_type, try to return a value ASAP
if aq_portal_type.has_key(ptype): if Base.aq_portal_type.has_key(ptype):
return getattr(aq_portal_type[ptype], id, None) return getattr(Base.aq_portal_type[ptype], id, None)
# Proceed with property generation # Proceed with property generation
global aq_method_generated, aq_related_generated
klass = self.__class__ klass = self.__class__
generated = 0 # Prevent infinite loops generated = 0 # Prevent infinite loops
# Generate class methods # Generate class methods
if not aq_method_generated.has_key(klass): if not Base.aq_method_generated.has_key(klass):
try: try:
initializeClassDynamicProperties(self, klass) initializeClassDynamicProperties(self, klass)
except: except:
...@@ -315,7 +315,7 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ): ...@@ -315,7 +315,7 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ):
generated = 1 generated = 1
# Generate portal_type methods # Generate portal_type methods
if not aq_portal_type.has_key(ptype): if not Base.aq_portal_type.has_key(ptype):
try: try:
initializePortalTypeDynamicProperties(self, klass, ptype) initializePortalTypeDynamicProperties(self, klass, ptype)
#LOG('_aq_dynamic for %s' % ptype,0, aq_portal_type[ptype].__dict__.keys()) #LOG('_aq_dynamic for %s' % ptype,0, aq_portal_type[ptype].__dict__.keys())
...@@ -324,9 +324,9 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ): ...@@ -324,9 +324,9 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ):
generated = 1 generated = 1
# Generate Related Accessors # Generate Related Accessors
if not aq_related_generated: if not Base.aq_related_generated:
from Utils import createRelatedValueAccessors from Utils import createRelatedValueAccessors
aq_related_generated = 1 Base.aq_related_generated = 1
generated = 1 generated = 1
portal_categories = getToolByName(self, 'portal_categories', None) portal_categories = getToolByName(self, 'portal_categories', None)
generated_bid = {} generated_bid = {}
...@@ -629,13 +629,12 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ): ...@@ -629,13 +629,12 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ):
method = getattr(self, accessor_name) method = getattr(self, accessor_name)
return method(**kw) return method(**kw)
# Try to get a portal_type property (Implementation Dependent) # Try to get a portal_type property (Implementation Dependent)
global aq_portal_type if not Base.aq_portal_type.has_key(self.portal_type):
if not aq_portal_type.has_key(self.portal_type):
try: try:
self._aq_dynamic(accessor_name) self._aq_dynamic(accessor_name)
except AttributeError: except AttributeError:
pass pass
if hasattr(aq_portal_type[self.portal_type], accessor_name): if hasattr(Base.aq_portal_type[self.portal_type], accessor_name):
method = getattr(self, accessor_name) method = getattr(self, accessor_name)
return method(**kw) return method(**kw)
#elif hasattr(aq_self, key): #elif hasattr(aq_self, key):
...@@ -708,14 +707,13 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ): ...@@ -708,14 +707,13 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ):
method(value, **kw) method(value, **kw)
return return
# Try to get a portal_type property (Implementation Dependent) # Try to get a portal_type property (Implementation Dependent)
global aq_portal_type if not Base.aq_portal_type.has_key(self.portal_type):
if not aq_portal_type.has_key(self.portal_type):
self._aq_dynamic('id') # Make sure _aq_dynamic has been called once self._aq_dynamic('id') # Make sure _aq_dynamic has been called once
if hasattr(aq_portal_type[self.portal_type], accessor_name): if hasattr(Base.aq_portal_type[self.portal_type], accessor_name):
method = getattr(self, accessor_name) method = getattr(self, accessor_name)
method(value, **kw) method(value, **kw)
return return
if hasattr(aq_portal_type[self.portal_type], public_accessor_name): if hasattr(Base.aq_portal_type[self.portal_type], public_accessor_name):
method = getattr(self, public_accessor_name) method = getattr(self, public_accessor_name)
method(value, **kw) method(value, **kw)
return return
...@@ -757,14 +755,13 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ): ...@@ -757,14 +755,13 @@ class Base( CopyContainer, PortalContent, ActiveObject, ERP5PropertyManager ):
method(value, **kw) method(value, **kw)
return return
# Try to get a portal_type property (Implementation Dependent) # Try to get a portal_type property (Implementation Dependent)
global aq_portal_type if not Base.aq_portal_type.has_key(self.portal_type):
if not aq_portal_type.has_key(self.portal_type):
self._aq_dynamic('id') # Make sure _aq_dynamic has been called once self._aq_dynamic('id') # Make sure _aq_dynamic has been called once
if hasattr(aq_portal_type[self.portal_type], accessor_name): if hasattr(Base.aq_portal_type[self.portal_type], accessor_name):
method = getattr(self, accessor_name) method = getattr(self, accessor_name)
method(value, **kw) method(value, **kw)
return return
if hasattr(aq_portal_type[self.portal_type], public_accessor_name): if hasattr(Base.aq_portal_type[self.portal_type], public_accessor_name):
method = getattr(self, public_accessor_name) method = getattr(self, public_accessor_name)
method(value, **kw) method(value, **kw)
return return
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
# #
############################################################################## ##############################################################################
from Globals import PersistentMapping
from AccessControl.SecurityInfo import allow_class from AccessControl.SecurityInfo import allow_class
from time import time from time import time
...@@ -35,9 +36,6 @@ from zLOG import LOG ...@@ -35,9 +36,6 @@ from zLOG import LOG
cache_check_time = time() cache_check_time = time()
CACHE_CHECK_TIMEOUT = 60 CACHE_CHECK_TIMEOUT = 60
# Use this global variable to store cached objects.
cached_object_dict = {}
# Special Exception for this code. # Special Exception for this code.
class CachedMethodError(Exception): pass class CachedMethodError(Exception): pass
...@@ -72,6 +70,9 @@ class CachingMethod: ...@@ -72,6 +70,9 @@ class CachingMethod:
all entries are checked to expire old ones. This should not be significant, all entries are checked to expire old ones. This should not be significant,
since this is done once per 100 calls. since this is done once per 100 calls.
""" """
# Use this global variable to store cached objects.
cached_object_dict = PersistentMapping()
def __init__(self, callable_object, id = None, cache_duration = 180): def __init__(self, callable_object, id = None, cache_duration = 180):
""" """
callable_object must be callable. callable_object must be callable.
...@@ -103,11 +104,11 @@ class CachingMethod: ...@@ -103,11 +104,11 @@ class CachingMethod:
# LOG('CachingMethod', 0, 'checking all entries to expire') # LOG('CachingMethod', 0, 'checking all entries to expire')
cache_check_time = now cache_check_time = now
try: try:
for index in cached_object_dict.keys(): for index in CachingMethod.cached_object_dict.keys():
obj = cached_object_dict[index] obj = CachingMethod.cached_object_dict[index]
if obj.time + obj.duration < now: if obj.time + obj.duration < now:
# LOG('CachingMethod', 0, 'expire %s' % index) # LOG('CachingMethod', 0, 'expire %s' % index)
del cached_object_dict[index] del CachingMethod.cached_object_dict[index]
except: except:
# This is necessary for multi-threading, because two threads can # This is necessary for multi-threading, because two threads can
# delete the same entry at a time. # delete the same entry at a time.
...@@ -122,7 +123,7 @@ class CachingMethod: ...@@ -122,7 +123,7 @@ class CachingMethod:
index.append((key, str(kwd[key]))) index.append((key, str(kwd[key])))
index = str(index) index = str(index)
obj = cached_object_dict.get(index) obj = CachingMethod.cached_object_dict.get(index)
if obj is None or obj.time + obj.duration < now: if obj is None or obj.time + obj.duration < now:
#LOG('CachingMethod', 0, 'cache miss: id = %s, duration = %s, method = %s, args = %s, kwd = %s' % (str(self.id), str(self.duration), str(self.method), str(args), str(kwd))) #LOG('CachingMethod', 0, 'cache miss: id = %s, duration = %s, method = %s, args = %s, kwd = %s' % (str(self.id), str(self.duration), str(self.method), str(args), str(kwd)))
if obj is None: if obj is None:
...@@ -131,7 +132,7 @@ class CachingMethod: ...@@ -131,7 +132,7 @@ class CachingMethod:
obj.duration = self.duration obj.duration = self.duration
obj.result = self.method(*args, **kwd) obj.result = self.method(*args, **kwd)
cached_object_dict[index] = obj CachingMethod.cached_object_dict[index] = obj
else: else:
#LOG('CachingMethod', 0, 'cache hit: id = %s, duration = %s, method = %s, args = %s, kwd = %s' % (str(self.id), str(self.duration), str(self.method), str(args), str(kwd))) #LOG('CachingMethod', 0, 'cache hit: id = %s, duration = %s, method = %s, args = %s, kwd = %s' % (str(self.id), str(self.duration), str(self.method), str(args), str(kwd)))
pass pass
...@@ -141,4 +142,4 @@ class CachingMethod: ...@@ -141,4 +142,4 @@ class CachingMethod:
allow_class(CachingMethod) allow_class(CachingMethod)
def clearCache(): def clearCache():
cached_object_dict.clear() CachingMethod.cached_object_dict.clear()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment