You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by mr...@apache.org on 2013/07/09 14:25:15 UTC
svn commit: r1501218 -
/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentFileOperationsTest.java
Author: mreutegg
Date: Tue Jul 9 12:25:15 2013
New Revision: 1501218
URL: http://svn.apache.org/r1501218
Log:
OAK-893: MongoMK may fail with MicroKernelException under concurrent commits
- Test (currently ignored when running with MongoMK)
Added:
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentFileOperationsTest.java (with props)
Added: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentFileOperationsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentFileOperationsTest.java?rev=1501218&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentFileOperationsTest.java (added)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentFileOperationsTest.java Tue Jul 9 12:25:15 2013
@@ -0,0 +1,190 @@
+/*
+ * 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.oak.jcr;
+
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.commons.JcrUtils;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+/**
+ * File related write operations on the repository.
+ */
+public class ConcurrentFileOperationsTest extends AbstractRepositoryTest {
+
+ private static final Logger log = LoggerFactory.getLogger(ConcurrentFileOperationsTest.class);
+ private static final int NUM_WRITERS = 10;
+ private static final byte[] DATA = new byte[8];
+
+ static {
+ new Random(0).nextBytes(DATA);
+ }
+
+ private Session session;
+ private Node testRootNode;
+
+ public ConcurrentFileOperationsTest(NodeStoreFixture fixture) {
+ super(fixture);
+ }
+
+ @Before
+ public void setup() throws RepositoryException {
+ session = getAdminSession();
+ testRootNode = JcrUtils.getOrAddNode(session.getRootNode(),
+ "test-node", "nt:unstructured");
+ session.save();
+ }
+
+ /**
+ * Multiple threads create and rename files.
+ */
+ @Test
+ public void concurrent() throws Exception {
+ // OAK-893
+ assumeTrue(fixture != NodeStoreFixture.MONGO_MK);
+ List<Session> sessions = new ArrayList<Session>();
+ for (int i = 0; i < NUM_WRITERS; i++) {
+ sessions.add(createAdminSession());
+ testRootNode.addNode("session-" + i, "nt:unstructured");
+ }
+ addFile(testRootNode, "dummy");
+ session.save();
+ final Map<String, Exception> exceptions = Collections.synchronizedMap(
+ new HashMap<String, Exception>());
+ List<Thread> writers = new ArrayList<Thread>();
+ for (int i = 0; i < sessions.size(); i++) {
+ final Session s = sessions.get(i);
+ final String path = testRootNode.getPath() + "/session-" + i;
+ writers.add(new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ s.refresh(false);
+ Node n = s.getNode(path);
+ for (int i = 0; i < 10; i++) {
+ String tmpFile = "file-" + i + ".tmp";
+ // create
+ addFile(n, tmpFile);
+ s.save();
+ String srcPath = n.getPath() + "/" + tmpFile;
+ String destPath = n.getPath() + "/file-" + i + ".bin";
+ // rename
+ s.move(srcPath, destPath);
+ s.save();
+ }
+
+ } catch (RepositoryException e) {
+ exceptions.put(path, e);
+ }
+ }
+ }));
+ }
+ for (Thread t : writers) {
+ t.start();
+ }
+ for (Thread t : writers) {
+ t.join();
+ }
+ for (Session s : sessions) {
+ s.logout();
+ }
+ for (Map.Entry<String, Exception> entry : exceptions.entrySet()) {
+ log.info("Worker (" + entry.getKey() + ") failed with exception: " + entry.getValue().toString());
+ throw entry.getValue();
+ }
+ }
+
+ @Test
+ public void interleavingOperations1() throws Exception {
+ Node folder1 = testRootNode.addNode("folder1", "nt:unstructured");
+ Node folder2 = testRootNode.addNode("folder2", "nt:unstructured");
+ Node file1 = addFile(session.getNode(folder1.getPath()), "file1.tmp");
+ Node file2 = addFile(session.getNode(folder2.getPath()), "file2.tmp");
+ session.save();
+
+ Session s1 = createAdminSession();
+ Session s2 = createAdminSession();
+ try {
+ rename(s1.getNode(file1.getPath()), "file1.bin");
+ rename(s2.getNode(file2.getPath()), "file2.bin");
+ s1.save();
+ s2.save();
+ } finally {
+ s1.logout();
+ s2.logout();
+ }
+ }
+
+ @Test
+ public void interleavingOperations2() throws Exception {
+ Node folder1 = testRootNode.addNode("folder1", "nt:unstructured");
+ Node folder2 = testRootNode.addNode("folder2", "nt:unstructured");
+ addFile(testRootNode, "dummy");
+ session.save();
+
+ Session s1 = createAdminSession();
+ Session s2 = createAdminSession();
+ try {
+ Node file1 = addFile(s1.getNode(folder1.getPath()), "file1.tmp");
+ Node file2 = addFile(s2.getNode(folder2.getPath()), "file2.tmp");
+ s1.save();
+ s2.save();
+ rename(file1, "file1.bin");
+ rename(file2, "file2.bin");
+ s1.save();
+ s2.save();
+ } finally {
+ s1.logout();
+ s2.logout();
+ }
+ session.refresh(false);
+ assertTrue(session.nodeExists(folder1.getPath() + "/file1.bin"));
+ assertFalse(session.nodeExists(folder1.getPath() + "/file1.tmp"));
+ assertTrue(session.nodeExists(folder2.getPath() + "/file2.bin"));
+ assertFalse(session.nodeExists(folder2.getPath() + "/file2.tmp"));
+ }
+
+ private static Node addFile(Node parent, String name)
+ throws RepositoryException {
+ return JcrUtils.putFile(parent, name,
+ "application/octet-stream", new ByteArrayInputStream(DATA));
+ }
+
+ private static void rename(Node node, String name)
+ throws RepositoryException {
+ String destPath = PathUtils.getParentPath(node.getPath()) + "/" + name;
+ node.getSession().move(node.getPath(), destPath);
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentFileOperationsTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentFileOperationsTest.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL