[ZODB-Dev] Savepoints are invalidated once they are used
Tim Peters
tim at zope.com
Tue Jul 12 10:18:27 EDT 2005
[Jeremy Hylton]
> IIRC, the old implementation of savepoints kept a copy of the index at
> the time the savepoint was taken so that you could rollback to it
> multiple times. I don't think there's any way to avoid such a copy.
Right, and the current implementation did that too. The "surprise" was that
it wasn't enough. Sketch:
1. Modify object 0.
2. Make savepoint 1.
It makes a copy of the current index, say {0: 0}, and remembers
the TmpStore size, say 100.
3. Fiddle around.
4. Rollback to savepoint 1.
This sets the TmpStore index to the saved {0: 0}, and truncatss
TmpStore to size 100. So far so good -- or so it seems.
5. Modify object 0 again, and make savepoint 2.
This changes the TmpStore index to {0: 100}, makes of a copy of
{0: 100} in savepoint 2, and increases TmpStore size to 200. This
just did something horribly wrong too, although it's subtle.
6. Rollback to savepoint 1 again.
Because a copy of savepoint 1's index wasn't _also_ made in
step #4, the index savepoint 1 is holding onto mutated to
{0: 100} during step #5 (object sharing). This (#6) step
leaves TmpStore with (the mutated) index {0: 100} and size 100.
7. Reference object 0.
Oops. The index tells us to seek to pos 100, but TmpStore has
been truncated to 100. We get a low-level exception from
struct.unpack() about not enough bytes to unpack the data record
header.
You can guess that I saw that happening <wink>. Step #4 also needs to copy
the index (from the savepoint to TmpStore) instead of sharing a reference,
although this wasn't needed so long as a savepoint could be "used" at most
once (then mutating the savepoint's index after a rollback had no ill
effect, as the savepoint's index could never be referenced again).
More information about the ZODB-Dev
mailing list