[Zope3-checkins] CVS: Zope3/src/zodb/storage/file - pack.py:1.1.2.2
Jeremy Hylton
jeremy@zope.com
Thu, 17 Apr 2003 15:55:50 -0400
Update of /cvs-repository/Zope3/src/zodb/storage/file
In directory cvs.zope.org:/tmp/cvs-serv12991/file
Modified Files:
Tag: jeremy-new-pack-branch
pack.py
Log Message:
Make pack work for objects created in versions that are unreachable at
the pack time.
=== Zope3/src/zodb/storage/file/pack.py 1.1.2.1 => 1.1.2.2 ===
--- Zope3/src/zodb/storage/file/pack.py:1.1.2.1 Wed Apr 16 14:12:32 2003
+++ Zope3/src/zodb/storage/file/pack.py Thu Apr 17 15:55:50 2003
@@ -29,18 +29,12 @@
self.packtime = packtime
# packpos: position of first txn header after pack time
self.packpos = None
- # XXX pos2oid may be unnecessary
- self.pos2oid = {} # maps data record position to oid
self.oid2curpos = {} # maps oid to current data record position
+ self.oid2verpos = {} # maps oid to current version data
self.reachable = {} # maps oid to list of reachable data record pos
- # XXX what about versions?
- # need PackAfterUndoDeleteVersion
-
def findReachable(self):
self.buildPackIndex()
- if ZERO not in self.oid2curpos:
- return
self.findReachableAtPacktime([ZERO])
self.findReachableFromFuture()
@@ -56,8 +50,10 @@
while pos < end:
dh = self._read_data_header(pos)
- self.pos2oid[pos] = dh.oid
- self.oid2curpos[dh.oid] = pos
+ if dh.version:
+ self.oid2verpos[dh.oid] = pos
+ else:
+ self.oid2curpos[dh.oid] = pos
pos += dh.recordlen()
tlen = self._read_num(pos)
@@ -74,9 +70,19 @@
if oid in self.reachable:
continue
- pos = self.oid2curpos[oid]
- self.reachable[oid] = [pos]
- todo.extend(self.findrefs(pos))
+ L = []
+
+ pos = self.oid2curpos.get(oid)
+ if pos is not None:
+ L.append(pos)
+ todo.extend(self.findrefs(pos))
+
+ pos = self.oid2verpos.get(oid)
+ if pos is not None:
+ L.append(pos)
+ todo.extend(self.findrefs(pos))
+
+ self.reachable[oid] = L
def findReachableFromFuture(self):
# In this pass, the roots are positions of object revisions.
@@ -100,6 +106,12 @@
if dh.back not in L:
L.append(dh.back)
extra_roots.append(dh.back)
+
+ if dh.pnv and dh.pnv < self.packpos:
+ L = self.reachable.setdefault(dh.oid, [])
+ if dh.pnv not in L:
+ L.append(dh.pnv)
+ extra_roots.append(dh.pnv)
pos += dh.recordlen()
@@ -340,69 +352,17 @@
if h.plen:
refs = self._file.read(8 * h.nrefs)
data = self._file.read(h.plen)
- else:
+ elif h.back:
# If a current record has a backpointer, fetch
# refs and data from the backpointer. We need
# to write the data in the new record.
data, refs, serial, tid = self._loadBackTxn(h.oid, h.back)
refs = "".join(refs)
-
- self.writePackedDataRecord(h, data, refs, new_tpos)
- new_pos = self._tfile.tell()
-
- return new_tpos, pos
-
- def VERSIONcopyDataRecords(self, pos, th):
- """Copy any current data records between pos and tend.
-
- Returns position of txn header in output file and position
- of next record in the input file.
-
- If any data records are copied, also write txn header (th).
- """
- copy = False
- new_tpos = 0
- tend = pos + th.tlen
- pos += th.headerlen()
- while pos < tend:
- h = self._read_data_header(pos)
- cur_nonversion = False
-
- # If this data record isn't current, don't copy it.
- # If the current record is in a version, this may be
- # the current non-version data.
- curpos = self.pindex.get(h.oid, 0)
- if curpos != pos:
- if self.isCurNonversion(h, pos, curpos):
- cur_nonversion = True
- else:
- pos += h.recordlen()
- continue
- pos += h.recordlen()
-
- # If we are going to copy any data, we need to copy
- # the transaction header. Note that we will need to
- # patch up the transaction length when we are done.
- if not copy:
- th.status = "p"
- s = th.asString()
- new_tpos = self._tfile.tell()
- self._tfile.write(s)
- new_pos = new_tpos + len(s)
- copy = True
-
- if cur_nonversion:
- self.nvindex[h.oid] = new_pos
-
- if h.plen:
- refs = self._file.read(8 * h.nrefs)
- data = self._file.read(h.plen)
else:
- # If a current record has a backpointer, fetch
- # refs and data from the backpointer. We need
- # to write the data in the new record.
- data, refs, serial, tid = self._loadBackTxn(h.oid, h.back)
- refs = "".join(refs)
+ assert h.plen == 0 and h.back == 0
+ data = ""
+ refs = ""
+ print "george", h.__dict__
self.writePackedDataRecord(h, data, refs, new_tpos)
new_pos = self._tfile.tell()
@@ -417,16 +377,26 @@
h.plen = len(data)
h.nrefs = len(refs) / 8
h.tloc = new_tpos
+ pos = self._tfile.tell()
if h.version:
- h.pnv = self.nvindex.get(h.oid, 0)
+ h.pnv = self.index.get(h.oid, 0)
h.vprev = self.vindex.get(h.version, 0)
- pos = self._tfile.tell()
+ self.vindex[h.version] = pos
self.index[h.oid] = pos
if h.version:
self.vindex[h.version] = pos
+ if not (data or refs):
+ print h.__dict__
+ print repr(h.asString())
+ print "writing at %d" % self._tfile.tell()
self._tfile.write(h.asString())
self._tfile.write(refs)
self._tfile.write(data)
+ if not data:
+ # Packed records never have backpointers (?).
+ # If there is no data, write a ZERO backpointer.
+ # This is a George Bailey event.
+ self._tfile.write(ZERO)
def copyRest(self, ipos):
# After the pack time, all data records are copied.