[Zodb-checkins] CVS: Zope3/src/zodb/storage - base.py:1.11.2.1 bdbfull.py:1.10.2.1 bdbminimal.py:1.10.2.1 file.py:1.7.2.1 fsrecover.py:1.2.6.1 interfaces.py:1.2.2.1 mapping.py:1.2.6.1

Sidnei da Silva sidnei@x3ng.com.br
Tue, 11 Feb 2003 09:41:53 -0500


Update of /cvs-repository/Zope3/src/zodb/storage
In directory cvs.zope.org:/tmp/cvs-serv18615/src/zodb/storage

Modified Files:
      Tag: paris-copypasterename-branch
	base.py bdbfull.py bdbminimal.py file.py fsrecover.py 
	interfaces.py mapping.py 
Log Message:
Updating from HEAD to make sure everything still works before merging

=== Zope3/src/zodb/storage/base.py 1.11 => 1.11.2.1 ===
--- Zope3/src/zodb/storage/base.py:1.11	Mon Feb  3 18:00:45 2003
+++ Zope3/src/zodb/storage/base.py	Tue Feb 11 09:40:49 2003
@@ -32,7 +32,7 @@
 # need to use pybsddb3, a.k.a. bsddb3.
 try:
     try:
-        from bsddb import _db as db
+        from bsddb import db
     except ImportError:
         from bsddb3 import db
     berkeley_is_available = True
@@ -40,9 +40,9 @@
     db = None
     berkeley_is_available = False
 
-from zodb import interfaces
 from zodb.timestamp import newTimeStamp, TimeStamp
 from zodb.interfaces import ITransactionAttrs
+from zodb.storage.interfaces import StorageTransactionError, ReadOnlyError
 # BaseStorage provides primitives for lock acquisition and release, and a host
 # of other methods, some of which are overridden here, some of which are not.
 from zodb.lockfile import lock_file
@@ -84,12 +84,12 @@
 
     def abortVersion(self, src, transaction):
         if transaction is not self._transaction:
-            raise interfaces.StorageTransactionError(self, transaction)
+            raise StorageTransactionError(self, transaction)
         return []
 
     def commitVersion(self, src, dest, transaction):
         if transaction is not self._transaction:
-            raise interfaces.StorageTransactionError(self, transaction)
+            raise StorageTransactionError(self, transaction)
         return []
 
     def close(self):
@@ -113,10 +113,10 @@
     def modifiedInVersion(self, oid):
         return ''
 
-    def new_oid(self, last=None):
+    def newObjectId(self, last=None):
          # 'last' is only for internal use, not part of the public API
         if self._is_read_only:
-            raise interfaces.ReadOnlyError()
+            raise ReadOnlyError()
         if last is None:
             self._lock_acquire()
             try:
@@ -125,7 +125,7 @@
                 if d < 255:
                     last = last[:-1] + chr(d+1)
                 else:
-                    last = self.new_oid(last[:-1])
+                    last = self.newObjectId(last[:-1])
                 self._oid = last
                 return last
             finally:
@@ -135,7 +135,7 @@
             if d < 255:
                 return last[:-1] + chr(d+1) + '\0'*(8-len(last))
             else:
-                return self.new_oid(last[:-1])
+                return self.newObjectId(last[:-1])
 
     def registerDB(self, db):
         pass # we don't care
@@ -143,15 +143,12 @@
     def isReadOnly(self):
         return self._is_read_only
 
-    def supportsVersions(self):
-        return False
-
     def _clear_temp(self):
         # Called by tpc_begin(), tpc_abort(), and tpc_finish(), this should be
         # overridden in storages to clear out any temporary state.
         pass
 
-    def tpc_abort(self, transaction):
+    def tpcAbort(self, transaction):
         self._lock_acquire()
         try:
             if transaction is not self._transaction:
@@ -167,10 +164,10 @@
         # Subclasses should define this to supply abort actions.
         pass
 
-    def tpc_begin(self, transaction, tid=None, status=' '):
+    def tpcBegin(self, transaction, tid=None, status=' '):
         assert ITransactionAttrs.isImplementedBy(transaction)
         if self._is_read_only:
