[Zodb-checkins] CVS: ZODB3/ZEO - cache.py:1.1.2.4
Jeremy Hylton
cvs-admin at zope.org
Tue Nov 11 16:46:20 EST 2003
Update of /cvs-repository/ZODB3/ZEO
In directory cvs.zope.org:/tmp/cvs-serv5297/ZEO
Modified Files:
Tag: ZODB3-mvcc-2-branch
cache.py
Log Message:
Improvements to serialization code.
Store the last tid (self.tid) in the file.
Handle reading non-current data.
Implement contents() using a different strategy.
Fix Q -> 8s.
Change the DLL to return None instead of False for objects that aren't
in the cache.
=== ZODB3/ZEO/cache.py 1.1.2.3 => 1.1.2.4 ===
--- ZODB3/ZEO/cache.py:1.1.2.3 Mon Nov 10 17:42:54 2003
+++ ZODB3/ZEO/cache.py Tue Nov 11 16:45:49 2003
@@ -14,6 +14,7 @@
"""Example client cache that stores multiple revisions of an object."""
import bisect
+import os
import struct
from sets import Set
@@ -100,31 +101,43 @@
self.dll = Cache(size or 10**6)
def open(self):
- self._read()
+ if os.path.exists(self.path):
+ self._read()
def _read(self):
- f = open(self.path, "rb")
+ f = open(self.path, "a+b")
+ tid = f.read(8)
+ if tid == "\0" * 8:
+ self.tid = None
+ else:
+ self.tid = tid
while 1:
o = Object.fromFile(f, self)
if o is None:
break
+ oid = o.key[0]
if o.version:
- self.version[o.oid] = o.start_tid
+ self.version[oid] = o.start_tid
elif o.end_tid is None:
- self.current[o.oid] = o.start_tid
+ self.current[oid] = o.start_tid
else:
- # XXX recreate the internal cache data structures
- print "non-current cache data"
+ L = self.noncurrent.setdefault(oid, [])
+ bisect.insort_left(L, (o.start_tid, o.end_tid))
+ self.dll.add(o)
def close(self):
self._write()
def _write(self):
+ if self.path is None:
+ return
# XXX The cache needs a minimal header.
# magic cookie, format version no, configured size of cache
+ # last tid
f = open(self.path, "wb")
+ f.write(self.tid or "\0" * 8)
for o in self.dll:
- o.write(f)
+ o.serialize(f)
f.close()
##
@@ -160,6 +173,8 @@
if tid is None:
return None
o = self.dll.access((oid, tid))
+ if o is None:
+ return None
return o.data, o.serialno
##
@@ -250,31 +265,31 @@
cur_tid = self.current.pop(oid)
# XXX Want to fetch object without marking it as accessed
o = self.dll.access((oid, cur_tid))
+ if o is None:
+ return None
o.end_tid = tid
L = self.noncurrent.setdefault(oid, [])
bisect.insort_left(L, (cur_tid, tid))
##
- # An iterator yielding the current contents of the cache.
- # @defreturn iterator
- # @return oid, version, serial number triples
-
- def contents(self):
- # XXX
- for oid, (data, serial) in self.current.items():
- yield oid, "", serial
- for oid, (version, data, serial, start_tid) in self.version.items():
- yield oid, version, serial
-
- ##
# Return the number of object revisions in the cache.
def __len__(self):
n = len(self.current) + len(self.version)
if self.noncurrent:
- n += reduce(int.__add__, map(len, self.noncurrent))
+ n += sum(map(len, self.noncurrent))
return n
+ ##
+ # Generates over, version, serial triples for all objects in the
+ # cache. This generator is used by cache verification.
+
+ def contents(self):
+ # 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
+
def _evicted(self, o):
# Called by Object o to signal its eviction
oid, tid = o.key
@@ -376,22 +391,29 @@
DLLNode.unlink(self)
self.cache._evicted(self)
+ # The serialization format uses an end tid of "\0" * 8, the least
+ # 8-byte string, to represent None. It isn't possible for an
+ # end_tid to be 0, because it must always be strictly greater
+ # than the start_tid.
+
def serialize(self, f):
# Write standard form of Object to file, f.
- s = struct.pack(">QQQQhi", self.key[0], self.serialno,
- self.start_tid, self.end_tid, len(self.version),
- len(self.data))
+ s = struct.pack(">8s8s8s8shi", self.key[0], self.serialno,
+ self.start_tid, self.end_tid or "\0" * 8,
+ len(self.version), len(self.data))
f.write(s)
f.write(self.version)
f.write(self.data)
- f.write(struct.pack(">Q", s))
+ f.write(struct.pack(">8s", s))
def fromFile(cls, f, cache):
- fmt = ">QQQQhi"
+ fmt = ">8s8s8s8shi"
s = f.read(struct.calcsize(fmt))
if not s:
return None
oid, serialno, start_tid, end_tid, vlen, dlen = struct.unpack(fmt, s)
+ if end_tid == "\0" * 8:
+ end_tid = None
version = f.read(vlen)
if vlen != len(version):
raise ValueError("corrupted record, version")
@@ -399,7 +421,7 @@
if dlen != len(data):
raise ValueError("corrupted record, data")
s = f.read(8)
- if struct.pack(">Q", s) != oid:
+ if struct.pack(">8s", s) != oid:
raise ValueError("corrupted record, oid")
return cls((oid, start_tid), version, serialno, data,
start_tid, end_tid, cache)
@@ -535,7 +557,7 @@
self._tick()
obj = self.key2object.get(oid)
if obj is None:
- return False # XXX None?
+ return None
self._change_worth(obj, obj.worth | 0x80)
return obj
More information about the Zodb-checkins
mailing list