Commit 55df5d83 authored by Jim Fulton's avatar Jim Fulton

Updated the cache to not store version information.

Also updated the format to allow cache files larger than 4G in size.
parent a4534105
...@@ -572,11 +572,11 @@ class ClientStorage(object): ...@@ -572,11 +572,11 @@ class ClientStorage(object):
# it should set self._server. If it goes through full cache # it should set self._server. If it goes through full cache
# verification, then endVerify() should self._server. # verification, then endVerify() should self._server.
# if not self._cache: if not self._cache:
# log2("No verification necessary -- empty cache") log2("No verification necessary -- empty cache")
# self._server = server self._server = server
# self._ready.set() self._ready.set()
# return "full verification" return "full verification"
last_inval_tid = self._cache.getLastTid() last_inval_tid = self._cache.getLastTid()
...@@ -608,7 +608,7 @@ class ClientStorage(object): ...@@ -608,7 +608,7 @@ class ClientStorage(object):
# TODO: should batch these operations for efficiency; would need # TODO: should batch these operations for efficiency; would need
# to acquire lock ... # to acquire lock ...
for oid, tid, version in self._cache.contents(): for oid, tid in self._cache.contents():
server.verify(oid, tid) server.verify(oid, tid)
self._pending_server = server self._pending_server = server
server.endZeoVerify() server.endZeoVerify()
...@@ -719,7 +719,7 @@ class ClientStorage(object): ...@@ -719,7 +719,7 @@ class ClientStorage(object):
""" """
self._lock.acquire() # for atomic processing of invalidations self._lock.acquire() # for atomic processing of invalidations
try: try:
t = self._cache.load(oid, '') t = self._cache.load(oid)
if t: if t:
return t[:2] # XXX strip version return t[:2] # XXX strip version
finally: finally:
...@@ -742,7 +742,7 @@ class ClientStorage(object): ...@@ -742,7 +742,7 @@ class ClientStorage(object):
self._lock.acquire() # for atomic processing of invalidations self._lock.acquire() # for atomic processing of invalidations
try: try:
if self._load_status: if self._load_status:
self._cache.store(oid, '', tid, None, data) self._cache.store(oid, tid, None, data)
self._load_oid = None self._load_oid = None
finally: finally:
self._lock.release() self._lock.release()
...@@ -781,7 +781,7 @@ class ClientStorage(object): ...@@ -781,7 +781,7 @@ class ClientStorage(object):
return data, start, end return data, start, end
self._lock.acquire() self._lock.acquire()
try: try:
self._cache.store(oid, "", start, end, data) self._cache.store(oid, start, end, data)
finally: finally:
self._lock.release() self._lock.release()
...@@ -1112,13 +1112,13 @@ class ClientStorage(object): ...@@ -1112,13 +1112,13 @@ class ClientStorage(object):
return return
for oid, data in self._tbuf: for oid, data in self._tbuf:
self._cache.invalidate(oid, '', tid) self._cache.invalidate(oid, tid)
# If data is None, we just invalidate. # If data is None, we just invalidate.
if data is not None: if data is not None:
s = self._seriald[oid] s = self._seriald[oid]
if s != ResolvedSerial: if s != ResolvedSerial:
assert s == tid, (s, tid) assert s == tid, (s, tid)
self._cache.store(oid, '', s, None, data) self._cache.store(oid, s, None, data)
if self.fshelper is not None: if self.fshelper is not None:
...@@ -1195,7 +1195,7 @@ class ClientStorage(object): ...@@ -1195,7 +1195,7 @@ class ClientStorage(object):
for oid in oids: for oid in oids:
if oid == self._load_oid: if oid == self._load_oid:
self._load_status = 0 self._load_status = 0
self._cache.invalidate(oid, '', tid) self._cache.invalidate(oid, tid)
if self._db is not None: if self._db is not None:
self._db.invalidate(tid, oids) self._db.invalidate(tid, oids)
......
This diff is collapsed.
This diff is collapsed.
...@@ -85,86 +85,67 @@ class CacheTests(unittest.TestCase): ...@@ -85,86 +85,67 @@ class CacheTests(unittest.TestCase):
self.assertEqual(self.cache.getLastTid(), None) self.assertEqual(self.cache.getLastTid(), None)
self.cache.setLastTid(n2) self.cache.setLastTid(n2)
self.assertEqual(self.cache.getLastTid(), n2) self.assertEqual(self.cache.getLastTid(), n2)
self.cache.invalidate(None, "", n1) self.cache.invalidate(None, n1)
self.assertEqual(self.cache.getLastTid(), n2) self.assertEqual(self.cache.getLastTid(), n2)
self.cache.invalidate(None, "", n3) self.cache.invalidate(None, n3)
self.assertEqual(self.cache.getLastTid(), n3) self.assertEqual(self.cache.getLastTid(), n3)
self.assertRaises(ValueError, self.cache.setLastTid, n2) self.assertRaises(ValueError, self.cache.setLastTid, n2)
def testLoad(self): def testLoad(self):
data1 = "data for n1" data1 = "data for n1"
self.assertEqual(self.cache.load(n1, ""), None) self.assertEqual(self.cache.load(n1), None)
self.cache.store(n1, "", n3, None, data1) self.cache.store(n1, n3, None, data1)
self.assertEqual(self.cache.load(n1, ""), (data1, n3, "")) self.assertEqual(self.cache.load(n1), (data1, n3))
# The cache doesn't know whether version exists, because it
# only has non-version data.
self.assertEqual(self.cache.modifiedInVersion(n1), None)
def testInvalidate(self): def testInvalidate(self):
data1 = "data for n1" data1 = "data for n1"
self.cache.store(n1, "", n3, None, data1) self.cache.store(n1, n3, None, data1)
self.cache.invalidate(n1, "", n4) self.cache.invalidate(n1, n4)
self.cache.invalidate(n2, "", n2) self.cache.invalidate(n2, n2)
self.assertEqual(self.cache.load(n1, ""), None) self.assertEqual(self.cache.load(n1), None)
self.assertEqual(self.cache.loadBefore(n1, n4), self.assertEqual(self.cache.loadBefore(n1, n4), (data1, n3, n4))
(data1, n3, n4))
def testVersion(self):
data1 = "data for n1"
data1v = "data for n1 in version"
self.cache.store(n1, "version", n3, None, data1v)
self.assertEqual(self.cache.load(n1, ""), None)
self.assertEqual(self.cache.load(n1, "version"),
(data1v, n3, "version"))
self.assertEqual(self.cache.load(n1, "random"), None)
self.assertEqual(self.cache.modifiedInVersion(n1), "version")
self.cache.invalidate(n1, "version", n4)
self.assertEqual(self.cache.load(n1, "version"), None)
def testNonCurrent(self): def testNonCurrent(self):
data1 = "data for n1" data1 = "data for n1"
data2 = "data for n2" data2 = "data for n2"
self.cache.store(n1, "", n4, None, data1) self.cache.store(n1, n4, None, data1)
self.cache.store(n1, "", n2, n3, data2) self.cache.store(n1, n2, n3, data2)
# can't say anything about state before n2 # can't say anything about state before n2
self.assertEqual(self.cache.loadBefore(n1, n2), None) self.assertEqual(self.cache.loadBefore(n1, n2), None)
# n3 is the upper bound of non-current record n2 # n3 is the upper bound of non-current record n2
self.assertEqual(self.cache.loadBefore(n1, n3), (data2, n2, n3)) self.assertEqual(self.cache.loadBefore(n1, n3), (data2, n2, n3))
# no data for between n2 and n3 # no data for between n2 and n3
self.assertEqual(self.cache.loadBefore(n1, n4), None) self.assertEqual(self.cache.loadBefore(n1, n4), None)
self.cache.invalidate(n1, "", n5) self.cache.invalidate(n1, n5)
self.assertEqual(self.cache.loadBefore(n1, n5), (data1, n4, n5)) self.assertEqual(self.cache.loadBefore(n1, n5), (data1, n4, n5))
self.assertEqual(self.cache.loadBefore(n2, n4), None) self.assertEqual(self.cache.loadBefore(n2, n4), None)
def testException(self): def testException(self):
self.cache.store(n1, n2, None, "data")
self.assertRaises(ValueError, self.assertRaises(ValueError,
self.cache.store, self.cache.store,
n1, "version", n2, n3, "data") n1, n3, None, "data")
self.cache.store(n1, "", n2, None, "data")
self.assertRaises(ValueError,
self.cache.store,
n1, "", n3, None, "data")
def testEviction(self): def testEviction(self):
# Manually override the current maxsize # Manually override the current maxsize
maxsize = self.cache.size = self.cache.fc.maxsize = 3395 # 1245 maxsize = self.cache.size = self.cache.fc.maxsize = 3295 # 1245
self.cache.fc = ZEO.cache.FileCache(3395, None, self.cache) self.cache.fc = ZEO.cache.FileCache(3295, None, self.cache)
# Trivial test of eviction code. Doesn't test non-current # Trivial test of eviction code. Doesn't test non-current
# eviction. # eviction.
data = ["z" * i for i in range(100)] data = ["z" * i for i in range(100)]
for i in range(50): for i in range(50):
n = p64(i) n = p64(i)
self.cache.store(n, "", n, None, data[i]) self.cache.store(n, n, None, data[i])
self.assertEquals(len(self.cache), i + 1) self.assertEquals(len(self.cache), i + 1)
# The cache now uses 1225 bytes. The next insert # The cache now uses 1225 bytes. The next insert
# should delete some objects. # should delete some objects.
n = p64(50) n = p64(50)
self.cache.store(n, "", n, None, data[51]) self.cache.store(n, n, None, data[51])
self.assert_(len(self.cache) < 51) self.assert_(len(self.cache) < 51)
# TODO: Need to make sure eviction of non-current data # TODO: Need to make sure eviction of non-current data
# and of version data are handled correctly. # are handled correctly.
def _run_fuzzing(self): def _run_fuzzing(self):
current_tid = 1 current_tid = 1
...@@ -183,13 +164,13 @@ class CacheTests(unittest.TestCase): ...@@ -183,13 +164,13 @@ class CacheTests(unittest.TestCase):
current_oid += 1 current_oid += 1
key = (oid(current_oid), tid(current_tid)) key = (oid(current_oid), tid(current_tid))
object = ZEO.cache.Object( object = ZEO.cache.Object(
key=key, version='', data='*'*random.randint(1,60*1024), key=key, data='*'*random.randint(1,60*1024),
start_tid=tid(current_tid), end_tid=None) start_tid=tid(current_tid), end_tid=None)
assert key not in objects assert key not in objects
log(key, len(object.data), current_tid) log(key, len(object.data), current_tid)
cache.add(object) cache.add(object)
if (object.size + ZEO.cache.OBJECT_HEADER_SIZE > if (object.size + ZEO.cache.OBJECT_HEADER_SIZE >
cache.maxsize - ZEO.cache.ZEC3_HEADER_SIZE): cache.maxsize - ZEO.cache.ZEC4_HEADER_SIZE):
assert key not in cache assert key not in cache
else: else:
objects[key] = object objects[key] = object
...@@ -237,10 +218,9 @@ class CacheTests(unittest.TestCase): ...@@ -237,10 +218,9 @@ class CacheTests(unittest.TestCase):
raise raise
def testSerialization(self): def testSerialization(self):
self.cache.store(n1, "", n2, None, "data for n1") self.cache.store(n1, n2, None, "data for n1")
self.cache.store(n2, "version", n2, None, "version data for n2") self.cache.store(n3, n3, n4, "non-current data for n3")
self.cache.store(n3, "", n3, n4, "non-current data for n3") self.cache.store(n3, n4, n5, "more non-current data for n3")
self.cache.store(n3, "", n4, n5, "more non-current data for n3")
path = tempfile.mktemp() path = tempfile.mktemp()
# Copy data from self.cache into path, reaching into the cache # Copy data from self.cache into path, reaching into the cache
...@@ -258,7 +238,6 @@ class CacheTests(unittest.TestCase): ...@@ -258,7 +238,6 @@ class CacheTests(unittest.TestCase):
eq = self.assertEqual eq = self.assertEqual
eq(copy.getLastTid(), self.cache.getLastTid()) eq(copy.getLastTid(), self.cache.getLastTid())
eq(len(copy), len(self.cache)) eq(len(copy), len(self.cache))
eq(copy.version, self.cache.version)
eq(copy.current, self.cache.current) eq(copy.current, self.cache.current)
eq(copy.noncurrent, self.cache.noncurrent) eq(copy.noncurrent, self.cache.noncurrent)
......
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