Back to index

plone3  3.1.7
cache.py
Go to the documentation of this file.
00001 ##########################################################
00002 #
00003 # Licensed under the terms of the GNU Public License
00004 # (see docs/LICENSE.GPL)
00005 #
00006 # Copyright (c) 2005:
00007 #   - The Open Planning Project (http://www.openplans.org/)
00008 #   - Whit Morriss <whit at www.openplans.org>
00009 #   - and contributors
00010 #
00011 ##########################################################
00012 from persistent import Persistent
00013 from persistent.mapping import PersistentMapping
00014 from BTrees.OOBTree import OOBTree
00015 from wicked.interfaces import ICacheManager, IAmWicked, IWickedFilter
00016 from wicked.interfaces import IUID
00017 from zope.annotation.interfaces import IAnnotations, IAnnotatable
00018 from zope.interface import implements
00019 from zope.component import adapts, getUtility
00020 from utils import memoizedproperty, memoize, clearbefore
00021 
00022 _marker = object()
00023 
00024 # @@ need sys-module alias
00025 
00026 class CacheStore(Persistent):
00027     """
00028     basic persistent cache object
00029     
00030     see cache.txt
00031     """
00032     def __init__(self, id_):
00033         self.id = id_
00034         super(CacheStore, self).__init__(self)
00035         self.field={}
00036         self._cache = OOBTree()
00037 
00038     def __repr__(self):
00039         name = self.__class__.__name__
00040         name = "%s '%s'" %(name, self.id)
00041         return "%s %s :: %s" %(name, self.field, [x for x in self._cache.items()])
00042 
00043     def get(self, key, default=None):
00044         return self._cache.get(key, default)
00045 
00046     def set(self, key, value):
00047         self._cache[key] = value
00048         self._p_changed
00049 
00050     def getCache(self, key):
00051         subcache = self.field.get(key, _marker)
00052         if subcache is _marker:
00053             cache = Cache(parent=self, id_=self.id)
00054             self.field[key] = cache
00055             subcache = self.field[key]
00056             self._p_changed
00057         return subcache
00058         
00059     def remove(self, key):
00060         val = self._cache.get(key)
00061         if val:
00062             del self._cache[key]
00063             self._p_changed=True
00064             for name, fcache in self.field.items():
00065                 for slug, uid in fcache.items():
00066                     if uid==key:
00067                         del fcache[slug]
00068 
00069            
00070 class Cache(PersistentMapping):
00071 
00072     def __init__(self, id_=None, parent=None):
00073         self.parent = parent
00074         self.id = id_
00075         self._reverse={}
00076         super(Cache, self).__init__()
00077 
00078     def getRaw(self, key):
00079         return super(Cache, self).__getitem__(key)
00080 
00081     def parentGet(self, uid, default=None):
00082         return self.parent.get(str(uid), default)
00083 
00084     def get(self, key, default=None):
00085         uid = super(Cache, self).get(key, default)
00086         return self.parentGet(uid, default)
00087 
00088     def set(self, key, value):
00089         slug, uid = key
00090         self[slug] = uid
00091         self._reverse[uid] = slug
00092         self.parent.set(uid, value)
00093         self._p_changed
00094         return value
00095         
00096     def __getitem__(self, key):
00097         retval = self.parentGet(key)
00098         if retval: return retval
00099         return self.getRaw(key)
00100 
00101     def __repr__(self):
00102         rep = super(Cache, self).__repr__()
00103         name = self.__class__.__name__
00104         name = "%s '%s'" %(name, self.id)
00105         return "%s %s" %(name, rep)
00106 
00107     def __delitem__(self, key):
00108         """
00109         trickle up deletion
00110         """
00111         uid = self.getRaw(key)
00112         self.parent.remove(key)
00113         
00114         super(Cache, self).__delitem__(key)
00115 
00116 # @@ migrate to new name        
00117 CACHE_KEY = 'Products.wicked.lib.factories.ContentCacheManager'
00118 
00119 class BaseCacheManager(object):
00120     """abstract base"""
00121     implements(ICacheManager)
00122     adapts(IWickedFilter, IAmWicked)
00123     
00124     def __init__(self, wicked, context):
00125         self.context = context
00126         self.name = wicked.section
00127 
00128     @clearbefore
00129     def setName(self, name):
00130         self.name = name
00131 
00132     @memoizedproperty
00133     def cache_store(self):
00134         raise NotImplementedError
00135 
00136     def _get_cache(self, name=None):
00137         if not name:
00138             name = self.name
00139         cache = self.cache_store.getCache(name)
00140         return cache
00141 
00142     @memoizedproperty
00143     def cache(self):
00144         return self._get_cache()
00145     
00146     def get(self, key, default=None):
00147         return self.cache.get(key, default)
00148         
00149     def set(self, key, value):
00150         self.cache.set(key, value)
00151         return value
00152         
00153     def unset(self, key, use_uid=False):
00154         val = None
00155         if use_uid:
00156             for tkey, uid in self.cache.items():
00157                 if uid == key:
00158                     val = self.get(tkey)
00159                     del self.cache[tkey]
00160 
00161         if self.cache.has_key(key):
00162             val = self.get(key)
00163             del self.cache[key]
00164 
00165         return val
00166     
00167     def remove(self, uid):
00168         self.cache_store.remove(uid)
00169 
00170     def reset(self, uid, value):
00171         self.cache_store.set(uid, value)
00172 
00173 
00174 class UtilityCacheManager(BaseCacheManager):
00175 
00176     @memoizedproperty
00177     def cache_store(self):
00178         # XXX There is no IWickedCacheStore
00179         return getUtility(IWickedCacheStore)
00180 
00181     def name(): 
00182         def _pset(self, name, value):
00183             self._name=(name, IUID(self.context))
00184         def _pget(self, name):
00185             return self._name
00186         return locals()
00187     name = property(name())
00188 
00189 
00190 class ContentCacheManager(BaseCacheManager):
00191 
00192     @memoizedproperty
00193     def cache_store(self):
00194         ann = IAnnotations(self.context)
00195         cache_store = ann.get(CACHE_KEY)
00196         if not cache_store:
00197             cache_store = CacheStore(id_='/'.join(self.context.getPhysicalPath()))
00198             ann[CACHE_KEY] = cache_store
00199         return cache_store
00200 
00201 
00202