-            raise interfaces.ReadOnlyError()
+            raise ReadOnlyError()
         self._lock_acquire()
         try:
             if self._transaction is transaction:
@@ -202,7 +199,7 @@
         # Subclasses should define this to supply transaction start actions.
         pass
 
-    def tpc_vote(self, transaction):
+    def tpcVote(self, transaction):
         self._lock_acquire()
         try:
             if transaction is not self._transaction:
@@ -215,7 +212,7 @@
         # Subclasses should define this to supply transaction vote actions.
         pass
 
-    def tpc_finish(self, transaction, f=None):
+    def tpcFinish(self, transaction, f=None):
         self._lock_acquire()
         try:
             if transaction is not self._transaction:
@@ -282,7 +279,7 @@
 
     def pack(self, t):
         if self._is_read_only:
-            raise interfaces.ReadOnlyError()
+            raise ReadOnlyError()
 
     def getSerial(self, oid):
         self._lock_acquire()
@@ -294,8 +291,7 @@
             self._lock_release()
 
     def loadSerial(self, oid, serial):
-        raise interfaces.Unsupported, (
-            "Retrieval of historical revisions is not supported")
+        raise NotImplementedError
 
     def getExtensionMethods(self):
         """getExtensionMethods
@@ -338,23 +334,14 @@
             if verbose:
                 print _ts
 
-            self.tpc_begin(transaction, tid, transaction.status)
+            self.tpcBegin(transaction, tid, transaction.status)
             for r in transaction:
                 if verbose:
                     print `r.oid`, r.version, len(r.data)
                 self.restore(r.oid, r.serial, r.data, r.version,
                              r.data_txn, transaction)
-            self.tpc_vote(transaction)
-            self.tpc_finish(transaction)
-
-class TransactionRecord:
-    """Abstract base class for iterator protocol."""
-
-    __implements__ = ITransactionAttrs
-
-class DataRecord:
-    """Abstract base class for iterator protocol."""
-
+            self.tpcVote(transaction)
+            self.tpcFinish(transaction)
 
 
 class BerkeleyConfig:
@@ -606,7 +593,7 @@
             self._len = len(self._serials)
         return self._len
 
-    def new_oid(self, last=None):
+    def newObjectId(self, last=None):
         """Create a new object id.
 
         If last is provided, the new oid will be one greater than that.
@@ -615,7 +602,7 @@
         if self._len is not None:
             # Increment the cached length
             self._len += 1
-        return BaseStorage.new_oid(self, last)
+        return BaseStorage.newObjectId(self, last)
 
     def getSize(self):
         """Return the size of the database."""


=== Zope3/src/zodb/storage/bdbfull.py 1.10 => 1.10.2.1 ===
--- Zope3/src/zodb/storage/bdbfull.py:1.10	Fri Jan 24 13:54:12 2003
+++ Zope3/src/zodb/storage/bdbfull.py	Tue Feb 11 09:40:49 2003
@@ -21,12 +21,14 @@
 import cPickle as pickle
 from struct import pack, unpack
 
-from zodb import interfaces
+from zodb.interfaces import *
+from zodb.storage.interfaces import *
 from zodb.utils import p64, u64
 from zodb.serialize import findrefs
 from zodb.timestamp import TimeStamp
 from zodb.conflict import ConflictResolvingStorage, ResolvedSerial
-from zodb.interfaces import ITransactionAttrs, StorageSystemError
+from zodb.interfaces import ITransactionAttrs
+from zodb.storage.interfaces import StorageSystemError
 from zodb.storage.base import db, ZERO, BerkeleyBase, PackStop, _WorkThread
 from zodb.storage._helper import incr
 
@@ -52,6 +54,9 @@
 
 
 class BDBFullStorage(BerkeleyBase, ConflictResolvingStorage):
+    
+    __implements__ = IStorage, IUndoStorage, IVersionStorage
+    
     def _init(self):
         # Data Type Assumptions:
         #
@@ -516,7 +521,7 @@
                 oversion = self._versions[ovid]
                 # We're trying to make a change on a version that's different
                 # than the version the current revision is on.  Nuh uh.
-                raise interfaces.VersionLockError(oid, oversion)
+                raise VersionLockError(oid, oversion)
             else:
                 # We're making another change to this object on this version.
                 # The non-version revid is the same as for the previous
