[Zodb-checkins] CVS: ZODB3/ZEO - cache.py:1.1.2.10

Jeremy Hylton cvs-admin at zope.org
Sat Nov 22 00:11:19 EST 2003


Update of /cvs-repository/ZODB3/ZEO
In directory cvs.zope.org:/tmp/cvs-serv28257

Modified Files:
      Tag: ZODB3-mvcc-2-branch
	cache.py 
Log Message:
Remove old debugging code.


=== ZODB3/ZEO/cache.py 1.1.2.9 => 1.1.2.10 ===
--- ZODB3/ZEO/cache.py:1.1.2.9	Wed Nov 19 22:13:18 2003
+++ ZODB3/ZEO/cache.py	Sat Nov 22 00:11:19 2003
@@ -181,8 +181,13 @@
         tid = None
         if version:
             p = self.version.get(oid)
-            if p is not None and p[0] == version:
+            if p is None:
+                return None
+            elif p[0] == version:
                 tid = p[1]
+            # Otherwise, we know the cache has version data but not
+            # for the requested version.  Thus, we know it is safe
+            # to return the non-version data from the cache.
         if tid is None:
             tid = self.current.get(oid)
         if tid is None:
@@ -192,7 +197,7 @@
         if o is None:
             return None
         self._trace(0x22, oid, version, o.start_tid, o.end_tid, len(o.data))
-        return o.data, o.serialno, tid
+        return o.data, o.serialno, tid, o.version
 
     ##
     # Return a non-current revision of oid that was current before tid.
@@ -251,6 +256,14 @@
     # @exception ValueError tried to store non-current version data
 
     def store(self, oid, version, serial, start_tid, end_tid, data):
+        # It's hard for the client to avoid storing the same object
+        # more than once.  One case is whether the client requests
+        # version data that doesn't exist.  It checks the cache for
+        # the requested version, doesn't find it, then asks the server
+        # for that data.  The server returns the non-version data,
+        # which may already by in the cache.
+        if (oid, start_tid) in self.dll:
+            return
         o = Object((oid, start_tid), version, serial, data, start_tid, end_tid,
                    self)
         if version:
@@ -267,7 +280,8 @@
                 _cur_start = self.current.get(oid)
                 if _cur_start:
                     if _cur_start != start_tid:
-                        raise ValueError("already have current data for oid")
+                        raise ValueError(
+                            "already have current data for oid")
                     else:
                         return
                 self.current[oid] = start_tid
@@ -292,15 +306,19 @@
     def invalidate(self, oid, version, tid):
         if tid > self.tid:
             self.tid = tid
-        if version:
-            if oid in self.version:
-                self._trace(0x1A, oid, version, tid)
-                del self.version[oid]
-            return
         if oid in self.version:
-            # If the non-version data changed, the version is gone.
-            # XXX Do we need a cache trace code for this?
-            del self.version[oid]
+            self._trace(0x1A, oid, version, tid)
+            dllversion, dlltid = self.version[oid]
+            assert not version or version == dllversion, (version, dllversion)
+            # remove() will call unlink() to delete from self.version
+            self.dll.remove((oid, dlltid))
+            # And continue on, we must also remove any non-version data
+            # from the cache.  This is a bit of a failure of the current
+            # cache consistency approach as the new tid of the version
+            # data gets confused with the old tid of the non-version data.
+            # I could sort this out, but it seems simpler to punt and
+            # have the cache invalidation too much for versions.
+            
         if oid not in self.current:
             self._trace(0x10, oid, version, tid)
             return
@@ -332,7 +350,22 @@
         # XXX May need to materialize list instead of iterating,
         # depends on whether the caller may change the cache.
         for o in self.dll:
-            yield o.key[0], o.version, o.serialno
+            yield o.key[0], o.key[1], o.version, o.serialno
+
+    def dump(self):
+        from ZODB.utils import oid_repr
+        print "cache size", len(self)
+        L = list(self.contents())
+        L.sort()
+        for oid, tid, version, serialno in L:
+            print oid_repr(oid), oid_repr(tid), repr(version), oid_repr(serialno)
+        print "dll contents"
+        L = list(self.dll)
+        L.sort(lambda x,y:cmp(x.key, y.key))
+        for x in L:
+            end_tid = x.end_tid or z64
+            print oid_repr(x.key[0]), oid_repr(x.key[1]), oid_repr(end_tid)
+        print
 
     def _evicted(self, o):
         # Called by Object o to signal its eviction
@@ -572,10 +605,12 @@
         self._n_adds = self._n_added_bytes = 0
         self._n_evicts = self._n_evicted_bytes = 0
         self._n_accesses = 0
+        self._n_removes = self._n_removed_bytes = 0
 
     def getStats(self):
         return (self._n_adds, self._n_added_bytes,
                 self._n_evicts, self._n_evicted_bytes,
+                self._n_removes, self._n_removed_bytes,
                 self._n_accesses,
                )
 
@@ -585,6 +620,9 @@
     def __iter__(self):
         return self.key2object.itervalues()
 
+    def __contains__(self, key):
+        return key in self.key2object
+
     # Unlink object from the circular list, taking care not to lose
     # track of the current object.  Always call this instead of
     # invoking obj.unlink() directly.
@@ -638,14 +676,22 @@
         self._change_worth(c, (c.worth + 1) >> 1)
         self.currentobj = c._next
 
-    def access(self, oid):
+    def access(self, key):
         self._n_accesses += 1
         self._tick()
-        obj = self.key2object.get(oid)
+        obj = self.key2object.get(key)
         if obj is None:
             return None
         self._change_worth(obj, obj.worth | 0x80)
         return obj
+
+    def remove(self, key):
+        obj = self.key2object.get(key)
+        if obj is None:
+            return None
+        self._n_removes += 1
+        self._n_removed_bytes += obj.msize
+        self._removeobj(obj)
         
     # Evict objects of least worth first, until at least nbytes bytes
     # have been freed.
@@ -656,11 +702,11 @@
                     return
                 obj = s.pop()
                 nbytes -= obj.msize
-                self._evictobj(obj)
+                self._n_evicts += 1
+                self._n_evicted_bytes += obj.msize
+                self._removeobj(obj)
             
-    def _evictobj(self, obj):
-        self._n_evicts += 1
-        self._n_evicted_bytes += obj.msize
+    def _removeobj(self, obj):
         self.currentsize -= obj.msize
         self.worthsets[obj.worth].discard(obj)
         del self.key2object[obj.key]




More information about the Zodb-checkins mailing list