[Zodb-checkins] CVS: StandaloneZODB/ZODB - FileStorage.py:1.87
Jeremy Hylton
jeremy@zope.com
Fri, 29 Mar 2002 17:47:48 -0500
Update of /cvs-repository/StandaloneZODB/ZODB
In directory cvs.zope.org:/tmp/cvs-serv1208
Modified Files:
FileStorage.py
Log Message:
Move undoLog() before transactionalUndo().
It makes more sense in this order, because the comments in undoLog()
help to explain what transactionalUndo() is doing.
=== StandaloneZODB/ZODB/FileStorage.py 1.86 => 1.87 ===
raise UndoError('Some data were modified by a later transaction')
+ def undoLog(self, first=0, last=-20, filter=None):
+ if last < 0:
+ last = first - last + 1
+ self._lock_acquire()
+ try:
+ if self._packt is None:
+ raise UndoError(
+ 'Undo is currently disabled for database maintenance.<p>')
+ pos = self._pos
+ # BAW: Why 39 please? This makes no sense (see also below).
+ if pos < 39:
+ return []
+ file=self._file
+ seek=file.seek
+ read=file.read
+ r = []
+ i = 0
+ while i < last and pos > 39:
+ self._file.seek(pos - 8)
+ pos = pos - U64(self._file.read(8)) - 8
+ self._file.seek(pos)
+ h = self._file.read(TRANS_HDR_LEN)
+ tid, tl, status, ul, dl, el = struct.unpack(">8s8scHHH", h)
+ if tid < self._packt:
+ break
+ if status != ' ':
+ continue
+ d = u = ''
+ if ul:
+ u = self._file.read(ul)
+ if dl:
+ d = self._file.read(dl)
+ e = {}
+ if el:
+ try:
+ e = loads(read(el))
+ except:
+ pass
+ # We now need an encoded id that isn't dependent on file
+ # position, because it will break after a pack, and in the
+ # face of replication, while the transaction and data records
+ # may be identical (as viewed from the storage interface),
+ # file positions may be meaningless across replicas.
+ #
+ # We'd love to just give the tid, but FS makes it expensive to
+ # go from tid to transaction record. :( However, if the txn
+ # has data records, then we can encode the oid of one of the
+ # objects affected by the txn. Then we can use the index to
+ # find the current revision of the object, follow a
+ # back-pointer to find its most-current txn, and then follow
+ # the txns back until we find a match. Seems like the best we
+ # can do w/o a persistent tid->filepos mapping.
+ #
+ # Note: if the txn has no data records, we're screwed. Punt
+ # on that for now.
+ #
+ # Note that we're still encoding the transaction position
+ # in the transaction ID in order to support non-transactional
+ # undo. This can be removed as soon as non-transactional
+ # undo is removed.
+ next = read(8)
+ # next is either the redundant txn length - 8, or an oid
+ if next == tl:
+ # There were no objects in this txn
+ id = tid + p64(pos)
+ else:
+ id = tid + p64(pos) + next
+ d = {'id': base64.encodestring(id).rstrip(),
+ 'time': TimeStamp(tid).timeTime(),
+ 'user_name': u,
+ 'description': d}
+ d.update(e)
+ if filter is None or filter(d):
+ if i >= first:
+ r.append(d)
+ i += 1
+ return r
+ finally:
+ self._lock_release()
+
def transactionalUndo(self, transaction_id, transaction):
"""Undo a transaction, given by transaction_id.
@@ -1161,86 +1241,6 @@
return tindex.keys()
finally: self._lock_release()
-
- def undoLog(self, first=0, last=-20, filter=None):
- if last < 0:
- last = first - last + 1
- self._lock_acquire()
- try:
- if self._packt is None:
- raise UndoError(
- 'Undo is currently disabled for database maintenance.<p>')
- pos = self._pos
- # BAW: Why 39 please? This makes no sense (see also below).
- if pos < 39:
- return []
- file=self._file
- seek=file.seek
- read=file.read
- r = []
- i = 0
- while i < last and pos > 39:
- self._file.seek(pos - 8)
- pos = pos - U64(self._file.read(8)) - 8
- self._file.seek(pos)
- h = self._file.read(TRANS_HDR_LEN)
- tid, tl, status, ul, dl, el = struct.unpack(">8s8scHHH", h)
- if tid < self._packt:
- break
- if status != ' ':
- continue
- d = u = ''
- if ul:
- u = self._file.read(ul)
- if dl:
- d = self._file.read(dl)
- e = {}
- if el:
- try:
- e = loads(read(el))
- except:
- pass
- # We now need an encoded id that isn't dependent on file
- # position, because it will break after a pack, and in the
- # face of replication, while the transaction and data records
- # may be identical (as viewed from the storage interface),
- # file positions may be meaningless across replicas.
- #
- # We'd love to just give the tid, but FS makes it expensive to
- # go from tid to transaction record. :( However, if the txn
- # has data records, then we can encode the oid of one of the
- # objects affected by the txn. Then we can use the index to
- # find the current revision of the object, follow a
- # back-pointer to find its most-current txn, and then follow
- # the txns back until we find a match. Seems like the best we
- # can do w/o a persistent tid->filepos mapping.
- #
- # Note: if the txn has no data records, we're screwed. Punt
- # on that for now.
- #
- # Note that we're still encoding the transaction position
- # in the transaction ID in order to support non-transactional
- # undo. This can be removed as soon as non-transactional
- # undo is removed.
- next = read(8)
- # next is either the redundant txn length - 8, or an oid
- if next == tl:
- # There were no objects in this txn
- id = tid + p64(pos)
- else:
- id = tid + p64(pos) + next
- d = {'id': base64.encodestring(id).rstrip(),
- 'time': TimeStamp(tid).timeTime(),
- 'user_name': u,
- 'description': d}
- d.update(e)
- if filter is None or filter(d):
- if i >= first:
- r.append(d)
- i += 1
- return r
- finally:
- self._lock_release()
def versionEmpty(self, version):
if not version: