[ZODB-Dev] savepoint bug

Jeremy Hylton jeremy at alum.mit.edu
Fri Jun 25 07:42:01 EDT 2004


On Thu, 2004-06-24 at 19:02, Edward Moy wrote:
> I'm still using a version of ZODB that was top of tree several months 
> ago, which has the savepoint/rollback changes I posted.
> 
> In using it, I've found a bug that has a strange, non-local behavior 
> that is way beyond my understanding of ZODB.  Here is a snippet of the 
> code that reproduces the bug:

The detailed example really helps, but I still don't have a full
explanation.  Here's what I came up with after staring at it for a few
minutes.

The XXX line is a great clue.  If it is executed, it will mark obj as
modified in the first savepoint.  Otherwise, I assume, False/False is
the initial state of the object and it is unmodified when you create
rb6.  If it is modified when you create rb6, then savepoint() will store
a revision of the object in the temporary storage.  I don't see how to
move from that to an obvious explanation of the error.

I'm looking at the ZODB4 code, which I assume is basically the same as
your patched version.  Assuming that's the case, what seems to be
missing is code the invalidates cached objects that were read from
rolled-back state and never modified.  When rollback is called, the
connection invalidates all modified objects; the definition of rollback
is to toss change made since the savepoint was created.  But I don't see
code that invalidates unmodified objects that were modified by an
intermediate savepoint.

If a modified object is saved by a savepoint() and then subsequently
read back into memory, it will read the state as written by the
savepoint.  If you then call rollback, the object you read needs to be
invalidated so that subsequent refererences will get the pre-savepoint
state.

This isn't trivial to implement, because the connection doesn't keep
track of which objects were read.  It has a cache with every object, but
you don't want to invalidate the entire cache -- just the one reads from
a savepoint that is being rolled back.  I think it could be implemented
by passing some information from savepoint to savepoint.  The Rollback
objects would need to be connected.  The Connection could save the
previous Rollback and pass a reference to the next one created by
savepoint(); then the Rollback objects would be connected in a chain. 
When a rollback is called, it would need to invalidate all the objects
modified by all of the rollbacks in its chain.

That sounds like a problem and its solution, although I don't know if it
addresses your example or if it's merely a related problem.  Or maybe
it's just too early and I've missed something ;-).

Jeremy




More information about the ZODB-Dev mailing list