HHH-6451 adapt hibernate-ehcache to the new api
This commit is contained in:
parent
c26a23bf90
commit
d0476de7f8
|
@ -4,5 +4,5 @@ dependencies {
|
|||
compile( project( ':hibernate-core' ) )
|
||||
compile( [group: 'net.sf.ehcache', name: 'ehcache-core', version: '2.4.3', ext: 'jar'] )
|
||||
testCompile( project(':hibernate-testing') )
|
||||
testCompile( [group: 'com.h2database', name: 'h2', version: '1.3.157', ext: 'jar'] )
|
||||
testCompile( libraries.h2 )
|
||||
}
|
||||
|
|
|
@ -23,19 +23,24 @@
|
|||
*/
|
||||
package org.hibernate.cache.ehcache;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import net.sf.ehcache.util.ClassLoaderUtil;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.internal.nonstop.NonstopAccessStrategyFactory;
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheCollectionRegion;
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheEntityRegion;
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheQueryResultsRegion;
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheTimestampsRegion;
|
||||
import org.hibernate.cache.ehcache.internal.strategy.EhcacheAccessStrategyFactory;
|
||||
import org.hibernate.cache.ehcache.internal.strategy.EhcacheAccessStrategyFactoryImpl;
|
||||
import org.hibernate.cache.ehcache.internal.util.HibernateUtil;
|
||||
import org.hibernate.cache.ehcache.management.impl.ProviderMBeanRegistrationHelper;
|
||||
import org.hibernate.cache.ehcache.nonstop.NonstopAccessStrategyFactory;
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheCollectionRegion;
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheEntityRegion;
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheQueryResultsRegion;
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheTimestampsRegion;
|
||||
import org.hibernate.cache.ehcache.strategy.EhcacheAccessStrategyFactory;
|
||||
import org.hibernate.cache.ehcache.strategy.EhcacheAccessStrategyFactoryImpl;
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.CollectionRegion;
|
||||
import org.hibernate.cache.spi.EntityRegion;
|
||||
|
@ -47,12 +52,6 @@ import org.hibernate.cfg.Settings;
|
|||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.service.spi.InjectService;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Abstract implementation of an Ehcache specific RegionFactory.
|
||||
*
|
||||
|
@ -64,160 +63,166 @@ import java.util.Properties;
|
|||
*/
|
||||
abstract class AbstractEhcacheRegionFactory implements RegionFactory {
|
||||
|
||||
/**
|
||||
* The Hibernate system property specifying the location of the ehcache configuration file name.
|
||||
* <p/>
|
||||
* If not set, ehcache.xml will be looked for in the root of the classpath.
|
||||
* <p/>
|
||||
* If set to say ehcache-1.xml, ehcache-1.xml will be looked for in the root of the classpath.
|
||||
*/
|
||||
public static final String NET_SF_EHCACHE_CONFIGURATION_RESOURCE_NAME = "net.sf.ehcache.configurationResourceName";
|
||||
/**
|
||||
* The Hibernate system property specifying the location of the ehcache configuration file name.
|
||||
* <p/>
|
||||
* If not set, ehcache.xml will be looked for in the root of the classpath.
|
||||
* <p/>
|
||||
* If set to say ehcache-1.xml, ehcache-1.xml will be looked for in the root of the classpath.
|
||||
*/
|
||||
public static final String NET_SF_EHCACHE_CONFIGURATION_RESOURCE_NAME = "net.sf.ehcache.configurationResourceName";
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger( AbstractEhcacheRegionFactory.class );
|
||||
private static final EhCacheMessageLogger LOG = Logger.getMessageLogger(
|
||||
EhCacheMessageLogger.class,
|
||||
AbstractEhcacheRegionFactory.class.getName()
|
||||
);
|
||||
|
||||
protected ClassLoaderService classLoaderService;
|
||||
/**
|
||||
* MBean registration helper class instance for Ehcache Hibernate MBeans.
|
||||
*/
|
||||
protected final ProviderMBeanRegistrationHelper mbeanRegistrationHelper = new ProviderMBeanRegistrationHelper();
|
||||
|
||||
/**
|
||||
* MBean registration helper class instance for Ehcache Hibernate MBeans.
|
||||
*/
|
||||
protected final ProviderMBeanRegistrationHelper mbeanRegistrationHelper = new ProviderMBeanRegistrationHelper();
|
||||
/**
|
||||
* Ehcache CacheManager that supplied Ehcache instances for this Hibernate RegionFactory.
|
||||
*/
|
||||
protected volatile CacheManager manager;
|
||||
|
||||
/**
|
||||
* Ehcache CacheManager that supplied Ehcache instances for this Hibernate RegionFactory.
|
||||
*/
|
||||
protected volatile CacheManager manager;
|
||||
/**
|
||||
* Settings object for the Hibernate persistence unit.
|
||||
*/
|
||||
protected Settings settings;
|
||||
|
||||
/**
|
||||
* Settings object for the Hibernate persistence unit.
|
||||
*/
|
||||
protected Settings settings;
|
||||
/**
|
||||
* {@link EhcacheAccessStrategyFactory} for creating various access strategies
|
||||
*/
|
||||
protected final EhcacheAccessStrategyFactory accessStrategyFactory =
|
||||
new NonstopAccessStrategyFactory( new EhcacheAccessStrategyFactoryImpl() );
|
||||
|
||||
/**
|
||||
* {@link EhcacheAccessStrategyFactory} for creating various access strategies
|
||||
*/
|
||||
protected final EhcacheAccessStrategyFactory accessStrategyFactory =
|
||||
new NonstopAccessStrategyFactory( new EhcacheAccessStrategyFactoryImpl() );
|
||||
/**
|
||||
* Whether to optimize for minimals puts or minimal gets.
|
||||
* <p/>
|
||||
* Indicates whether when operating in non-strict read/write or read-only mode
|
||||
* Hibernate should optimize the access patterns for minimal puts or minimal gets.
|
||||
* In Ehcache we default to minimal puts since this should have minimal to no
|
||||
* affect on unclustered users, and has great benefit for clustered users.
|
||||
* <p/>
|
||||
* This setting can be overridden by setting the "hibernate.cache.use_minimal_puts"
|
||||
* property in the Hibernate configuration.
|
||||
*
|
||||
* @return true, optimize for minimal puts
|
||||
*/
|
||||
public boolean isMinimalPutsEnabledByDefault() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to optimize for minimals puts or minimal gets.
|
||||
* <p/>
|
||||
* Indicates whether when operating in non-strict read/write or read-only mode
|
||||
* Hibernate should optimize the access patterns for minimal puts or minimal gets.
|
||||
* In Ehcache we default to minimal puts since this should have minimal to no
|
||||
* affect on unclustered users, and has great benefit for clustered users.
|
||||
* <p/>
|
||||
* This setting can be overridden by setting the "hibernate.cache.use_minimal_puts"
|
||||
* property in the Hibernate configuration.
|
||||
*
|
||||
* @return true, optimize for minimal puts
|
||||
*/
|
||||
public boolean isMinimalPutsEnabledByDefault() {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public long nextTimestamp() {
|
||||
return net.sf.ehcache.util.Timestamper.next();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public long nextTimestamp() {
|
||||
return net.sf.ehcache.util.Timestamper.next();
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata)
|
||||
throws CacheException {
|
||||
return new EhcacheEntityRegion( accessStrategyFactory, getCache( regionName ), settings, metadata, properties );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata)
|
||||
throws CacheException {
|
||||
return new EhcacheEntityRegion( accessStrategyFactory, getCache( regionName ), settings, metadata, properties );
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public CollectionRegion buildCollectionRegion(String regionName, Properties properties, CacheDataDescription metadata)
|
||||
throws CacheException {
|
||||
return new EhcacheCollectionRegion(
|
||||
accessStrategyFactory,
|
||||
getCache( regionName ),
|
||||
settings,
|
||||
metadata,
|
||||
properties
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public CollectionRegion buildCollectionRegion(String regionName, Properties properties, CacheDataDescription metadata)
|
||||
throws CacheException {
|
||||
return new EhcacheCollectionRegion(
|
||||
accessStrategyFactory,
|
||||
getCache( regionName ),
|
||||
settings,
|
||||
metadata,
|
||||
properties
|
||||
);
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException {
|
||||
return new EhcacheQueryResultsRegion( accessStrategyFactory, getCache( regionName ), properties );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException {
|
||||
return new EhcacheQueryResultsRegion( accessStrategyFactory, getCache( regionName ), properties );
|
||||
}
|
||||
@InjectService
|
||||
public void setClassLoaderService(ClassLoaderService classLoaderService) {
|
||||
this.classLoaderService = classLoaderService;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException {
|
||||
return new EhcacheTimestampsRegion( accessStrategyFactory, getCache( regionName ), properties );
|
||||
}
|
||||
private ClassLoaderService classLoaderService;
|
||||
|
||||
private Ehcache getCache(String name) throws CacheException {
|
||||
try {
|
||||
Ehcache cache = manager.getEhcache( name );
|
||||
if ( cache == null ) {
|
||||
LOG.warn( "Couldn't find a specific ehcache configuration for cache named [" + name + "]; using defaults." );
|
||||
manager.addCache( name );
|
||||
cache = manager.getEhcache( name );
|
||||
LOG.debug( "started EHCache region: " + name );
|
||||
}
|
||||
HibernateUtil.validateEhcache( cache );
|
||||
return cache;
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException {
|
||||
return new EhcacheTimestampsRegion( accessStrategyFactory, getCache( regionName ), properties );
|
||||
}
|
||||
|
||||
}
|
||||
private Ehcache getCache(String name) throws CacheException {
|
||||
try {
|
||||
Ehcache cache = manager.getEhcache( name );
|
||||
if ( cache == null ) {
|
||||
LOG.unableToFindEhCacheConfiguration( name );
|
||||
manager.addCache( name );
|
||||
cache = manager.getEhcache( name );
|
||||
LOG.debug( "started EHCache region: " + name );
|
||||
}
|
||||
HibernateUtil.validateEhcache( cache );
|
||||
return cache;
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a resource from the classpath.
|
||||
*/
|
||||
protected URL loadResource(String configurationResourceName) {
|
||||
URL url = null;
|
||||
if ( classLoaderService != null ) {
|
||||
url = classLoaderService.locateResource( configurationResourceName );
|
||||
}
|
||||
if ( url == null ) {
|
||||
ClassLoader standardClassloader = ClassLoaderUtil.getStandardClassLoader();
|
||||
if ( standardClassloader != null ) {
|
||||
url = standardClassloader.getResource( configurationResourceName );
|
||||
}
|
||||
if ( url == null ) {
|
||||
url = AbstractEhcacheRegionFactory.class.getResource( configurationResourceName );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG.debug(
|
||||
"Creating EhCacheRegionFactory from a specified resource: {}. Resolved to URL: {}",
|
||||
configurationResourceName,
|
||||
url
|
||||
);
|
||||
if ( url == null ) {
|
||||
/**
|
||||
* Load a resource from the classpath.
|
||||
*/
|
||||
protected URL loadResource(String configurationResourceName) {
|
||||
URL url = null;
|
||||
if ( classLoaderService != null ) {
|
||||
url = classLoaderService.locateResource( configurationResourceName );
|
||||
}
|
||||
if ( url == null ) {
|
||||
ClassLoader standardClassloader = ClassLoaderUtil.getStandardClassLoader();
|
||||
if ( standardClassloader != null ) {
|
||||
url = standardClassloader.getResource( configurationResourceName );
|
||||
}
|
||||
if ( url == null ) {
|
||||
url = AbstractEhcacheRegionFactory.class.getResource( configurationResourceName );
|
||||
}
|
||||
}
|
||||
if ( LOG.isDebugEnabled() ) {
|
||||
LOG.debugf(
|
||||
"Creating EhCacheRegionFactory from a specified resource: %s. Resolved to URL: %s",
|
||||
configurationResourceName,
|
||||
url
|
||||
);
|
||||
}
|
||||
if ( url == null ) {
|
||||
|
||||
LOG.warn(
|
||||
"A configurationResourceName was set to {} but the resource could not be loaded from the classpath." +
|
||||
"Ehcache will configure itself using defaults.", configurationResourceName
|
||||
);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
LOG.unableToLoadConfiguration( configurationResourceName );
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default access-type used when the configured using JPA 2.0 config. JPA 2.0 allows <code>@Cacheable(true)</code> to be attached to an
|
||||
* entity without any access type or usage qualification.
|
||||
* <p/>
|
||||
* We are conservative here in specifying {@link AccessType#READ_WRITE} so as to follow the mantra of "do no harm".
|
||||
* <p/>
|
||||
* This is a Hibernate 3.5 method.
|
||||
*/
|
||||
public AccessType getDefaultAccessType() {
|
||||
return AccessType.READ_WRITE;
|
||||
}
|
||||
/**
|
||||
* Default access-type used when the configured using JPA 2.0 config. JPA 2.0 allows <code>@Cacheable(true)</code> to be attached to an
|
||||
* entity without any access type or usage qualification.
|
||||
* <p/>
|
||||
* We are conservative here in specifying {@link AccessType#READ_WRITE} so as to follow the mantra of "do no harm".
|
||||
* <p/>
|
||||
* This is a Hibernate 3.5 method.
|
||||
*/
|
||||
public AccessType getDefaultAccessType() {
|
||||
return AccessType.READ_WRITE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,4 +57,25 @@ public interface EhCacheMessageLogger extends CoreMessageLogger {
|
|||
@LogMessage( level = WARN )
|
||||
@Message( value = "A configurationResourceName was set to %s but the resource could not be loaded from the classpath. Ehcache will configure itself using defaults.", id = 20004 )
|
||||
void unableToLoadConfiguration( String configurationResourceName );
|
||||
|
||||
@LogMessage( level = WARN )
|
||||
@Message( value = "The default cache value mode for this Ehcache configuration is \"identity\". This is incompatible with clustered "
|
||||
+ "Hibernate caching - the value mode has therefore been switched to \"serialization\"", id = 20005 )
|
||||
void incompatibleCacheValueMode( );
|
||||
|
||||
@LogMessage( level = WARN )
|
||||
@Message( value = "The value mode for the cache[%s] is \"identity\". This is incompatible with clustered Hibernate caching - "
|
||||
+ "the value mode has therefore been switched to \"serialization\"", id = 20006 )
|
||||
void incompatibleCacheValueModePerCache( String cacheName );
|
||||
@LogMessage( level = WARN )
|
||||
@Message( value = "read-only cache configured for mutable entity [%s]", id = 20007 )
|
||||
void readOnlyCacheConfiguredForMutableEntity( String entityName );
|
||||
|
||||
@LogMessage( level = WARN )
|
||||
@Message( value = "Cache[%s] Key[%s] Lockable[%s]\n"
|
||||
+ "A soft-locked cache entry was expired by the underlying Ehcache. "
|
||||
+ "If this happens regularly you should consider increasing the cache timeouts and/or capacity limits", id = 20008 )
|
||||
void softLockedCacheExpired( String regionName, Object key, String lock);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -23,22 +23,19 @@
|
|||
*/
|
||||
package org.hibernate.cache.ehcache;
|
||||
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.config.Configuration;
|
||||
import net.sf.ehcache.config.ConfigurationFactory;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cfg.Settings;
|
||||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.service.spi.InjectService;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.config.Configuration;
|
||||
import net.sf.ehcache.config.ConfigurationFactory;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.internal.util.HibernateUtil;
|
||||
import org.hibernate.cfg.Settings;
|
||||
|
||||
/**
|
||||
* A non-singleton EhCacheRegionFactory implementation.
|
||||
*
|
||||
|
@ -50,91 +47,85 @@ import java.util.Properties;
|
|||
*/
|
||||
public class EhCacheRegionFactory extends AbstractEhcacheRegionFactory {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger( EhCacheRegionFactory.class );
|
||||
private static final EhCacheMessageLogger LOG = Logger.getMessageLogger(
|
||||
EhCacheMessageLogger.class,
|
||||
EhCacheRegionFactory.class.getName()
|
||||
);
|
||||
|
||||
private ClassLoaderService classLoaderService;
|
||||
|
||||
public EhCacheRegionFactory() {
|
||||
}
|
||||
public EhCacheRegionFactory() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a non-singleton EhCacheRegionFactory
|
||||
*/
|
||||
public EhCacheRegionFactory(Properties prop) {
|
||||
super();
|
||||
}
|
||||
/**
|
||||
* Creates a non-singleton EhCacheRegionFactory
|
||||
*/
|
||||
public EhCacheRegionFactory(Properties prop) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void start(Settings settings, Properties properties) throws CacheException {
|
||||
this.settings = settings;
|
||||
if ( manager != null ) {
|
||||
LOG.warn(
|
||||
"Attempt to restart an already started EhCacheRegionFactory. Use sessionFactory.close() " +
|
||||
" between repeated calls to buildSessionFactory. Using previously created EhCacheRegionFactory." +
|
||||
" If this behaviour is required, consider using SingletonEhCacheRegionFactory."
|
||||
);
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void start(Settings settings, Properties properties) throws CacheException {
|
||||
this.settings = settings;
|
||||
if ( manager != null ) {
|
||||
LOG.attemptToRestartAlreadyStartedEhCacheProvider();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
String configurationResourceName = null;
|
||||
if ( properties != null ) {
|
||||
configurationResourceName = (String) properties.get( NET_SF_EHCACHE_CONFIGURATION_RESOURCE_NAME );
|
||||
}
|
||||
if ( configurationResourceName == null || configurationResourceName.length() == 0 ) {
|
||||
Configuration configuration = ConfigurationFactory.parseConfiguration();
|
||||
manager = new CacheManager( configuration );
|
||||
}
|
||||
else {
|
||||
URL url;
|
||||
try {
|
||||
url = new URL( configurationResourceName );
|
||||
}
|
||||
catch ( MalformedURLException e ) {
|
||||
url = loadResource( configurationResourceName );
|
||||
}
|
||||
Configuration configuration = HibernateUtil.loadAndCorrectConfiguration( url );
|
||||
manager = new CacheManager( configuration );
|
||||
}
|
||||
mbeanRegistrationHelper.registerMBean( manager, properties );
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
if ( e.getMessage().startsWith(
|
||||
"Cannot parseConfiguration CacheManager. Attempt to create a new instance of " +
|
||||
"CacheManager using the diskStorePath"
|
||||
) ) {
|
||||
throw new CacheException(
|
||||
"Attempt to restart an already started EhCacheRegionFactory. " +
|
||||
"Use sessionFactory.close() between repeated calls to buildSessionFactory. " +
|
||||
"Consider using SingletonEhCacheRegionFactory. Error from ehcache was: " + e.getMessage()
|
||||
);
|
||||
}
|
||||
else {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
String configurationResourceName = null;
|
||||
if ( properties != null ) {
|
||||
configurationResourceName = (String) properties.get( NET_SF_EHCACHE_CONFIGURATION_RESOURCE_NAME );
|
||||
}
|
||||
if ( configurationResourceName == null || configurationResourceName.length() == 0 ) {
|
||||
Configuration configuration = ConfigurationFactory.parseConfiguration();
|
||||
manager = new CacheManager( configuration );
|
||||
}
|
||||
else {
|
||||
URL url;
|
||||
try {
|
||||
url = new URL( configurationResourceName );
|
||||
}
|
||||
catch ( MalformedURLException e ) {
|
||||
url = loadResource( configurationResourceName );
|
||||
}
|
||||
Configuration configuration = HibernateUtil.loadAndCorrectConfiguration( url );
|
||||
manager = new CacheManager( configuration );
|
||||
}
|
||||
mbeanRegistrationHelper.registerMBean( manager, properties );
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
if ( e.getMessage().startsWith(
|
||||
"Cannot parseConfiguration CacheManager. Attempt to create a new instance of " +
|
||||
"CacheManager using the diskStorePath"
|
||||
) ) {
|
||||
throw new CacheException(
|
||||
"Attempt to restart an already started EhCacheRegionFactory. " +
|
||||
"Use sessionFactory.close() between repeated calls to buildSessionFactory. " +
|
||||
"Consider using SingletonEhCacheRegionFactory. Error from ehcache was: " + e.getMessage()
|
||||
);
|
||||
}
|
||||
else {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stop() {
|
||||
try {
|
||||
if ( manager != null ) {
|
||||
mbeanRegistrationHelper.unregisterMBean();
|
||||
manager.shutdown();
|
||||
manager = null;
|
||||
}
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stop() {
|
||||
try {
|
||||
if ( manager != null ) {
|
||||
mbeanRegistrationHelper.unregisterMBean();
|
||||
manager.shutdown();
|
||||
manager = null;
|
||||
}
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
|
||||
@InjectService
|
||||
public void setClassLoaderService(ClassLoaderService classLoaderService) {
|
||||
this.classLoaderService = classLoaderService;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,120 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import net.sf.ehcache.config.CacheConfiguration;
|
||||
import net.sf.ehcache.config.Configuration;
|
||||
import net.sf.ehcache.config.ConfigurationFactory;
|
||||
import net.sf.ehcache.config.NonstopConfiguration;
|
||||
import net.sf.ehcache.config.TerracottaConfiguration;
|
||||
import net.sf.ehcache.config.TerracottaConfiguration.ValueMode;
|
||||
import net.sf.ehcache.config.TimeoutBehaviorConfiguration.TimeoutBehaviorType;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @author Chris Dennis
|
||||
* @author Abhishek Sanoujam
|
||||
* @author Alex Snaps
|
||||
*/
|
||||
final class HibernateUtil {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger( HibernateUtil.class );
|
||||
|
||||
private HibernateUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a cache manager configuration from the supplied url, correcting it for Hibernate compatibility.
|
||||
* <p/>
|
||||
* Currently correcting for Hibernate compatibility means simply switching any identity based value modes to serialization.
|
||||
*/
|
||||
static Configuration loadAndCorrectConfiguration(URL url) {
|
||||
Configuration config = ConfigurationFactory.parseConfiguration( url );
|
||||
if ( config.getDefaultCacheConfiguration().isTerracottaClustered() ) {
|
||||
if ( ValueMode.IDENTITY
|
||||
.equals( config.getDefaultCacheConfiguration().getTerracottaConfiguration().getValueMode() ) ) {
|
||||
LOG.warn(
|
||||
"The default cache value mode for this Ehcache configuration is \"identity\". This is incompatible with clustered "
|
||||
+ "Hibernate caching - the value mode has therefore been switched to \"serialization\""
|
||||
);
|
||||
config.getDefaultCacheConfiguration()
|
||||
.getTerracottaConfiguration()
|
||||
.setValueMode( ValueMode.SERIALIZATION.name() );
|
||||
}
|
||||
setupHibernateTimeoutBehavior(
|
||||
config.getDefaultCacheConfiguration()
|
||||
.getTerracottaConfiguration()
|
||||
.getNonstopConfiguration()
|
||||
);
|
||||
}
|
||||
|
||||
for ( CacheConfiguration cacheConfig : config.getCacheConfigurations().values() ) {
|
||||
if ( cacheConfig.isTerracottaClustered() ) {
|
||||
if ( ValueMode.IDENTITY.equals( cacheConfig.getTerracottaConfiguration().getValueMode() ) ) {
|
||||
LOG.warn(
|
||||
"The value mode for the {0} cache is \"identity\". This is incompatible with clustered Hibernate caching - "
|
||||
+ "the value mode has therefore been switched to \"serialization\"",
|
||||
cacheConfig.getName()
|
||||
);
|
||||
cacheConfig.getTerracottaConfiguration().setValueMode( ValueMode.SERIALIZATION.name() );
|
||||
}
|
||||
setupHibernateTimeoutBehavior( cacheConfig.getTerracottaConfiguration().getNonstopConfiguration() );
|
||||
}
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
private static void setupHibernateTimeoutBehavior(NonstopConfiguration nonstopConfig) {
|
||||
nonstopConfig.getTimeoutBehavior().setType( TimeoutBehaviorType.EXCEPTION.getTypeName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the supplied Ehcache instance is valid for use as a Hibernate cache.
|
||||
*/
|
||||
static void validateEhcache(Ehcache cache) throws CacheException {
|
||||
CacheConfiguration cacheConfig = cache.getCacheConfiguration();
|
||||
|
||||
if ( cacheConfig.isTerracottaClustered() ) {
|
||||
TerracottaConfiguration tcConfig = cacheConfig.getTerracottaConfiguration();
|
||||
switch ( tcConfig.getValueMode() ) {
|
||||
case IDENTITY:
|
||||
throw new CacheException(
|
||||
"The clustered Hibernate cache " + cache.getName() + " is using IDENTITY value mode.\n"
|
||||
+ "Identity value mode cannot be used with Hibernate cache regions."
|
||||
);
|
||||
case SERIALIZATION:
|
||||
default:
|
||||
// this is the recommended valueMode
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,22 +23,19 @@
|
|||
*/
|
||||
package org.hibernate.cache.ehcache;
|
||||
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.config.Configuration;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cfg.Settings;
|
||||
import org.hibernate.service.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.service.spi.InjectService;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.config.Configuration;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.internal.util.HibernateUtil;
|
||||
import org.hibernate.cfg.Settings;
|
||||
|
||||
/**
|
||||
* A singleton EhCacheRegionFactory implementation.
|
||||
*
|
||||
|
@ -49,75 +46,73 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
*/
|
||||
public class SingletonEhCacheRegionFactory extends AbstractEhcacheRegionFactory {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger( SingletonEhCacheRegionFactory.class );
|
||||
private static final EhCacheMessageLogger LOG = Logger.getMessageLogger(
|
||||
EhCacheMessageLogger.class,
|
||||
SingletonEhCacheRegionFactory.class.getName()
|
||||
);
|
||||
private static final AtomicInteger REFERENCE_COUNT = new AtomicInteger();
|
||||
|
||||
private static final AtomicInteger REFERENCE_COUNT = new AtomicInteger();
|
||||
/**
|
||||
* Returns a representation of the singleton EhCacheRegionFactory
|
||||
*/
|
||||
public SingletonEhCacheRegionFactory(Properties prop) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a representation of the singleton EhCacheRegionFactory
|
||||
*/
|
||||
public SingletonEhCacheRegionFactory(Properties prop) {
|
||||
super();
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void start(Settings settings, Properties properties) throws CacheException {
|
||||
try {
|
||||
String configurationResourceName = null;
|
||||
if ( properties != null ) {
|
||||
configurationResourceName = (String) properties.get( NET_SF_EHCACHE_CONFIGURATION_RESOURCE_NAME );
|
||||
}
|
||||
if ( configurationResourceName == null || configurationResourceName.length() == 0 ) {
|
||||
manager = CacheManager.create();
|
||||
REFERENCE_COUNT.incrementAndGet();
|
||||
}
|
||||
else {
|
||||
URL url;
|
||||
try {
|
||||
url = new URL( configurationResourceName );
|
||||
}
|
||||
catch ( MalformedURLException e ) {
|
||||
if ( !configurationResourceName.startsWith( "/" ) ) {
|
||||
configurationResourceName = "/" + configurationResourceName;
|
||||
LOG.debugf(
|
||||
"prepending / to %s. It should be placed in the root of the classpath rather than in a package.",
|
||||
configurationResourceName
|
||||
);
|
||||
}
|
||||
url = loadResource( configurationResourceName );
|
||||
}
|
||||
Configuration configuration = HibernateUtil.loadAndCorrectConfiguration( url );
|
||||
manager = CacheManager.create( configuration );
|
||||
REFERENCE_COUNT.incrementAndGet();
|
||||
}
|
||||
mbeanRegistrationHelper.registerMBean( manager, properties );
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void start(Settings settings, Properties properties) throws CacheException {
|
||||
try {
|
||||
String configurationResourceName = null;
|
||||
if ( properties != null ) {
|
||||
configurationResourceName = (String) properties.get( NET_SF_EHCACHE_CONFIGURATION_RESOURCE_NAME );
|
||||
}
|
||||
if ( configurationResourceName == null || configurationResourceName.length() == 0 ) {
|
||||
manager = CacheManager.create();
|
||||
REFERENCE_COUNT.incrementAndGet();
|
||||
}
|
||||
else {
|
||||
URL url;
|
||||
try {
|
||||
url = new URL( configurationResourceName );
|
||||
}
|
||||
catch ( MalformedURLException e ) {
|
||||
if ( !configurationResourceName.startsWith( "/" ) ) {
|
||||
configurationResourceName = "/" + configurationResourceName;
|
||||
LOG.debug(
|
||||
"prepending / to {}. It should be placed in the root of the classpath rather than in a package.",
|
||||
configurationResourceName
|
||||
);
|
||||
}
|
||||
url = loadResource( configurationResourceName );
|
||||
}
|
||||
Configuration configuration = HibernateUtil.loadAndCorrectConfiguration( url );
|
||||
manager = CacheManager.create( configuration );
|
||||
REFERENCE_COUNT.incrementAndGet();
|
||||
}
|
||||
mbeanRegistrationHelper.registerMBean( manager, properties );
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stop() {
|
||||
try {
|
||||
if ( manager != null ) {
|
||||
if ( REFERENCE_COUNT.decrementAndGet() == 0 ) {
|
||||
manager.shutdown();
|
||||
}
|
||||
manager = null;
|
||||
}
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void stop() {
|
||||
try {
|
||||
if ( manager != null ) {
|
||||
if ( REFERENCE_COUNT.decrementAndGet() == 0 ) {
|
||||
manager.shutdown();
|
||||
}
|
||||
manager = null;
|
||||
}
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
|
||||
@InjectService
|
||||
public void setClassLoaderService(ClassLoaderService classLoaderService) {
|
||||
this.classLoaderService = classLoaderService;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.internal.nonstop;
|
||||
|
||||
import net.sf.ehcache.constructs.nonstop.NonStopCacheException;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.ehcache.EhCacheMessageLogger;
|
||||
|
||||
/**
|
||||
* Class that takes care of {@link net.sf.ehcache.constructs.nonstop.NonStopCacheException} that happens in hibernate module
|
||||
*
|
||||
* @author Abhishek Sanoujam
|
||||
* @author Alex Snaps
|
||||
*/
|
||||
public final class HibernateNonstopCacheExceptionHandler {
|
||||
/**
|
||||
* Property name which set as "true" will throw exceptions on timeout with hibernate
|
||||
*/
|
||||
public static final String HIBERNATE_THROW_EXCEPTION_ON_TIMEOUT_PROPERTY = "ehcache.hibernate.propagateNonStopCacheException";
|
||||
|
||||
/**
|
||||
* Property name for logging the stack trace of the nonstop cache exception too. False by default
|
||||
*/
|
||||
public static final String HIBERNATE_LOG_EXCEPTION_STACK_TRACE_PROPERTY = "ehcache.hibernate.logNonStopCacheExceptionStackTrace";
|
||||
|
||||
private static final EhCacheMessageLogger LOG = Logger.getMessageLogger(
|
||||
EhCacheMessageLogger.class,
|
||||
HibernateNonstopCacheExceptionHandler.class.getName()
|
||||
);
|
||||
private static final HibernateNonstopCacheExceptionHandler INSTANCE = new HibernateNonstopCacheExceptionHandler();
|
||||
|
||||
/**
|
||||
* private constructor
|
||||
*/
|
||||
private HibernateNonstopCacheExceptionHandler() {
|
||||
// private
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the singleton instance
|
||||
*
|
||||
* @return the singleton instance
|
||||
*/
|
||||
public static HibernateNonstopCacheExceptionHandler getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle {@link net.sf.ehcache.constructs.nonstop.NonStopCacheException}.
|
||||
* If {@link HibernateNonstopCacheExceptionHandler#HIBERNATE_THROW_EXCEPTION_ON_TIMEOUT_PROPERTY} system property is set to true,
|
||||
* rethrows the {@link net.sf.ehcache.constructs.nonstop.NonStopCacheException}, otherwise logs the exception. While logging, if
|
||||
* {@link HibernateNonstopCacheExceptionHandler#HIBERNATE_LOG_EXCEPTION_STACK_TRACE_PROPERTY} is set to true, logs the exception stack
|
||||
* trace too, otherwise logs the exception message only
|
||||
*
|
||||
* @param nonStopCacheException
|
||||
*/
|
||||
public void handleNonstopCacheException(NonStopCacheException nonStopCacheException) {
|
||||
if ( Boolean.getBoolean( HIBERNATE_THROW_EXCEPTION_ON_TIMEOUT_PROPERTY ) ) {
|
||||
throw nonStopCacheException;
|
||||
}
|
||||
else {
|
||||
if ( Boolean.getBoolean( HIBERNATE_LOG_EXCEPTION_STACK_TRACE_PROPERTY ) ) {
|
||||
LOG.debug(
|
||||
"Ignoring NonstopCacheException - " + nonStopCacheException.getMessage(),
|
||||
nonStopCacheException
|
||||
);
|
||||
}
|
||||
else {
|
||||
LOG.debug( "Ignoring NonstopCacheException - " + nonStopCacheException.getMessage() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.internal.nonstop;
|
||||
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheCollectionRegion;
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheEntityRegion;
|
||||
import org.hibernate.cache.ehcache.internal.strategy.EhcacheAccessStrategyFactory;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
|
||||
/**
|
||||
* Implementation of {@link org.hibernate.cache.ehcache.internal.strategy.EhcacheAccessStrategyFactory} that takes care of Nonstop cache exceptions using
|
||||
* {@link HibernateNonstopCacheExceptionHandler}
|
||||
*
|
||||
* @author Abhishek Sanoujam
|
||||
* @author Alex Snaps
|
||||
*/
|
||||
public class NonstopAccessStrategyFactory implements EhcacheAccessStrategyFactory {
|
||||
|
||||
private final EhcacheAccessStrategyFactory actualFactory;
|
||||
|
||||
/**
|
||||
* Constructor accepting the actual factory
|
||||
*
|
||||
* @param actualFactory
|
||||
*/
|
||||
public NonstopAccessStrategyFactory(EhcacheAccessStrategyFactory actualFactory) {
|
||||
this.actualFactory = actualFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public EntityRegionAccessStrategy createEntityRegionAccessStrategy(EhcacheEntityRegion entityRegion, AccessType accessType) {
|
||||
return new NonstopAwareEntityRegionAccessStrategy(
|
||||
actualFactory.createEntityRegionAccessStrategy( entityRegion, accessType ),
|
||||
HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public CollectionRegionAccessStrategy createCollectionRegionAccessStrategy(EhcacheCollectionRegion collectionRegion,
|
||||
AccessType accessType) {
|
||||
return new NonstopAwareCollectionRegionAccessStrategy(
|
||||
actualFactory.createCollectionRegionAccessStrategy(
|
||||
collectionRegion,
|
||||
accessType
|
||||
), HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -21,7 +21,7 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.nonstop;
|
||||
package org.hibernate.cache.ehcache.internal.nonstop;
|
||||
|
||||
import net.sf.ehcache.constructs.nonstop.NonStopCacheException;
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.nonstop;
|
||||
package org.hibernate.cache.ehcache.internal.nonstop;
|
||||
|
||||
import net.sf.ehcache.constructs.nonstop.NonStopCacheException;
|
||||
|
|
@ -22,16 +22,14 @@
|
|||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package org.hibernate.cache.ehcache.regions;
|
||||
package org.hibernate.cache.ehcache.internal.regions;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.strategy.EhcacheAccessStrategyFactory;
|
||||
import org.hibernate.cache.ehcache.internal.strategy.EhcacheAccessStrategyFactory;
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.CollectionRegion;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
|
@ -50,22 +48,21 @@ import org.hibernate.cfg.Settings;
|
|||
*/
|
||||
public class EhcacheCollectionRegion extends EhcacheTransactionalDataRegion implements CollectionRegion {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger( EhcacheCollectionRegion.class );
|
||||
|
||||
/**
|
||||
* Constructs an EhcacheCollectionRegion around the given underlying cache.
|
||||
*
|
||||
* @param accessStrategyFactory
|
||||
*/
|
||||
public EhcacheCollectionRegion(EhcacheAccessStrategyFactory accessStrategyFactory, Ehcache underlyingCache, Settings settings,
|
||||
CacheDataDescription metadata, Properties properties) {
|
||||
super( accessStrategyFactory, underlyingCache, settings, metadata, properties );
|
||||
}
|
||||
/**
|
||||
* Constructs an EhcacheCollectionRegion around the given underlying cache.
|
||||
*
|
||||
* @param accessStrategyFactory
|
||||
*/
|
||||
public EhcacheCollectionRegion(EhcacheAccessStrategyFactory accessStrategyFactory, Ehcache underlyingCache, Settings settings,
|
||||
CacheDataDescription metadata, Properties properties) {
|
||||
super( accessStrategyFactory, underlyingCache, settings, metadata, properties );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public CollectionRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
|
||||
return accessStrategyFactory.createCollectionRegionAccessStrategy( this, accessType );
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public CollectionRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
|
||||
return accessStrategyFactory.createCollectionRegionAccessStrategy( this, accessType );
|
||||
}
|
||||
}
|
225
hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/regions/EhcacheDataRegion.java
vendored
Normal file
225
hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/regions/EhcacheDataRegion.java
vendored
Normal file
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package org.hibernate.cache.ehcache.internal.regions;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import net.sf.ehcache.constructs.nonstop.NonStopCacheException;
|
||||
import net.sf.ehcache.util.Timestamper;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.EhCacheMessageLogger;
|
||||
import org.hibernate.cache.ehcache.internal.nonstop.HibernateNonstopCacheExceptionHandler;
|
||||
import org.hibernate.cache.ehcache.internal.strategy.EhcacheAccessStrategyFactory;
|
||||
import org.hibernate.cache.spi.Region;
|
||||
|
||||
/**
|
||||
* An Ehcache specific data region implementation.
|
||||
* <p/>
|
||||
* This class is the ultimate superclass for all Ehcache Hibernate cache regions.
|
||||
*
|
||||
* @author Chris Dennis
|
||||
* @author Greg Luck
|
||||
* @author Emmanuel Bernard
|
||||
* @author Abhishek Sanoujam
|
||||
* @author Alex Snaps
|
||||
*/
|
||||
public abstract class EhcacheDataRegion implements Region {
|
||||
|
||||
private static final EhCacheMessageLogger LOG = Logger.getMessageLogger(
|
||||
EhCacheMessageLogger.class,
|
||||
EhcacheDataRegion.class.getName()
|
||||
);
|
||||
private static final String CACHE_LOCK_TIMEOUT_PROPERTY = "net.sf.ehcache.hibernate.cache_lock_timeout";
|
||||
private static final int DEFAULT_CACHE_LOCK_TIMEOUT = 60000;
|
||||
|
||||
/**
|
||||
* Ehcache instance backing this Hibernate data region.
|
||||
*/
|
||||
protected final Ehcache cache;
|
||||
|
||||
/**
|
||||
* The {@link EhcacheAccessStrategyFactory} used for creating various access strategies
|
||||
*/
|
||||
protected final EhcacheAccessStrategyFactory accessStrategyFactory;
|
||||
|
||||
private final int cacheLockTimeout;
|
||||
|
||||
|
||||
/**
|
||||
* Create a Hibernate data region backed by the given Ehcache instance.
|
||||
*/
|
||||
EhcacheDataRegion(EhcacheAccessStrategyFactory accessStrategyFactory, Ehcache cache, Properties properties) {
|
||||
this.accessStrategyFactory = accessStrategyFactory;
|
||||
this.cache = cache;
|
||||
String timeout = properties.getProperty(
|
||||
CACHE_LOCK_TIMEOUT_PROPERTY,
|
||||
Integer.toString( DEFAULT_CACHE_LOCK_TIMEOUT )
|
||||
);
|
||||
this.cacheLockTimeout = Timestamper.ONE_MS * Integer.decode( timeout );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String getName() {
|
||||
return cache.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void destroy() throws CacheException {
|
||||
try {
|
||||
cache.getCacheManager().removeCache( cache.getName() );
|
||||
}
|
||||
catch ( IllegalStateException e ) {
|
||||
//When Spring and Hibernate are both involved this will happen in normal shutdown operation.
|
||||
//Do not throw an exception, simply log this one.
|
||||
LOG.debug( "This can happen if multiple frameworks both try to shutdown ehcache", e );
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
if ( e instanceof NonStopCacheException ) {
|
||||
HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
.handleNonstopCacheException( (NonStopCacheException) e );
|
||||
}
|
||||
else {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public long getSizeInMemory() {
|
||||
try {
|
||||
return cache.calculateInMemorySize();
|
||||
}
|
||||
catch ( Throwable t ) {
|
||||
if ( t instanceof NonStopCacheException ) {
|
||||
HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
.handleNonstopCacheException( (NonStopCacheException) t );
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public long getElementCountInMemory() {
|
||||
try {
|
||||
return cache.getMemoryStoreSize();
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException ce ) {
|
||||
if ( ce instanceof NonStopCacheException ) {
|
||||
HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
.handleNonstopCacheException( (NonStopCacheException) ce );
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
throw new CacheException( ce );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public long getElementCountOnDisk() {
|
||||
try {
|
||||
return cache.getDiskStoreSize();
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException ce ) {
|
||||
if ( ce instanceof NonStopCacheException ) {
|
||||
HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
.handleNonstopCacheException( (NonStopCacheException) ce );
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
throw new CacheException( ce );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Map toMap() {
|
||||
try {
|
||||
Map<Object, Object> result = new HashMap<Object, Object>();
|
||||
for ( Object key : cache.getKeys() ) {
|
||||
result.put( key, cache.get( key ).getObjectValue() );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
if ( e instanceof NonStopCacheException ) {
|
||||
HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
.handleNonstopCacheException( (NonStopCacheException) e );
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
else {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public long nextTimestamp() {
|
||||
return Timestamper.next();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int getTimeout() {
|
||||
return cacheLockTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Ehcache instance backing this Hibernate data region.
|
||||
*/
|
||||
public Ehcache getEhcache() {
|
||||
return cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this region contains data for the given key.
|
||||
* <p/>
|
||||
* This is a Hibernate 3.5 method.
|
||||
*/
|
||||
public boolean contains(Object key) {
|
||||
return cache.isKeyInCache( key );
|
||||
}
|
||||
}
|
|
@ -21,16 +21,14 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.regions;
|
||||
package org.hibernate.cache.ehcache.internal.regions;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.strategy.EhcacheAccessStrategyFactory;
|
||||
import org.hibernate.cache.ehcache.internal.strategy.EhcacheAccessStrategyFactory;
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.EntityRegion;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
|
@ -49,22 +47,21 @@ import org.hibernate.cfg.Settings;
|
|||
*/
|
||||
public class EhcacheEntityRegion extends EhcacheTransactionalDataRegion implements EntityRegion {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger( EhcacheEntityRegion.class );
|
||||
|
||||
/**
|
||||
* Constructs an EhcacheEntityRegion around the given underlying cache.
|
||||
*
|
||||
* @param accessStrategyFactory
|
||||
*/
|
||||
public EhcacheEntityRegion(EhcacheAccessStrategyFactory accessStrategyFactory, Ehcache underlyingCache, Settings settings,
|
||||
CacheDataDescription metadata, Properties properties) {
|
||||
super( accessStrategyFactory, underlyingCache, settings, metadata, properties );
|
||||
}
|
||||
/**
|
||||
* Constructs an EhcacheEntityRegion around the given underlying cache.
|
||||
*
|
||||
* @param accessStrategyFactory
|
||||
*/
|
||||
public EhcacheEntityRegion(EhcacheAccessStrategyFactory accessStrategyFactory, Ehcache underlyingCache, Settings settings,
|
||||
CacheDataDescription metadata, Properties properties) {
|
||||
super( accessStrategyFactory, underlyingCache, settings, metadata, properties );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
|
||||
return accessStrategyFactory.createEntityRegionAccessStrategy( this, accessType );
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
|
||||
return accessStrategyFactory.createEntityRegionAccessStrategy( this, accessType );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.internal.regions;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import net.sf.ehcache.Element;
|
||||
import net.sf.ehcache.constructs.nonstop.NonStopCacheException;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.EhCacheMessageLogger;
|
||||
import org.hibernate.cache.ehcache.internal.nonstop.HibernateNonstopCacheExceptionHandler;
|
||||
import org.hibernate.cache.ehcache.internal.strategy.EhcacheAccessStrategyFactory;
|
||||
import org.hibernate.cache.spi.GeneralDataRegion;
|
||||
|
||||
/**
|
||||
* An Ehcache specific GeneralDataRegion.
|
||||
* <p/>
|
||||
* GeneralDataRegion instances are used for both the timestamps and query caches.
|
||||
*
|
||||
* @author Chris Dennis
|
||||
* @author Greg Luck
|
||||
* @author Emmanuel Bernard
|
||||
* @author Abhishek Sanoujam
|
||||
* @author Alex Snaps
|
||||
*/
|
||||
abstract class EhcacheGeneralDataRegion extends EhcacheDataRegion implements GeneralDataRegion {
|
||||
|
||||
private static final EhCacheMessageLogger LOG = Logger.getMessageLogger(
|
||||
EhCacheMessageLogger.class,
|
||||
EhcacheGeneralDataRegion.class.getName()
|
||||
);
|
||||
|
||||
/**
|
||||
* Creates an EhcacheGeneralDataRegion using the given Ehcache instance as a backing.
|
||||
*/
|
||||
public EhcacheGeneralDataRegion(EhcacheAccessStrategyFactory accessStrategyFactory, Ehcache cache, Properties properties) {
|
||||
super( accessStrategyFactory, cache, properties );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Object get(Object key) throws CacheException {
|
||||
try {
|
||||
LOG.debugf( "key: %s", key );
|
||||
if ( key == null ) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
Element element = cache.get( key );
|
||||
if ( element == null ) {
|
||||
LOG.debugf( "Element for key %s is null", key );
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return element.getObjectValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
if ( e instanceof NonStopCacheException ) {
|
||||
HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
.handleNonstopCacheException( (NonStopCacheException) e );
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void put(Object key, Object value) throws CacheException {
|
||||
LOG.debugf( "key: %s value: %s", key, value );
|
||||
try {
|
||||
Element element = new Element( key, value );
|
||||
cache.put( element );
|
||||
}
|
||||
catch ( IllegalArgumentException e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
catch ( IllegalStateException e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
if ( e instanceof NonStopCacheException ) {
|
||||
HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
.handleNonstopCacheException( (NonStopCacheException) e );
|
||||
}
|
||||
else {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void evict(Object key) throws CacheException {
|
||||
try {
|
||||
cache.remove( key );
|
||||
}
|
||||
catch ( ClassCastException e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
catch ( IllegalStateException e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
if ( e instanceof NonStopCacheException ) {
|
||||
HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
.handleNonstopCacheException( (NonStopCacheException) e );
|
||||
}
|
||||
else {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void evictAll() throws CacheException {
|
||||
try {
|
||||
cache.removeAll();
|
||||
}
|
||||
catch ( IllegalStateException e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
if ( e instanceof NonStopCacheException ) {
|
||||
HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
.handleNonstopCacheException( (NonStopCacheException) e );
|
||||
}
|
||||
else {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,13 +21,13 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.regions;
|
||||
package org.hibernate.cache.ehcache.internal.regions;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import net.sf.ehcache.Ehcache;
|
||||
|
||||
import org.hibernate.cache.ehcache.strategy.EhcacheAccessStrategyFactory;
|
||||
import org.hibernate.cache.ehcache.internal.strategy.EhcacheAccessStrategyFactory;
|
||||
import org.hibernate.cache.spi.QueryResultsRegion;
|
||||
|
||||
/**
|
|
@ -21,11 +21,11 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.regions;
|
||||
package org.hibernate.cache.ehcache.internal.regions;
|
||||
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import org.hibernate.cache.ehcache.strategy.EhcacheAccessStrategyFactory;
|
||||
import org.hibernate.cache.ehcache.strategy.EhcacheAccessStrategyFactory;
|
||||
|
||||
import org.hibernate.cache.ehcache.internal.strategy.EhcacheAccessStrategyFactory;
|
||||
import org.hibernate.cache.spi.TimestampsRegion;
|
||||
|
||||
import java.util.Properties;
|
|
@ -21,7 +21,7 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.regions;
|
||||
package org.hibernate.cache.ehcache.internal.regions;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
|
@ -33,8 +33,8 @@ import net.sf.ehcache.concurrent.StripedReadWriteLockSync;
|
|||
import net.sf.ehcache.constructs.nonstop.NonStopCacheException;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.nonstop.HibernateNonstopCacheExceptionHandler;
|
||||
import org.hibernate.cache.ehcache.strategy.EhcacheAccessStrategyFactory;
|
||||
import org.hibernate.cache.ehcache.internal.nonstop.HibernateNonstopCacheExceptionHandler;
|
||||
import org.hibernate.cache.ehcache.internal.strategy.EhcacheAccessStrategyFactory;
|
||||
import org.hibernate.cache.spi.CacheDataDescription;
|
||||
import org.hibernate.cache.spi.TransactionalDataRegion;
|
||||
import org.hibernate.cfg.Settings;
|
|
@ -21,10 +21,10 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.strategy;
|
||||
package org.hibernate.cache.ehcache.internal.strategy;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheTransactionalDataRegion;
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheTransactionalDataRegion;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.cfg.Settings;
|
||||
|
|
@ -0,0 +1,427 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.internal.strategy;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Comparator;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.EhCacheMessageLogger;
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheTransactionalDataRegion;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.cfg.Settings;
|
||||
|
||||
/**
|
||||
* Superclass for all Ehcache specific read/write AccessStrategy implementations.
|
||||
*
|
||||
* @param <T> the type of the enclosed cache region
|
||||
*
|
||||
* @author Chris Dennis
|
||||
* @author Alex Snaps
|
||||
*/
|
||||
abstract class AbstractReadWriteEhcacheAccessStrategy<T extends EhcacheTransactionalDataRegion>
|
||||
extends AbstractEhcacheAccessStrategy<T> {
|
||||
|
||||
private static final EhCacheMessageLogger LOG = Logger.getMessageLogger(
|
||||
EhCacheMessageLogger.class,
|
||||
AbstractReadWriteEhcacheAccessStrategy.class.getName()
|
||||
);
|
||||
private final UUID uuid = UUID.randomUUID();
|
||||
private final AtomicLong nextLockId = new AtomicLong();
|
||||
|
||||
private final Comparator versionComparator;
|
||||
|
||||
/**
|
||||
* Creates a read/write cache access strategy around the given cache region.
|
||||
*/
|
||||
public AbstractReadWriteEhcacheAccessStrategy(T region, Settings settings) {
|
||||
super( region, settings );
|
||||
this.versionComparator = region.getCacheDataDescription().getVersionComparator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>null</code> if the item is not readable. Locked items are not readable, nor are items created
|
||||
* after the start of this transaction.
|
||||
*
|
||||
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#get(java.lang.Object, long)
|
||||
* @see org.hibernate.cache.spi.access.CollectionRegionAccessStrategy#get(java.lang.Object, long)
|
||||
*/
|
||||
public final Object get(Object key, long txTimestamp) throws CacheException {
|
||||
readLockIfNeeded( key );
|
||||
try {
|
||||
Lockable item = (Lockable) region.get( key );
|
||||
|
||||
boolean readable = item != null && item.isReadable( txTimestamp );
|
||||
if ( readable ) {
|
||||
return item.getValue();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
readUnlockIfNeeded( key );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>false</code> and fails to put the value if there is an existing un-writeable item mapped to this
|
||||
* key.
|
||||
*
|
||||
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object, boolean)
|
||||
* @see org.hibernate.cache.spi.access.CollectionRegionAccessStrategy#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object, boolean)
|
||||
*/
|
||||
@Override
|
||||
public final boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
|
||||
throws CacheException {
|
||||
region.writeLock( key );
|
||||
try {
|
||||
Lockable item = (Lockable) region.get( key );
|
||||
boolean writeable = item == null || item.isWriteable( txTimestamp, version, versionComparator );
|
||||
if ( writeable ) {
|
||||
region.put( key, new Item( value, version, region.nextTimestamp() ) );
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
region.writeUnlock( key );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Soft-lock a cache item.
|
||||
*
|
||||
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#lockItem(java.lang.Object, java.lang.Object)
|
||||
* @see org.hibernate.cache.spi.access.CollectionRegionAccessStrategy#lockItem(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
public final SoftLock lockItem(Object key, Object version) throws CacheException {
|
||||
region.writeLock( key );
|
||||
try {
|
||||
Lockable item = (Lockable) region.get( key );
|
||||
long timeout = region.nextTimestamp() + region.getTimeout();
|
||||
final Lock lock = ( item == null ) ? new Lock( timeout, uuid, nextLockId(), version ) : item.lock(
|
||||
timeout,
|
||||
uuid,
|
||||
nextLockId()
|
||||
);
|
||||
region.put( key, lock );
|
||||
return lock;
|
||||
}
|
||||
finally {
|
||||
region.writeUnlock( key );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Soft-unlock a cache item.
|
||||
*
|
||||
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#unlockItem(java.lang.Object, org.hibernate.cache.spi.access.SoftLock)
|
||||
* @see org.hibernate.cache.spi.access.CollectionRegionAccessStrategy#unlockItem(java.lang.Object, org.hibernate.cache.spi.access.SoftLock)
|
||||
*/
|
||||
public final void unlockItem(Object key, SoftLock lock) throws CacheException {
|
||||
region.writeLock( key );
|
||||
try {
|
||||
Lockable item = (Lockable) region.get( key );
|
||||
|
||||
if ( ( item != null ) && item.isUnlockable( lock ) ) {
|
||||
decrementLock( key, (Lock) item );
|
||||
}
|
||||
else {
|
||||
handleLockExpiry( key, item );
|
||||
}
|
||||
}
|
||||
finally {
|
||||
region.writeUnlock( key );
|
||||
}
|
||||
}
|
||||
|
||||
private long nextLockId() {
|
||||
return nextLockId.getAndIncrement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock and re-put the given key, lock combination.
|
||||
*/
|
||||
protected void decrementLock(Object key, Lock lock) {
|
||||
lock.unlock( region.nextTimestamp() );
|
||||
region.put( key, lock );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the timeout of a previous lock mapped to this key
|
||||
*/
|
||||
protected void handleLockExpiry(Object key, Lockable lock) {
|
||||
LOG.softLockedCacheExpired( region.getName(), key, lock.toString() );
|
||||
|
||||
long ts = region.nextTimestamp() + region.getTimeout();
|
||||
// create new lock that times out immediately
|
||||
Lock newLock = new Lock( ts, uuid, nextLockId.getAndIncrement(), null );
|
||||
newLock.unlock( ts );
|
||||
region.put( key, newLock );
|
||||
}
|
||||
|
||||
/**
|
||||
* Read lock the entry for the given key if internal cache locks will not provide correct exclusion.
|
||||
*/
|
||||
private void readLockIfNeeded(Object key) {
|
||||
if ( region.locksAreIndependentOfCache() ) {
|
||||
region.readLock( key );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read unlock the entry for the given key if internal cache locks will not provide correct exclusion.
|
||||
*/
|
||||
private void readUnlockIfNeeded(Object key) {
|
||||
if ( region.locksAreIndependentOfCache() ) {
|
||||
region.readUnlock( key );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface type implemented by all wrapper objects in the cache.
|
||||
*/
|
||||
protected static interface Lockable {
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the enclosed value can be read by a transaction started at the given time.
|
||||
*/
|
||||
public boolean isReadable(long txTimestamp);
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the enclosed value can be replaced with one of the given version by a
|
||||
* transaction started at the given time.
|
||||
*/
|
||||
public boolean isWriteable(long txTimestamp, Object version, Comparator versionComparator);
|
||||
|
||||
/**
|
||||
* Returns the enclosed value.
|
||||
*/
|
||||
public Object getValue();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the given lock can be unlocked using the given SoftLock instance as a handle.
|
||||
*/
|
||||
public boolean isUnlockable(SoftLock lock);
|
||||
|
||||
/**
|
||||
* Locks this entry, stamping it with the UUID and lockId given, with the lock timeout occuring at the specified
|
||||
* time. The returned Lock object can be used to unlock the entry in the future.
|
||||
*/
|
||||
public Lock lock(long timeout, UUID uuid, long lockId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper type representing unlocked items.
|
||||
*/
|
||||
protected final static class Item implements Serializable, Lockable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final Object value;
|
||||
private final Object version;
|
||||
private final long timestamp;
|
||||
|
||||
/**
|
||||
* Creates an unlocked item wrapping the given value with a version and creation timestamp.
|
||||
*/
|
||||
Item(Object value, Object version, long timestamp) {
|
||||
this.value = value;
|
||||
this.version = version;
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isReadable(long txTimestamp) {
|
||||
return txTimestamp > timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isWriteable(long txTimestamp, Object newVersion, Comparator versionComparator) {
|
||||
return version != null && versionComparator.compare( version, newVersion ) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isUnlockable(SoftLock lock) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Lock lock(long timeout, UUID uuid, long lockId) {
|
||||
return new Lock( timeout, uuid, lockId, version );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper type representing locked items.
|
||||
*/
|
||||
protected final static class Lock implements Serializable, Lockable, SoftLock {
|
||||
|
||||
private static final long serialVersionUID = 2L;
|
||||
|
||||
private final UUID sourceUuid;
|
||||
private final long lockId;
|
||||
private final Object version;
|
||||
|
||||
private long timeout;
|
||||
private boolean concurrent;
|
||||
private int multiplicity = 1;
|
||||
private long unlockTimestamp;
|
||||
|
||||
/**
|
||||
* Creates a locked item with the given identifiers and object version.
|
||||
*/
|
||||
Lock(long timeout, UUID sourceUuid, long lockId, Object version) {
|
||||
this.timeout = timeout;
|
||||
this.lockId = lockId;
|
||||
this.version = version;
|
||||
this.sourceUuid = sourceUuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isReadable(long txTimestamp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isWriteable(long txTimestamp, Object newVersion, Comparator versionComparator) {
|
||||
if ( txTimestamp > timeout ) {
|
||||
// if timedout then allow write
|
||||
return true;
|
||||
}
|
||||
if ( multiplicity > 0 ) {
|
||||
// if still locked then disallow write
|
||||
return false;
|
||||
}
|
||||
return version == null ? txTimestamp > unlockTimestamp : versionComparator.compare(
|
||||
version,
|
||||
newVersion
|
||||
) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Object getValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isUnlockable(SoftLock lock) {
|
||||
return equals( lock );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( o == this ) {
|
||||
return true;
|
||||
}
|
||||
else if ( o instanceof Lock ) {
|
||||
return ( lockId == ( (Lock) o ).lockId ) && sourceUuid.equals( ( (Lock) o ).sourceUuid );
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = ( sourceUuid != null ? sourceUuid.hashCode() : 0 );
|
||||
int temp = (int) lockId;
|
||||
for ( int i = 1; i < Long.SIZE / Integer.SIZE; i++ ) {
|
||||
temp ^= ( lockId >>> ( i * Integer.SIZE ) );
|
||||
}
|
||||
return hash + temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this Lock has been concurrently locked by more than one transaction.
|
||||
*/
|
||||
public boolean wasLockedConcurrently() {
|
||||
return concurrent;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Lock lock(long timeout, UUID uuid, long lockId) {
|
||||
concurrent = true;
|
||||
multiplicity++;
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks this Lock, and timestamps the unlock event.
|
||||
*/
|
||||
public void unlock(long timestamp) {
|
||||
if ( --multiplicity == 0 ) {
|
||||
unlockTimestamp = timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder( "Lock Source-UUID:" + sourceUuid + " Lock-ID:" + lockId );
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,10 +21,10 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.strategy;
|
||||
package org.hibernate.cache.ehcache.internal.strategy;
|
||||
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheCollectionRegion;
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheEntityRegion;
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheCollectionRegion;
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheEntityRegion;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
|
@ -48,7 +48,7 @@ public interface EhcacheAccessStrategyFactory {
|
|||
public EntityRegionAccessStrategy createEntityRegionAccessStrategy(EhcacheEntityRegion entityRegion, AccessType accessType);
|
||||
|
||||
/**
|
||||
* Create {@link CollectionRegionAccessStrategy} for the input {@link org.hibernate.cache.ehcache.regions.EhcacheCollectionRegion} and {@link AccessType}
|
||||
* Create {@link CollectionRegionAccessStrategy} for the input {@link org.hibernate.cache.ehcache.internal.regions.EhcacheCollectionRegion} and {@link AccessType}
|
||||
*
|
||||
* @param collectionRegion
|
||||
* @param accessType
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.internal.strategy;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.ehcache.EhCacheMessageLogger;
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheCollectionRegion;
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheEntityRegion;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
|
||||
/**
|
||||
* Class implementing {@link EhcacheAccessStrategyFactory}
|
||||
*
|
||||
* @author Abhishek Sanoujam
|
||||
* @author Alex Snaps
|
||||
*/
|
||||
public class EhcacheAccessStrategyFactoryImpl implements EhcacheAccessStrategyFactory {
|
||||
|
||||
private static final EhCacheMessageLogger LOG = Logger.getMessageLogger(
|
||||
EhCacheMessageLogger.class,
|
||||
EhcacheAccessStrategyFactoryImpl.class.getName()
|
||||
);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public EntityRegionAccessStrategy createEntityRegionAccessStrategy(EhcacheEntityRegion entityRegion, AccessType accessType) {
|
||||
switch ( accessType ) {
|
||||
case READ_ONLY:
|
||||
if ( entityRegion.getCacheDataDescription().isMutable() ) {
|
||||
LOG.readOnlyCacheConfiguredForMutableEntity( entityRegion.getName() );
|
||||
}
|
||||
return new ReadOnlyEhcacheEntityRegionAccessStrategy( entityRegion, entityRegion.getSettings() );
|
||||
case READ_WRITE:
|
||||
return new ReadWriteEhcacheEntityRegionAccessStrategy( entityRegion, entityRegion.getSettings() );
|
||||
|
||||
case NONSTRICT_READ_WRITE:
|
||||
return new NonStrictReadWriteEhcacheEntityRegionAccessStrategy(
|
||||
entityRegion,
|
||||
entityRegion.getSettings()
|
||||
);
|
||||
|
||||
case TRANSACTIONAL:
|
||||
return new TransactionalEhcacheEntityRegionAccessStrategy(
|
||||
entityRegion,
|
||||
entityRegion.getEhcache(),
|
||||
entityRegion.getSettings()
|
||||
);
|
||||
default:
|
||||
throw new IllegalArgumentException( "unrecognized access strategy type [" + accessType + "]" );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public CollectionRegionAccessStrategy createCollectionRegionAccessStrategy(EhcacheCollectionRegion collectionRegion,
|
||||
AccessType accessType) {
|
||||
switch ( accessType ) {
|
||||
case READ_ONLY:
|
||||
if ( collectionRegion.getCacheDataDescription().isMutable() ) {
|
||||
LOG.readOnlyCacheConfiguredForMutableEntity( collectionRegion.getName() );
|
||||
}
|
||||
return new ReadOnlyEhcacheCollectionRegionAccessStrategy(
|
||||
collectionRegion,
|
||||
collectionRegion.getSettings()
|
||||
);
|
||||
case READ_WRITE:
|
||||
return new ReadWriteEhcacheCollectionRegionAccessStrategy(
|
||||
collectionRegion,
|
||||
collectionRegion.getSettings()
|
||||
);
|
||||
case NONSTRICT_READ_WRITE:
|
||||
return new NonStrictReadWriteEhcacheCollectionRegionAccessStrategy(
|
||||
collectionRegion,
|
||||
collectionRegion.getSettings()
|
||||
);
|
||||
case TRANSACTIONAL:
|
||||
return new TransactionalEhcacheCollectionRegionAccessStrategy(
|
||||
collectionRegion, collectionRegion.getEhcache(), collectionRegion
|
||||
.getSettings()
|
||||
);
|
||||
default:
|
||||
throw new IllegalArgumentException( "unrecognized access strategy type [" + accessType + "]" );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -21,10 +21,10 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.strategy;
|
||||
package org.hibernate.cache.ehcache.internal.strategy;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheCollectionRegion;
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheCollectionRegion;
|
||||
import org.hibernate.cache.spi.CollectionRegion;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
|
@ -21,10 +21,10 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.strategy;
|
||||
package org.hibernate.cache.ehcache.internal.strategy;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheEntityRegion;
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheEntityRegion;
|
||||
import org.hibernate.cache.spi.EntityRegion;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
|
@ -21,10 +21,10 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.strategy;
|
||||
package org.hibernate.cache.ehcache.internal.strategy;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheCollectionRegion;
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheCollectionRegion;
|
||||
import org.hibernate.cache.spi.CollectionRegion;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
|
@ -21,10 +21,10 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.strategy;
|
||||
package org.hibernate.cache.ehcache.internal.strategy;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheEntityRegion;
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheEntityRegion;
|
||||
import org.hibernate.cache.spi.EntityRegion;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
|
@ -21,9 +21,9 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.strategy;
|
||||
package org.hibernate.cache.ehcache.internal.strategy;
|
||||
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheCollectionRegion;
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheCollectionRegion;
|
||||
import org.hibernate.cache.spi.CollectionRegion;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cfg.Settings;
|
|
@ -21,10 +21,10 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.strategy;
|
||||
package org.hibernate.cache.ehcache.internal.strategy;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheEntityRegion;
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheEntityRegion;
|
||||
import org.hibernate.cache.spi.EntityRegion;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
|
@ -21,13 +21,13 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.strategy;
|
||||
package org.hibernate.cache.ehcache.internal.strategy;
|
||||
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import net.sf.ehcache.Element;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheCollectionRegion;
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheCollectionRegion;
|
||||
import org.hibernate.cache.spi.CollectionRegion;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
|
@ -21,13 +21,13 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.strategy;
|
||||
package org.hibernate.cache.ehcache.internal.strategy;
|
||||
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import net.sf.ehcache.Element;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheEntityRegion;
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheEntityRegion;
|
||||
import org.hibernate.cache.spi.EntityRegion;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
116
hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/util/HibernateUtil.java
vendored
Normal file
116
hibernate-ehcache/src/main/java/org/hibernate/cache/ehcache/internal/util/HibernateUtil.java
vendored
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.internal.util;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import net.sf.ehcache.config.CacheConfiguration;
|
||||
import net.sf.ehcache.config.Configuration;
|
||||
import net.sf.ehcache.config.ConfigurationFactory;
|
||||
import net.sf.ehcache.config.NonstopConfiguration;
|
||||
import net.sf.ehcache.config.TerracottaConfiguration;
|
||||
import net.sf.ehcache.config.TerracottaConfiguration.ValueMode;
|
||||
import net.sf.ehcache.config.TimeoutBehaviorConfiguration.TimeoutBehaviorType;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.EhCacheMessageLogger;
|
||||
|
||||
|
||||
/**
|
||||
* @author Chris Dennis
|
||||
* @author Abhishek Sanoujam
|
||||
* @author Alex Snaps
|
||||
*/
|
||||
public final class HibernateUtil {
|
||||
|
||||
private static final EhCacheMessageLogger LOG = Logger.getMessageLogger(
|
||||
EhCacheMessageLogger.class,
|
||||
HibernateUtil.class.getName()
|
||||
);
|
||||
|
||||
private HibernateUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a cache manager configuration from the supplied url, correcting it for Hibernate compatibility.
|
||||
* <p/>
|
||||
* Currently correcting for Hibernate compatibility means simply switching any identity based value modes to serialization.
|
||||
*/
|
||||
public static Configuration loadAndCorrectConfiguration(URL url) {
|
||||
Configuration config = ConfigurationFactory.parseConfiguration( url );
|
||||
if ( config.getDefaultCacheConfiguration().isTerracottaClustered() ) {
|
||||
if ( ValueMode.IDENTITY
|
||||
.equals( config.getDefaultCacheConfiguration().getTerracottaConfiguration().getValueMode() ) ) {
|
||||
LOG.incompatibleCacheValueMode();
|
||||
config.getDefaultCacheConfiguration()
|
||||
.getTerracottaConfiguration()
|
||||
.setValueMode( ValueMode.SERIALIZATION.name() );
|
||||
}
|
||||
setupHibernateTimeoutBehavior(
|
||||
config.getDefaultCacheConfiguration()
|
||||
.getTerracottaConfiguration()
|
||||
.getNonstopConfiguration()
|
||||
);
|
||||
}
|
||||
|
||||
for ( CacheConfiguration cacheConfig : config.getCacheConfigurations().values() ) {
|
||||
if ( cacheConfig.isTerracottaClustered() ) {
|
||||
if ( ValueMode.IDENTITY.equals( cacheConfig.getTerracottaConfiguration().getValueMode() ) ) {
|
||||
LOG.incompatibleCacheValueModePerCache( cacheConfig.getName() );
|
||||
cacheConfig.getTerracottaConfiguration().setValueMode( ValueMode.SERIALIZATION.name() );
|
||||
}
|
||||
setupHibernateTimeoutBehavior( cacheConfig.getTerracottaConfiguration().getNonstopConfiguration() );
|
||||
}
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
private static void setupHibernateTimeoutBehavior(NonstopConfiguration nonstopConfig) {
|
||||
nonstopConfig.getTimeoutBehavior().setType( TimeoutBehaviorType.EXCEPTION.getTypeName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the supplied Ehcache instance is valid for use as a Hibernate cache.
|
||||
*/
|
||||
public static void validateEhcache(Ehcache cache) throws CacheException {
|
||||
CacheConfiguration cacheConfig = cache.getCacheConfiguration();
|
||||
|
||||
if ( cacheConfig.isTerracottaClustered() ) {
|
||||
TerracottaConfiguration tcConfig = cacheConfig.getTerracottaConfiguration();
|
||||
switch ( tcConfig.getValueMode() ) {
|
||||
case IDENTITY:
|
||||
throw new CacheException(
|
||||
"The clustered Hibernate cache " + cache.getName() + " is using IDENTITY value mode.\n"
|
||||
+ "Identity value mode cannot be used with Hibernate cache regions."
|
||||
);
|
||||
case SERIALIZATION:
|
||||
default:
|
||||
// this is the recommended valueMode
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,10 +33,10 @@ import net.sf.ehcache.CacheException;
|
|||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.Status;
|
||||
import net.sf.ehcache.event.CacheManagerEventListener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.cache.ehcache.EhCacheMessageLogger;
|
||||
import org.hibernate.cfg.Environment;
|
||||
|
||||
/**
|
||||
|
@ -48,130 +48,132 @@ import org.hibernate.cfg.Environment;
|
|||
* @author <a href="mailto:asanoujam@terracottatech.com">Abhishek Sanoujam</a>
|
||||
*/
|
||||
public class EhcacheHibernateMBeanRegistrationImpl
|
||||
implements EhcacheHibernateMBeanRegistration, CacheManagerEventListener {
|
||||
implements EhcacheHibernateMBeanRegistration, CacheManagerEventListener {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger( EhcacheHibernateMBeanRegistrationImpl.class.getName() );
|
||||
private static final EhCacheMessageLogger LOG = Logger.getMessageLogger(
|
||||
EhCacheMessageLogger.class,
|
||||
EhcacheHibernateMBeanRegistrationImpl.class.getName()
|
||||
);
|
||||
private static final int MAX_MBEAN_REGISTRATION_RETRIES = 50;
|
||||
private String cacheManagerClusterUUID;
|
||||
private String registeredCacheManagerName;
|
||||
private Status status = Status.STATUS_UNINITIALISED;
|
||||
private volatile EhcacheHibernate ehcacheHibernate;
|
||||
private volatile ObjectName cacheManagerObjectName;
|
||||
|
||||
private static final int MAX_MBEAN_REGISTRATION_RETRIES = 50;
|
||||
private String cacheManagerClusterUUID;
|
||||
private String registeredCacheManagerName;
|
||||
private Status status = Status.STATUS_UNINITIALISED;
|
||||
private volatile EhcacheHibernate ehcacheHibernate;
|
||||
private volatile ObjectName cacheManagerObjectName;
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public synchronized void registerMBeanForCacheManager(final CacheManager manager, final Properties properties)
|
||||
throws Exception {
|
||||
String sessionFactoryName = properties.getProperty( Environment.SESSION_FACTORY_NAME );
|
||||
String name = null;
|
||||
if ( sessionFactoryName == null ) {
|
||||
name = manager.getName();
|
||||
}
|
||||
else {
|
||||
name = "".equals( sessionFactoryName.trim() ) ? manager.getName() : sessionFactoryName;
|
||||
}
|
||||
registerBean( name, manager );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public synchronized void registerMBeanForCacheManager(final CacheManager manager, final Properties properties)
|
||||
throws Exception {
|
||||
String sessionFactoryName = properties.getProperty( Environment.SESSION_FACTORY_NAME );
|
||||
String name = null;
|
||||
if ( sessionFactoryName == null ) {
|
||||
name = manager.getName();
|
||||
}
|
||||
else {
|
||||
name = "".equals( sessionFactoryName.trim() ) ? manager.getName() : sessionFactoryName;
|
||||
}
|
||||
registerBean( name, manager );
|
||||
}
|
||||
private void registerBean(String name, CacheManager manager) throws Exception {
|
||||
ehcacheHibernate = new EhcacheHibernate( manager );
|
||||
int tries = 0;
|
||||
boolean success = false;
|
||||
Exception exception = null;
|
||||
cacheManagerClusterUUID = manager.getClusterUUID();
|
||||
do {
|
||||
this.registeredCacheManagerName = name;
|
||||
if ( tries != 0 ) {
|
||||
registeredCacheManagerName += "_" + tries;
|
||||
}
|
||||
try {
|
||||
// register the CacheManager MBean
|
||||
MBeanServer mBeanServer = getMBeanServer();
|
||||
cacheManagerObjectName = EhcacheHibernateMbeanNames.getCacheManagerObjectName(
|
||||
cacheManagerClusterUUID,
|
||||
registeredCacheManagerName
|
||||
);
|
||||
mBeanServer.registerMBean( ehcacheHibernate, cacheManagerObjectName );
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
catch ( InstanceAlreadyExistsException e ) {
|
||||
success = false;
|
||||
exception = e;
|
||||
}
|
||||
tries++;
|
||||
} while ( tries < MAX_MBEAN_REGISTRATION_RETRIES );
|
||||
if ( !success ) {
|
||||
throw new Exception(
|
||||
"Cannot register mbean for CacheManager with name" + manager.getName() + " after "
|
||||
+ MAX_MBEAN_REGISTRATION_RETRIES + " retries. Last tried name=" + registeredCacheManagerName,
|
||||
exception
|
||||
);
|
||||
}
|
||||
status = status.STATUS_ALIVE;
|
||||
}
|
||||
|
||||
private void registerBean(String name, CacheManager manager) throws Exception {
|
||||
ehcacheHibernate = new EhcacheHibernate( manager );
|
||||
int tries = 0;
|
||||
boolean success = false;
|
||||
Exception exception = null;
|
||||
cacheManagerClusterUUID = manager.getClusterUUID();
|
||||
do {
|
||||
this.registeredCacheManagerName = name;
|
||||
if ( tries != 0 ) {
|
||||
registeredCacheManagerName += "_" + tries;
|
||||
}
|
||||
try {
|
||||
// register the CacheManager MBean
|
||||
MBeanServer mBeanServer = getMBeanServer();
|
||||
cacheManagerObjectName = EhcacheHibernateMbeanNames.getCacheManagerObjectName(
|
||||
cacheManagerClusterUUID,
|
||||
registeredCacheManagerName
|
||||
);
|
||||
mBeanServer.registerMBean( ehcacheHibernate, cacheManagerObjectName );
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
catch ( InstanceAlreadyExistsException e ) {
|
||||
success = false;
|
||||
exception = e;
|
||||
}
|
||||
tries++;
|
||||
} while ( tries < MAX_MBEAN_REGISTRATION_RETRIES );
|
||||
if ( !success ) {
|
||||
throw new Exception(
|
||||
"Cannot register mbean for CacheManager with name" + manager.getName() + " after "
|
||||
+ MAX_MBEAN_REGISTRATION_RETRIES + " retries. Last tried name=" + registeredCacheManagerName,
|
||||
exception
|
||||
);
|
||||
}
|
||||
status = status.STATUS_ALIVE;
|
||||
}
|
||||
private MBeanServer getMBeanServer() {
|
||||
return ManagementFactory.getPlatformMBeanServer();
|
||||
}
|
||||
|
||||
private MBeanServer getMBeanServer() {
|
||||
return ManagementFactory.getPlatformMBeanServer();
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void enableHibernateStatisticsSupport(SessionFactory sessionFactory) {
|
||||
ehcacheHibernate.enableHibernateStatistics( sessionFactory );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void enableHibernateStatisticsSupport(SessionFactory sessionFactory) {
|
||||
ehcacheHibernate.enableHibernateStatistics( sessionFactory );
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public synchronized void dispose() throws CacheException {
|
||||
if ( status == Status.STATUS_SHUTDOWN ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public synchronized void dispose() throws CacheException {
|
||||
if ( status == Status.STATUS_SHUTDOWN ) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
getMBeanServer().unregisterMBean( cacheManagerObjectName );
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
LOG.warn(
|
||||
"Error unregistering object instance " + cacheManagerObjectName + " . Error was " + e.getMessage(),
|
||||
e
|
||||
);
|
||||
}
|
||||
ehcacheHibernate = null;
|
||||
cacheManagerObjectName = null;
|
||||
status = Status.STATUS_SHUTDOWN;
|
||||
}
|
||||
|
||||
try {
|
||||
getMBeanServer().unregisterMBean( cacheManagerObjectName );
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
LOG.warn(
|
||||
"Error unregistering object instance " + cacheManagerObjectName + " . Error was " + e.getMessage(),
|
||||
e
|
||||
);
|
||||
}
|
||||
ehcacheHibernate = null;
|
||||
cacheManagerObjectName = null;
|
||||
status = Status.STATUS_SHUTDOWN;
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public synchronized Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public synchronized Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
/**
|
||||
* No-op in this case
|
||||
*/
|
||||
public void init() throws CacheException {
|
||||
// no-op
|
||||
}
|
||||
|
||||
/**
|
||||
* No-op in this case
|
||||
*/
|
||||
public void init() throws CacheException {
|
||||
// no-op
|
||||
}
|
||||
/**
|
||||
* No-op in this case
|
||||
*/
|
||||
public void notifyCacheAdded(String cacheName) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
/**
|
||||
* No-op in this case
|
||||
*/
|
||||
public void notifyCacheAdded(String cacheName) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
/**
|
||||
* No-op in this case
|
||||
*/
|
||||
public void notifyCacheRemoved(String cacheName) {
|
||||
// no-op
|
||||
}
|
||||
/**
|
||||
* No-op in this case
|
||||
*/
|
||||
public void notifyCacheRemoved(String cacheName) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,11 +31,11 @@ import java.util.TimerTask;
|
|||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.EhCacheMessageLogger;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.internal.SessionFactoryRegistry;
|
||||
|
||||
|
@ -48,139 +48,141 @@ import org.hibernate.internal.SessionFactoryRegistry;
|
|||
* @author <a href="mailto:alexsnaps@terracottatech.com">Alex Snaps</a>
|
||||
*/
|
||||
public class ProviderMBeanRegistrationHelper {
|
||||
private static final Logger LOG = LoggerFactory.getLogger( ProviderMBeanRegistrationHelper.class );
|
||||
private static final EhCacheMessageLogger LOG = Logger.getMessageLogger(
|
||||
EhCacheMessageLogger.class,
|
||||
ProviderMBeanRegistrationHelper.class.getName()
|
||||
);
|
||||
private static final int MILLIS_PER_SECOND = 1000;
|
||||
private static final int SLEEP_MILLIS = 500;
|
||||
|
||||
private static final int MILLIS_PER_SECOND = 1000;
|
||||
private static final int SLEEP_MILLIS = 500;
|
||||
private volatile EhcacheHibernateMBeanRegistrationImpl ehcacheHibernateMBeanRegistration;
|
||||
|
||||
private volatile EhcacheHibernateMBeanRegistrationImpl ehcacheHibernateMBeanRegistration;
|
||||
/**
|
||||
* Registers mbean for the input cache manager and the session factory name
|
||||
*
|
||||
* @param manager the backing cachemanager
|
||||
* @param properties session factory config properties
|
||||
*/
|
||||
public void registerMBean(final CacheManager manager, final Properties properties) {
|
||||
if ( Boolean.getBoolean( "tc.active" ) ) {
|
||||
ehcacheHibernateMBeanRegistration = new EhcacheHibernateMBeanRegistrationImpl();
|
||||
manager.getTimer().scheduleAtFixedRate(
|
||||
new RegisterMBeansTask( ehcacheHibernateMBeanRegistration, manager, properties ), SLEEP_MILLIS,
|
||||
SLEEP_MILLIS
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers mbean for the input cache manager and the session factory name
|
||||
*
|
||||
* @param manager the backing cachemanager
|
||||
* @param properties session factory config properties
|
||||
*/
|
||||
public void registerMBean(final CacheManager manager, final Properties properties) {
|
||||
if ( Boolean.getBoolean( "tc.active" ) ) {
|
||||
ehcacheHibernateMBeanRegistration = new EhcacheHibernateMBeanRegistrationImpl();
|
||||
manager.getTimer().scheduleAtFixedRate(
|
||||
new RegisterMBeansTask( ehcacheHibernateMBeanRegistration, manager, properties ), SLEEP_MILLIS,
|
||||
SLEEP_MILLIS
|
||||
);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Unregisters previously registered mbean.
|
||||
*/
|
||||
public void unregisterMBean() {
|
||||
if ( ehcacheHibernateMBeanRegistration != null ) {
|
||||
ehcacheHibernateMBeanRegistration.dispose();
|
||||
ehcacheHibernateMBeanRegistration = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters previously registered mbean.
|
||||
*/
|
||||
public void unregisterMBean() {
|
||||
if ( ehcacheHibernateMBeanRegistration != null ) {
|
||||
ehcacheHibernateMBeanRegistration.dispose();
|
||||
ehcacheHibernateMBeanRegistration = null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Task for running mbean registration that can be scheduled in a timer
|
||||
*/
|
||||
private static class RegisterMBeansTask extends TimerTask {
|
||||
private static final int NUM_SECONDS = 30;
|
||||
private long startTime;
|
||||
private final AtomicBoolean mbeanRegistered = new AtomicBoolean( false );
|
||||
private final EhcacheHibernateMBeanRegistrationImpl ehcacheHibernateMBeanRegistration;
|
||||
private final CacheManager manager;
|
||||
private final Properties properties;
|
||||
|
||||
/**
|
||||
* Task for running mbean registration that can be scheduled in a timer
|
||||
*/
|
||||
private static class RegisterMBeansTask extends TimerTask {
|
||||
private static final int NUM_SECONDS = 30;
|
||||
private long startTime;
|
||||
private final AtomicBoolean mbeanRegistered = new AtomicBoolean( false );
|
||||
private final EhcacheHibernateMBeanRegistrationImpl ehcacheHibernateMBeanRegistration;
|
||||
private final CacheManager manager;
|
||||
private final Properties properties;
|
||||
public RegisterMBeansTask(EhcacheHibernateMBeanRegistrationImpl ehcacheHibernateMBeanRegistration,
|
||||
CacheManager manager, Properties properties) {
|
||||
this.ehcacheHibernateMBeanRegistration = ehcacheHibernateMBeanRegistration;
|
||||
this.manager = manager;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public RegisterMBeansTask(EhcacheHibernateMBeanRegistrationImpl ehcacheHibernateMBeanRegistration,
|
||||
CacheManager manager, Properties properties) {
|
||||
this.ehcacheHibernateMBeanRegistration = ehcacheHibernateMBeanRegistration;
|
||||
this.manager = manager;
|
||||
this.properties = properties;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
LOG.debug( "Running mbean initializer task for ehcache hibernate..." );
|
||||
startTime = System.currentTimeMillis();
|
||||
if ( mbeanRegistered.compareAndSet( false, true ) ) {
|
||||
try {
|
||||
ehcacheHibernateMBeanRegistration.registerMBeanForCacheManager( manager, properties );
|
||||
LOG.debug( "Successfully registered bean" );
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
SessionFactory sessionFactory = locateSessionFactory();
|
||||
if ( sessionFactory == null ) {
|
||||
LOG.debug(
|
||||
"SessionFactory is probably still being initialized..."
|
||||
+ " waiting for it to complete before enabling hibernate statistics monitoring via JMX"
|
||||
);
|
||||
if ( System.currentTimeMillis() > startTime + ( NUM_SECONDS * MILLIS_PER_SECOND ) ) {
|
||||
LOG.info( "Hibernate statistics monitoring through JMX is DISABLED." );
|
||||
LOG.info(
|
||||
"Failed to look up SessionFactory after " + NUM_SECONDS + " seconds using session-factory properties '"
|
||||
+ properties + "'"
|
||||
);
|
||||
this.cancel();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
ehcacheHibernateMBeanRegistration.enableHibernateStatisticsSupport( sessionFactory );
|
||||
LOG.info( "Hibernate statistics monitoring through JMX is ENABLED. " );
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
LOG.debug( "Running mbean initializer task for ehcache hibernate..." );
|
||||
startTime = System.currentTimeMillis();
|
||||
if ( mbeanRegistered.compareAndSet( false, true ) ) {
|
||||
try {
|
||||
ehcacheHibernateMBeanRegistration.registerMBeanForCacheManager( manager, properties );
|
||||
LOG.debug( "Successfully registered bean" );
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
SessionFactory sessionFactory = locateSessionFactory();
|
||||
if ( sessionFactory == null ) {
|
||||
LOG.debug(
|
||||
"SessionFactory is probably still being initialized..."
|
||||
+ " waiting for it to complete before enabling hibernate statistics monitoring via JMX"
|
||||
);
|
||||
if ( System.currentTimeMillis() > startTime + ( NUM_SECONDS * MILLIS_PER_SECOND ) ) {
|
||||
LOG.info( "Hibernate statistics monitoring through JMX is DISABLED." );
|
||||
LOG.info(
|
||||
"Failed to look up SessionFactory after " + NUM_SECONDS + " seconds using session-factory properties '"
|
||||
+ properties + "'"
|
||||
);
|
||||
this.cancel();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
ehcacheHibernateMBeanRegistration.enableHibernateStatisticsSupport( sessionFactory );
|
||||
LOG.info( "Hibernate statistics monitoring through JMX is ENABLED. " );
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
private SessionFactory locateSessionFactory() {
|
||||
String jndiName = properties.getProperty( Environment.SESSION_FACTORY_NAME );
|
||||
if ( jndiName != null ) {
|
||||
return SessionFactoryRegistry.INSTANCE.getNamedSessionFactory( jndiName );
|
||||
}
|
||||
try {
|
||||
Class factoryType = SessionFactoryRegistry.class;
|
||||
Field instancesField = getField( factoryType, "sessionFactoryMap" );
|
||||
if ( instancesField == null ) {
|
||||
throw new RuntimeException( "Expected 'sessionFactoryMap' field on " + SessionFactoryRegistry.class.getName() );
|
||||
}
|
||||
instancesField.setAccessible( true );
|
||||
Map map = (Map) instancesField.get( null );
|
||||
if ( map == null ) {
|
||||
return null;
|
||||
}
|
||||
Iterator values = map.values().iterator();
|
||||
while ( values.hasNext() ) {
|
||||
SessionFactory sessionFactory = (SessionFactory) values.next();
|
||||
Class sessionFactoryType = sessionFactory.getClass();
|
||||
Field propertiesField = getField( sessionFactoryType, "properties" );
|
||||
if ( propertiesField != null ) {
|
||||
propertiesField.setAccessible( true );
|
||||
Properties props = (Properties) propertiesField.get( sessionFactory );
|
||||
if ( props != null && props.equals( properties ) ) {
|
||||
return sessionFactory;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( RuntimeException re ) {
|
||||
LOG.error( "Error locating Hibernate Session Factory", re );
|
||||
}
|
||||
catch ( IllegalAccessException iae ) {
|
||||
LOG.error( "Error locating Hibernate Session Factory", iae );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private SessionFactory locateSessionFactory() {
|
||||
String jndiName = properties.getProperty( Environment.SESSION_FACTORY_NAME );
|
||||
if ( jndiName != null ) {
|
||||
return SessionFactoryRegistry.INSTANCE.getNamedSessionFactory( jndiName );
|
||||
}
|
||||
try {
|
||||
Class factoryType = SessionFactoryRegistry.class;
|
||||
Field instancesField = getField( factoryType, "sessionFactoryMap" );
|
||||
if ( instancesField == null ) {
|
||||
throw new RuntimeException( "Expected 'sessionFactoryMap' field on " + SessionFactoryRegistry.class.getName() );
|
||||
}
|
||||
instancesField.setAccessible( true );
|
||||
Map map = (Map) instancesField.get( null );
|
||||
if ( map == null ) {
|
||||
return null;
|
||||
}
|
||||
Iterator values = map.values().iterator();
|
||||
while ( values.hasNext() ) {
|
||||
SessionFactory sessionFactory = (SessionFactory) values.next();
|
||||
Class sessionFactoryType = sessionFactory.getClass();
|
||||
Field propertiesField = getField( sessionFactoryType, "properties" );
|
||||
if ( propertiesField != null ) {
|
||||
propertiesField.setAccessible( true );
|
||||
Properties props = (Properties) propertiesField.get( sessionFactory );
|
||||
if ( props != null && props.equals( properties ) ) {
|
||||
return sessionFactory;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( RuntimeException re ) {
|
||||
LOG.error( "Error locating Hibernate Session Factory", re );
|
||||
}
|
||||
catch ( IllegalAccessException iae ) {
|
||||
LOG.error( "Error locating Hibernate Session Factory", iae );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Field getField(Class c, String fieldName) {
|
||||
for ( Field field : c.getDeclaredFields() ) {
|
||||
if ( field.getName().equals( fieldName ) ) {
|
||||
return field;
|
||||
}
|
||||
}
|
||||
throw new NoSuchFieldError( "Type '" + c + "' has no field '" + fieldName + "'" );
|
||||
}
|
||||
private static Field getField(Class c, String fieldName) {
|
||||
for ( Field field : c.getDeclaredFields() ) {
|
||||
if ( field.getName().equals( fieldName ) ) {
|
||||
return field;
|
||||
}
|
||||
}
|
||||
throw new NoSuchFieldError( "Type '" + c + "' has no field '" + fieldName + "'" );
|
||||
}
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.nonstop;
|
||||
|
||||
import net.sf.ehcache.constructs.nonstop.NonStopCacheException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Class that takes care of {@link net.sf.ehcache.constructs.nonstop.NonStopCacheException} that happens in hibernate module
|
||||
*
|
||||
* @author Abhishek Sanoujam
|
||||
* @author Alex Snaps
|
||||
*/
|
||||
public final class HibernateNonstopCacheExceptionHandler {
|
||||
/**
|
||||
* Property name which set as "true" will throw exceptions on timeout with hibernate
|
||||
*/
|
||||
public static final String HIBERNATE_THROW_EXCEPTION_ON_TIMEOUT_PROPERTY = "ehcache.hibernate.propagateNonStopCacheException";
|
||||
|
||||
/**
|
||||
* Property name for logging the stack trace of the nonstop cache exception too. False by default
|
||||
*/
|
||||
public static final String HIBERNATE_LOG_EXCEPTION_STACK_TRACE_PROPERTY = "ehcache.hibernate.logNonStopCacheExceptionStackTrace";
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger( HibernateNonstopCacheExceptionHandler.class );
|
||||
|
||||
private static final HibernateNonstopCacheExceptionHandler INSTANCE = new HibernateNonstopCacheExceptionHandler();
|
||||
|
||||
/**
|
||||
* private constructor
|
||||
*/
|
||||
private HibernateNonstopCacheExceptionHandler() {
|
||||
// private
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the singleton instance
|
||||
*
|
||||
* @return the singleton instance
|
||||
*/
|
||||
public static HibernateNonstopCacheExceptionHandler getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle {@link net.sf.ehcache.constructs.nonstop.NonStopCacheException}.
|
||||
* If {@link HibernateNonstopCacheExceptionHandler#HIBERNATE_THROW_EXCEPTION_ON_TIMEOUT_PROPERTY} system property is set to true,
|
||||
* rethrows the {@link net.sf.ehcache.constructs.nonstop.NonStopCacheException}, otherwise logs the exception. While logging, if
|
||||
* {@link HibernateNonstopCacheExceptionHandler#HIBERNATE_LOG_EXCEPTION_STACK_TRACE_PROPERTY} is set to true, logs the exception stack
|
||||
* trace too, otherwise logs the exception message only
|
||||
*
|
||||
* @param nonStopCacheException
|
||||
*/
|
||||
public void handleNonstopCacheException(NonStopCacheException nonStopCacheException) {
|
||||
if ( Boolean.getBoolean( HIBERNATE_THROW_EXCEPTION_ON_TIMEOUT_PROPERTY ) ) {
|
||||
throw nonStopCacheException;
|
||||
}
|
||||
else {
|
||||
if ( Boolean.getBoolean( HIBERNATE_LOG_EXCEPTION_STACK_TRACE_PROPERTY ) ) {
|
||||
LOGGER.debug(
|
||||
"Ignoring NonstopCacheException - " + nonStopCacheException.getMessage(),
|
||||
nonStopCacheException
|
||||
);
|
||||
}
|
||||
else {
|
||||
LOGGER.debug( "Ignoring NonstopCacheException - " + nonStopCacheException.getMessage() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.nonstop;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheCollectionRegion;
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheEntityRegion;
|
||||
import org.hibernate.cache.ehcache.strategy.EhcacheAccessStrategyFactory;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
|
||||
/**
|
||||
* Implementation of {@link org.hibernate.cache.ehcache.strategy.EhcacheAccessStrategyFactory} that takes care of Nonstop cache exceptions using
|
||||
* {@link HibernateNonstopCacheExceptionHandler}
|
||||
*
|
||||
* @author Abhishek Sanoujam
|
||||
* @author Alex Snaps
|
||||
*/
|
||||
public class NonstopAccessStrategyFactory implements EhcacheAccessStrategyFactory {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger( NonstopAccessStrategyFactory.class );
|
||||
private final EhcacheAccessStrategyFactory actualFactory;
|
||||
|
||||
/**
|
||||
* Constructor accepting the actual factory
|
||||
*
|
||||
* @param actualFactory
|
||||
*/
|
||||
public NonstopAccessStrategyFactory(EhcacheAccessStrategyFactory actualFactory) {
|
||||
this.actualFactory = actualFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public EntityRegionAccessStrategy createEntityRegionAccessStrategy(EhcacheEntityRegion entityRegion, AccessType accessType) {
|
||||
return new NonstopAwareEntityRegionAccessStrategy(
|
||||
actualFactory.createEntityRegionAccessStrategy( entityRegion, accessType ),
|
||||
HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public CollectionRegionAccessStrategy createCollectionRegionAccessStrategy(EhcacheCollectionRegion collectionRegion,
|
||||
AccessType accessType) {
|
||||
return new NonstopAwareCollectionRegionAccessStrategy(
|
||||
actualFactory.createCollectionRegionAccessStrategy(
|
||||
collectionRegion,
|
||||
accessType
|
||||
), HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,223 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package org.hibernate.cache.ehcache.regions;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import net.sf.ehcache.constructs.nonstop.NonStopCacheException;
|
||||
import net.sf.ehcache.util.Timestamper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.nonstop.HibernateNonstopCacheExceptionHandler;
|
||||
import org.hibernate.cache.ehcache.strategy.EhcacheAccessStrategyFactory;
|
||||
import org.hibernate.cache.spi.Region;
|
||||
|
||||
/**
|
||||
* An Ehcache specific data region implementation.
|
||||
* <p/>
|
||||
* This class is the ultimate superclass for all Ehcache Hibernate cache regions.
|
||||
*
|
||||
* @author Chris Dennis
|
||||
* @author Greg Luck
|
||||
* @author Emmanuel Bernard
|
||||
* @author Abhishek Sanoujam
|
||||
* @author Alex Snaps
|
||||
*/
|
||||
public abstract class EhcacheDataRegion implements Region {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger( EhcacheDataRegion.class );
|
||||
|
||||
private static final String CACHE_LOCK_TIMEOUT_PROPERTY = "net.sf.ehcache.hibernate.cache_lock_timeout";
|
||||
private static final int DEFAULT_CACHE_LOCK_TIMEOUT = 60000;
|
||||
|
||||
/**
|
||||
* Ehcache instance backing this Hibernate data region.
|
||||
*/
|
||||
protected final Ehcache cache;
|
||||
|
||||
/**
|
||||
* The {@link EhcacheAccessStrategyFactory} used for creating various access strategies
|
||||
*/
|
||||
protected final EhcacheAccessStrategyFactory accessStrategyFactory;
|
||||
|
||||
private final int cacheLockTimeout;
|
||||
|
||||
|
||||
/**
|
||||
* Create a Hibernate data region backed by the given Ehcache instance.
|
||||
*/
|
||||
EhcacheDataRegion(EhcacheAccessStrategyFactory accessStrategyFactory, Ehcache cache, Properties properties) {
|
||||
this.accessStrategyFactory = accessStrategyFactory;
|
||||
this.cache = cache;
|
||||
String timeout = properties.getProperty(
|
||||
CACHE_LOCK_TIMEOUT_PROPERTY,
|
||||
Integer.toString( DEFAULT_CACHE_LOCK_TIMEOUT )
|
||||
);
|
||||
this.cacheLockTimeout = Timestamper.ONE_MS * Integer.decode( timeout );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String getName() {
|
||||
return cache.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void destroy() throws CacheException {
|
||||
try {
|
||||
cache.getCacheManager().removeCache( cache.getName() );
|
||||
}
|
||||
catch ( IllegalStateException e ) {
|
||||
//When Spring and Hibernate are both involved this will happen in normal shutdown operation.
|
||||
//Do not throw an exception, simply log this one.
|
||||
LOG.debug( "This can happen if multiple frameworks both try to shutdown ehcache", e );
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
if ( e instanceof NonStopCacheException ) {
|
||||
HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
.handleNonstopCacheException( (NonStopCacheException) e );
|
||||
}
|
||||
else {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public long getSizeInMemory() {
|
||||
try {
|
||||
return cache.calculateInMemorySize();
|
||||
}
|
||||
catch ( Throwable t ) {
|
||||
if ( t instanceof NonStopCacheException ) {
|
||||
HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
.handleNonstopCacheException( (NonStopCacheException) t );
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public long getElementCountInMemory() {
|
||||
try {
|
||||
return cache.getMemoryStoreSize();
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException ce ) {
|
||||
if ( ce instanceof NonStopCacheException ) {
|
||||
HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
.handleNonstopCacheException( (NonStopCacheException) ce );
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
throw new CacheException( ce );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public long getElementCountOnDisk() {
|
||||
try {
|
||||
return cache.getDiskStoreSize();
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException ce ) {
|
||||
if ( ce instanceof NonStopCacheException ) {
|
||||
HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
.handleNonstopCacheException( (NonStopCacheException) ce );
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
throw new CacheException( ce );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Map toMap() {
|
||||
try {
|
||||
Map<Object, Object> result = new HashMap<Object, Object>();
|
||||
for ( Object key : cache.getKeys() ) {
|
||||
result.put( key, cache.get( key ).getObjectValue() );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
if ( e instanceof NonStopCacheException ) {
|
||||
HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
.handleNonstopCacheException( (NonStopCacheException) e );
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
else {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public long nextTimestamp() {
|
||||
return Timestamper.next();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int getTimeout() {
|
||||
return cacheLockTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Ehcache instance backing this Hibernate data region.
|
||||
*/
|
||||
public Ehcache getEhcache() {
|
||||
return cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this region contains data for the given key.
|
||||
* <p/>
|
||||
* This is a Hibernate 3.5 method.
|
||||
*/
|
||||
public boolean contains(Object key) {
|
||||
return cache.isKeyInCache( key );
|
||||
}
|
||||
}
|
|
@ -1,163 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.regions;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import net.sf.ehcache.Ehcache;
|
||||
import net.sf.ehcache.Element;
|
||||
import net.sf.ehcache.constructs.nonstop.NonStopCacheException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.nonstop.HibernateNonstopCacheExceptionHandler;
|
||||
import org.hibernate.cache.ehcache.strategy.EhcacheAccessStrategyFactory;
|
||||
import org.hibernate.cache.spi.GeneralDataRegion;
|
||||
|
||||
/**
|
||||
* An Ehcache specific GeneralDataRegion.
|
||||
* <p/>
|
||||
* GeneralDataRegion instances are used for both the timestamps and query caches.
|
||||
*
|
||||
* @author Chris Dennis
|
||||
* @author Greg Luck
|
||||
* @author Emmanuel Bernard
|
||||
* @author Abhishek Sanoujam
|
||||
* @author Alex Snaps
|
||||
*/
|
||||
abstract class EhcacheGeneralDataRegion extends EhcacheDataRegion implements GeneralDataRegion {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger( EhcacheGeneralDataRegion.class );
|
||||
|
||||
/**
|
||||
* Creates an EhcacheGeneralDataRegion using the given Ehcache instance as a backing.
|
||||
*/
|
||||
public EhcacheGeneralDataRegion(EhcacheAccessStrategyFactory accessStrategyFactory, Ehcache cache, Properties properties) {
|
||||
super( accessStrategyFactory, cache, properties );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Object get(Object key) throws CacheException {
|
||||
try {
|
||||
LOG.debug( "key: {}", key );
|
||||
if ( key == null ) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
Element element = cache.get( key );
|
||||
if ( element == null ) {
|
||||
LOG.debug( "Element for key {} is null", key );
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return element.getObjectValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
if ( e instanceof NonStopCacheException ) {
|
||||
HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
.handleNonstopCacheException( (NonStopCacheException) e );
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void put(Object key, Object value) throws CacheException {
|
||||
LOG.debug( "key: {} value: {}", key, value );
|
||||
try {
|
||||
Element element = new Element( key, value );
|
||||
cache.put( element );
|
||||
}
|
||||
catch ( IllegalArgumentException e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
catch ( IllegalStateException e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
if ( e instanceof NonStopCacheException ) {
|
||||
HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
.handleNonstopCacheException( (NonStopCacheException) e );
|
||||
}
|
||||
else {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void evict(Object key) throws CacheException {
|
||||
try {
|
||||
cache.remove( key );
|
||||
}
|
||||
catch ( ClassCastException e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
catch ( IllegalStateException e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
if ( e instanceof NonStopCacheException ) {
|
||||
HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
.handleNonstopCacheException( (NonStopCacheException) e );
|
||||
}
|
||||
else {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void evictAll() throws CacheException {
|
||||
try {
|
||||
cache.removeAll();
|
||||
}
|
||||
catch ( IllegalStateException e ) {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
catch ( net.sf.ehcache.CacheException e ) {
|
||||
if ( e instanceof NonStopCacheException ) {
|
||||
HibernateNonstopCacheExceptionHandler.getInstance()
|
||||
.handleNonstopCacheException( (NonStopCacheException) e );
|
||||
}
|
||||
else {
|
||||
throw new CacheException( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,428 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.strategy;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Comparator;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheTransactionalDataRegion;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.cfg.Settings;
|
||||
|
||||
/**
|
||||
* Superclass for all Ehcache specific read/write AccessStrategy implementations.
|
||||
*
|
||||
* @param <T> the type of the enclosed cache region
|
||||
*
|
||||
* @author Chris Dennis
|
||||
* @author Alex Snaps
|
||||
*/
|
||||
abstract class AbstractReadWriteEhcacheAccessStrategy<T extends EhcacheTransactionalDataRegion>
|
||||
extends AbstractEhcacheAccessStrategy<T> {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger( AbstractReadWriteEhcacheAccessStrategy.class );
|
||||
|
||||
private final UUID uuid = UUID.randomUUID();
|
||||
private final AtomicLong nextLockId = new AtomicLong();
|
||||
|
||||
private final Comparator versionComparator;
|
||||
|
||||
/**
|
||||
* Creates a read/write cache access strategy around the given cache region.
|
||||
*/
|
||||
public AbstractReadWriteEhcacheAccessStrategy(T region, Settings settings) {
|
||||
super( region, settings );
|
||||
this.versionComparator = region.getCacheDataDescription().getVersionComparator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>null</code> if the item is not readable. Locked items are not readable, nor are items created
|
||||
* after the start of this transaction.
|
||||
*
|
||||
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#get(java.lang.Object, long)
|
||||
* @see org.hibernate.cache.spi.access.CollectionRegionAccessStrategy#get(java.lang.Object, long)
|
||||
*/
|
||||
public final Object get(Object key, long txTimestamp) throws CacheException {
|
||||
readLockIfNeeded( key );
|
||||
try {
|
||||
Lockable item = (Lockable) region.get( key );
|
||||
|
||||
boolean readable = item != null && item.isReadable( txTimestamp );
|
||||
if ( readable ) {
|
||||
return item.getValue();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
readUnlockIfNeeded( key );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>false</code> and fails to put the value if there is an existing un-writeable item mapped to this
|
||||
* key.
|
||||
*
|
||||
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object, boolean)
|
||||
* @see org.hibernate.cache.spi.access.CollectionRegionAccessStrategy#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object, boolean)
|
||||
*/
|
||||
@Override
|
||||
public final boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
|
||||
throws CacheException {
|
||||
region.writeLock( key );
|
||||
try {
|
||||
Lockable item = (Lockable) region.get( key );
|
||||
boolean writeable = item == null || item.isWriteable( txTimestamp, version, versionComparator );
|
||||
if ( writeable ) {
|
||||
region.put( key, new Item( value, version, region.nextTimestamp() ) );
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
region.writeUnlock( key );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Soft-lock a cache item.
|
||||
*
|
||||
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#lockItem(java.lang.Object, java.lang.Object)
|
||||
* @see org.hibernate.cache.spi.access.CollectionRegionAccessStrategy#lockItem(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
public final SoftLock lockItem(Object key, Object version) throws CacheException {
|
||||
region.writeLock( key );
|
||||
try {
|
||||
Lockable item = (Lockable) region.get( key );
|
||||
long timeout = region.nextTimestamp() + region.getTimeout();
|
||||
final Lock lock = ( item == null ) ? new Lock( timeout, uuid, nextLockId(), version ) : item.lock(
|
||||
timeout,
|
||||
uuid,
|
||||
nextLockId()
|
||||
);
|
||||
region.put( key, lock );
|
||||
return lock;
|
||||
}
|
||||
finally {
|
||||
region.writeUnlock( key );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Soft-unlock a cache item.
|
||||
*
|
||||
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#unlockItem(java.lang.Object, org.hibernate.cache.spi.access.SoftLock)
|
||||
* @see org.hibernate.cache.spi.access.CollectionRegionAccessStrategy#unlockItem(java.lang.Object, org.hibernate.cache.spi.access.SoftLock)
|
||||
*/
|
||||
public final void unlockItem(Object key, SoftLock lock) throws CacheException {
|
||||
region.writeLock( key );
|
||||
try {
|
||||
Lockable item = (Lockable) region.get( key );
|
||||
|
||||
if ( ( item != null ) && item.isUnlockable( lock ) ) {
|
||||
decrementLock( key, (Lock) item );
|
||||
}
|
||||
else {
|
||||
handleLockExpiry( key, item );
|
||||
}
|
||||
}
|
||||
finally {
|
||||
region.writeUnlock( key );
|
||||
}
|
||||
}
|
||||
|
||||
private long nextLockId() {
|
||||
return nextLockId.getAndIncrement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock and re-put the given key, lock combination.
|
||||
*/
|
||||
protected void decrementLock(Object key, Lock lock) {
|
||||
lock.unlock( region.nextTimestamp() );
|
||||
region.put( key, lock );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the timeout of a previous lock mapped to this key
|
||||
*/
|
||||
protected void handleLockExpiry(Object key, Lockable lock) {
|
||||
LOG.warn(
|
||||
"Cache " + region.getName() + " Key " + key + " Lockable : " + lock + "\n"
|
||||
+ "A soft-locked cache entry was expired by the underlying Ehcache. "
|
||||
+ "If this happens regularly you should consider increasing the cache timeouts and/or capacity limits"
|
||||
);
|
||||
long ts = region.nextTimestamp() + region.getTimeout();
|
||||
// create new lock that times out immediately
|
||||
Lock newLock = new Lock( ts, uuid, nextLockId.getAndIncrement(), null );
|
||||
newLock.unlock( ts );
|
||||
region.put( key, newLock );
|
||||
}
|
||||
|
||||
/**
|
||||
* Read lock the entry for the given key if internal cache locks will not provide correct exclusion.
|
||||
*/
|
||||
private void readLockIfNeeded(Object key) {
|
||||
if ( region.locksAreIndependentOfCache() ) {
|
||||
region.readLock( key );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read unlock the entry for the given key if internal cache locks will not provide correct exclusion.
|
||||
*/
|
||||
private void readUnlockIfNeeded(Object key) {
|
||||
if ( region.locksAreIndependentOfCache() ) {
|
||||
region.readUnlock( key );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface type implemented by all wrapper objects in the cache.
|
||||
*/
|
||||
protected static interface Lockable {
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the enclosed value can be read by a transaction started at the given time.
|
||||
*/
|
||||
public boolean isReadable(long txTimestamp);
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the enclosed value can be replaced with one of the given version by a
|
||||
* transaction started at the given time.
|
||||
*/
|
||||
public boolean isWriteable(long txTimestamp, Object version, Comparator versionComparator);
|
||||
|
||||
/**
|
||||
* Returns the enclosed value.
|
||||
*/
|
||||
public Object getValue();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the given lock can be unlocked using the given SoftLock instance as a handle.
|
||||
*/
|
||||
public boolean isUnlockable(SoftLock lock);
|
||||
|
||||
/**
|
||||
* Locks this entry, stamping it with the UUID and lockId given, with the lock timeout occuring at the specified
|
||||
* time. The returned Lock object can be used to unlock the entry in the future.
|
||||
*/
|
||||
public Lock lock(long timeout, UUID uuid, long lockId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper type representing unlocked items.
|
||||
*/
|
||||
protected final static class Item implements Serializable, Lockable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final Object value;
|
||||
private final Object version;
|
||||
private final long timestamp;
|
||||
|
||||
/**
|
||||
* Creates an unlocked item wrapping the given value with a version and creation timestamp.
|
||||
*/
|
||||
Item(Object value, Object version, long timestamp) {
|
||||
this.value = value;
|
||||
this.version = version;
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isReadable(long txTimestamp) {
|
||||
return txTimestamp > timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isWriteable(long txTimestamp, Object newVersion, Comparator versionComparator) {
|
||||
return version != null && versionComparator.compare( version, newVersion ) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isUnlockable(SoftLock lock) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Lock lock(long timeout, UUID uuid, long lockId) {
|
||||
return new Lock( timeout, uuid, lockId, version );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper type representing locked items.
|
||||
*/
|
||||
protected final static class Lock implements Serializable, Lockable, SoftLock {
|
||||
|
||||
private static final long serialVersionUID = 2L;
|
||||
|
||||
private final UUID sourceUuid;
|
||||
private final long lockId;
|
||||
private final Object version;
|
||||
|
||||
private long timeout;
|
||||
private boolean concurrent;
|
||||
private int multiplicity = 1;
|
||||
private long unlockTimestamp;
|
||||
|
||||
/**
|
||||
* Creates a locked item with the given identifiers and object version.
|
||||
*/
|
||||
Lock(long timeout, UUID sourceUuid, long lockId, Object version) {
|
||||
this.timeout = timeout;
|
||||
this.lockId = lockId;
|
||||
this.version = version;
|
||||
this.sourceUuid = sourceUuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isReadable(long txTimestamp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isWriteable(long txTimestamp, Object newVersion, Comparator versionComparator) {
|
||||
if ( txTimestamp > timeout ) {
|
||||
// if timedout then allow write
|
||||
return true;
|
||||
}
|
||||
if ( multiplicity > 0 ) {
|
||||
// if still locked then disallow write
|
||||
return false;
|
||||
}
|
||||
return version == null ? txTimestamp > unlockTimestamp : versionComparator.compare(
|
||||
version,
|
||||
newVersion
|
||||
) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Object getValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean isUnlockable(SoftLock lock) {
|
||||
return equals( lock );
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( o == this ) {
|
||||
return true;
|
||||
}
|
||||
else if ( o instanceof Lock ) {
|
||||
return ( lockId == ( (Lock) o ).lockId ) && sourceUuid.equals( ( (Lock) o ).sourceUuid );
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = ( sourceUuid != null ? sourceUuid.hashCode() : 0 );
|
||||
int temp = (int) lockId;
|
||||
for ( int i = 1; i < Long.SIZE / Integer.SIZE; i++ ) {
|
||||
temp ^= ( lockId >>> ( i * Integer.SIZE ) );
|
||||
}
|
||||
return hash + temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this Lock has been concurrently locked by more than one transaction.
|
||||
*/
|
||||
public boolean wasLockedConcurrently() {
|
||||
return concurrent;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Lock lock(long timeout, UUID uuid, long lockId) {
|
||||
concurrent = true;
|
||||
multiplicity++;
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks this Lock, and timestamps the unlock event.
|
||||
*/
|
||||
public void unlock(long timestamp) {
|
||||
if ( --multiplicity == 0 ) {
|
||||
unlockTimestamp = timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder( "Lock Source-UUID:" + sourceUuid + " Lock-ID:" + lockId );
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cache.ehcache.strategy;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheCollectionRegion;
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheEntityRegion;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
|
||||
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
|
||||
|
||||
/**
|
||||
* Class implementing {@link EhcacheAccessStrategyFactory}
|
||||
*
|
||||
* @author Abhishek Sanoujam
|
||||
* @author Alex Snaps
|
||||
*/
|
||||
public class EhcacheAccessStrategyFactoryImpl implements EhcacheAccessStrategyFactory {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger( EhcacheAccessStrategyFactoryImpl.class );
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public EntityRegionAccessStrategy createEntityRegionAccessStrategy(EhcacheEntityRegion entityRegion, AccessType accessType) {
|
||||
if ( AccessType.READ_ONLY.equals( accessType ) ) {
|
||||
if ( entityRegion.getCacheDataDescription().isMutable() ) {
|
||||
LOG.warn( "read-only cache configured for mutable entity [" + entityRegion.getName() + "]" );
|
||||
}
|
||||
return new ReadOnlyEhcacheEntityRegionAccessStrategy( entityRegion, entityRegion.getSettings() );
|
||||
}
|
||||
else if ( AccessType.READ_WRITE.equals( accessType ) ) {
|
||||
return new ReadWriteEhcacheEntityRegionAccessStrategy( entityRegion, entityRegion.getSettings() );
|
||||
}
|
||||
else if ( AccessType.NONSTRICT_READ_WRITE.equals( accessType ) ) {
|
||||
return new NonStrictReadWriteEhcacheEntityRegionAccessStrategy( entityRegion, entityRegion.getSettings() );
|
||||
}
|
||||
else if ( AccessType.TRANSACTIONAL.equals( accessType ) ) {
|
||||
return new TransactionalEhcacheEntityRegionAccessStrategy(
|
||||
entityRegion,
|
||||
entityRegion.getEhcache(),
|
||||
entityRegion.getSettings()
|
||||
);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException( "unrecognized access strategy type [" + accessType + "]" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public CollectionRegionAccessStrategy createCollectionRegionAccessStrategy(EhcacheCollectionRegion collectionRegion,
|
||||
AccessType accessType) {
|
||||
if ( AccessType.READ_ONLY.equals( accessType ) ) {
|
||||
if ( collectionRegion.getCacheDataDescription().isMutable() ) {
|
||||
LOG.warn( "read-only cache configured for mutable entity [" + collectionRegion.getName() + "]" );
|
||||
}
|
||||
return new ReadOnlyEhcacheCollectionRegionAccessStrategy(
|
||||
collectionRegion,
|
||||
collectionRegion.getSettings()
|
||||
);
|
||||
}
|
||||
else if ( AccessType.READ_WRITE.equals( accessType ) ) {
|
||||
return new ReadWriteEhcacheCollectionRegionAccessStrategy(
|
||||
collectionRegion,
|
||||
collectionRegion.getSettings()
|
||||
);
|
||||
}
|
||||
else if ( AccessType.NONSTRICT_READ_WRITE.equals( accessType ) ) {
|
||||
return new NonStrictReadWriteEhcacheCollectionRegionAccessStrategy(
|
||||
collectionRegion,
|
||||
collectionRegion.getSettings()
|
||||
);
|
||||
}
|
||||
else if ( AccessType.TRANSACTIONAL.equals( accessType ) ) {
|
||||
return new TransactionalEhcacheCollectionRegionAccessStrategy(
|
||||
collectionRegion, collectionRegion.getEhcache(), collectionRegion
|
||||
.getSettings()
|
||||
);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException( "unrecognized access strategy type [" + accessType + "]" );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
package org.hibernate.cache.ehcache.strategy;
|
||||
package org.hibernate.cache.ehcache.internal.strategy;
|
||||
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheTransactionalDataRegion;
|
||||
import org.hibernate.cache.ehcache.regions.EhcacheTransactionalDataRegion;
|
||||
import org.hibernate.cache.ehcache.strategy.AbstractReadWriteEhcacheAccessStrategy;
|
||||
import org.hibernate.cache.ehcache.internal.regions.EhcacheTransactionalDataRegion;
|
||||
import org.hibernate.cache.ehcache.internal.strategy.AbstractReadWriteEhcacheAccessStrategy;
|
||||
import org.hibernate.cfg.Settings;
|
||||
|
||||
|
|
@ -6,7 +6,7 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.cache.ehcache.strategy.ItemValueExtractor;
|
||||
import org.hibernate.cache.ehcache.internal.strategy.ItemValueExtractor;
|
||||
import org.hibernate.cache.spi.access.SoftLock;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.stat.QueryStatistics;
|
||||
|
|
|
@ -21,7 +21,7 @@ public class EhCacheRegionFactoryImpl extends EhCacheTest {
|
|||
@Override
|
||||
protected Map getMapFromCacheEntry(final Object entry) {
|
||||
final Map map;
|
||||
if ( "org.hibernate.cache.ehcache.strategy.AbstractReadWriteEhcacheAccessStrategy$Item".equals(
|
||||
if ( "org.hibernate.cache.ehcache.internal.strategy.AbstractReadWriteEhcacheAccessStrategy$Item".equals(
|
||||
entry.getClass()
|
||||
.getName()
|
||||
) ) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package org.hibernate.test.cache.ehcache;
|
||||
|
||||
import org.hibernate.cache.ehcache.EhCacheRegionFactory;
|
||||
import org.hibernate.cache.ehcache.strategy.ItemValueExtractor;
|
||||
import org.hibernate.cache.ehcache.internal.strategy.ItemValueExtractor;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
|
||||
|
@ -22,7 +22,7 @@ public class EhCacheRegionTest extends EhCacheTest {
|
|||
final Map map;
|
||||
if ( entry.getClass()
|
||||
.getName()
|
||||
.equals( "org.hibernate.cache.ehcache.strategy.AbstractReadWriteEhcacheAccessStrategy$Item" ) ) {
|
||||
.equals( "org.hibernate.cache.ehcache.internal.strategy.AbstractReadWriteEhcacheAccessStrategy$Item" ) ) {
|
||||
map = ItemValueExtractor.getValue( entry );
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -189,7 +189,7 @@ public abstract class EhCacheTest extends BaseCoreFunctionalTestCase {
|
|||
// } else
|
||||
if ( entry.getClass()
|
||||
.getName()
|
||||
.equals( "org.hibernate.cache.ehcache.strategy.AbstractReadWriteEhcacheAccessStrategy$Lock" ) ) {
|
||||
.equals( "org.hibernate.cache.ehcache.internal.strategy.AbstractReadWriteEhcacheAccessStrategy$Lock" ) ) {
|
||||
//FIXME don't know what to test here
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
*/
|
||||
package org.hibernate.test.domain;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
|
@ -27,7 +26,6 @@ import java.util.Map;
|
|||
|
||||
public class HolidayCalendar {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(HolidayCalendar.class);
|
||||
|
||||
private Long id;
|
||||
// Date -> String
|
||||
|
@ -41,7 +39,6 @@ public class HolidayCalendar {
|
|||
holidays.put(df.parse("2009.02.14"), "Valentine's Day");
|
||||
holidays.put(df.parse("2009.11.11"), "Armistice Day");
|
||||
} catch (ParseException e) {
|
||||
LOG.info("Error parsing date string");
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
|
|
Loading…
Reference in New Issue