RE: [ZODB-Dev] Savepoints are invalidated once they are used

2005-07-16 Thread Dieter Maurer
Tim Peters wrote at 2005-7-15 16:06 -0400:
 ...
Anyway, for reasons explained before, making a savepoint would still need to
copy the index, so I don't see that this would save anything worth saving.
It might allow skipping an index copy when a _rollback_ is done (at the cost
of clumsier coding for the user), but I don't care much about that expense.

Okay :-)


-- 
Dieter
___
For more information about ZODB, see the ZODB Wiki:
http://www.zope.org/Wikis/ZODB/

ZODB-Dev mailing list  -  ZODB-Dev@zope.org
http://mail.zope.org/mailman/listinfo/zodb-dev


RE: [ZODB-Dev] Savepoints are invalidated once they are used

2005-07-15 Thread Dieter Maurer
Tim Peters wrote at 2005-7-14 19:20 -0400:
 ...
[Dieter]
 If we do, we can (usually) create a one with the state after the
 restore.

[Tim]
Sorry, I couldn't follow that sentence.

After I have restored to a savepoint s, then the current state is
the one saved in s, thus the sequence:

s.restore() # and eliminate from stack
s = transaction.savepoint()

essentially recreates s and the situation I would get would restore
not eliminate s from the stack -- modulo the fact, that s now
contains a new savepoint object (and other bindings to the old
object no longer work as expected).
An s.push() would eliminate this drawback (at the expense of
an additional method).


-- 
Dieter
___
For more information about ZODB, see the ZODB Wiki:
http://www.zope.org/Wikis/ZODB/

ZODB-Dev mailing list  -  ZODB-Dev@zope.org
http://mail.zope.org/mailman/listinfo/zodb-dev


RE: [ZODB-Dev] Savepoints are invalidated once they are used

2005-07-15 Thread Tim Peters
[Dieter]
 If we do, we can (usually) create a one with the state after the
 restore.

[Tim]
 Sorry, I couldn't follow that sentence.

[Dieter]
 After I have restored to a savepoint s, then the current state is the
 one saved in s, thus the sequence:

 s.restore() # and eliminate from stack
 s = transaction.savepoint()

 essentially recreates s and the situation I would get would restore
 not eliminate s from the stack -- modulo the fact, that s now
 contains a new savepoint object (and other bindings to the old object no
 longer work as expected). An s.push() would eliminate this drawback (at
 the expense of an additional method).

Got it -- thanks.  Part of the hangup was simply that what you call
restore there is actually spelled rollback, and for some reason I didn't
grasp that you were talking about the same thing (unsure why -- seems
obvious enough today!).

Anyway, for reasons explained before, making a savepoint would still need to
copy the index, so I don't see that this would save anything worth saving.
It might allow skipping an index copy when a _rollback_ is done (at the cost
of clumsier coding for the user), but I don't care much about that expense.

I do care about the expense of copying the index when a savepoint is made,
but all schemes so far have that expense, regardless of whether they allow
multiple rollbacks to a given savepoint (Jeremy misremembered when he wrote
that the old scheme made a copy (solely) to support multiple rollbacks;
it's also needed just to support nesting, which is the primary feature of
savepoints).

___
For more information about ZODB, see the ZODB Wiki:
http://www.zope.org/Wikis/ZODB/

ZODB-Dev mailing list  -  ZODB-Dev@zope.org
http://mail.zope.org/mailman/listinfo/zodb-dev


Re: [ZODB-Dev] Savepoints are invalidated once they are used

2005-07-14 Thread Dieter Maurer
Jeremy Hylton wrote at 2005-7-11 18:37 -0700:
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.

Maybe, we keep the original implementation (a savepoint restore
deletes this savepoint) and update the docstring?

It is rare that we need to keep the savepoint.
If we do, we can (usually) create a one with the state
after the restore.

-- 
Dieter
___
For more information about ZODB, see the ZODB Wiki:
http://www.zope.org/Wikis/ZODB/

ZODB-Dev mailing list  -  ZODB-Dev@zope.org
http://mail.zope.org/mailman/listinfo/zodb-dev


RE: [ZODB-Dev] Savepoints are invalidated once they are used