@@ -546,7 +551,7 @@
     def store(self, oid, serial, data, version, transaction):
         # Lock and transaction wrapper
         if transaction is not self._transaction:
-            raise interfaces.StorageTransactionError(self, transaction)
+            raise StorageTransactionError(self, transaction)
         self._lock_acquire()
         try:
             return self._withtxn(self._dostore, oid, serial, data, version)
@@ -647,7 +652,7 @@
         # should be considered just a hint, and is ignored if the transaction
         # doesn't exist.
         if transaction is not self._transaction:
-            raise interfaces.StorageTransactionError(self, transaction)
+            raise StorageTransactionError(self, transaction)
         self._lock_acquire()
         try:
             self._withtxn(
@@ -678,7 +683,7 @@
     def _doAbortVersion(self, txn, version):
         vid = self._vids.get(version)
         if vid is None:
-            raise interfaces.VersionError, 'not a version: %s' % version
+            raise VersionError, 'not a version: %s' % version
         # We need to keep track of the oids that are affected by the abort so
         # that we can return it to the connection, which must invalidate the
         # objects so they can be reloaded.
@@ -757,10 +762,10 @@
         # Abort the version, but retain enough information to make the abort
         # undoable.
         if transaction is not self._transaction:
-            raise interfaces.StorageTransactionError(self, transaction)
+            raise StorageTransactionError(self, transaction)
         # We can't abort the empty version, because it's not a version!
         if not version:
-            raise interfaces.VersionError
+            raise VersionError
         self._lock_acquire()
         try:
             return self._withtxn(self._doAbortVersion, version)
@@ -832,10 +837,10 @@
         # and dest are version strings, and if we're committing to a
         # non-version, dest will be empty.
         if transaction is not self._transaction:
-            raise interfaces.StorageTransactionError(self, transaction)
+            raise StorageTransactionError(self, transaction)
         # Sanity checks
         if not src or src == dest:
-            raise interfaces.VersionCommitError
+            raise VersionCommitError
         self._lock_acquire()
         try:
             return self._withtxn(self._doCommitVersion, src, dest)
@@ -1097,7 +1102,7 @@
             # The object's revision is in it's initial creation state but
             # we're asking for an undo of something other than the initial
             # creation state.  No, no.
-            raise interfaces.UndoError, 'Undoing mismatched zombification'
+            raise UndoError, 'Undoing mismatched zombification'
         last_lrevid     = self._metadata[oid+last_prevrevid][16:24]
         target_metadata = self._metadata[oid+target_prevrevid]
         target_lrevid   = target_metadata[16:24]
@@ -1115,15 +1120,15 @@
             try:
                 data = self.resolveConflict(
                     oid, ctid, tid, self._pickles[oid+target_lrevid])
-            except interfaces.ConflictError:
-                raise interfaces.UndoError('Cannot undo transaction')
+            except ConflictError:
+                raise UndoError, 'Cannot undo transaction'
             return oid, target_metadata, data
 
     def _dotxnundo(self, txn, tid):
         # First, make sure the transaction isn't protected by a pack.
         packtime = self._last_packtime()
         if tid <= packtime:
-            raise interfaces.UndoError, 'Transaction cannot be undone'
+            raise UndoError, 'Transaction cannot be undone'
         # Calculate all the oids of objects modified in this transaction
         newrevs = []
         c = self._txnoids.cursor(txn=txn)
@@ -1181,9 +1186,9 @@
             self._objrevs.put(newserial+oid, prevrevid, txn=txn)
         return rtnoids.keys()
 
-    def transactionalUndo(self, tid, transaction):
+    def undo(self, tid, transaction):
         if transaction is not self._transaction:
-            raise interfaces.StorageTransactionError(self, transaction)
+            raise StorageTransactionError(self, transaction)
         self._lock_acquire()
         try:
             return self._withtxn(self._dotxnundo, tid)
@@ -1255,59 +1260,6 @@
             last = abs(last)
         return self._withlock(self._doundolog, first, last, filter)
 
-    def history(self, oid, version=None, size=1, filter=None):
-        self._lock_acquire()
-        try:
-            # Jim says:
-            #
-            #     This documentation is wrong. I think that the version should
-            #     be ignored.  It really shouldn't be in the signature. Zope
-            #     never passes the version argument.
-            #
-            # so we ignore `version', which makes our lives a bit easier.  We
-            # start with the most recent revision of the object, then search
-            # the transaction records backwards until we find enough records.
-            history = []
-            serial, tid = self._getSerialAndTid(oid)
-            # BAW: Again, let KeyErrors percolate up
-            while len(history) < size:
-                # Some information comes out of the revision metadata...
-                vid, nvrevid, lrevid, previd = unpack(
-                    '>8s8s8s8s', self._metadata[oid+tid])
-                # ...while other information comes out of the transaction
-                # metadata.
-                txnmeta = self._txnMetadata[tid]
-                userlen, desclen = unpack('>II', txnmeta[:8])
-                user = txnmeta[8:8+userlen]
-                desc = txnmeta[8+userlen:8+userlen+desclen]
-                # Now get the pickle size
-                data = self._pickles[oid+lrevid]
-                # Create a HistoryEntry structure, which turns out to be a
-                # dictionary with some specifically named entries (BAW:
-                # although this poorly documented).
-                if vid == ZERO:
-                    retvers = ''
-                else:
-                    retvers = self._versions[vid]
-                # The HistoryEntry object
-                d = {'time'       : TimeStamp(tid).timeTime(),
-                     'user_name'  : user,
-                     'description': desc,
-                     'serial'     : serial,
-                     'version'    : retvers,
-                     'size'       : len(data),
-                     }
-                if filter is None or filter(d):
-                    history.append(d)
-                # Chase the link backwards to the next most historical
-                # revision, stopping when we've reached the end.
-                if previd == ZERO:
-                    break
-                serial = tid = previd
-            return history
-        finally:
-            self._lock_release()
-
     # Packing
     #
     # There are two types of pack operations, the classic pack and the
@@ -1727,17 +1679,6 @@
         finally:
             c.close()
             self._lock_release()
-
-    # Other interface assertions
-    def supportsTransactionalUndo(self):
-        return True
-
-    def supportsUndo(self):
-        return True
-
-    def supportsVersions(self):
-        return True
-
 
 
 class _GetItemBase:


=== Zope3/src/zodb/storage/bdbminimal.py 1.10 => 1.10.2.1 ===
--- Zope3/src/zodb/storage/bdbminimal.py:1.10	Thu Jan 30 18:17:43 2003
+++ Zope3/src/zodb/storage/bdbminimal.py	Tue Feb 11 09:40:49 2003
@@ -17,7 +17,7 @@
 $Revision$
 """
 
-from zodb import interfaces
+from zodb.storage.interfaces import *
 from zodb.utils import p64, u64
 from zodb.serialize import findrefs
 from zodb.conflict import ConflictResolvingStorage, ResolvedSerial
@@ -40,6 +40,9 @@
 
 
 class BDBMinimalStorage(BerkeleyBase, ConflictResolvingStorage):
+
+    __implements__ = IStorage
+    
     def _init(self):
         # Data Type Assumptions:
         #
@@ -283,10 +286,10 @@
 
     def store(self, oid, serial, data, version, transaction):
         if transaction is not self._transaction:
-            raise interfaces.StorageTransactionError(self, transaction)
+            raise StorageTransactionError(self, transaction)
         # We don't support versions
         if version <> '':
-            raise interfaces.Unsupported, 'versions are not supported'
+            raise NotImplementedError
         # All updates must be done with the application lock acquired
         self._lock_acquire()
         try:
@@ -343,7 +346,7 @@
 
     def load(self, oid, version):
         if version <> '':
-            raise interfaces.Unsupported, 'versions are not supported'
+            raise NotImplementedError
         self._lock_acquire()
         try:
             # Get the current serial number for this object
@@ -512,30 +515,7 @@
             orec = self._oidqueue.consume(txn)
         assert len(self._oidqueue) == 0
 
-    #
-    # Stuff we don't support
-    #
-
-    def supportsTransactionalUndo(self):
-        return False
-
-    def supportsUndo(self):
-        return False
-
-    def supportsVersions(self):
-        return False
-
-    # Don't implement these
-    #
-    # versionEmpty(self, version)
-    # versions(self, max=None)
-    # loadSerial(self, oid, serial)
     # getSerial(self, oid)
-    # transactionalUndo(self, tid, transaction)
-    # undoLog(self, first=0, last=-20, filter=None)
-    # history(self, oid, version=None, size=1, filter=None)
-    # iterator(self, start=None, stop=None)
-
 
 
 class _Autopack(_WorkThread):


=== Zope3/src/zodb/storage/file.py 1.7 => 1.7.2.1 ===
--- Zope3/src/zodb/storage/file.py:1.7	Mon Feb  3 18:00:45 2003
+++ Zope3/src/zodb/storage/file.py	Tue Feb 11 09:40:49 2003
@@ -127,6 +127,8 @@
 $Id$
 """
 
+from __future__ import generators
+
 import base64
 from cPickle import Pickler, Unpickler, loads
 import errno
@@ -144,7 +146,7 @@
     fsync = None
 
 import zodb.db
-from zodb.storage.base import BaseStorage, TransactionRecord, DataRecord
+from zodb.storage.base import BaseStorage
 from zodb import conflict
 from zodb import interfaces
 from zodb.interfaces import UndoError, POSKeyError, MultipleUndoErrors
@@ -153,6 +155,8 @@
 from zodb.lockfile import lock_file
 from zodb.utils import p64, u64, cp, z64
 from zodb.storage.fsindex import fsIndex
+from zodb.storage.interfaces import *
+from zodb.interfaces import ITransactionAttrs
 
 t32 = 1L << 32
 # the struct formats for the headers
@@ -175,7 +179,7 @@
     logger.critical(message, *data)
     raise CorruptedTransactionError(message % data)
 
-class FileStorageError(interfaces.StorageError):
+class FileStorageError(StorageError):
     pass
 
 class PackError(FileStorageError):
@@ -187,8 +191,7 @@
     The format of the given file is not valid.
     """
 
-class CorruptedFileStorageError(FileStorageError,
-                                interfaces.StorageSystemError):
+class CorruptedFileStorageError(FileStorageError, StorageSystemError):
     """Corrupted file storage."""
 
 class CorruptedTransactionError(CorruptedFileStorageError):
@@ -206,8 +209,7 @@
         else:
             return "Error reading unknown oid.  Found %r" % self.buf
 
-class FileStorageQuotaError(FileStorageError,
-                            interfaces.StorageSystemError):
+class FileStorageQuotaError(FileStorageError, StorageSystemError):
     """File storage quota exceeded."""
 
 def DB(file_name, create=0, read_only=0, stop=None, quota=None,
@@ -486,6 +488,8 @@
     # default pack time is 0
     _packt = z64
 
+    __implements__ = IStorage, IUndoStorage, IVersionStorage
+
     def __init__(self, file_name, create=0, read_only=0, stop=None,
                  quota=None):
 
@@ -674,7 +678,7 @@
     def commitVersion(self, src, dest, transaction, abort=None):
         # We are going to commit by simply storing back pointers.
         if self._is_read_only:
-            raise interfaces.ReadOnlyError()
+            raise ReadOnlyError()
         if not (src and isinstance(src, StringType)
                 and isinstance(dest, StringType)):
             raise interfaces.VersionCommitError('Invalid source version')
@@ -688,7 +692,7 @@
                 "Internal error, can't abort to a version")
 
         if transaction is not self._transaction:
-            raise interfaces.StorageTransactionError(self, transaction)
+            raise StorageTransactionError(self, transaction)
 
         self._lock_acquire()
         try:
@@ -820,9 +824,9 @@
 
     def store(self, oid, serial, data, version, transaction):
         if self._is_read_only:
-            raise interfaces.ReadOnlyError()
+            raise ReadOnlyError()
         if transaction is not self._transaction:
-            raise interfaces.StorageTransactionError(self, transaction)
+            raise StorageTransactionError(self, transaction)
 
         self._lock_acquire()
         try:
@@ -927,9 +931,9 @@
         # should be considered just a hint, and is ignored if the transaction
         # doesn't exist.
         if self._is_read_only:
-            raise interfaces.ReadOnlyError()
+            raise ReadOnlyError()
         if transaction is not self._transaction:
-            raise interfaces.StorageTransactionError(self, transaction)
+            raise StorageTransactionError(self, transaction)
 
         self._lock_acquire()
         try:
@@ -1009,12 +1013,6 @@
                      "at %d or %d", prev, bp)
                 return None
 
-    def supportsUndo(self):
-        return 1
-
-    def supportsVersions(self):
-        return 1
-
     def _clear_temp(self):
         self._tindex.clear()
         self._tvindex.clear()
@@ -1036,7 +1034,7 @@
                 raise FileStorageError('too much extension data')
 
 
-    def tpc_vote(self, transaction):
+    def tpcVote(self, transaction):
         self._lock_acquire()
         try:
             if transaction is not self._transaction:
@@ -1104,9 +1102,6 @@
             self._file.truncate(self._pos)
             self._nextpos=0
 
-    def supportsTransactionalUndo(self):
-        return 1
-
     def _undoDataInfo(self, oid, pos, tpos):
         """Return the serial, data pointer, data, and version for the oid
         record at pos"""
@@ -1267,7 +1262,7 @@
         finally:
             self._lock_release()
 
-    def transactionalUndo(self, transaction_id, transaction):
+    def undo(self, transaction_id, transaction):
         """Undo a transaction, given by transaction_id.
 
         Do so by writing new data that reverses the action taken by
@@ -1280,9 +1275,9 @@
         """
 
         if self._is_read_only:
-            raise interfaces.ReadOnlyError()
+            raise ReadOnlyError()
         if transaction is not self._transaction:
-            raise interfaces.StorageTransactionError(self, transaction)
+            raise StorageTransactionError(self, transaction)
 
         self._lock_acquire()
         try:
@@ -1445,7 +1440,7 @@
         """
 
         if self._is_read_only:
-            raise interfaces.ReadOnlyError()
+            raise ReadOnlyError()
 
         stop = timeStampFromTime(t).raw()
         if stop == z64:
@@ -2180,33 +2175,18 @@
                 break
     except:
         error("couldn\'t write truncated data for %s", name)
-        raise interfaces.StorageSystemError, (
-            "Couldn't save truncated data")
+        raise StorageSystemError("Couldn't save truncated data")
 
     seek(pos)
     file.truncate()
 
-class Iterator:
-    """A General simple iterator that uses the Python for-loop index protocol
-    """
-    __index=-1
-    __current=None
-
-    def __getitem__(self, i):
-        __index=self.__index
-        while i > __index:
-            __index=__index+1
-            self.__current=self.next(__index)
-
-        self.__index=__index
-        return self.__current
-
-
-class FileIterator(Iterator, FileStorageFormatter):
+class FileIterator(FileStorageFormatter):
     """Iterate over the transactions in a FileStorage file."""
     _ltid = z64
     _file = None
 
+    __implements__ = IStorageIterator
+
     def __init__(self, file, start=None, stop=None):
         if isinstance(file, StringType):
             file = open(file, 'rb')
@@ -2253,16 +2233,16 @@
                           "(%s != %s)",
                           self._file.name, pos, u64(rtl), u64(stl))
 
