/*
* Hibernate Search, full-text search for your domain model
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.search.test.performance.scenario;
import static org.hibernate.search.test.performance.util.Util.runGarbageCollectorAndWait;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import org.hibernate.SessionFactory;
import org.hibernate.search.test.performance.task.AbstractTask;
import org.hibernate.search.testsupport.TestConstants;
/**
* @author Tomas Hradec
*/
public class TestContext {
private static final Boolean PERFORMANCE_ENABLED = TestConstants.arePerformanceTestsEnabled();
public static final boolean VERBOSE = PERFORMANCE_ENABLED;
public static final boolean MEASURE_MEMORY = PERFORMANCE_ENABLED;
public static final boolean MEASURE_TASK_TIME = PERFORMANCE_ENABLED;
public static final boolean ASSERT_QUERY_RESULTS = true;
public static final boolean CHECK_INDEX_STATE = true;
public static final int MAX_AUTHORS = 1000;
public static final int THREADS_COUNT = PERFORMANCE_ENABLED ? 20 : 2;
public final SessionFactory sf;
public final TestScenario scenario;
public final ExecutorService executor = Executors.newFixedThreadPool( THREADS_COUNT );
public final CountDownLatch startSignal = new CountDownLatch( 1 );
public final List<AbstractTask> tasks = new CopyOnWriteArrayList<AbstractTask>();
public final AtomicLong bookIdCounter = new AtomicLong( 0 );
public final AtomicLong authorIdCounter = new AtomicLong( 0 );
public final Random bookRandom = new Random();
public final Random authorRandom = new Random();
public final AtomicReference<RuntimeException> firstKnownError = new AtomicReference<>();
public long startTime;
public long stopTime;
public long freeMemory;
public long totalMemory;
public TestContext(TestScenario testScenario, SessionFactory sf) {
this.scenario = testScenario;
this.sf = sf;
if ( MEASURE_MEMORY ) {
runGarbageCollectorAndWait();
freeMemory = Runtime.getRuntime().freeMemory();
totalMemory = Runtime.getRuntime().totalMemory();
}
}
public long getRandomBookId() {
long bookId = bookIdCounter.get();
if ( bookId > 0 ) {
return Math.abs( bookRandom.nextLong() ) % bookId;
}
return 0;
}
public long getRandomAutorId() {
long authorId = authorIdCounter.get();
if ( authorId > 0 ) {
return Math.abs( authorRandom.nextLong() ) % authorIdCounter.get();
}
return 0;
}
public void startAndWait() {
try {
startTime = System.nanoTime();
startSignal.countDown();
executor.shutdown();
executor.awaitTermination( 1, TimeUnit.DAYS );
stopTime = System.nanoTime();
}
catch (InterruptedException e) {
throw new RuntimeException( e );
}
RuntimeException firstRuntimeError = getFirstRuntimeError();
if ( firstRuntimeError != null ) {
throw firstRuntimeError;
}
}
public void reportRuntimeException(RuntimeException e) {
//We only want to track the first exception:
//having any error is enough to invalidate the results,
//and if there are multiple it's likely that they are either
//repeated errors, or that others are caused by the first one.
firstKnownError.compareAndSet( null, e );
}
private RuntimeException getFirstRuntimeError() {
return firstKnownError.get();
}
}