HHH-10381 - Introduce a ThreadLocal-based pooled-lo optimizer to avoid locking
This commit is contained in:
parent
0c358d80f6
commit
20ebd8f5ca
|
@ -784,9 +784,19 @@ public interface AvailableSettings {
|
|||
/**
|
||||
* When using pooled {@link org.hibernate.id.enhanced.Optimizer optimizers}, prefer interpreting the
|
||||
* database value as the lower (lo) boundary. The default is to interpret it as the high boundary.
|
||||
*
|
||||
* @deprecated Use {@link #PREFERRED_POOLED_OPTIMIZER} instead
|
||||
*/
|
||||
@Deprecated
|
||||
String PREFER_POOLED_VALUES_LO = "hibernate.id.optimizer.pooled.prefer_lo";
|
||||
|
||||
/**
|
||||
* When a generator specified an increment-size and an optimizer was not explicitly specified, which of
|
||||
* the "pooled" optimizers should be preferred? Can specify an optimizer short name or an Optimizer
|
||||
* impl FQN.
|
||||
*/
|
||||
String PREFERRED_POOLED_OPTIMIZER = "hibernate.id.optimizer.pooled.preferred";
|
||||
|
||||
/**
|
||||
* The maximum number of strong references maintained by {@link org.hibernate.engine.query.spi.QueryPlanCache}. Default is 128.
|
||||
* @deprecated in favor of {@link #QUERY_PLAN_CACHE_PARAMETER_METADATA_MAX_SIZE}
|
||||
|
|
|
@ -7,9 +7,14 @@
|
|||
package org.hibernate.id.enhanced;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
|
@ -144,6 +149,26 @@ public class OptimizerFactory {
|
|||
@SuppressWarnings( {"UnusedDeclaration"})
|
||||
public static final String POOL_LO = "pooled-lo";
|
||||
|
||||
/**
|
||||
* Determine the optimizer to use when there was not one explicitly specified.
|
||||
*/
|
||||
public static String determineImplicitOptimizerName(int incrementSize, Properties configSettings) {
|
||||
if ( incrementSize <= 1 ) {
|
||||
return StandardOptimizerDescriptor.NONE.getExternalName();
|
||||
}
|
||||
|
||||
// see if the user defined a preferred pooled optimizer...
|
||||
final String preferredPooledOptimizerStrategy = configSettings.getProperty( AvailableSettings.PREFERRED_POOLED_OPTIMIZER );
|
||||
if ( StringHelper.isNotEmpty( preferredPooledOptimizerStrategy ) ) {
|
||||
return preferredPooledOptimizerStrategy;
|
||||
}
|
||||
|
||||
// otherwise fallback to the fallback strategy (considering the deprecated PREFER_POOLED_VALUES_LO setting)
|
||||
return ConfigurationHelper.getBoolean( AvailableSettings.PREFER_POOLED_VALUES_LO, configSettings, false )
|
||||
? StandardOptimizerDescriptor.POOLED_LO.getExternalName()
|
||||
: StandardOptimizerDescriptor.POOLED.getExternalName();
|
||||
}
|
||||
|
||||
private OptimizerFactory() {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,29 +6,30 @@
|
|||
*/
|
||||
package org.hibernate.id.enhanced;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.id.IntegralDataTypeHolder;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.id.IntegralDataTypeHolder;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Variation of {@link PooledOptimizer} which interprets the incoming database value as the lo value, rather than
|
||||
* the hi value, as well as using thread local to cache the generation state.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @author Stuart Douglas
|
||||
* @author Scott Marlow
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @see PooledOptimizer
|
||||
*/
|
||||
public class PooledThreadLocalLoOptimizer extends AbstractOptimizer {
|
||||
public class PooledLoThreadLocalOptimizer extends AbstractOptimizer {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
PooledThreadLocalLoOptimizer.class.getName()
|
||||
PooledLoThreadLocalOptimizer.class.getName()
|
||||
);
|
||||
|
||||
private static class GenerationState {
|
||||
|
@ -51,7 +52,7 @@ public class PooledThreadLocalLoOptimizer extends AbstractOptimizer {
|
|||
* @param returnClass The Java type of the values to be generated
|
||||
* @param incrementSize The increment size.
|
||||
*/
|
||||
public PooledThreadLocalLoOptimizer(Class returnClass, int incrementSize) {
|
||||
public PooledLoThreadLocalOptimizer(Class returnClass, int incrementSize) {
|
||||
super( returnClass, incrementSize );
|
||||
if ( incrementSize < 1 ) {
|
||||
throw new HibernateException( "increment size cannot be less than 1" );
|
|
@ -15,7 +15,6 @@ import org.hibernate.boot.model.naming.Identifier;
|
|||
import org.hibernate.boot.model.relational.Database;
|
||||
import org.hibernate.boot.model.relational.QualifiedName;
|
||||
import org.hibernate.boot.model.relational.QualifiedNameParser;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
|
@ -347,15 +346,11 @@ public class SequenceStyleGenerator
|
|||
* @return The optimizer strategy (name)
|
||||
*/
|
||||
protected String determineOptimizationStrategy(Properties params, int incrementSize) {
|
||||
// if the increment size is greater than one, we prefer pooled optimization; but we first
|
||||
// need to see if the user prefers POOL or POOL_LO...
|
||||
final String defaultPooledOptimizerStrategy = ConfigurationHelper.getBoolean( Environment.PREFER_POOLED_VALUES_LO, params, false )
|
||||
? StandardOptimizerDescriptor.POOLED_LO.getExternalName()
|
||||
: StandardOptimizerDescriptor.POOLED.getExternalName();
|
||||
final String defaultOptimizerStrategy = incrementSize <= 1
|
||||
? StandardOptimizerDescriptor.NONE.getExternalName()
|
||||
: defaultPooledOptimizerStrategy;
|
||||
return ConfigurationHelper.getString( OPT_PARAM, params, defaultOptimizerStrategy );
|
||||
return ConfigurationHelper.getString(
|
||||
OPT_PARAM,
|
||||
params,
|
||||
OptimizerFactory.determineImplicitOptimizerName( incrementSize, params )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -43,7 +43,7 @@ public enum StandardOptimizerDescriptor {
|
|||
* Describes the optimizer for use with tables/sequences that store the chunk information. Here, specifically the
|
||||
* lo value is stored in the database and ThreadLocal used to cache the generation state.
|
||||
*/
|
||||
POOLED_LOTL( "pooled-lotl", PooledThreadLocalLoOptimizer.class, true );
|
||||
POOLED_LOTL( "pooled-lotl", PooledLoThreadLocalOptimizer.class, true );
|
||||
|
||||
private static final Logger log = Logger.getLogger( StandardOptimizerDescriptor.class );
|
||||
|
||||
|
@ -51,11 +51,11 @@ public enum StandardOptimizerDescriptor {
|
|||
private final Class<? extends Optimizer> optimizerClass;
|
||||
private final boolean isPooled;
|
||||
|
||||
private StandardOptimizerDescriptor(String externalName, Class<? extends Optimizer> optimizerClass) {
|
||||
StandardOptimizerDescriptor(String externalName, Class<? extends Optimizer> optimizerClass) {
|
||||
this( externalName, optimizerClass, false );
|
||||
}
|
||||
|
||||
private StandardOptimizerDescriptor(String externalName, Class<? extends Optimizer> optimizerClass, boolean pooled) {
|
||||
StandardOptimizerDescriptor(String externalName, Class<? extends Optimizer> optimizerClass, boolean pooled) {
|
||||
this.externalName = externalName;
|
||||
this.optimizerClass = optimizerClass;
|
||||
this.isPooled = pooled;
|
||||
|
|
|
@ -25,7 +25,6 @@ import org.hibernate.boot.model.relational.Database;
|
|||
import org.hibernate.boot.model.relational.Namespace;
|
||||
import org.hibernate.boot.model.relational.QualifiedName;
|
||||
import org.hibernate.boot.model.relational.QualifiedNameParser;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.engine.jdbc.internal.FormatStyle;
|
||||
|
@ -360,15 +359,11 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
initialValue = determineInitialValue( params );
|
||||
incrementSize = determineIncrementSize( params );
|
||||
|
||||
// if the increment size is greater than one, we prefer pooled optimization; but we
|
||||
// need to see if the user prefers POOL or POOL_LO...
|
||||
final String defaultPooledOptimizerStrategy = ConfigurationHelper.getBoolean( Environment.PREFER_POOLED_VALUES_LO, params, false )
|
||||
? StandardOptimizerDescriptor.POOLED_LO.getExternalName()
|
||||
: StandardOptimizerDescriptor.POOLED.getExternalName();
|
||||
final String defaultOptimizerStrategy = incrementSize <= 1
|
||||
? StandardOptimizerDescriptor.NONE.getExternalName()
|
||||
: defaultPooledOptimizerStrategy;
|
||||
final String optimizationStrategy = ConfigurationHelper.getString( OPT_PARAM, params, defaultOptimizerStrategy );
|
||||
final String optimizationStrategy = ConfigurationHelper.getString(
|
||||
OPT_PARAM,
|
||||
params,
|
||||
OptimizerFactory.determineImplicitOptimizerName( incrementSize, params )
|
||||
);
|
||||
optimizer = OptimizerFactory.buildOptimizer(
|
||||
optimizationStrategy,
|
||||
identifierType.getReturnedClass(),
|
||||
|
|
Loading…
Reference in New Issue