[hibernate-commits] Hibernate SVN: r19477 - in core/branches/Branch_3_5: core/src/test/java/org/hibernate/id and 2 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed May 12 11:13:04 EDT 2010


Author: steve.ebersole at jboss.com
Date: 2010-05-12 11:13:03 -0400 (Wed, 12 May 2010)
New Revision: 19477

Added:
   core/branches/Branch_3_5/core/src/test/java/org/hibernate/id/enhanced/
   core/branches/Branch_3_5/core/src/test/java/org/hibernate/id/enhanced/OptimizerUnitTest.java
   core/branches/Branch_3_5/core/src/test/java/org/hibernate/id/enhanced/SequenceStyleConfigUnitTest.java
Removed:
   core/branches/Branch_3_5/testsuite/src/test/java/org/hibernate/test/idgen/enhanced/OptimizerUnitTest.java
   core/branches/Branch_3_5/testsuite/src/test/java/org/hibernate/test/idgen/enhanced/SequenceStyleConfigUnitTest.java
Modified:
   core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/OptimizerFactory.java
   core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java
   core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java
Log:
HHH-5217 - Minimize double sequence value reads in PooledOptimizer

Modified: core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/OptimizerFactory.java
===================================================================
--- core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/OptimizerFactory.java	2010-05-12 14:46:34 UTC (rev 19476)
+++ core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/OptimizerFactory.java	2010-05-12 15:13:03 UTC (rev 19477)
@@ -44,10 +44,40 @@
 
 	public static final String NONE = "none";
 	public static final String HILO = "hilo";
+	public static final String LEGACY_HILO = "legacy-hilo";
 	public static final String POOL = "pooled";
 
 	private static Class[] CTOR_SIG = new Class[] { Class.class, int.class };
 
