[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