HHH-6451 adapt hibernate-ehcache to the new api

This commit is contained in:
Strong Liu 2011-07-19 01:50:18 +08:00
parent c26a23bf90
commit d0476de7f8
44 changed files with 1877 additions and 1868 deletions

View File

@ -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 )
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}
}

View File

@ -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;
}
}

View File

@ -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() );
}
}
}
}

View File

@ -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()
);
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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 );
}
}

View 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 );
}
}

View File

@ -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 );
}
}

View File

@ -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 );
}
}
}
}

View File

@ -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;
/**

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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();
}
}
}

View File

@ -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

View File

@ -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 + "]" );
}
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View 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;
}
}
}
}

View File

@ -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
}
}

View File

@ -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 + "'" );
}
}

View File

@ -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() );
}
}
}
}

View File

@ -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()
);
}
}

View File

@ -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 );
}
}

View File

@ -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 );
}
}
}
}

View File

@ -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();
}
}
}

View File

@ -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 + "]" );
}
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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()
) ) {

View File

@ -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 {

View File

@ -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 {

View File

@ -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;