2005-07-14 Thread Tim Peters
[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.

[Dieter Maurer]
 Maybe, we keep the original implementation (a savepoint restore deletes
 this savepoint) and update the docstring?

 It is rare that we need to keep the savepoint.

All implementations (the current one in SVN, the old one, and the
original one) copy the index at the time a savepoint is made, but for more
reasons than Jeremy gave (I suspect his memory of the old implementation's
details has faded a bit ;-)).  To be usable for rollback at all (even once),
a savepoint has to remember the state of the TmpStore index at the time the
savepoint is made -- otherwise it couldn't restore the index to that state
on a rollback.  If the savepoint shares its remembered index object with
TmpStore, then mutations to the latter's index effectively corrupt the
savepoint's remembered index.

The additional copying recently added, to support rolling back to a
savepoint multiple times, occurs only when a rollback is actually performed.
I don't mind that expense at all.

BTW, I don't expect we can know what's rare or not with these yet.  Nesting
is a powerful ability subtransactions couldn't approach, so it's plausible
to imagine that savepoints will get used for much more than just their
RAM-freeing side effects -- and most copying here is to support nesting
correctly.
 
 If we do, we can (usually) create a one with the state after the
 restore.

Sorry, I couldn't follow that sentence.

I would like to do less indexing copying when a savepoint is made, but don't
see an obvious and effective way to get away with that.  The current
implementation has become obviously correct instead of not obviously
wrong, and that's a good place to leave it for now in the absence of dire
need.

___
For more information about ZODB, see the ZODB Wiki:
http://www.zope.org/Wikis/ZODB/

ZODB-Dev mailing list  -  ZODB-Dev@zope.org
http://mail.zope.org/mailman/listinfo/zodb-dev


Re: [ZODB-Dev] Savepoints are invalidated once they are used

2005-07-12 Thread Jeremy Hylton
On 7/12/05, Tim Peters [EMAIL PROTECTED] wrote:
 [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).

I understand.  The further invariant is that the index captured when a
savepoint created is immutable.

Jeremy
___
For more information about ZODB, see the ZODB Wiki:
http://www.zope.org/Wikis/ZODB/

ZODB-Dev mailing list  -  ZODB-Dev@zope.org
http://mail.zope.org/mailman/listinfo/zodb-dev


RE: [ZODB-Dev] Savepoints are invalidated once they are used

2005-07-12 Thread Tim Peters
[Jeremy Hylton]
 I understand.  The further invariant is that the index captured when a
 savepoint created is immutable.

Or at least acts like it.  Copying is an easy-to-code and effective way to
ensure that, and I don't know of a better feasible way.  Capturing a lot of
savepoints (or doing a lot of commit(True)) while modifying a lot of objects
makes for a lot of index copying, though, effectively injecting an O(N**2)
time drag (even if rollback/abort(True) is never done).

A copy on modify flavor of dict could do much better.  Since I'm sure
Google could also make good use of that, I expect to see a patch on the
Python tracker from you implementing that by the end of this weekend wink.

___
For more information about ZODB, see the ZODB Wiki:
http://www.zope.org/Wikis/ZODB/

ZODB-Dev mailing list  -  ZODB-Dev@zope.org
http://mail.zope.org/mailman/listinfo/zodb-dev


[ZODB-Dev] Savepoints are invalidated once they are used

2005-07-11 Thread Christian Heimes
Today I stumbled over an unexpected behavior of savepoints. As far as 
I'm able to understand savepoints they mark a well defined state in the 
middle of a transaction. A savepoint is invalid if its transaction is 
committed or another savepoint is created. Well nesting savepoints would 
be a nice feature but I can live w/o it.


Something else strikes me. Why am I unable to roll back to the same 
savepoint multiple times?


Pseudo code example

 sp = transaction.savepoint()
 dosomething()
 sp.valid
True
 sp.rollback()
 domore()
 sp.valid
False
 sp.rollback()
FunkyRollbackException

From my point of view I can't see a reason why the ZODB forbids a 
second rolback to the savepoint.


Christian

___
For more information about ZODB, see the ZODB Wiki:
http://www.zope.org/Wikis/ZODB/

ZODB-Dev mailing list  -  ZODB-Dev@zope.org
http://mail.zope.org/mailman/listinfo/zodb-dev


Re: [ZODB-Dev] Savepoints are invalidated once they are used

2005-07-11 Thread Jim Fulton

Christian Heimes wrote:
Today I stumbled over an unexpected behavior of savepoints. As far as 
I'm able to understand savepoints they mark a well defined state in the 
middle of a transaction. A savepoint is invalid if its transaction is 
committed or another savepoint is created. Well nesting savepoints would 
be a nice feature but I can live w/o it.