+	/**
+	 * Marker interface for optimizer which wish to know the user-specified initial value.
+	 * <p/>
+	 * Used instead of constructor injection since that is already a public understanding and
+	 * because not all optimizers care.
+	 */
+	public static interface InitialValueAwareOptimizer {
+		/**
+		 * Reports the user specified initial value to the optimizer.
+		 * <p/>
+		 * <tt>-1</tt> is used to indicate that the user did not specify.
+		 *
+		 * @param initialValue The initial value specified by the user, or <tt>-1</tt> to indicate that the
+		 * user did not specify.
+		 */
+		public void injectInitialValue(long initialValue);
+	}
+
+	/**
+	 * Builds an optimizer
+	 *
+	 * @param type The optimizer type, either a short-hand name or the {@link Optimizer} class name.
+	 * @param returnClass The generated value java type
+	 * @param incrementSize The increment size.
+	 *
+	 * @return The built optimizer
+	 *
+	 * @deprecated Use {@link #buildOptimizer(String, Class, int, long)} instead
+	 */
 	public static Optimizer buildOptimizer(String type, Class returnClass, int incrementSize) {
 		String optimizerClassName;
 		if ( NONE.equals( type ) ) {
@@ -56,6 +86,9 @@
 		else if ( HILO.equals( type ) ) {
 			optimizerClassName = HiLoOptimizer.class.getName();
 		}
+		else if ( LEGACY_HILO.equals( type ) ) {
+			optimizerClassName = LegacyHiLoAlgorithmOptimizer.class.getName();
+		}
 		else if ( POOL.equals( type ) ) {
 			optimizerClassName = PooledOptimizer.class.getName();
 		}
@@ -76,7 +109,27 @@
 		return new NoopOptimizer( returnClass, incrementSize );
 	}
 
+
 	/**
+	 * Builds an optimizer
+	 *
+	 * @param type The optimizer type, either a short-hand name or the {@link Optimizer} class name.
+	 * @param returnClass The generated value java type
+	 * @param incrementSize The increment size.
+	 * @param explicitInitialValue The user supplied initial-value (-1 indicates the user did not specify).
+	 *
+	 * @return The built optimizer
+	 */
+	public static Optimizer buildOptimizer(String type, Class returnClass, int incrementSize, long explicitInitialValue) {
+		//noinspection deprecation
+		final Optimizer optimizer = buildOptimizer( type, returnClass, incrementSize );
+		if ( InitialValueAwareOptimizer.class.isInstance( optimizer ) ) {
+			( (InitialValueAwareOptimizer) optimizer ).injectInitialValue( explicitInitialValue );
+		}
+		return optimizer;
+	}
+
+	/**
 	 * Common support for optimizer implementations.
 	 */
 	public static abstract class OptimizerSupport implements Optimizer {
@@ -334,9 +387,10 @@
 	 * {@link HiLoOptimizer} except that here the bucket ranges are actually
 	 * encoded into the database structures.
 	 */
-	public static class PooledOptimizer extends OptimizerSupport {
+	public static class PooledOptimizer extends OptimizerSupport implements InitialValueAwareOptimizer {
 		private IntegralDataTypeHolder hiValue;
 		private IntegralDataTypeHolder value;
+		private long initialValue = -1;
 
 		public PooledOptimizer(Class returnClass, int incrementSize) {
 			super( returnClass, incrementSize );
@@ -361,7 +415,14 @@
 					// we are using a sequence...
 					log.info( "pooled optimizer source reported [" + value + "] as the initial value; use of 1 or greater highly recommended" );
 				}
-				hiValue = callback.getNextValue();
+				if ( ( initialValue == -1 && value.lt( incrementSize ) ) || value.eq( initialValue ) ) {
+					// the call to obtain next-value just gave us the initialValue
+					hiValue = callback.getNextValue();
+				}
+				else {
+					hiValue = value;
+					value = hiValue.copy().subtract( incrementSize );
+				}
 			}
 			else if ( ! hiValue.gt( value ) ) {
 				hiValue = callback.getNextValue();
@@ -394,5 +455,12 @@
 		public IntegralDataTypeHolder getLastValue() {
 			return value.copy().decrement();
 		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		public void injectInitialValue(long initialValue) {
+			this.initialValue = initialValue;
+		}
 	}
 }

Modified: core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java
===================================================================
--- core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java	2010-05-12 14:46:34 UTC (rev 19476)
+++ core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java	2010-05-12 15:13:03 UTC (rev 19477)
@@ -187,8 +187,12 @@
 				initialValue,
 				incrementSize
 		);
-
-		this.optimizer = OptimizerFactory.buildOptimizer( optimizationStrategy, identifierType.getReturnedClass(), incrementSize );
+		this.optimizer = OptimizerFactory.buildOptimizer(
+				optimizationStrategy,
+				identifierType.getReturnedClass(),
+				incrementSize,
+				PropertiesHelper.getInt( INITIAL_PARAM, params, -1 )
+		);
 		this.databaseStructure.prepare( optimizer );
 	}
 
@@ -305,7 +309,9 @@
 	 * @param forceTableUse Should a table be used even if the dialect supports sequences?
 	 * @param sequenceName The name to use for the sequence or table.
 	 * @param initialValue The initial value.
-	 * @param incrementSize the increment size to use (after any adjustments).       @return The db structure representation
+	 * @param incrementSize the increment size to use (after any adjustments).
+	 *
+	 * @return An abstraction for the actual database structure in use (table vs. sequence).
 	 */
 	protected DatabaseStructure buildDatabaseStructure(
 			Type type,

Modified: core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java
===================================================================
--- core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java	2010-05-12 14:46:34 UTC (rev 19476)
+++ core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java	2010-05-12 15:13:03 UTC (rev 19477)
@@ -305,7 +305,12 @@
 
 		String defOptStrategy = incrementSize <= 1 ? OptimizerFactory.NONE : OptimizerFactory.POOL;
 		String optimizationStrategy = PropertiesHelper.getString( OPT_PARAM, params, defOptStrategy );
-		optimizer = OptimizerFactory.buildOptimizer( optimizationStrategy, identifierType.getReturnedClass(), incrementSize );
+		optimizer = OptimizerFactory.buildOptimizer(
+				optimizationStrategy,
+				identifierType.getReturnedClass(),
+				incrementSize,
+				PropertiesHelper.getInt( INITIAL_PARAM, params, -1 )
+		);
 	}
 
 	/**
@@ -430,8 +435,8 @@
 		String query = "select " + StringHelper.qualify( alias, valueColumnName ) +
 				" from " + tableName + ' ' + alias +
 				" where " + StringHelper.qualify( alias, segmentColumnName ) + "=?";
-		LockOptions lockOptions = new LockOptions(LockMode.UPGRADE);
-		lockOptions.setAliasSpecificLockMode( alias, LockMode.UPGRADE );
+		LockOptions lockOptions = new LockOptions( LockMode.PESSIMISTIC_WRITE );
+		lockOptions.setAliasSpecificLockMode( alias, LockMode.PESSIMISTIC_WRITE );
 		Map updateTargetColumnsMap = Collections.singletonMap( alias, new String[] { valueColumnName } );
 		return dialect.applyLocksToSql( query, lockOptions, updateTargetColumnsMap );
 	}

Copied: core/branches/Branch_3_5/core/src/test/java/org/hibernate/id/enhanced/OptimizerUnitTest.java (from rev 19465, core/branches/Branch_3_5/testsuite/src/test/java/org/hibernate/test/idgen/enhanced/OptimizerUnitTest.java)
===================================================================
--- core/branches/Branch_3_5/core/src/test/java/org/hibernate/id/enhanced/OptimizerUnitTest.java	                        (rev 0)
+++ core/branches/Branch_3_5/core/src/test/java/org/hibernate/id/enhanced/OptimizerUnitTest.java	2010-05-12 15:13:03 UTC (rev 19477)
@@ -0,0 +1,186 @@
+package org.hibernate.id.enhanced;
+
+import junit.framework.Assert;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.hibernate.id.IdentifierGeneratorHelper;
+import org.hibernate.id.IntegralDataTypeHolder;
+
+/**
+ * {@inheritDoc}
+ *
+ * @author Steve Ebersole
+ */
+public class OptimizerUnitTest extends TestCase {
+	public OptimizerUnitTest(String string) {
+		super( string );
+	}
+
+	public static Test suite() {
+		return new TestSuite( OptimizerUnitTest.class );
+	}
+
+	public void testBasicNoOptimizerUsage() {
+		// test historic sequence behavior, where the initial values start at 1...
+		SourceMock sequence = new SourceMock( 1 );
+		Optimizer optimizer = OptimizerFactory.buildOptimizer( OptimizerFactory.NONE, Long.class, 1 );
+		for ( int i = 1; i < 11; i++ ) {
+			final Long next = ( Long ) optimizer.generate( sequence );
+			Assert.assertEquals( i, next.intValue() );
+		}
+		Assert.assertEquals( 10, sequence.getTimesCalled() );
+		Assert.assertEquals( 10, sequence.getCurrentValue() );
+
+		// test historic table behavior, where the initial values started at 0 (we now force 1 to be the first used id value)
+		sequence = new SourceMock( 0 );
+		optimizer = OptimizerFactory.buildOptimizer( OptimizerFactory.NONE, Long.class, 1 );
+		for ( int i = 1; i < 11; i++ ) {
+			final Long next = ( Long ) optimizer.generate( sequence );
+			Assert.assertEquals( i, next.intValue() );
+		}
+		Assert.assertEquals( 11, sequence.getTimesCalled() ); // an extra time to get to 1 initially
+		Assert.assertEquals( 10, sequence.getCurrentValue() );
+	}
+
+	public void testBasicHiLoOptimizerUsage() {
+		int increment = 10;
+		Long next;
+
+		// test historic sequence behavior, where the initial values start at 1...
+		SourceMock sequence = new SourceMock( 1 );
+		Optimizer optimizer = OptimizerFactory.buildOptimizer( OptimizerFactory.HILO, Long.class, increment );
+		for ( int i = 1; i <= increment; i++ ) {
+			next = ( Long ) optimizer.generate( sequence );
+			Assert.assertEquals( i, next.intValue() );
+		}
+		Assert.assertEquals( 1, sequence.getTimesCalled() ); // once to initialze state
+		Assert.assertEquals( 1, sequence.getCurrentValue() );
+		// force a "clock over"
+		next = ( Long ) optimizer.generate( sequence );
+		Assert.assertEquals( 11, next.intValue() );
+		Assert.assertEquals( 2, sequence.getTimesCalled() );
+		Assert.assertEquals( 2, sequence.getCurrentValue() );
+
+		// test historic table behavior, where the initial values started at 0 (we now force 1 to be the first used id value)
+		sequence = new SourceMock( 0 );
+		optimizer = OptimizerFactory.buildOptimizer( OptimizerFactory.HILO, Long.class, increment );
+		for ( int i = 1; i <= increment; i++ ) {
+			next = ( Long ) optimizer.generate( sequence );
+			Assert.assertEquals( i, next.intValue() );
+		}
+		Assert.assertEquals( 2, sequence.getTimesCalled() ); // here have have an extra call to get to 1 initially
+		Assert.assertEquals( 1, sequence.getCurrentValue() );
+		// force a "clock over"
+		next = ( Long ) optimizer.generate( sequence );
+		Assert.assertEquals( 11, next.intValue() );
+		Assert.assertEquals( 3, sequence.getTimesCalled() );
+		Assert.assertEquals( 2, sequence.getCurrentValue() );
+	}
+
+	public void testBasicPooledOptimizerUsage() {
+		Long next;
+		// test historic sequence behavior, where the initial values start at 1...
+		SourceMock sequence = new SourceMock( 1, 10 );
+		Optimizer optimizer = OptimizerFactory.buildOptimizer( OptimizerFactory.POOL, Long.class, 10 );
+		for ( int i = 1; i < 11; i++ ) {
+			next = ( Long ) optimizer.generate( sequence );
+			Assert.assertEquals( i, next.intValue() );
+		}
+		Assert.assertEquals( 2, sequence.getTimesCalled() ); // twice to initialize state
+		Assert.assertEquals( 11, sequence.getCurrentValue() );
+		// force a "clock over"
+		next = ( Long ) optimizer.generate( sequence );
+		Assert.assertEquals( 11, next.intValue() );
+		Assert.assertEquals( 3, sequence.getTimesCalled() );
+		Assert.assertEquals( 21, sequence.getCurrentValue() );
+	}
+
+	public void testSubsequentPooledOptimizerUsage() {
+		// test the pooled optimizer in situation where the sequence is already beyond its initial value on init.
+		//		cheat by telling the sequence to start with 1000
+		final SourceMock sequence = new SourceMock( 1000, 3, 5 );
+		//		but tell the optimizer the start-with is 1
+		final Optimizer optimizer = OptimizerFactory.buildOptimizer( OptimizerFactory.POOL, Long.class, 3, 1 );
+
+		assertEquals( 5, sequence.getTimesCalled() );
+		assertEquals( 1000, sequence.getCurrentValue() );
+
+		Long next = (Long) optimizer.generate( sequence );
+		assertEquals( 1000, next.intValue() );
+		assertEquals( (5+1), sequence.getTimesCalled() );
+		assertEquals( (1000+3), sequence.getCurrentValue() );
+
+		next = (Long) optimizer.generate( sequence );
+		assertEquals( 1001, next.intValue() );
+		assertEquals( (5+1), sequence.getTimesCalled() );
+		assertEquals( (1000+3), sequence.getCurrentValue() );
+
+		next = (Long) optimizer.generate( sequence );
+		assertEquals( 1002, next.intValue() );
+		assertEquals( (5+1), sequence.getTimesCalled() );
+		assertEquals( (1000+3), sequence.getCurrentValue() );
+
+		// force a "clock over"
+		next = (Long) optimizer.generate( sequence );
+		assertEquals( 1003, next.intValue() );
+		assertEquals( (5+2), sequence.getTimesCalled() );
+		assertEquals( (1000+6), sequence.getCurrentValue() );
+	}
+
+	private static class SourceMock implements AccessCallback {
+		private IdentifierGeneratorHelper.BasicHolder value = new IdentifierGeneratorHelper.BasicHolder( Long.class );
+		private long initialValue;
+		private int increment;
+		private int timesCalled = 0;
+
+		public SourceMock(long initialValue) {
+			this( initialValue, 1 );
+		}
+
+		public SourceMock(long initialValue, int increment) {
+			this( initialValue, increment, 0 );
+		}
+
+		public SourceMock(long initialValue, int increment, int timesCalled) {
+			this.increment = increment;
+			this.timesCalled = timesCalled;
+			if ( timesCalled != 0 ) {
+				this.value.initialize( initialValue );
+				this.initialValue = 1;
+			}
+			else {
+				this.initialValue = initialValue;
+			}
+		}
+
+		public IntegralDataTypeHolder getNextValue() {
+			try {
+				if ( timesCalled == 0 ) {
+					initValue();
+					return value.copy();
+				}
+				else {
+					return value.add( increment ).copy();
+				}
+			}
+			finally {
+				timesCalled++;
+			}
+		}
+
+		private void initValue() {
+			this.value.initialize( initialValue );
+		}
+
+		public int getTimesCalled() {
+			return timesCalled;
+		}
+
+		public long getCurrentValue() {
+			return value == null ? -1 : value.getActualLongValue();
+		}
+	}
+
+}

Copied: core/branches/Branch_3_5/core/src/test/java/org/hibernate/id/enhanced/SequenceStyleConfigUnitTest.java (from rev 19465, core/branches/Branch_3_5/testsuite/src/test/java/org/hibernate/test/idgen/enhanced/SequenceStyleConfigUnitTest.java)
===================================================================
--- core/branches/Branch_3_5/core/src/test/java/org/hibernate/id/enhanced/SequenceStyleConfigUnitTest.java	                        (rev 0)
+++ core/branches/Branch_3_5/core/src/test/java/org/hibernate/id/enhanced/SequenceStyleConfigUnitTest.java	2010-05-12 15:13:03 UTC (rev 19477)
@@ -0,0 +1,208 @@
+package org.hibernate.id.enhanced;
+
+import java.util.Properties;
+
+import junit.framework.Assert;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.hibernate.Hibernate;
+import org.hibernate.MappingException;
+import org.hibernate.cfg.NamingStrategy;
+import org.hibernate.cfg.ObjectNameNormalizer;
+import org.hibernate.dialect.Dialect;
+import org.hibernate.id.PersistentIdentifierGenerator;
+
+/**
+ * Tests that SequenceStyleGenerator configures itself as expected
+ * in various scenarios
+ *
+ * @author Steve Ebersole
+ * @noinspection deprecation
+ */
+public class SequenceStyleConfigUnitTest extends TestCase {
+	public SequenceStyleConfigUnitTest(String string) {
+		super( string );
+	}
+
+	public static Test suite() {
+		return new TestSuite( SequenceStyleConfigUnitTest.class );
+	}
+
+
+	private void assertClassAssignability(Class expected, Class actual) {
+		if ( ! expected.isAssignableFrom( actual ) ) {
+			fail( "Actual type [" + actual.getName() + "] is not assignable to expected type [" + expected.getName() + "]" );
+		}
+	}
+
+	/**
+	 * Test all params defaulted with a dialect supporting sequences
+	 */
+	public void testDefaultedSequenceBackedConfiguration() {
+		Dialect dialect = new SequenceDialect();
+		Properties props = buildGeneratorPropertiesBase();
+		SequenceStyleGenerator generator = new SequenceStyleGenerator();
+		generator.configure( Hibernate.LONG, props, dialect );
+
+		assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() );
+		assertClassAssignability( OptimizerFactory.NoopOptimizer.class, generator.getOptimizer().getClass() );
+		Assert.assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() );
+	}
+
+	private Properties buildGeneratorPropertiesBase() {
+		Properties props = new Properties();
+		props.put(
+				PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER,
+				new ObjectNameNormalizer() {
+					protected boolean isUseQuotedIdentifiersGlobally() {
+						return false;
+					}
+
+					protected NamingStrategy getNamingStrategy() {
+						return null;
+					}
+				}
+		);
+		return props;
+	}
+
+	/**
+	 * Test all params defaulted with a dialect which does not support sequences
+	 */
+	public void testDefaultedTableBackedConfiguration() {
+		Dialect dialect = new TableDialect();
+		Properties props = buildGeneratorPropertiesBase();
+		SequenceStyleGenerator generator = new SequenceStyleGenerator();
+		generator.configure( Hibernate.LONG, props, dialect );
+
+		assertClassAssignability( TableStructure.class, generator.getDatabaseStructure().getClass() );
+		assertClassAssignability( OptimizerFactory.NoopOptimizer.class, generator.getOptimizer().getClass() );
+		Assert.assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() );
+	}
+
+	/**
+	 * Test default optimizer selection for sequence backed generators
+	 * based on the configured increment size; both in the case of the
+	 * dialect supporting pooled sequences (pooled) and not (hilo)
+	 */
+	public void testDefaultOptimizerBasedOnIncrementBackedBySequence() {
+		Properties props = buildGeneratorPropertiesBase();
+		props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "10" );
+
+		// for dialects which do not support pooled sequences, we default to pooled+table
+		Dialect dialect = new SequenceDialect();
+		SequenceStyleGenerator generator = new SequenceStyleGenerator();
+		generator.configure( Hibernate.LONG, props, dialect );
+		assertClassAssignability( TableStructure.class, generator.getDatabaseStructure().getClass() );
+		assertClassAssignability( OptimizerFactory.PooledOptimizer.class, generator.getOptimizer().getClass() );
+		Assert.assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() );
+
+		// for dialects which do support pooled sequences, we default to pooled+sequence
+		dialect = new PooledSequenceDialect();
+		generator = new SequenceStyleGenerator();
+		generator.configure( Hibernate.LONG, props, dialect );
+		assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() );
+		assertClassAssignability( OptimizerFactory.PooledOptimizer.class, generator.getOptimizer().getClass() );
+		Assert.assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() );
+	}
+
+	/**
+	 * Test default optimizer selection for table backed generators
+	 * based on the configured increment size.  Here we always prefer
+	 * pooled.
+	 */
+	public void testDefaultOptimizerBasedOnIncrementBackedByTable() {
+		Properties props = buildGeneratorPropertiesBase();
+		props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "10" );
+		Dialect dialect = new TableDialect();
+		SequenceStyleGenerator generator = new SequenceStyleGenerator();
+		generator.configure( Hibernate.LONG, props, dialect );
+		assertClassAssignability( TableStructure.class, generator.getDatabaseStructure().getClass() );
+		assertClassAssignability( OptimizerFactory.PooledOptimizer.class, generator.getOptimizer().getClass() );
+		Assert.assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() );
+	}
+
+	/**
+	 * Test forcing of table as backing strucuture with dialect supporting sequences
+	 */
+	public void testForceTableUse() {
+		Dialect dialect = new SequenceDialect();
+		Properties props = buildGeneratorPropertiesBase();
+		props.setProperty( SequenceStyleGenerator.FORCE_TBL_PARAM, "true" );
+		SequenceStyleGenerator generator = new SequenceStyleGenerator();
+		generator.configure( Hibernate.LONG, props, dialect );
+		assertClassAssignability( TableStructure.class, generator.getDatabaseStructure().getClass() );
+		assertClassAssignability( OptimizerFactory.NoopOptimizer.class, generator.getOptimizer().getClass() );
+		Assert.assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() );
+	}
+
+	/**
+	 * Test explicitly specifying both optimizer and increment
+	 */
+	public void testExplicitOptimizerWithExplicitIncrementSize() {
+		// with sequence ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+		final Dialect dialect = new SequenceDialect();
+
+		// optimizer=none w/ increment > 1 => should honor optimizer
+		Properties props = buildGeneratorPropertiesBase();
+		props.setProperty( SequenceStyleGenerator.OPT_PARAM, OptimizerFactory.NONE );
+		props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "20" );
+		SequenceStyleGenerator generator = new SequenceStyleGenerator();
+		generator.configure( Hibernate.LONG, props, dialect );
+		assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() );
+		assertClassAssignability( OptimizerFactory.NoopOptimizer.class, generator.getOptimizer().getClass() );
+		Assert.assertEquals( 1, generator.getOptimizer().getIncrementSize() );
+		Assert.assertEquals( 1, generator.getDatabaseStructure().getIncrementSize() );
+
+		// optimizer=hilo w/ increment > 1 => hilo
+		props = buildGeneratorPropertiesBase();
+		props.setProperty( SequenceStyleGenerator.OPT_PARAM, OptimizerFactory.HILO );
+		props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "20" );
+		generator = new SequenceStyleGenerator();
+		generator.configure( Hibernate.LONG, props, dialect );
+		assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() );
+		assertClassAssignability( OptimizerFactory.HiLoOptimizer.class, generator.getOptimizer().getClass() );
+		Assert.assertEquals( 20, generator.getOptimizer().getIncrementSize() );
+		Assert.assertEquals( 20, generator.getDatabaseStructure().getIncrementSize() );
+
+		// optimizer=pooled w/ increment > 1 => hilo
+		props = buildGeneratorPropertiesBase();
+		props.setProperty( SequenceStyleGenerator.OPT_PARAM, OptimizerFactory.POOL );
+		props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "20" );
+		generator = new SequenceStyleGenerator();
+		generator.configure( Hibernate.LONG, props, dialect );
+		// because the dialect reports to not support pooled seqyences, the expectation is that we will
+		// use a table for the backing structure...
+		assertClassAssignability( TableStructure.class, generator.getDatabaseStructure().getClass() );
+		assertClassAssignability( OptimizerFactory.PooledOptimizer.class, generator.getOptimizer().getClass() );
+		Assert.assertEquals( 20, generator.getOptimizer().getIncrementSize() );
+		Assert.assertEquals( 20, generator.getDatabaseStructure().getIncrementSize() );
+
+	}
+
+	private static class TableDialect extends Dialect {
+		public boolean supportsSequences() {
+			return false;
+		}
+	}
+
+	private static class SequenceDialect extends Dialect {
+		public boolean supportsSequences() {
+			return true;
+		}
+		public boolean supportsPooledSequences() {
+			return false;
+		}
+		public String getSequenceNextValString(String sequenceName) throws MappingException {
+			return "";
+		}
+	}
+
+	private static class PooledSequenceDialect extends SequenceDialect {
+		public boolean supportsPooledSequences() {
+			return true;
+		}
+	}
+}