-    def next(self, index=0):
+    def __iter__(self):
         if self._file is None:
             # A closed iterator.  XXX: Is IOError the best we can do?  For
             # now, mimic a read on a closed file.
-            raise IOError, 'iterator is closed'
+            raise IOError("iterator is closed")
         file=self._file
         seek=file.seek
         read=file.read
-        pos=self._pos
-
+        
+        pos = self._pos
         while 1:
             # Read the transaction record
             seek(pos)
@@ -2312,7 +2292,7 @@
                     break
 
             if self._stop is not None and tid > self._stop:
-                raise IndexError, index
+                return
 
             tpos=pos
             tend=tpos+tl
@@ -2346,15 +2326,14 @@
                 warn("%s redundant transaction length check failed at %s",
                      self._file.name, pos)
                 break
-            self._pos = pos + 8
-
-            return result
-
-        raise IndexError, index
+            pos += 8
+            yield result
 
-class RecordIterator(Iterator, FileStorageFormatter, TransactionRecord):
+class RecordIterator(FileStorageFormatter):
     """Iterate over the transactions in a FileStorage file."""
 
+    __implements__ = ITransactionRecordIterator, ITransactionAttrs
+
     def __init__(self, tid, status, user, desc, ext, pos, tend, file, tpos):
         self.tid = tid
         self.status = status
