[Zodb-checkins] CVS: ZODB3/ZODB - FileStorage.py:1.105.2.6.2.2

Jeremy Hylton jeremy@zope.com
Fri, 15 Nov 2002 11:20:05 -0500


Update of /cvs-repository/ZODB3/ZODB
In directory cvs.zope.org:/tmp/cvs-serv27733

Modified Files:
      Tag: ZODB3-restore-debug-branch
	FileStorage.py 
Log Message:
Two important fixes for backpointer handling.

In restore():
- If the backpointer points to a record with another backpointer,
  assume the backpointer is valid.
- If the backpointer points to a record with data and the length of
  the data doesn't match the length of the data passed to restore, log
  an error() and return 0.

In iterator(): When assigning data_txn for a data record, don't chase
backpointers all the way to the data.


=== ZODB3/ZODB/FileStorage.py 1.105.2.6.2.1 => 1.105.2.6.2.2 ===
--- ZODB3/ZODB/FileStorage.py:1.105.2.6.2.1	Fri Nov 15 10:44:13 2002
+++ ZODB3/ZODB/FileStorage.py	Fri Nov 15 11:20:04 2002
@@ -766,9 +766,13 @@
                 if vl:
                     self._file.read(vl + 16)
                 # Make sure this looks like the right data record
+                if dl == 0:
+                    # This is also a backpointer.  Gotta trust it.
+                    return pos
                 if dl != len(data):
-                    # XXX what if this data record also has a backpointer?
-                    # I don't think that's possible, but I'm not sure.
+                    # The expected data doesn't match what's in the
+                    # backpointer.  Something is wrong.
+                    error("Mismatch between data and backpointer at %d", pos)
                     return 0
                 _data = self._file.read(dl)
                 if data != _data:
@@ -2211,6 +2215,17 @@
     tid = h[:8]
     return data, serial, tid
 
+def getTxnFromData(file, oid, back):
+    """Return transaction id for data at back."""
+    file.seek(U64(back))
+    h = file.read(DATA_HDR_LEN)
+    doid, serial, prev, stloc, vlen, plen = unpack(DATA_HDR, h)
+    assert oid == doid
+    tloc = U64(stloc)
+    file.seek(tloc)
+    # seek to transaction header, where tid is first 8 bytes
+    return file.read(8)
+
 def _truncate(file, name, pos):
     seek=file.seek
     seek(0,2)
@@ -2451,7 +2466,7 @@
                 break
 
             self._pos = pos + dlen
-            tid = None
+            prev_txn = None
             if plen:
                 data = self._file.read(plen)
             else:
@@ -2464,10 +2479,12 @@
                     # Return None instead of a pickle to indicate
                     # this.
                     data = None
+                    prev_txn = z64
                 else:
                     data, _s, tid = _loadBackTxn(self._file, oid, bp)
+                    prev_txn = getTxnFromData(self._file, oid, bp)
 
-            r = Record(oid, serial, version, data, tid)
+            r = Record(oid, serial, version, data, prev_txn)
 
             return r