Commit a895e3f9 authored by Kirill Smelkov's avatar Kirill Smelkov

Add support to retrieve raw extension data to ZEO

See https://github.com/zopefoundation/ZODB/pull/183 for context.
parent d8438a30
......@@ -371,14 +371,20 @@ class ClientStorage(ZODB.ConflictResolution.ConflictResolvingStorage):
self._info.update(info)
for iface in (
ifacev = (
ZODB.interfaces.IStorageRestoreable,
ZODB.interfaces.IStorageIteration,
ZODB.interfaces.IStorageUndoable,
ZODB.interfaces.IStorageCurrentRecordIteration,
ZODB.interfaces.IBlobStorage,
ZODB.interfaces.IExternalGC,
):
)
# if ZODB is recent enough to have IStorageIterationRaw - use it too
IStorageIterationRaw = getattr(ZODB.interfaces, 'IStorageIterationRaw', None)
if IStorageIterationRaw is not None:
ifacev += (IStorageIterationRaw,)
for iface in ifacev:
if (iface.__module__, iface.__name__) in self._info.get(
'interfaces', ()):
zope.interface.alsoProvides(self, iface)
......@@ -978,7 +984,11 @@ class ClientStorage(ZODB.ConflictResolution.ConflictResolvingStorage):
if self._db is not None:
self._db.invalidate(tid, oids)
# IStorageIteration
# IStorageIteration + IStorageIterationRaw
def supportsTransactionInformationRaw(self):
"""Storage API: return whether iterated transactions are provided with raw metadata"""
return self._info.get('supportsTransactionInformationRaw', False)
def iterator(self, start=None, stop=None):
"""Return an IStorageTransactionInformation iterator."""
......@@ -1068,18 +1078,13 @@ class TransactionIterator(object):
class ClientStorageTransactionInformation(ZODB.BaseStorage.TransactionRecord):
def __init__(self, storage, txiter, tid, status, user, description,
extension):
def __init__(self, storage, txiter, *args):
self._storage = storage
self._txiter = txiter
self._completed = False
self._riid = None
self.tid = tid
self.status = status
self.user = user
self.description = description
self.extension = extension
super(ClientStorageTransactionInformation, self).__init__(*args)
def __iter__(self):
riid = self._storage._call('iterator_record_start',
......
......@@ -230,6 +230,10 @@ class ZEOStorage(object):
supportsUndo = (getattr(storage, 'supportsUndo', lambda : False)()
and self.connection.protocol_version[1:] >= b'310')
supportsTransactionInformationRaw = \
getattr(storage, 'supportsTransactionInformationRaw',
lambda : False)()
# Communicate the backend storage interfaces to the client
storage_provides = zope.interface.providedBy(storage)
interfaces = []
......@@ -240,6 +244,7 @@ class ZEOStorage(object):
'size': storage.getSize(),
'name': storage.getName(),
'supportsUndo': supportsUndo,
'supportsTransactionInformationRaw': supportsTransactionInformationRaw,
'supports_record_iternext': hasattr(self, 'record_iternext'),
'interfaces': tuple(interfaces),
}
......@@ -571,6 +576,10 @@ class ZEOStorage(object):
info.user,
info.description,
info.extension)
# propagate IStorageTransactionInformationRaw if we have its data
raw_extension = getattr(info, "raw_extension", None)
if raw_extension is not None:
item += (raw_extension,)
# Keep a reference to the last iterator result to allow starting a
# record iterator off it.
self._txn_iterators_last[iid] = info
......
......@@ -719,6 +719,10 @@ class ZEOStorage(object):
info.user,
info.description,
info.extension)
# propagate IStorageTransactionInformationRaw if we have its data
raw_extension = getattr(info, "raw_extension", None)
if raw_extension is not None:
item += (raw_extension,)
# Keep a reference to the last iterator result to allow starting a
# record iterator off it.
self._txn_iterators_last[iid] = info
......
......@@ -173,6 +173,11 @@ class GenericTestBase(
)
self._storage.registerDB(DummyDB())
# here we trust ZEO to properly propagate
# supportsTransactionInformationRaw from original storage.
self.supportsTransactionInformationRaw = \
self._storage.supportsTransactionInformationRaw()
def getZEOConfig(self):
return forker.ZEOConfig(('127.0.0.1', 0))
......@@ -320,15 +325,22 @@ class FileStorageTests(FullGenericTests):
</filestorage>
"""
_expected_interfaces = (
('ZODB.interfaces', 'IStorageRestoreable'),
('ZODB.interfaces', 'IStorageIteration'),
('ZODB.interfaces', 'IStorageUndoable'),
('ZODB.interfaces', 'IStorageCurrentRecordIteration'),
('ZODB.interfaces', 'IExternalGC'),
('ZODB.interfaces', 'IStorage'),
('zope.interface', 'Interface'),
)
def setUp(self):
super(FileStorageTests, self).setUp()
self._expected_interfaces = set((
('ZODB.interfaces', 'IStorageRestoreable'),
('ZODB.interfaces', 'IStorageIteration'),
('ZODB.interfaces', 'IStorageUndoable'),
('ZODB.interfaces', 'IStorageCurrentRecordIteration'),
('ZODB.interfaces', 'IExternalGC'),
('ZODB.interfaces', 'IStorage'),
('zope.interface', 'Interface'),
))
if self.supportsTransactionInformationRaw:
self._expected_interfaces.add(
('ZODB.interfaces', 'IStorageIterationRaw'))
def checkInterfaceFromRemoteStorage(self):
# ClientStorage itself doesn't implement IStorageIteration, but the
......@@ -338,9 +350,17 @@ class FileStorageTests(FullGenericTests):
ZEO.ClientStorage.ClientStorage))
self.failUnless(ZODB.interfaces.IStorageIteration.providedBy(
self._storage))
# same for IStorageIterationRaw
IStorageIterationRaw = getattr(ZODB.interfaces, 'IStorageIterationRaw', None)
if IStorageIterationRaw is not None:
self.failIf(IStorageIterationRaw.implementedBy(
ZEO.ClientStorage.ClientStorage))
self.assertEqual(IStorageIterationRaw.providedBy(self._storage),
self.supportsTransactionInformationRaw)
# This is communicated using ClientStorage's _info object:
self.assertEquals(self._expected_interfaces,
self._storage._info['interfaces']
set(self._storage._info['interfaces'])
)
class FileStorageSSLTests(FileStorageTests):
......@@ -353,16 +373,12 @@ class FileStorageSSLTests(FileStorageTests):
class FileStorageHexTests(FileStorageTests):
_expected_interfaces = (
('ZODB.interfaces', 'IStorageRestoreable'),
('ZODB.interfaces', 'IStorageIteration'),
('ZODB.interfaces', 'IStorageUndoable'),
('ZODB.interfaces', 'IStorageCurrentRecordIteration'),
('ZODB.interfaces', 'IExternalGC'),
('ZODB.interfaces', 'IStorage'),
('ZODB.interfaces', 'IStorageWrapper'),
('zope.interface', 'Interface'),
)
def setUp(self):
super(FileStorageHexTests, self).setUp()
self._expected_interfaces.add(
('ZODB.interfaces', 'IStorageWrapper'))
def getConfig(self):
return """\
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment