[Zodb-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 Zodb-checkins
mailing list