Commit ec370c85 authored by Jim Fulton's avatar Jim Fulton

Fixed: the ZEO cache loadBefore method failed to utilize current data.

parent 50692664
...@@ -494,7 +494,7 @@ class ClientCache(object): ...@@ -494,7 +494,7 @@ class ClientCache(object):
# @defreturn 3-tuple: (string, string, string) # @defreturn 3-tuple: (string, string, string)
@locked @locked
def load(self, oid): def load(self, oid, before_tid=None):
ofs = self.current.get(oid) ofs = self.current.get(oid)
if ofs is None: if ofs is None:
self._trace(0x20, oid) self._trace(0x20, oid)
...@@ -509,6 +509,9 @@ class ClientCache(object): ...@@ -509,6 +509,9 @@ class ClientCache(object):
assert end_tid == z64, (ofs, self.f.tell(), oid, tid, end_tid) assert end_tid == z64, (ofs, self.f.tell(), oid, tid, end_tid)
assert lver == 0, "Versions aren't supported" assert lver == 0, "Versions aren't supported"
if before_tid and tid >= before_tid:
return None
data = read(ldata) data = read(ldata)
assert len(data) == ldata, (ofs, self.f.tell(), oid, len(data), ldata) assert len(data) == ldata, (ofs, self.f.tell(), oid, len(data), ldata)
...@@ -550,13 +553,22 @@ class ClientCache(object): ...@@ -550,13 +553,22 @@ class ClientCache(object):
def loadBefore(self, oid, before_tid): def loadBefore(self, oid, before_tid):
noncurrent_for_oid = self.noncurrent.get(u64(oid)) noncurrent_for_oid = self.noncurrent.get(u64(oid))
if noncurrent_for_oid is None: if noncurrent_for_oid is None:
self._trace(0x24, oid, "", before_tid) result = self.load(oid, before_tid)
return None if result:
return result[0], result[1], None
else:
self._trace(0x24, oid, "", before_tid)
return result
items = noncurrent_for_oid.items(None, u64(before_tid)-1) items = noncurrent_for_oid.items(None, u64(before_tid)-1)
if not items: if not items:
self._trace(0x24, oid, "", before_tid) result = self.load(oid, before_tid)
return None if result:
return result[0], result[1], None
else:
self._trace(0x24, oid, "", before_tid)
return result
tid, ofs = items[-1] tid, ofs = items[-1]
self.f.seek(ofs) self.f.seek(ofs)
...@@ -577,8 +589,12 @@ class ClientCache(object): ...@@ -577,8 +589,12 @@ class ClientCache(object):
assert read(8) == oid, (ofs, self.f.tell(), oid) assert read(8) == oid, (ofs, self.f.tell(), oid)
if end_tid < before_tid: if end_tid < before_tid:
self._trace(0x24, oid, "", before_tid) result = self.load(oid, before_tid)
return None if result:
return result[0], result[1], None
else:
self._trace(0x24, oid, "", before_tid)
return result
self._n_accesses += 1 self._n_accesses += 1
self._trace(0x26, oid, "", saved_tid) self._trace(0x26, oid, "", saved_tid)
......
...@@ -314,7 +314,9 @@ class CacheTests(ZODB.tests.util.TestCase): ...@@ -314,7 +314,9 @@ class CacheTests(ZODB.tests.util.TestCase):
# We use large-2 for the same reason we used small-1 above. # We use large-2 for the same reason we used small-1 above.
expected_len = large-2 expected_len = large-2
self.assertEquals(len(cache), expected_len) self.assertEquals(len(cache), expected_len)
expected_oids = set(list(range(11, 50))+list(range(106, 110))+list(range(200, 305))) expected_oids = set(list(range(11, 50)) +
list(range(106, 110)) +
list(range(200, 305)))
self.assertEquals(set(u64(oid) for (oid, tid) in cache.contents()), self.assertEquals(set(u64(oid) for (oid, tid) in cache.contents()),
expected_oids) expected_oids)
...@@ -336,6 +338,21 @@ class CacheTests(ZODB.tests.util.TestCase): ...@@ -336,6 +338,21 @@ class CacheTests(ZODB.tests.util.TestCase):
self.cache.setLastTid(p64(3)) self.cache.setLastTid(p64(3))
self.cache.setLastTid(p64(4)) self.cache.setLastTid(p64(4))
def test_loadBefore_doesnt_miss_current(self):
# Make sure that loadBefore get's current data if there
# isn't non-current data
cache = self.cache
oid = n1
cache.store(oid, n1, None, b'first')
self.assertEqual(cache.loadBefore(oid, n1), None)
self.assertEqual(cache.loadBefore(oid, n2), (b'first', n1, None))
self.cache.invalidate(oid, n2)
cache.store(oid, n2, None, b'second')
self.assertEqual(cache.loadBefore(oid, n1), None)
self.assertEqual(cache.loadBefore(oid, n2), (b'first', n1, n2))
self.assertEqual(cache.loadBefore(oid, n3), (b'second', n2, None))
def kill_does_not_cause_cache_corruption(): def kill_does_not_cause_cache_corruption():
r""" r"""
......
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