Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
ZEO
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
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
ZEO
Commits
24d0d2f4
Commit
24d0d2f4
authored
Jun 18, 2004
by
Tim Peters
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
New test checkRestoreWithMultipleObjectsInUndoRedo from ZODB 3.2.2.
3.3 didn't have the bug, and this confirms it.
parent
657b747b
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
103 additions
and
0 deletions
+103
-0
src/ZODB/tests/RecoveryStorage.py
src/ZODB/tests/RecoveryStorage.py
+103
-0
No files found.
src/ZODB/tests/RecoveryStorage.py
View file @
24d0d2f4
...
...
@@ -183,3 +183,106 @@ class RecoveryStorage(IteratorDeepCompare):
data
,
serial
=
self
.
_dst
.
load
(
root
.
_p_oid
,
''
)
raises
(
KeyError
,
self
.
_dst
.
load
,
obj1
.
_p_oid
,
''
)
raises
(
KeyError
,
self
.
_dst
.
load
,
obj2
.
_p_oid
,
''
)
def
checkRestoreWithMultipleObjectsInUndoRedo
(
self
):
from
ZODB.FileStorage
import
FileStorage
# Undo creates backpointers in (at least) FileStorage. ZODB 3.2.1
# FileStorage._data_find() had an off-by-8 error, neglecting to
# account for the size of the backpointer when searching a
# transaction with multiple data records. The results were
# unpredictable. For example, it could raise a Python exception
# due to passing a negative offset to file.seek(), or could
# claim that a transaction didn't have data for an oid despite
# that it actually did.
#
# The former failure mode was seen in real life, in a ZRS secondary
# doing recovery. On my box today, the second failure mode is
# what happens in this test (with an unpatched _data_find, of
# course). Note that the error can only "bite" if more than one
# data record is in a transaction, and the oid we're looking for
# follows at least one data record with a backpointer.
#
# Unfortunately, _data_find() is a low-level implementation detail,
# and this test does some horrid white-box abuse to test it.
is_filestorage
=
isinstance
(
self
.
_storage
,
FileStorage
)
db
=
DB
(
self
.
_storage
)
c
=
db
.
open
()
r
=
c
.
root
()
# Create some objects.
r
[
"obj1"
]
=
MinPO
(
1
)
r
[
"obj2"
]
=
MinPO
(
1
)
transaction
.
commit
()
# Add x attributes to them.
r
[
"obj1"
].
x
=
'x1'
r
[
"obj2"
].
x
=
'x2'
transaction
.
commit
()
r
=
db
.
open
().
root
()
self
.
assertEquals
(
r
[
"obj1"
].
x
,
'x1'
)
self
.
assertEquals
(
r
[
"obj2"
].
x
,
'x2'
)
# Dirty tricks.
if
is_filestorage
:
obj1_oid
=
r
[
"obj1"
].
_p_oid
obj2_oid
=
r
[
"obj2"
].
_p_oid
# This will be the offset of the next transaction, which
# will contain two backpointers.
pos
=
self
.
_storage
.
getSize
()
# Undo the attribute creation.
info
=
self
.
_storage
.
undoInfo
()
tid
=
info
[
0
][
'id'
]
t
=
Transaction
()
self
.
_storage
.
tpc_begin
(
t
)
oids
=
self
.
_storage
.
undo
(
tid
,
t
)
self
.
_storage
.
tpc_vote
(
t
)
self
.
_storage
.
tpc_finish
(
t
)
r
=
db
.
open
().
root
()
self
.
assertRaises
(
AttributeError
,
getattr
,
r
[
"obj1"
],
'x'
)
self
.
assertRaises
(
AttributeError
,
getattr
,
r
[
"obj2"
],
'x'
)
if
is_filestorage
:
# _data_find should find data records for both objects in that
# transaction. Without the patch, the second assert failed
# (it claimed it couldn't find a data record for obj2) on my
# box, but other failure modes were possible.
self
.
assert_
(
self
.
_storage
.
_data_find
(
pos
,
obj1_oid
,
''
)
>
0
)
self
.
assert_
(
self
.
_storage
.
_data_find
(
pos
,
obj2_oid
,
''
)
>
0
)
# The offset of the next ("redo") transaction.
pos
=
self
.
_storage
.
getSize
()
# Undo the undo (restore the attributes).
info
=
self
.
_storage
.
undoInfo
()
tid
=
info
[
0
][
'id'
]
t
=
Transaction
()
self
.
_storage
.
tpc_begin
(
t
)
oids
=
self
.
_storage
.
undo
(
tid
,
t
)
self
.
_storage
.
tpc_vote
(
t
)
self
.
_storage
.
tpc_finish
(
t
)
r
=
db
.
open
().
root
()
self
.
assertEquals
(
r
[
"obj1"
].
x
,
'x1'
)
self
.
assertEquals
(
r
[
"obj2"
].
x
,
'x2'
)
if
is_filestorage
:
# Again _data_find should find both objects in this txn, and
# again the second assert failed on my box.
self
.
assert_
(
self
.
_storage
.
_data_find
(
pos
,
obj1_oid
,
''
)
>
0
)
self
.
assert_
(
self
.
_storage
.
_data_find
(
pos
,
obj2_oid
,
''
)
>
0
)
# Indirectly provoke .restore(). .restore in turn indirectly
# provokes _data_find too, but not usefully for the purposes of
# the specific bug this test aims at: copyTransactionsFrom() uses
# storage iterators that chase backpointers themselves, and
# return the data they point at instead. The result is that
# _data_find didn't actually see anything dangerous in this
# part of the test.
self
.
_dst
.
copyTransactionsFrom
(
self
.
_storage
)
self
.
compare
(
self
.
_storage
,
self
.
_dst
)
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