[Zope-Checkins] CVS: ZODB3/ZODB/tests -
test_datamanageradapter.py:1.1.2.2
Jim Fulton
jim at zope.com
Fri Jan 23 09:54:33 EST 2004
Update of /cvs-repository/ZODB3/ZODB/tests
In directory cvs.zope.org:/tmp/cvs-serv32527
Modified Files:
Tag: zope3-zodb3-devel-branch
test_datamanageradapter.py
Log Message:
Added remaining tests.
=== ZODB3/ZODB/tests/test_datamanageradapter.py 1.1.2.1 => 1.1.2.2 ===
--- ZODB3/ZODB/tests/test_datamanageradapter.py:1.1.2.1 Thu Jan 22 16:24:42 2004
+++ ZODB3/ZODB/tests/test_datamanageradapter.py Fri Jan 23 09:54:31 2004
@@ -533,6 +533,275 @@
False
"""
+def test_abort_w_subtransactions():
+ """
+ So, we have a data manager:
+
+ >>> dm = DataManager()
+
+ and we do some work that modifies uncommited state:
+
+ >>> dm.inc()
+ >>> dm.state, dm.delta
+ (0, 1)
+
+ Now we'll commit the changes in a subtransaction. When the data
+ manager joins a transaction, the transaction will create an
+ adapter.
+
+ >>> dma = DataManagerAdapter(dm)
+
+ and register it as a modified object. At commit time, the
+ transaction will get the "jar" like this:
+
+ >>> jar = getattr(dma, '_p_jar', dma)
+
+ and, of course, the jar and the adapter will be the same:
+
+ >>> jar is dma
+ True
+
+ The transaction will call tpc_begin:
+
+ >>> t1 = '1'
+ >>> jar.tpc_begin(t1, 1) # 1 -> subtxn
+
+ Then the transaction will call commit on the jar:
+
+ >>> jar.commit(dma, t1)
+
+ This doesn't actually do anything. :)
+
+ >>> dm.state, dm.delta
+ (0, 1)
+
+ The transaction will then call tpc_vote:
+
+ >>> jar.tpc_vote(t1)
+
+ This doesn't do anything either, because zodb4 data managers don't
+ actually do two-phase commit for subtransactions.
+
+ >>> dm.state, dm.delta
+ (0, 1)
+
+ Finally, we call tpc_finish. This does actally create a savepoint,
+ but we can't really tell that from outside.
+
+ >>> jar.tpc_finish(t1)
+ >>> dm.state, dm.delta
+ (0, 1)
+
+ We'll do more of the above:
+
+ >>> dm.inc()
+ >>> dm.state, dm.delta
+ (0, 2)
+ >>> jar.tpc_begin(t1, 1) # 1 -> subtxn
+ >>> jar.commit(dma, t1)
+ >>> jar.tpc_vote(t1)
+ >>> jar.tpc_finish(t1)
+ >>> dm.state, dm.delta
+ (0, 2)
+ >>> dm.inc()
+ >>> dm.state, dm.delta
+ (0, 3)
+ >>> jar.tpc_begin(t1, 1) # 1 -> subtxn
+ >>> jar.commit(dma, t1)
+ >>> jar.tpc_vote(t1)
+ >>> jar.tpc_finish(t1)
+ >>> dm.state, dm.delta
+ (0, 3)
+
+ Note that the bove works *because* the same transaction is used
+ for each subtransaction.
+
+ Finally, we'll do a little more work:
+
+ >>> dm.inc()
+ >>> dm.inc()
+ >>> dm.state, dm.delta
+ (0, 5)
+
+ and then abort the top-level transaction.
+
+ The transaction first call abort on the jar:
+
+ >>> jar.abort(dma, t1)
+
+ This will have the effect of aborting the subtrancation:
+
+ >>> dm.state, dm.delta
+ (0, 3)
+
+ Then the transaction will call abort_sub:
+
+ >>> jar.abort_sub(t1)
+
+ This will abort all of the subtransactions:
+
+ >>> dm.state, dm.delta
+ (0, 0)
+ """
+
+
+def test_tpc_abort_w_subtransactions_featuring_subtransaction_abort():
+ """
+ So, we have a data manager:
+
+ >>> dm = DataManager()
+
+ and we do some work that modifies uncommited state:
+
+ >>> dm.inc()
+ >>> dm.state, dm.delta
+ (0, 1)
+
+ Now we'll commit the changes in a subtransaction. When the data
+ manager joins a transaction, the transaction will create an
+ adapter.
+
+ >>> dma = DataManagerAdapter(dm)
+
+ and register it as a modified object. At commit time, the
+ transaction will get the "jar" like this:
+
+ >>> jar = getattr(dma, '_p_jar', dma)
+
+ and, of course, the jar and the adapter will be the same:
+
+ >>> jar is dma
+ True
+
+ The transaction will call tpc_begin:
+
+ >>> t1 = '1'
+ >>> jar.tpc_begin(t1, 1) # 1 -> subtxn
+
+ Then the transaction will call commit on the jar:
+
+ >>> jar.commit(dma, t1)
+
+ This doesn't actually do anything. :)
+
+ >>> dm.state, dm.delta
+ (0, 1)
+
+ The transaction will then call tpc_vote:
+
+ >>> jar.tpc_vote(t1)
+
+ This doesn't do anything either, because zodb4 data managers don't
+ actually do two-phase commit for subtransactions.
+
+ >>> dm.state, dm.delta
+ (0, 1)
+
+ Finally, we call tpc_finish. This does actally create a savepoint,
+ but we can't really tell that from outside.
+
+ >>> jar.tpc_finish(t1)
+ >>> dm.state, dm.delta
+ (0, 1)
+
+ We'll do more of the above:
+
+ >>> dm.inc()
+ >>> dm.state, dm.delta
+ (0, 2)
+ >>> jar.tpc_begin(t1, 1) # 1 -> subtxn
+ >>> jar.commit(dma, t1)
+ >>> jar.tpc_vote(t1)
+ >>> jar.tpc_finish(t1)
+ >>> dm.state, dm.delta
+ (0, 2)
+
+
+ >>> dm.inc()
+ >>> dm.state, dm.delta
+ (0, 3)
+
+ But then we'll decide to abort a subtransaction.
+
+ The transaction will just call abort as usual:
+
+ >>> jar.abort(dma, t1)
+
+ This will cause a rollback to the last savepoint:
+ >>> dm.state, dm.delta
+ (0, 2)
+
+ Then we do more work:
+
+ >>> dm.inc()
+ >>> dm.state, dm.delta
+ (0, 3)
+ >>> jar.tpc_begin(t1, 1) # 1 -> subtxn
+ >>> jar.commit(dma, t1)
+ >>> jar.tpc_vote(t1)
+ >>> jar.tpc_finish(t1)
+ >>> dm.state, dm.delta
+ (0, 3)
+
+ Note that the bove works *because* the same transaction is used
+ for each subtransaction.
+
+ Finally, we'll do a little more work:
+
+ >>> dm.inc()
+ >>> dm.inc()
+ >>> dm.state, dm.delta
+ (0, 5)
+
+ and then commit the top-level transaction.
+
+ The transaction will actually go through the steps for a subtransaction:
+
+ >>> jar.tpc_begin(t1, 1) # 1 -> subtxn
+ >>> jar.commit(dma, t1)
+ >>> jar.tpc_vote(t1)
+ >>> jar.tpc_finish(t1)
+
+ And then call commit_sub:
+
+ >>> jar.commit_sub(t1)
+
+ As usual, this doesn't actually do anything. ;)
+
+ >>> dm.state, dm.delta
+ (0, 5)
+
+ The transaction manager doesn's call tpc_begin, because commit_sub
+ implies the start of two-phase commit. Next, it does call commit:
+
+ >>> jar.commit(dma, t1)
+
+ which doesn't do anything.
+
+ Finally, the transaction calls tpc_vote:
+
+ >>> jar.tpc_vote(t1)
+
+ which actually does something (because this is the top-level txn):
+
+ >>> dm.state, dm.delta
+ (5, 5)
+ >>> dm.prepared
+ True
+
+ Now, at the last minute, the transaction is aborted (possibly due
+ to a "no vote" from another data manager):
+
+ >>> jar.tpc_abort(t1)
+
+ An the changes are undone:
+
+ >>> dm.state, dm.delta
+ (0, 0)
+ >>> dm.prepared
+ False
+ """
+
def test_suite():
return unittest.TestSuite((
DocTestSuite(),
More information about the Zope-Checkins
mailing list