[Zodb-checkins] SVN: ZODB/branches/jim-storage-api-cleanup/src/ZODB/BaseStorage.py Updated to work with new model in which storages that don't support

Jim Fulton jim at zope.com
Thu Apr 26 15:35:42 EDT 2007


Log message for revision 74813:
  Updated to work with new model in which storages that don't support
  undo don't have to provide any undo messages.
  

Changed:
  U   ZODB/branches/jim-storage-api-cleanup/src/ZODB/BaseStorage.py

-=-
Modified: ZODB/branches/jim-storage-api-cleanup/src/ZODB/BaseStorage.py
===================================================================
--- ZODB/branches/jim-storage-api-cleanup/src/ZODB/BaseStorage.py	2007-04-26 19:01:08 UTC (rev 74812)
+++ ZODB/branches/jim-storage-api-cleanup/src/ZODB/BaseStorage.py	2007-04-26 19:35:41 UTC (rev 74813)
@@ -54,21 +54,7 @@
     If it stores multiple revisions, it should implement
     loadSerial()
     loadBefore()
-    iterator()
 
-    If the subclass wants to implement undo, it should implement the
-    multiple revision methods and:
-    undo()
-    undoInfo()
-    undoLog()
-
-    If the subclass wants to implement versions, it must implement:
-    abortVersion()
-    commitVersion()
-    modifiedInVersion()
-    versionEmpty()
-    versions()
-
     Each storage will have two locks that are accessed via lock
     acquire and release methods bound to the instance.  (Yuck.)
     _lock_acquire / _lock_release (reentrant)
@@ -112,12 +98,6 @@
         else:
             self._oid = oid
 
