[Checkins] SVN: ZODB/branches/gocept-iteration/src/Z snapshot

Thomas Lotze tl at gocept.com
Wed Feb 13 10:58:19 EST 2008


Log message for revision 83798:
  snapshot

Changed:
  U   ZODB/branches/gocept-iteration/src/ZEO/ClientStorage.py
  U   ZODB/branches/gocept-iteration/src/ZEO/ServerStub.py
  U   ZODB/branches/gocept-iteration/src/ZEO/StorageServer.py
  U   ZODB/branches/gocept-iteration/src/ZEO/tests/testZEO.py
  U   ZODB/branches/gocept-iteration/src/ZODB/DemoStorage.py
  U   ZODB/branches/gocept-iteration/src/ZODB/interfaces.py
  U   ZODB/branches/gocept-iteration/src/ZODB/tests/PackableStorage.py

-=-
Modified: ZODB/branches/gocept-iteration/src/ZEO/ClientStorage.py
===================================================================
--- ZODB/branches/gocept-iteration/src/ZEO/ClientStorage.py	2008-02-13 15:58:03 UTC (rev 83797)
+++ ZODB/branches/gocept-iteration/src/ZEO/ClientStorage.py	2008-02-13 15:58:18 UTC (rev 83798)
@@ -28,6 +28,7 @@
 import time
 import types
 import logging
+import weakref
 
 from zope.interface import implements
 from ZEO import ServerStub
@@ -37,11 +38,12 @@
 from ZEO.auth import get_module
 from ZEO.zrpc.client import ConnectionManager
 
+import ZODB.interfaces
 import ZODB.lock_file
+import ZODB.BaseStorage
 from ZODB import POSException
 from ZODB import utils
 from ZODB.loglevels import BLATHER
-from ZODB.interfaces import IBlobStorage
 from ZODB.blob import rename_or_copy_blob
 from persistent.TimeStamp import TimeStamp
 
@@ -91,7 +93,6 @@
 MB = 1024**2
 
 class ClientStorage(object):
-
     """A Storage class that is a network client to a remote storage.
 
     This is a faithful implementation of the Storage API.
@@ -100,9 +101,10 @@
     tpc_begin().
     """
 
-    implements(IBlobStorage)
+    implements(ZODB.interfaces.IBlobStorage,
+               ZODB.interfaces.IStorageIteration)
+
     # Classes we instantiate.  A subclass might override.
-
     TransactionBufferClass = TransactionBuffer
     ClientCacheClass = ClientCache
     ConnectionManagerClass = ConnectionManager
@@ -259,6 +261,8 @@
         self._password = password
         self._realm = realm
 
+        self._iterators = weakref.WeakValueDictionary()
+
         # Flag tracking disconnections in the middle of a transaction.  This
         # is reset in tpc_begin() and set in notifyDisconnected().
         self._midtxn_disconnect = 0
@@ -1241,3 +1245,43 @@
     end = endVerify
     Invalidate = invalidateTrans
 
+    # IStorageIteration
+
+    def iterator(self, start=None, stop=None):
+        """Return an IStorageTransactionInformation iterator."""
+        # iids are "iterator IDs" that can be used to query an iterator whose
+        # status is held on the server.
+        iid = self._server.iterator_start(start, stop)
+        iterator = self._iterators[iid] = self._iterator(iid, start, stop)
+        return iterator
+
+    def _iterator(self, iid, start, stop):
+        while True:
+            item = self._server.iterator_next(iid)
+            if item is None:
+                break
+            yield ClientStorageTransactionInformation(self, *item)
+
+
+class ClientStorageTransactionInformation(ZODB.BaseStorage.TransactionRecord):
+
+    def __init__(self, storage, tid, status, user, description, extension):
+        self._storage = storage
+
+        self.tid = tid
+        self.status = status
+        self.user = user
+        self.description = description
+        self.extension = extension
+
+    def __iter__(self):
+        riid = self._storage._server.iterator_record_start(self.tid)
+        iterator = self._storage._iterators[riid] = self._iterator(riid)
+        return iterator
+
+    def _iterator(self, riid):
+        while True:
+            item = self._storage._server.iterator_record_next(riid)
+            if item is None:
+                break
+            yield ZODB.BaseStorage.DataRecord(*item)

