From ec370c85daf5e2b63c056ad8b23b54142efb9b3c Mon Sep 17 00:00:00 2001 From: Jim Fulton Date: Mon, 6 Jun 2016 10:20:17 -0400 Subject: [PATCH] Fixed: the ZEO cache loadBefore method failed to utilize current data. --- src/ZEO/cache.py | 30 +++++++++++++++++++++++------- src/ZEO/tests/test_cache.py | 19 ++++++++++++++++++- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/ZEO/cache.py b/src/ZEO/cache.py index 0126dbdce..482a9a7b7 100644 --- a/src/ZEO/cache.py +++ b/src/ZEO/cache.py @@ -494,7 +494,7 @@ def getLastTid(self): # @defreturn 3-tuple: (string, string, string) @locked - def load(self, oid): + def load(self, oid, before_tid=None): ofs = self.current.get(oid) if ofs is None: self._trace(0x20, oid) @@ -509,6 +509,9 @@ def load(self, oid): assert end_tid == z64, (ofs, self.f.tell(), oid, tid, end_tid) assert lver == 0, "Versions aren't supported" + if before_tid and tid >= before_tid: + return None + data = read(ldata) assert len(data) == ldata, (ofs, self.f.tell(), oid, len(data), ldata) @@ -550,13 +553,22 @@ def load(self, oid): def loadBefore(self, oid, before_tid): noncurrent_for_oid = self.noncurrent.get(u64(oid)) if noncurrent_for_oid is None: - self._trace(0x24, oid, "", before_tid) - return None + result = self.load(oid, before_tid) + 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) if not items: - self._trace(0x24, oid, "", before_tid) - return None + result = self.load(oid, before_tid) + if result: + return result[0], result[1], None + else: + self._trace(0x24, oid, "", before_tid) + return result + tid, ofs = items[-1] self.f.seek(ofs) @@ -577,8 +589,12 @@ def loadBefore(self, oid, before_tid): assert read(8) == oid, (ofs, self.f.tell(), oid) if end_tid < before_tid: - self._trace(0x24, oid, "", before_tid) - return None + result = self.load(oid, before_tid) + if result: + return result[0], result[1], None + else: + self._trace(0x24, oid, "", before_tid) + return result self._n_accesses += 1 self._trace(0x26, oid, "", saved_tid) diff --git a/src/ZEO/tests/test_cache.py b/src/ZEO/tests/test_cache.py index bff388497..ca69c4210 100644 --- a/src/ZEO/tests/test_cache.py +++ b/src/ZEO/tests/test_cache.py @@ -314,7 +314,9 @@ def testChangingCacheSize(self): # We use large-2 for the same reason we used small-1 above. expected_len = large-2 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()), expected_oids) @@ -336,6 +338,21 @@ def testSetAnyLastTidOnEmptyCache(self): self.cache.setLastTid(p64(3)) 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(): r"""