[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