[Erp5-report] r38549 jm - in /erp5/trunk/products: ERP5/Document/ ERP5Type/
nobody at svn.erp5.org
nobody at svn.erp5.org
Wed Sep 22 16:41:05 CEST 2010
Author: jm
Date: Wed Sep 22 16:41:05 2010
New Revision: 38549
URL: http://svn.erp5.org?rev=38549&view=rev
Log:
Replacement for clearAllCache
The idea is to store cache keys (or a part of cache keys) persistently,
so that modifying them makes Cache Tool looks at for cache value in a new place.
Modified:
erp5/trunk/products/ERP5/Document/BusinessTemplate.py
erp5/trunk/products/ERP5Type/Cache.py
Modified: erp5/trunk/products/ERP5/Document/BusinessTemplate.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/BusinessTemplate.py?rev=38549&r1=38548&r2=38549&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/BusinessTemplate.py [utf8] (original)
+++ erp5/trunk/products/ERP5/Document/BusinessTemplate.py [utf8] Wed Sep 22 16:41:05 2010
@@ -589,17 +589,17 @@ class BaseTemplateItem(Implicit, Persist
if meta_type == 'Script (Python)':
meta_type = 'ERP5 Python Script'
- attr_list = [ '_dav_writelocks', '_filepath', '_owner', 'uid',
- 'workflow_history', '__ac_local_roles__' ]
+ attr_set = set(('_dav_writelocks', '_filepath', '_owner', 'uid',
+ 'workflow_history', '__ac_local_roles__'))
if export:
- attr_list += {
+ attr_set.update({
'ERP5 Python Script': (#'func_code', 'func_defaults', '_code',
'_lazy_compilation', 'Python_magic'),
#'Z SQL Method': ('_arg', 'template',),
- }.get(meta_type, ())
+ }.get(meta_type, ()))
- for attr in attr_list:
- if attr in obj.__dict__:
+ for attr in obj.__dict__.keys():
+ if attr in attr_set or attr.startswith('_cache_cookie_'):
delattr(obj, attr)
if meta_type == 'ERP5 PDF Form':
Modified: erp5/trunk/products/ERP5Type/Cache.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/Cache.py?rev=38549&r1=38548&r2=38549&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/Cache.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/Cache.py [utf8] Wed Sep 22 16:41:05 2010
@@ -29,9 +29,13 @@
import string
from time import time
-from AccessControl.SecurityInfo import allow_class
+from AccessControl import allow_class, ClassSecurityInfo
+from Acquisition import aq_base
+from BTrees.Length import Length
from CachePlugins.BaseCache import CachedMethodError
+from persistent import Persistent
from zLOG import LOG, WARNING
+from Products.ERP5Type import Permissions
from Products.ERP5Type.TransactionalVariable import getTransactionalVariable, _MARKER
from Products.ERP5Type.Utils import simple_decorator
from warnings import warn
@@ -55,6 +59,50 @@ def initializePortalCachingProperties(se
# itself will cause cache misses that we want to ignore
is_cache_ready = 1
+
+class Cookie(Persistent):
+
+ value = 0
+
+ def __getstate__(self):
+ return self.value
+
+ def __setstate__(self, value):
+ self.value = value
+
+ def _p_resolveConflict(self, old_state, saved_state, new_state):
+ return 1 + max(saved_state, new_state)
+
+ def _p_independent(self):
+ return 1
+
+
+class CacheCookieMixin:
+ """Provides methods managing (ZODB) persistent keys to access caches
+ """
+ security = ClassSecurityInfo()
+
+ security.declareProtected(Permissions.AccessContentsInformation,
+ 'getCacheCookie')
+ def getCacheCookie(self, cache_name='default'):
+ """Get key of valid cache for this object"""
+ cache_name = '_cache_cookie_' + cache_name
+ try:
+ return self.__dict__[cache_name].value
+ except KeyError:
+ self.__dict__[cache_name] = Cookie()
+ return Cookie.value
+
+ security.declareProtected(Permissions.ModifyPortalContent, 'newCacheCookie')
+ def newCacheCookie(self, cache_name):
+ """Invalidate cache for this object"""
+ cache_name = '_cache_cookie_' + cache_name
+ try:
+ self.__dict__[cache_name].value += 1
+ except KeyError:
+ self.__dict__[cache_name] = Cookie()
+
+
class CacheFactory:
""" CacheFactory is a RAM based object which contains different cache plugin
objects ordered in a list.
@@ -157,9 +205,20 @@ class CachingMethod:
## cache factories will be initialized for every ERP5 site
factories = {}
+ def _default_cache_id_generator(method_id, *args, **kw):
+ """ Generate proper cache id based on *args and **kw """
+ ## generate cache id out of arguments passed.
+ ## depending on arguments we may have different
+ ## cache_id for same method_id
+ return str((method_id, args, kw))
+
+ @staticmethod
+ def erasable_cache_id_generator(method_id, obj, *args, **kw):
+ return str((method_id, obj.getCacheCookie(method_id), args, kw))
+
def __init__(self, callable_object, id, cache_duration=180,
cache_factory=DEFAULT_CACHE_FACTORY,
- cache_id_generator=None):
+ cache_id_generator=_default_cache_id_generator):
"""Wrap a callable object in a caching method.
callable_object must be callable.
@@ -177,7 +236,7 @@ class CachingMethod:
self.callable_object = callable_object
self.cache_duration = cache_duration
self.cache_factory = cache_factory
- self.cache_id_generator = cache_id_generator
+ self.generateCacheId = cache_id_generator
def __call__(self, *args, **kwd):
"""Call the method or return cached value using appropriate cache plugin """
@@ -220,16 +279,6 @@ class CachingMethod:
for cp in cache_factory.getCachePluginList():
cp.delete(cache_id, scope)
- def generateCacheId(self, method_id, *args, **kwd):
- """ Generate proper cache id based on *args and **kwd """
- ## generate cache id out of arguments passed.
- ## depending on arguments we may have different
- ## cache_id for same method_id
- cache_id_generator = self.cache_id_generator
- if cache_id_generator is not None:
- return cache_id_generator(method_id, *args, **kwd)
- return str((method_id, args, kwd))
-
allow_class(CachingMethod)
# TransactionCache is a cache per transaction. The purpose of this cache is
@@ -274,16 +323,16 @@ def generateCacheIdWithoutFirstArg(metho
def caching_instance_method(*args, **kw):
kw.setdefault('cache_id_generator', generateCacheIdWithoutFirstArg)
@simple_decorator
- def wrapped(method):
+ def decorator(function):
# The speed of returned function must be fast
# so we instanciate CachingMethod now.
- caching_method = CachingMethod(method, *args, **kw)
+ caching_method = CachingMethod(function, *args, **kw)
# Here, we can't return caching_method directly because an instanciated
# class with a __call__ method does not behave exactly like a simple
# function: if the decorator is used to create a method, the instance on
# which the method is called would not be passed as first parameter.
return lambda *args, **kw: caching_method(*args, **kw)
- return wrapped
+ return decorator
def transactional_cached(key_method=lambda *args: args):
@simple_decorator
More information about the Erp5-report
mailing list