[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