On 17 Mar 2009, at 20:33, Jason T. Greene wrote:
Brian Stansberry wrote:
However, this sounds like a problem with PFER. If someone calls PFER, I think the original transaction should resync the node snapshot.
How would this be done? AFAIK the application has no control over the data in JBCs transaction context.
The PFER implementation, not the application, would just drop the node from the tx context which invoked pfer. That would mean that any subsequent read would fetch the most current data.
No, that is not correct. PFER suspends ongoing TXs and runs outside of any TX, to prevent a failure rolling back the TX. And this is the root of the problem.
I have fixed this in trunk, the correct solution is to fix the mismatch in expected behaviour between a removeNode() and any other write when using R_R, write skew checking is disabled, and a null node has already been read into the tx context.
Basically, what happens is this (assuming write skew checking is off):
1. Read node, is null // if using R_R, a NullNodeMarker is placed in context so a re-read is not attempted, preserving R_R semantics.
2. A Write is performed // this ends up in creating a new node, and writing changes, overwriting any concurrent changes that may have occurred between 1 and 2.
This is correct and expected if using R_R and write skew checking is off. Now looking at the remove node case:
1. Read node, is null // if using R_R, a NullNodeMarker is placed in context so a re-read is not attempted, preserving R_R semantics.
2. A removeNode is performed // the node in context is marked as removed and processed accordingly, and in the case of a NullMarkerNode, this is a no-op.
This is where the problem lies.
I have fixed this using a new type of marker node, NullNodeMarkerForRemove, which holds a reference to the parent, and actually causes the parent to remove the necessary child, providing the same overwrite semantics as in the case of a write.
This is in trunk if anyone wants to take a look
Cheers
Manik
--