Commit 1397ada8 authored by Jim Fulton's avatar Jim Fulton

Bug fixed

---------

- Database connections didn't invalidate cache entries when conflict
  errors were raised in response to checkCurrentSerialInTransaction
  errors. Normally, this shouldn't be a problem, since there should be
  pending invalidations for these oids which will cause the object to
  be invalidated. There have been issues with ZEO persistent cache
  management that have caused out of date data to remain in the cache.
  (It's possible that the last of these were addressed in the
  3.10.0b5.) Invalidating read data when there is a conflict error
  provides some extra insurance.
parent ae178fe5
...@@ -2,6 +2,23 @@ ...@@ -2,6 +2,23 @@
Change History Change History
================ ================
3.10.0b6 (2010-09-??)
=====================
Bugs fixed
----------
- Database connections didn't invalidate cache entries when conflict
errors were raised in response to checkCurrentSerialInTransaction
errors. Normally, this shouldn't be a problem, since there should be
pending invalidations for these oids which will cause the object to
be invalidated. There have been issues with ZEO persistent cache
management that have caused out of date data to remain in the cache.
(It's possible that the last of these were addressed in the
3.10.0b5.) Invalidating read data when there is a conflict error
provides some extra insurance.
3.10.0b5 (2010-09-02) 3.10.0b5 (2010-09-02)
===================== =====================
......
...@@ -557,8 +557,12 @@ class Connection(ExportImport, object): ...@@ -557,8 +557,12 @@ class Connection(ExportImport, object):
self._commit(transaction) self._commit(transaction)
for oid, serial in self._readCurrent.iteritems(): for oid, serial in self._readCurrent.iteritems():
self._storage.checkCurrentSerialInTransaction( try:
oid, serial, transaction) self._storage.checkCurrentSerialInTransaction(
oid, serial, transaction)
except ConflictError:
self._cache.invalidate(oid)
raise
def _commit(self, transaction): def _commit(self, transaction):
"""Commit changes to an object""" """Commit changes to an object"""
...@@ -754,7 +758,13 @@ class Connection(ExportImport, object): ...@@ -754,7 +758,13 @@ class Connection(ExportImport, object):
vote = self._storage.tpc_vote vote = self._storage.tpc_vote
except AttributeError: except AttributeError:
return return
s = vote(transaction) try:
s = vote(transaction)
except ReadConflictError, v:
if v.oid:
self._cache.invalidate(v.oid)
raise
if s: if s:
for oid, serial in s: for oid, serial in s:
self._handle_serial(oid, serial) self._handle_serial(oid, serial)
......
...@@ -680,6 +680,7 @@ Or if the object it was called on is modified: ...@@ -680,6 +680,7 @@ Or if the object it was called on is modified:
If the storage raises a conflict error, it'll be propigated: If the storage raises a conflict error, it'll be propigated:
>>> _ = str(conn.root.a) # do read
>>> bad.add(conn.root.a._p_oid) >>> bad.add(conn.root.a._p_oid)
>>> conn.readCurrent(conn.root.a) >>> conn.readCurrent(conn.root.a)
>>> conn.root.b.x += 1 >>> conn.root.b.x += 1
...@@ -690,6 +691,10 @@ If the storage raises a conflict error, it'll be propigated: ...@@ -690,6 +691,10 @@ If the storage raises a conflict error, it'll be propigated:
>>> transaction.abort() >>> transaction.abort()
The conflict error will cause the affected object to be invalidated:
>>> conn.root.a._p_changed
The storage may raise it later: The storage may raise it later:
>>> def checkCurrentSerialInTransaction(oid, serial, trans): >>> def checkCurrentSerialInTransaction(oid, serial, trans):
...@@ -709,6 +714,7 @@ The storage may raise it later: ...@@ -709,6 +714,7 @@ The storage may raise it later:
It will still be propigated: It will still be propigated:
>>> _ = str(conn.root.a) # do read
>>> conn.readCurrent(conn.root.a) >>> conn.readCurrent(conn.root.a)
>>> conn.root.b.x = +1 >>> conn.root.b.x = +1
>>> transaction.commit() >>> transaction.commit()
...@@ -718,6 +724,10 @@ It will still be propigated: ...@@ -718,6 +724,10 @@ It will still be propigated:
>>> transaction.abort() >>> transaction.abort()
The conflict error will cause the affected object to be invalidated:
>>> conn.root.a._p_changed
Read checks don't leak accross transactions: Read checks don't leak accross transactions:
>>> conn.readCurrent(conn.root.a) >>> conn.readCurrent(conn.root.a)
......
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