[ 
https://issues.apache.org/jira/browse/JCR-2579?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Jukka Zitting updated JCR-2579:
-------------------------------

    Fix Version/s: 2.1.1
                       (was: 2.1.0)

Unfortunately I still don't have a fix for this issue, even though I can fairly 
easily recreate it with the ConcurrentNodeModificationTest class in 
jackrabbit-core.

Since this is the last bug open for 2.1.0 and the number of use cases it 
impacts is somewhat limited I'm postponing it to 2.1.1 to avoid holding up the 
2.1.0 release too much.

> InvalidItemStateException when attempting concurrent, non conflicting writes
> ----------------------------------------------------------------------------
>
>                 Key: JCR-2579
>                 URL: https://issues.apache.org/jira/browse/JCR-2579
>             Project: Jackrabbit Content Repository
>          Issue Type: Bug
>          Components: jackrabbit-core
>    Affects Versions: 1.6.1
>            Reporter: Dan Diephouse
>            Assignee: Jukka Zitting
>             Fix For: 2.1.1
>
>
> I'm having some problems doing concurrent addition of nodes to a parent node 
> in Jackrabbit.  I've attached a simple test which starts up a bunch of 
> threads which add nodes to a parent node concurrently. If I add in locks I 
> can get this to work, however according to the mailing list this should work 
> without locks. However, the test always fails with this:
> javax.jcr.InvalidItemStateException: Item cannot be saved because it has been 
> modified externally: node /testParent
>       at 
> org.apache.jackrabbit.core.ItemImpl.getTransientStates(ItemImpl.java:281)
>       at org.apache.jackrabbit.core.ItemImpl.save(ItemImpl.java:939)
>       at 
> org.mule.galaxy.impl.JackrabbitConcurrentWriteTest$1.run(JackrabbitConcurrentWriteTest.java:71)
> I'm using Jackrabbit 1.6.1. Here is my (verbose) node type:
>   <nodeType name="galaxy:noSiblings" 
>     isMixin="false" 
>     hasOrderableChildNodes="false"
>     primaryItemName="">
>     <propertyDefinition name="*" requiredType="undefined" 
> onParentVersion="COPY" />
>     <propertyDefinition name="*" requiredType="undefined" 
> onParentVersion="COPY" multiple="true"/>
>     <childNodeDefinition name="*" defaultPrimaryType="nt:unstructured" 
> onParentVersion="COPY" sameNameSiblings="false" />
>     <supertypes>
>         <supertype>nt:base</supertype>
>         <supertype>mix:referenceable</supertype>
>         <supertype>mix:lockable</supertype>
>     </supertypes>
>   </nodeType>
> And my test:    
> package org.mule.galaxy.impl;
> import java.io.File;
> import java.io.IOException;
> import java.io.InputStream;
> import java.util.ArrayList;
> import java.util.List;
> import java.util.UUID;
> import java.util.concurrent.CountDownLatch;
> import java.util.concurrent.TimeUnit;
> import javax.jcr.LoginException;
> import javax.jcr.Node;
> import javax.jcr.Repository;
> import javax.jcr.RepositoryException;
> import javax.jcr.Session;
> import javax.jcr.SimpleCredentials;
> import junit.framework.TestCase;
> import org.apache.commons.io.FileUtils;
> import org.apache.jackrabbit.api.JackrabbitNodeTypeManager;
> import org.apache.jackrabbit.core.RepositoryImpl;
> import org.apache.jackrabbit.core.TransientRepository;
> import org.apache.jackrabbit.core.config.RepositoryConfig;
> public class JackrabbitConcurrentWriteTest extends TestCase {
>     
>     private Repository repository;
>     private Session session;
>     private String parentUUID;
>     private boolean continueLoop = true;
>     
>     public void setUp() throws Exception {
>         FileUtils.deleteDirectory(new File("repository"));
>         File repoDir = new File("repository");
>         repoDir.mkdirs();
>         RepositoryConfig config = RepositoryConfig.create(new 
> File("src/test/resources/META-INF/jackrabbit-repo-test.xml"), repoDir);
>         repository = RepositoryImpl.create(config);
>         session = createSession();
>         
>         createCustomNodeTypes(session);
>         
>         parentUUID = session.getRootNode().addNode("testParent", 
> "galaxy:noSiblings").getUUID();
>         session.save();
>         session.logout();
>     }
>     private Session createSession() throws LoginException, 
> RepositoryException {
>         return repository.login(new SimpleCredentials("username", 
> "password".toCharArray()));
>     }
>     
>     public void testConcurrency() throws Exception {
>         final List<Exception> exceptions = new ArrayList<Exception>();
>         int threadCount = 20;
>         final CountDownLatch latch = new CountDownLatch(threadCount);
>         
>         for (int i = 0; i < threadCount; i++) {
>             Thread thread = new Thread() {
>                 @Override
>                 public void run() {
>                     try {
>                         while (continueLoop) {
>                             Session session = createSession();
>                             try {
>                                 Node node = session.getNodeByUUID(parentUUID);
>                                 node.addNode(UUID.randomUUID().toString());
>                                 node.save();
>                                 session.save();
>                             } finally {
>                                 session.logout();
>                             }   
>                         }
>                     } catch (RepositoryException e) {
>                         exceptions.add(e);
>                         continueLoop = false;
>                     }
>                     latch.countDown();
>                 }
>                 
>             };
>             thread.start();
>         }
>         
>         latch.await(10, TimeUnit.SECONDS);
>         continueLoop = false;
>         
>         for (Exception e : exceptions) {
>             e.printStackTrace();
>         }
>         assertEquals(0, exceptions.size());
>     }
>     
>     public void createCustomNodeTypes(Session session) throws 
> RepositoryException, IOException {
>         // Get the JackrabbitNodeTypeManager from the Workspace.
>         // Note that it must be cast from the generic JCR NodeTypeManager to
>         // the Jackrabbit-specific implementation.
>         // (see: http://jackrabbit.apache.org/node-types.html)
>         JackrabbitNodeTypeManager manager = (JackrabbitNodeTypeManager) 
> session.getWorkspace().getNodeTypeManager();
>         // Register the custom node types defined in the CND file
>         InputStream is = Thread.currentThread().getContextClassLoader()
>                 
> .getResourceAsStream("org/mule/galaxy/impl/jcr/nodeTypes.xml");
>         manager.registerNodeTypes(is, JackrabbitNodeTypeManager.TEXT_XML);
>     }
> }

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
https://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Reply via email to