@@ -2366,7 +2345,7 @@
         self._file = file
         self._tpos = tpos
 
-    def next(self, index=0):
+    def __iter__(self):
         pos = self._pos
         while pos < self._tend:
             # Read the data records for this transaction
@@ -2377,9 +2356,9 @@
             if pos + dlen > self._tend or h.tloc != self._tpos:
                 warn("%s data record exceeds transaction record at %s",
                      file.name, pos)
-                break
+                return
 
-            self._pos = pos + dlen
+            pos += dlen
             prev_txn = None
             if h.plen:
                 data = self._file.read(h.plen)
@@ -2395,14 +2374,13 @@
                     data, _s, tid = self._loadBackTxn(h.oid, h.back)
                     prev_txn = self.getTxnFromData(h.oid, h.back)
 
-            r = Record(h.oid, h.serial, h.version, data, prev_txn)
+            yield Record(h.oid, h.serial, h.version, data, prev_txn)
 
-            return r
-
-        raise IndexError, index
-
-class Record(DataRecord):
+class Record:
     """An abstract database record."""
+
+    __implements__ = IDataRecord
+    
     def __init__(self, *args):
         self.oid, self.serial, self.version, self.data, self.data_txn = args
 


=== Zope3/src/zodb/storage/fsrecover.py 1.2 => 1.2.6.1 ===
--- Zope3/src/zodb/storage/fsrecover.py:1.2	Wed Dec 25 09:12:19 2002
+++ Zope3/src/zodb/storage/fsrecover.py	Tue Feb 11 09:40:49 2003
@@ -269,7 +269,7 @@
             if verbose > 1: print
             sys.stdout.flush()
 