-    def close(self):
-        pass
-
-    def cleanup(self):
-        pass
-
     def sortKey(self):
         """Return a string that can be used to sort storage instances.
 
@@ -186,7 +166,7 @@
 
     def _abort(self):
         """Subclasses should redefine this to supply abort actions"""
-        raise NotImplementedError
+        pass
 
     def tpc_begin(self, transaction, tid=None, status=' '):
         if self._is_read_only:
@@ -230,7 +210,7 @@
     def _begin(self, tid, u, d, e):
         """Subclasses should redefine this to supply transaction start actions.
         """
-        raise NotImplementedError
+        pass
 
     def tpc_vote(self, transaction):
         self._lock_acquire()
@@ -244,7 +224,7 @@
     def _vote(self):
         """Subclasses should redefine this to supply transaction vote actions.
         """
-        raise NotImplementedError
+        pass
 
     def tpc_finish(self, transaction, f=None):
         # It's important that the storage calls the function we pass
@@ -279,7 +259,14 @@
     def getTid(self, oid):
         self._lock_acquire()
         try:
-            v = self.modifiedInVersion(oid)
+            v = ''
+            try:
+                supportsVersions = self.supportsVersions
+            except AttributeError:
+                pass
+            else:
+                if supportsVersions():
+                    v = self.modifiedInVersion(oid)
             pickledata, serial = self.load(oid, v)
             return serial
         finally:
@@ -291,120 +278,78 @@
 
     def loadBefore(self, oid, tid):
         """Return most recent revision of oid before tid committed."""
+        return None
 
-        # Unsure: Is it okay for loadBefore() to return current data?
-        # There doesn't seem to be a good reason to forbid it, even
-        # though the typical use of this method will never find
-        # current data.  But maybe we should call it loadByTid()?
-
-        n = 2
-        start_time = None
-        end_time = None
-        while start_time is None:
-            # The history() approach is a hack, because the dict
-            # returned by history() doesn't contain a tid.  It
-            # contains a serialno, which is often the same, but isn't
-            # required to be.  We'll pretend it is for now.
-
-            # A second problem is that history() doesn't say anything
-            # about whether the transaction status.  If it falls before
-            # the pack time, we can't honor the MVCC request.
-
-            # Note: history() returns the most recent record first.
-
-            # TODO: The filter argument to history() only appears to be
-            # supported by FileStorage.  Perhaps it shouldn't be used.
-            L = self.history(oid, "", n, lambda d: not d["version"])
-            if not L:
-                return
-            for d in L:
-                if d["serial"] < tid:
-                    start_time = d["serial"]
-                    break
-                else:
-                    end_time = d["serial"]
-            if len(L) < n:
-                break
-            n *= 2
-        if start_time is None:
-            return None
-        data = self.loadSerial(oid, start_time)
-        return data, start_time, end_time
-
-    def getExtensionMethods(self):
-        """getExtensionMethods
-
-        This returns a dictionary whose keys are names of extra methods
-        provided by this storage. Storage proxies (such as ZEO) should
-        call this method to determine the extra methods that they need
-        to proxy in addition to the standard storage methods.
-        Dictionary values should be None; this will be a handy place
-        for extra marshalling information, should we need it
-        """
-        return {}
-
     def copyTransactionsFrom(self, other, verbose=0):
         """Copy transactions from another storage.
 
         This is typically used for converting data from one storage to
         another.  `other` must have an .iterator() method.
         """
-        _ts=None
-        ok=1
-        preindex={};
-        preget=preindex.get   # waaaa
-        # restore() is a new storage API method which has an identical
-        # signature to store() except that it does not return anything.
-        # Semantically, restore() is also identical to store() except that it
-        # doesn't do the ConflictError or VersionLockError consistency
-        # checks.  The reason to use restore() over store() in this method is
-        # that store() cannot be used to copy transactions spanning a version
-        # commit or abort, or over transactional undos.
-        #
-        # We'll use restore() if it's available, otherwise we'll fall back to
-        # using store().  However, if we use store, then
-        # copyTransactionsFrom() may fail with VersionLockError or
-        # ConflictError.
-        restoring = hasattr(self, 'restore')
-        fiter = other.iterator()
-        for transaction in fiter:
-            tid=transaction.tid
-            if _ts is None:
-                _ts=TimeStamp(tid)
+        copy(other, self, verbose)
+
+def copy(source, dest, verbose=0):
+    """Copy transactions from a source to a destination storage
+
+    This is typically used for converting data from one storage to
+    another.  `source` must have an .iterator() method.
+    """
+    _ts = None
+    ok = 1
+    preindex = {};
+    preget = preindex.get
+    # restore() is a new storage API method which has an identical
+    # signature to store() except that it does not return anything.
+    # Semantically, restore() is also identical to store() except that it
+    # doesn't do the ConflictError or VersionLockError consistency
+    # checks.  The reason to use restore() over store() in this method is
+    # that store() cannot be used to copy transactions spanning a version
+    # commit or abort, or over transactional undos.
+    #
+    # We'll use restore() if it's available, otherwise we'll fall back to
+    # using store().  However, if we use store, then
+    # copyTransactionsFrom() may fail with VersionLockError or
+    # ConflictError.
+    restoring = hasattr(dest, 'restore')
+    fiter = source.iterator()
+    for transaction in fiter:
+        tid = transaction.tid
+        if _ts is None:
+            _ts = TimeStamp(tid)
+        else:
+            t = TimeStamp(tid)
+            if t <= _ts:
+                if ok: print ('Time stamps out of order %s, %s' % (_ts, t))
+                ok = 0
+                _ts = t.laterThan(_ts)
+                tid = `_ts`
             else:
-                t=TimeStamp(tid)
-                if t <= _ts:
-                    if ok: print ('Time stamps out of order %s, %s' % (_ts, t))
-                    ok=0
-                    _ts=t.laterThan(_ts)
-                    tid=`_ts`
-                else:
-                    _ts = t
-                    if not ok:
-                        print ('Time stamps back in order %s' % (t))
-                        ok=1
+                _ts = t
+                if not ok:
+                    print ('Time stamps back in order %s' % (t))
+                    ok = 1
 
+        if verbose:
+            print _ts
+
+        dest.tpc_begin(transaction, tid, transaction.status)
+        for r in transaction:
+            oid = r.oid
             if verbose:
-                print _ts
+                print oid_repr(oid), r.version, len(r.data)
+            if restoring:
+                dest.restore(oid, r.tid, r.data, r.version,
+                             r.data_txn, transaction)
+            else:
+                pre = preget(oid, None)
+                s = dest.store(oid, pre, r.data, r.version, transaction)
+                preindex[oid] = s
 
-            self.tpc_begin(transaction, tid, transaction.status)
-            for r in transaction:
-                oid=r.oid
-                if verbose:
-                    print oid_repr(oid), r.version, len(r.data)
-                if restoring:
-                    self.restore(oid, r.tid, r.data, r.version,
-                                 r.data_txn, transaction)
-                else:
-                    pre=preget(oid, None)
-                    s=self.store(oid, pre, r.data, r.version, transaction)
-                    preindex[oid]=s
+        dest.tpc_vote(transaction)
+        dest.tpc_finish(transaction)
 
-            self.tpc_vote(transaction)
-            self.tpc_finish(transaction)
+    fiter.close()
 
-        fiter.close()
-
 class TransactionRecord:
     """Abstract base class for iterator protocol"""
 



More information about the Zodb-checkins mailing list