/*
 * 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.performance;

import java.util.Random;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;

/**
 * Test case that traverses 10k unstructured nodes (100x100) while
 * 50 concurrent readers randomly access nodes from within this tree.
 */
public class ConcurrentReadTest extends AbstractTest {

    protected static final int NODE_COUNT = 100;

    private static final int READER_COUNT = 50;

    private Session session;

    protected Node root;

    public void beforeSuite() throws Exception {
        session = loginWriter();
        root = session.getRootNode().addNode("testroot", "nt:unstructured");
        for (int i = 0; i < NODE_COUNT; i++) {
            Node node = root.addNode("node" + i, "nt:unstructured");
            for (int j = 0; j < NODE_COUNT; j++) {
                node.addNode("node" + j, "nt:unstructured");
            }
            session.save();
        }

        for (int i = 0; i < READER_COUNT; i++) {
            addBackgroundJob(new Reader());
        }
    }

    private class Reader implements Runnable {

        private final Session session = loginReader();

        private final Random random = new Random();

        public void run() {
            try {
                int i = random.nextInt(NODE_COUNT);
                int j = random.nextInt(NODE_COUNT);
                session.getRootNode().getNode(
                        "testroot/node" + i + "/node" + j);
            } catch (RepositoryException e) {
                throw new RuntimeException(e);
            }
        }

    }

    public void runTest() throws Exception {
        NodeIterator i = root.getNodes();
        while (i.hasNext()) {
            NodeIterator j = i.nextNode().getNodes();
            while (j.hasNext()) {
                j.nextNode();
            }
        }
    }

    public void afterSuite() throws Exception {
        for (int i = 0; i < NODE_COUNT; i++) {
            root.getNode("node" + i).remove();
            session.save();
        }

        root.remove();
        session.save();
    }

}

@@ -893,39 +893,8 @@
 de;%0A
-import javax.jcr.NodeIterator;%0A
 impo
@@ -2456,203 +2456,104 @@
     
-NodeIterator i = root.getNodes();%0A        while (i.hasNext()) %7B%0A            NodeIterator j = i.nextNode().getNodes();%0A            while (j.hasNext()) %7B%0A                j.nextNode();%0A            %7D
+Reader reader = new Reader();%0A        for (int i = 0; i %3C 1000; i++) %7B%0A            reader.run();
 %0A   

Improve read/write concurrency