-        ofs.tpc_begin(transaction, tid, transaction.status)
+        ofs.tpcBegin(transaction, tid, transaction.status)
 
         if verbose:
             print 'begin', pos, _ts,
@@ -288,17 +288,17 @@
         except:
             if partial and nrec:
                 ofs._status='p'
-                ofs.tpc_vote(transaction)
-                ofs.tpc_finish(transaction)
+                ofs.tpcVote(transaction)
+                ofs.tpcFinish(transaction)
                 if verbose: print 'partial'
             else:
-                ofs.tpc_abort(transaction)
+                ofs.tpcAbort(transaction)
             print "\n%s: %s\n" % sys.exc_info()[:2]
             if not verbose: progress(prog1)
             pos = scan(file, pos, file_size)
         else:
-            ofs.tpc_vote(transaction)
-            ofs.tpc_finish(transaction)
+            ofs.tpcVote(transaction)
+            ofs.tpcFinish(transaction)
             if verbose:
                 print 'finish'
                 sys.stdout.flush()


=== Zope3/src/zodb/storage/interfaces.py 1.2 => 1.2.2.1 ===
--- Zope3/src/zodb/storage/interfaces.py:1.2	Mon Feb  3 18:05:05 2003
+++ Zope3/src/zodb/storage/interfaces.py	Tue Feb 11 09:40:49 2003
@@ -16,7 +16,8 @@
 $Id$
 """
 
-from zope.interface import Interface
+from zope.interface import Interface, Attribute
+from zodb.interfaces import POSError
 
 __all__ = ["IStorage",
            "IUndoStorage",
@@ -24,6 +25,14 @@
            "IStorageIterator",
            "ITransactionRecordIterator",
            "IDataRecord",
+           # the rest are exceptions
+           "StorageError",
+           "StorageVersionError",
+           "StorageTransactionError",
+           "StorageSystemError",
+           "MountedStorageError",
+           "ReadOnlyError",
+           "TransactionTooLargeError",
            ]
 
 class IStorage(Interface):
@@ -116,7 +125,7 @@
         """
         pass
 
