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 >>
