Commit 911e8f5d authored by Jim Fulton's avatar Jim Fulton

Reverted the format used for ZEO client-cache files.

This means that cache files created by ZODB 3.8 can be read.
parent 8ddb46b2
# This file is empty even though this package contains scripts. The
# reason for that is that we don't want the scripts to be installed
# for Zope releases (which ZEO is part of). For standalone ZODB
# releases, these scripts are installed through
# ZODB/releases/ZODB3/PACKAGE.cfg and .../SETUP.cfg.
...@@ -79,7 +79,7 @@ logger = logging.getLogger("ZEO.cache") ...@@ -79,7 +79,7 @@ logger = logging.getLogger("ZEO.cache")
# file's magic number - ZEC3 - indicating zeo cache version 4. The # file's magic number - ZEC3 - indicating zeo cache version 4. The
# next eight bytes are the last transaction id. # next eight bytes are the last transaction id.
magic = "ZEC4" magic = "ZEC3"
ZEC_HEADER_SIZE = 12 ZEC_HEADER_SIZE = 12
# After the header, the file contains a contiguous sequence of blocks. All # After the header, the file contains a contiguous sequence of blocks. All
...@@ -90,7 +90,7 @@ ZEC_HEADER_SIZE = 12 ...@@ -90,7 +90,7 @@ ZEC_HEADER_SIZE = 12
# format total block size. # format total block size.
# #
# 'f' # 'f'
# Free. The block is free; the next 8 bytes are >Q format total # Free. The block is free; the next 4 bytes are >I format total
# block size. # block size.
# #
# '1', '2', '3', '4' # '1', '2', '3', '4'
...@@ -107,6 +107,7 @@ ZEC_HEADER_SIZE = 12 ...@@ -107,6 +107,7 @@ ZEC_HEADER_SIZE = 12
# 8 byte oid # 8 byte oid
# 8 byte start_tid # 8 byte start_tid
# 8 byte end_tid # 8 byte end_tid
# 2 byte version length must be 0
# 4 byte data size # 4 byte data size
# data # data
...@@ -203,7 +204,7 @@ class ClientCache(object): ...@@ -203,7 +204,7 @@ class ClientCache(object):
self.f.write(magic) self.f.write(magic)
self.f.write(z64) self.f.write(z64)
# and one free block. # and one free block.
self.f.write('f' + pack(">Q", self.maxsize - ZEC_HEADER_SIZE)) self.f.write('f' + pack(">I", self.maxsize - ZEC_HEADER_SIZE))
sync(self.f) sync(self.f)
# Statistics: _n_adds, _n_added_bytes, # Statistics: _n_adds, _n_added_bytes,
...@@ -260,18 +261,19 @@ class ClientCache(object): ...@@ -260,18 +261,19 @@ class ClientCache(object):
seek(ofs) seek(ofs)
status = read(1) status = read(1)
if status == 'a': if status == 'a':
size, oid, start_tid, end_tid = unpack(">I8s8s8s", read(28)) size, oid, start_tid, end_tid, lver = unpack(
">I8s8s8sH", read(30))
if end_tid == z64: if end_tid == z64:
assert oid not in current, (ofs, self.f.tell()) assert oid not in current, (ofs, self.f.tell())
current[oid] = ofs current[oid] = ofs
else: else:
assert start_tid < end_tid, (ofs, self.f.tell()) assert start_tid < end_tid, (ofs, self.f.tell())
self._set_noncurrent(oid, start_tid, ofs) self._set_noncurrent(oid, start_tid, ofs)
assert lver == 0, "Versions aren't supported"
l += 1 l += 1
elif status == 'f': elif status == 'f':
size, = unpack(">Q", read(8)) size, = unpack(">I", read(4))
elif status in '12345678': elif status in '1234':
size = int(status) size = int(status)
else: else:
raise ValueError("unknown status byte value %s in client " raise ValueError("unknown status byte value %s in client "
...@@ -362,9 +364,9 @@ class ClientCache(object): ...@@ -362,9 +364,9 @@ class ClientCache(object):
self._len -= 1 self._len -= 1
else: else:
if status == 'f': if status == 'f':
size = unpack(">Q", read(8))[0] size = unpack(">I", read(4))[0]
else: else:
assert status in '12345678' assert status in '1234'
size = int(status) size = int(status)
ofs += size ofs += size
nbytes -= size nbytes -= size
...@@ -414,9 +416,10 @@ class ClientCache(object): ...@@ -414,9 +416,10 @@ class ClientCache(object):
self.f.seek(ofs) self.f.seek(ofs)
read = self.f.read read = self.f.read
assert read(1) == 'a', (ofs, self.f.tell(), oid) assert read(1) == 'a', (ofs, self.f.tell(), oid)
size, saved_oid, tid, end_tid, ldata = unpack( size, saved_oid, tid, end_tid, lver, ldata = unpack(
">I8s8s8sI", read(32)) ">I8s8s8sHI", read(34))
assert saved_oid == oid, (ofs, self.f.tell(), oid, saved_oid) assert saved_oid == oid, (ofs, self.f.tell(), oid, saved_oid)
assert lver == 0, "Versions aren't supported"
data = read(ldata) data = read(ldata)
assert len(data) == ldata, (ofs, self.f.tell(), oid, len(data), ldata) assert len(data) == ldata, (ofs, self.f.tell(), oid, len(data), ldata)
...@@ -449,11 +452,12 @@ class ClientCache(object): ...@@ -449,11 +452,12 @@ class ClientCache(object):
self.f.seek(ofs) self.f.seek(ofs)
read = self.f.read read = self.f.read
assert read(1) == 'a', (ofs, self.f.tell(), oid, before_tid) assert read(1) == 'a', (ofs, self.f.tell(), oid, before_tid)
size, saved_oid, saved_tid, end_tid, ldata = unpack( size, saved_oid, saved_tid, end_tid, lver, ldata = unpack(
">I8s8s8sI", read(32)) ">I8s8s8sHI", read(34))
assert saved_oid == oid, (ofs, self.f.tell(), oid, saved_oid) assert saved_oid == oid, (ofs, self.f.tell(), oid, saved_oid)
assert saved_tid == p64(tid), (ofs, self.f.tell(), oid, saved_tid, tid) assert saved_tid == p64(tid), (ofs, self.f.tell(), oid, saved_tid, tid)
assert end_tid != z64, (ofs, self.f.tell(), oid) assert end_tid != z64, (ofs, self.f.tell(), oid)
assert lver == 0, "Versions aren't supported"
data = read(ldata) data = read(ldata)
assert len(data) == ldata, (ofs, self.f.tell()) assert len(data) == ldata, (ofs, self.f.tell())
assert read(8) == oid, (ofs, self.f.tell(), oid) assert read(8) == oid, (ofs, self.f.tell(), oid)
...@@ -496,7 +500,7 @@ class ClientCache(object): ...@@ -496,7 +500,7 @@ class ClientCache(object):
if noncurrent_for_oid and (u64(start_tid) in noncurrent_for_oid): if noncurrent_for_oid and (u64(start_tid) in noncurrent_for_oid):
return return
size = 41 + len(data) size = 43 + len(data)
# A number of cache simulation experiments all concluded that the # A number of cache simulation experiments all concluded that the
# 2nd-level ZEO cache got a much higher hit rate if "very large" # 2nd-level ZEO cache got a much higher hit rate if "very large"
...@@ -517,10 +521,10 @@ class ClientCache(object): ...@@ -517,10 +521,10 @@ class ClientCache(object):
# expensive -- it's all a contiguous write. # expensive -- it's all a contiguous write.
if excess == 0: if excess == 0:
extra = '' extra = ''
elif excess < 9: elif excess < 5:
extra = "012345678"[excess] extra = "01234"[excess]
else: else:
extra = 'f' + pack(">Q", excess) extra = 'f' + pack(">I", excess)
ofs = self.currentofs ofs = self.currentofs
seek(ofs) seek(ofs)
...@@ -529,10 +533,10 @@ class ClientCache(object): ...@@ -529,10 +533,10 @@ class ClientCache(object):
# Before writing data, we'll write a free block for the space freed. # Before writing data, we'll write a free block for the space freed.
# We'll come back with a last atomic write to rewrite the start of the # We'll come back with a last atomic write to rewrite the start of the
# allocated-block header. # allocated-block header.
write('f'+pack(">Q", nfreebytes)+'xxxx') write('f'+pack(">I", nfreebytes))
# Now write the rest of the allocation block header and object data. # Now write the rest of the allocation block header and object data.
write(pack(">8s8sI", start_tid, end_tid or z64, len(data))) write(pack(">8s8s8sHI", oid, start_tid, end_tid or z64, 0, len(data)))
write(data) write(data)
write(oid) write(oid)
write(extra) write(extra)
...@@ -540,7 +544,7 @@ class ClientCache(object): ...@@ -540,7 +544,7 @@ class ClientCache(object):
# Now, we'll go back and rewrite the beginning of the # Now, we'll go back and rewrite the beginning of the
# allocated block header. # allocated block header.
seek(ofs) seek(ofs)
write('a'+pack(">I8s", size, oid)) write('a'+pack(">I", size))
if end_tid: if end_tid:
self._set_noncurrent(oid, start_tid, ofs) self._set_noncurrent(oid, start_tid, ofs)
...@@ -597,7 +601,7 @@ class ClientCache(object): ...@@ -597,7 +601,7 @@ class ClientCache(object):
del self.current[oid] del self.current[oid]
if tid is None: if tid is None:
self.f.seek(ofs) self.f.seek(ofs)
self.f.write('f'+pack(">Q", size)) self.f.write('f'+pack(">I", size))
# 0x1E = invalidate (hit, discarding current or non-current) # 0x1E = invalidate (hit, discarding current or non-current)
self._trace(0x1E, oid, tid) self._trace(0x1E, oid, tid)
self._len -= 1 self._len -= 1
......
...@@ -121,7 +121,7 @@ class CacheTests(unittest.TestCase): ...@@ -121,7 +121,7 @@ class CacheTests(unittest.TestCase):
def testEviction(self): def testEviction(self):
# Manually override the current maxsize # Manually override the current maxsize
cache = ZEO.cache.ClientCache(None, 3295) cache = ZEO.cache.ClientCache(None, 3395)
# Trivial test of eviction code. Doesn't test non-current # Trivial test of eviction code. Doesn't test non-current
# eviction. # eviction.
......
BTrees
ZConfig
persistent
transaction
# referenced by ZODB.config and related tests
ZEO
zope.interface
zope.testing
# Extension information for zpkg.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment