/*
* Hibernate OGM, Domain model persistence for NoSQL datastores
*
* 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.ogm.backendtck.id;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.ogm.dialect.spi.GridDialect;
import org.hibernate.ogm.dialect.spi.NextValueRequest;
import org.hibernate.ogm.jpa.impl.OgmEntityManagerFactory;
import org.hibernate.ogm.model.key.spi.IdSourceKey;
import org.hibernate.ogm.utils.jpa.OgmJpaTestCase;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.junit.Before;
/**
* @author Davide D'Alto
*/
public abstract class TestNextValueGeneration extends OgmJpaTestCase {
protected static boolean RUN_FULL_TESTS = Boolean.getBoolean( "ogm.runFullStressTests" );
protected static int PARALLEL_THREADS = Runtime.getRuntime().availableProcessors();
protected static int NUMBER_OF_TASKS = PARALLEL_THREADS * 3;
protected static int INCREASES_PER_TASK = RUN_FULL_TESTS ? 100_000 : 10;
protected GridDialect dialect;
@Before
public void setUp() {
ServiceRegistryImplementor serviceRegistry = getServiceRegistry();
dialect = serviceRegistry.getService( GridDialect.class );
}
protected IncrementJob[] runJobs(final NextValueRequest nextValueRequest) throws InterruptedException {
ExecutorService executorService = Executors.newWorkStealingPool( PARALLEL_THREADS );
IncrementJob[] runJobs = new IncrementJob[NUMBER_OF_TASKS];
System.out.println( "Starting stress tests on " + PARALLEL_THREADS + " Threads running " + NUMBER_OF_TASKS + " tasks" );
// Prepare all jobs (quite a lot of array allocations):
for ( int i = 0; i < NUMBER_OF_TASKS; i ++ ) {
runJobs[i] = new IncrementJob( dialect, nextValueRequest );
}
// Start them, pretty much in parallel (not really, but we have a lot so they will eventually run in parallel):
for ( int i = 0; i < NUMBER_OF_TASKS; i ++ ) {
executorService.execute( runJobs[i] );
}
executorService.shutdown();
executorService.awaitTermination( 10, TimeUnit.MINUTES );
return runJobs;
}
protected abstract IdSourceKey buildIdGeneratorKey(Class<?> entityClass, String sequenceName);
protected IdentifierGenerator generateKeyMetadata(Class<?> entityClass) {
OgmEntityManagerFactory emFactory = ( (OgmEntityManagerFactory) getFactory() );
SessionFactoryImplementor sessionFactory = emFactory.getSessionFactory();
IdentifierGenerator generator = sessionFactory.getIdentifierGenerator( entityClass.getName() );
return generator;
}
protected static class IncrementJob implements Runnable {
private final GridDialect dialect;
private final NextValueRequest nextValueRequest;
//GuardedBy synchronization on IncrementJob.this :
private final int[] generatedValues = new int[INCREASES_PER_TASK];
private IncrementJob(GridDialect dialect, NextValueRequest nextValueRequest) {
this.nextValueRequest = nextValueRequest;
this.dialect = dialect;
}
@Override
public void run() {
for ( int i = 0; i < INCREASES_PER_TASK; i++ ) {
recordValue( i, dialect.nextValue( nextValueRequest ) );
}
}
private synchronized void recordValue(int i, Number sequenceValue) {
generatedValues[i] = sequenceValue.intValue();
}
protected synchronized int[] retrieveAllGeneratedValues() {
return generatedValues;
}
}
}