Commit 20d25c7b authored by Jim Fulton's avatar Jim Fulton

- Conflict errors didn't invalidate ZEO cache entries.

parent d3280409
...@@ -45,6 +45,9 @@ Bugs fixed ...@@ -45,6 +45,9 @@ Bugs fixed
invalidation transaction ids matched the cached transaction ids invalidation transaction ids matched the cached transaction ids
should have been ignored. should have been ignored.
- Conflict errors didn't invalidate ZEO cache entries.
3.10.0b1 (2010-05-18) 3.10.0b1 (2010-05-18)
===================== =====================
......
...@@ -917,6 +917,7 @@ class ClientStorage(object): ...@@ -917,6 +917,7 @@ class ClientStorage(object):
del self._serials[:l] del self._serials[:l]
for oid, s in r: for oid, s in r:
if isinstance(s, Exception): if isinstance(s, Exception):
self._cache.invalidate(oid, None)
raise s raise s
self._seriald[oid] = s self._seriald[oid] = s
return r return r
......
...@@ -24,7 +24,7 @@ from ZODB.tests import StorageTestBase, BasicStorage, \ ...@@ -24,7 +24,7 @@ from ZODB.tests import StorageTestBase, BasicStorage, \
MTStorage, ReadOnlyStorage, IteratorStorage, RecoveryStorage MTStorage, ReadOnlyStorage, IteratorStorage, RecoveryStorage
from ZODB.tests.MinPO import MinPO from ZODB.tests.MinPO import MinPO
from ZODB.tests.StorageTestBase import zodb_unpickle from ZODB.tests.StorageTestBase import zodb_unpickle
from ZODB.utils import p64, u64
from zope.testing import renormalizing from zope.testing import renormalizing
import doctest import doctest
...@@ -1377,6 +1377,77 @@ You can specify the client label via a configuration file as well: ...@@ -1377,6 +1377,77 @@ You can specify the client label via a configuration file as well:
""" """
def invalidate_client_cache_entry_on_server_commit_error():
"""
When the serials returned during commit includes an error, typically a
conflict error, invalidate the cache entry. This is important when
the cache is messed up.
>>> addr, _ = start_server()
>>> conn1 = ZEO.connection(addr)
>>> conn1.root.x = conn1.root().__class__()
>>> transaction.commit()
>>> conn1.root.x
{}
>>> cs = ZEO.ClientStorage.ClientStorage(addr, client='cache')
>>> conn2 = ZODB.connection(cs)
>>> conn2.root.x
{}
>>> conn2.close()
>>> cs.close()
>>> conn1.root.x['x'] = 1
>>> transaction.commit()
>>> conn1.root.x
{'x': 1}
Now, let's screw up the cache by making it have a last tid that is later than
the root serial.
>>> import ZEO.cache
>>> cache = ZEO.cache.ClientCache('cache-1.zec')
>>> cache.setLastTid(p64(u64(conn1.root.x._p_serial)+1))
>>> cache.close()
We'll also update the server so that it's last tid is newer than the cache's:
>>> conn1.root.y = 1
>>> transaction.commit()
>>> conn1.root.y = 2
>>> transaction.commit()
Now, if we reopen the client storage, we'll get the wrong root:
>>> cs = ZEO.ClientStorage.ClientStorage(addr, client='cache')
>>> conn2 = ZODB.connection(cs)
>>> conn2.root.x
{}
And, we'll get a conflict error if we try to modify it:
>>> conn2.root.x['y'] = 1
>>> transaction.commit() # doctest: +ELLIPSIS
Traceback (most recent call last):
...
ConflictError: ...
But, if we abort, we'll get up to date data and we'll see the changes.
>>> transaction.abort()
>>> conn2.root.x
{'x': 1}
>>> conn2.root.x['y'] = 1
>>> transaction.commit()
>>> sorted(conn2.root.x.items())
[('x', 1), ('y', 1)]
>>> cs.close()
>>> conn1.close()
"""
if sys.version_info >= (2, 6): if sys.version_info >= (2, 6):
import multiprocessing import multiprocessing
......
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