[Zodb-checkins] SVN: ZODB/trunk/src/ZEO/ - A ZEO cache internal data structure can get out of sync
Jim Fulton
jim at zope.com
Fri Sep 5 14:37:03 EDT 2008
Log message for revision 90890:
- A ZEO cache internal data structure can get out of sync
with the data in a way that prevents data from being loaded into the
cache. We don't yet know why, but added an exception handler to
prevent this error from being fatal.
Changed:
U ZODB/trunk/src/ZEO/cache.py
U ZODB/trunk/src/ZEO/tests/test_cache.py
-=-
Modified: ZODB/trunk/src/ZEO/cache.py
===================================================================
--- ZODB/trunk/src/ZEO/cache.py 2008-09-05 18:34:04 UTC (rev 90889)
+++ ZODB/trunk/src/ZEO/cache.py 2008-09-05 18:37:03 UTC (rev 90890)
@@ -292,11 +292,15 @@
noncurrent_for_oid[u64(tid)] = ofs
def _del_noncurrent(self, oid, tid):
- noncurrent_for_oid = self.noncurrent[u64(oid)]
- del noncurrent_for_oid[u64(tid)]
- if not noncurrent_for_oid:
- del self.noncurrent[u64(oid)]
+ try:
+ noncurrent_for_oid = self.noncurrent[u64(oid)]
+ del noncurrent_for_oid[u64(tid)]
+ if not noncurrent_for_oid:
+ del self.noncurrent[u64(oid)]
+ except KeyError:
+ logger.error("Couldn't find non-current %r", (oid, tid))
+
def clearStats(self):
self._n_adds = self._n_added_bytes = 0
self._n_evicts = self._n_evicted_bytes = 0
Modified: ZODB/trunk/src/ZEO/tests/test_cache.py
===================================================================
--- ZODB/trunk/src/ZEO/tests/test_cache.py 2008-09-05 18:34:04 UTC (rev 90889)
+++ ZODB/trunk/src/ZEO/tests/test_cache.py 2008-09-05 18:37:03 UTC (rev 90890)
@@ -313,6 +313,37 @@
>>> cache.close()
""",
+
+ broken_non_current =
+ r"""
+
+ In production, we saw a situation where an _del_noncurrent raused
+ a key error when trying to free space, causing the cache to become
+ unusable. I can't see why this would occur, but added a logging
+ exception handler so, in the future, we'll still see cases in the
+ log, but will ignore the error and keep going.
+
+ >>> import ZEO.cache, ZODB.utils, logging, sys
+ >>> logger = logging.getLogger('ZEO.cache')
+ >>> logger.setLevel(logging.ERROR)
+ >>> handler = logging.StreamHandler(sys.stdout)
+ >>> logger.addHandler(handler)
+ >>> cache = ZEO.cache.ClientCache('cache', 1000)
+ >>> cache.store(ZODB.utils.p64(1), ZODB.utils.p64(1), None, '0')
+ >>> cache.invalidate(ZODB.utils.p64(1), ZODB.utils.p64(2))
+ >>> cache._del_noncurrent(ZODB.utils.p64(1), ZODB.utils.p64(2))
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Couldn't find non-current
+ ('\x00\x00\x00\x00\x00\x00\x00\x01', '\x00\x00\x00\x00\x00\x00\x00\x02')
+ >>> cache._del_noncurrent(ZODB.utils.p64(1), ZODB.utils.p64(1))
+ >>> cache._del_noncurrent(ZODB.utils.p64(1), ZODB.utils.p64(1)) #
+ ... # doctest: +NORMALIZE_WHITESPACE
+ Couldn't find non-current
+ ('\x00\x00\x00\x00\x00\x00\x00\x01', '\x00\x00\x00\x00\x00\x00\x00\x01')
+
+ >>> logger.setLevel(logging.NOTSET)
+ >>> logger.removeHandler(handler)
+ """
)
def test_suite():
More information about the Zodb-checkins
mailing list