Deleted: core/branches/Branch_3_5/testsuite/src/test/java/org/hibernate/test/idgen/enhanced/OptimizerUnitTest.java
===================================================================
--- core/branches/Branch_3_5/testsuite/src/test/java/org/hibernate/test/idgen/enhanced/OptimizerUnitTest.java	2010-05-12 14:46:34 UTC (rev 19476)
+++ core/branches/Branch_3_5/testsuite/src/test/java/org/hibernate/test/idgen/enhanced/OptimizerUnitTest.java	2010-05-12 15:13:03 UTC (rev 19477)
@@ -1,156 +0,0 @@
-package org.hibernate.test.idgen.enhanced;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import org.hibernate.id.IdentifierGeneratorHelper;
-import org.hibernate.id.IntegralDataTypeHolder;
-import org.hibernate.junit.UnitTestCase;
-import org.hibernate.id.enhanced.Optimizer;
-import org.hibernate.id.enhanced.OptimizerFactory;
-import org.hibernate.id.enhanced.AccessCallback;
-
-/**
- * {@inheritDoc}
- *
- * @author Steve Ebersole
- */
-public class OptimizerUnitTest extends UnitTestCase {
-	public OptimizerUnitTest(String string) {
-		super( string );
-	}
-
-	public static Test suite() {
-		return new TestSuite( OptimizerUnitTest.class );
-	}
-
-	public void testBasicNoOptimizerUsage() {
-		// test historic sequence behavior, where the initial values start at 1...
-		SourceMock sequence = new SourceMock( 1 );
-		Optimizer optimizer = OptimizerFactory.buildOptimizer( OptimizerFactory.NONE, Long.class, 1 );
-		for ( int i = 1; i < 11; i++ ) {
-			final Long next = ( Long ) optimizer.generate( sequence );
-			assertEquals( i, next.intValue() );
-		}
-		assertEquals( 10, sequence.getTimesCalled() );
-		assertEquals( 10, sequence.getCurrentValue() );
-
-		// test historic table behavior, where the initial values started at 0 (we now force 1 to be the first used id value)
-		sequence = new SourceMock( 0 );
-		optimizer = OptimizerFactory.buildOptimizer( OptimizerFactory.NONE, Long.class, 1 );
-		for ( int i = 1; i < 11; i++ ) {
-			final Long next = ( Long ) optimizer.generate( sequence );
-			assertEquals( i, next.intValue() );
-		}
-		assertEquals( 11, sequence.getTimesCalled() ); // an extra time to get to 1 initially
-		assertEquals( 10, sequence.getCurrentValue() );
-	}
-
-	public void testBasicHiLoOptimizerUsage() {
-		int increment = 10;
-		Long next;
-
-		// test historic sequence behavior, where the initial values start at 1...
-		SourceMock sequence = new SourceMock( 1 );
-		Optimizer optimizer = OptimizerFactory.buildOptimizer( OptimizerFactory.HILO, Long.class, increment );
-		for ( int i = 1; i <= increment; i++ ) {
-			next = ( Long ) optimizer.generate( sequence );
-			assertEquals( i, next.intValue() );
-		}
-		assertEquals( 1, sequence.getTimesCalled() ); // once to initialze state
-		assertEquals( 1, sequence.getCurrentValue() );
-		// force a "clock over"
-		next = ( Long ) optimizer.generate( sequence );
-		assertEquals( 11, next.intValue() );
-		assertEquals( 2, sequence.getTimesCalled() );
-		assertEquals( 2, sequence.getCurrentValue() );
-
-		// test historic table behavior, where the initial values started at 0 (we now force 1 to be the first used id value)
-		sequence = new SourceMock( 0 );
-		optimizer = OptimizerFactory.buildOptimizer( OptimizerFactory.HILO, Long.class, increment );
-		for ( int i = 1; i <= increment; i++ ) {
-			next = ( Long ) optimizer.generate( sequence );
-			assertEquals( i, next.intValue() );
-		}
-		assertEquals( 2, sequence.getTimesCalled() ); // here have have an extra call to get to 1 initially
-		assertEquals( 1, sequence.getCurrentValue() );
-		// force a "clock over"
-		next = ( Long ) optimizer.generate( sequence );
-		assertEquals( 11, next.intValue() );
-		assertEquals( 3, sequence.getTimesCalled() );
-		assertEquals( 2, sequence.getCurrentValue() );
-	}
-
-	public void testBasicPooledOptimizerUsage() {
-		Long next;
-		// test historic sequence behavior, where the initial values start at 1...
-		SourceMock sequence = new SourceMock( 1, 10 );
-		Optimizer optimizer = OptimizerFactory.buildOptimizer( OptimizerFactory.POOL, Long.class, 10 );
-		for ( int i = 1; i < 11; i++ ) {
-			next = ( Long ) optimizer.generate( sequence );
-			assertEquals( i, next.intValue() );
-		}
-		assertEquals( 2, sequence.getTimesCalled() ); // twice to initialize state
-		assertEquals( 11, sequence.getCurrentValue() );
-		// force a "clock over"
-		next = ( Long ) optimizer.generate( sequence );
-		assertEquals( 11, next.intValue() );
-		assertEquals( 3, sequence.getTimesCalled() );
-		assertEquals( 21, sequence.getCurrentValue() );
-	}
-
-	private static class SourceMock implements AccessCallback {
-		private IdentifierGeneratorHelper.BasicHolder value = new IdentifierGeneratorHelper.BasicHolder( Long.class );
-		private int increment;
-		private int timesCalled = 0;
-
-		public SourceMock(long initialValue) {
-			this( initialValue, 1 );
-		}
-
-		public SourceMock(long initialValue, int increment) {
-			this.increment = increment;
-			this.value.initialize( initialValue - increment );
-		}
-
-		public IntegralDataTypeHolder getNextValue() {
-			timesCalled++;
-			return value.add( increment ).copy();
-		}
-
-		public int getTimesCalled() {
-			return timesCalled;
-		}
-
-		public long getCurrentValue() {
-			return value.getActualLongValue();
-		}
-	}
-
-//	public void testNoopDumping() {
-//		SourceMock sequence = new SourceMock( 1 );
-//		Optimizer optimizer = OptimizerFactory.buildOptimizer( OptimizerFactory.NONE, Long.class, 1 );
-//		for ( int i = 1; i <= 41; i++ ) {
-//			System.out.println( i + " => " + optimizer.generate( sequence ) + " (" + sequence.getCurrentValue() + ")" );
-//		}
-//	}
-//
-//	public void testHiLoDumping() {
-//		int increment = 10;
-//		SourceMock sequence = new SourceMock( 1 );
-//		Optimizer optimizer = OptimizerFactory.buildOptimizer( OptimizerFactory.HILO, Long.class, increment );
-//		for ( int i = 1; i <= 41; i++ ) {
-//			System.out.println( i + " => " + optimizer.generate( sequence ) + " (" + sequence.getCurrentValue() + ")" );
-//		}
-//	}
-//
-//	public void testPooledDumping() {
-//		int increment = 10;
-//		SourceMock sequence = new SourceMock( 1, increment );
-//		Optimizer optimizer = OptimizerFactory.buildOptimizer( OptimizerFactory.POOL, Long.class, increment );
-//		for ( int i = 1; i <= 41; i++ ) {
-//			System.out.println( i + " => " + optimizer.generate( sequence ) + " (" + sequence.getCurrentValue() + ")" );
-//		}
-//	}
-
-}

