/*
* 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.integration.daily;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
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.core.RepositoryImpl;
import org.apache.jackrabbit.core.config.RepositoryConfig;
public class ItemStateHierarchyManagerDeadlockTest extends TestCase {
public int g_numThreads = 30;
private int g_numRuns = 30;
private File repoDescriptor;
private File repoHome;
private RepositoryImpl repository;
public void setUp() throws IOException, RepositoryException {
File baseDir = new File(System.getProperty("basedir", "."));
File repoBaseDir = new File(baseDir, "target/ItemStateHierarchyManagerDeadlockTest");
FileUtils.deleteQuietly(repoBaseDir);
repoDescriptor = new File(repoBaseDir, "repository.xml");
repoHome = new File(repoBaseDir, "repository");
repoHome.mkdirs();
File repositoryDescriptor = new File(baseDir, "src/test/repository/repository.xml");
FileUtils.copyFile(repositoryDescriptor, repoDescriptor);
}
public void tearDown() throws IOException, InterruptedException {
FileUtils.deleteQuietly(repoHome.getParentFile());
}
private void startRepository() throws RepositoryException {
repository =
RepositoryImpl.create(RepositoryConfig.create(repoDescriptor.getAbsolutePath(), repoHome
.getAbsolutePath()));
}
private Session login() throws RepositoryException {
return repository.login(new SimpleCredentials("admin", "admin".toCharArray()), null);
}
private void stopRepository() throws RepositoryException {
repository.shutdown();
}
public void testConcurrentWritingSessions() throws Exception {
startRepository();
for (int i = 0; i < g_numRuns; i++) {
clearInvRootNode();
createInvRootNode();
runDeadlockTest();
try {
System.out.println("*** DONE FOR RUN " + (i + 1) + "/" + g_numRuns
+ ". SLEEP 1s before running next one");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
stopRepository();
}
public void clearInvRootNode() {
System.out.println("Clear test repository InventoryTest.");
Session session = null;
try {
session = login();
Node root = session.getRootNode();
try {
Node inv = root.getNode("InventoryTest");
inv.remove();
session.save();
} catch (PathNotFoundException pnfx) {
System.err.println(" The root node <InventoryTest> is not available.");
}
} catch (Exception e) {
System.err.println("Exception in clear test repository:" + e.getMessage());
e.printStackTrace();
} finally {
if (session != null)
session.logout();
}
}
public void createInvRootNode() throws RepositoryException {
Session session = null;
try {
session = login();
getInvRootNode(session);
} catch (Exception e) {
System.err.println("Exception in clear test repository:" + e.getMessage());
e.printStackTrace();
} finally {
if (session != null)
session.logout();
}
}
private Node getInvRootNode(Session session) throws RepositoryException {
Node root = session.getRootNode();
Node inventoryRoot;
try {
inventoryRoot = root.getNode("InventoryTest");
} catch (PathNotFoundException pnfx) {
System.err.println(" The root node <InventoryTest> is not available. So creating new root Node.");
inventoryRoot = root.addNode("InventoryTest");
session.save();
}
return inventoryRoot;
}
public void createNodesUnderInvRootNode() {
System.out.println("Start createNodesUnderInvRootNode ");
Session session = null;
try {
session = login();
Node inventoryRoot = getInvRootNode(session);
for (int num = 0; num < 3; num++) {
Node current = inventoryRoot.addNode("Test" + num + "_" + System.currentTimeMillis());
current.setProperty("profondeur", 123);
current.setProperty("tree", "1");
current.setProperty("clientid", 1);
current.setProperty("propId", System.currentTimeMillis());
current.setProperty("name", "Node " + System.currentTimeMillis());
current.setProperty("address", "1.22.3.3");
}
session.save();
System.out.println("End createNodesUnderInvRootNode ");
} catch (Exception e) {
System.err.println("Exception in createNodesUnderInvRootNode:" + e.getMessage());
} finally {
if (session != null)
session.logout();
}
}
public void retrieveNodesUnderInvRootNode() {
System.out.println("Start retrieveNodesUnderInvRootNode ");
Session session = null;
try {
session = login();
// start from the bottom of the tree and move up
Node inventoryRoot = getInvRootNode(session);
NodeIterator nodes = inventoryRoot.getNodes();
while (nodes.hasNext()) {
Node node = nodes.nextNode();
// System.out.println(" Node: " + node.getName());
PropertyIterator properties = node.getProperties();
while (properties.hasNext()) {
Property prop = properties.nextProperty();
// System.out.println(" Prop: " + prop.getName() + " - " + prop.getString());
}
}
session.save();
System.out.println("End retrieveNodesUnderInvRootNode");
} catch (Exception e) {
System.err.println("Exception in retrieveNodesUnderInvRootNode:" + e.getMessage());
} finally {
if (session != null)
session.logout();
}
}
public void removeNodesUnderInvRootNode() {
System.out.println("Start removeNodesUnderInvRootNode ");
Session session = null;
try {
session = login();
// start from the bottom of the tree and move up
Node inventoryRoot = getInvRootNode(session);
NodeIterator nodes = inventoryRoot.getNodes();
int num = 0;
while (nodes.hasNext() && num < 3) {
Node node = nodes.nextNode();
node.remove();
num++;
}
session.save();
System.out.println("End removeNodesUnderInvRootNode");
} catch (Exception e) {
System.err.println("Exception in removeNodesUnderInvRootNode:" + e.getMessage());
} finally {
if (session != null)
session.logout();
}
}
public void runDeadlockTest() {
long start = System.currentTimeMillis();
List threads = new ArrayList();
for (int instanceIndex = 0; instanceIndex < g_numThreads; instanceIndex++) {
final int index = instanceIndex;
Thread t = new Thread(new Runnable() {
public void run() {
for (int rounds = 0; rounds < 2; rounds++) {
if (index % 2 == 0) {
removeNodesUnderInvRootNode();
}
createNodesUnderInvRootNode();
retrieveNodesUnderInvRootNode();
if (index % 2 != 0) {
removeNodesUnderInvRootNode();
}
}
}
});
threads.add(t);
t.start();
}
try {
Iterator it = threads.listIterator();
while (it.hasNext()) {
Thread t = (Thread) it.next();
t.join();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Duration for run: " + (System.currentTimeMillis() - start) / 1000 + "s");
}
}