-    def new_oid():
+    def newObjectId():
         pass
 
     def registerDB(db):
@@ -125,70 +134,44 @@
     def isReadOnly():
         pass
 
-    def supportsUndo():
-        pass
-
-    def supportsVersions():
-        pass
-
     def getExtensionMethods():
         pass
 
     def copyTransactionsFrom(other, versbose=False):
         pass
 
-    def iterator(start=None, stop=None):
-        pass
-
     def lastTransaction():
         pass
 
     def lastSerial(oid):
         pass
 
-    # two-phase commit
-
-    def tpc_begin(txn):
-        pass
-
-    def tpc_vote(txn):
+    def pack(t):
         pass
 
-    def tpc_finish(txn):
-        pass
+    # two-phase commit
 
-    def tpc_abort(txn):
+    def tpcBegin(txn):
         pass
 
-    # storages that keep revisions
-
-    def transactionalUndo(txnid, txn):
+    def tpcVote(txn):
         pass
 
-    def undoInfo(first=0, last=-20, specification=None):
+    def tpcFinish(txn):
         pass
 
-    def undoLog(first, last, filter=None):
+    def tpcAbort(txn):
         pass
 
     def pack(t):
         pass
 
-    def getSerial(oid):
-        pass
-
-    def loadSerial(oid, serial):
-        pass
-
 class IUndoStorage(Interface):
     
