[Zope-CVS] CVS: Products/FileCacheManager - CHANGES.txt:1.2
FileCache.py:1.10
Chris McDonough
chrism at plope.com
Fri Nov 19 01:31:53 EST 2004
Update of /cvs-repository/Products/FileCacheManager
In directory cvs.zope.org:/tmp/cvs-serv14131
Modified Files:
CHANGES.txt FileCache.py
Log Message:
Add "entries_being_written" cache to prevent returning of stale data from ZCache_get after a ZCache_set of an already-cached object has been performed.
=== Products/FileCacheManager/CHANGES.txt 1.1 => 1.2 ===
--- Products/FileCacheManager/CHANGES.txt:1.1 Mon Aug 30 13:40:43 2004
+++ Products/FileCacheManager/CHANGES.txt Fri Nov 19 01:31:52 2004
@@ -1,6 +1,16 @@
CHANGES.txt for the FileCacheManager product
+ post-1.0
+
+ After a ZCache_set has been performed, during the transaction lifetime,
+ return the file data fed to ZCache_set via ZCache_get even though it
+ hasn't yet been written to the ultimate filepath. If this is not done,
+ ZCache_get could return "stale" data from the perspective of the
+ application using FCM.
+
+ HTTP caching added.
+
1.0
First public release
-
+
=== Products/FileCacheManager/FileCache.py 1.9 => 1.10 ===
--- Products/FileCacheManager/FileCache.py:1.9 Sun Oct 31 12:59:29 2004
+++ Products/FileCacheManager/FileCache.py Fri Nov 19 01:31:52 2004
@@ -20,7 +20,7 @@
import zLOG
-from thread import allocate_lock
+from ThreadLock import allocate_lock
from AccessControl.SecurityManagement import getSecurityManager
from App.Common import rfc1123_date
@@ -33,6 +33,9 @@
_debug = 0
+entries_being_written = {}
+entries_being_written_lock = allocate_lock()
+
class FileCache(RAMCache):
""" A cache that caches rendered content to the filesystem """
_tempfile_path = ''
@@ -51,6 +54,10 @@
self._http_caching_anonymous_only = True
self.entries = {}
+ def get_entries_being_written(self):
+ # for unit testing
+ return entries_being_written
+
def _fileName(self, ob):
""" Compute a filename based on an MD5 hash: doesn't preserve
human-readable path, but otherwise makes life much easier """
@@ -126,6 +133,15 @@
pp = '/'.join(ob.getPhysicalPath())
fname = self._fileName(ob)
+ entries_being_written_lock.acquire()
+ try:
+ entry = entries_being_written.get(fname)
+ finally:
+ entries_being_written_lock.release()
+
+ if entry is not None:
+ fname = entry.get_temppath()
+
try:
fiter = filestream_iterator(fname, 'rb')
except IOError:
@@ -249,7 +265,20 @@
# Register as Transaction Manager so my transaction hooks get called.
get_transaction().register(self)
+
+ def get_temppath(self):
+ if not self.temppath:
+ raise AssertionError, 'temppath is None'
+ return self.temppath
+ def del_from_entry_registry(self):
+ entries_being_written_lock.acquire()
+ try:
+ entry = entries_being_written.get(self.path)
+ if entry and entry.temppath == self.temppath:
+ del entries_being_written[self.path]
+ finally:
+ entries_being_written_lock.release()
def remove(self):
""" Delete the cache file from disk """
@@ -285,6 +314,12 @@
self.op_write = 1
+ entries_being_written_lock.acquire()
+ try:
+ entries_being_written[self.path] = self
+ finally:
+ entries_being_written_lock.release()
+
except IOError, msg:
zLOG.LOG( 'FileCacheManager'
, zLOG.ERROR
@@ -322,11 +357,11 @@
except (OSError, IOError):
pass
+ self.del_from_entry_registry()
self.temppath = None
self.op_write = 0
self.op_remove = 0
-
def tpc_vote(self, transaction):
""" Only called for real transactions, not subtransactions """
self._transaction_done = 1
@@ -395,6 +430,7 @@
, error=sys.exc_info()
)
finally:
+ self.del_from_entry_registry()
self.writelock.release()
self.temppath = None
self.op_write = 0
More information about the Zope-CVS
mailing list