Skip to content

Commit

Permalink
alternate implementation from review
Browse files Browse the repository at this point in the history
Co-authored-by: Kirill Smelkov <kirr@nexedi.com>
  • Loading branch information
perrinjerome and navytux committed Feb 1, 2024
1 parent 44d36b0 commit 37db547
Showing 1 changed file with 29 additions and 20 deletions.
49 changes: 29 additions & 20 deletions src/ZODB/FileStorage/FileStorage.py
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,10 @@ def _data_find(self, tpos, oid, data):
# Else oid's data record contains the data, and the file offset of
# oid's data record is returned. This data record should contain
# a pickle identical to the 'data' argument.
# When looking for oid's data record we scan all data records in
# the transaction till the end looking for the latest record with oid,
# even if there are multiple such records. This matches load behaviour
# which uses the data record created by last store.

# Unclear: If the length of the stored data doesn't match len(data),
# an exception is raised. If the lengths match but the data isn't
Expand All @@ -674,31 +678,36 @@ def _data_find(self, tpos, oid, data):
self._file.read(ul + dl + el)
tend = tpos + tl
pos = self._file.tell()
backpointer = None
data_hdr = None
data_pos = 0
# scan all data records in this transaction looking for the latest
# record with our oid
while pos < tend:
h = self._read_data_header(pos)
if h.oid == oid:
# Make sure this looks like the right data record
if h.plen == 0:
# This is also a backpointer, remember it and keep
# looking at other records from this transaction,
# if there is multiple undo records, we use the
# oldest.
backpointer = pos
else:
if h.plen != len(data):
# The expected data doesn't match what's in the
# backpointer. Something is wrong.
logger.error("Mismatch between data and"
" backpointer at %d", pos)
return 0
_data = self._file.read(h.plen)
if data != _data:
return 0
return pos
data_hdr = h
data_pos = pos
pos += h.recordlen()
self._file.seek(pos)
return backpointer or 0
if data_hdr is None:
return 0

# return position of found data record, but make sure this looks like
# the right data record to return.
if data_hdr.plen == 0:
# This is also a backpointer, Gotta trust it.
return data_pos
else:
if data_hdr.plen != len(data):
# The expected data doesn't match what's in the
# backpointer. Something is wrong.
logger.error("Mismatch between data and"
" backpointer at %d", pos)
return 0
_data = self._file.read(data_hdr.plen)
if data != _data:
return 0
return data_pos

def restore(self, oid, serial, data, version, prev_txn, transaction):
# A lot like store() but without all the consistency checks. This
Expand Down

0 comments on commit 37db547

Please sign in to comment.