[Zope3-checkins] CVS: ZODB4/ZODB - FileStorage.py:1.110.6.2
Jeremy Hylton
jeremy@zope.com
Tue, 10 Dec 2002 17:04:31 -0500
Update of /cvs-repository/ZODB4/ZODB
In directory cvs.zope.org:/tmp/cvs-serv23438/ZODB
Modified Files:
Tag: ZODB4-Q-branch
FileStorage.py
Log Message:
Another checkpoint in the Q saga.
Try to sanitize CorruptedDataError. Define ctor with explicit oid and
buf arguments.
Add FileStorageFormatter class that should eventually collect all the
functionality for reading and writing the low-level file format,
including backpointers.
Start converting FileStorage to use FileStorageFormatter. Currently
there are several pack errors and a couple of recover errors.
=== ZODB4/ZODB/FileStorage.py 1.110.6.1 => 1.110.6.2 === (482/582 lines abridged)
--- ZODB4/ZODB/FileStorage.py:1.110.6.1 Fri Dec 6 18:58:01 2002
+++ ZODB4/ZODB/FileStorage.py Tue Dec 10 17:04:30 2002
@@ -198,7 +198,16 @@
pass
class CorruptedDataError(CorruptedFileStorageError):
- pass
+
+ def __init__(self, oid=None, buf=None):
+ self.oid = oid
+ self.buf = buf
+
+ def __str__(self):
+ if self.oid:
+ return "Error reading oid %016x. Found %r" % (self.oid, self.buf)
+ else:
+ return "Error reading unknown oid. Found %r" % self.buf
class FileStorageQuotaError(FileStorageError,
POSException.StorageSystemError):
@@ -211,7 +220,81 @@
db = ZODB.DB.DB(fs, pool_size, cache_size)
return db
+class FileStorageFormatter:
+ """Mixin class that can read and write the low-level format."""
+
+ # subclasses must provide _file
+ def _read_data_header(self, pos, oid=None):
+ self._file.seek(pos)
+ s = self._file.read(DATA_HDR_LEN)
+ if len(s) != DATA_HDR_LEN:
+ raise CorruptedDataError(oid, s)
+ h = DataHeader.fromString(s)
+ if oid is not None and oid != h.oid:
+ raise CorruptedDataError(oid, s)
+ if h.vlen:
+ s = self._file.read(16 + h.vlen)
+ h.parseVersion(s)
+ if not h.plen:
+ h.back = u64(self._file.read(8))
+ return h
+
+ def _write_data_header(self, file, oid, serial, prev, tloc, vlen, plen):
+ s = struct.pack(DATA_HDR, oid, serial, prev, tloc, vlen, plen)
+ file.write(s)
+
+ def _write_version_header(self, file, pnv, vprev, version):
+ s = struct.pack(">QQ", pnv, vprev)
+ file.write(s + version)
[-=- -=- -=- 482 lines omitted -=- -=- -=-]
else:
- bp = self._file.read(8)
- if bp == z64:
- # If the backpointer is 0 (encoded as z64), then
- # this transaction undoes the object creation. It
- # either aborts the version that created the
- # object or undid the transaction that created it.
- # Return None instead of a pickle to indicate
- # this.
+ print h.back
+ if not h.back:
+ # If the backpointer is 0, then this transaction
+ # undoes the object creation. It either aborts
+ # the version that created the object or undid the
+ # transaction that created it. Return None
+ # instead of a pickle to indicate this.
data = None
else:
- data, _s, tid = _loadBackTxn(self._file, oid, bp)
- prev_txn = getTxnFromData(self._file, oid, bp)
+ data, _s, tid = self._loadBackTxn(h.oid, h.back)
+ prev_txn = self.getTxnFromData(h.oid, h.back)
- r = Record(oid, serial, version, data, prev_txn)
+ r = Record(h.oid, h.serial, h.version, data, prev_txn)
return r
@@ -2467,7 +2431,12 @@
class DataHeader:
"""Header for a data record."""
- __slots__ = "oid", "serial", "prev", "tloc", "vlen", "plen"
+ __slots__ = ("oid", "serial", "prev", "tloc", "vlen", "plen", "back",
+ # These three attributes are only defined when vlen > 0
+ "pnv", "vprev", "version")
+
+ version = ""
+ back = 0
def __init__(self, oid, serial, prev, tloc, vlen, plen):
self.oid = oid
@@ -2481,3 +2450,7 @@
return cls(*struct.unpack(DATA_HDR, s))
fromString = classmethod(fromString)
+
+ def parseVersion(self, buf):
+ self.pnv, self.vprev = struct.unpack(">QQ", buf[:16])
+ self.version = buf[16:]