Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
ZODB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
ZODB
Commits
a910b691
Commit
a910b691
authored
May 06, 2007
by
Jim Fulton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Removed the synch option to DB and Connection open.
Removed subtransaction support.
parent
f73688b1
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
14 additions
and
426 deletions
+14
-426
src/ZODB/Connection.py
src/ZODB/Connection.py
+7
-25
src/ZODB/DB.py
src/ZODB/DB.py
+2
-4
src/ZODB/interfaces.py
src/ZODB/interfaces.py
+1
-8
src/ZODB/tests/testConnection.py
src/ZODB/tests/testConnection.py
+0
-35
src/ZODB/tests/testConnectionSavepoint.py
src/ZODB/tests/testConnectionSavepoint.py
+2
-6
src/ZODB/tests/testSubTransaction.py
src/ZODB/tests/testSubTransaction.py
+0
-179
src/ZODB/tests/testZODB.py
src/ZODB/tests/testZODB.py
+2
-169
No files found.
src/ZODB/Connection.py
View file @
a910b691
...
@@ -88,8 +88,6 @@ class Connection(ExportImport, object):
...
@@ -88,8 +88,6 @@ class Connection(ExportImport, object):
# Multi-database support
# Multi-database support
self
.
connections
=
{
self
.
_db
.
database_name
:
self
}
self
.
connections
=
{
self
.
_db
.
database_name
:
self
}
self
.
_synch
=
None
self
.
_version
=
version
self
.
_version
=
version
self
.
_normal_storage
=
self
.
_storage
=
db
.
_storage
self
.
_normal_storage
=
self
.
_storage
=
db
.
_storage
self
.
new_oid
=
db
.
_storage
.
new_oid
self
.
new_oid
=
db
.
_storage
.
new_oid
...
@@ -283,9 +281,8 @@ class Connection(ExportImport, object):
...
@@ -283,9 +281,8 @@ class Connection(ExportImport, object):
self
.
_debug_info
=
()
self
.
_debug_info
=
()
if
self
.
_
synch
:
if
self
.
_
opened
:
self
.
transaction_manager
.
unregisterSynch
(
self
)
self
.
transaction_manager
.
unregisterSynch
(
self
)
self
.
_synch
=
None
if
primary
:
if
primary
:
for
connection
in
self
.
connections
.
values
():
for
connection
in
self
.
connections
.
values
():
...
@@ -347,7 +344,7 @@ class Connection(ExportImport, object):
...
@@ -347,7 +344,7 @@ class Connection(ExportImport, object):
if
connection
is
None
:
if
connection
is
None
:
new_con
=
self
.
_db
.
databases
[
database_name
].
open
(
new_con
=
self
.
_db
.
databases
[
database_name
].
open
(
transaction_manager
=
self
.
transaction_manager
,
transaction_manager
=
self
.
transaction_manager
,
version
=
self
.
_version
,
synch
=
self
.
_synch
,
version
=
self
.
_version
,
)
)
self
.
connections
.
update
(
new_con
.
connections
)
self
.
connections
.
update
(
new_con
.
connections
)
new_con
.
connections
=
self
.
connections
new_con
.
connections
=
self
.
connections
...
@@ -452,8 +449,6 @@ class Connection(ExportImport, object):
...
@@ -452,8 +449,6 @@ class Connection(ExportImport, object):
def
_tpc_cleanup
(
self
):
def
_tpc_cleanup
(
self
):
"""Performs cleanup operations to support tpc_finish and tpc_abort."""
"""Performs cleanup operations to support tpc_finish and tpc_abort."""
self
.
_conflicts
.
clear
()
self
.
_conflicts
.
clear
()
if
not
self
.
_synch
:
self
.
_flush_invalidations
()
self
.
_needs_to_join
=
True
self
.
_needs_to_join
=
True
self
.
_registered_objects
=
[]
self
.
_registered_objects
=
[]
self
.
_creating
.
clear
()
self
.
_creating
.
clear
()
...
@@ -648,12 +643,6 @@ class Connection(ExportImport, object):
...
@@ -648,12 +643,6 @@ class Connection(ExportImport, object):
# return an exception object and expect that the Connection
# return an exception object and expect that the Connection
# will raise the exception.
# will raise the exception.
# When commit_sub() exceutes a store, there is no need to
# update the _p_changed flag, because the subtransaction
# tpc_vote() calls already did this. The change=1 argument
# exists to allow commit_sub() to avoid setting the flag
# again.
# When conflict resolution occurs, the object state held by
# When conflict resolution occurs, the object state held by
# the connection does not match what is written to the
# the connection does not match what is written to the
# database. Invalidate the object here to guarantee that
# database. Invalidate the object here to guarantee that
...
@@ -970,7 +959,7 @@ class Connection(ExportImport, object):
...
@@ -970,7 +959,7 @@ class Connection(ExportImport, object):
# return a list of [ghosts....not recently used.....recently used]
# return a list of [ghosts....not recently used.....recently used]
return
everything
.
items
()
+
items
return
everything
.
items
()
+
items
def
open
(
self
,
transaction_manager
=
None
,
synch
=
True
,
delegate
=
True
):
def
open
(
self
,
transaction_manager
=
None
,
delegate
=
True
):
"""Register odb, the DB that this Connection uses.
"""Register odb, the DB that this Connection uses.
This method is called by the DB every time a Connection
This method is called by the DB every time a Connection
...
@@ -984,16 +973,10 @@ class Connection(ExportImport, object):
...
@@ -984,16 +973,10 @@ class Connection(ExportImport, object):
odb: database that owns the Connection
odb: database that owns the Connection
transaction_manager: transaction manager to use. None means
transaction_manager: transaction manager to use. None means
use the default transaction manager.
use the default transaction manager.
synch: boolean indicating whether Connection should
register for afterCompletion() calls.
register for afterCompletion() calls.
"""
"""
# TODO: Why do we go to all the trouble of setting _db and
# other attributes on open and clearing them on close?
# A Connection is only ever associated with a single DB
# and Storage.
self
.
_opened
=
time
()
self
.
_opened
=
time
()
self
.
_synch
=
synch
if
transaction_manager
is
None
:
if
transaction_manager
is
None
:
transaction_manager
=
transaction
.
manager
transaction_manager
=
transaction
.
manager
...
@@ -1006,8 +989,7 @@ class Connection(ExportImport, object):
...
@@ -1006,8 +989,7 @@ class Connection(ExportImport, object):
else
:
else
:
self
.
_flush_invalidations
()
self
.
_flush_invalidations
()
if
synch
:
transaction_manager
.
registerSynch
(
self
)
transaction_manager
.
registerSynch
(
self
)
if
self
.
_cache
is
not
None
:
if
self
.
_cache
is
not
None
:
self
.
_cache
.
incrgc
()
# This is a good time to do some GC
self
.
_cache
.
incrgc
()
# This is a good time to do some GC
...
@@ -1016,7 +998,7 @@ class Connection(ExportImport, object):
...
@@ -1016,7 +998,7 @@ class Connection(ExportImport, object):
# delegate open to secondary connections
# delegate open to secondary connections
for
connection
in
self
.
connections
.
values
():
for
connection
in
self
.
connections
.
values
():
if
connection
is
not
self
:
if
connection
is
not
self
:
connection
.
open
(
transaction_manager
,
synch
,
False
)
connection
.
open
(
transaction_manager
,
False
)
def
_resetCache
(
self
):
def
_resetCache
(
self
):
"""Creates a new cache, discarding the old one.
"""Creates a new cache, discarding the old one.
...
@@ -1111,7 +1093,7 @@ class Connection(ExportImport, object):
...
@@ -1111,7 +1093,7 @@ class Connection(ExportImport, object):
src
.
reset
(
*
state
)
src
.
reset
(
*
state
)
def
_commit_savepoint
(
self
,
transaction
):
def
_commit_savepoint
(
self
,
transaction
):
"""Commit all changes made in s
ubtransaction
s and begin 2-phase commit
"""Commit all changes made in s
avepoint
s and begin 2-phase commit
"""
"""
src
=
self
.
_savepoint_storage
src
=
self
.
_savepoint_storage
self
.
_storage
=
self
.
_normal_storage
self
.
_storage
=
self
.
_normal_storage
...
@@ -1143,7 +1125,7 @@ class Connection(ExportImport, object):
...
@@ -1143,7 +1125,7 @@ class Connection(ExportImport, object):
src
.
close
()
src
.
close
()
def
_abort_savepoint
(
self
):
def
_abort_savepoint
(
self
):
"""Discard all s
ubtransaction
data."""
"""Discard all s
avepoint
data."""
src
=
self
.
_savepoint_storage
src
=
self
.
_savepoint_storage
self
.
_storage
=
self
.
_normal_storage
self
.
_storage
=
self
.
_normal_storage
self
.
_savepoint_storage
=
None
self
.
_savepoint_storage
=
None
...
...
src/ZODB/DB.py
View file @
a910b691
...
@@ -554,7 +554,7 @@ class DB(object):
...
@@ -554,7 +554,7 @@ class DB(object):
def
objectCount
(
self
):
def
objectCount
(
self
):
return
len
(
self
.
_storage
)
return
len
(
self
.
_storage
)
def
open
(
self
,
version
=
''
,
transaction_manager
=
None
,
synch
=
True
):
def
open
(
self
,
version
=
''
,
transaction_manager
=
None
):
"""Return a database Connection for use by application code.
"""Return a database Connection for use by application code.
The optional `version` argument can be used to specify that a
The optional `version` argument can be used to specify that a
...
@@ -569,8 +569,6 @@ class DB(object):
...
@@ -569,8 +569,6 @@ class DB(object):
in, defaults to no version.
in, defaults to no version.
- `transaction_manager`: transaction manager to use. None means
- `transaction_manager`: transaction manager to use. None means
use the default transaction manager.
use the default transaction manager.
- `synch`: boolean indicating whether Connection should
register for afterCompletion() calls.
"""
"""
if
version
:
if
version
:
...
@@ -607,7 +605,7 @@ class DB(object):
...
@@ -607,7 +605,7 @@ class DB(object):
assert
result
is
not
None
assert
result
is
not
None
# Tell the connection it belongs to self.
# Tell the connection it belongs to self.
result
.
open
(
transaction_manager
,
synch
)
result
.
open
(
transaction_manager
)
# A good time to do some cache cleanup.
# A good time to do some cache cleanup.
self
.
_connectionMap
(
lambda
c
:
c
.
cacheGC
())
self
.
_connectionMap
(
lambda
c
:
c
.
cacheGC
())
...
...
src/ZODB/interfaces.py
View file @
a910b691
...
@@ -355,20 +355,13 @@ class IDatabase(IStorageDB):
...
@@ -355,20 +355,13 @@ class IDatabase(IStorageDB):
entry.
entry.
"""
)
"""
)
def
open
(
version
=
''
,
def
open
(
version
=
''
,
transaction_manager
=
None
):
mvcc
=
True
,
transaction_manager
=
None
,
synch
=
True
):
"""Return an IConnection object for use by application code.
"""Return an IConnection object for use by application code.
version: the "version" that all changes will be made
version: the "version" that all changes will be made
in, defaults to no version.
in, defaults to no version.
mvcc: boolean indicating whether MVCC is enabled
transaction_manager: transaction manager to use. None means
transaction_manager: transaction manager to use. None means
use the default transaction manager.
use the default transaction manager.
synch: boolean indicating whether Connection should
register for afterCompletion() calls.
Note that the connection pool is managed as a stack, to
Note that the connection pool is managed as a stack, to
increase the likelihood that the connection's stack will
increase the likelihood that the connection's stack will
...
...
src/ZODB/tests/testConnection.py
View file @
a910b691
...
@@ -24,12 +24,6 @@ from ZODB.utils import p64, u64
...
@@ -24,12 +24,6 @@ from ZODB.utils import p64, u64
from
ZODB.tests.warnhook
import
WarningsHook
from
ZODB.tests.warnhook
import
WarningsHook
from
zope.interface.verify
import
verifyObject
from
zope.interface.verify
import
verifyObject
# deprecated37 remove when subtransactions go away
# Don't complain about subtxns in these tests.
warnings
.
filterwarnings
(
"ignore"
,
".*
\
n
subtransactions are deprecated"
,
DeprecationWarning
,
__name__
)
class
ConnectionDotAdd
(
unittest
.
TestCase
):
class
ConnectionDotAdd
(
unittest
.
TestCase
):
def
setUp
(
self
):
def
setUp
(
self
):
...
@@ -292,35 +286,6 @@ class UserMethodTests(unittest.TestCase):
...
@@ -292,35 +286,6 @@ class UserMethodTests(unittest.TestCase):
10
10
>>> cn.close(); cn2.close()
>>> cn.close(); cn2.close()
Bug: We weren't catching the case where the only changes pending
were in a subtransaction.
>>> cn = db.open()
>>> cn.root()['a'] = 100
>>> transaction.commit(True)
>>> cn.close() # this was succeeding
Traceback (most recent call last):
...
ConnectionStateError: Cannot close a connection joined to a transaction
Again this leaves the connection as it was.
>>> transaction.commit()
>>> cn2 = db.open()
>>> cn2.root()['a']
100
>>> cn.close(); cn2.close()
Make sure we can still close a connection after aborting a pending
subtransaction.
>>> cn = db.open()
>>> cn.root()['a'] = 1000
>>> transaction.commit(True)
>>> cn.root()['a']
1000
>>> transaction.abort()
>>> cn.root()['a']
100
>>> cn.close()
>>> db.close()
>>> db.close()
"""
"""
...
...
src/ZODB/tests/testConnectionSavepoint.py
View file @
a910b691
...
@@ -54,10 +54,7 @@ savepoint.
...
@@ -54,10 +54,7 @@ savepoint.
The problem was that we were effectively commiting the object twice --
The problem was that we were effectively commiting the object twice --
when commiting the current data and when committing the savepoint.
when commiting the current data and when committing the savepoint.
The fix was to first make a new savepoint to move new changes to the
The fix was to first make a new savepoint to move new changes to the
savepoint storage and *then* to commit the savepoint storage. (This is
savepoint storage and *then* to commit the savepoint storage.
similar to the strategy that was used for subtransactions prior to
savepoints.)
>>> import ZODB.tests.util
>>> import ZODB.tests.util
>>> db = ZODB.tests.util.DB()
>>> db = ZODB.tests.util.DB()
...
@@ -90,8 +87,7 @@ def testSavepointDoesCacheGC():
...
@@ -90,8 +87,7 @@ def testSavepointDoesCacheGC():
"""
\
"""
\
Although the interface doesn't guarantee this internal detail, making a
Although the interface doesn't guarantee this internal detail, making a
savepoint should do incremental gc on connection memory caches. Indeed,
savepoint should do incremental gc on connection memory caches. Indeed,
one traditional use for savepoints (started by the older, related
one traditional use for savepoints is simply to free memory space midstream
"subtransaction commit" idea) is simply to free memory space midstream
during a long transaction. Before ZODB 3.4.2, making a savepoint failed
during a long transaction. Before ZODB 3.4.2, making a savepoint failed
to trigger cache gc, and this test verifies that it now does.
to trigger cache gc, and this test verifies that it now does.
...
...
src/ZODB/tests/testSubTransaction.py
deleted
100644 → 0
View file @
f73688b1
##############################################################################
#
# Copyright (c) 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""
ZODB subtransaction tests
=========================
Subtransactions are deprecated. First we install a hook, to verify that
deprecation warnings are generated.
>>> hook = WarningsHook()
>>> hook.install()
Subtransactions are provided by a generic transaction interface, but
only supported by ZODB. These tests verify that some of the important
cases work as expected.
>>> import transaction
>>> from ZODB import DB
>>> from ZODB.tests.test_storage import MinimalMemoryStorage
>>> from ZODB.tests.MinPO import MinPO
First create a few objects in the database root with a normal commit.
We're going to make a series of modifications to these objects.
>>> db = DB(MinimalMemoryStorage())
>>> cn = db.open()
>>> rt = cn.root()
>>> def init():
... global a, b, c
... a = rt["a"] = MinPO("a0")
... b = rt["b"] = MinPO("b0")
... c = rt["c"] = MinPO("c0")
... transaction.commit()
>>> init()
We'll also open a second database connection and use it to verify that
the intermediate results of subtransactions are not visible to other
connections.
>>> cn2 = db.open(synch=False)
>>> rt2 = cn2.root()
>>> shadow_a = rt2["a"]
>>> shadow_b = rt2["b"]
>>> shadow_c = rt2["c"]
Subtransaction commit
---------------------
We'll make a series of modifications in subtransactions.
>>> a.value = "a1"
>>> b.value = "b1"
>>> transaction.commit(1)
>>> a.value, b.value
('a1', 'b1')
>>> shadow_a.value, shadow_b.value
('a0', 'b0')
The subtransaction commit should have generated a deprecation wng:
>>> len(hook.warnings)
1
>>> message, category, filename, lineno = hook.warnings[0]
>>> print message
This will be removed in ZODB 3.7:
subtransactions are deprecated; use transaction.savepoint() instead of
\
transaction.commit(1)
>>> category.__name__
'DeprecationWarning'
>>> hook.clear()
>>> a.value = "a2"
>>> c.value = "c1"
>>> transaction.commit(1)
>>> a.value, c.value
('a2', 'c1')
>>> shadow_a.value, shadow_c.value
('a0', 'c0')
>>> a.value = "a3"
>>> transaction.commit(1)
>>> a.value
'a3'
>>> shadow_a.value
'a0'
>>> transaction.commit()
>>> a.value, b.value, c.value
('a3', 'b1', 'c1')
Subtransaction with nested abort
--------------------------------
>>> init()
>>> a.value = "a1"
>>> transaction.commit(1)
>>> b.value = "b1"
>>> transaction.commit(1)
A sub-transaction abort will undo current changes, reverting to the
database state as of the last sub-transaction commit. There is
(apparently) no way to abort an already-committed subtransaction.
>>> c.value = "c1"
>>> transaction.abort(1)
>>> a.value, b.value, c.value
('a1', 'b1', 'c0')
The subtxn abort should also have generated a deprecation warning:
>>> len(hook.warnings)
1
>>> message, category, filename, lineno = hook.warnings[0]
>>> print message
This will be removed in ZODB 3.7:
subtransactions are deprecated; use sp.rollback() instead of
\
transaction.abort(1), where `sp` is the corresponding savepoint
\
captured earlier
>>> category.__name__
'DeprecationWarning'
>>> hook.clear()
Multiple aborts have no extra effect.
>>> transaction.abort(1)
>>> a.value, b.value, c.value
('a1', 'b1', 'c0')
>>> transaction.commit()
>>> a.value, b.value, c.value
('a1', 'b1', 'c0')
Subtransaction with top-level abort
-----------------------------------
>>> init()
>>> a.value = "a1"
>>> transaction.commit(1)
>>> b.value = "b1"
>>> transaction.commit(1)
A sub-transaction abort will undo current changes, reverting to the
database state as of the last sub-transaction commit. There is
(apparently) no way to abort an already-committed subtransaction.
>>> c.value = "c1"
>>> transaction.abort(1)
>>> transaction.abort()
>>> a.value, b.value, c.value
('a0', 'b0', 'c0')
We have to uninstall the hook so that other warnings don't get lost.
>>> len(hook.warnings) # we don't expect we captured other warnings
0
>>> hook.uninstall()
"""
from
ZODB.tests.warnhook
import
WarningsHook
from
zope.testing
import
doctest
def
test_suite
():
return
doctest
.
DocTestSuite
()
src/ZODB/tests/testZODB.py
View file @
a910b691
...
@@ -25,11 +25,7 @@ from persistent import Persistent
...
@@ -25,11 +25,7 @@ from persistent import Persistent
from
persistent.mapping
import
PersistentMapping
from
persistent.mapping
import
PersistentMapping
import
transaction
import
transaction
# deprecated37 remove when subtransactions go away
# deprecated39 remove when versions go away
# Don't complain about subtxns in these tests.
warnings
.
filterwarnings
(
"ignore"
,
".*
\
n
subtransactions are deprecated"
,
DeprecationWarning
,
__name__
)
warnings
.
filterwarnings
(
"ignore"
,
warnings
.
filterwarnings
(
"ignore"
,
"Versions are deprecated"
,
"Versions are deprecated"
,
DeprecationWarning
,
__name__
)
DeprecationWarning
,
__name__
)
...
@@ -217,70 +213,6 @@ class ZODBTests(unittest.TestCase):
...
@@ -217,70 +213,6 @@ class ZODBTests(unittest.TestCase):
conn1
.
close
()
conn1
.
close
()
conn2
.
close
()
conn2
.
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
tm1
=
transaction
.
TransactionManager
()
conn
=
self
.
_db
.
open
(
transaction_manager
=
tm1
)
r1
=
conn
.
root
()
p
=
P
()
p
.
value
=
1
r1
[
"p"
]
=
p
q
=
P
()
q
.
value
=
2
r1
[
"q"
]
=
q
tm1
.
commit
()
# Now txn T1 changes p.value to 3 locally (subtxn commit).
p
.
value
=
3
tm1
.
commit
(
True
)
# Start new txn T2 with a new connection.
tm2
=
transaction
.
TransactionManager
()
cn2
=
self
.
_db
.
open
(
transaction_manager
=
tm2
)
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
tm2
.
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
()
tm1
.
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
:
tm1
.
abort
()
def
checkSavepointDoesntGetInvalidations
(
self
):
def
checkSavepointDoesntGetInvalidations
(
self
):
# Prior to ZODB 3.2.9 and 3.4, Connection.tpc_finish() processed
# Prior to ZODB 3.2.9 and 3.4, Connection.tpc_finish() processed
# invalidations even for a subtxn commit. This could make
# invalidations even for a subtxn commit. This could make
...
@@ -357,23 +289,14 @@ class ZODBTests(unittest.TestCase):
...
@@ -357,23 +289,14 @@ class ZODBTests(unittest.TestCase):
rt
=
cn
.
root
()
rt
=
cn
.
root
()
self
.
assertRaises
(
KeyError
,
rt
.
__getitem__
,
'a'
)
self
.
assertRaises
(
KeyError
,
rt
.
__getitem__
,
'a'
)
# A longstanding bug: this didn't work if changes were only in
# subtransactions.
transaction
.
begin
()
rt
=
cn
.
root
()
rt
[
'a'
]
=
2
transaction
.
commit
(
1
)
transaction
.
begin
()
transaction
.
begin
()
rt
=
cn
.
root
()
rt
=
cn
.
root
()
self
.
assertRaises
(
KeyError
,
rt
.
__getitem__
,
'a'
)
self
.
assertRaises
(
KeyError
,
rt
.
__getitem__
,
'a'
)
# One more time
, mixing "top level" and subtransaction changes
.
# One more time.
transaction
.
begin
()
transaction
.
begin
()
rt
=
cn
.
root
()
rt
=
cn
.
root
()
rt
[
'a'
]
=
3
rt
[
'a'
]
=
3
transaction
.
commit
(
1
)
rt
[
'b'
]
=
4
transaction
.
begin
()
transaction
.
begin
()
rt
=
cn
.
root
()
rt
=
cn
.
root
()
...
@@ -389,7 +312,6 @@ class ZODBTests(unittest.TestCase):
...
@@ -389,7 +312,6 @@ class ZODBTests(unittest.TestCase):
# rest of this test was tossed.
# rest of this test was tossed.
def
checkFailingCommitSticks
(
self
):
def
checkFailingCommitSticks
(
self
):
# See also checkFailingSubtransactionCommitSticks.
# See also checkFailingSavepointSticks.
# See also checkFailingSavepointSticks.
cn
=
self
.
_db
.
open
()
cn
=
self
.
_db
.
open
()
rt
=
cn
.
root
()
rt
=
cn
.
root
()
...
@@ -435,93 +357,6 @@ class ZODBTests(unittest.TestCase):
...
@@ -435,93 +357,6 @@ class ZODBTests(unittest.TestCase):
cn
.
close
()
cn
.
close
()
def
checkFailingSubtransactionCommitSticks
(
self
):
cn
=
self
.
_db
.
open
()
rt
=
cn
.
root
()
rt
[
'a'
]
=
1
transaction
.
commit
(
True
)
self
.
assertEqual
(
rt
[
'a'
],
1
)
rt
[
'b'
]
=
2
# Make a jar that raises PoisonedError when a subtxn commit is done.
poisoned
=
PoisonedJar
(
break_savepoint
=
True
)
transaction
.
get
().
join
(
poisoned
)
# We're using try/except here instead of assertRaises so that this
# module's attempt to suppress subtransaction deprecation wngs
# works.
try
:
transaction
.
commit
(
True
)
except
PoisonedError
:
pass
else
:
self
.
fail
(
"expected PoisonedError"
)
# Trying to subtxn-commit again fails too.
try
:
transaction
.
commit
(
True
)
except
TransactionFailedError
:
pass
else
:
self
.
fail
(
"expected TransactionFailedError"
)
try
:
transaction
.
commit
(
True
)
except
TransactionFailedError
:
pass
else
:
self
.
fail
(
"expected TransactionFailedError"
)
# Top-level commit also fails.
self
.
assertRaises
(
TransactionFailedError
,
transaction
.
commit
)
# The changes to rt['a'] and rt['b'] are lost.
self
.
assertRaises
(
KeyError
,
rt
.
__getitem__
,
'a'
)
self
.
assertRaises
(
KeyError
,
rt
.
__getitem__
,
'b'
)
# Trying to modify an object also fails, because Transaction.join()
# also raises TransactionFailedError.
self
.
assertRaises
(
TransactionFailedError
,
rt
.
__setitem__
,
'b'
,
2
)
# Clean up via abort(), and try again.
transaction
.
abort
()
rt
[
'a'
]
=
1
transaction
.
commit
()
self
.
assertEqual
(
rt
[
'a'
],
1
)
# Cleaning up via begin() should also work.
rt
[
'a'
]
=
2
transaction
.
get
().
join
(
poisoned
)
try
:
transaction
.
commit
(
True
)
except
PoisonedError
:
pass
else
:
self
.
fail
(
"expected PoisonedError"
)
# Trying to subtxn-commit again fails too.
try
:
transaction
.
commit
(
True
)
except
TransactionFailedError
:
pass
else
:
self
.
fail
(
"expected TransactionFailedError"
)
# The change to rt['a'] is lost.
self
.
assertEqual
(
rt
[
'a'
],
1
)
# Trying to modify an object also fails.
self
.
assertRaises
(
TransactionFailedError
,
rt
.
__setitem__
,
'b'
,
2
)
# Clean up via begin(), and try again.
transaction
.
begin
()
rt
[
'a'
]
=
2
transaction
.
commit
(
True
)
self
.
assertEqual
(
rt
[
'a'
],
2
)
transaction
.
get
().
commit
()
cn2
=
self
.
_db
.
open
()
rt
=
cn
.
root
()
self
.
assertEqual
(
rt
[
'a'
],
2
)
cn
.
close
()
cn2
.
close
()
def
checkFailingSavepointSticks
(
self
):
def
checkFailingSavepointSticks
(
self
):
cn
=
self
.
_db
.
open
()
cn
=
self
.
_db
.
open
()
rt
=
cn
.
root
()
rt
=
cn
.
root
()
...
@@ -786,8 +621,6 @@ class PoisonedJar:
...
@@ -786,8 +621,6 @@ class PoisonedJar:
def
sortKey
(
self
):
def
sortKey
(
self
):
return
str
(
id
(
self
))
return
str
(
id
(
self
))
# A way that used to poison a subtransaction commit. With the current
# implementation of subtxns, pass break_savepoint=True instead.
def
tpc_begin
(
self
,
*
args
):
def
tpc_begin
(
self
,
*
args
):
if
self
.
break_tpc_begin
:
if
self
.
break_tpc_begin
:
raise
PoisonedError
(
"tpc_begin fails"
)
raise
PoisonedError
(
"tpc_begin fails"
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment