[Zodb-checkins] CVS: Packages/ZODB/tests - testZODB.py:1.15.8.9

Tim Peters tim.one at comcast.net
Mon May 2 16:30:27 EDT 2005


Update of /cvs-repository/Packages/ZODB/tests
In directory cvs.zope.org:/tmp/cvs-serv26821/ZODB/tests

Modified Files:
      Tag: Zope-2_7-branch
	testZODB.py 
Log Message:
tpc_finish:  Repair longstanding bugs in subtransaction commit.

Jim (Fulton) discovered this in ZODB 3.4's code, while implementing
savepoint/rollback.  Same bugs have been there at least since ZODB 3.1.


=== Packages/ZODB/tests/testZODB.py 1.15.8.8 => 1.15.8.9 ===
--- Packages/ZODB/tests/testZODB.py:1.15.8.8	Thu Sep 16 20:42:01 2004
+++ Packages/ZODB/tests/testZODB.py	Mon May  2 16:30:27 2005
@@ -468,5 +468,69 @@
         self.assertEqual(cn.root()['a'], 100)
         cn.close()
 
+    def checkSubtxnCommitDoesntGetInvalidations(self):
+        # Prior to ZODB 3.2.9 and 3.4, Connection.tpc_finish() processed
+        # invalidations even for a subtxn commit.  This could make
+        # inconsistent state visible after a subtxn commit.  There was a
+        # suspicion that POSKeyError was possible as a result, but I wasn't
+        # able to construct a case where that happened.
+
+        # Set up the database, to hold
+        # root --> "p" -> value = 1
+        #      --> "q" -> value = 2
+        conn = self._db.open()
+        conn.setLocalTransaction()
+        r1 = conn.root()
+        p = P()
+        p.value = 1
+        r1["p"] = p
+        q = P()
+        q.value = 2
+        r1["q"] = q
+        conn.getTransaction().commit()
+
+        # Now txn T1 changes p.value to 3 locally (subtxn commit).
+        p.value = 3
+        conn.getTransaction().commit(True)
+
+        # Start new txn T2 with a new connection.
+        cn2 = self._db.open()
+        cn2.setLocalTransaction()
+        r2 = cn2.root()
+        p2 = r2["p"]
+        self.assertEqual(p._p_oid, p2._p_oid)
+        # T2 shouldn't see T1's change of p.value to 3, because T1 didn't
+        # commit yet.
+        self.assertEqual(p2.value, 1)
+        # Change p.value to 4, and q.value to 5.  Neither should be visible
+        # to T1, because T1 is still in progress.
+        p2.value = 4
+        q2 = r2["q"]
+        self.assertEqual(q._p_oid, q2._p_oid)
+        self.assertEqual(q2.value, 2)
+        q2.value = 5
+        cn2.getTransaction().commit()
+
+        # Back to T1.  p and q still have the expected values.
+        rt = conn.root()
+        self.assertEqual(rt["p"].value, 3)
+        self.assertEqual(rt["q"].value, 2)
+
+        # Now do another subtxn commit in T1.  This shouldn't change what
+        # T1 sees for p and q.
+        rt["r"] = P()
+        conn.getTransaction().commit(True)
+
+        # Doing that subtxn commit in T1 should not process invalidations
+        # from T2's commit.  p.value should still be 3 here (because that's
+        # what T1 subtxn-committed earlier), and q.value should still be 2.
+        # Prior to ZODB 3.2.9 and 3.4, q.value was 5 here.
+        rt = conn.root()
+        try:
+            self.assertEqual(rt["p"].value, 3)
+            self.assertEqual(rt["q"].value, 2)
+        finally:
+            conn.getTransaction().abort()
+
 def test_suite():
     return unittest.makeSuite(ZODBTests, 'check')



More information about the Zodb-checkins mailing list