Commit ecc1a831 authored by Shane Hathaway's avatar Shane Hathaway

Added "max_age" parameter to RAM cache manager, making it easier to

configure for certain kinds of setups.
parent 62c36ef8
...@@ -127,6 +127,7 @@ class CacheEntry: ...@@ -127,6 +127,7 @@ class CacheEntry:
self.size = len(dumps(index)) + len(dumps(data)) self.size = len(dumps(index)) + len(dumps(data))
except: except:
raise CacheException('The data for the cache is not pickleable.') raise CacheException('The data for the cache is not pickleable.')
self.created = time.time()
self.data = data self.data = data
self.view_name = view_name self.view_name = view_name
self.access_count = 0 self.access_count = 0
...@@ -142,7 +143,7 @@ class ObjectCacheEntries: ...@@ -142,7 +143,7 @@ class ObjectCacheEntries:
def __init__(self, path): def __init__(self, path):
self.physical_path = path self.physical_path = path
self.lastmod = 0 self.lastmod = 0 # Mod time of the object, class, etc.
self.entries = {} self.entries = {}
def aggregateIndex(self, view_name, req, req_names, local_keys): def aggregateIndex(self, view_name, req, req_names, local_keys):
...@@ -181,6 +182,10 @@ class ObjectCacheEntries: ...@@ -181,6 +182,10 @@ class ObjectCacheEntries:
self.lastmod = lastmod self.lastmod = lastmod
self.entries[index] = CacheEntry(index, data, view_name) self.entries[index] = CacheEntry(index, data, view_name)
def delEntry(self, index):
try: del self.entries[index]
except KeyError: pass
class RAMCache (Cache): class RAMCache (Cache):
# Note the need to take thread safety into account. # Note the need to take thread safety into account.
...@@ -258,10 +263,27 @@ class RAMCache (Cache): ...@@ -258,10 +263,27 @@ class RAMCache (Cache):
finally: finally:
self.writelock.release() self.writelock.release()
def deleteStaleEntries(self):
"""
Deletes entries that have expired.
"""
self.writelock.acquire()
try:
min_created = time.time() - self.max_age
for p, oc in self.cache.items():
for agindex, entry in oc.entries.items():
if entry.created < min_created:
del oc.entries[agindex]
if len(oc.entries) < 1:
del self.cache[p]
finally:
self.writelock.release()
def cleanup(self): def cleanup(self):
''' '''
Removes cache entries. Removes cache entries.
''' '''
self.deleteStaleEntries()
new_count = self.countAllEntries() new_count = self.countAllEntries()
if new_count > self.threshold: if new_count > self.threshold:
counters = self.countAccesses() counters = self.countAccesses()
...@@ -334,6 +356,14 @@ class RAMCache (Cache): ...@@ -334,6 +356,14 @@ class RAMCache (Cache):
entry = oc.getEntry(lastmod, index) entry = oc.getEntry(lastmod, index)
if entry is _marker: if entry is _marker:
return default return default
if entry.created < time.time() - self.max_age:
# Expired.
self.writelock.acquire()
try:
oc.delEntry(index)
finally:
self.writelock.release()
return default
oc.hits = oc.hits + 1 oc.hits = oc.hits + 1
entry.access_count = entry.access_count + 1 entry.access_count = entry.access_count + 1
return entry.data return entry.data
...@@ -389,7 +419,9 @@ class RAMCacheManager (CacheManager, SimpleItem): ...@@ -389,7 +419,9 @@ class RAMCacheManager (CacheManager, SimpleItem):
self._settings = { self._settings = {
'threshold': 1000, 'threshold': 1000,
'cleanup_interval': 300, 'cleanup_interval': 300,
'request_vars': ('AUTHENTICATED_USER',)} 'request_vars': ('AUTHENTICATED_USER',),
'max_age': 3600,
}
self.__cacheid = '%s_%f' % (id(self), time.time()) self.__cacheid = '%s_%f' % (id(self), time.time())
def getId(self): def getId(self):
...@@ -423,7 +455,9 @@ class RAMCacheManager (CacheManager, SimpleItem): ...@@ -423,7 +455,9 @@ class RAMCacheManager (CacheManager, SimpleItem):
self._settings = { self._settings = {
'threshold': int(settings['threshold']), 'threshold': int(settings['threshold']),
'cleanup_interval': int(settings['cleanup_interval']), 'cleanup_interval': int(settings['cleanup_interval']),
'request_vars': tuple(request_vars)} 'request_vars': tuple(request_vars),
'max_age': int(settings['max_age']),
}
cache = self.ZCacheManager_getCache() cache = self.ZCacheManager_getCache()
cache.initSettings(self._settings) cache.initSettings(self._settings)
if REQUEST is not None: if REQUEST is not None:
......
...@@ -18,18 +18,19 @@ ...@@ -18,18 +18,19 @@
<tr> <tr>
<td align="left" valign="top"> <td align="left" valign="top">
<div class="form-label"> <div class="form-label">
REQUEST Variables REQUEST variables
</div> </div>
</td> </td>
<td align="left" valign="top"> <td align="left" valign="top">
<textarea name="request_vars:lines" rows="5" cols="30"><dtml-in <textarea name="request_vars:lines" rows="5" cols="30"><dtml-in
request_vars>&dtml-sequence-item;</dtml-in></textarea> request_vars>&dtml-sequence-item;
</dtml-in></textarea>
</td> </td>
</tr> </tr>
<tr> <tr>
<td align="left" valign="top"> <td align="left" valign="top">
<div class="form-label"> <div class="form-label">
Threshold Entries Threshold entries
</div> </div>
</td> </td>
<td align="left" valign="top"> <td align="left" valign="top">
...@@ -40,7 +41,18 @@ ...@@ -40,7 +41,18 @@
<tr> <tr>
<td align="left" valign="top"> <td align="left" valign="top">
<div class="form-label"> <div class="form-label">
Cleanup Interval (Seconds) Maximum age of a cache entry (seconds)
</div>
</td>
<td align="left" valign="top">
<input type="text" name="max_age" size="40"
value="&dtml-max_age;" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Cleanup interval (seconds)
</div> </div>
</td> </td>
<td align="left" valign="top"> <td align="left" valign="top">
......
StandardCacheManagers-1-0-0 StandardCacheManagers-1-1-0
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