/* * 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.LinkedList; import java.util.List; import javax.jcr.Credentials; import javax.jcr.Repository; import javax.jcr.RepositoryException; import javax.jcr.Session; /** * Abstract base class for individual performance benchmarks. */ public abstract class AbstractTest { private Repository repository; private Credentials credentials; private List<Session> sessions; private List<Thread> threads; private volatile boolean running; protected static int getScale(int def) { int scale = Integer.getInteger("scale", 0); if (scale == 0) { scale = def; } return scale; } /** * Prepares this performance benchmark. * * @param repository the repository to use * @param credentials credentials of a user with write access * @throws Exception if the benchmark can not be prepared */ public void setUp(Repository repository, Credentials credentials) throws Exception { this.repository = repository; this.credentials = credentials; this.sessions = new LinkedList<Session>(); this.threads = new LinkedList<Thread>(); this.running = true; beforeSuite(); } /** * Executes a single iteration of this test. * * @return number of milliseconds spent in this iteration * @throws Exception if an error occurs */ public long execute() throws Exception { beforeTest(); try { long start = System.currentTimeMillis(); runTest(); return System.currentTimeMillis() - start; } finally { afterTest(); } } /** * Cleans up after this performance benchmark. * * @throws Exception if the benchmark can not be cleaned up */ public void tearDown() throws Exception { this.running = false; for (Thread thread : threads) { thread.join(); } afterSuite(); for (Session session : sessions) { if (session.isLive()) { session.logout(); } } this.threads = null; this.sessions = null; this.credentials = null; this.repository = null; } /** * Run before any iterations of this test get executed. Subclasses can * override this method to set up static test content. * * @throws Exception if an error occurs */ protected void beforeSuite() throws Exception { } protected void beforeTest() throws Exception { } protected abstract void runTest() throws Exception; protected void afterTest() throws Exception { } /** * Run after all iterations of this test have been executed. Subclasses can * override this method to clean up static test content. * * @throws Exception if an error occurs */ protected void afterSuite() throws Exception { } protected void failOnRepositoryVersions(String... versions) throws RepositoryException { String repositoryVersion = repository.getDescriptor(Repository.REP_VERSION_DESC); for (String version : versions) { if (repositoryVersion.startsWith(version)) { throw new RepositoryException( "Unable to run " + getClass().getName() + " on repository version " + version); } } } protected Repository getRepository() { return repository; } protected Credentials getCredentials() { return credentials; } /** * Returns a new reader session that will be automatically closed once * all the iterations of this test have been executed. * * @return reader session */ protected Session loginReader() { try { Session session = repository.login(); sessions.add(session); return session; } catch (RepositoryException e) { throw new RuntimeException(e); } } /** * Returns a new writer session that will be automatically closed once * all the iterations of this test have been executed. * * @return writer session */ protected Session loginWriter() { try { Session session = repository.login(credentials); sessions.add(session); return session; } catch (RepositoryException e) { throw new RuntimeException(e); } } /** * Adds a background thread that repeatedly executes the given job * until all the iterations of this test have been executed. * * @param job background job */ protected void addBackgroundJob(final Runnable job) { Thread thread = new Thread() { @Override public void run() { while (running) { job.run(); } } }; thread.start(); threads.add(thread); } public String toString() { String name = getClass().getName(); return name.substring(name.lastIndexOf('.') + 1); } }