[Zodb-checkins] CVS: ZODB3/ZEO - ClientCache.py:1.30
Guido van Rossum
guido@python.org
Wed, 28 Aug 2002 14:58:36 -0400
Update of /cvs-repository/ZODB3/ZEO
In directory cvs.zope.org:/tmp/cvs-serv24742
Modified Files:
ClientCache.py
Log Message:
Log an info message whenever a broken record is detected.
Log cache flips and non-trivial read_index statistics (at info level).
Move RCS info into docstring.
Add XXX TO DO comment at top.
Whitespace normalization.
=== ZODB3/ZEO/ClientCache.py 1.29 => 1.30 ===
--- ZODB3/ZEO/ClientCache.py:1.29 Wed Aug 28 11:48:25 2002
+++ ZODB3/ZEO/ClientCache.py Wed Aug 28 14:58:35 2002
@@ -2,15 +2,22 @@
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
-#
+#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
-#
+#
##############################################################################
+
+# XXX TO DO
+# use two indices rather than the sign bit of the index??????
+# add a shared routine to read + verify a record???
+# redesign header to include vdlen???
+# rewrite the cache using a different algorithm???
+
"""Implement a client cache
The cache is managed as two files.
@@ -90,15 +97,16 @@
If var is not writable, then temporary files are used for
file 0 and file 1.
+$Id$
"""
-__version__ = "$Revision$"[11:-2]
-
import os
import tempfile
from struct import pack, unpack
from thread import allocate_lock
+from ZODB.utils import U64
+
import zLOG
from ZEO.ICache import ICache
@@ -186,7 +194,7 @@
# This may be called more than once (by the cache verification code).
self._acquire()
try:
- self._index=index={}
+ self._index = index = {}
self._get = index.get
serial = {}
f = self._f
@@ -231,6 +239,7 @@
return
f.seek(p+8) # Switch from reading to writing
if version and h[15:19] != '\0\0\0\0':
+ # There's still relevant non-version data in the cache record
f.write('n')
else:
del self._index[oid]
@@ -255,6 +264,9 @@
else:
tlen = -1
if tlen <= 0 or vlen < 0 or dlen < 0 or vlen+dlen > tlen:
+ log("load: bad record for oid %16x "
+ "at position %d in cache file %d"
+ % (U64(oid), ap, p < 0))
del self._index[oid]
return None
@@ -345,6 +357,9 @@
else:
tlen = -1
if tlen <= 0 or vlen < 0 or dlen < 0 or vlen+dlen > tlen:
+ log("modifiedInVersion: bad record for oid %16x "
+ "at position %d in cache file %d"
+ % (U64(oid), ap, p < 0))
del self._index[oid]
return None
@@ -366,6 +381,7 @@
if self._pos + size > self._limit:
current = not self._current
self._current = current
+ log("flipping cache files. new current = %d" % current)
# Delete the half of the index that's no longer valid
index = self._index
for oid in index.keys():
@@ -434,33 +450,50 @@
seek = f.seek
read = f.read
pos = 4
+ count = 0
while 1:
f.seek(pos)
h = read(27)
+ if len(h) != 27:
+ # An empty read is expected, anything else is suspect
+ if h:
+ rilog("truncated header", pos, fileindex)
+ break
- if len(h)==27 and h[8] in 'vni':
+ if h[8] in 'vni':
tlen, vlen, dlen = unpack(">iHi", h[9:19])
else:
tlen = -1
if tlen <= 0 or vlen < 0 or dlen < 0 or vlen + dlen > tlen:
+ rilog("invalid header data", pos, fileindex)
break
oid = h[:8]
- if h[8]=='v' and vlen:
+ if h[8] == 'v' and vlen:
seek(dlen+vlen, 1)
vdlen = read(4)
if len(vdlen) != 4:
+ rilog("truncated record", pos, fileindex)
break
vdlen = unpack(">i", vdlen)[0]
if vlen+dlen+43+vdlen != tlen:
+ rilog("inconsistent lengths", pos, fileindex)
break
seek(vdlen, 1)
vs = read(8)
if read(4) != h[9:13]:
+ rilog("inconsistent tlen", pos, fileindex)
break
else:
+ if h[8] in 'vn' and vlen == 0:
+ if dlen+31 != tlen:
+ rilog("inconsistent nv lengths", pos, fileindex)
+ seek(dlen, 1)
+ if read(4) != h[9:13]:
+ rilog("inconsistent nv tlen", pos, fileindex)
+ break
vs = None
if h[8] in 'vn':
@@ -477,6 +510,7 @@
pos = pos + tlen
+ count += 1
f.seek(pos)
try:
@@ -484,4 +518,13 @@
except:
pass
+ if count:
+ log("read_index: cache file %d has %d records and %d bytes"
+ % (fileindex, count, pos))
+
return pos
+
+def rilog(msg, pos, fileindex):
+ # Helper to log messages from read_index
+ log("read_index: %s at position %d in cache file %d"
+ % (msg, pos, fileindex))