[Checkins] SVN: transaction/branches/elro-savepoint-release-1.1/ merge changes from elro-savepoint-release branch to current copy of trunk

Laurence Rowe l at lrowe.co.uk
Mon Jun 7 12:34:04 EDT 2010


Log message for revision 113246:
  merge changes from elro-savepoint-release branch to current copy of trunk

Changed:
  U   transaction/branches/elro-savepoint-release-1.1/CHANGES.txt
  U   transaction/branches/elro-savepoint-release-1.1/transaction/_transaction.py
  U   transaction/branches/elro-savepoint-release-1.1/transaction/interfaces.py
  U   transaction/branches/elro-savepoint-release-1.1/transaction/tests/savepoint.txt
  U   transaction/branches/elro-savepoint-release-1.1/transaction/tests/test_SampleResourceManager.py

-=-
Modified: transaction/branches/elro-savepoint-release-1.1/CHANGES.txt
===================================================================
--- transaction/branches/elro-savepoint-release-1.1/CHANGES.txt	2010-06-07 16:20:21 UTC (rev 113245)
+++ transaction/branches/elro-savepoint-release-1.1/CHANGES.txt	2010-06-07 16:34:04 UTC (rev 113246)
@@ -1,6 +1,10 @@
 Changes
 =======
 
+- Add support for savepoint.release(). Some databases only support a limited
+  number of savepoints or subtransactions, this provides an opportunity for a
+  data manager to free those resources.
+
 1.1.0 (1010-05-12)
 ------------------
 

Modified: transaction/branches/elro-savepoint-release-1.1/transaction/_transaction.py
===================================================================
--- transaction/branches/elro-savepoint-release-1.1/transaction/_transaction.py	2010-06-07 16:20:21 UTC (rev 113245)
+++ transaction/branches/elro-savepoint-release-1.1/transaction/_transaction.py	2010-06-07 16:34:04 UTC (rev 113246)
@@ -278,6 +278,13 @@
                 savepoint.transaction = None # invalidate
                 del savepoint2index[savepoint]
 
+    # Remove and invalidate a savepoint. This is what's needed on release
+    # of `savepoint`.
+    def _remove_and_invalidate(self, savepoint):
+        self._remove_and_invalidate_after(savepoint)
+        savepoint.transaction = None # invalidate
+        del self._savepoint2index[savepoint]
+
     # Invalidate and forget about all savepoints.
     def _invalidate_all_savepoints(self):
         for savepoint in self._savepoint2index.keys():
@@ -658,7 +665,7 @@
     def rollback(self):
         transaction = self.transaction
         if transaction is None:
-            raise interfaces.InvalidSavepointRollbackError
+            raise interfaces.InvalidSavepointError
         transaction._remove_and_invalidate_after(self)
 
         try:
@@ -668,6 +675,24 @@
             # Mark the transaction as failed.
             transaction._saveAndRaiseCommitishError() # reraises!
 
+    def release(self):
+        transaction = self.transaction
+        if transaction is None:
+            raise interfaces.InvalidSavepointError
+        transaction._remove_and_invalidate(self)
+
+        try:
+            for savepoint in self._savepoints:
+                try:
+                    release = savepoint.release
+                except AttributeError:
+                    pass
+                else:
+                    release()
+        except:
+            # Mark the transaction as failed.
+            transaction._saveAndRaiseCommitishError() # reraises!
+
 class AbortSavepoint:
 
     def __init__(self, datamanager, transaction):

Modified: transaction/branches/elro-savepoint-release-1.1/transaction/interfaces.py
===================================================================
--- transaction/branches/elro-savepoint-release-1.1/transaction/interfaces.py	2010-06-07 16:20:21 UTC (rev 113245)
+++ transaction/branches/elro-savepoint-release-1.1/transaction/interfaces.py	2010-06-07 16:34:04 UTC (rev 113246)
@@ -432,6 +432,10 @@
         """Rollback any work done since the savepoint.
         """
 
+    def release():
+        """Release the savepoint. (Optional method.)
+        """
+
 class ISavepoint(zope.interface.Interface):
     """A transaction savepoint.
     """