Deleted: core/branches/Branch_3_5/testsuite/src/test/java/org/hibernate/test/idgen/enhanced/SequenceStyleConfigUnitTest.java
===================================================================
--- core/branches/Branch_3_5/testsuite/src/test/java/org/hibernate/test/idgen/enhanced/SequenceStyleConfigUnitTest.java	2010-05-12 14:46:34 UTC (rev 19476)
+++ core/branches/Branch_3_5/testsuite/src/test/java/org/hibernate/test/idgen/enhanced/SequenceStyleConfigUnitTest.java	2010-05-12 15:13:03 UTC (rev 19477)
@@ -1,203 +0,0 @@
-package org.hibernate.test.idgen.enhanced;
-
-import java.util.Properties;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import org.hibernate.junit.UnitTestCase;
-import org.hibernate.dialect.Dialect;
-import org.hibernate.id.enhanced.SequenceStyleGenerator;
-import org.hibernate.id.enhanced.SequenceStructure;
-import org.hibernate.id.enhanced.OptimizerFactory;
-import org.hibernate.id.enhanced.TableStructure;
-import org.hibernate.id.PersistentIdentifierGenerator;
-import org.hibernate.Hibernate;
-import org.hibernate.MappingException;
-import org.hibernate.cfg.ObjectNameNormalizer;
-import org.hibernate.cfg.NamingStrategy;
-
-/**
- * Tests that SequenceStyleGenerator configures itself as expected
- * in various scenarios
- *
- * @author Steve Ebersole
- */
-public class SequenceStyleConfigUnitTest extends UnitTestCase {
-	public SequenceStyleConfigUnitTest(String string) {
-		super( string );
-	}
-
-	public static Test suite() {
-		return new TestSuite( SequenceStyleConfigUnitTest.class );
-	}
-
-	/**
-	 * Test all params defaulted with a dialect supporting sequences
-	 */
-	public void testDefaultedSequenceBackedConfiguration() {
-		Dialect dialect = new SequenceDialect();
-		Properties props = buildGeneratorPropertiesBase();
-		SequenceStyleGenerator generator = new SequenceStyleGenerator();
-		generator.configure( Hibernate.LONG, props, dialect );
-
-		assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() );
-		assertClassAssignability( OptimizerFactory.NoopOptimizer.class, generator.getOptimizer().getClass() );
-		assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() );
-	}
-
-	private Properties buildGeneratorPropertiesBase() {
-		Properties props = new Properties();
-		props.put(
-				PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER,
-				new ObjectNameNormalizer() {
-					protected boolean isUseQuotedIdentifiersGlobally() {
-						return false;
-					}
-
-					protected NamingStrategy getNamingStrategy() {
-						return null;
-					}
-				}
-		);
-		return props;
-	}
-
-	/**
-	 * Test all params defaulted with a dialect which does not support sequences
-	 */
-	public void testDefaultedTableBackedConfiguration() {
-		Dialect dialect = new TableDialect();
-		Properties props = buildGeneratorPropertiesBase();
-		SequenceStyleGenerator generator = new SequenceStyleGenerator();
-		generator.configure( Hibernate.LONG, props, dialect );
-
-		assertClassAssignability( TableStructure.class, generator.getDatabaseStructure().getClass() );
-		assertClassAssignability( OptimizerFactory.NoopOptimizer.class, generator.getOptimizer().getClass() );
-		assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() );
-	}
-
-	/**
-	 * Test default optimizer selection for sequence backed generators
-	 * based on the configured increment size; both in the case of the
-	 * dialect supporting pooled sequences (pooled) and not (hilo)
-	 */
-	public void testDefaultOptimizerBasedOnIncrementBackedBySequence() {
-		Properties props = buildGeneratorPropertiesBase();
-		props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "10" );
-
-		// for dialects which do not support pooled sequences, we default to pooled+table
-		Dialect dialect = new SequenceDialect();
-		SequenceStyleGenerator generator = new SequenceStyleGenerator();
-		generator.configure( Hibernate.LONG, props, dialect );
-		assertClassAssignability( TableStructure.class, generator.getDatabaseStructure().getClass() );
-		assertClassAssignability( OptimizerFactory.PooledOptimizer.class, generator.getOptimizer().getClass() );
-		assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() );
-
-		// for dialects which do support pooled sequences, we default to pooled+sequence
-		dialect = new PooledSequenceDialect();
-		generator = new SequenceStyleGenerator();
-		generator.configure( Hibernate.LONG, props, dialect );
-		assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() );
-		assertClassAssignability( OptimizerFactory.PooledOptimizer.class, generator.getOptimizer().getClass() );
-		assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() );
-	}
-
-	/**
-	 * Test default optimizer selection for table backed generators
-	 * based on the configured increment size.  Here we always prefer
-	 * pooled.
-	 */
-	public void testDefaultOptimizerBasedOnIncrementBackedByTable() {
-		Properties props = buildGeneratorPropertiesBase();
-		props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "10" );
-		Dialect dialect = new TableDialect();
-		SequenceStyleGenerator generator = new SequenceStyleGenerator();
-		generator.configure( Hibernate.LONG, props, dialect );
-		assertClassAssignability( TableStructure.class, generator.getDatabaseStructure().getClass() );
-		assertClassAssignability( OptimizerFactory.PooledOptimizer.class, generator.getOptimizer().getClass() );
-		assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() );
-	}
-
-	/**
-	 * Test forcing of table as backing strucuture with dialect supporting sequences
-	 */
-	public void testForceTableUse() {
-		Dialect dialect = new SequenceDialect();
-		Properties props = buildGeneratorPropertiesBase();
-		props.setProperty( SequenceStyleGenerator.FORCE_TBL_PARAM, "true" );
-		SequenceStyleGenerator generator = new SequenceStyleGenerator();
-		generator.configure( Hibernate.LONG, props, dialect );
-		assertClassAssignability( TableStructure.class, generator.getDatabaseStructure().getClass() );
-		assertClassAssignability( OptimizerFactory.NoopOptimizer.class, generator.getOptimizer().getClass() );
-		assertEquals( SequenceStyleGenerator.DEF_SEQUENCE_NAME, generator.getDatabaseStructure().getName() );
-	}
-
-	/**
-	 * Test explicitly specifying both optimizer and increment
-	 */
-	public void testExplicitOptimizerWithExplicitIncrementSize() {
-		// with sequence ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-		final Dialect dialect = new SequenceDialect();
-
-		// optimizer=none w/ increment > 1 => should honor optimizer
-		Properties props = buildGeneratorPropertiesBase();
-		props.setProperty( SequenceStyleGenerator.OPT_PARAM, OptimizerFactory.NONE );
-		props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "20" );
-		SequenceStyleGenerator generator = new SequenceStyleGenerator();
-		generator.configure( Hibernate.LONG, props, dialect );
-		assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() );
-		assertClassAssignability( OptimizerFactory.NoopOptimizer.class, generator.getOptimizer().getClass() );
-		assertEquals( 1, generator.getOptimizer().getIncrementSize() );
-		assertEquals( 1, generator.getDatabaseStructure().getIncrementSize() );
-
-		// optimizer=hilo w/ increment > 1 => hilo
-		props = buildGeneratorPropertiesBase();
-		props.setProperty( SequenceStyleGenerator.OPT_PARAM, OptimizerFactory.HILO );
-		props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "20" );
-		generator = new SequenceStyleGenerator();
-		generator.configure( Hibernate.LONG, props, dialect );
-		assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() );
-		assertClassAssignability( OptimizerFactory.HiLoOptimizer.class, generator.getOptimizer().getClass() );
-		assertEquals( 20, generator.getOptimizer().getIncrementSize() );
-		assertEquals( 20, generator.getDatabaseStructure().getIncrementSize() );
-
-		// optimizer=pooled w/ increment > 1 => hilo
-		props = buildGeneratorPropertiesBase();
-		props.setProperty( SequenceStyleGenerator.OPT_PARAM, OptimizerFactory.POOL );
-		props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "20" );
-		generator = new SequenceStyleGenerator();
-		generator.configure( Hibernate.LONG, props, dialect );
-		// because the dialect reports to not support pooled seqyences, the expectation is that we will
-		// use a table for the backing structure...
-		assertClassAssignability( TableStructure.class, generator.getDatabaseStructure().getClass() );
-		assertClassAssignability( OptimizerFactory.PooledOptimizer.class, generator.getOptimizer().getClass() );
-		assertEquals( 20, generator.getOptimizer().getIncrementSize() );
-		assertEquals( 20, generator.getDatabaseStructure().getIncrementSize() );
-
-	}
-
-	private static class TableDialect extends Dialect {
-		public boolean supportsSequences() {
-			return false;
-		}
-	}
-
-	private static class SequenceDialect extends Dialect {
-		public boolean supportsSequences() {
-			return true;
-		}
-		public boolean supportsPooledSequences() {
-			return false;
-		}
-		public String getSequenceNextValString(String sequenceName) throws MappingException {
-			return "";
-		}
-	}
-
-	private static class PooledSequenceDialect extends SequenceDialect {
-		public boolean supportsPooledSequences() {
-			return true;
-		}
-	}
-}



More information about the hibernate-commits mailing list