Something else strikes me. Why am I unable to roll back to the same 
savepoint multiple times?


Pseudo code example

  sp = transaction.savepoint()
  dosomething()
  sp.valid
True
  sp.rollback()
  domore()
  sp.valid
False
  sp.rollback()
FunkyRollbackException

 From my point of view I can't see a reason why the ZODB forbids a 
second rolback to the savepoint.


I agree. This should be changed.

Jim

--
Jim Fulton   mailto:[EMAIL PROTECTED]   Python Powered!
CTO  (540) 361-1714http://www.python.org
Zope Corporation http://www.zope.com   http://www.zope.org
___
For more information about ZODB, see the ZODB Wiki:
http://www.zope.org/Wikis/ZODB/

ZODB-Dev mailing list  -  ZODB-Dev@zope.org
http://mail.zope.org/mailman/listinfo/zodb-dev


Re: [ZODB-Dev] Savepoints are invalidated once they are used

2005-07-11 Thread Jim Fulton

Tim Peters wrote:

[Christian Heimes]


...


Something else strikes me. Why am I unable to roll back to the same
savepoint multiple times?



Because that's how it works wink.  Maybe Jim can explain why quickly --
offhand I'm not sure.  I don't think it could be guessed from the interface
docs:

class InvalidSavepointRollbackError(Exception):
Attempt to rollback an invalid savepoint.

A savepoint may be invalid because:

- The surrounding transaction has committed or aborted.

- An earlier savepoint in the same transaction has been rolled back.


