[Zodb-checkins] SVN: ZODB/trunk/src/ - Fixed bug in ClientCache
that occurred with objects larger than the total
Thomas Lotze
tl at gocept.com
Tue Jan 15 07:45:36 EST 2008
Log message for revision 82895:
- Fixed bug in ClientCache that occurred with objects larger than the total
cache size.
Changed:
U ZODB/trunk/src/CHANGES.txt
U ZODB/trunk/src/ZEO/cache.py
U ZODB/trunk/src/ZEO/tests/filecache.txt
U ZODB/trunk/src/ZEO/tests/test_cache.py
-=-
Modified: ZODB/trunk/src/CHANGES.txt
===================================================================
--- ZODB/trunk/src/CHANGES.txt 2008-01-15 12:31:00 UTC (rev 82894)
+++ ZODB/trunk/src/CHANGES.txt 2008-01-15 12:45:36 UTC (rev 82895)
@@ -10,7 +10,7 @@
- Versions are no-longer supported.
-- ZEO cache files can be larger than 4G. Note that lder ZEO cache
+- ZEO cache files can be larger than 4G. Note that older ZEO cache
files are not supported.
- Document conflict resolution (see ZODB/ConflictResolution.txt).
@@ -62,3 +62,6 @@
deal with garbage files
- Fixed bug in which MVCC would not work for blobs.
+
+- Fixed bug in ClientCache that occurred with objects larger than the total
+ cache size.
Modified: ZODB/trunk/src/ZEO/cache.py
===================================================================
--- ZODB/trunk/src/ZEO/cache.py 2008-01-15 12:31:00 UTC (rev 82894)
+++ ZODB/trunk/src/ZEO/cache.py 2008-01-15 12:45:36 UTC (rev 82895)
@@ -234,6 +234,8 @@
"already have current data for oid")
else:
return
+ if not self.fc.add(o):
+ return # too large
self.current[oid] = start_tid
self._trace(0x52, oid, start_tid, dlen=len(data))
else:
@@ -241,9 +243,10 @@
p = start_tid, end_tid
if p in L:
return # duplicate store
+ if not self.fc.add(o):
+ return # too large
bisect.insort_left(L, p)
self._trace(0x54, oid, start_tid, end_tid, dlen=len(data))
- self.fc.add(o)
##
# Remove all knowledge of noncurrent revisions of oid, both in
@@ -883,7 +886,8 @@
##
# Add Object object to the cache. This may evict existing objects, to
# make room (and almost certainly will, in steady state once the cache
- # is first full). The object must not already be in the cache.
+ # is first full). The object must not already be in the cache. If the
+ # object is too large for the cache, False is returned, otherwise True.
def add(self, object):
size = OBJECT_HEADER_SIZE + object.size
# A number of cache simulation experiments all concluded that the
@@ -891,7 +895,7 @@
# objects simply weren't cached. For now, we ignore the request
# only if the entire cache file is too small to hold the object.
if size > self.maxsize - ZEC4_HEADER_SIZE:
- return
+ return False
assert object.key not in self.key2entry
assert len(object.key[0]) == 8
@@ -902,6 +906,7 @@
available = self._makeroom(size)
self._writeobj(object, available)
+ return True
##
# Return Object for key, or None if not in cache.
Modified: ZODB/trunk/src/ZEO/tests/filecache.txt
===================================================================
--- ZODB/trunk/src/ZEO/tests/filecache.txt 2008-01-15 12:31:00 UTC (rev 82894)
+++ ZODB/trunk/src/ZEO/tests/filecache.txt 2008-01-15 12:45:36 UTC (rev 82895)
@@ -52,6 +52,7 @@
We can add it to the cache:
>>> fc.add(obj1_1)
+ True
And now it's in the cache:
@@ -146,6 +147,7 @@
>>> obj2_1 = Object(key=(oid(2), tid(1)), data='******',
... start_tid=tid(1), end_tid=None)
>>> fc.add(obj2_1)
+ True
The new block fits exactly in the remaining 47 bytes (41 bytes header + 6
bytes payload) so the beginning of the data is the same except for the last 47
@@ -171,6 +173,7 @@
>>> obj3_1 = Object(key=(oid(3), tid(1)), data='@'*100,
... start_tid=tid(1), end_tid=None)
>>> fc.add(obj3_1)
+ True
>>> hexprint(fc.f)
00000000 5a 45 43 34 00 00 00 00 00 00 00 00 61 00 00 00 |ZEC4........a...|
@@ -192,6 +195,7 @@
>>> obj4_1 = Object(key=(oid(4), tid(1)), data='~~~~~',
... start_tid=tid(1), end_tid=None)
>>> fc.add(obj4_1)
+ True
>>> hexprint(fc.f)
00000000 5a 45 43 34 00 00 00 00 00 00 00 00 61 00 00 00 |ZEC4........a...|
@@ -213,6 +217,7 @@
>>> obj4_1 = Object(key=(oid(5), tid(1)), data='^'*98,
... start_tid=tid(1), end_tid=None)
>>> fc.add(obj4_1)
+ True
>>> hexprint(fc.f)
00000000 5a 45 43 34 00 00 00 00 00 00 00 00 61 00 00 00 |ZEC4........a...|
@@ -239,6 +244,7 @@
>>> obj4_1 = Object(key=(oid(6), tid(1)), data='+'*95,
... start_tid=tid(1), end_tid=None)
>>> fc.add(obj4_1)
+ True
>>> hexprint(fc.f)
00000000 5a 45 43 34 00 00 00 00 00 00 00 00 61 00 00 00 |ZEC4........a...|
@@ -264,6 +270,7 @@
>>> obj4_1 = Object(key=(oid(7), tid(1)), data='-'*89,
... start_tid=tid(1), end_tid=None)
>>> fc.add(obj4_1)
+ True
>>> hexprint(fc.f)
00000000 5a 45 43 34 00 00 00 00 00 00 00 00 61 00 00 00 |ZEC4........a...|
@@ -287,6 +294,7 @@
>>> obj4_1 = Object(key=(oid(8), tid(1)), data='='*80,
... start_tid=tid(1), end_tid=None)
>>> fc.add(obj4_1)
+ True
>>> hexprint(fc.f)
00000000 5a 45 43 34 00 00 00 00 00 00 00 00 61 00 00 00 |ZEC4........a...|
Modified: ZODB/trunk/src/ZEO/tests/test_cache.py
===================================================================
--- ZODB/trunk/src/ZEO/tests/test_cache.py 2008-01-15 12:31:00 UTC (rev 82894)
+++ ZODB/trunk/src/ZEO/tests/test_cache.py 2008-01-15 12:45:36 UTC (rev 82895)
@@ -241,7 +241,37 @@
eq(copy.current, self.cache.current)
eq(copy.noncurrent, self.cache.noncurrent)
+ def testCurrentObjectLargerThanCache(self):
+ if self.cache.path:
+ os.remove(self.cache.path)
+ self.cache = ZEO.cache.ClientCache(size=50)
+ self.cache.open()
+ # We store an object that is a bit larger than the cache can handle.
+ self.cache.store(n1, n2, None, "x"*64)
+ # We can see that it was not stored.
+ self.assertEquals(None, self.cache.load(n1))
+ # If an object cannot be stored in the cache, it must not be
+ # recorded as current.
+ self.assert_(n1 not in self.cache.current)
+ # Regression test: invalidation must still work.
+ self.cache.invalidate(n1, n2)
+
+ def testOldObjectLargerThanCache(self):
+ if self.cache.path:
+ os.remove(self.cache.path)
+ self.cache = ZEO.cache.ClientCache(size=50)
+ self.cache.open()
+
+ # We store an object that is a bit larger than the cache can handle.
+ self.cache.store(n1, n2, n3, "x"*64)
+ # We can see that it was not stored.
+ self.assertEquals(None, self.cache.load(n1))
+ # If an object cannot be stored in the cache, it must not be
+ # recorded as non-current.
+ self.assert_((n2, n3) not in self.cache.noncurrent[n1])
+
+
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(CacheTests))
More information about the Zodb-checkins
mailing list