[Zodb-checkins] CVS: ZODB3/ZEO - ClientCache.py:1.36.2.1 stats.py:1.16.6.1

Guido van Rossum guido@python.org
Wed, 18 Sep 2002 14:51:43 -0400


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

Modified Files:
      Tag: zeo_alt_cache_branch
	ClientCache.py stats.py 
Log Message:
Cache policy improvement:
When load() finds a hit in the non-current file, copy it to the
current file (except when this would cause a cache flip).

It is hoped that this improves the cache performance.

=== ZODB3/ZEO/ClientCache.py 1.36 => 1.36.2.1 ===
--- ZODB3/ZEO/ClientCache.py:1.36	Fri Sep 13 16:59:28 2002
+++ ZODB3/ZEO/ClientCache.py	Wed Sep 18 14:51:42 2002
@@ -303,6 +303,8 @@
                 if dlen:
                     data = read(dlen)
                     self._trace(0x2A, oid, version, h[19:], dlen)
+                    if (p < 0) != self._current:
+                        self._copytocurrent(ap, tlen, dlen, vlen, h, data)
                     return data, h[19:]
                 else:
                     self._trace(0x26, oid, version)
@@ -317,6 +319,9 @@
                     seek(ap+27)
                     data = read(dlen)
                     self._trace(0x2C, oid, version, h[19:], dlen)
+                    if (p < 0) != self._current:
+                        self._copytocurrent(ap, tlen, dlen, vlen, h,
+                                            data, vheader)
                     return data, h[19:]
                 else:
                     self._trace(0x28, oid, version)
@@ -326,10 +331,71 @@
             vdata = read(vdlen)
             vserial = read(8)
             self._trace(0x2E, oid, version, vserial, vdlen)
+            if (p < 0) != self._current:
+                self._copytocurrent(ap, tlen, dlen, vlen, h,
+                                    None, vheader, vdata, vserial)
             return vdata, vserial
         finally:
             self._release()
 
+    def _copytocurrent(self, pos, tlen, dlen, vlen, header,
+                       data=None, vheader=None, vdata=None, vserial=None):
+        """Copy a cache hit from the non-current file to the current file.
+
+        Arguments are the file position in the non-current file,
+        record length, data length, version string length, header, and
+        optionally parts of the record that have already been read.
+        """
+        if self._pos + tlen > self._limit:
+            return # Don't let this cause a cache flip
+        assert len(header) == 27
+        if header[8] == 'n':
+            # Rewrite the header to drop the version data.
+            # This shortens the record.
+            tlen = 31 + dlen
+            vlen = 0
+            # (oid:8, status:1, tlen:4, vlen:2, dlen:4, serial:8)
+            header = header[:9] + pack(">IHI", tlen, vlen, dlen) + header[-8:]
+        else:
+            assert header[8] == 'v'
+        f = self._f[not self._current]
+        if data is None:
+            f.seek(pos+27)
+            data = f.read(dlen)
+            if len(data) != dlen:
+                return
+        l = [header, data]
+        if vlen:
+            assert vheader is not None
+            l.append(vheader)
+            assert (vdata is None) == (vserial is None)
+            if vdata is None:
+                vdlen = unpack(">I", vheader[-4:])[0]
+                f.seek(pos+27+dlen+vlen+4)
+                vdata = f.read(vdlen)
+                if len(vdata) != vdlen:
+                    return
+                vserial = f.read(8)
+                if len(vserial) != 8:
+                    return
+            l.append(vdata)
+            l.append(vserial)
+        else:
+            assert None is vheader is vdata is vserial
+        l.append(header[9:13]) # copy of tlen
+        g = self._f[self._current]
+        g.seek(self._pos)
+        g.writelines(l)
+        assert g.tell() == self._pos + tlen
+        oid = header[:8]
+        if self._current:
+            self._index[oid] = - self._pos
+        else:
+            self._index[oid] = self._pos
+        self._pos += tlen
+        self._trace(0x6A, header[:8], vlen and vheader[:-4] or '',
+                    vlen and vserial or header[-8:], dlen)
+
     def update(self, oid, serial, version, data):
         self._acquire()
         try:
@@ -476,7 +542,7 @@
         l.append(stlen)
         f = self._f[self._current]
         f.seek(self._pos)
-        f.write("".join(l))
+        f.writelines(l) # write all list elements
 
         if self._current:
             self._index[oid] = - self._pos


=== ZODB3/ZEO/stats.py 1.16 => 1.16.6.1 ===
--- ZODB3/ZEO/stats.py:1.16	Mon Sep  9 23:13:04 2002
+++ ZODB3/ZEO/stats.py	Wed Sep 18 14:51:43 2002
@@ -364,6 +364,8 @@
     0x5A: "store (non-version data present)",
     0x5C: "store (only version data present)",
 
+    0x6A: "_copytocurrent",
+
     0x70: "checkSize (cache flip)",
     }