Modified: ZODB/branches/gocept-iteration/src/ZEO/ServerStub.py
===================================================================
--- ZODB/branches/gocept-iteration/src/ZEO/ServerStub.py	2008-02-13 15:58:03 UTC (rev 83797)
+++ ZODB/branches/gocept-iteration/src/ZEO/ServerStub.py	2008-02-13 15:58:18 UTC (rev 83798)
@@ -292,6 +292,19 @@
     def undoInfo(self, first, last, spec):
         return self.rpc.call('undoInfo', first, last, spec)
 
+    def iterator_start(self, start, stop):
+        return self.rpc.call('iterator_start', start, stop)
+
+    def iterator_next(self, iid):
+        return self.rpc.call('iterator_next', iid)
+
+    def iterator_record_start(self, tid):
+        return self.rpc.call('iterator_record_start', tid)
+
+    def iterator_record_next(self, iid):
+        return self.rpc.call('iterator_record_next', iid)
+
+
 class ExtensionMethodWrapper:
     def __init__(self, rpc, name):
         self.rpc = rpc

Modified: ZODB/branches/gocept-iteration/src/ZEO/StorageServer.py
===================================================================
--- ZODB/branches/gocept-iteration/src/ZEO/StorageServer.py	2008-02-13 15:58:03 UTC (rev 83797)
+++ ZODB/branches/gocept-iteration/src/ZEO/StorageServer.py	2008-02-13 15:58:18 UTC (rev 83798)
@@ -29,6 +29,7 @@
 import threading
 import time
 import warnings
+import itertools
 
 import transaction
 
@@ -53,7 +54,6 @@
 
 logger = logging.getLogger('ZEO.StorageServer')
 
-
 # TODO:  This used to say "ZSS", which is now implied in the logger name.
 # Can this be either set to str(os.getpid()) (if that makes sense) or removed?
 _label = "" # default label used for logging.
@@ -110,6 +110,8 @@
         self._extensions = {}
         for func in self.extensions:
             self._extensions[func.func_name] = None
+        self._iterators = {}
+        self._iterator_ids = itertools.count()
 
     def finish_auth(self, authenticated):
         if not self.auth_realm:
@@ -683,6 +685,51 @@
 
     abortVersion = commitVersion
 
+    # IStorageIteration support
+
+    def iterator_start(self, start, stop):
+        iid = self._iterator_ids.next()
+        self._iterators[iid] = self.storage.iterator(start, stop)
+        return iid
+
+    def iterator_next(self, iid):
+        iterator = self._iterators[iid]
+        try:
+            info = iterator.next()
+        except StopIteration:
+            del self._iterators[iid]
+            item = None
+        else:
+            item = (info.tid,
+                    info.status,
+                    info.user,
+                    info.description,
+                    info.extension)
+        return item
+
+    def iterator_record_start(self, tid):
+        iid = self._iterator_ids.next()
+        txn_infos = list(self.storage.iterator(tid, tid))
+        assert len(txn_infos) == 1
+        self._iterators[iid] = iter(txn_infos[0])
+        return iid
+
+    def iterator_record_next(self, iid):
+        iterator = self._iterators[iid]
+        try:
+            info = iterator.next()
+        except StopIteration:
+            del self._iterators[iid]
+            item = None
+        else:
+            item = (info.oid,
+                    info.tid,
+                    info.data,
+                    info.version,
+                    info.data_txn)
+        return item
+
+
 class StorageServerDB:
 
     def __init__(self, server, storage_id):

Modified: ZODB/branches/gocept-iteration/src/ZEO/tests/testZEO.py
===================================================================
--- ZODB/branches/gocept-iteration/src/ZEO/tests/testZEO.py	2008-02-13 15:58:03 UTC (rev 83797)
+++ ZODB/branches/gocept-iteration/src/ZEO/tests/testZEO.py	2008-02-13 15:58:18 UTC (rev 83798)
@@ -56,8 +56,8 @@
 import ZEO.StorageServer
 
 logger = logging.getLogger('ZEO.tests.testZEO')
+logging.getLogger().addHandler(logging.StreamHandler())
 