The last line there reads like it's OK to roll back to the _same_ savepoint
multiple times (it's not earlier than itself ...).


Yup

  But

transaction/savepoint.txt explicitly says (and tests that) you can't, so
it's intended behavior:


Yup, but I think it is incorrect behavior.

Jim

--
Jim Fulton   mailto:[EMAIL PROTECTED]   Python Powered!
CTO  (540) 361-1714http://www.python.org
Zope Corporation http://www.zope.com   http://www.zope.org
___
For more information about ZODB, see the ZODB Wiki:
http://www.zope.org/Wikis/ZODB/

ZODB-Dev mailing list  -  ZODB-Dev@zope.org
http://mail.zope.org/mailman/listinfo/zodb-dev


RE: [ZODB-Dev] Savepoints are invalidated once they are used

2005-07-11 Thread Tim Peters
[Christian Heimes]
...
  From my point of view I can't see a reason why the ZODB forbids a
 second rolback to the savepoint.

[Jim Fulton]
 I agree. This should be changed.

Sounds good to me -- it looks easy, so I'll do it wink.

___
For more information about ZODB, see the ZODB Wiki:
http://www.zope.org/Wikis/ZODB/

ZODB-Dev mailing list  -  ZODB-Dev@zope.org
http://mail.zope.org/mailman/listinfo/zodb-dev


RE: [ZODB-Dev] Savepoints are invalidated once they are used

2005-07-11 Thread Tim Peters
[Christian Heimes]
  From my point of view I can't see a reason why the ZODB forbids a
 second rolback to the savepoint.

[Jim Fulton]
 I agree. This should be changed.

[Tim Peters]
 Sounds good to me -- it looks easy, so I'll do it wink.

Something subtler than I've been able to figure out yet is going wrong, so I
made a tim-savepoint branch.  All the tests pass, but ...

After my first round of changes, subtxn abort (transaction.abort(1)) tests
failed.  Turned out the code implementing abort(1) relied on that
savepoint.rollback() marked `savepoint` as invalid, and that was easily
repaired (changed abort(1) to explicitly mark the subtxn savepoint as
invalid).  But after thinking about it, I couldn't understand _why_ that
repair was needed (except perhaps as an optimization), and that spawned this
failing code, which doesn't use subtxns:


import ZODB
from ZODB.FileStorage import FileStorage
import transaction
from BTrees.IIBTree import IIBTree

st = FileStorage(blah.fs)
db = ZODB.DB(st)
cn = db.open()
rt = cn.root()

tree = rt['tree'] = IIBTree()
tree[1] = 1
transaction.commit()

tree[1] = 2
sp2 = transaction.savepoint()

tree[1] = 3
sp3 = transaction.savepoint()

tree[1] = 4
assert tree[1] == 4

sp3.rollback()
assert tree[1] == 3

if 1: # turns out this is irrelevant; if 0 fails the same way
tree[1] = 4
assert tree[1] == 4

sp3.rollback()
assert tree[1] == 3, (tree[1], 3)


The second time sp3.rollback() is done, it seems to revert the state all the
way back to the first commit:  tree[1] is back to 1 again.  The same kind of
thing happened under abort(1) if the subtxn savepoint wasn't explicitly
marked as invalid.  Stepping thru it under pdb didn't reveal the cause,
which means I must have stepped over the important parts ... I'll try again
later.

___
For more information about ZODB, see the ZODB Wiki:
http://www.zope.org/Wikis/ZODB/

ZODB-Dev mailing list  -  ZODB-Dev@zope.org
http://mail.zope.org/mailman/listinfo/zodb-dev


RE: [ZODB-Dev] Savepoints are invalidated once they are used

2005-07-11 Thread Tim Peters
[Tim Peters]
 Something subtler than I've been able to figure out yet is going wrong,
 so I made a tim-savepoint branch.  All the tests pass, but ...

Br.  The pickle cache invalidate method (which is coded in C, so isn't
visible from pdb) clears the dictionary passed to it, and when using a
savepoint more than once that can end up clearing the index of the TmpStore
holding the savepoint'ed data.  Then the TmpStore no longer believes it
holds any objects, so after that point acts as if no savepoints had ever
made.

The good news is that, while it was hard to find, it's a one-line repair.

___
For more information about ZODB, see the ZODB Wiki:
http://www.zope.org/Wikis/ZODB/

ZODB-Dev mailing list  -  ZODB-Dev@zope.org
http://mail.zope.org/mailman/listinfo/zodb-dev


RE: [ZODB-Dev] Savepoints are invalidated once they are used

2005-07-11 Thread Tim Peters
[Tim Peters]
 ...
 The good news is that, while it was hard to find, it's a one-line repair.

Alas, that wasn't the end of it either.  I think I'm at the end now, and all
the tests are passing again (including new tests to provoke new problems I
found).

A savepoint (of the data manager Connection flavor) remembers the TmpStore
index at the time the savepoint was made.  When a savepoint could be used
only once, the savepoint only needed to make sure it had a copy of the index
at the time the savepoint was _made_.  But when a savepoint can be reused,
even the TmpStore.reset() line

self.index = index

was a source of subtle bugs (later mutations to `self.index` showed up in
`index` too, and `index` there is typically taken from a savepoint's this
is what the world looked like when I was new state -- mutating that was
harmless before because the rollback could never be used again, but became
disastrous when allowing re-use).

___
For more information about ZODB, see the ZODB Wiki:
http://www.zope.org/Wikis/ZODB/

ZODB-Dev mailing list  -  ZODB-Dev@zope.org
http://mail.zope.org/mailman/listinfo/zodb-dev


Re: [ZODB-Dev] Savepoints are invalidated once they are used

2005-07-11 Thread 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.

Jeremy

On 7/11/05, Tim Peters [EMAIL PROTECTED] wrote:
 [Tim Peters]
  ...
  The good news is that, while it was hard to find, it's a one-line repair.
 
 Alas, that wasn't the end of it either.  I think I'm at the end now, and all
 the tests are passing again (including new tests to provoke new problems I
 found).
 
 A savepoint (of the data manager Connection flavor) remembers the TmpStore
 index at the time the savepoint was made.  When a savepoint could be used
 only once, the savepoint only needed to make sure it had a copy of the index
 at the time the savepoint was _made_.  But when a savepoint can be reused,
 even the TmpStore.reset() line
 
 self.index = index
 
 was a source of subtle bugs (later mutations to `self.index` showed up in
 `index` too, and `index` there is typically taken from a savepoint's this
 is what the world looked like when I was new state -- mutating that was
 harmless before because the rollback could never be used again, but became
 disastrous when allowing re-use).
 
 ___
 For more information about ZODB, see the ZODB Wiki:
 http://www.zope.org/Wikis/ZODB/
 
 ZODB-Dev mailing list  -  ZODB-Dev@zope.org
 http://mail.zope.org/mailman/listinfo/zodb-dev

___
For more information about ZODB, see the ZODB Wiki:
http://www.zope.org/Wikis/ZODB/

ZODB-Dev mailing list  -  ZODB-Dev@zope.org
http://mail.zope.org/mailman/listinfo/zodb-dev