[Zope-CVS] CVS: Products/FileCacheManager - FileCache.py:1.3
Jens Vagelpohl
jens at dataflake.org
Thu Aug 19 15:38:03 EDT 2004
Update of /cvs-repository/Products/FileCacheManager
In directory cvs.zope.org:/tmp/cvs-serv7600
Modified Files:
FileCache.py
Log Message:
- add transaction awareness in two places:
* ZCacheable_set will only write a file if the transaction commits
* ZCacheable_invalidate will only delete a file if the transation commits
=== Products/FileCacheManager/FileCache.py 1.2 => 1.3 ===
--- Products/FileCacheManager/FileCache.py:1.2 Thu Aug 19 14:38:58 2004
+++ Products/FileCacheManager/FileCache.py Thu Aug 19 15:37:30 2004
@@ -146,24 +146,19 @@
def __init__(self, path):
""" Instantiate a new instance """
self.path = path
+ self.temppath = None
self.writelock = allocate_lock()
+ self.op_remove = 0
+ self.op_write = 0
+ self._transaction_done = 0
+
+ # Register as Transaction Manager so my transaction hooks get called.
+ get_transaction().register(self)
def remove(self):
""" Delete the cache file from disk """
- try:
- try:
- self.writelock.acquire()
- if os.path.exists(self.path): # XXX race?
- os.remove(self.path)
- except IOError, msg:
- zLOG.LOG( 'FileCacheManager'
- , zLOG.ERROR
- , 'IOError removing file'
- , error=msg
- )
- finally:
- self.writelock.release()
+ self.op_remove = 1
def write(self, data):
@@ -171,6 +166,7 @@
try:
# Open a tempfile to safely dump data into
fd, tempname = tempfile.mkstemp()
+ self.temppath = tempname
# isinstance won't work on extension class
if type(data) == type(''):
@@ -187,12 +183,80 @@
os.fsync(fd)
os.close(fd)
+ self.op_write = 1
+
+ except IOError, msg:
+ zLOG.LOG( 'FileCacheManager'
+ , zLOG.ERROR
+ , 'IOError writing file'
+ , error=msg
+ )
+
+
+ #######################################################
+ # ZODB Transaction hooks
+ #######################################################
+
+ def commit(self, reallyme, t):
+ """ Called for every (sub-)transaction commit """
+ pass
+
+
+ def tpc_begin(self, transaction):
+ """ Called at the beginning of a transaction """
+ pass
+
+
+ def tpc_abort(self, transaction):
+ """ Called on abort - but not always :( """
+ pass
+
+
+ def abort(self, reallyme, t):
+ """ Called if the transaction has been aborted """
+ if self.op_write and self.temppath:
+ # If this was a write operation we need to remove the
+ # tempfile that's still hanging around.
+ try:
+ os.unlink(self.temppath)
+ except (OSError, IOError):
+ pass
+
+ 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
+
+
+ def tpc_finish(self, transaction):
+ """ Called at the end of a successful transaction """
+ if getattr(self, '_transaction_done', 0) and self.op_remove:
+ try:
+ try:
+ self.writelock.acquire()
+ if os.path.exists(self.path): # XXX race?
+ os.remove(self.path)
+ except IOError, msg:
+ zLOG.LOG( 'FileCacheManager'
+ , zLOG.ERROR
+ , 'IOError removing file'
+ , error=msg
+ )
+ finally:
+ self.writelock.release()
+ self.op_remove = 0
+
+ elif getattr(self, '_transaction_done', 0) and self.op_write:
# Now rename the tempfile to reflect the desired name.
# This may fail if they are not on the same filesystem.
try:
self.writelock.acquire()
try:
- os.rename(tempname, self.path)
+ os.rename(self.temppath, self.path)
except OSError:
# Windows fails if fname exists.
# If this doesn't work, tough noogies
@@ -200,12 +264,14 @@
os.rename(tempname, self.path)
finally:
self.writelock.release()
+ self.temppath = None
+ self.op_write = 0
- except IOError, msg:
- zLOG.LOG( 'FileCacheManager'
- , zLOG.ERROR
- , 'IOError writing file'
- , error=msg
- )
+ def sortKey(self, *ignored):
+ """ The sortKey method is used for recent ZODB compatibility which
+ needs to have a known commit order for lock acquisition.
+ I don't care about commit order, so return the constant 1
+ """
+ return 1
More information about the Zope-CVS
mailing list