You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@jackrabbit.apache.org by "Stefan Guggisberg (JIRA)" <ji...@apache.org> on 2009/09/02 18:04:32 UTC
[jira] Resolved: (JCR-2269) Possible concurrency bug with
Workspace.copy()
[ https://issues.apache.org/jira/browse/JCR-2269?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Stefan Guggisberg resolved JCR-2269.
------------------------------------
Resolution: Fixed
fixed in svn r810565.
thanks for reporting this issue and providing a test case!
> Possible concurrency bug with Workspace.copy()
> -----------------------------------------------
>
> Key: JCR-2269
> URL: https://issues.apache.org/jira/browse/JCR-2269
> Project: Jackrabbit Content Repository
> Issue Type: Bug
> Components: jackrabbit-core
> Affects Versions: 1.6.0
> Reporter: Jervis Liu
> Attachments: ConcurrentCopyTest.java
>
>
> Hi,
> Enclosed below is a test case that can be used to reproduce a
> concurrency bug. This test case uses two con-current threads to
> execute Workspace.copy() to copy a node to same destination. The
> parent node has set its allowSameNameSiblings to false. According to
> the javadoc of Workspace.copy(String srcAbsPath, String destAbsPath) :
> "This method copies the node at srcAbsPath to the new location at
> destAbsPath. If successful, the change is persisted immediately, there
> is no need to call save.". "An ItemExistException is thrown if a
> property already exists at destAbsPath or a node already exist there,
> and same name siblings are not allowed. "
> However in reality this is not the case. The test case can end up
> with two child nodes with same names. Please note, not every run can
> reproduce the problem, but generally I can get the problem within 3 to
> 10 iterations. I also got an InvalidItemStateException once (only
> once). Can someone kindly help to confirm if this is a bug in
> Jackrabbit or maybe I am using JackRabbit in a wrong way? The test
> case has been tested on Jackrabbit 1.6 branch
> (http://svn.apache.org/repos/asf/jackrabbit/tags/1.6.0), Windows
> Vista, JDK 1.5.0_14.
> The test case is also attached for your convenience.
> Thanks,
> Jervis Liu
> package org.apache.jackrabbit.core;
> import org.apache.jackrabbit.test.AbstractJCRTest;
> import javax.jcr.ItemExistsException;
> import javax.jcr.Node;
> import javax.jcr.Session;
> import javax.jcr.Value;
> import javax.jcr.NodeIterator;
> import java.util.Random;
> import java.util.ArrayList;
> import java.util.Iterator;
> import javax.jcr.nodetype.NodeType;
> import org.apache.jackrabbit.test.NotExecutableException;
> import javax.jcr.RepositoryException;
> import javax.jcr.nodetype.NodeTypeManager;
> public class ConcurrentCopyTest extends AbstractJCRTest {
> private static final int NUM_ITERATIONS = 40;
> private static final int NUM_SESSIONS = 2;
> String sourcePath;
> String destPath;
> public void testConcurrentCopy() throws Exception {
> for (int n = 0; n < NUM_ITERATIONS; n++) {
> System.out.println("---Iteration---- " + n);
> // clean up testRoot first
> if (testRootNode.hasNode("ConcurrentCopyTestNode")) {
> Node testNode = testRootNode.getNode("ConcurrentCopyTestNode");
> testNode.remove();
> testRootNode.save();
> System.out.println("---old node removed---");
> }
> // create a parent node where allowSameNameSiblings is set to false
> Node snsfNode = testRootNode.addNode("ConcurrentCopyTestNode",
> "nt:folder");
> testRootNode.save();
> sourcePath = snsfNode.getPath();
> destPath = sourcePath + "/" + "CopiedFromConcurrentCopyTestNode";
> System.out.println("---sourcePath-----------------" + sourcePath);
> System.out.println("---destPath-----------------" + destPath);
> // firstly we verify it works with single thread.
> Session rootSession = helper.getSuperuserSession();
> rootSession.getWorkspace().copy(sourcePath, destPath + "test");
> // copy again to same destPath, expect an ItemExistsException
> try {
> rootSession.getWorkspace().copy(sourcePath, destPath + "test");
> fail("Node exists below '" + destPath + "'. Test should fail.");
> } catch (ItemExistsException e) {
> }
> Thread[] threads = new Thread[NUM_SESSIONS];
> for (int i = 0; i < threads.length; i++) {
> // create new session
> Session session = helper.getSuperuserSession();
> TestSession ts = new TestSession("s" + i, session);
> Thread t = new Thread(ts);
> t.setName((NUM_ITERATIONS - n) + "-s" + i);
> t.start();
> log.println("Thread#" + i + " started");
> threads[i] = t;
> // Thread.yield();
> // Thread.sleep(100);
> }
> for (int i = 0; i < threads.length; i++) {
> threads[i].join();
> }
> NodeIterator results = testRootNode.getNode(
> "ConcurrentCopyTestNode").getNodes(
> "CopiedFromConcurrentCopyTestNode");
> while (results.hasNext()) {
> Node node = results.nextNode();
> System.out.println("--result node- " + node.getName());
> }
> assertEquals(1, results.getSize());
> }
> }
> // --------------------------------------------------------< inner classes >
> class TestSession implements Runnable {
> Session session;
> String identity;
> Random r;
> TestSession(String identity, Session s) {
> session = s;
> this.identity = identity;
> r = new Random();
> }
> private void randomSleep() {
> long l = r.nextInt(90) + 20;
> try {
> Thread.sleep(l);
> } catch (InterruptedException ie) {
> }
> }
> public void run() {
> log.println("started.");
> String state = "";
> try {
> this.session.getWorkspace().copy(sourcePath, destPath);
> session.save();
> Node newNode =
> testRootNode.getNode("ConcurrentCopyTestNode/CopiedFromConcurrentCopyTestNode");
> System.out.println("--Added node- " + newNode.getName());
> session.save();
> randomSleep();
> } catch (Exception e) {
> log.println("Exception while " + state + ": " + e.getMessage());
> e.printStackTrace();
> } finally {
> session.logout();
> }
> log.println("ended.");
> }
> }
> }
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.