@@ -439,22 +443,32 @@
     def rollback():
         """Rollback any work done since the savepoint.
 
-        InvalidSavepointRollbackError is raised if the savepoint isn't valid.
+        InvalidSavepointError is raised if the savepoint isn't valid.
         """
 
+    def release():
+        """Release the savepoint.
+
+        InvalidSavepointError is raised if the savepoint isn't valid.
+        """
+
     valid = zope.interface.Attribute(
         "Boolean indicating whether the savepoint is valid")
 
-class InvalidSavepointRollbackError(Exception):
-    """Attempt to rollback an invalid savepoint.
+class InvalidSavepointError(Exception):
+    """Attempt to rollback or relase an invalid savepoint.
 
     A savepoint may be invalid because:
 
     - The surrounding transaction has committed or aborted.
 
     - An earlier savepoint in the same transaction has been rolled back.
+
+    - The savepoint has been released.
     """
 
+InvalidSavepointRollbackError = InvalidSavepointError #BBB
+
 class ISynchronizer(zope.interface.Interface):
     """Objects that participate in the transaction-boundary notification API.
     """

Modified: transaction/branches/elro-savepoint-release-1.1/transaction/tests/savepoint.txt
===================================================================
--- transaction/branches/elro-savepoint-release-1.1/transaction/tests/savepoint.txt	2010-06-07 16:20:21 UTC (rev 113245)
+++ transaction/branches/elro-savepoint-release-1.1/transaction/tests/savepoint.txt	2010-06-07 16:34:04 UTC (rev 113246)
@@ -187,16 +187,63 @@
     >>> savepoint2.rollback()
     Traceback (most recent call last):
     ...
-    InvalidSavepointRollbackError
+    InvalidSavepointError
 
     >>> savepoint1.rollback()
     Traceback (most recent call last):
     ...
-    InvalidSavepointRollbackError
+    InvalidSavepointError
 
     >>> transaction.abort()
 
 
+Savepoint release
+-----------------
+
+Some data managers may only support a limited number of savepoints.
+
+    >>> dm['bob-balance'] = 100.0
+    >>> dm['bob-balance']
+    100.0
+    >>> savepoint1 = transaction.savepoint()
+
+    >>> dm['bob-balance'] = 200.0
+    >>> dm['bob-balance']
+    200.0
+    >>> savepoint2 = transaction.savepoint()
+
+    >>> dm['bob-balance'] = 300.0
+    >>> dm['bob-balance']
+    300.0
+    >>> savepoint3 = transaction.savepoint()
+
+To release resources on the data manager, a savepoint may be released:
+
+    >>> savepoint2.release()
+
+The savepoint then becomes invalid and may no longer be used:
+
+    >>> savepoint2.rollback()
+    Traceback (most recent call last):
+    ...
+    InvalidSavepointError
+
+Subsequent savepoints are invalidated:
+
+    >>> savepoint3.rollback()
+    Traceback (most recent call last):
+    ...
+    InvalidSavepointError
+
+Previous savepoints continue to be valid:
+
+    >>> savepoint1.rollback()
+    >>> dm['bob-balance']
+    100.0
+
+    >>> transaction.abort()
+
+
 Databases without savepoint support
 -----------------------------------
 

Modified: transaction/branches/elro-savepoint-release-1.1/transaction/tests/test_SampleResourceManager.py
===================================================================
--- transaction/branches/elro-savepoint-release-1.1/transaction/tests/test_SampleResourceManager.py	2010-06-07 16:20:21 UTC (rev 113245)
+++ transaction/branches/elro-savepoint-release-1.1/transaction/tests/test_SampleResourceManager.py	2010-06-07 16:34:04 UTC (rev 113246)
@@ -404,9 +404,6 @@
         self.sp += 1
         return SavePoint(self)
 
-    def discard(self, transaction):
-        pass
-
 class SavePoint(object):
 
     def __init__(self, rm):
@@ -424,9 +421,6 @@
         self.rm.sp = self.sp
         self.rm.delta = self.delta
 
-    def discard(self):
-        pass
-
 def test_suite():
     from doctest import DocTestSuite
     return DocTestSuite()



More information about the checkins mailing list