[Checkins] SVN: transaction/branches/elro-savepoint-release/ savepoint.release() support

Laurence Rowe l at lrowe.co.uk
Sat Jan 16 12:18:02 EST 2010


Log message for revision 108178:
  savepoint.release() support

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

-=-
Modified: transaction/branches/elro-savepoint-release/CHANGES.txt
===================================================================
--- transaction/branches/elro-savepoint-release/CHANGES.txt	2010-01-16 17:17:00 UTC (rev 108177)
+++ transaction/branches/elro-savepoint-release/CHANGES.txt	2010-01-16 17:18:02 UTC (rev 108178)
@@ -4,15 +4,19 @@
 1.1.0 (unreleased)
 ------------------
 
-- ...
+* 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.
 
+* Rename InvalidSavepointRollbackError to InvalidSavepointError (BBB provided.)
+
 1.0.0 (2009-07-24)
 ------------------
 
 * Fix test that incorrectly relied on the order of a list that was generated
   from a dict.
 
- * Remove crufty DEPENDENCIES.cfg left over from zpkg.
+* Remove crufty DEPENDENCIES.cfg left over from zpkg.
 
 1.0a1 (2007-12-18)
 ------------------

Modified: transaction/branches/elro-savepoint-release/transaction/_transaction.py
===================================================================
--- transaction/branches/elro-savepoint-release/transaction/_transaction.py	2010-01-16 17:17:00 UTC (rev 108177)
+++ transaction/branches/elro-savepoint-release/transaction/_transaction.py	2010-01-16 17:18:02 UTC (rev 108178)
@@ -271,6 +271,12 @@
                 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):
+        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():
@@ -651,7 +657,7 @@
     def rollback(self):
         transaction = self.transaction
         if transaction is None:
-            raise interfaces.InvalidSavepointRollbackError
+            raise interfaces.InvalidSavepointError
         transaction._remove_and_invalidate_after(self)
 
         try:
@@ -661,6 +667,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/transaction/interfaces.py
===================================================================
--- transaction/branches/elro-savepoint-release/transaction/interfaces.py	2010-01-16 17:17:00 UTC (rev 108177)
+++ transaction/branches/elro-savepoint-release/transaction/interfaces.py	2010-01-16 17:18:02 UTC (rev 108178)
@@ -430,6 +430,10 @@
         """Rollback any work done since the savepoint.
         """
 
+    def release():
+        """Release the savepoint. (Optional method.)
+        """
+
 class ISavepoint(zope.interface.Interface):
     """A transaction savepoint.
     """
@@ -437,22 +441,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/transaction/tests/savepoint.txt
===================================================================
--- transaction/branches/elro-savepoint-release/transaction/tests/savepoint.txt	2010-01-16 17:17:00 UTC (rev 108177)
+++ transaction/branches/elro-savepoint-release/transaction/tests/savepoint.txt	2010-01-16 17:18:02 UTC (rev 108178)
@@ -187,16 +187,65 @@
     >>> 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 remain valid:
+
+    >>> dm['bob-balance'] = 400.0
+    >>> dm['bob-balance']
+    400.0
+    >>> savepoint3.rollback()
+    >>> dm['bob-balance']
+    300.0
+
+As do previous savepoints:
+
+    >>> savepoint1.rollback()
+    >>> dm['bob-balance']
+    100.0
+
+    >>> transaction.abort()
+
+
 Databases without savepoint support
 -----------------------------------
 



More information about the checkins mailing list