Manik Surtani wrote:
Now with MVCC - since there are no read locks - we have a problem.
Consider:
1. Tx begns.
2. Tx reads /a (no locks)
3. Tx removes /a/b (locks /a/b)
4. Tx counts children of /a (will still see that /a/b is in /a's child
map).
he approaches I have considered are:
1. Removing /a/b from /a's child map.
This will provide a consistent view to the tx removing /a/b but will
mean that other txs will also see /a/b disappear when counting /a's
children, but not when querying the cache for /a/b! Worse, rollbacks
would mean re-adding /a/b to /a's child map, providing weird views on
other readers (/a/b disappears for a while, then reappears)
2. Make a copy of /a for the tx to work off, when removing /a/b. This
is the same as having LockParentForChildInsertRemove semantics.
Copy the parent as well and work off it, but to prevent problems with
concurrent child removes and adds, we'd have to lock the parent.
My vote is for approach 2. In fact, LockParentForChildInsertRemove
would always need to be enabled when using MVCC. Perhaps this should be
a deprecated property that just supports additional consistency for OL
and PL, and be removed when OL/PL eventually get removed?
Thoughts?
Why not treat a delete like a modify (as I think it has been done in the
past)? When a node is deleted, it is locked, and either a sentinel or
just an fqn is stored in the TX context that issued the delete. Then the
parent still conains the original node, allowing concurrent readers,
while the calling tx knows to filter deleted nodes from child operations.
--
Jason T. Greene
JBoss, a division of Red Hat