[
https://issues.apache.org/jira/browse/JCR-1359?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12573797#action_12573797
]
Stefan Guggisberg commented on JCR-1359:
----------------------------------------
it took me a while to figure it out but i guess i finally found the root causes
of the 2 aforementioned exceptions, i.e.
a) javax.jcr.nodetype.ConstraintViolationException: /A/7 needs to be saved as
well.
b) javax.jcr.RepositoryException: /A: unable to update item.: Unable to resolve
path for item:
016b885a-64aa-45b9-a990-05cbabb4586f/{http://www.jcp.org/jcr/1.0}primaryType
here's my analysis (based on r632346):
a) happens when
- thread 1 is in ItemImpl.save(), somewhere around line 1153, just about
calling
nodeState.getRemovedChildNodeEntries()
- thread 2 then calls LocalItemStateManager.stateModified() and updates the
underlying
local state
- thread 1 continues and calls nodeState.getRemovedChildNodeEntries(),
reporting
the id of the child node added by thread 2 (transient and local state are
not in sync
at this moment, i.e. the transient state is temporarily stale)
- thread 2 then calls SessionItemStateManager.stateModified() and merges the
transient
state with the underlying local state; transient and local state are in sync
again
- the result is an exception incorrectly complaining about an unsatisfied
dependency
(id needs to be saved as well)
b) is more severe, it happens when
- thread 1 is in NodeImpl.makePersistent(), somewhere within the synchronized
block
starting at line 933, holding the monitor on the NodeState instance
'persistentState'
- thread 2 then calls ItemState.pull() (via
LocalItemStateManager.stateModified()) and
waits for the monitor the NodeState instance before entering
NodeState.copy())...
- thread 1 leaves the synchronized block
- thread 2 now calls NodeState.copy(), effectively overwriting thread 1's
changes in
the change log...
- the result is an exception (unable to resolve path) because the child node
entry
created by thread 1 was lost
> Adding nodes from concurrently running sessions cause exceptions
> ----------------------------------------------------------------
>
> Key: JCR-1359
> URL: https://issues.apache.org/jira/browse/JCR-1359
> Project: Jackrabbit
> Issue Type: Bug
> Components: jackrabbit-core
> Affects Versions: 1.3.3, 1.4, core 1.4.1
> Reporter: Alexander Nesterov
> Assignee: Stefan Guggisberg
> Priority: Critical
> Fix For: core 1.4.2
>
>
> Exceptions are thrown when trying to add child nodes to one parent node from
> different sessions running concurrently. One of the following exceptions is
> always thrown:
> * Exception in thread "Thread-8" java.lang.RuntimeException:
> javax.jcr.nodetype.ConstraintViolationException: /A/7 needs to be saved as
> well.
> * Exception in thread "Thread-8" java.lang.RuntimeException:
> javax.jcr.RepositoryException: /A: unable to update item.: Unable to
> resolve path for item:
> 016b885a-64aa-45b9-a990-05cbabb4586f/{http://www.jcp.org/jcr/1.0}primaryType:
> Unable to resolve path for item:
> 016b885a-64aa-45b9-a990-05cbabb4586f/{http://www.jcp.org/jcr/1.0}primaryType
> According to JCR-584 "Improve handling of concurrent node modifications" the
> following scenario "session 1 adds or removes child node 'x', session 2 adds
> or removes child node 'y'" should run gracefully, but the following test
> constantly fails:
> public void testSync() throws Exception
> {
> Node rootNode = getSession ().getRootNode ();
> rootNode.addNode ("A");
> rootNode.save();
> final Session session1 = getRepository().login (new SimpleCredentials
> ("userName", "password".toCharArray()));
> final Session session2 = getRepository().login (new SimpleCredentials
> ("userName", "password".toCharArray()));
> Thread thread1 = new Thread (new Runnable()
> {
> public void run()
> {
> try
> {
> addNodes ("A", session1, 0);
> }
> catch (RepositoryException ex)
> {
> throw new RuntimeException (ex);
> }
> }
> });
> Thread thread2 = new Thread (new Runnable()
> {
> public void run()
> {
> try
> {
> addNodes ("A", session2, 1001);
> }
> catch (RepositoryException ex)
> {
> throw new RuntimeException (ex);
> }
> }
> });
> thread1.start();
> thread2.start();
> thread1.join();
> thread2.join();
> }
> private void addNodes (String parentName, Session session, int startIndex)
> throws RepositoryException
> {
> Node parentNode = session.getRootNode().getNode (parentName);
> for (int i = startIndex; i < startIndex + 100; i++)
> {
> String name = Integer.toString (i);
> parentNode.addNode (name);
> parentNode.save();
> }
> }
> BTW: exceptions were also thrown when I tried to add nodes from one thread
> and remove some of them from another one. Each thread used it's own session,
> each node had unique name.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.