[Zope-Checkins] CVS: ZODB3/ZODB - Transaction.py:1.38

Jeremy Hylton jeremy@zope.com
Wed, 11 Sep 2002 14:41:24 -0400


Update of /cvs-repository/ZODB3/ZODB
In directory cvs.zope.org:/tmp/cvs-serv20918

Modified Files:
	Transaction.py 
Log Message:
Make hososity more likely for failed multi-jar commits.

The old code would avoid hosing the system when the first jar failed
during its finish.  The logic is that the failure means that
transaction did not commit, so it was safe for all the other jars to
abort.  There are counter-examples to this assumption.  For example,
ZEO could fail after commiting the transaction on the server but
before communicating that success to the client.  It would lead to
inconsistency if the other jars aborted after the first committed.

The solution is to reduce the special case yet further:  If a
single-jar transaction fails during the finish, assume the transaction
is aborted and avoid hosage.  If the jar actually committed, it's
possible to get back to a consistent state since only one jar was
involved.




=== ZODB3/ZODB/Transaction.py 1.37 => 1.38 ===
--- ZODB3/ZODB/Transaction.py:1.37	Wed Aug 14 18:07:09 2002
+++ ZODB3/ZODB/Transaction.py	Wed Sep 11 14:41:24 2002
@@ -206,12 +206,13 @@
                         else:
                             vote(self) # last chance to bail
 
-                # Try to finish one jar, since we may be able to
-                # recover if the first one fails.
-                self._finish_one(jarsv)
-                # Once a single jar has finished, it's a fatal (hosed)
-                # error if another jar fails.
-                self._finish_rest(jarsv)
+                # Handle multiple jars separately.  If there are
+                # multiple jars and one fails during the finish, we
+                # mark this transaction manager as hosed.
+                if len(jarsv) == 1:
+                    self._finish_one(jarsv[0])
+                else:
+                    self._finish_many(jarsv)
             except:
                 # Ugh, we got an got an error during commit, so we
                 # have to clean up.
@@ -266,11 +267,9 @@
                 jars[i] = j
             j.commit_sub(self)
 
-    def _finish_one(self, jarsv):
+    def _finish_one(self, jar):
         try:
-            if jarsv:
-                jarsv[-1].tpc_finish(self) # This should never fail
-                jarsv.pop() # It didn't, so it's taken care of.
+            jar.tpc_finish(self) # This should never fail
         except:
             # Bug if it does, we need to keep track of it
             LOG('ZODB', ERROR,
@@ -279,7 +278,7 @@
                 error=sys.exc_info())
             raise
 
-    def _finish_rest(self, jarsv):
+    def _finish_many(self, jarsv):
         global hosed
         try:
             while jarsv: