SVN: ZODB/trunk/src/ - Conflict errors didn't invalidate ZEO cache entries.

Jim Fulton <[email protected]>
Newsgroups gmane.comp.python.zope.zodb.cvs
Message-ID <20100712184559.07C89941DF__27620.0198954486$1278960372$gmane$org@cvs.zope.org>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.