-
 class DummyDB:
     def invalidate(self, *args):
         pass

Modified: ZODB/branches/gocept-iteration/src/ZODB/DemoStorage.py
===================================================================
--- ZODB/branches/gocept-iteration/src/ZODB/DemoStorage.py	2008-02-13 15:58:03 UTC (rev 83797)
+++ ZODB/branches/gocept-iteration/src/ZODB/DemoStorage.py	2008-02-13 15:58:18 UTC (rev 83798)
@@ -81,14 +81,14 @@
 """
 
 import base64, time
+import ZODB.BaseStorage
 from ZODB import POSException
 from ZODB.utils import z64, oid_repr
-from ZODB.BaseStorage import BaseStorage
 from persistent.TimeStamp import TimeStamp
 from cPickle import loads
 from BTrees import OOBTree
 
-class DemoStorage(BaseStorage):
+class DemoStorage(ZODB.BaseStorage.BaseStorage):
     """Demo storage
 
     Demo storages provide useful storages for writing tests because
@@ -106,7 +106,7 @@
     
 
     def __init__(self, name='Demo Storage', base=None, quota=None):
-        BaseStorage.__init__(self, name, base)
+        ZODB.BaseStorage.BaseStorage.__init__(self, name, base)
 
         # We use a BTree because the items are sorted!
         self._data = OOBTree.OOBTree()
@@ -133,7 +133,7 @@
     # by the base storage, leading to a variety of "impossible" problems.
     def new_oid(self):
         if self._base is None:
-            return BaseStorage.new_oid(self)
+            return ZODB.BaseStorage.BaseStorage.new_oid(self)
         else:
             return self._base.new_oid()
 
@@ -569,3 +569,35 @@
     def close(self):
         if self._base is not None:
             self._base.close()
+
+    def iterator(self, start, stop):
+        for tid, (packed, user, description, extension, records) \
+                in self._data.items():
+            if tid < start:
+                continue
+            if tid > stop:
+                break
+            if packed:
+                status = 'p'
+            else:
+                status = ' '
+            yield TransactionRecord(
+                tid, status, user, description, extension, records)
+
+
+class TransactionRecord(ZODB.BaseStorage.TransactionRecord):
+
+    def __init__(self, tid, status, user, description, extension, records):
+        super(TransactionRecord, self).__init__(
+            tid, status, user, description, extension)
+        self._records = records
+
+    def __iter__(self):
+        for oid, pre, vdata, data, tid in self._records:
+            if vdata is None:
+                version = ''
+            else:
+                version, data = vdata
+            prev = pre[-1] # pre is supposed to be the previous data record,
+                           # which has its tid as its last element
+            yield ZODB.BaseStorage.DataRecord(oid, tid, data, version, prev)

Modified: ZODB/branches/gocept-iteration/src/ZODB/interfaces.py
===================================================================
--- ZODB/branches/gocept-iteration/src/ZODB/interfaces.py	2008-02-13 15:58:03 UTC (rev 83797)
+++ ZODB/branches/gocept-iteration/src/ZODB/interfaces.py	2008-02-13 15:58:18 UTC (rev 83798)
@@ -780,8 +780,12 @@
     """
 
     oid = Attribute("The object id")
+    tid = Attribute("The transaction id")
     data = Attribute("The data record")
+    version = Attribute("The version id")
+    data_txn = Attribute("The previous transaction id")
 
+
 class IStorageTransactionInformation(Interface):
     """Provide information about a storage transaction
     """

Modified: ZODB/branches/gocept-iteration/src/ZODB/tests/PackableStorage.py
===================================================================
--- ZODB/branches/gocept-iteration/src/ZODB/tests/PackableStorage.py	2008-02-13 15:58:03 UTC (rev 83797)
+++ ZODB/branches/gocept-iteration/src/ZODB/tests/PackableStorage.py	2008-02-13 15:58:18 UTC (rev 83798)
@@ -309,8 +309,11 @@
         for txn in it:
             for data in txn:
                 pass
-        it.close()
+        # XXX see bug #191573
+        if hasattr(it, "close"):
+            it.close()
 
+
 class PackableUndoStorage(PackableStorageBase):
 
     def checkPackAllRevisions(self):



More information about the Checkins mailing list