[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