[Zope3-checkins] CVS: Zope3/src/zodb/storage - file.py:1.23.2.3
Jeremy Hylton
jeremy@zope.com
Mon, 14 Apr 2003 18:53:39 -0400
Update of /cvs-repository/Zope3/src/zodb/storage
In directory cvs.zope.org:/tmp/cvs-serv1009/storage
Modified Files:
Tag: jeremy-new-pack-branch
file.py
Log Message:
Completed rewrite of pack.
The code is still a mess, but it passes the tests. Need to sit on it
for a while, then do a code review.
Add testPackVersionsInPast() which failed with the old pack. Still
need to get Dieter's failing test included.
=== Zope3/src/zodb/storage/file.py 1.23.2.2 => 1.23.2.3 === (885/985 lines abridged)
--- Zope3/src/zodb/storage/file.py:1.23.2.2 Fri Apr 11 13:35:14 2003
+++ Zope3/src/zodb/storage/file.py Mon Apr 14 18:53:38 2003
@@ -444,11 +444,6 @@
h.back = u64(self._file.read(8))
return h
- def _write_data_header(self, file, oid, serial, prev, tloc, vlen, nrefs,
- plen):
- s = struct.pack(DATA_HDR, oid, serial, prev, tloc, vlen, nrefs, plen)
- file.write(s)
-
def _write_version_header(self, file, pnv, vprev, version):
s = struct.pack(">QQ", pnv, vprev)
file.write(s + version)
@@ -509,7 +504,156 @@
def __init__(self, afile):
self._file = afile
-class FileStorage(BaseStorage, FileStorageFormatter):
+class DataCopier(FileStorageFormatter):
+ """Mixin class for copying transactions into a storage.
+
+ The restore() and pack() methods share a need to copy data records
+ and update pointers to data in earlier transaction records. This
+ class provides the shared logic.
+
+ The mixin extends the FileStorageFormatter with a copy() method.
+ It also requires that the concrete class provides the following
+ attributes:
+
+ _file -- file with earlier destination data
+ _tfile -- destination file for copied data
+ _packt -- p64() representation of latest pack time
+ _pos -- file pos of destination transaction
+ _tindex -- maps oid to data record file pos
+ _tvindex -- maps version name to data record file pos
+
+ _tindex and _tvindex are updated by copy().
+
+ The copy() method does not do any locking.
+ """
+
+ def _txn_find(self, tid, stop_at_pack):
+ # _pos always points just past the last transaction
+ pos = self._pos
+ while pos > 1024:
+ self._file.seek(pos - 8)
+ pos = pos - u64(self._file.read(8)) - 8
+ self._file.seek(pos)
+ h = self._file.read(TRANS_HDR_LEN)
[-=- -=- -=- 885 lines omitted -=- -=- -=-]
+ self._file.seek(self.pos - 8)
+ self.pos -= u64(self._file.read(8)) + 8
+ if self.pos < 1024:
return None
- if status != ' ':
+ h = self._read_txn_header(self.pos)
+ if h.tid < self.packt or h.status == 'p':
+ self.stop = 1
return None
- d = u = ''
- # user and description are utf-8 encoded strings
- if ul:
- u = self.file.read(ul).decode('utf-8')
- if dl:
- d = self.file.read(dl).decode('utf-8')
- e = {}
- if el:
- try:
- e = loads(self.file.read(el))
- except:
- pass
- d = {'id': base64.encodestring(tid).rstrip(),
- 'time': TimeStamp(tid).timeTime(),
- 'user_name': u,
- 'description': d}
- d.update(e)
+ assert h.status == " "
+ d = {'id': base64.encodestring(h.tid).rstrip(),
+ 'time': TimeStamp(h.tid).timeTime(),
+ 'user_name': h.user,
+ 'description': h.descr}
+ if h.ext:
+ ext = loads(h.ext)
+ d.update(ext)
return d
class DataHeader:
@@ -2309,6 +2213,12 @@
return s + v + self.version
else:
return s
+
+ def setVersion(self, version, pnv, vprev):
+ self.version = version
+ self.vlen = len(version)
+ self.pnv = pnv
+ self.vprev = vprev
def parseVersion(self, buf):
self.pnv, self.vprev = struct.unpack(">QQ", buf[:16])