Hi,
Oops, sorry, Tom just hinted at my misreading of the calculation. Of course session3 is expected
to have -1 (the op is + not -).
The problem here is for session2 really. What could session2 possibly do ? to a refresh before
calculating ? Are we postulating short-lived sessions ? What about sessions backing ObservationListeners
(which are inherently long-lived) ? Do they get accurate data back ?
Say, s1 listens on changes to node x, s2 updates node x and on receiving the event s1 would
access the new property. What happens ?
Regards
Felix
Am 30.11.2011 um 14:02 schrieb Michael Dürig:
>
>
>> This kind of scares me a bit: What could session3 possibly do about this here ?
>>
>> It looks like session3 is created after everything is set and done, thus it is expected
that p1==p2==-1 and thus p1-p2==0.
>
> session3 can't do anything about it, session 2 could. See [1]. This is a
> consequence inherent to snapshot isolation.
>
> [1] http://dl.acm.org/citation.cfm?id=1376690
>
>
>>
>> Regards
>> Felix
>>
>> Am 30.11.2011 um 13:38 schrieb Michael Dürig:
>>
>>>
>>> Hi,
>>>
>>> As documented earlier [1] new Mircokernel based JCR implementations will
>>> most likely introduce snapshot isolation for sessions. While I think
>>> this is a good thing in general, it also introduces potentially
>>> troublesome write skew: application level constraints might hold locally
>>> (i.e. per session) but might fail globally. That is, in order to enforce
>>> some constraints, applications might need to implement explicit cross
>>> session synchronization mechanisms instead of being able to rely on
>>> session isolation. The following test case demonstrates the issue.
>>>
>>> /**
>>> * Trans-session isolation differs from Jackrabbit 2.
>>> * Snapshot isolation can result in write skew as this
>>> * test demonstrates: the check method enforces an
>>> * application logic constraint which says that the sum
>>> * of the properties p1 and p2 must not be negative. While
>>> * session1 and session2 each enforce this constraint before
>>> * saving, the constraint might not hold globally as can be
>>> * seen in session3.
>>> */
>>> @Test
>>> public void testSessionIsolation() throws RepositoryException {
>>> Repository repository = getRepository();
>>>
>>> Session session0 = repository.login();
>>> Node testNode = session0.getNode("/").addNode("testNode");
>>> testNode.setProperty("p1", 1);
>>> testNode.setProperty("p2", 1);
>>> session0.save();
>>> check(getSession());
>>>
>>> Session session1 = repository.login();
>>> Session session2 = repository.login();
>>>
>>> session1.getNode("/testNode").setProperty("p1", -1);
>>> check(session1);
>>> session1.save();
>>>
>>> session2.getNode("/testNode").setProperty("p2", -1);
>>> check(session2); // Throws on JR2 but not on JR3
>>> session2.save();
>>>
>>> Session session3 = repository.login();
>>> check(session3); // Throws on JR3
>>> }
>>>
>>> private static void check(Session session) throws RepositoryException {
>>> if (session.getNode("/testNode").getProperty("p1").getLong() +
>>> session.getNode("/testNode").getProperty("p2").getLong()< 0) {
>>> fail("p1 + p2< 0");
>>> }
>>> }
>>>
>>> Michael
>>>
>>> [1]
>>> http://wiki.apache.org/jackrabbit/Transactional%20model%20of%20the%20Microkernel%20based%20Jackrabbit%20prototype
>>
|