You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by mr...@apache.org on 2007/05/04 10:17:38 UTC
svn commit: r535126 - in
/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core:
AbstractConcurrencyTest.java ConcurrentReadWriteTest.java
ConcurrentVersioningTest.java
Author: mreutegg
Date: Fri May 4 01:17:36 2007
New Revision: 535126
URL: http://svn.apache.org/viewvc?view=rev&rev=535126
Log:
JCR-862: unsynchronized access on 'itemCache' map in ItemManager
- test case to reproduce deadlock
Added:
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/AbstractConcurrencyTest.java (with props)
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentReadWriteTest.java (with props)
Modified:
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentVersioningTest.java
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/AbstractConcurrencyTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/AbstractConcurrencyTest.java?view=auto&rev=535126
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/AbstractConcurrencyTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/AbstractConcurrencyTest.java Fri May 4 01:17:36 2007
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+
+import javax.jcr.Session;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+/**
+ * <code>AbstractConcurrencyTest</code> provides utility methods to run tests
+ * using concurrent threads.
+ */
+public abstract class AbstractConcurrencyTest extends AbstractJCRTest {
+
+ /**
+ * Runs a task with the given concurrency and creates an individual test
+ * node for each thread.
+ *
+ * @param task the task to run.
+ * @param concurrency the concurrency.
+ * @throws RepositoryException if an error occurs.
+ */
+ protected void runTask(Task task, int concurrency) throws RepositoryException {
+ Thread[] threads = new Thread[concurrency];
+ for (int i = 0; i < concurrency; i++) {
+ Session s = helper.getSuperuserSession();
+ Node test = s.getRootNode().addNode(testPath + "/node" + i);
+ s.save();
+ threads[i] = new Thread(new Executor(s, test, task));
+ }
+ for (int i = 0; i < threads.length; i++) {
+ threads[i].start();
+ }
+ for (int i = 0; i < threads.length; i++) {
+ try {
+ threads[i].join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Runs a task with the given concurrency on the node identified by path.
+ *
+ * @param task the task to run.
+ * @param concurrency the concurrency.
+ * @param path the path to the test node.
+ * @throws RepositoryException if an error occurs.
+ */
+ protected void runTask(Task task, int concurrency, String path)
+ throws RepositoryException {
+ Thread[] threads = new Thread[concurrency];
+ for (int i = 0; i < concurrency; i++) {
+ Session s = helper.getSuperuserSession();
+ Node test = (Node) s.getItem(path);
+ s.save();
+ threads[i] = new Thread(new Executor(s, test, task));
+ }
+ for (int i = 0; i < threads.length; i++) {
+ threads[i].start();
+ }
+ for (int i = 0; i < threads.length; i++) {
+ try {
+ threads[i].join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public interface Task {
+
+ public abstract void execute(Session session, Node test)
+ throws RepositoryException;
+ }
+
+ protected static class Executor implements Runnable {
+
+ protected final Session session;
+
+ protected final Node test;
+
+ protected final Task task;
+
+ public Executor(Session session, Node test, Task task) {
+ this.session = session;
+ this.test = test;
+ this.task = task;
+ }
+
+ public void run() {
+ try {
+ task.execute(session, test);
+ } catch (RepositoryException e) {
+ e.printStackTrace();
+ } finally {
+ session.logout();
+ }
+ }
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/AbstractConcurrencyTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentReadWriteTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentReadWriteTest.java?view=auto&rev=535126
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentReadWriteTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentReadWriteTest.java Fri May 4 01:17:36 2007
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.PropertyIterator;
+import javax.jcr.Property;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Random;
+
+/**
+ * <code>ConcurrentReadWriteTest</code> performs a test with a number of
+ * concurrent readers and one writer.
+ */
+public class ConcurrentReadWriteTest extends AbstractConcurrencyTest {
+
+ private static final int NUM_NODES = 5;
+
+ private static final int NUM_THREADS = 5;
+
+ private static final int RUN_NUM_SECONDS = 20;
+
+ public void testReadWrite() throws RepositoryException {
+ final List uuids = new ArrayList();
+ for (int i = 0; i < NUM_NODES; i++) {
+ Node n = testRootNode.addNode("node" + i);
+ n.addMixin(mixReferenceable);
+ uuids.add(n.getUUID());
+ }
+ final long[] numReads = new long[]{0};
+ testRootNode.save();
+ Thread t = new Thread(new Runnable() {
+ public void run() {
+ try {
+ runTask(new Task() {
+ public void execute(Session session, Node test)
+ throws RepositoryException {
+ Random rand = new Random();
+ long start = System.currentTimeMillis();
+ long reads = 0;
+ while (System.currentTimeMillis() < start + RUN_NUM_SECONDS * 1000) {
+ String uuid = (String) uuids.get(rand.nextInt(uuids.size()));
+ Node n = session.getNodeByUUID(uuid);
+ try {
+ for (PropertyIterator it = n.getProperties(); it.hasNext(); ) {
+ Property p = it.nextProperty();
+ if (p.getDefinition().isMultiple()) {
+ p.getValues();
+ } else {
+ p.getValue();
+ }
+ }
+ } catch (RepositoryException e) {
+ System.out.println(e);
+ }
+ reads++;
+ }
+ synchronized (numReads) {
+ numReads[0] += reads;
+ }
+ }
+ }, NUM_THREADS, testRoot);
+ } catch (RepositoryException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ t.start();
+ long numWrites = 0;
+ while (t.isAlive()) {
+ Random rand = new Random();
+ String uuid = (String) uuids.get(rand.nextInt(uuids.size()));
+ Node n = superuser.getNodeByUUID(uuid);
+ if (n.hasProperty("test")) {
+ n.getProperty("test").remove();
+ } else {
+ n.setProperty("test", "hello world");
+ }
+ n.save();
+ numWrites++;
+ }
+ System.out.println("#writes performed: " + numWrites);
+ System.out.println("#reads performed: " + numReads[0]);
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentReadWriteTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentVersioningTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentVersioningTest.java?view=diff&rev=535126&r1=535125&r2=535126
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentVersioningTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ConcurrentVersioningTest.java Fri May 4 01:17:36 2007
@@ -16,8 +16,6 @@
*/
package org.apache.jackrabbit.core;
-import org.apache.jackrabbit.test.AbstractJCRTest;
-
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Node;
@@ -30,7 +28,7 @@
* <code>ConcurrentVersioningTest</code> contains test cases that run version
* operations with concurrent threads.
*/
-public class ConcurrentVersioningTest extends AbstractJCRTest {
+public class ConcurrentVersioningTest extends AbstractConcurrencyTest {
/**
* The number of threads.
@@ -46,15 +44,11 @@
public void testConcurrentAddVersionable() throws RepositoryException {
runTask(new Task() {
public void execute(Session session, Node test) throws RepositoryException {
- try {
- // add versionable nodes
- for (int i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
- Node n = test.addNode("test" + i);
- n.addMixin(mixVersionable);
- session.save();
- }
- } finally {
- session.logout();
+ // add versionable nodes
+ for (int i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
+ Node n = test.addNode("test" + i);
+ n.addMixin(mixVersionable);
+ session.save();
}
}
}, CONCURRENCY);
@@ -63,18 +57,14 @@
public void testConcurrentCheckin() throws RepositoryException {
runTask(new Task() {
public void execute(Session session, Node test) throws RepositoryException {
- try {
- Node n = test.addNode("test");
- n.addMixin(mixVersionable);
- session.save();
- for (int i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
- n.checkout();
- n.checkin();
- }
+ Node n = test.addNode("test");
+ n.addMixin(mixVersionable);
+ session.save();
+ for (int i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
n.checkout();
- } finally {
- session.logout();
+ n.checkin();
}
+ n.checkout();
}
}, CONCURRENCY);
}
@@ -82,18 +72,14 @@
public void testConcurrentCreateAndCheckinCheckout() throws RepositoryException {
runTask(new Task() {
public void execute(Session session, Node test) throws RepositoryException {
- try {
- // add versionable nodes
- for (int i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
- Node n = test.addNode("test" + i);
- n.addMixin(mixVersionable);
- session.save();
- n.checkout();
- n.checkin();
- n.checkout();
- }
- } finally {
- session.logout();
+ // add versionable nodes
+ for (int i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
+ Node n = test.addNode("test" + i);
+ n.addMixin(mixVersionable);
+ session.save();
+ n.checkout();
+ n.checkin();
+ n.checkout();
}
}
}, CONCURRENCY);
@@ -102,78 +88,23 @@
public void testConcurrentRestore() throws RepositoryException {
runTask(new Task() {
public void execute(Session session, Node test) throws RepositoryException {
- try {
- Node n = test.addNode("test");
- n.addMixin(mixVersionable);
- session.save();
- // create 3 version
- List versions = new ArrayList();
- for (int i = 0; i < 3; i++) {
- n.checkout();
- versions.add(n.checkin());
- }
- // do random restores
- Random rand = new Random();
- for (int i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
- Version v = (Version) versions.get(rand.nextInt(versions.size()));
- n.restore(v, true);
- }
+ Node n = test.addNode("test");
+ n.addMixin(mixVersionable);
+ session.save();
+ // create 3 version
+ List versions = new ArrayList();
+ for (int i = 0; i < 3; i++) {
n.checkout();
- } finally {
- session.logout();
+ versions.add(n.checkin());
}
+ // do random restores
+ Random rand = new Random();
+ for (int i = 0; i < NUM_OPERATIONS / CONCURRENCY; i++) {
+ Version v = (Version) versions.get(rand.nextInt(versions.size()));
+ n.restore(v, true);
+ }
+ n.checkout();
}
}, CONCURRENCY);
- }
-
- //----------------------------< internal >----------------------------------
-
- private void runTask(Task task, int concurrency) throws RepositoryException {
- Thread[] threads = new Thread[concurrency];
- for (int i = 0; i < concurrency; i++) {
- Session s = helper.getSuperuserSession();
- Node test = s.getRootNode().addNode(testPath + "/node" + i);
- s.save();
- threads[i] = new Thread(new Executor(s, test, task));
- }
- for (int i = 0; i < threads.length; i++) {
- threads[i].start();
- }
- for (int i = 0; i < threads.length; i++) {
- try {
- threads[i].join();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
-
- public interface Task {
-
- public abstract void execute(Session session, Node test)
- throws RepositoryException;
- }
-
- private static class Executor implements Runnable {
-
- protected final Session session;
-
- protected final Node test;
-
- protected final Task task;
-
- public Executor(Session session, Node test, Task task) {
- this.session = session;
- this.test = test;
- this.task = task;
- }
-
- public void run() {
- try {
- task.execute(session, test);
- } catch (RepositoryException e) {
- e.printStackTrace();
- }
- }
}
}