-    def pack(t):
-        pass
-
     def loadSerial(oid, serial):
         pass
     
-    def transactionalUndo(txnid, txn):
+    def undo(txnid, txn):
         pass
 
     def undoInfo(first=0, last=-20, specification=None):
@@ -197,6 +180,9 @@
     def undoLog(first, last, filter=None):
         """deprecated, using undoInfo instead"""
 
+    def iterator(start=None, stop=None):
+        pass
+
 class IVersionStorage(Interface):
     # XXX should be renamed
     def abortVersion(version):
@@ -255,3 +241,35 @@
                          wrote the data.  The current transaction contains
                          a logical copy of that data.
                          """)
+
+class StorageError(POSError):
+    """Base class for storage based exceptions."""
+
+class StorageVersionError(StorageError):
+    """The storage version doesn't match the database version."""
+
+    def __init__(self, db_ver, storage_ver):
+        self.db_ver = db_ver
+        self.storage_ver = storage_ver
+
+    def __str__(self):
+        db = ".".join(self.db_ver)
+        storage = ".".join(self.storage_ver)
+        return ("Storage version %s passed to database version %s"
+                % (storage, db))
+
+class StorageTransactionError(StorageError):
+    """An operation was invoked for an invalid transaction or state."""
+
+class StorageSystemError(StorageError):
+    """Panic! Internal storage error!"""
+
+class MountedStorageError(StorageError):
+    """Unable to access mounted storage."""
+
+class ReadOnlyError(StorageError):
+    """Unable to modify objects in a read-only storage."""
+
+class TransactionTooLargeError(StorageTransactionError):
+    """The transaction exhausted some finite storage resource."""
+


=== Zope3/src/zodb/storage/mapping.py 1.2 => 1.2.6.1 ===
--- Zope3/src/zodb/storage/mapping.py:1.2	Wed Dec 25 09:12:19 2002
+++ Zope3/src/zodb/storage/mapping.py	Tue Feb 11 09:40:50 2003
@@ -92,6 +92,7 @@
 import zodb.db
 from zodb import interfaces, utils
 from zodb.storage import base
+from zodb.storage.interfaces import *
 from zodb.serialize import findrefs
 from zodb.timestamp import TimeStamp
 from zodb.utils import z64
@@ -104,6 +105,8 @@
 
 class MappingStorage(base.BaseStorage):
 
+    __implements__ = IStorage
+
     def __init__(self, name='Mapping Storage'):
 
         base.BaseStorage.__init__(self, name)
@@ -125,10 +128,10 @@
 
     def store(self, oid, serial, data, version, transaction):
         if transaction is not self._transaction:
-            raise interfaces.StorageTransactionError(self, transaction)
+            raise StorageTransactionError(self, transaction)
 
         if version:
-            raise interfaces.Unsupported, "Versions aren't supported"
+            raise NotImplementedError
 
         self._lock_acquire()
         try: