[Zodb-checkins] SVN: ZODB/trunk/src/ - Conflict errors didn't invalidate ZEO cache entries.
Jim Fulton
jim at zope.com
Mon Jul 12 14:45:59 EDT 2010
Log message for revision 114650:
- Conflict errors didn't invalidate ZEO cache entries.
Changed:
U ZODB/trunk/src/CHANGES.txt
U ZODB/trunk/src/ZEO/ClientStorage.py
U ZODB/trunk/src/ZEO/tests/testZEO.py
-=-
Modified: ZODB/trunk/src/CHANGES.txt
===================================================================
--- ZODB/trunk/src/CHANGES.txt 2010-07-12 18:45:57 UTC (rev 114649)
+++ ZODB/trunk/src/CHANGES.txt 2010-07-12 18:45:58 UTC (rev 114650)
@@ -45,6 +45,9 @@
invalidation transaction ids matched the cached transaction ids
should have been ignored.
+- Conflict errors didn't invalidate ZEO cache entries.
+
+
3.10.0b1 (2010-05-18)
=====================
Modified: ZODB/trunk/src/ZEO/ClientStorage.py
===================================================================
--- ZODB/trunk/src/ZEO/ClientStorage.py 2010-07-12 18:45:57 UTC (rev 114649)
+++ ZODB/trunk/src/ZEO/ClientStorage.py 2010-07-12 18:45:58 UTC (rev 114650)
@@ -917,6 +917,7 @@
del self._serials[:l]
for oid, s in r:
if isinstance(s, Exception):
+ self._cache.invalidate(oid, None)
raise s
self._seriald[oid] = s
return r
Modified: ZODB/trunk/src/ZEO/tests/testZEO.py
===================================================================
--- ZODB/trunk/src/ZEO/tests/testZEO.py 2010-07-12 18:45:57 UTC (rev 114649)
+++ ZODB/trunk/src/ZEO/tests/testZEO.py 2010-07-12 18:45:58 UTC (rev 114650)
@@ -24,7 +24,7 @@
MTStorage, ReadOnlyStorage, IteratorStorage, RecoveryStorage
from ZODB.tests.MinPO import MinPO
from ZODB.tests.StorageTestBase import zodb_unpickle
-
+from ZODB.utils import p64, u64
from zope.testing import renormalizing
import doctest
@@ -1377,7 +1377,78 @@
"""
+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):
import multiprocessing
More information about the Zodb-checkins
mailing list