not needed with 20Mi
[pyTivo/wgw.git] / Cheetah / CacheRegion.py
blob16de1880b237033414d512be9ca3fed72692cb22
1 # $Id: CacheRegion.py,v 1.3 2006/01/28 04:19:30 tavis_rudd Exp $
2 """Cache holder classes for Cheetah:
4 Cache regions are defined using the #cache Cheetah directive. Each
5 cache region can be viewed as a dictionary (keyed by cacheRegionID)
6 handling at least one cache item (the default one). It's possible to add
7 cacheItems in a region by using the `varyBy` #cache directive parameter as
8 in the following example::
9 #def getArticle
10 this is the article content.
11 #end def
13 #cache varyBy=$getArticleID()
14 $getArticle($getArticleID())
15 #end cache
17 The code above will generate a CacheRegion and add new cacheItem for each value
18 of $getArticleID().
20 Meta-Data
21 ================================================================================
22 Author: Tavis Rudd <tavis@damnsimple.com> and Philippe Normand <phil@base-art.net>
23 Version: $Revision: 1.3 $
24 Start Date: 2005/06/20
25 Last Revision Date: $Date: 2006/01/28 04:19:30 $
26 """
27 __author__ = "Tavis Rudd <tavis@damnsimple.com> and Philippe Normand <phil@base-art.net>"
28 __revision__ = "$Revision: 1.3 $"[11:-2]
30 import md5
31 from time import time as currentTime
32 from Cheetah.CacheStore import MemoryCacheStore
34 class CacheItem:
35 """A CacheItem is a container storing:
37 - cacheID (string)
38 - refreshTime (timestamp or None) : last time the cache was refreshed
39 - data (string) : the content of the cache
40 """
42 def __init__(self, cacheItemID, cacheStore):
43 self._cacheItemID = cacheItemID
44 self._cacheStore = cacheStore
45 self._refreshTime = None
46 self._expiryTime = 0
48 def hasExpired(self):
49 return (self._expiryTime and currentTime() > self._expiryTime)
51 def setExpiryTime(self, time):
52 self._expiryTime = time
54 def getExpiryTime(self):
55 return self._expiryTime
57 def setData(self, data):
58 self._refreshTime = currentTime()
59 self._cacheStore.set(self._cacheItemID, data, self._expiryTime)
61 def getRefreshTime(self):
62 return self._refreshTime
64 def getData(self):
65 assert self._refreshTime
66 return self._cacheStore.get(self._cacheItemID)
68 def renderOutput(self):
69 """Can be overridden to implement edge-caching"""
70 return self.getData() or ""
72 def clear(self):
73 self._cacheStore.delete(self._cacheItemID)
74 self._refreshTime = None
76 class _CacheDataStoreWrapper:
77 def __init__(self, dataStore, keyPrefix):
78 self._dataStore = dataStore
79 self._keyPrefix = keyPrefix
81 def get(self, key):
82 return self._dataStore.get(self._keyPrefix+key)
84 def delete(self, key):
85 self._dataStore.delete(self._keyPrefix+key)
87 def set(self, key, val, time=0):
88 self._dataStore.set(self._keyPrefix+key, val, time=time)
90 class CacheRegion:
91 """ A `CacheRegion` stores some `CacheItem` instances.
93 This implementation stores the data in the memory of the current process.
94 If you need a more advanced data store, create a cacheStore class that works
95 with Cheetah's CacheStore protocol and provide it as the cacheStore argument
96 to __init__. For example you could use
97 Cheetah.CacheStore.MemcachedCacheStore, a wrapper around the Python
98 memcached API (http://www.danga.com/memcached).
99 """
100 _cacheItemClass = CacheItem
102 def __init__(self, regionID, templateCacheIdPrefix='', cacheStore=None):
103 self._isNew = True
104 self._regionID = regionID
105 self._templateCacheIdPrefix = templateCacheIdPrefix
106 if not cacheStore:
107 cacheStore = MemoryCacheStore()
108 self._cacheStore = cacheStore
109 self._wrappedCacheDataStore = _CacheDataStoreWrapper(
110 cacheStore, keyPrefix=templateCacheIdPrefix+':'+regionID+':')
111 self._cacheItems = {}
113 def isNew(self):
114 return self._isNew
116 def clear(self):
117 " drop all the caches stored in this cache region "
118 for cacheItemId in self._cacheItems.keys():
119 cacheItem = self._cacheItems[cacheItemId]
120 cacheItem.clear()
121 del self._cacheItems[cacheItemId]
123 def getCacheItem(self, cacheItemID):
124 """ Lazy access to a cacheItem
126 Try to find a cache in the stored caches. If it doesn't
127 exist, it's created.
129 Returns a `CacheItem` instance.
131 cacheItemID = md5.new(str(cacheItemID)).hexdigest()
133 if not self._cacheItems.has_key(cacheItemID):
134 cacheItem = self._cacheItemClass(
135 cacheItemID=cacheItemID, cacheStore=self._wrappedCacheDataStore)
136 self._cacheItems[cacheItemID] = cacheItem
137 self._isNew = False
138 return self._cacheItems[cacheItemID]