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
Kirill Smelkov
ZODB
Commits
420984b7
Commit
420984b7
authored
Jul 18, 2016
by
Julien Muchembled
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Drop old commit protocol
parent
683f7faf
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
92 additions
and
324 deletions
+92
-324
src/ZODB/ConflictResolution.py
src/ZODB/ConflictResolution.py
+0
-2
src/ZODB/Connection.py
src/ZODB/Connection.py
+22
-57
src/ZODB/blob.py
src/ZODB/blob.py
+1
-2
src/ZODB/interfaces.py
src/ZODB/interfaces.py
+3
-48
src/ZODB/multicommitadapter.py
src/ZODB/multicommitadapter.py
+0
-65
src/ZODB/mvccadapter.py
src/ZODB/mvccadapter.py
+3
-9
src/ZODB/tests/StorageTestBase.py
src/ZODB/tests/StorageTestBase.py
+6
-8
src/ZODB/tests/TransactionalUndoStorage.py
src/ZODB/tests/TransactionalUndoStorage.py
+56
-130
src/ZODB/tests/testConnection.py
src/ZODB/tests/testConnection.py
+1
-3
No files found.
src/ZODB/ConflictResolution.py
View file @
420984b7
...
...
@@ -28,8 +28,6 @@ from pickle import PicklingError
logger
=
logging
.
getLogger
(
'ZODB.ConflictResolution'
)
ResolvedSerial
=
b'rs'
# deprecated: see IMultiCommitStorage.tpc_vote
class
BadClassName
(
Exception
):
pass
...
...
src/ZODB/Connection.py
View file @
420984b7
...
...
@@ -37,7 +37,6 @@ import transaction
import
ZODB
from
ZODB.blob
import
SAVEPOINT_SUFFIX
from
ZODB.ConflictResolution
import
ResolvedSerial
from
ZODB.ExportImport
import
ExportImport
from
ZODB
import
POSException
from
ZODB.POSException
import
InvalidObjectReference
,
ConnectionStateError
...
...
@@ -589,27 +588,13 @@ class Connection(ExportImport, object):
self
.
_cache
.
update_object_size_estimation
(
oid
,
len
(
p
))
obj
.
_p_estimated_size
=
len
(
p
)
self
.
_handle_serial
(
oid
,
s
)
def
_handle_serial
(
self
,
oid
,
serial
=
ResolvedSerial
,
change
=
True
):
# if we write an object, we don't want to check if it was read
# while current. This is a convenient choke point to do this.
self
.
_readCurrent
.
pop
(
oid
,
None
)
if
not
serial
:
return
assert
isinstance
(
serial
,
bytes
),
serial
obj
=
self
.
_cache
.
get
(
oid
,
None
)
if
obj
is
None
:
return
if
serial
==
ResolvedSerial
:
del
obj
.
_p_changed
# transition from changed to ghost
else
:
self
.
_warn_about_returned_serial
()
if
change
:
if
s
:
# savepoint
obj
.
_p_changed
=
0
# transition from changed to up-to-date
obj
.
_p_serial
=
serial
obj
.
_p_serial
=
s
def
tpc_abort
(
self
,
transaction
):
if
self
.
_import
:
...
...
@@ -674,21 +659,17 @@ class Connection(ExportImport, object):
if
v
.
oid
:
self
.
_cache
.
invalidate
(
v
.
oid
)
raise
if
s
:
if
type
(
next
(
iter
(
s
)))
is
bytes
:
# Resolved conflicts.
for
oid
in
s
:
self
.
_handle_serial
(
oid
)
return
self
.
_warn_about_returned_serial
()
for
oid
,
serial
in
s
:
self
.
_handle_serial
(
oid
,
serial
)
obj
=
self
.
_cache
.
get
(
oid
)
if
obj
is
not
None
:
del
obj
.
_p_changed
# transition from changed to ghost
def
tpc_finish
(
self
,
transaction
):
"""Indicate confirmation that the transaction is done.
"""
serial
=
self
.
_storage
.
tpc_finish
(
transaction
)
if
serial
is
not
None
:
assert
type
(
serial
)
is
bytes
,
repr
(
serial
)
for
oid_iterator
in
self
.
_modified
,
self
.
_creating
:
for
oid
in
oid_iterator
:
...
...
@@ -697,23 +678,8 @@ class Connection(ExportImport, object):
if
obj
is
not
None
and
obj
.
_p_changed
is
not
None
:
obj
.
_p_changed
=
0
obj
.
_p_serial
=
serial
else
:
self
.
_warn_about_returned_serial
()
self
.
_tpc_cleanup
()
def
_warn_about_returned_serial
(
self
):
# Do not warn about own implementations of ZODB.
# We're aware and the user can't do anything about it.
if
self
.
_normal_storage
.
__module__
.
startswith
(
"_ZODB."
):
self
.
_warn_about_returned_serial
=
lambda
:
None
else
:
warnings
.
warn
(
"In ZODB 5+, the new API for the returned value of"
" store/tpc_vote/tpc_finish will be mandatory."
" See IStorage for more information."
,
DeprecationWarning
,
2
)
Connection
.
_warn_about_returned_serial
=
lambda
self
:
None
def
sortKey
(
self
):
"""Return a consistent sort key for this connection."""
return
"%s:%s"
%
(
self
.
_storage
.
sortKey
(),
id
(
self
))
...
...
@@ -1033,7 +999,7 @@ class Connection(ExportImport, object):
obj
.
_p_estimated_size
=
len
(
data
)
if
isinstance
(
self
.
_reader
.
getGhost
(
data
),
Blob
):
blobfilename
=
src
.
loadBlob
(
oid
,
serial
)
s
=
s
elf
.
_storage
.
storeBlob
(
self
.
_storage
.
storeBlob
(
oid
,
serial
,
data
,
blobfilename
,
''
,
transaction
)
# we invalidate the object here in order to ensure
...
...
@@ -1042,10 +1008,9 @@ class Connection(ExportImport, object):
# to be reattached "cleanly"
self
.
_cache
.
invalidate
(
oid
)
else
:
s
=
self
.
_storage
.
store
(
oid
,
serial
,
data
,
''
,
transaction
)
self
.
_storage
.
store
(
oid
,
serial
,
data
,
''
,
transaction
)
self
.
_
handle_serial
(
oid
,
s
,
change
=
False
)
self
.
_
readCurrent
.
pop
(
oid
,
None
)
# same as in _store_objects(
)
finally
:
src
.
close
()
...
...
src/ZODB/blob.py
View file @
420984b7
...
...
@@ -709,9 +709,8 @@ class BlobStorageMixin(object):
transaction
):
"""Stores data that has a BLOB attached."""
assert
not
version
,
"Versions aren't supported."
se
rial
=
se
lf
.
store
(
oid
,
oldserial
,
data
,
''
,
transaction
)
self
.
store
(
oid
,
oldserial
,
data
,
''
,
transaction
)
self
.
_blob_storeblob
(
oid
,
self
.
_tid
,
blobfilename
)
return
serial
def
temporaryDirectory
(
self
):
return
self
.
fshelper
.
temp_dir
...
...
src/ZODB/interfaces.py
View file @
420984b7
...
...
@@ -653,23 +653,6 @@ class IStorage(Interface):
A transaction object. This should match the current
transaction for the storage, set by tpc_begin.
The new serial for the object is returned, but not necessarily
immediately. It may be returned directly, or on a subsequent
store or tpc_vote call.
The return value may be:
- None, or
- A new serial (string) for the object
If None is returned, then a new serial (or other special
values) must ve returned in tpc_vote results.
A serial, returned as a string, may be the special value
ZODB.ConflictResolution.ResolvedSerial to indicate that a
conflict occured and that the object should be invalidated.
Several different exceptions may be raised when an error occurs.
ConflictError
...
...
@@ -739,18 +722,8 @@ class IStorage(Interface):
without an error, then there must not be an error if
tpc_finish or tpc_abort is called subsequently.
The return value can be None or a sequence of object-id
and serial pairs giving new serials for objects whose ids were
passed to previous store calls in the same transaction. The serial
can be the special value ZODB.ConflictResolution.ResolvedSerial to
indicate that a conflict occurred and that the object should be
invalidated.
The return value can also be a sequence of object ids, as
described in IMultiCommitStorage.tpc_vote.
After the tpc_vote call, all solved conflicts must have been notified,
either from tpc_vote or store for objects passed to store.
The return value can be None or a sequence of a sequence of object ids,
as described in IMultiCommitStorage.tpc_vote.
"""
...
...
@@ -790,7 +763,7 @@ class IMultiCommitStorage(IStorage):
def
tpc_vote
(
transaction
):
"""Provide a storage with an opportunity to veto a transaction
See IStorage.
stor
e. For objects implementing this interface,
See IStorage.
tpc_vot
e. For objects implementing this interface,
the return value can be either None or a sequence of oids for which
a conflict was resolved.
"""
...
...
@@ -1236,24 +1209,6 @@ class IBlobStorage(Interface):
(or copy and remove it) immediately, or at transaction-commit
time. The file must not be open.
The new serial for the object is returned, but not necessarily
immediately. It may be returned directly, or on a subsequent
store or tpc_vote call.
The return value may be:
- None
- A new serial (string) for the object, or
- An iterable of object-id and serial pairs giving new serials
for objects.
A serial, returned as a string or in a sequence of oid/serial
pairs, may be the special value
ZODB.ConflictResolution.ResolvedSerial to indicate that a
conflict occured and that the object should be invalidated.
Several different exceptions may be raised when an error occurs.
ConflictError
...
...
src/ZODB/multicommitadapter.py
deleted
100644 → 0
View file @
683f7faf
"""Adapt non-IMultiCommitStorage storages to IMultiCommitStorage
"""
import
zope.interface
from
.ConflictResolution
import
ResolvedSerial
class
MultiCommitAdapter
:
def
__init__
(
self
,
storage
):
self
.
_storage
=
storage
ifaces
=
zope
.
interface
.
providedBy
(
storage
)
zope
.
interface
.
alsoProvides
(
self
,
ifaces
)
self
.
_resolved
=
set
()
# {OID}, here to make linters happy
def
__getattr__
(
self
,
name
):
v
=
getattr
(
self
.
_storage
,
name
)
self
.
__dict__
[
name
]
=
v
return
v
def
tpc_begin
(
self
,
*
args
):
self
.
_storage
.
tpc_begin
(
*
args
)
self
.
_resolved
=
set
()
def
store
(
self
,
oid
,
*
args
):
if
self
.
_storage
.
store
(
oid
,
*
args
)
==
ResolvedSerial
:
self
.
_resolved
.
add
(
oid
)
def
storeBlob
(
self
,
oid
,
*
args
):
s
=
self
.
_storage
.
storeBlob
(
oid
,
*
args
)
if
s
:
if
isinstance
(
s
,
bytes
):
s
=
((
oid
,
s
),
)
for
oid
,
serial
in
s
:
if
s
==
ResolvedSerial
:
self
.
_resolved
.
add
(
oid
)
def
undo
(
self
,
transaction_id
,
transaction
):
r
=
self
.
_storage
.
undo
(
transaction_id
,
transaction
)
if
r
:
self
.
_resolved
.
update
(
r
[
1
])
def
tpc_vote
(
self
,
*
args
):
s
=
self
.
_storage
.
tpc_vote
(
*
args
)
for
(
oid
,
serial
)
in
(
s
or
()):
if
serial
==
ResolvedSerial
:
self
.
_resolved
.
add
(
oid
)
return
self
.
_resolved
def
tpc_finish
(
self
,
transaction
,
f
=
lambda
tid
:
None
):
t
=
[]
def
func
(
tid
):
t
.
append
(
tid
)
f
(
tid
)
self
.
_storage
.
tpc_finish
(
transaction
,
func
)
return
t
[
0
]
def
__len__
(
self
):
return
len
(
self
.
_storage
)
src/ZODB/mvccadapter.py
View file @
420984b7
...
...
@@ -163,15 +163,13 @@ class MVCCAdapterInstance(Base):
self
.
_modified
=
set
()
def
store
(
self
,
oid
,
serial
,
data
,
version
,
transaction
):
s
=
s
elf
.
_storage
.
store
(
oid
,
serial
,
data
,
version
,
transaction
)
self
.
_storage
.
store
(
oid
,
serial
,
data
,
version
,
transaction
)
self
.
_modified
.
add
(
oid
)
return
s
def
storeBlob
(
self
,
oid
,
serial
,
data
,
blobfilename
,
version
,
transaction
):
s
=
s
elf
.
_storage
.
storeBlob
(
self
.
_storage
.
storeBlob
(
oid
,
serial
,
data
,
blobfilename
,
''
,
transaction
)
self
.
_modified
.
add
(
oid
)
return
s
def
tpc_finish
(
self
,
transaction
,
func
=
lambda
tid
:
None
):
modified
=
self
.
_modified
...
...
@@ -253,11 +251,7 @@ class UndoAdapterInstance(Base):
def
tpc_vote
(
self
,
transaction
):
result
=
self
.
_storage
.
tpc_vote
(
transaction
)
if
result
:
if
isinstance
(
next
(
iter
(
result
)),
bytes
):
self
.
_undone
.
update
(
result
)
else
:
for
oid
,
_
in
result
:
self
.
_undone
.
add
(
oid
)
def
tpc_finish
(
self
,
transaction
,
func
=
lambda
tid
:
None
):
...
...
src/ZODB/tests/StorageTestBase.py
View file @
420984b7
...
...
@@ -175,11 +175,9 @@ class StorageTestBase(ZODB.tests.util.TestCase):
self
.
_storage
.
tpc_begin
(
t
)
undo_result
=
self
.
_storage
.
undo
(
tid
,
t
)
vote_result
=
self
.
_storage
.
tpc_vote
(
t
)
serial
=
self
.
_storage
.
tpc_finish
(
t
)
if
expected_oids
is
not
None
and
serial
is
None
:
oids
=
list
(
undo_result
[
1
])
if
undo_result
else
[]
oids
.
extend
(
oid
for
(
oid
,
_
)
in
vote_result
or
())
self
.
assertEqual
(
len
(
oids
),
len
(
expected_oids
),
repr
(
oids
))
for
oid
in
expected_oids
:
self
.
assertTrue
(
oid
in
oids
)
return
self
.
_storage
.
lastTransaction
()
if
expected_oids
is
not
None
:
oids
=
set
(
undo_result
[
1
])
if
undo_result
else
set
()
if
vote_result
:
oids
.
update
(
vote_result
)
self
.
assertEqual
(
oids
,
set
(
expected_oids
))
return
self
.
_storage
.
tpc_finish
(
t
)
src/ZODB/tests/TransactionalUndoStorage.py
View file @
420984b7
...
...
@@ -52,46 +52,13 @@ def listeq(L1, L2):
class
TransactionalUndoStorage
:
def
_transaction_begin
(
self
):
self
.
__serials
=
{}
def
_transaction_store
(
self
,
oid
,
rev
,
data
,
vers
,
trans
):
r
=
self
.
_storage
.
store
(
oid
,
rev
,
data
,
vers
,
trans
)
if
r
:
if
isinstance
(
r
,
bytes
):
self
.
__serials
[
oid
]
=
r
else
:
for
oid
,
serial
in
r
:
self
.
__serials
[
oid
]
=
serial
def
_transaction_vote
(
self
,
trans
):
r
=
self
.
_storage
.
tpc_vote
(
trans
)
if
r
:
for
oid
,
serial
in
r
:
self
.
__serials
[
oid
]
=
serial
def
_transaction_newserial
(
self
,
oid
):
return
self
.
__serials
[
oid
]
def
_transaction_finish
(
self
,
t
,
oid_list
):
tid
=
self
.
_storage
.
tpc_finish
(
t
)
if
tid
is
not
None
:
for
oid
in
oid_list
:
self
.
__serials
[
oid
]
=
tid
def
_multi_obj_transaction
(
self
,
objs
):
newrevs
=
{}
t
=
Transaction
()
self
.
_storage
.
tpc_begin
(
t
)
self
.
_transaction_begin
()
for
oid
,
rev
,
data
in
objs
:
self
.
_transaction_store
(
oid
,
rev
,
data
,
''
,
t
)
newrevs
[
oid
]
=
None
self
.
_transaction_vote
(
t
)
self
.
_transaction_finish
(
t
,
[
x
[
0
]
for
x
in
objs
])
for
oid
in
newrevs
.
keys
():
newrevs
[
oid
]
=
self
.
_transaction_newserial
(
oid
)
return
newrevs
self
.
_storage
.
store
(
oid
,
rev
,
data
,
''
,
t
)
self
.
_storage
.
tpc_vote
(
t
)
return
self
.
_storage
.
tpc_finish
(
t
)
def
_iterate
(
self
):
"""Iterate over the storage in its final state."""
...
...
@@ -106,21 +73,17 @@ class TransactionalUndoStorage:
def
_begin_undos_vote
(
self
,
t
,
*
tids
):
self
.
_storage
.
tpc_begin
(
t
)
oids
=
[]
oids
=
set
()
for
tid
in
tids
:
undo_result
=
self
.
_storage
.
undo
(
tid
,
t
)
if
undo_result
:
oids
.
extend
(
undo_result
[
1
])
v
=
self
.
_storage
.
tpc_vote
(
t
)
if
v
:
if
isinstance
(
next
(
iter
(
v
)),
bytes
):
oids
.
extend
(
v
)
else
:
oids
.
extend
(
oid
for
(
oid
,
_
)
in
v
)
oids
.
update
(
undo_result
[
1
])
oids
.
update
(
self
.
_storage
.
tpc_vote
(
t
)
or
())
return
oids
def
undo
(
self
,
tid
,
note
):
def
undo
(
self
,
tid
,
note
=
None
):
t
=
Transaction
()
if
note
is
not
None
:
t
.
note
(
note
)
oids
=
self
.
_begin_undos_vote
(
t
,
tid
)
self
.
_storage
.
tpc_finish
(
t
)
...
...
@@ -165,10 +128,7 @@ class TransactionalUndoStorage:
# undo its creation
info
=
self
.
_storage
.
undoInfo
()
tid
=
info
[
0
][
'id'
]
t
=
Transaction
()
t
.
note
(
'undo1'
)
self
.
_begin_undos_vote
(
t
,
tid
)
self
.
_storage
.
tpc_finish
(
t
)
self
.
undo
(
tid
,
'undo1'
)
# Check that calling getTid on an uncreated object raises a KeyError
# The current version of FileStorage fails this test
self
.
assertRaises
(
KeyError
,
self
.
_storage
.
getTid
,
oid
)
...
...
@@ -224,27 +184,19 @@ class TransactionalUndoStorage:
# Store two objects in the same transaction
t
=
Transaction
()
self
.
_storage
.
tpc_begin
(
t
)
self
.
_transaction_begin
()
self
.
_transaction_store
(
oid1
,
revid1
,
p31
,
''
,
t
)
self
.
_transaction_store
(
oid2
,
revid2
,
p51
,
''
,
t
)
self
.
_storage
.
store
(
oid1
,
revid1
,
p31
,
''
,
t
)
self
.
_storage
.
store
(
oid2
,
revid2
,
p51
,
''
,
t
)
# Finish the transaction
self
.
_transaction_vote
(
t
)
self
.
_transaction_finish
(
t
,
[
oid1
,
oid2
])
revid1
=
self
.
_transaction_newserial
(
oid1
)
revid2
=
self
.
_transaction_newserial
(
oid2
)
eq
(
revid1
,
revid2
)
self
.
_storage
.
tpc_vote
(
t
)
tid
=
self
.
_storage
.
tpc_finish
(
t
)
# Update those same two objects
t
=
Transaction
()
self
.
_storage
.
tpc_begin
(
t
)
self
.
_transaction_begin
()
self
.
_transaction_store
(
oid1
,
revid1
,
p32
,
''
,
t
)
self
.
_transaction_store
(
oid2
,
revid2
,
p52
,
''
,
t
)
self
.
_storage
.
store
(
oid1
,
tid
,
p32
,
''
,
t
)
self
.
_storage
.
store
(
oid2
,
tid
,
p52
,
''
,
t
)
# Finish the transaction
self
.
_transaction_vote
(
t
)
self
.
_transaction_finish
(
t
,
[
oid1
,
oid2
])
revid1
=
self
.
_transaction_newserial
(
oid1
)
revid2
=
self
.
_transaction_newserial
(
oid2
)
eq
(
revid1
,
revid2
)
self
.
_storage
.
tpc_vote
(
t
)
self
.
_storage
.
tpc_finish
(
t
)
# Make sure the objects have the current value
data
,
revid1
=
load_current
(
self
.
_storage
,
oid1
)
eq
(
zodb_unpickle
(
data
),
MinPO
(
32
))
...
...
@@ -269,25 +221,18 @@ class TransactionalUndoStorage:
(
30
,
31
,
32
,
50
,
51
,
52
)))
oid1
=
self
.
_storage
.
new_oid
()
oid2
=
self
.
_storage
.
new_oid
()
revid1
=
revid2
=
ZERO
# Store two objects in the same transaction
d
=
self
.
_multi_obj_transaction
([(
oid1
,
revid1
,
p30
),
(
oid2
,
revid2
,
p50
),
tid
=
self
.
_multi_obj_transaction
([(
oid1
,
ZERO
,
p30
),
(
oid2
,
ZERO
,
p50
),
])
eq
(
d
[
oid1
],
d
[
oid2
])
# Update those same two objects
d
=
self
.
_multi_obj_transaction
([(
oid1
,
d
[
oid1
]
,
p31
),
(
oid2
,
d
[
oid2
]
,
p51
),
tid
=
self
.
_multi_obj_transaction
([(
oid1
,
tid
,
p31
),
(
oid2
,
tid
,
p51
),
])
eq
(
d
[
oid1
],
d
[
oid2
])
# Update those same two objects
d
=
self
.
_multi_obj_transaction
([(
oid1
,
d
[
oid1
]
,
p32
),
(
oid2
,
d
[
oid2
]
,
p52
),
tid
=
self
.
_multi_obj_transaction
([(
oid1
,
tid
,
p32
),
(
oid2
,
tid
,
p52
),
])
eq
(
d
[
oid1
],
d
[
oid2
])
revid1
=
self
.
_transaction_newserial
(
oid1
)
revid2
=
self
.
_transaction_newserial
(
oid2
)
eq
(
revid1
,
revid2
)
# Make sure the objects have the current value
data
,
revid1
=
load_current
(
self
.
_storage
,
oid1
)
eq
(
zodb_unpickle
(
data
),
MinPO
(
32
))
...
...
@@ -303,7 +248,7 @@ class TransactionalUndoStorage:
# We may get the finalization stuff called an extra time,
# depending on the implementation.
if
serial
is
None
:
self
.
assertEqual
(
set
(
oids
)
,
{
oid1
,
oid2
})
self
.
assertEqual
(
oids
,
{
oid1
,
oid2
})
data
,
revid1
=
load_current
(
self
.
_storage
,
oid1
)
eq
(
zodb_unpickle
(
data
),
MinPO
(
30
))
data
,
revid2
=
load_current
(
self
.
_storage
,
oid2
)
...
...
@@ -332,15 +277,11 @@ class TransactionalUndoStorage:
# Update those same two objects
t
=
Transaction
()
self
.
_storage
.
tpc_begin
(
t
)
self
.
_transaction_begin
()
self
.
_transaction_store
(
oid1
,
revid1
,
p32
,
''
,
t
)
self
.
_transaction_store
(
oid2
,
revid2
,
p52
,
''
,
t
)
self
.
_storage
.
store
(
oid1
,
revid1
,
p32
,
''
,
t
)
self
.
_storage
.
store
(
oid2
,
revid2
,
p52
,
''
,
t
)
# Finish the transaction
self
.
_transaction_vote
(
t
)
self
.
_transaction_finish
(
t
,
[
oid1
,
oid2
])
revid1
=
self
.
_transaction_newserial
(
oid1
)
revid2
=
self
.
_transaction_newserial
(
oid2
)
eq
(
revid1
,
revid2
)
self
.
_storage
.
tpc_vote
(
t
)
self
.
_storage
.
tpc_finish
(
t
)
# Now attempt to undo the transaction containing two objects
info
=
self
.
_storage
.
undoInfo
()
self
.
_undo
(
info
[
0
][
"id"
],
[
oid1
,
oid2
])
...
...
@@ -352,28 +293,17 @@ class TransactionalUndoStorage:
# one object.
t
=
Transaction
()
self
.
_storage
.
tpc_begin
(
t
)
self
.
_transaction_begin
()
self
.
_transaction_store
(
oid1
,
revid1
,
p33
,
''
,
t
)
self
.
_transaction_store
(
oid2
,
revid2
,
p53
,
''
,
t
)
self
.
_storage
.
store
(
oid1
,
revid1
,
p33
,
''
,
t
)
self
.
_storage
.
store
(
oid2
,
revid2
,
p53
,
''
,
t
)
# Finish the transaction
self
.
_transaction_vote
(
t
)
self
.
_transaction_finish
(
t
,
[
oid1
,
oid2
])
revid1
=
self
.
_transaction_newserial
(
oid1
)
revid2
=
self
.
_transaction_newserial
(
oid2
)
eq
(
revid1
,
revid2
)
self
.
_storage
.
tpc_vote
(
t
)
tid
=
self
.
_storage
.
tpc_finish
(
t
)
# Update in different transactions
revid1
=
self
.
_dostore
(
oid1
,
revid
=
revid1
,
data
=
MinPO
(
34
))
revid2
=
self
.
_dostore
(
oid2
,
revid
=
revid2
,
data
=
MinPO
(
54
))
revid1
=
self
.
_dostore
(
oid1
,
revid
=
tid
,
data
=
MinPO
(
34
))
revid2
=
self
.
_dostore
(
oid2
,
revid
=
tid
,
data
=
MinPO
(
54
))
# Now attempt to undo the transaction containing two objects
info
=
self
.
_storage
.
undoInfo
()
tid
=
info
[
1
][
'id'
]
t
=
Transaction
()
oids
=
self
.
_begin_undos_vote
(
t
,
tid
)
serial
=
self
.
_storage
.
tpc_finish
(
t
)
if
serial
is
None
:
eq
(
len
(
oids
),
1
)
self
.
assertTrue
(
oid1
in
oids
)
self
.
assertTrue
(
not
oid2
in
oids
)
self
.
undo
(
info
[
1
][
'id'
])
data
,
revid1
=
load_current
(
self
.
_storage
,
oid1
)
eq
(
zodb_unpickle
(
data
),
MinPO
(
33
))
data
,
revid2
=
load_current
(
self
.
_storage
,
oid2
)
...
...
@@ -406,25 +336,20 @@ class TransactionalUndoStorage:
t
=
Transaction
()
self
.
_storage
.
tpc_begin
(
t
)
self
.
_transaction_begin
()
self
.
_transaction_store
(
oid1
,
revid1
,
p81
,
''
,
t
)
self
.
_transaction_store
(
oid2
,
revid2
,
p91
,
''
,
t
)
self
.
_transaction_vote
(
t
)
self
.
_transaction_finish
(
t
,
[
oid1
,
oid2
])
revid1
=
self
.
_transaction_newserial
(
oid1
)
revid2
=
self
.
_transaction_newserial
(
oid2
)
eq
(
revid1
,
revid2
)
self
.
_storage
.
store
(
oid1
,
revid1
,
p81
,
''
,
t
)
self
.
_storage
.
store
(
oid2
,
revid2
,
p91
,
''
,
t
)
self
.
_storage
.
tpc_vote
(
t
)
tid
=
self
.
_storage
.
tpc_finish
(
t
)
# Make sure the objects have the expected values
data
,
revid_11
=
load_current
(
self
.
_storage
,
oid1
)
eq
(
zodb_unpickle
(
data
),
MinPO
(
81
))
data
,
revid_22
=
load_current
(
self
.
_storage
,
oid2
)
eq
(
zodb_unpickle
(
data
),
MinPO
(
91
))
eq
(
revid_11
,
revid1
)
eq
(
revid_22
,
revid2
)
eq
(
revid_11
,
tid
)
eq
(
revid_22
,
tid
)
# Now modify oid2
revid2
=
self
.
_dostore
(
oid2
,
revid
=
revid2
,
data
=
MinPO
(
92
))
self
.
assertNotEqual
(
revid1
,
revid2
)
self
.
assertNotEqual
(
revid2
,
revid_22
)
revid2
=
self
.
_dostore
(
oid2
,
tid
,
MinPO
(
92
))
self
.
assertNotEqual
(
tid
,
revid2
)
info
=
self
.
_storage
.
undoInfo
()
tid
=
info
[
1
][
'id'
]
t
=
Transaction
()
...
...
@@ -468,11 +393,8 @@ class TransactionalUndoStorage:
info2
=
self
.
_storage
.
undoInfo
()
self
.
assertEqual
(
len
(
info2
),
2
)
# And now attempt to undo the last transaction
t
=
Transaction
()
oids
=
self
.
_begin_undos_vote
(
t
,
tid
)
self
.
_storage
.
tpc_finish
(
t
)
self
.
assertEqual
(
len
(
oids
),
1
)
self
.
assertEqual
(
oids
[
0
],
oid
)
undone
,
=
self
.
undo
(
tid
)
self
.
assertEqual
(
undone
,
oid
)
data
,
revid
=
load_current
(
self
.
_storage
,
oid
)
# The object must now be at the second state
self
.
assertEqual
(
zodb_unpickle
(
data
),
MinPO
(
52
))
...
...
@@ -805,8 +727,9 @@ class TransactionalUndoStorage:
from
.ConflictResolution
import
PCounter
db
=
DB
(
self
.
_storage
)
with
db
.
transaction
()
as
conn
:
conn
.
root
.
x
=
PCounter
()
cn
=
db
.
open
()
cn
.
root
.
x
=
PCounter
()
transaction
.
commit
()
for
i
in
range
(
4
):
with
db
.
transaction
()
as
conn
:
...
...
@@ -815,10 +738,13 @@ class TransactionalUndoStorage:
ids
=
[
l
[
'id'
]
for
l
in
db
.
undoLog
(
1
,
3
)]
if
reverse
:
ids
=
list
(
reversed
(
ids
)
)
ids
.
reverse
(
)
db
.
undoMultiple
(
ids
)
transaction
.
commit
()
self
.
assertEqual
(
cn
.
root
.
x
.
_value
,
2
)
cn
.
close
()
def
checkUndoMultipleConflictResolutionReversed
(
self
):
self
.
checkUndoMultipleConflictResolution
(
True
)
src/ZODB/tests/testConnection.py
View file @
420984b7
...
...
@@ -1275,6 +1275,7 @@ class StubStorage:
del
self
.
_transaction
self
.
_transdata
.
clear
()
self
.
_transstored
=
[]
return
z64
def
load
(
self
,
oid
,
version
=
''
):
if
version
!=
''
:
...
...
@@ -1295,9 +1296,6 @@ class StubStorage:
self
.
_stored
.
append
(
oid
)
self
.
_transstored
.
append
(
oid
)
self
.
_transdata
[
oid
]
=
(
p
,
serial
)
# Explicitly returning None, as we're not pretending to be a ZEO
# storage
return
None
def
lastTransaction
(
self
):
return
z64
...
...
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