Commit 5ba506e7 authored by Jim Fulton's avatar Jim Fulton

Fixed a bug handling ZEO4 invalidations during cache verification

ZEO4 servers can send invalidations out of order with
``getInvalidations`` results, presumably because ``getInvalidations``
didn't get the commit lock.  ZEO4 clients worked around this (maybe
not directly) by queuing invalidations during cache verification.
ZEO5 servers don't send invalidations out of order with
``getInvalidations`` calls and the ZEO5 client didn't need an
invalidation queue, except they do need one to work correctly with
ZEO4 servers. :/
parent c7a96bae
...@@ -313,6 +313,12 @@ class Client(object): ...@@ -313,6 +313,12 @@ class Client(object):
self.protocols = () self.protocols = ()
self.disconnected(None) self.disconnected(None)
# Work around odd behavior of ZEO4 server. It may send
# invalidations for transactions later than the result of
# getInvalidations. While we support ZEO 4 servers, we'll
# need to keep an invalidation queue. :(
self.verify_invalidation_queue = []
def new_addrs(self, addrs): def new_addrs(self, addrs):
self.addrs = addrs self.addrs = addrs
if self.trying_to_connect(): if self.trying_to_connect():
...@@ -409,6 +415,8 @@ class Client(object): ...@@ -409,6 +415,8 @@ class Client(object):
@future_generator @future_generator
def verify(self, server_tid): def verify(self, server_tid):
self.verify_invalidation_queue = [] # See comment in init :(
protocol = self.protocol protocol = self.protocol
if server_tid is None: if server_tid is None:
server_tid = yield protocol.fut('lastTransaction') server_tid = yield protocol.fut('lastTransaction')
...@@ -465,6 +473,12 @@ class Client(object): ...@@ -465,6 +473,12 @@ class Client(object):
self.cache.setLastTid(server_tid) self.cache.setLastTid(server_tid)
self.ready = True self.ready = True
# Gaaaa, ZEO 4 work around. See comment in __init__. :(
for tid, oids in self.verify_invalidation_queue:
if tid > server_tid:
self.invalidateTransaction(tid, oids)
self.verify_invalidation_queue = []
try: try:
info = yield protocol.fut('get_info') info = yield protocol.fut('get_info')
except Exception as exc: except Exception as exc:
...@@ -597,6 +611,8 @@ class Client(object): ...@@ -597,6 +611,8 @@ class Client(object):
self.cache.invalidate(oid, tid) self.cache.invalidate(oid, tid)
self.client.invalidateTransaction(tid, oids) self.client.invalidateTransaction(tid, oids)
self.cache.setLastTid(tid) self.cache.setLastTid(tid)
else:
self.verify_invalidation_queue.append((tid, oids))
def serialnos(self, serials): def serialnos(self, serials):
# Method called by ZEO4 storage servers. # Method called by ZEO4 storage servers.
......
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