EHC-864 Moved all Hibernate dependent classes from ehcache-core to hibernate-ehcache module and fixed to use new API

This commit is contained in:
Alex Snaps 2011-07-14 15:14:35 +02:00 committed by Strong Liu
parent c7421837a4
commit c26a23bf90
71 changed files with 9279 additions and 184 deletions

View File

@ -66,7 +66,8 @@ public class RegionFactoryInitiator implements BasicServiceInitiator<RegionFacto
customImplClass = (Class<? extends RegionFactory>) impl;
}
else {
customImplClass = registry.getService( ClassLoaderService.class ).classForName( impl.toString() );
customImplClass = registry.getService( ClassLoaderService.class )
.classForName( mapLegacyNames( impl.toString() ) );
}
try {
@ -78,4 +79,18 @@ public class RegionFactoryInitiator implements BasicServiceInitiator<RegionFacto
);
}
}
// todo this shouldn't be public (nor really static):
// hack for org.hibernate.cfg.SettingsFactory.createRegionFactory()
public static String mapLegacyNames(final String name) {
if ( "org.hibernate.cache.EhCacheRegionFactory".equals( name ) ) {
return "org.hibernate.cache.ehcache.EhCacheRegionFactory";
}
if ( "org.hibernate.cache.SingletonEhCacheRegionFactory".equals( name ) ) {
return "org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory";
}
return name;
}
}

View File

@ -34,6 +34,7 @@ import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.MultiTenancyStrategy;
import org.hibernate.cache.internal.NoCachingRegionFactory;
import org.hibernate.cache.internal.RegionFactoryInitiator;
import org.hibernate.cache.internal.StandardQueryCacheFactory;
import org.hibernate.cache.spi.QueryCacheFactory;
import org.hibernate.cache.spi.RegionFactory;
@ -323,8 +324,10 @@ public class SettingsFactory implements Serializable {
}
private static RegionFactory createRegionFactory(Properties properties, boolean cachingEnabled, ServiceRegistry serviceRegistry) {
String regionFactoryClassName = ConfigurationHelper.getString(
String regionFactoryClassName = RegionFactoryInitiator.mapLegacyNames(
ConfigurationHelper.getString(
Environment.CACHE_REGION_FACTORY, properties, null
)
);
if ( regionFactoryClassName == null || !cachingEnabled) {
regionFactoryClassName = DEF_CACHE_REG_FACTORY;
@ -354,9 +357,11 @@ public class SettingsFactory implements Serializable {
}
//todo remove this once we move to new metamodel
public static RegionFactory createRegionFactory(Properties properties, boolean cachingEnabled) {
// todo : REMOVE! THIS IS TOTALLY A TEMPORARY HACK FOR org.hibernate.cfg.AnnotationSourceProcessor which will be going away
String regionFactoryClassName = ConfigurationHelper.getString(
// todo : REMOVE! THIS IS TOTALLY A TEMPORARY HACK FOR org.hibernate.cfg.AnnotationBinder which will be going away
String regionFactoryClassName = RegionFactoryInitiator.mapLegacyNames(
ConfigurationHelper.getString(
Environment.CACHE_REGION_FACTORY, properties, null
)
);
if ( regionFactoryClassName == null ) {
regionFactoryClassName = DEF_CACHE_REG_FACTORY;

View File

@ -2,10 +2,7 @@ apply plugin: 'java'
dependencies {
compile( project( ':hibernate-core' ) )
compile( [group: 'net.sf.ehcache', name: 'ehcache-core', version: '2.4.1', ext: 'jar'] )
compile( [group: 'net.sf.ehcache', name: 'ehcache-core', version: '2.4.3', ext: 'jar'] )
testCompile( project(':hibernate-testing') )
}
// temporary
test {
ignoreFailures = true
testCompile( [group: 'com.h2database', name: 'h2', version: '1.3.157', ext: 'jar'] )
}

View File

@ -0,0 +1,223 @@
/*
* 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 net.sf.ehcache.CacheManager;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.util.ClassLoaderUtil;
import org.hibernate.cache.CacheException;
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;
import org.hibernate.cache.spi.QueryResultsRegion;
import org.hibernate.cache.spi.RegionFactory;
import org.hibernate.cache.spi.TimestampsRegion;
import org.hibernate.cache.spi.access.AccessType;
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.
*
* @author Chris Dennis
* @author Greg Luck
* @author Emmanuel Bernard
* @author Abhishek Sanoujam
* @author Alex Snaps
*/
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";
private static final Logger LOG = LoggerFactory.getLogger( AbstractEhcacheRegionFactory.class );
protected ClassLoaderService classLoaderService;
/**
* 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;
/**
* 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() );
/**
* 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 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 QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException {
return new EhcacheQueryResultsRegion( accessStrategyFactory, getCache( regionName ), properties );
}
/**
* {@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.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 );
}
}
/**
* 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 ) {
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;
}
/**
* 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

@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.cache.internal;
package org.hibernate.cache.ehcache;
import static org.jboss.logging.Logger.Level.WARN;

View File

@ -0,0 +1,140 @@
/*
* 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 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;
/**
* A non-singleton EhCacheRegionFactory implementation.
*
* @author Chris Dennis
* @author Greg Luck
* @author Emmanuel Bernard
* @author Abhishek Sanoujam
* @author Alex Snaps
*/
public class EhCacheRegionFactory extends AbstractEhcacheRegionFactory {
private static final Logger LOG = LoggerFactory.getLogger( EhCacheRegionFactory.class );
private ClassLoaderService classLoaderService;
public EhCacheRegionFactory() {
}
/**
* 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;
}
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 );
}
}
@InjectService
public void setClassLoaderService(ClassLoaderService classLoaderService) {
this.classLoaderService = classLoaderService;
}
}

View File

@ -0,0 +1,120 @@
/*
* 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

@ -0,0 +1,123 @@
/*
* 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 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;
/**
* A singleton EhCacheRegionFactory implementation.
*
* @author Chris Dennis
* @author Greg Luck
* @author Emmanuel Bernard
* @author Alex Snaps
*/
public class SingletonEhCacheRegionFactory extends AbstractEhcacheRegionFactory {
private static final Logger LOG = LoggerFactory.getLogger( SingletonEhCacheRegionFactory.class );
private static final AtomicInteger REFERENCE_COUNT = new AtomicInteger();
/**
* 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.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 );
}
}
@InjectService
public void setClassLoaderService(ClassLoaderService classLoaderService) {
this.classLoaderService = classLoaderService;
}
}

View File

@ -0,0 +1,182 @@
/*
* 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.management.impl;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicLong;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanNotificationInfo;
import javax.management.NotCompliantMBeanException;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationEmitter;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.StandardMBean;
/**
* @author gkeim
*/
public abstract class BaseEmitterBean extends StandardMBean implements NotificationEmitter {
/**
* emitter
*/
protected final Emitter emitter = new Emitter();
/**
* sequenceNumber
*/
protected final AtomicLong sequenceNumber = new AtomicLong();
private final List<NotificationListener> notificationListeners = new CopyOnWriteArrayList<NotificationListener>();
/**
* BaseEmitterBean
*
* @param <T>
* @param mbeanInterface
*
* @throws javax.management.NotCompliantMBeanException
*/
protected <T> BaseEmitterBean(Class<T> mbeanInterface) throws NotCompliantMBeanException {
super( mbeanInterface );
}
/**
* sendNotification
*
* @param eventType
*/
public void sendNotification(String eventType) {
sendNotification( eventType, null, null );
}
/**
* sendNotification
*
* @param eventType
* @param data
*/
public void sendNotification(String eventType, Object data) {
sendNotification( eventType, data, null );
}
/**
* sendNotification
*
* @param eventType
* @param data
* @param msg
*/
public void sendNotification(String eventType, Object data, String msg) {
Notification notif = new Notification(
eventType,
this,
sequenceNumber.incrementAndGet(),
System.currentTimeMillis(),
msg
);
if ( data != null ) {
notif.setUserData( data );
}
emitter.sendNotification( notif );
}
/**
* Dispose of this SampledCacheManager and clean up held resources
*/
public final void dispose() {
doDispose();
removeAllNotificationListeners();
}
/**
* Dispose callback of subclasses
*/
protected abstract void doDispose();
/**
* @author gkeim
*/
private class Emitter extends NotificationBroadcasterSupport {
/**
* @see javax.management.NotificationBroadcasterSupport#getNotificationInfo()
*/
@Override
public MBeanNotificationInfo[] getNotificationInfo() {
return BaseEmitterBean.this.getNotificationInfo();
}
}
/**
* @see javax.management.NotificationBroadcaster#addNotificationListener(javax.management.NotificationListener,
* javax.management.NotificationFilter, java.lang.Object)
*/
public void addNotificationListener(NotificationListener notif, NotificationFilter filter, Object callBack) {
emitter.addNotificationListener( notif, filter, callBack );
notificationListeners.add( notif );
}
/**
* remove all added notification listeners
*/
private void removeAllNotificationListeners() {
for ( NotificationListener listener : notificationListeners ) {
try {
emitter.removeNotificationListener( listener );
}
catch ( ListenerNotFoundException e ) {
// ignore
}
}
notificationListeners.clear();
}
/**
* @see javax.management.NotificationBroadcaster#getNotificationInfo()
*/
public abstract MBeanNotificationInfo[] getNotificationInfo();
/**
* @see javax.management.NotificationBroadcaster#removeNotificationListener(javax.management.NotificationListener)
*/
public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException {
emitter.removeNotificationListener( listener );
notificationListeners.remove( listener );
}
/**
* @see javax.management.NotificationEmitter#removeNotificationListener(javax.management.NotificationListener,
* javax.management.NotificationFilter, java.lang.Object)
*/
public void removeNotificationListener(NotificationListener notif, NotificationFilter filter, Object callBack)
throws ListenerNotFoundException {
emitter.removeNotificationListener( notif, filter, callBack );
notificationListeners.remove( notif );
}
}

View File

@ -0,0 +1,145 @@
/*
* 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.management.impl;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* Reflective utilities for dealing with backward-incompatible change to statistics types in Hibernate 3.5.
*
* @author gkeim
*/
public class BeanUtils {
/**
* Return the named getter method on the bean or null if not found.
*
* @param bean
* @param propertyName
*
* @return the named getter method
*/
private static Method getMethod(Object bean, String propertyName) {
StringBuilder sb = new StringBuilder( "get" ).append( Character.toUpperCase( propertyName.charAt( 0 ) ) );
if ( propertyName.length() > 1 ) {
sb.append( propertyName.substring( 1 ) );
}
String getterName = sb.toString();
for ( Method m : bean.getClass().getMethods() ) {
if ( getterName.equals( m.getName() ) && m.getParameterTypes().length == 0 ) {
return m;
}
}
return null;
}
/**
* Return the named field on the bean or null if not found.
*
* @param bean
* @param propertyName
*
* @return the named field
*/
private static Field getField(Object bean, String propertyName) {
for ( Field f : bean.getClass().getDeclaredFields() ) {
if ( propertyName.equals( f.getName() ) ) {
return f;
}
}
return null;
}
private static void validateArgs(Object bean, String propertyName) {
if ( bean == null ) {
throw new IllegalArgumentException( "bean is null" );
}
if ( propertyName == null ) {
throw new IllegalArgumentException( "propertyName is null" );
}
if ( propertyName.trim().length() == 0 ) {
throw new IllegalArgumentException( "propertyName is empty" );
}
}
/**
* Retrieve a named bean property value.
*
* @param bean bean
* @param propertyName
*
* @return the property value
*/
public static Object getBeanProperty(Object bean, String propertyName) {
validateArgs( bean, propertyName );
// try getters first
Method getter = getMethod( bean, propertyName );
if ( getter != null ) {
try {
return getter.invoke( bean );
}
catch ( Exception e ) {
/**/
}
}
// then try fields
Field field = getField( bean, propertyName );
if ( field != null ) {
try {
field.setAccessible( true );
return field.get( bean );
}
catch ( Exception e ) {
/**/
}
}
return null;
}
/**
* Retrieve a Long bean property value.
*
* @param bean bean
* @param propertyName
*
* @return long value
*
* @throws NoSuchFieldException
*/
public static long getLongBeanProperty(final Object bean, final String propertyName) throws NoSuchFieldException {
validateArgs( bean, propertyName );
Object o = getBeanProperty( bean, propertyName );
if ( o == null ) {
throw new NoSuchFieldException( propertyName );
}
else if ( !( o instanceof Number ) ) {
throw new IllegalArgumentException( propertyName + " not an Number" );
}
return ( (Number) o ).longValue();
}
}

View File

@ -0,0 +1,303 @@
/*
* 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.management.impl;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
import org.hibernate.stat.SecondLevelCacheStatistics;
/**
* @author gkeim
*/
public class CacheRegionStats implements Serializable {
private static final String COMPOSITE_TYPE_NAME = "CacheRegionStats";
private static final String COMPOSITE_TYPE_DESCRIPTION = "Statistics per Cache-region";
private static final String[] ITEM_NAMES = new String[] {
"region", "shortName", "hitCount",
"missCount", "putCount", "hitRatio", "elementCountInMemory", "elementCountOnDisk", "elementCountTotal",
};
private static final String[] ITEM_DESCRIPTIONS = new String[] {
"region", "shortName", "hitCount",
"missCount", "putCount", "hitRatio", "elementCountInMemory", "elementCountOnDisk", "elementCountTotal",
};
private static final OpenType[] ITEM_TYPES = new OpenType[] {
SimpleType.STRING,
SimpleType.STRING, SimpleType.LONG, SimpleType.LONG, SimpleType.LONG, SimpleType.DOUBLE, SimpleType.LONG,
SimpleType.LONG, SimpleType.LONG,
};
private static final CompositeType COMPOSITE_TYPE;
private static final String TABULAR_TYPE_NAME = "Statistics by Cache-region";
private static final String TABULAR_TYPE_DESCRIPTION = "All Cache Region Statistics";
private static final String[] INDEX_NAMES = new String[] { "region", };
private static final TabularType TABULAR_TYPE;
static {
try {
COMPOSITE_TYPE = new CompositeType(
COMPOSITE_TYPE_NAME, COMPOSITE_TYPE_DESCRIPTION, ITEM_NAMES,
ITEM_DESCRIPTIONS, ITEM_TYPES
);
TABULAR_TYPE = new TabularType( TABULAR_TYPE_NAME, TABULAR_TYPE_DESCRIPTION, COMPOSITE_TYPE, INDEX_NAMES );
}
catch ( OpenDataException e ) {
throw new RuntimeException( e );
}
}
/**
* region name
*/
protected final String region;
/**
* region short name
*/
protected final String shortName;
/**
* hit count
*/
protected long hitCount;
/**
* miss count
*/
protected long missCount;
/**
* put count
*/
protected long putCount;
/**
* hit ratio
*/
protected double hitRatio;
/**
* in-memory element count
*/
protected long elementCountInMemory;
/**
* on-disk element count
*/
protected long elementCountOnDisk;
/**
* total element count
*/
protected long elementCountTotal;
/**
* @param region
*/
public CacheRegionStats(String region) {
this.region = region;
this.shortName = CacheRegionUtils.determineShortName( region );
}
/**
* @param region
* @param src
*/
public CacheRegionStats(String region, SecondLevelCacheStatistics src) {
this( region );
try {
this.hitCount = BeanUtils.getLongBeanProperty( src, "hitCount" );
this.missCount = BeanUtils.getLongBeanProperty( src, "missCount" );
this.putCount = BeanUtils.getLongBeanProperty( src, "putCount" );
this.hitRatio = determineHitRatio();
this.elementCountInMemory = BeanUtils.getLongBeanProperty( src, "elementCountInMemory" );
this.elementCountOnDisk = BeanUtils.getLongBeanProperty( src, "elementCountOnDisk" );
this.elementCountTotal = BeanUtils.getLongBeanProperty( src, "elementCountOnDisk" );
}
catch ( Exception e ) {
e.printStackTrace();
throw new RuntimeException( "Exception retrieving statistics", e );
}
}
/**
* @param cData
*/
public CacheRegionStats(final CompositeData cData) {
int i = 0;
region = (String) cData.get( ITEM_NAMES[i++] );
shortName = (String) cData.get( ITEM_NAMES[i++] );
hitCount = (Long) cData.get( ITEM_NAMES[i++] );
missCount = (Long) cData.get( ITEM_NAMES[i++] );
putCount = (Long) cData.get( ITEM_NAMES[i++] );
hitRatio = (Double) cData.get( ITEM_NAMES[i++] );
elementCountInMemory = (Long) cData.get( ITEM_NAMES[i++] );
elementCountOnDisk = (Long) cData.get( ITEM_NAMES[i++] );
elementCountTotal = (Long) cData.get( ITEM_NAMES[i++] );
}
private static int safeParseInt(String s) {
try {
return Integer.parseInt( s );
}
catch ( Exception e ) {
return -1;
}
}
/**
* @return hit ratio
*/
protected double determineHitRatio() {
double result = 0;
long readCount = getHitCount() + getMissCount();
if ( readCount > 0 ) {
result = getHitCount() / ( (double) readCount );
}
return result;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "region=" + getRegion() + "shortName=" + getShortName() + ", hitCount=" + getHitCount() + ", missCount="
+ getMissCount() + ", putCount" + getPutCount() + ", hitRatio" + getHitRatio() + ", elementCountInMemory="
+ getElementCountInMemory() + ", elementCountOnDisk=" + getElementCountOnDisk() + ", elementCountTotal="
+ getElementCountTotal();
}
/**
* @return region name
*/
public String getRegion() {
return region;
}
/**
* @return short name
*/
public String getShortName() {
return shortName;
}
/**
* @return hit count
*/
public long getHitCount() {
return hitCount;
}
/**
* @return miss count
*/
public long getMissCount() {
return missCount;
}
/**
* @return put count
*/
public long getPutCount() {
return putCount;
}
/**
* @return hit ratio
*/
public double getHitRatio() {
return hitRatio;
}
/**
* @return in-memory element count
*/
public long getElementCountInMemory() {
return elementCountInMemory;
}
/**
* @return on-disk element count
*/
public long getElementCountOnDisk() {
return elementCountOnDisk;
}
/**
* @return total element count
*/
public long getElementCountTotal() {
return elementCountTotal;
}
/**
* @return composite data
*/
public CompositeData toCompositeData() {
try {
return new CompositeDataSupport(
COMPOSITE_TYPE, ITEM_NAMES, new Object[] {
getRegion(), getShortName(),
getHitCount(), getMissCount(), getPutCount(), getHitRatio(), getElementCountInMemory(),
getElementCountOnDisk(), getElementCountTotal(),
}
);
}
catch ( OpenDataException e ) {
throw new RuntimeException( e );
}
}
/**
* @return tabular data
*/
public static TabularData newTabularDataInstance() {
return new TabularDataSupport( TABULAR_TYPE );
}
/**
* @param tabularData
*
* @return array of region statistics
*/
public static CacheRegionStats[] fromTabularData(final TabularData tabularData) {
final List<CacheRegionStats> countList = new ArrayList( tabularData.size() );
for ( final Iterator pos = tabularData.values().iterator(); pos.hasNext(); ) {
countList.add( new CacheRegionStats( (CompositeData) pos.next() ) );
}
return countList.toArray( new CacheRegionStats[countList.size()] );
}
}

View File

@ -0,0 +1,126 @@
/*
* 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.management.impl;
import java.awt.*;
/**
* CacheRegionUtils
*
* @author gkeim
*/
public abstract class CacheRegionUtils {
/**
* HIT_COLOR
*/
public static final Color HIT_COLOR = Color.green;
/**
* MISS_COLOR
*/
public static final Color MISS_COLOR = Color.red;
/**
* PUT_COLOR
*/
public static final Color PUT_COLOR = Color.blue;
/**
* HIT_FILL_COLOR
*/
public final static Color HIT_FILL_COLOR = CacheRegionUtils.HIT_COLOR.brighter().brighter().brighter();
/**
* MISS_FILL_COLOR
*/
public final static Color MISS_FILL_COLOR = CacheRegionUtils.MISS_COLOR.brighter().brighter().brighter();
/**
* PUT_FILL_COLOR
*/
public final static Color PUT_FILL_COLOR = CacheRegionUtils.PUT_COLOR.brighter().brighter().brighter();
/**
* HIT_DRAW_COLOR
*/
public final static Color HIT_DRAW_COLOR = CacheRegionUtils.HIT_COLOR.darker();
/**
* MISS_DRAW_COLOR
*/
public final static Color MISS_DRAW_COLOR = CacheRegionUtils.MISS_COLOR.darker();
/**
* PUT_DRAW_COLOR
*/
public final static Color PUT_DRAW_COLOR = CacheRegionUtils.PUT_COLOR.darker();
/**
* determineShortName
*
* @param fullName
*/
public static String determineShortName(String fullName) {
String result = fullName;
if ( fullName != null ) {
String[] comps = fullName.split( "\\." );
if ( comps.length == 1 ) {
return fullName;
}
boolean truncate = true;
for ( int i = 0; i < comps.length; i++ ) {
String comp = comps[i];
char c = comp.charAt( 0 );
if ( truncate && Character.isUpperCase( c ) ) {
truncate = false;
}
if ( truncate ) {
comps[i] = Character.toString( c );
}
}
result = join( comps, '.' );
}
return result;
}
/**
* join
*
* @param elements
* @param c
*/
private static String join(String[] elements, char c) {
if ( elements == null ) {
return null;
}
StringBuilder sb = new StringBuilder();
for ( String s : elements ) {
sb.append( s ).append( c );
}
return sb.length() > 0 ? sb.substring( 0, sb.length() - 1 ) : "";
}
}

View File

@ -0,0 +1,273 @@
/*
* 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.management.impl;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
import org.hibernate.stat.CollectionStatistics;
/**
* CollectionStats
*
* @author gkeim
*/
public class CollectionStats implements Serializable {
private static final String COMPOSITE_TYPE_NAME = "CollectionsStats";
private static final String COMPOSITE_TYPE_DESCRIPTION = "Statistics per Collections";
private static final String[] ITEM_NAMES = new String[] {
"roleName", "shortName", "loadCount",
"fetchCount", "updateCount", "removeCount", "recreateCount",
};
private static final String[] ITEM_DESCRIPTIONS = new String[] {
"roleName", "shortName", "loadCount",
"fetchCount", "updateCount", "removeCount", "recreateCount",
};
private static final OpenType[] ITEM_TYPES = new OpenType[] {
SimpleType.STRING,
SimpleType.STRING, SimpleType.LONG, SimpleType.LONG, SimpleType.LONG, SimpleType.LONG, SimpleType.LONG,
};
private static final CompositeType COMPOSITE_TYPE;
private static final String TABULAR_TYPE_NAME = "Statistics by Collection";
private static final String TABULAR_TYPE_DESCRIPTION = "All Collection Statistics";
private static final String[] INDEX_NAMES = new String[] { "roleName", };
private static final TabularType TABULAR_TYPE;
static {
try {
COMPOSITE_TYPE = new CompositeType(
COMPOSITE_TYPE_NAME, COMPOSITE_TYPE_DESCRIPTION, ITEM_NAMES,
ITEM_DESCRIPTIONS, ITEM_TYPES
);
TABULAR_TYPE = new TabularType( TABULAR_TYPE_NAME, TABULAR_TYPE_DESCRIPTION, COMPOSITE_TYPE, INDEX_NAMES );
}
catch ( OpenDataException e ) {
throw new RuntimeException( e );
}
}
/**
* roleName
*/
protected final String roleName;
/**
* shortName
*/
protected final String shortName;
/**
* loadCount
*/
protected long loadCount;
/**
* fetchCount
*/
protected long fetchCount;
/**
* updateCount
*/
protected long updateCount;
/**
* removeCount
*/
protected long removeCount;
/**
* recreateCount
*/
protected long recreateCount;
/**
* @param roleName
*/
public CollectionStats(String roleName) {
this.roleName = roleName;
this.shortName = CacheRegionUtils.determineShortName( roleName );
}
/**
* @param name
* @param src
*/
public CollectionStats(String name, CollectionStatistics src) {
this( name );
try {
this.loadCount = BeanUtils.getLongBeanProperty( src, "loadCount" );
this.fetchCount = BeanUtils.getLongBeanProperty( src, "fetchCount" );
this.updateCount = BeanUtils.getLongBeanProperty( src, "updateCount" );
this.removeCount = BeanUtils.getLongBeanProperty( src, "removeCount" );
this.recreateCount = BeanUtils.getLongBeanProperty( src, "recreateCount" );
}
catch ( Exception e ) {
e.printStackTrace();
throw new RuntimeException( "Exception retrieving statistics", e );
}
}
/**
* @param cData
*/
public CollectionStats(final CompositeData cData) {
int i = 0;
roleName = (String) cData.get( ITEM_NAMES[i++] );
shortName = (String) cData.get( ITEM_NAMES[i++] );
loadCount = (Long) cData.get( ITEM_NAMES[i++] );
fetchCount = (Long) cData.get( ITEM_NAMES[i++] );
updateCount = (Long) cData.get( ITEM_NAMES[i++] );
removeCount = (Long) cData.get( ITEM_NAMES[i++] );
recreateCount = (Long) cData.get( ITEM_NAMES[i++] );
}
private static int safeParseInt(String s) {
try {
return Integer.parseInt( s );
}
catch ( Exception e ) {
return -1;
}
}
/**
* @param stats
*/
public void add(CollectionStats stats) {
loadCount += stats.getLoadCount();
fetchCount += stats.getFetchCount();
updateCount += stats.getUpdateCount();
removeCount += stats.getRemoveCount();
recreateCount += stats.getRecreateCount();
}
/**
* toString
*/
@Override
public String toString() {
return "roleName=" + roleName + "shortName=" + shortName + ", loadCount=" + loadCount + ", fetchCount="
+ fetchCount + ", updateCount=" + updateCount + ", removeCount=" + removeCount + ", recreateCount"
+ recreateCount;
}
/**
* getRoleName
*/
public String getRoleName() {
return roleName;
}
/**
* getShortName
*/
public String getShortName() {
return shortName;
}
/**
* getLoadCount
*/
public long getLoadCount() {
return loadCount;
}
/**
* getFetchCount
*/
public long getFetchCount() {
return fetchCount;
}
/**
* getUpdateCount
*/
public long getUpdateCount() {
return updateCount;
}
/**
* getRemoveCount
*/
public long getRemoveCount() {
return removeCount;
}
/**
* getRecreateCount
*/
public long getRecreateCount() {
return recreateCount;
}
/**
* toCompositeData
*/
public CompositeData toCompositeData() {
try {
return new CompositeDataSupport(
COMPOSITE_TYPE, ITEM_NAMES, new Object[] {
roleName, shortName, loadCount,
fetchCount, updateCount, removeCount, recreateCount,
}
);
}
catch ( OpenDataException e ) {
throw new RuntimeException( e );
}
}
/**
* newTabularDataInstance
*/
public static TabularData newTabularDataInstance() {
return new TabularDataSupport( TABULAR_TYPE );
}
/**
* fromTabularData
*/
public static CollectionStats[] fromTabularData(final TabularData tabularData) {
final List<CollectionStats> countList = new ArrayList( tabularData.size() );
for ( final Iterator pos = tabularData.values().iterator(); pos.hasNext(); ) {
countList.add( new CollectionStats( (CompositeData) pos.next() ) );
}
return countList.toArray( new CollectionStats[countList.size()] );
}
}

View File

@ -0,0 +1,597 @@
/*
* 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.management.impl;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.management.MBeanNotificationInfo;
import javax.management.NotCompliantMBeanException;
import javax.management.Notification;
import javax.management.openmbean.TabularData;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.hibernate.management.api.EhcacheHibernateMBean;
import net.sf.ehcache.hibernate.management.api.EhcacheStats;
import net.sf.ehcache.hibernate.management.api.HibernateStats;
import org.hibernate.SessionFactory;
/**
* Implementation of the {@link EhcacheHibernateMBean}
* <p/>
* <p/>
*
* @author <a href="mailto:asanoujam@terracottatech.com">Abhishek Sanoujam</a>
*/
public class EhcacheHibernate extends BaseEmitterBean implements EhcacheHibernateMBean {
private static final MBeanNotificationInfo NOTIFICATION_INFO;
private final AtomicBoolean statsEnabled = new AtomicBoolean( true );
private EhcacheStats ehcacheStats;
private volatile HibernateStats hibernateStats = NullHibernateStats.INSTANCE;
static {
final String[] notifTypes = new String[] { };
final String name = Notification.class.getName();
final String description = "Ehcache Hibernate Statistics Event";
NOTIFICATION_INFO = new MBeanNotificationInfo( notifTypes, name, description );
}
/**
* Constructor accepting the backing {@link CacheManager}
*
* @param manager the backing {@link CacheManager}
*
* @throws NotCompliantMBeanException
*/
public EhcacheHibernate(CacheManager manager) throws NotCompliantMBeanException {
super( EhcacheHibernateMBean.class );
ehcacheStats = new EhcacheStatsImpl( manager );
}
/**
* Enable hibernate statistics with the input session factory
*/
public void enableHibernateStatistics(SessionFactory sessionFactory) {
try {
hibernateStats = new HibernateStatsImpl( sessionFactory );
}
catch ( Exception e ) {
throw new RuntimeException( e );
}
}
/**
* {@inheritDoc}
*/
public boolean isHibernateStatisticsSupported() {
return hibernateStats instanceof HibernateStatsImpl;
}
/**
* {@inheritDoc}
*/
public void setStatisticsEnabled(boolean flag) {
if ( flag ) {
ehcacheStats.enableStats();
hibernateStats.enableStats();
}
else {
ehcacheStats.disableStats();
hibernateStats.disableStats();
}
statsEnabled.set( flag );
sendNotification( HibernateStats.CACHE_STATISTICS_ENABLED, flag );
}
/**
* {@inheritDoc}
*/
public boolean isStatisticsEnabled() {
return statsEnabled.get();
}
/**
* {@inheritDoc}
*/
public void clearStats() {
ehcacheStats.clearStats();
hibernateStats.clearStats();
}
/**
* {@inheritDoc}
*/
public void disableStats() {
setStatisticsEnabled( false );
}
/**
* {@inheritDoc}
*/
public void enableStats() {
setStatisticsEnabled( true );
}
/**
* {@inheritDoc}
*/
public void flushRegionCache(String region) {
ehcacheStats.flushRegionCache( region );
sendNotification( HibernateStats.CACHE_REGION_FLUSHED, region );
}
/**
* {@inheritDoc}
*/
public void flushRegionCaches() {
ehcacheStats.flushRegionCaches();
sendNotification( HibernateStats.CACHE_FLUSHED );
}
/**
* {@inheritDoc}
*/
public String generateActiveConfigDeclaration() {
return ehcacheStats.generateActiveConfigDeclaration();
}
/**
* {@inheritDoc}
*/
public String generateActiveConfigDeclaration(String region) {
return ehcacheStats.generateActiveConfigDeclaration( region );
}
/**
* {@inheritDoc}
*/
public long getCacheHitCount() {
return ehcacheStats.getCacheHitCount();
}
/**
* {@inheritDoc}
*/
public double getCacheHitRate() {
return ehcacheStats.getCacheHitRate();
}
/**
* {@inheritDoc}
*/
public long getCacheHitSample() {
return ehcacheStats.getCacheHitSample();
}
/**
* {@inheritDoc}
*/
public long getCacheMissCount() {
return ehcacheStats.getCacheMissCount();
}
/**
* {@inheritDoc}
*/
public double getCacheMissRate() {
return ehcacheStats.getCacheMissRate();
}
/**
* {@inheritDoc}
*/
public long getCacheMissSample() {
return ehcacheStats.getCacheMissSample();
}
/**
* {@inheritDoc}
*/
public long getCachePutCount() {
return ehcacheStats.getCachePutCount();
}
/**
* {@inheritDoc}
*/
public double getCachePutRate() {
return ehcacheStats.getCachePutRate();
}
/**
* {@inheritDoc}
*/
public long getCachePutSample() {
return ehcacheStats.getCachePutSample();
}
/**
* {@inheritDoc}
*/
public TabularData getCacheRegionStats() {
return hibernateStats.getCacheRegionStats();
}
/**
* {@inheritDoc}
*/
public long getCloseStatementCount() {
return hibernateStats.getCloseStatementCount();
}
/**
* {@inheritDoc}
*/
public TabularData getCollectionStats() {
return hibernateStats.getCollectionStats();
}
/**
* {@inheritDoc}
*/
public long getConnectCount() {
return hibernateStats.getConnectCount();
}
/**
* {@inheritDoc}
*/
public TabularData getEntityStats() {
return hibernateStats.getEntityStats();
}
/**
* {@inheritDoc}
*/
public long getFlushCount() {
return hibernateStats.getFlushCount();
}
/**
* {@inheritDoc}
*/
public long getOptimisticFailureCount() {
return hibernateStats.getOptimisticFailureCount();
}
/**
* {@inheritDoc}
*/
public String getOriginalConfigDeclaration() {
return ehcacheStats.getOriginalConfigDeclaration();
}
/**
* {@inheritDoc}
*/
public String getOriginalConfigDeclaration(String region) {
return ehcacheStats.getOriginalConfigDeclaration( region );
}
/**
* {@inheritDoc}
*/
public long getPrepareStatementCount() {
return hibernateStats.getPrepareStatementCount();
}
/**
* {@inheritDoc}
*/
public long getQueryExecutionCount() {
return hibernateStats.getQueryExecutionCount();
}
/**
* {@inheritDoc}
*/
public double getQueryExecutionRate() {
return hibernateStats.getQueryExecutionRate();
}
/**
* {@inheritDoc}
*/
public long getQueryExecutionSample() {
return hibernateStats.getQueryExecutionSample();
}
/**
* {@inheritDoc}
*/
public TabularData getQueryStats() {
return hibernateStats.getQueryStats();
}
/**
* {@inheritDoc}
*/
public Map<String, Map<String, Object>> getRegionCacheAttributes() {
return ehcacheStats.getRegionCacheAttributes();
}
/**
* {@inheritDoc}
*/
public Map<String, Object> getRegionCacheAttributes(String regionName) {
return ehcacheStats.getRegionCacheAttributes( regionName );
}
/**
* {@inheritDoc}
*/
public int getRegionCacheMaxTTISeconds(String region) {
return ehcacheStats.getRegionCacheMaxTTISeconds( region );
}
/**
* {@inheritDoc}
*/
public int getRegionCacheMaxTTLSeconds(String region) {
return ehcacheStats.getRegionCacheMaxTTLSeconds( region );
}
/**
* {@inheritDoc}
*/
public int getRegionCacheOrphanEvictionPeriod(String region) {
return ehcacheStats.getRegionCacheOrphanEvictionPeriod( region );
}
/**
* {@inheritDoc}
*/
public Map<String, int[]> getRegionCacheSamples() {
return ehcacheStats.getRegionCacheSamples();
}
/**
* {@inheritDoc}
*/
public int getRegionCacheTargetMaxInMemoryCount(String region) {
return ehcacheStats.getRegionCacheTargetMaxInMemoryCount( region );
}
/**
* {@inheritDoc}
*/
public int getRegionCacheTargetMaxTotalCount(String region) {
return ehcacheStats.getRegionCacheTargetMaxTotalCount( region );
}
/**
* {@inheritDoc}
*/
public long getSessionCloseCount() {
return hibernateStats.getSessionCloseCount();
}
/**
* {@inheritDoc}
*/
public long getSessionOpenCount() {
return hibernateStats.getSessionOpenCount();
}
/**
* {@inheritDoc}
*/
public long getSuccessfulTransactionCount() {
return hibernateStats.getSuccessfulTransactionCount();
}
/**
* {@inheritDoc}
*/
public String[] getTerracottaHibernateCacheRegionNames() {
return ehcacheStats.getTerracottaHibernateCacheRegionNames();
}
/**
* {@inheritDoc}
*/
public long getTransactionCount() {
return hibernateStats.getTransactionCount();
}
/**
* {@inheritDoc}
*/
public boolean isRegionCacheEnabled(String region) {
return ehcacheStats.isRegionCacheEnabled( region );
}
/**
* {@inheritDoc}
*/
public void setRegionCachesEnabled(boolean enabled) {
ehcacheStats.setRegionCachesEnabled( enabled );
sendNotification( HibernateStats.CACHE_ENABLED, enabled );
}
/**
* {@inheritDoc}
*/
public void setRegionCacheEnabled(String region, boolean enabled) {
ehcacheStats.setRegionCacheEnabled( region, enabled );
sendNotification( HibernateStats.CACHE_REGION_CHANGED, getRegionCacheAttributes( region ), region );
}
/**
* {@inheritDoc}
*/
public boolean isRegionCacheLoggingEnabled(String region) {
return ehcacheStats.isRegionCacheLoggingEnabled( region );
}
/**
* {@inheritDoc}
*/
public boolean isRegionCacheOrphanEvictionEnabled(String region) {
return ehcacheStats.isRegionCacheOrphanEvictionEnabled( region );
}
/**
* {@inheritDoc}
*/
public boolean isRegionCachesEnabled() {
return ehcacheStats.isRegionCachesEnabled();
}
/**
* {@inheritDoc}
*/
public boolean isTerracottaHibernateCache(String region) {
return ehcacheStats.isTerracottaHibernateCache( region );
}
/**
* {@inheritDoc}
*/
public void setRegionCacheLoggingEnabled(String region, boolean loggingEnabled) {
ehcacheStats.setRegionCacheLoggingEnabled( region, loggingEnabled );
sendNotification( HibernateStats.CACHE_REGION_CHANGED, getRegionCacheAttributes( region ), region );
}
/**
* {@inheritDoc}
*/
public void setRegionCacheMaxTTISeconds(String region, int maxTTISeconds) {
ehcacheStats.setRegionCacheMaxTTISeconds( region, maxTTISeconds );
sendNotification( HibernateStats.CACHE_REGION_CHANGED, getRegionCacheAttributes( region ), region );
}
/**
* {@inheritDoc}
*/
public void setRegionCacheMaxTTLSeconds(String region, int maxTTLSeconds) {
ehcacheStats.setRegionCacheMaxTTLSeconds( region, maxTTLSeconds );
sendNotification( HibernateStats.CACHE_REGION_CHANGED, getRegionCacheAttributes( region ), region );
}
/**
* {@inheritDoc}
*/
public void setRegionCacheTargetMaxInMemoryCount(String region, int targetMaxInMemoryCount) {
ehcacheStats.setRegionCacheTargetMaxInMemoryCount( region, targetMaxInMemoryCount );
sendNotification( HibernateStats.CACHE_REGION_CHANGED, getRegionCacheAttributes( region ), region );
}
/**
* {@inheritDoc}
*/
public void setRegionCacheTargetMaxTotalCount(String region, int targetMaxTotalCount) {
ehcacheStats.setRegionCacheTargetMaxTotalCount( region, targetMaxTotalCount );
sendNotification( HibernateStats.CACHE_REGION_CHANGED, getRegionCacheAttributes( region ), region );
}
/**
* {@inheritDoc}
*
* @see EhcacheStats#getNumberOfElementsInMemory(java.lang.String)
*/
public int getNumberOfElementsInMemory(String region) {
return ehcacheStats.getNumberOfElementsInMemory( region );
}
/**
* {@inheritDoc}
*
* @see EhcacheStats#getNumberOfElementsInMemory(java.lang.String)
*/
public int getNumberOfElementsOffHeap(String region) {
return ehcacheStats.getNumberOfElementsOffHeap( region );
}
/**
* {@inheritDoc}
*
* @see EhcacheStats#getNumberOfElementsOnDisk(java.lang.String)
*/
public int getNumberOfElementsOnDisk(String region) {
return ehcacheStats.getNumberOfElementsOnDisk( region );
}
/**
* {@inheritDoc}
*
* @see EhcacheStats#getMaxGetTimeMillis()
*/
public long getMaxGetTimeMillis() {
return ehcacheStats.getMaxGetTimeMillis();
}
/**
* {@inheritDoc}
*
* @see EhcacheStats#getMaxGetTimeMillis(java.lang.String)
*/
public long getMaxGetTimeMillis(String cacheName) {
return ehcacheStats.getMaxGetTimeMillis( cacheName );
}
/**
* {@inheritDoc}
*
* @see EhcacheStats#getMinGetTimeMillis()
*/
public long getMinGetTimeMillis() {
return ehcacheStats.getMinGetTimeMillis();
}
/**
* {@inheritDoc}
*
* @see EhcacheStats#getMinGetTimeMillis(java.lang.String)
*/
public long getMinGetTimeMillis(String cacheName) {
return ehcacheStats.getMinGetTimeMillis( cacheName );
}
/**
* {@inheritDoc}
*
* @see EhcacheStats#getAverageGetTimeMillis(java.lang.String)
*/
public float getAverageGetTimeMillis(String region) {
return ehcacheStats.getAverageGetTimeMillis( region );
}
/**
* {@inheritDoc}
*/
@Override
protected void doDispose() {
// no-op
}
/**
* @see BaseEmitterBean#getNotificationInfo()
*/
@Override
public MBeanNotificationInfo[] getNotificationInfo() {
return new MBeanNotificationInfo[] { NOTIFICATION_INFO };
}
}

View File

@ -0,0 +1,61 @@
/*
* 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.management.impl;
import java.util.Properties;
import net.sf.ehcache.CacheManager;
import org.hibernate.SessionFactory;
/**
* Interface for helping registering mbeans for ehcache backed hibernate second-level cache
* <p/>
* <p/>
*
* @author <a href="mailto:asanoujam@terracottatech.com">Abhishek Sanoujam</a>
*/
public interface EhcacheHibernateMBeanRegistration {
/**
* Registers MBean for the input manager and session factory properties.
* <p/>
* MBeans will be registered based on the input session factory name. If the input name is null or blank, the name of the cache-manager
* is used
*
* @param manager
* @param properties
*
* @throws Exception
*/
public void registerMBeanForCacheManager(CacheManager manager, Properties properties) throws Exception;
/**
* Enable hibernate statistics in the mbean.
*
* @param sessionFactory
*/
public void enableHibernateStatisticsSupport(SessionFactory sessionFactory);
}

View File

@ -0,0 +1,177 @@
/*
* 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.management.impl;
import java.lang.management.ManagementFactory;
import java.util.Properties;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
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.hibernate.SessionFactory;
import org.hibernate.cfg.Environment;
/**
* Implementation of {@link EhcacheHibernateMBeanRegistration}.
* Also implements {@link net.sf.ehcache.event.CacheManagerEventListener}. Deregisters mbeans when the associated cachemanager is shutdown.
* <p/>
* <p/>
*
* @author <a href="mailto:asanoujam@terracottatech.com">Abhishek Sanoujam</a>
*/
public class EhcacheHibernateMBeanRegistrationImpl
implements EhcacheHibernateMBeanRegistration, CacheManagerEventListener {
private static final Logger LOG = LoggerFactory.getLogger( 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;
/**
* {@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 MBeanServer getMBeanServer() {
return ManagementFactory.getPlatformMBeanServer();
}
/**
* {@inheritDoc}
*/
public void enableHibernateStatisticsSupport(SessionFactory sessionFactory) {
ehcacheHibernate.enableHibernateStatistics( sessionFactory );
}
/**
* {@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;
}
/**
* {@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 notifyCacheAdded(String cacheName) {
// no-op
}
/**
* No-op in this case
*/
public void notifyCacheRemoved(String cacheName) {
// no-op
}
}

View File

@ -0,0 +1,89 @@
/*
* 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.management.impl;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
/**
* Utility class used for getting {@link javax.management.ObjectName}'s for ehcache hibernate MBeans
* <p/>
* <p/>
*
* @author <a href="mailto:asanoujam@terracottatech.com">Abhishek Sanoujam</a>
* @since 1.7
*/
public abstract class EhcacheHibernateMbeanNames {
/**
* Group id for all sampled mbeans registered
*/
public static final String GROUP_ID = "net.sf.ehcache.hibernate";
/**
* Type for the ehcache backed hibernate second level cache statistics mbean
*/
public static final String EHCACHE_HIBERNATE_TYPE = "EhcacheHibernateStats";
/**
* Filter out invalid ObjectName characters from s.
*
* @param s
*
* @return A valid JMX ObjectName attribute value.
*/
public static String mbeanSafe(String s) {
return s == null ? "" : s.replaceAll( ":|=|\n", "." );
}
/**
* Returns an ObjectName for the passed name
*
* @param name
*
* @return An {@link javax.management.ObjectName} using the input name of cache manager
*
* @throws javax.management.MalformedObjectNameException
*/
public static ObjectName getCacheManagerObjectName(String cacheManagerClusterUUID, String name)
throws MalformedObjectNameException {
ObjectName objectName = new ObjectName(
GROUP_ID + ":type=" + EHCACHE_HIBERNATE_TYPE + ",name=" + mbeanSafe( name )
+ getBeanNameSuffix( cacheManagerClusterUUID )
);
return objectName;
}
private static String getBeanNameSuffix(String cacheManagerClusterUUID) {
String suffix = "";
if ( !isBlank( cacheManagerClusterUUID ) ) {
suffix = ",node=" + cacheManagerClusterUUID;
}
return suffix;
}
private static boolean isBlank(String param) {
return param == null || "".equals( param.trim() );
}
}

View File

@ -0,0 +1,689 @@
/*
* 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.management.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.management.MBeanNotificationInfo;
import javax.management.NotCompliantMBeanException;
import javax.management.Notification;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.hibernate.management.api.EhcacheStats;
import net.sf.ehcache.management.sampled.SampledCacheManager;
/**
* Implementation of {@link EhcacheStats}
* <p/>
* <p/>
*
* @author <a href="mailto:asanoujam@terracottatech.com">Abhishek Sanoujam</a>
*/
public class EhcacheStatsImpl extends BaseEmitterBean implements EhcacheStats {
private static final long MILLIS_PER_SECOND = 1000;
private static final MBeanNotificationInfo NOTIFICATION_INFO;
private final SampledCacheManager sampledCacheManager;
private final CacheManager cacheManager;
private long statsSince = System.currentTimeMillis();
static {
final String[] notifTypes = new String[] {
CACHE_ENABLED, CACHE_REGION_CHANGED, CACHE_FLUSHED, CACHE_REGION_FLUSHED,
CACHE_STATISTICS_ENABLED, CACHE_STATISTICS_RESET,
};
final String name = Notification.class.getName();
final String description = "Ehcache Hibernate Statistics Event";
NOTIFICATION_INFO = new MBeanNotificationInfo( notifTypes, name, description );
}
/**
* Constructor accepting the backing {@link CacheManager}
*
* @throws javax.management.NotCompliantMBeanException
*/
public EhcacheStatsImpl(CacheManager manager) throws NotCompliantMBeanException {
super( EhcacheStats.class );
this.sampledCacheManager = new SampledCacheManager( manager );
this.cacheManager = manager;
}
/**
* {@inheritDoc}
*/
public boolean isStatisticsEnabled() {
return false;
}
/**
* {@inheritDoc}
*/
public void clearStats() {
sampledCacheManager.clearStatistics();
statsSince = System.currentTimeMillis();
}
/**
* {@inheritDoc}
*/
public void disableStats() {
setStatisticsEnabled( false );
}
/**
* {@inheritDoc}
*/
public void enableStats() {
setStatisticsEnabled( true );
}
/**
* {@inheritDoc}
*/
public void flushRegionCache(String region) {
Cache cache = this.cacheManager.getCache( region );
if ( cache != null ) {
cache.flush();
}
}
/**
* {@inheritDoc}
*/
public void flushRegionCaches() {
for ( String name : cacheManager.getCacheNames() ) {
Cache cache = this.cacheManager.getCache( name );
if ( cache != null ) {
cache.flush();
}
}
}
/**
* {@inheritDoc}
*/
public String generateActiveConfigDeclaration() {
return this.cacheManager.getActiveConfigurationText();
}
/**
* {@inheritDoc}
*/
public String generateActiveConfigDeclaration(String region) {
return this.cacheManager.getActiveConfigurationText( region );
}
/**
* {@inheritDoc}
*/
public long getCacheHitCount() {
long count = 0;
for ( String name : cacheManager.getCacheNames() ) {
Cache cache = cacheManager.getCache( name );
if ( cache != null ) {
count += cache.getLiveCacheStatistics().getCacheHitCount();
}
}
return count;
}
/**
* {@inheritDoc}
*/
public double getCacheHitRate() {
long now = System.currentTimeMillis();
double deltaSecs = (double) ( now - statsSince ) / MILLIS_PER_SECOND;
return getCacheHitCount() / deltaSecs;
}
/**
* {@inheritDoc}
*/
public long getCacheHitSample() {
long count = 0;
for ( String name : cacheManager.getCacheNames() ) {
Cache cache = cacheManager.getCache( name );
if ( cache != null ) {
count += cache.getSampledCacheStatistics().getCacheHitMostRecentSample();
}
}
return count;
}
/**
* {@inheritDoc}
*/
public long getCacheMissCount() {
long count = 0;
for ( String name : cacheManager.getCacheNames() ) {
Cache cache = cacheManager.getCache( name );
if ( cache != null ) {
count += cache.getLiveCacheStatistics().getCacheMissCount();
}
}
return count;
}
/**
* {@inheritDoc}
*/
public double getCacheMissRate() {
long now = System.currentTimeMillis();
double deltaSecs = (double) ( now - statsSince ) / MILLIS_PER_SECOND;
return getCacheMissCount() / deltaSecs;
}
/**
* {@inheritDoc}
*/
public long getCacheMissSample() {
long count = 0;
for ( String name : cacheManager.getCacheNames() ) {
Cache cache = cacheManager.getCache( name );
if ( cache != null ) {
count += cache.getSampledCacheStatistics().getCacheMissMostRecentSample();
}
}
return count;
}
/**
* {@inheritDoc}
*/
public long getCachePutCount() {
long count = 0;
for ( String name : cacheManager.getCacheNames() ) {
Cache cache = cacheManager.getCache( name );
if ( cache != null ) {
count += cache.getLiveCacheStatistics().getPutCount();
}
}
return count;
}
/**
* {@inheritDoc}
*/
public double getCachePutRate() {
long now = System.currentTimeMillis();
double deltaSecs = (double) ( now - statsSince ) / MILLIS_PER_SECOND;
return getCachePutCount() / deltaSecs;
}
/**
* {@inheritDoc}
*/
public long getCachePutSample() {
long count = 0;
for ( String name : cacheManager.getCacheNames() ) {
Cache cache = cacheManager.getCache( name );
if ( cache != null ) {
count += cache.getSampledCacheStatistics().getCacheElementPutMostRecentSample();
}
}
return count;
}
/**
* {@inheritDoc}
*/
public String getOriginalConfigDeclaration() {
return this.cacheManager.getOriginalConfigurationText();
}
/**
* {@inheritDoc}
*/
public String getOriginalConfigDeclaration(String region) {
return this.cacheManager.getOriginalConfigurationText( region );
}
/**
* {@inheritDoc}
*/
public Map<String, Map<String, Object>> getRegionCacheAttributes() {
Map<String, Map<String, Object>> result = new HashMap<String, Map<String, Object>>();
for ( String regionName : this.cacheManager.getCacheNames() ) {
result.put( regionName, getRegionCacheAttributes( regionName ) );
}
return result;
}
/**
* {@inheritDoc}
*/
public Map<String, Object> getRegionCacheAttributes(String regionName) {
Map<String, Object> result = new HashMap<String, Object>();
result.put( "Enabled", isRegionCacheEnabled( regionName ) );
result.put( "LoggingEnabled", isRegionCacheLoggingEnabled( regionName ) );
result.put( "MaxTTISeconds", getRegionCacheMaxTTISeconds( regionName ) );
result.put( "MaxTTLSeconds", getRegionCacheMaxTTLSeconds( regionName ) );
result.put( "TargetMaxInMemoryCount", getRegionCacheTargetMaxInMemoryCount( regionName ) );
result.put( "TargetMaxTotalCount", getRegionCacheTargetMaxTotalCount( regionName ) );
result.put( "OrphanEvictionEnabled", isRegionCacheOrphanEvictionEnabled( regionName ) );
result.put( "OrphanEvictionPeriod", getRegionCacheOrphanEvictionPeriod( regionName ) );
return result;
}
/**
* {@inheritDoc}
*/
public int getRegionCacheMaxTTISeconds(String region) {
Cache cache = cacheManager.getCache( region );
if ( cache != null ) {
return (int) cache.getCacheConfiguration().getTimeToIdleSeconds();
}
else {
return -1;
}
}
/**
* {@inheritDoc}
*/
public int getRegionCacheMaxTTLSeconds(String region) {
Cache cache = cacheManager.getCache( region );
if ( cache != null ) {
return (int) cache.getCacheConfiguration().getTimeToLiveSeconds();
}
else {
return -1;
}
}
/**
* {@inheritDoc}
*/
public int getRegionCacheOrphanEvictionPeriod(String region) {
Cache cache = this.cacheManager.getCache( region );
if ( cache != null && cache.isTerracottaClustered() ) {
return cache.getCacheConfiguration().getTerracottaConfiguration().getOrphanEvictionPeriod();
}
else {
return -1;
}
}
/**
* {@inheritDoc}
*/
public Map<String, int[]> getRegionCacheSamples() {
Map<String, int[]> rv = new HashMap<String, int[]>();
for ( String name : cacheManager.getCacheNames() ) {
Cache cache = cacheManager.getCache( name );
if ( cache != null ) {
rv.put(
name, new int[] {
(int) cache.getSampledCacheStatistics().getCacheHitMostRecentSample(),
(int) ( cache.getSampledCacheStatistics().getCacheMissNotFoundMostRecentSample()
+ cache.getSampledCacheStatistics().getCacheMissExpiredMostRecentSample() ),
(int) cache.getSampledCacheStatistics().getCacheElementPutMostRecentSample(),
}
);
}
}
return rv;
}
/**
* {@inheritDoc}
*/
public int getRegionCacheTargetMaxInMemoryCount(String region) {
Cache cache = cacheManager.getCache( region );
if ( cache != null ) {
return cache.getCacheConfiguration().getMaxElementsInMemory();
}
else {
return -1;
}
}
/**
* {@inheritDoc}
*/
public int getRegionCacheTargetMaxTotalCount(String region) {
Cache cache = cacheManager.getCache( region );
if ( cache != null ) {
return cache.getCacheConfiguration().getMaxElementsOnDisk();
}
else {
return -1;
}
}
/**
* {@inheritDoc}
*/
public String[] getTerracottaHibernateCacheRegionNames() {
ArrayList<String> rv = new ArrayList<String>();
for ( String name : cacheManager.getCacheNames() ) {
Cache cache = cacheManager.getCache( name );
if ( cache != null ) {
if ( cache.getCacheConfiguration().isTerracottaClustered() ) {
rv.add( name );
}
}
}
return rv.toArray( new String[] { } );
}
/**
* {@inheritDoc}
*/
public boolean isRegionCacheEnabled(String region) {
Cache cache = this.cacheManager.getCache( region );
if ( cache != null ) {
return !cache.isDisabled();
}
else {
return false;
}
}
/**
* {@inheritDoc}
*/
public void setRegionCacheEnabled(String region, boolean enabled) {
Cache cache = this.cacheManager.getCache( region );
if ( cache != null ) {
cache.setDisabled( !enabled );
}
sendNotification( CACHE_REGION_CHANGED, getRegionCacheAttributes( region ), region );
}
/**
* {@inheritDoc}
*/
public boolean isRegionCachesEnabled() {
for ( String name : this.cacheManager.getCacheNames() ) {
Cache cache = this.cacheManager.getCache( name );
if ( cache != null ) {
if ( cache.isDisabled() ) {
return false;
}
}
}
return true;
}
/**
* @see EhcacheStats#setRegionCachesEnabled(boolean)
*/
public void setRegionCachesEnabled(final boolean flag) {
for ( String name : this.cacheManager.getCacheNames() ) {
Cache cache = this.cacheManager.getCache( name );
if ( cache != null ) {
cache.setDisabled( !flag );
}
}
sendNotification( CACHE_ENABLED, flag );
}
/**
* {@inheritDoc}
*/
public boolean isRegionCacheLoggingEnabled(String region) {
Cache cache = this.cacheManager.getCache( region );
if ( cache != null ) {
return cache.getCacheConfiguration().getLogging();
}
else {
return false;
}
}
/**
* {@inheritDoc}
*/
public boolean isRegionCacheOrphanEvictionEnabled(String region) {
Cache cache = this.cacheManager.getCache( region );
if ( cache != null && cache.isTerracottaClustered() ) {
return cache.getCacheConfiguration().getTerracottaConfiguration().getOrphanEviction();
}
else {
return false;
}
}
/**
* {@inheritDoc}
*/
public boolean isTerracottaHibernateCache(String region) {
Cache cache = cacheManager.getCache( region );
if ( cache != null ) {
return cache.getCacheConfiguration().isTerracottaClustered();
}
else {
return false;
}
}
/**
* {@inheritDoc}
*/
public void setRegionCacheLoggingEnabled(String region, boolean loggingEnabled) {
Cache cache = this.cacheManager.getCache( region );
if ( cache != null ) {
cache.getCacheConfiguration().setLogging( loggingEnabled );
sendNotification( CACHE_REGION_CHANGED, getRegionCacheAttributes( region ), region );
}
}
/**
* {@inheritDoc}
*/
public void setRegionCacheMaxTTISeconds(String region, int maxTTISeconds) {
Cache cache = this.cacheManager.getCache( region );
if ( cache != null ) {
cache.getCacheConfiguration().setTimeToIdleSeconds( maxTTISeconds );
sendNotification( CACHE_REGION_CHANGED, getRegionCacheAttributes( region ), region );
}
}
/**
* {@inheritDoc}
*/
public void setRegionCacheMaxTTLSeconds(String region, int maxTTLSeconds) {
Cache cache = this.cacheManager.getCache( region );
if ( cache != null ) {
cache.getCacheConfiguration().setTimeToLiveSeconds( maxTTLSeconds );
sendNotification( CACHE_REGION_CHANGED, getRegionCacheAttributes( region ), region );
}
}
/**
* {@inheritDoc}
*/
public void setRegionCacheTargetMaxInMemoryCount(String region, int targetMaxInMemoryCount) {
Cache cache = this.cacheManager.getCache( region );
if ( cache != null ) {
cache.getCacheConfiguration().setMaxElementsInMemory( targetMaxInMemoryCount );
sendNotification( CACHE_REGION_CHANGED, getRegionCacheAttributes( region ), region );
}
}
/**
* {@inheritDoc}
*/
public void setRegionCacheTargetMaxTotalCount(String region, int targetMaxTotalCount) {
Cache cache = this.cacheManager.getCache( region );
if ( cache != null ) {
cache.getCacheConfiguration().setMaxElementsOnDisk( targetMaxTotalCount );
sendNotification( CACHE_REGION_CHANGED, getRegionCacheAttributes( region ), region );
}
}
/**
* {@inheritDoc}
*
* @see EhcacheStats#getNumberOfElementsInMemory(java.lang.String)
*/
public int getNumberOfElementsInMemory(String region) {
Cache cache = this.cacheManager.getCache( region );
if ( cache != null ) {
return (int) cache.getMemoryStoreSize();
}
else {
return -1;
}
}
/**
* {@inheritDoc}
*
* @see EhcacheStats#getNumberOfElementsOffHeap(java.lang.String)
*/
public int getNumberOfElementsOffHeap(String region) {
Cache cache = this.cacheManager.getCache( region );
if ( cache != null ) {
return (int) cache.getOffHeapStoreSize();
}
else {
return -1;
}
}
/**
* {@inheritDoc}
*
* @see EhcacheStats#getNumberOfElementsOnDisk(java.lang.String)
*/
public int getNumberOfElementsOnDisk(String region) {
Cache cache = this.cacheManager.getCache( region );
if ( cache != null ) {
return cache.getDiskStoreSize();
}
else {
return -1;
}
}
/**
* {@inheritDoc}
*/
public void setStatisticsEnabled(boolean flag) {
for ( String cacheName : cacheManager.getCacheNames() ) {
Cache cache = cacheManager.getCache( cacheName );
if ( cache != null ) {
cache.setStatisticsEnabled( flag );
}
}
if ( flag ) {
clearStats();
}
sendNotification( CACHE_STATISTICS_ENABLED, flag );
}
/**
* {@inheritDoc}
*/
public long getMaxGetTimeMillis() {
long rv = 0;
for ( String cacheName : cacheManager.getCacheNames() ) {
Cache cache = cacheManager.getCache( cacheName );
if ( cache != null ) {
rv = Math.max( rv, cache.getLiveCacheStatistics().getMaxGetTimeMillis() );
}
}
return rv;
}
/**
* {@inheritDoc}
*/
public long getMinGetTimeMillis() {
long rv = 0;
for ( String cacheName : cacheManager.getCacheNames() ) {
Cache cache = cacheManager.getCache( cacheName );
if ( cache != null ) {
rv = Math.max( rv, cache.getLiveCacheStatistics().getMinGetTimeMillis() );
}
}
return rv;
}
/**
* {@inheritDoc}
*
* @see EhcacheStats#getMaxGetTimeMillis(java.lang.String)
*/
public long getMaxGetTimeMillis(String cacheName) {
Cache cache = cacheManager.getCache( cacheName );
if ( cache != null ) {
return cache.getLiveCacheStatistics().getMaxGetTimeMillis();
}
else {
return 0;
}
}
/**
* {@inheritDoc}
*
* @see EhcacheStats#getMinGetTimeMillis(java.lang.String)
*/
public long getMinGetTimeMillis(String cacheName) {
Cache cache = cacheManager.getCache( cacheName );
if ( cache != null ) {
return cache.getLiveCacheStatistics().getMinGetTimeMillis();
}
else {
return 0;
}
}
/**
* {@inheritDoc}
*
* @see EhcacheStats#getAverageGetTimeMillis(java.lang.String)
*/
public float getAverageGetTimeMillis(String region) {
Cache cache = this.cacheManager.getCache( region );
if ( cache != null ) {
return cache.getLiveCacheStatistics().getAverageGetTimeMillis();
}
else {
return -1f;
}
}
/**
* {@inheritDoc}
*/
@Override
protected void doDispose() {
// no-op
}
/**
* @see BaseEmitterBean#getNotificationInfo()
*/
@Override
public MBeanNotificationInfo[] getNotificationInfo() {
return new MBeanNotificationInfo[] { NOTIFICATION_INFO };
}
}

View File

@ -0,0 +1,288 @@
/*
* 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.management.impl;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
import org.hibernate.stat.EntityStatistics;
/**
* When we only support Java 6, all of this OpenMBean scaffolding can be removed in favor or MXBeans.
*
* @author gkeim
*/
public class EntityStats implements Serializable {
private static final String COMPOSITE_TYPE_NAME = "EntityStats";
private static final String COMPOSITE_TYPE_DESCRIPTION = "Statistics per Entity";
private static final String[] ITEM_NAMES = new String[] {
"name", "shortName", "loadCount",
"updateCount", "insertCount", "deleteCount", "fetchCount", "optimisticFailureCount",
};
private static final String[] ITEM_DESCRIPTIONS = new String[] {
"name", "shortName", "loadCount",
"updateCount", "insertCount", "deleteCount", "fetchCount", "optimisticFailureCount",
};
private static final OpenType[] ITEM_TYPES = new OpenType[] {
SimpleType.STRING,
SimpleType.STRING, SimpleType.LONG, SimpleType.LONG, SimpleType.LONG, SimpleType.LONG, SimpleType.LONG,
SimpleType.LONG,
};
private static final CompositeType COMPOSITE_TYPE;
private static final String TABULAR_TYPE_NAME = "Statistics by Entity";
private static final String TABULAR_TYPE_DESCRIPTION = "All Entity Statistics";
private static final String[] INDEX_NAMES = new String[] { "name", };
private static final TabularType TABULAR_TYPE;
static {
try {
COMPOSITE_TYPE = new CompositeType(
COMPOSITE_TYPE_NAME, COMPOSITE_TYPE_DESCRIPTION, ITEM_NAMES,
ITEM_DESCRIPTIONS, ITEM_TYPES
);
TABULAR_TYPE = new TabularType( TABULAR_TYPE_NAME, TABULAR_TYPE_DESCRIPTION, COMPOSITE_TYPE, INDEX_NAMES );
}
catch ( OpenDataException e ) {
throw new RuntimeException( e );
}
}
/**
* name
*/
protected final String name;
/**
* shortName
*/
protected final String shortName;
/**
* loadCount
*/
protected long loadCount;
/**
* updateCount
*/
protected long updateCount;
/**
* insertCount
*/
protected long insertCount;
/**
* deleteCount
*/
protected long deleteCount;
/**
* fetchCount
*/
protected long fetchCount;
/**
* optimisticFailureCount
*/
protected long optimisticFailureCount;
/**
* @param name
*/
public EntityStats(String name) {
this.name = name;
this.shortName = CacheRegionUtils.determineShortName( name );
}
/**
* @param name
* @param src
*/
public EntityStats(String name, EntityStatistics src) {
this( name );
try {
this.loadCount = BeanUtils.getLongBeanProperty( src, "loadCount" );
this.updateCount = BeanUtils.getLongBeanProperty( src, "updateCount" );
this.insertCount = BeanUtils.getLongBeanProperty( src, "insertCount" );
this.deleteCount = BeanUtils.getLongBeanProperty( src, "deleteCount" );
this.fetchCount = BeanUtils.getLongBeanProperty( src, "fetchCount" );
this.optimisticFailureCount = BeanUtils.getLongBeanProperty( src, "optimisticFailureCount" );
}
catch ( Exception e ) {
e.printStackTrace();
throw new RuntimeException( "Exception retrieving statistics", e );
}
}
/**
* @param cData
*/
public EntityStats(final CompositeData cData) {
int i = 0;
name = (String) cData.get( ITEM_NAMES[i++] );
shortName = (String) cData.get( ITEM_NAMES[i++] );
loadCount = (Long) cData.get( ITEM_NAMES[i++] );
updateCount = (Long) cData.get( ITEM_NAMES[i++] );
insertCount = (Long) cData.get( ITEM_NAMES[i++] );
deleteCount = (Long) cData.get( ITEM_NAMES[i++] );
fetchCount = (Long) cData.get( ITEM_NAMES[i++] );
optimisticFailureCount = (Long) cData.get( ITEM_NAMES[i++] );
}
private static int safeParseInt(String s) {
try {
return Integer.parseInt( s );
}
catch ( Exception e ) {
return -1;
}
}
/**
* @param stats
*/
public void add(EntityStats stats) {
loadCount += stats.getLoadCount();
updateCount += stats.getUpdateCount();
insertCount += stats.getInsertCount();
deleteCount += stats.getDeleteCount();
fetchCount += stats.getFetchCount();
optimisticFailureCount += stats.getOptimisticFailureCount();
}
/**
* toString
*/
@Override
public String toString() {
return "name=" + name + ", shortName=" + shortName + ",loadCount=" + loadCount + ", updateCount=" + updateCount
+ ", insertCount=" + insertCount + ", deleteCount=" + deleteCount + ", fetchCount=" + fetchCount
+ ", optimisticFailureCount" + optimisticFailureCount;
}
/**
* getName
*/
public String getName() {
return name;
}
/**
* getShortName
*/
public String getShortName() {
return shortName;
}
/**
* getLoadCount
*/
public long getLoadCount() {
return loadCount;
}
/**
* getUpdateCount
*/
public long getUpdateCount() {
return updateCount;
}
/**
* getInsertCount
*/
public long getInsertCount() {
return insertCount;
}
/**
* getDeleteCount
*/
public long getDeleteCount() {
return deleteCount;
}
/**
* getFetchCount
*/
public long getFetchCount() {
return fetchCount;
}
/**
* getOptimisticFailureCount
*/
public long getOptimisticFailureCount() {
return optimisticFailureCount;
}
/**
* toCompositeData
*/
public CompositeData toCompositeData() {
try {
return new CompositeDataSupport(
COMPOSITE_TYPE, ITEM_NAMES, new Object[] {
name, shortName, loadCount,
updateCount, insertCount, deleteCount, fetchCount, optimisticFailureCount,
}
);
}
catch ( OpenDataException e ) {
throw new RuntimeException( e );
}
}
/**
* newTabularDataInstance
*/
public static TabularData newTabularDataInstance() {
return new TabularDataSupport( TABULAR_TYPE );
}
/**
* fromTabularData
*/
public static EntityStats[] fromTabularData(final TabularData tabularData) {
final List<EntityStats> countList = new ArrayList( tabularData.size() );
for ( final Iterator pos = tabularData.values().iterator(); pos.hasNext(); ) {
countList.add( new EntityStats( (CompositeData) pos.next() ) );
}
return countList.toArray( new EntityStats[countList.size()] );
}
}

View File

@ -0,0 +1,330 @@
/*
* 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.management.impl;
import java.util.ArrayList;
import java.util.List;
import javax.management.MBeanNotificationInfo;
import javax.management.NotCompliantMBeanException;
import javax.management.Notification;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.TabularData;
import net.sf.ehcache.hibernate.management.api.HibernateStats;
import org.hibernate.SessionFactory;
import org.hibernate.stat.Statistics;
/**
* Implementation of {@link HibernateStats}
* <p/>
* <p/>
*
* @author <a href="mailto:asanoujam@terracottatech.com">Abhishek Sanoujam</a>
*/
public class HibernateStatsImpl extends BaseEmitterBean implements HibernateStats {
private static final double MILLIS_PER_SECOND = 1000;
private static final MBeanNotificationInfo NOTIFICATION_INFO;
private final SessionFactory sessionFactory;
static {
final String[] notifTypes = new String[] { };
final String name = Notification.class.getName();
final String description = "Hibernate Statistics Event";
NOTIFICATION_INFO = new MBeanNotificationInfo( notifTypes, name, description );
}
/**
* Constructor accepting the backing {@link SessionFactory}
*
* @param sessionFactory
*
* @throws javax.management.NotCompliantMBeanException
*/
public HibernateStatsImpl(SessionFactory sessionFactory) throws NotCompliantMBeanException {
super( HibernateStats.class );
this.sessionFactory = sessionFactory;
}
/**
* @return statistics
*/
private Statistics getStatistics() {
return sessionFactory.getStatistics();
}
/**
* {@inheritDoc}
*
* @see HibernateStats#clearStats()
*/
public void clearStats() {
getStatistics().clear();
sendNotification( CACHE_STATISTICS_RESET );
}
/**
* {@inheritDoc}
*
* @see HibernateStats#disableStats()
*/
public void disableStats() {
setStatisticsEnabled( false );
}
/**
* {@inheritDoc}
*
* @see HibernateStats#enableStats()
*/
public void enableStats() {
setStatisticsEnabled( true );
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getCloseStatementCount()
*/
public long getCloseStatementCount() {
return getStatistics().getCloseStatementCount();
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getConnectCount()
*/
public long getConnectCount() {
return getStatistics().getConnectCount();
}
/**
* Not supported right now
*/
public long getDBSQLExecutionSample() {
throw new UnsupportedOperationException( "Use getQueryExecutionCount() instead" );
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getFlushCount()
*/
public long getFlushCount() {
return getStatistics().getFlushCount();
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getOptimisticFailureCount()
*/
public long getOptimisticFailureCount() {
return getStatistics().getOptimisticFailureCount();
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getPrepareStatementCount()
*/
public long getPrepareStatementCount() {
return getStatistics().getPrepareStatementCount();
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getQueryExecutionCount()
*/
public long getQueryExecutionCount() {
return getStatistics().getQueryExecutionCount();
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getQueryExecutionRate()
*/
public double getQueryExecutionRate() {
long startTime = getStatistics().getStartTime();
long now = System.currentTimeMillis();
double deltaSecs = ( now - startTime ) / MILLIS_PER_SECOND;
return getQueryExecutionCount() / deltaSecs;
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getQueryExecutionSample()
*/
public long getQueryExecutionSample() {
throw new UnsupportedOperationException( "TODO: need to impl. rates for query execution" );
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getSessionCloseCount()
*/
public long getSessionCloseCount() {
return getStatistics().getSessionCloseCount();
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getSessionOpenCount()
*/
public long getSessionOpenCount() {
return getStatistics().getSessionOpenCount();
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getSuccessfulTransactionCount()
*/
public long getSuccessfulTransactionCount() {
return getStatistics().getSuccessfulTransactionCount();
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getTransactionCount()
*/
public long getTransactionCount() {
return getStatistics().getTransactionCount();
}
/**
* {@inheritDoc}
*
* @see HibernateStats#isStatisticsEnabled()
*/
public boolean isStatisticsEnabled() {
return getStatistics().isStatisticsEnabled();
}
/**
* {@inheritDoc}
*
* @see HibernateStats#setStatisticsEnabled(boolean)
*/
public void setStatisticsEnabled(boolean flag) {
getStatistics().setStatisticsEnabled( flag );
sendNotification( CACHE_STATISTICS_ENABLED, flag );
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getEntityStats()
*/
public TabularData getEntityStats() {
List<CompositeData> result = new ArrayList<CompositeData>();
Statistics statistics = getStatistics();
for ( String entity : statistics.getEntityNames() ) {
EntityStats entityStats = new EntityStats( entity, statistics.getEntityStatistics( entity ) );
result.add( entityStats.toCompositeData() );
}
TabularData td = EntityStats.newTabularDataInstance();
td.putAll( result.toArray( new CompositeData[result.size()] ) );
return td;
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getCollectionStats()
*/
public TabularData getCollectionStats() {
List<CompositeData> result = new ArrayList<CompositeData>();
Statistics statistics = getStatistics();
for ( String roleName : statistics.getCollectionRoleNames() ) {
CollectionStats collectionStats = new CollectionStats(
roleName,
statistics.getCollectionStatistics( roleName )
);
result.add( collectionStats.toCompositeData() );
}
TabularData td = CollectionStats.newTabularDataInstance();
td.putAll( result.toArray( new CompositeData[result.size()] ) );
return td;
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getQueryStats()
*/
public TabularData getQueryStats() {
List<CompositeData> result = new ArrayList<CompositeData>();
Statistics statistics = getStatistics();
for ( String query : statistics.getQueries() ) {
QueryStats queryStats = new QueryStats( query, statistics.getQueryStatistics( query ) );
result.add( queryStats.toCompositeData() );
}
TabularData td = QueryStats.newTabularDataInstance();
td.putAll( result.toArray( new CompositeData[result.size()] ) );
return td;
}
/**
* {@inheritDoc}
*/
public TabularData getCacheRegionStats() {
List<CompositeData> list = new ArrayList<CompositeData>();
Statistics statistics = getStatistics();
for ( String region : statistics.getSecondLevelCacheRegionNames() ) {
CacheRegionStats l2CacheStats = new CacheRegionStats(
region,
statistics.getSecondLevelCacheStatistics( region )
);
list.add( l2CacheStats.toCompositeData() );
}
TabularData td = CacheRegionStats.newTabularDataInstance();
td.putAll( list.toArray( new CompositeData[list.size()] ) );
return td;
}
/**
* {@inheritDoc}
*/
@Override
protected void doDispose() {
// no-op
}
/**
* @see BaseEmitterBean#getNotificationInfo()
*/
@Override
public MBeanNotificationInfo[] getNotificationInfo() {
return new MBeanNotificationInfo[] { NOTIFICATION_INFO };
}
}

View File

@ -0,0 +1,300 @@
/*
* 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.management.impl;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanNotificationInfo;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.openmbean.TabularData;
import net.sf.ehcache.hibernate.management.api.HibernateStats;
/**
* Implementation of {@link HibernateStats} that does nothing
* <p/>
* <p/>
*
* @author <a href="mailto:asanoujam@terracottatech.com">Abhishek Sanoujam</a>
*/
public final class NullHibernateStats implements HibernateStats {
/**
* Singleton instance.
*/
public static final HibernateStats INSTANCE = new NullHibernateStats();
/**
* private constructor. No need to create instances of this. Use singleton instance
*/
private NullHibernateStats() {
super();
// TODO Auto-generated constructor stub
}
/**
* {@inheritDoc}
*
* @see HibernateStats#clearStats()
*/
public void clearStats() {
// no-op
}
/**
* {@inheritDoc}
*
* @see HibernateStats#disableStats()
*/
public void disableStats() {
// no-op
}
/**
* {@inheritDoc}
*
* @see HibernateStats#enableStats()
*/
public void enableStats() {
// no-op
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getCloseStatementCount()
*/
public long getCloseStatementCount() {
// no-op
return 0;
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getCollectionStats()
*/
public TabularData getCollectionStats() {
// no-op
return null;
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getConnectCount()
*/
public long getConnectCount() {
// no-op
return 0;
}
/**
* Not supported right now
*/
public long getDBSQLExecutionSample() {
// no-op
return 0;
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getEntityStats()
*/
public TabularData getEntityStats() {
// no-op
return null;
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getFlushCount()
*/
public long getFlushCount() {
// no-op
return 0;
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getOptimisticFailureCount()
*/
public long getOptimisticFailureCount() {
// no-op
return 0;
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getPrepareStatementCount()
*/
public long getPrepareStatementCount() {
// no-op
return 0;
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getQueryExecutionCount()
*/
public long getQueryExecutionCount() {
// no-op
return 0;
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getQueryExecutionRate()
*/
public double getQueryExecutionRate() {
// no-op
return 0;
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getQueryExecutionSample()
*/
public long getQueryExecutionSample() {
// no-op
return 0;
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getQueryStats()
*/
public TabularData getQueryStats() {
// no-op
return null;
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getSessionCloseCount()
*/
public long getSessionCloseCount() {
// no-op
return 0;
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getSessionOpenCount()
*/
public long getSessionOpenCount() {
// no-op
return 0;
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getSuccessfulTransactionCount()
*/
public long getSuccessfulTransactionCount() {
// no-op
return 0;
}
/**
* {@inheritDoc}
*
* @see HibernateStats#getTransactionCount()
*/
public long getTransactionCount() {
// no-op
return 0;
}
/**
* {@inheritDoc}
*
* @see HibernateStats#isStatisticsEnabled()
*/
public boolean isStatisticsEnabled() {
// no-op
return false;
}
/**
* {@inheritDoc}
*
* @see HibernateStats#setStatisticsEnabled(boolean)
*/
public void setStatisticsEnabled(boolean flag) {
// no-op
}
/**
* @see HibernateStats#getCacheRegionStats()
*/
public TabularData getCacheRegionStats() {
return null;
}
/**
* @see javax.management.NotificationEmitter#removeNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object)
*/
public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback)
throws ListenerNotFoundException {
/**/
}
/**
* @see javax.management.NotificationBroadcaster#addNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object)
*/
public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback)
throws IllegalArgumentException {
/**/
}
/**
* @see javax.management.NotificationBroadcaster#getNotificationInfo()
*/
public MBeanNotificationInfo[] getNotificationInfo() {
return null;
}
/**
* @see javax.management.NotificationBroadcaster#removeNotificationListener(javax.management.NotificationListener)
*/
public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException {
/**/
}
}

View File

@ -0,0 +1,186 @@
/*
* 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.management.impl;
import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
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.hibernate.SessionFactory;
import org.hibernate.cache.CacheException;
import org.hibernate.cfg.Environment;
import org.hibernate.internal.SessionFactoryRegistry;
/**
* Helper class for registering mbeans for ehcache backed hibernate second level cache
* <p/>
* <p/>
*
* @author <a href="mailto:asanoujam@terracottatech.com">Abhishek Sanoujam</a>
* @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 int MILLIS_PER_SECOND = 1000;
private static final int SLEEP_MILLIS = 500;
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
);
}
}
/**
* 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;
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();
}
}
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 + "'" );
}
}

View File

@ -0,0 +1,322 @@
/*
* 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.management.impl;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
import org.hibernate.stat.QueryStatistics;
/**
* @author gkeim
* @author Alex Snaps
*/
public class QueryStats implements Serializable {
private static final String COMPOSITE_TYPE_NAME = "QueryStats";
private static final String COMPOSITE_TYPE_DESCRIPTION = "Statistics per Query";
private static final String[] ITEM_NAMES = new String[] {
"query", "cacheHitCount",
"cacheMissCount",
"cachePutCount",
"executionCount",
"executionRowCount",
"executionAvgTime",
"executionMaxTime",
"executionMinTime",
};
private static final String[] ITEM_DESCRIPTIONS = new String[] {
"query", "cacheHitCount",
"cacheMissCount",
"cachePutCount",
"executionCount",
"executionRowCount",
"executionAvgTime",
"executionMaxTime",
"executionMinTime",
};
private static final OpenType[] ITEM_TYPES = new OpenType[] {
SimpleType.STRING, SimpleType.LONG,
SimpleType.LONG, SimpleType.LONG, SimpleType.LONG, SimpleType.LONG, SimpleType.LONG, SimpleType.LONG,
SimpleType.LONG,
};
private static final CompositeType COMPOSITE_TYPE;
private static final String TABULAR_TYPE_NAME = "Statistics by Query";
private static final String TABULAR_TYPE_DESCRIPTION = "All Query Statistics";
private static final String[] INDEX_NAMES = new String[] { "query", };
private static final TabularType TABULAR_TYPE;
static {
try {
COMPOSITE_TYPE = new CompositeType(
COMPOSITE_TYPE_NAME, COMPOSITE_TYPE_DESCRIPTION, ITEM_NAMES,
ITEM_DESCRIPTIONS, ITEM_TYPES
);
TABULAR_TYPE = new TabularType( TABULAR_TYPE_NAME, TABULAR_TYPE_DESCRIPTION, COMPOSITE_TYPE, INDEX_NAMES );
}
catch ( OpenDataException e ) {
throw new RuntimeException( e );
}
}
/**
* query
*/
protected final String query;
/**
* cacheHitCount
*/
protected long cacheHitCount;
/**
* cacheMissCount
*/
protected long cacheMissCount;
/**
* cachePutCount
*/
protected long cachePutCount;
/**
* executionCount
*/
protected long executionCount;
/**
* executionRowCount
*/
protected long executionRowCount;
/**
* executionAvgTime
*/
protected long executionAvgTime;
/**
* executionMaxTime
*/
protected long executionMaxTime;
/**
* executionMinTime
*/
protected long executionMinTime;
/**
* @param name
*/
public QueryStats(String name) {
this.query = name;
}
/**
* @param name
* @param src
*/
public QueryStats(String name, QueryStatistics src) {
this( name );
try {
this.cacheHitCount = BeanUtils.getLongBeanProperty( src, "cacheHitCount" );
this.cacheMissCount = BeanUtils.getLongBeanProperty( src, "cacheMissCount" );
this.cachePutCount = BeanUtils.getLongBeanProperty( src, "cachePutCount" );
this.executionCount = BeanUtils.getLongBeanProperty( src, "executionCount" );
this.executionRowCount = BeanUtils.getLongBeanProperty( src, "executionRowCount" );
this.executionAvgTime = BeanUtils.getLongBeanProperty( src, "executionAvgTime" );
this.executionMaxTime = BeanUtils.getLongBeanProperty( src, "executionMaxTime" );
this.executionMinTime =
BeanUtils.getLongBeanProperty( src, "executionMinTime" );
}
catch ( Exception e ) {
e.printStackTrace();
throw new RuntimeException( "Exception retrieving statistics", e );
}
}
/**
* @param cData
*/
public QueryStats(final CompositeData cData) {
int i = 0;
query = (String) cData.get( ITEM_NAMES[i++] );
cacheHitCount = (Long) cData.get( ITEM_NAMES[i++] );
cacheMissCount = (Long) cData.get( ITEM_NAMES[i++] );
cachePutCount = (Long) cData.get( ITEM_NAMES[i++] );
executionCount = (Long) cData.get( ITEM_NAMES[i++] );
executionRowCount = (Long) cData.get( ITEM_NAMES[i++] );
executionAvgTime = (Long) cData.get( ITEM_NAMES[i++] );
executionMaxTime = (Long) cData.get( ITEM_NAMES[i++] );
executionMinTime = (Long) cData.get( ITEM_NAMES[i++] );
}
private static int safeParseInt(String s) {
try {
return Integer.parseInt( s );
}
catch ( Exception e ) {
return -1;
}
}
/**
* @param stats
*/
public void add(QueryStats stats) {
cacheHitCount += stats.getCacheHitCount();
cacheMissCount += stats.getCacheMissCount();
cachePutCount += stats.getCachePutCount();
executionCount += stats.getExecutionCount();
executionRowCount += stats.getExecutionRowCount();
executionAvgTime += stats.getExecutionAvgTime();
executionMaxTime += stats.getExecutionMaxTime();
executionMinTime += stats.getExecutionMinTime();
}
/**
* toString
*/
@Override
public String toString() {
return "query=" + query + ", cacheHitCount=" + cacheHitCount + ", cacheMissCount=" + cacheMissCount
+ ", cachePutCount=" + cachePutCount + ", executionCount=" + executionCount + ", executionRowCount="
+ executionRowCount + ", executionAvgTime=" + executionAvgTime + ", executionMaxTime=" + executionMaxTime
+ ", executionMinTime=" + executionMinTime;
}
/**
* getQuery
*/
public String getQuery() {
return query;
}
/**
* getCacheHitCount
*/
public long getCacheHitCount() {
return cacheHitCount;
}
/**
* getCacheMissCount
*/
public long getCacheMissCount() {
return cacheMissCount;
}
/**
* getCachePutCount
*/
public long getCachePutCount() {
return cachePutCount;
}
/**
* getExecutionCount
*/
public long getExecutionCount() {
return executionCount;
}
/**
* getExecutionRowCount
*/
public long getExecutionRowCount() {
return executionRowCount;
}
/**
* getExecutionAvgTime
*/
public long getExecutionAvgTime() {
return executionAvgTime;
}
/**
* getExecutionMaxTime
*/
public long getExecutionMaxTime() {
return executionMaxTime;
}
/**
* getExecutionMinTime
*/
public long getExecutionMinTime() {
return executionMinTime;
}
/**
* toCompositeData
*/
public CompositeData toCompositeData() {
try {
return new CompositeDataSupport(
COMPOSITE_TYPE, ITEM_NAMES, new Object[] {
query, cacheHitCount, cacheMissCount,
cachePutCount,
executionCount,
executionRowCount,
executionAvgTime,
executionMaxTime,
executionMinTime,
}
);
}
catch ( OpenDataException e ) {
throw new RuntimeException( e );
}
}
/**
* newTabularDataInstance
*/
public static TabularData newTabularDataInstance() {
return new TabularDataSupport( TABULAR_TYPE );
}
/**
* fromTabularData
*/
public static QueryStats[] fromTabularData(final TabularData tabularData) {
final List<QueryStats> countList = new ArrayList( tabularData.size() );
for ( final Iterator pos = tabularData.values().iterator(); pos.hasNext(); ) {
countList.add( new QueryStats( (CompositeData) pos.next() ) );
}
return countList.toArray( new QueryStats[countList.size()] );
}
}

View File

@ -0,0 +1,92 @@
/*
* 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

@ -0,0 +1,80 @@
/*
* 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

@ -0,0 +1,227 @@
/*
* 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.hibernate.cache.CacheException;
import org.hibernate.cache.spi.CollectionRegion;
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
import org.hibernate.cache.spi.access.SoftLock;
/**
* Implementation of {@link CollectionRegionAccessStrategy} that handles {@link NonStopCacheException} using
* {@link HibernateNonstopCacheExceptionHandler}
*
* @author Abhishek Sanoujam
* @author Alex Snaps
*/
public class NonstopAwareCollectionRegionAccessStrategy implements CollectionRegionAccessStrategy {
private final CollectionRegionAccessStrategy actualStrategy;
private final HibernateNonstopCacheExceptionHandler hibernateNonstopExceptionHandler;
/**
* Constructor accepting the actual {@link CollectionRegionAccessStrategy} and the {@link HibernateNonstopCacheExceptionHandler}
*
* @param actualStrategy
* @param hibernateNonstopExceptionHandler
*/
public NonstopAwareCollectionRegionAccessStrategy(CollectionRegionAccessStrategy actualStrategy,
HibernateNonstopCacheExceptionHandler hibernateNonstopExceptionHandler) {
this.actualStrategy = actualStrategy;
this.hibernateNonstopExceptionHandler = hibernateNonstopExceptionHandler;
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#getRegion()
*/
public CollectionRegion getRegion() {
return actualStrategy.getRegion();
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#evict(java.lang.Object)
*/
public void evict(Object key) throws CacheException {
try {
actualStrategy.evict( key );
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#evictAll()
*/
public void evictAll() throws CacheException {
try {
actualStrategy.evictAll();
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#get(java.lang.Object, long)
*/
public Object get(Object key, long txTimestamp) throws CacheException {
try {
return actualStrategy.get( key, txTimestamp );
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
return null;
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#lockItem(java.lang.Object, java.lang.Object)
*/
public SoftLock lockItem(Object key, Object version) throws CacheException {
try {
return actualStrategy.lockItem( key, version );
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
return null;
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#lockRegion()
*/
public SoftLock lockRegion() throws CacheException {
try {
return actualStrategy.lockRegion();
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
return null;
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object,
* boolean)
*/
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
throws CacheException {
try {
return actualStrategy.putFromLoad( key, value, txTimestamp, version, minimalPutOverride );
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
return false;
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object)
*/
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
try {
return actualStrategy.putFromLoad( key, value, txTimestamp, version );
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
return false;
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#remove(java.lang.Object)
*/
public void remove(Object key) throws CacheException {
try {
actualStrategy.remove( key );
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#removeAll()
*/
public void removeAll() throws CacheException {
try {
actualStrategy.removeAll();
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#unlockItem(java.lang.Object, org.hibernate.cache.spi.access.SoftLock)
*/
public void unlockItem(Object key, SoftLock lock) throws CacheException {
try {
actualStrategy.unlockItem( key, lock );
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#unlockRegion(org.hibernate.cache.spi.access.SoftLock)
*/
public void unlockRegion(SoftLock lock) throws CacheException {
try {
actualStrategy.unlockRegion( lock );
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
}
}
}

View File

@ -0,0 +1,290 @@
/*
* 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.hibernate.cache.CacheException;
import org.hibernate.cache.spi.EntityRegion;
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
import org.hibernate.cache.spi.access.SoftLock;
/**
* Implementation of {@link EntityRegionAccessStrategy} that handles {@link net.sf.ehcache.constructs.nonstop.NonStopCacheException} using
* {@link HibernateNonstopCacheExceptionHandler}
*
* @author Abhishek Sanoujam
* @author Alex Snaps
*/
public class NonstopAwareEntityRegionAccessStrategy implements EntityRegionAccessStrategy {
private final EntityRegionAccessStrategy actualStrategy;
private final HibernateNonstopCacheExceptionHandler hibernateNonstopExceptionHandler;
/**
* Constructor accepting the actual {@link EntityRegionAccessStrategy} and the {@link HibernateNonstopCacheExceptionHandler}
*
* @param actualStrategy
* @param hibernateNonstopExceptionHandler
*/
public NonstopAwareEntityRegionAccessStrategy(EntityRegionAccessStrategy actualStrategy,
HibernateNonstopCacheExceptionHandler hibernateNonstopExceptionHandler) {
this.actualStrategy = actualStrategy;
this.hibernateNonstopExceptionHandler = hibernateNonstopExceptionHandler;
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#getRegion()
*/
public EntityRegion getRegion() {
return actualStrategy.getRegion();
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#afterInsert(java.lang.Object, java.lang.Object, java.lang.Object)
*/
public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
try {
return actualStrategy.afterInsert( key, value, version );
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
return false;
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#afterUpdate(java.lang.Object, java.lang.Object, java.lang.Object,
* java.lang.Object, org.hibernate.cache.spi.access.SoftLock)
*/
public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
throws CacheException {
try {
return actualStrategy.afterUpdate( key, value, currentVersion, previousVersion, lock );
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
return false;
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#evict(java.lang.Object)
*/
public void evict(Object key) throws CacheException {
try {
actualStrategy.evict( key );
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#evictAll()
*/
public void evictAll() throws CacheException {
try {
actualStrategy.evictAll();
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#get(java.lang.Object, long)
*/
public Object get(Object key, long txTimestamp) throws CacheException {
try {
return actualStrategy.get( key, txTimestamp );
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
return null;
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#insert(java.lang.Object, java.lang.Object, java.lang.Object)
*/
public boolean insert(Object key, Object value, Object version) throws CacheException {
try {
return actualStrategy.insert( key, value, version );
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
return false;
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#lockItem(java.lang.Object, java.lang.Object)
*/
public SoftLock lockItem(Object key, Object version) throws CacheException {
try {
return actualStrategy.lockItem( key, version );
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
return null;
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#lockRegion()
*/
public SoftLock lockRegion() throws CacheException {
try {
return actualStrategy.lockRegion();
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
return null;
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object,
* boolean)
*/
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
throws CacheException {
try {
return actualStrategy.putFromLoad( key, value, txTimestamp, version, minimalPutOverride );
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
return false;
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object)
*/
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
try {
return actualStrategy.putFromLoad( key, value, txTimestamp, version );
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
return false;
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#remove(java.lang.Object)
*/
public void remove(Object key) throws CacheException {
try {
actualStrategy.remove( key );
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#removeAll()
*/
public void removeAll() throws CacheException {
try {
actualStrategy.removeAll();
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#unlockItem(java.lang.Object, org.hibernate.cache.spi.access.SoftLock)
*/
public void unlockItem(Object key, SoftLock lock) throws CacheException {
try {
actualStrategy.unlockItem( key, lock );
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#unlockRegion(org.hibernate.cache.spi.access.SoftLock)
*/
public void unlockRegion(SoftLock lock) throws CacheException {
try {
actualStrategy.unlockRegion( lock );
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
}
}
/**
* {@inheritDoc}
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#update(java.lang.Object, java.lang.Object, java.lang.Object,
* java.lang.Object)
*/
public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
throws CacheException {
try {
return actualStrategy.update( key, value, currentVersion, previousVersion );
}
catch ( NonStopCacheException nonStopCacheException ) {
hibernateNonstopExceptionHandler.handleNonstopCacheException( nonStopCacheException );
return false;
}
}
}

View File

@ -0,0 +1,71 @@
/*
* 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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.ehcache.strategy.EhcacheAccessStrategyFactory;
import org.hibernate.cache.spi.CacheDataDescription;
import org.hibernate.cache.spi.CollectionRegion;
import org.hibernate.cache.spi.access.AccessType;
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
import org.hibernate.cfg.Settings;
/**
* A collection region specific wrapper around an Ehcache instance.
* <p/>
* This implementation returns Ehcache specific access strategy instances for all the non-transactional access types. Transactional access
* is not supported.
*
* @author Chris Dennis
* @author Abhishek Sanoujam
* @author Alex Snaps
*/
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 );
}
/**
* {@inheritDoc}
*/
public CollectionRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
return accessStrategyFactory.createCollectionRegionAccessStrategy( this, accessType );
}
}

View File

@ -0,0 +1,223 @@
/*
* 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

@ -0,0 +1,70 @@
/*
* 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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.ehcache.strategy.EhcacheAccessStrategyFactory;
import org.hibernate.cache.spi.CacheDataDescription;
import org.hibernate.cache.spi.EntityRegion;
import org.hibernate.cache.spi.access.AccessType;
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
import org.hibernate.cfg.Settings;
/**
* An entity region specific wrapper around an Ehcache instance.
* <p/>
* This implementation returns Ehcache specific access strategy instances for all the non-transactional access types. Transactional access
* is not supported.
*
* @author Chris Dennis
* @author Abhishek Sanoujam
* @author Alex Snaps
*/
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 );
}
/**
* {@inheritDoc}
*/
public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType) throws CacheException {
return accessStrategyFactory.createEntityRegionAccessStrategy( this, accessType );
}
}

View File

@ -0,0 +1,163 @@
/*
* 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,7 +1,7 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
* 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.
@ -21,20 +21,30 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.cache.internal;
package org.hibernate.cache.ehcache.regions;
import java.util.Properties;
import net.sf.ehcache.Ehcache;
import org.hibernate.cache.ehcache.strategy.EhcacheAccessStrategyFactory;
import org.hibernate.cache.spi.QueryResultsRegion;
/**
* Thin wrapper class around the within Ehcache-core packaged EhCacheRegionFactory.
* It directly delegates to the wrapped instance, enabling users to upgrade Ehcache-core versions
* by simply dropping in the new jar.
* A query results region specific wrapper around an Ehcache instance.
*
* @author Chris Dennis
* @author Alex Snaps
*/
public final class EhCacheRegionFactory extends AbstractEhCacheRegionFactory {
public class EhcacheQueryResultsRegion extends EhcacheGeneralDataRegion implements QueryResultsRegion {
public EhCacheRegionFactory(Properties properties) {
super(new net.sf.ehcache.hibernate.EhCacheRegionFactory(properties));
/**
* Constructs an EhcacheQueryResultsRegion around the given underlying cache.
*
* @param accessStrategyFactory
*/
public EhcacheQueryResultsRegion(EhcacheAccessStrategyFactory accessStrategyFactory, Ehcache underlyingCache, Properties properties) {
super( accessStrategyFactory, underlyingCache, properties );
}
}

View File

@ -1,7 +1,7 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
* 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.
@ -21,20 +21,30 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.cache.internal;
package org.hibernate.cache.ehcache.regions;
import net.sf.ehcache.Ehcache;
import org.hibernate.cache.ehcache.strategy.EhcacheAccessStrategyFactory;
import org.hibernate.cache.ehcache.strategy.EhcacheAccessStrategyFactory;
import org.hibernate.cache.spi.TimestampsRegion;
import java.util.Properties;
/**
* Thin wrapper class around the within Ehcache-core packaged SingletonEhCacheRegionFactory.
* It directly delegates to the wrapped instance, enabling user to upgrade the Ehcache-core version
* by simply dropping in a new jar.
* A timestamps region specific wrapper around an Ehcache instance.
*
* @author Chris Dennis
* @author Abhishek Sanoujam
* @author Alex Snaps
*/
public final class SingletonEhCacheRegionFactory extends AbstractEhCacheRegionFactory {
public class EhcacheTimestampsRegion extends EhcacheGeneralDataRegion implements TimestampsRegion {
public SingletonEhCacheRegionFactory(Properties properties) {
super(new net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory(properties));
/**
* Constructs an EhcacheTimestampsRegion around the given underlying cache.
*
* @param accessStrategyFactory
*/
public EhcacheTimestampsRegion(EhcacheAccessStrategyFactory accessStrategyFactory, Ehcache underlyingCache, Properties properties) {
super(accessStrategyFactory, underlyingCache, properties);
}
}

View File

@ -0,0 +1,286 @@
/*
* 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.concurrent.CacheLockProvider;
import net.sf.ehcache.concurrent.LockType;
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.spi.CacheDataDescription;
import org.hibernate.cache.spi.TransactionalDataRegion;
import org.hibernate.cfg.Settings;
/**
* An Ehcache specific TransactionalDataRegion.
* <p/>
* This is the common superclass entity and collection regions.
*
* @author Chris Dennis
* @author Greg Luck
* @author Emmanuel Bernard
* @author Abhishek Sanoujam
* @author Alex Snaps
*/
public class EhcacheTransactionalDataRegion extends EhcacheDataRegion implements TransactionalDataRegion {
private static final int LOCAL_LOCK_PROVIDER_CONCURRENCY = 128;
/**
* Hibernate settings associated with the persistence unit.
*/
protected final Settings settings;
/**
* Metadata associated with the objects stored in the region.
*/
protected final CacheDataDescription metadata;
private final CacheLockProvider lockProvider;
/**
* Construct an transactional Hibernate cache region around the given Ehcache instance.
*/
EhcacheTransactionalDataRegion(EhcacheAccessStrategyFactory accessStrategyFactory, Ehcache cache, Settings settings,
CacheDataDescription metadata, Properties properties) {
super( accessStrategyFactory, cache, properties );
this.settings = settings;
this.metadata = metadata;
Object context = cache.getInternalContext();
if ( context instanceof CacheLockProvider ) {
this.lockProvider = (CacheLockProvider) context;
}
else {
this.lockProvider = new StripedReadWriteLockSync( LOCAL_LOCK_PROVIDER_CONCURRENCY );
}
}
/**
* Return the hibernate settings
*
* @return settings
*/
public Settings getSettings() {
return settings;
}
/**
* {@inheritDoc}
*/
public boolean isTransactionAware() {
return false;
}
/**
* {@inheritDoc}
*/
public CacheDataDescription getCacheDataDescription() {
return metadata;
}
/**
* Get the value mapped to this key, or null if no value is mapped to this key.
*/
public final Object get(Object key) {
try {
Element element = cache.get( key );
if ( element == null ) {
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 );
}
}
}
/**
* Map the given value to the given key, replacing any existing mapping for this key
*/
public final void put(Object key, Object value) throws CacheException {
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 );
}
}
}
/**
* Remove the mapping for this key (if any exists).
*/
public final void remove(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 );
}
}
}
/**
* Remove all mapping from this cache region.
*/
public final void clear() 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 );
}
}
}
/**
* Attempts to write lock the mapping for the given key.
*/
public final void writeLock(Object key) {
try {
lockProvider.getSyncForKey( key ).lock( LockType.WRITE );
}
catch ( net.sf.ehcache.CacheException e ) {
if ( e instanceof NonStopCacheException ) {
HibernateNonstopCacheExceptionHandler.getInstance()
.handleNonstopCacheException( (NonStopCacheException) e );
}
else {
throw new CacheException( e );
}
}
}
/**
* Attempts to write unlock the mapping for the given key.
*/
public final void writeUnlock(Object key) {
try {
lockProvider.getSyncForKey( key ).unlock( LockType.WRITE );
}
catch ( net.sf.ehcache.CacheException e ) {
if ( e instanceof NonStopCacheException ) {
HibernateNonstopCacheExceptionHandler.getInstance()
.handleNonstopCacheException( (NonStopCacheException) e );
}
else {
throw new CacheException( e );
}
}
}
/**
* Attempts to read lock the mapping for the given key.
*/
public final void readLock(Object key) {
try {
lockProvider.getSyncForKey( key ).lock( LockType.WRITE );
}
catch ( net.sf.ehcache.CacheException e ) {
if ( e instanceof NonStopCacheException ) {
HibernateNonstopCacheExceptionHandler.getInstance()
.handleNonstopCacheException( (NonStopCacheException) e );
}
else {
throw new CacheException( e );
}
}
}
/**
* Attempts to read unlock the mapping for the given key.
*/
public final void readUnlock(Object key) {
try {
lockProvider.getSyncForKey( key ).unlock( LockType.WRITE );
}
catch ( net.sf.ehcache.CacheException e ) {
if ( e instanceof NonStopCacheException ) {
HibernateNonstopCacheExceptionHandler.getInstance()
.handleNonstopCacheException( (NonStopCacheException) e );
}
else {
throw new CacheException( e );
}
}
}
/**
* Returns <code>true</code> if the locks used by the locking methods of this region are the independent of the cache.
* <p/>
* Independent locks are not locked by the cache when the cache is accessed directly. This means that for an independent lock
* lock holds taken through a region method will not block direct access to the cache via other means.
*/
public final boolean locksAreIndependentOfCache() {
return lockProvider instanceof StripedReadWriteLockSync;
}
}

View File

@ -0,0 +1,140 @@
/*
* 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.hibernate.cache.CacheException;
import org.hibernate.cache.ehcache.regions.EhcacheTransactionalDataRegion;
import org.hibernate.cache.spi.access.SoftLock;
import org.hibernate.cfg.Settings;
/**
* Ultimate superclass for all Ehcache specific Hibernate AccessStrategy implementations.
*
* @param <T> type of the enclosed region
*
* @author Chris Dennis
* @author Alex Snaps
*/
abstract class AbstractEhcacheAccessStrategy<T extends EhcacheTransactionalDataRegion> {
/**
* The wrapped Hibernate cache region.
*/
protected final T region;
/**
* The settings for this persistence unit.
*/
protected final Settings settings;
/**
* Create an access strategy wrapping the given region.
*/
AbstractEhcacheAccessStrategy(T region, Settings settings) {
this.region = region;
this.settings = settings;
}
/**
* This method is a placeholder for method signatures supplied by interfaces pulled in further down the class
* hierarchy.
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object)
* @see org.hibernate.cache.spi.access.CollectionRegionAccessStrategy#putFromLoad(java.lang.Object, java.lang.Object, long, java.lang.Object)
*/
public final boolean putFromLoad(Object key, Object value, long txTimestamp, Object version) throws CacheException {
return putFromLoad( key, value, txTimestamp, version, settings.isMinimalPutsEnabled() );
}
/**
* This method is a placeholder for method signatures supplied by interfaces pulled in further down the class
* hierarchy.
*
* @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)
*/
public abstract boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
throws CacheException;
/**
* Region locks are not supported.
*
* @return <code>null</code>
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#lockRegion()
* @see org.hibernate.cache.spi.access.CollectionRegionAccessStrategy#lockRegion()
*/
public final SoftLock lockRegion() {
return null;
}
/**
* Region locks are not supported - perform a cache clear as a precaution.
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#unlockRegion(org.hibernate.cache.spi.access.SoftLock)
* @see org.hibernate.cache.spi.access.CollectionRegionAccessStrategy#unlockRegion(org.hibernate.cache.spi.access.SoftLock)
*/
public final void unlockRegion(SoftLock lock) throws CacheException {
region.clear();
}
/**
* A no-op since this is an asynchronous cache access strategy.
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#remove(java.lang.Object)
* @see org.hibernate.cache.spi.access.CollectionRegionAccessStrategy#remove(java.lang.Object)
*/
public void remove(Object key) throws CacheException {
}
/**
* Called to evict data from the entire region
*
* @throws CacheException Propogated from underlying {@link org.hibernate.cache.spi.Region}
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#removeAll()
* @see org.hibernate.cache.spi.access.CollectionRegionAccessStrategy#removeAll()
*/
public final void removeAll() throws CacheException {
region.clear();
}
/**
* Remove the given mapping without regard to transactional safety
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#evict(java.lang.Object)
* @see org.hibernate.cache.spi.access.CollectionRegionAccessStrategy#evict(java.lang.Object)
*/
public final void evict(Object key) throws CacheException {
region.remove( key );
}
/**
* Remove all mappings without regard to transactional safety
*
* @see org.hibernate.cache.spi.access.EntityRegionAccessStrategy#evictAll()
* @see org.hibernate.cache.spi.access.CollectionRegionAccessStrategy#evictAll()
*/
public final void evictAll() throws CacheException {
region.clear();
}
}

View File

@ -0,0 +1,428 @@
/*
* 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

@ -0,0 +1,61 @@
/*
* 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.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;
/**
* Factory to create {@link EntityRegionAccessStrategy}
*
* @author Abhishek Sanoujam
* @author Alex Snaps
*/
public interface EhcacheAccessStrategyFactory {
/**
* Create {@link EntityRegionAccessStrategy} for the input {@link EhcacheEntityRegion} and {@link AccessType}
*
* @param entityRegion
* @param accessType
*
* @return the created {@link EntityRegionAccessStrategy}
*/
public EntityRegionAccessStrategy createEntityRegionAccessStrategy(EhcacheEntityRegion entityRegion, AccessType accessType);
/**
* Create {@link CollectionRegionAccessStrategy} for the input {@link org.hibernate.cache.ehcache.regions.EhcacheCollectionRegion} and {@link AccessType}
*
* @param collectionRegion
* @param accessType
*
* @return the created {@link CollectionRegionAccessStrategy}
*/
public CollectionRegionAccessStrategy createCollectionRegionAccessStrategy(EhcacheCollectionRegion collectionRegion,
AccessType accessType);
}

View File

@ -0,0 +1,110 @@
/*
* 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

@ -0,0 +1,99 @@
/*
* 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.hibernate.cache.CacheException;
import org.hibernate.cache.ehcache.regions.EhcacheCollectionRegion;
import org.hibernate.cache.spi.CollectionRegion;
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
import org.hibernate.cache.spi.access.SoftLock;
import org.hibernate.cfg.Settings;
/**
* Ehcache specific non-strict read/write collection region access strategy
*
* @author Chris Dennis
* @author Alex Snaps
*/
public class NonStrictReadWriteEhcacheCollectionRegionAccessStrategy
extends AbstractEhcacheAccessStrategy<EhcacheCollectionRegion>
implements CollectionRegionAccessStrategy {
/**
* Create a non-strict read/write access strategy accessing the given collection region.
*/
public NonStrictReadWriteEhcacheCollectionRegionAccessStrategy(EhcacheCollectionRegion region, Settings settings) {
super( region, settings );
}
/**
* {@inheritDoc}
*/
public CollectionRegion getRegion() {
return region;
}
/**
* {@inheritDoc}
*/
public Object get(Object key, long txTimestamp) throws CacheException {
return region.get( key );
}
/**
* {@inheritDoc}
*/
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
throws CacheException {
if ( minimalPutOverride && region.contains( key ) ) {
return false;
}
else {
region.put( key, value );
return true;
}
}
/**
* Since this is a non-strict read/write strategy item locking is not used.
*/
public SoftLock lockItem(Object key, Object version) throws CacheException {
return null;
}
/**
* Since this is a non-strict read/write strategy item locking is not used.
*/
public void unlockItem(Object key, SoftLock lock) throws CacheException {
region.remove( key );
}
/**
* {@inheritDoc}
*/
@Override
public void remove(Object key) throws CacheException {
region.remove( key );
}
}

View File

@ -0,0 +1,131 @@
/*
* 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.hibernate.cache.CacheException;
import org.hibernate.cache.ehcache.regions.EhcacheEntityRegion;
import org.hibernate.cache.spi.EntityRegion;
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
import org.hibernate.cache.spi.access.SoftLock;
import org.hibernate.cfg.Settings;
/**
* Ehcache specific non-strict read/write entity region access strategy
*
* @author Chris Dennis
* @author Alex Snaps
*/
public class NonStrictReadWriteEhcacheEntityRegionAccessStrategy
extends AbstractEhcacheAccessStrategy<EhcacheEntityRegion>
implements EntityRegionAccessStrategy {
/**
* Create a non-strict read/write access strategy accessing the given collection region.
*/
public NonStrictReadWriteEhcacheEntityRegionAccessStrategy(EhcacheEntityRegion region, Settings settings) {
super( region, settings );
}
/**
* {@inheritDoc}
*/
public EntityRegion getRegion() {
return region;
}
/**
* {@inheritDoc}
*/
public Object get(Object key, long txTimestamp) throws CacheException {
return region.get( key );
}
/**
* {@inheritDoc}
*/
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
throws CacheException {
if ( minimalPutOverride && region.contains( key ) ) {
return false;
}
else {
region.put( key, value );
return true;
}
}
/**
* Since this is a non-strict read/write strategy item locking is not used.
*/
public SoftLock lockItem(Object key, Object version) throws CacheException {
return null;
}
/**
* Since this is a non-strict read/write strategy item locking is not used.
*/
public void unlockItem(Object key, SoftLock lock) throws CacheException {
region.remove( key );
}
/**
* Returns <code>false</code> since this is an asynchronous cache access strategy.
*/
public boolean insert(Object key, Object value, Object version) throws CacheException {
return false;
}
/**
* Returns <code>false</code> since this is a non-strict read/write cache access strategy
*/
public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
return false;
}
/**
* Removes the entry since this is a non-strict read/write cache strategy.
*/
public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
throws CacheException {
remove( key );
return false;
}
/**
* {@inheritDoc}
*/
public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
throws CacheException {
unlockItem( key, lock );
return false;
}
/**
* {@inheritDoc}
*/
@Override
public void remove(Object key) throws CacheException {
region.remove( key );
}
}

View File

@ -0,0 +1,93 @@
/*
* 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.hibernate.cache.CacheException;
import org.hibernate.cache.ehcache.regions.EhcacheCollectionRegion;
import org.hibernate.cache.spi.CollectionRegion;
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
import org.hibernate.cache.spi.access.SoftLock;
import org.hibernate.cfg.Settings;
/**
* Ehcache specific read-only collection region access strategy
*
* @author Chris Dennis
* @author Alex Snaps
*/
public class ReadOnlyEhcacheCollectionRegionAccessStrategy
extends AbstractEhcacheAccessStrategy<EhcacheCollectionRegion>
implements CollectionRegionAccessStrategy {
/**
* Create a read-only access strategy accessing the given collection region.
*/
public ReadOnlyEhcacheCollectionRegionAccessStrategy(EhcacheCollectionRegion region, Settings settings) {
super( region, settings );
}
/**
* {@inheritDoc}
*/
public CollectionRegion getRegion() {
return region;
}
/**
* {@inheritDoc}
*/
public Object get(Object key, long txTimestamp) throws CacheException {
return region.get( key );
}
/**
* {@inheritDoc}
*/
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
throws CacheException {
if ( minimalPutOverride && region.contains( key ) ) {
return false;
}
else {
region.put( key, value );
return true;
}
}
/**
* Throws UnsupportedOperationException since this cache is read-only
*
* @throws UnsupportedOperationException always
*/
public SoftLock lockItem(Object key, Object version) throws UnsupportedOperationException {
throw new UnsupportedOperationException( "Can't write to a readonly object" );
}
/**
* A no-op since this cache is read-only
*/
public void unlockItem(Object key, SoftLock lock) throws CacheException {
//throw new UnsupportedOperationException("Can't write to a readonly object");
}
}

View File

@ -0,0 +1,131 @@
/*
* 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.hibernate.cache.CacheException;
import org.hibernate.cache.ehcache.regions.EhcacheEntityRegion;
import org.hibernate.cache.spi.EntityRegion;
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
import org.hibernate.cache.spi.access.SoftLock;
import org.hibernate.cfg.Settings;
/**
* @author Alex Snaps
*/
/**
* Ehcache specific read-only entity region access strategy
*
* @author Chris Dennis
* @author Alex Snaps
*/
public class ReadOnlyEhcacheEntityRegionAccessStrategy extends AbstractEhcacheAccessStrategy<EhcacheEntityRegion>
implements EntityRegionAccessStrategy {
/**
* Create a read-only access strategy accessing the given entity region.
*/
public ReadOnlyEhcacheEntityRegionAccessStrategy(EhcacheEntityRegion region, Settings settings) {
super( region, settings );
}
/**
* {@inheritDoc}
*/
public EntityRegion getRegion() {
return region;
}
/**
* {@inheritDoc}
*/
public Object get(Object key, long txTimestamp) throws CacheException {
return region.get( key );
}
/**
* {@inheritDoc}
*/
public boolean putFromLoad(Object key, Object value, long txTimestamp, Object version, boolean minimalPutOverride)
throws CacheException {
if ( minimalPutOverride && region.contains( key ) ) {
return false;
}
else {
region.put( key, value );
return true;
}
}
/**
* Throws UnsupportedOperationException since this cache is read-only
*
* @throws UnsupportedOperationException always
*/
public SoftLock lockItem(Object key, Object version) throws UnsupportedOperationException {
throw new UnsupportedOperationException( "Can't write to a readonly object" );
}
/**
* A no-op since this cache is read-only
*/
public void unlockItem(Object key, SoftLock lock) throws CacheException {
//throw new UnsupportedOperationException("Can't write to a readonly object");
}
/**
* This cache is asynchronous hence a no-op
*/
public boolean insert(Object key, Object value, Object version) throws CacheException {
return false;
}
/**
* {@inheritDoc}
*/
public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
region.put( key, value );
return true;
}
/**
* Throws UnsupportedOperationException since this cache is read-only
*
* @throws UnsupportedOperationException always
*/
public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
throws UnsupportedOperationException {
throw new UnsupportedOperationException( "Can't write to a readonly object" );
}
/**
* Throws UnsupportedOperationException since this cache is read-only
*
* @throws UnsupportedOperationException always
*/
public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
throws UnsupportedOperationException {
throw new UnsupportedOperationException( "Can't write to a readonly object" );
}
}

View File

@ -0,0 +1,54 @@
/*
* 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.hibernate.cache.ehcache.regions.EhcacheCollectionRegion;
import org.hibernate.cache.spi.CollectionRegion;
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
import org.hibernate.cfg.Settings;
/**
* Ehcache specific read/write collection region access strategy
*
* @author Chris Dennis
* @author Alex Snaps
*/
public class ReadWriteEhcacheCollectionRegionAccessStrategy
extends AbstractReadWriteEhcacheAccessStrategy<EhcacheCollectionRegion>
implements CollectionRegionAccessStrategy {
/**
* Create a read/write access strategy accessing the given collection region.
*/
public ReadWriteEhcacheCollectionRegionAccessStrategy(EhcacheCollectionRegion region, Settings settings) {
super( region, settings );
}
/**
* {@inheritDoc}
*/
public CollectionRegion getRegion() {
return region;
}
}

View File

@ -0,0 +1,128 @@
/*
* 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.hibernate.cache.CacheException;
import org.hibernate.cache.ehcache.regions.EhcacheEntityRegion;
import org.hibernate.cache.spi.EntityRegion;
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
import org.hibernate.cache.spi.access.SoftLock;
import org.hibernate.cfg.Settings;
/**
* Ehcache specific read/write entity region access strategy
*
* @author Chris Dennis
* @author Alex Snaps
*/
public class ReadWriteEhcacheEntityRegionAccessStrategy
extends AbstractReadWriteEhcacheAccessStrategy<EhcacheEntityRegion>
implements EntityRegionAccessStrategy {
/**
* Create a read/write access strategy accessing the given entity region.
*/
public ReadWriteEhcacheEntityRegionAccessStrategy(EhcacheEntityRegion region, Settings settings) {
super( region, settings );
}
/**
* {@inheritDoc}
*/
public EntityRegion getRegion() {
return region;
}
/**
* A no-op since this is an asynchronous cache access strategy.
*/
public boolean insert(Object key, Object value, Object version) throws CacheException {
return false;
}
/**
* {@inheritDoc}
* <p/>
* Inserts will only succeed if there is no existing value mapped to this key.
*/
public boolean afterInsert(Object key, Object value, Object version) throws CacheException {
region.writeLock( key );
try {
Lockable item = (Lockable) region.get( key );
if ( item == null ) {
region.put( key, new Item( value, version, region.nextTimestamp() ) );
return true;
}
else {
return false;
}
}
finally {
region.writeUnlock( key );
}
}
/**
* A no-op since this is an asynchronous cache access strategy.
*/
public boolean update(Object key, Object value, Object currentVersion, Object previousVersion)
throws CacheException {
return false;
}
/**
* {@inheritDoc}
* <p/>
* Updates will only succeed if this entry was locked by this transaction and exclusively this transaction for the
* duration of this transaction. It is important to also note that updates will fail if the soft-lock expired during
* the course of this transaction.
*/
public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock)
throws CacheException {
//what should we do with previousVersion here?
region.writeLock( key );
try {
Lockable item = (Lockable) region.get( key );
if ( item != null && item.isUnlockable( lock ) ) {
Lock lockItem = (Lock) item;
if ( lockItem.wasLockedConcurrently() ) {
decrementLock( key, lockItem );
return false;
}
else {
region.put( key, new Item( value, currentVersion, region.nextTimestamp() ) );
return true;
}
}
else {
handleLockExpiry( key, item );
return false;
}
}
finally {
region.writeUnlock( key );
}
}
}

View File

@ -0,0 +1,127 @@
/*
* 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 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.spi.CollectionRegion;
import org.hibernate.cache.spi.access.CollectionRegionAccessStrategy;
import org.hibernate.cache.spi.access.SoftLock;
import org.hibernate.cfg.Settings;
/**
* JTA CollectionRegionAccessStrategy.
*
* @author Chris Dennis
* @author Ludovic Orban
* @author Alex Snaps
*/
public class TransactionalEhcacheCollectionRegionAccessStrategy
extends AbstractEhcacheAccessStrategy<EhcacheCollectionRegion>
implements CollectionRegionAccessStrategy {
private final Ehcache ehcache;
/**
* Construct a new collection region access strategy.
*
* @param region the Hibernate region.
* @param ehcache the cache.
* @param settings the Hibernate settings.
*/
public TransactionalEhcacheCollectionRegionAccessStrategy(EhcacheCollectionRegion region, Ehcache ehcache, Settings settings) {
super( region, settings );
this.ehcache = ehcache;
}
/**
* {@inheritDoc}
*/
public Object get(Object key, long txTimestamp) throws CacheException {
try {
Element element = ehcache.get( key );
return element == null ? null : element.getObjectValue();
}
catch ( net.sf.ehcache.CacheException e ) {
throw new CacheException( e );
}
}
/**
* {@inheritDoc}
*/
public CollectionRegion getRegion() {
return region;
}
/**
* {@inheritDoc}
*/
public SoftLock lockItem(Object key, Object version) throws CacheException {
return null;
}
/**
* {@inheritDoc}
*/
public boolean putFromLoad(Object key, Object value, long txTimestamp,
Object version, boolean minimalPutOverride) throws CacheException {
try {
if ( minimalPutOverride && ehcache.get( key ) != null ) {
return false;
}
//OptimisticCache? versioning?
ehcache.put( new Element( key, value ) );
return true;
}
catch ( net.sf.ehcache.CacheException e ) {
throw new CacheException( e );
}
}
/**
* {@inheritDoc}
*/
@Override
public void remove(Object key) throws CacheException {
try {
ehcache.remove( key );
}
catch ( net.sf.ehcache.CacheException e ) {
throw new CacheException( e );
}
}
/**
* {@inheritDoc}
*/
public void unlockItem(Object key, SoftLock lock) throws CacheException {
// no-op
}
}

View File

@ -0,0 +1,167 @@
/*
* 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 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.spi.EntityRegion;
import org.hibernate.cache.spi.access.EntityRegionAccessStrategy;
import org.hibernate.cache.spi.access.SoftLock;
import org.hibernate.cfg.Settings;
/**
* JTA EntityRegionAccessStrategy.
*
* @author Chris Dennis
* @author Ludovic Orban
* @author Alex Snaps
*/
public class TransactionalEhcacheEntityRegionAccessStrategy extends AbstractEhcacheAccessStrategy<EhcacheEntityRegion>
implements EntityRegionAccessStrategy {
private final Ehcache ehcache;
/**
* Construct a new entity region access strategy.
*
* @param region the Hibernate region.
* @param ehcache the cache.
* @param settings the Hibernate settings.
*/
public TransactionalEhcacheEntityRegionAccessStrategy(EhcacheEntityRegion region, Ehcache ehcache, Settings settings) {
super( region, settings );
this.ehcache = ehcache;
}
/**
* {@inheritDoc}
*/
public boolean afterInsert(Object key, Object value, Object version) {
return false;
}
/**
* {@inheritDoc}
*/
public boolean afterUpdate(Object key, Object value, Object currentVersion, Object previousVersion, SoftLock lock) {
return false;
}
/**
* {@inheritDoc}
*/
public Object get(Object key, long txTimestamp) throws CacheException {
try {
Element element = ehcache.get( key );
return element == null ? null : element.getObjectValue();
}
catch ( net.sf.ehcache.CacheException e ) {
throw new CacheException( e );
}
}
/**
* {@inheritDoc}
*/
public EntityRegion getRegion() {
return region;
}
/**
* {@inheritDoc}
*/
public boolean insert(Object key, Object value, Object version)
throws CacheException {
//OptimisticCache? versioning?
try {
ehcache.put( new Element( key, value ) );
return true;
}
catch ( net.sf.ehcache.CacheException e ) {
throw new CacheException( e );
}
}
/**
* {@inheritDoc}
*/
public SoftLock lockItem(Object key, Object version) throws CacheException {
return null;
}
/**
* {@inheritDoc}
*/
public boolean putFromLoad(Object key, Object value, long txTimestamp,
Object version, boolean minimalPutOverride) throws CacheException {
try {
if ( minimalPutOverride && ehcache.get( key ) != null ) {
return false;
}
//OptimisticCache? versioning?
ehcache.put( new Element( key, value ) );
return true;
}
catch ( net.sf.ehcache.CacheException e ) {
throw new CacheException( e );
}
}
/**
* {@inheritDoc}
*/
@Override
public void remove(Object key) throws CacheException {
try {
ehcache.remove( key );
}
catch ( net.sf.ehcache.CacheException e ) {
throw new CacheException( e );
}
}
/**
* {@inheritDoc}
*/
public void unlockItem(Object key, SoftLock lock) throws CacheException {
// no-op
}
/**
* {@inheritDoc}
*/
public boolean update(Object key, Object value, Object currentVersion,
Object previousVersion) throws CacheException {
try {
ehcache.put( new Element( key, value ) );
return true;
}
catch ( net.sf.ehcache.CacheException e ) {
throw new CacheException( e );
}
}
}

View File

@ -1,117 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC 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 Middleware LLC.
*
* 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.internal;
import java.util.Properties;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.spi.CacheDataDescription;
import org.hibernate.cache.spi.CollectionRegion;
import org.hibernate.cache.spi.EntityRegion;
import org.hibernate.cache.spi.QueryResultsRegion;
import org.hibernate.cache.spi.RegionFactory;
import org.hibernate.cache.spi.TimestampsRegion;
import org.hibernate.cache.spi.access.AccessType;
import org.hibernate.cfg.Settings;
/**
* Abstract class that will delegate all calls to org.hibernate.cache.spi.RegionFactory to the instance it wraps.
* This abstracts the Singleton CacheManager construct of Ehcache
*
* @author Alex Snaps
*/
class AbstractEhCacheRegionFactory implements RegionFactory {
private final RegionFactory underlyingRegionFactory;
/**
* {@inheritDoc}
*/
protected AbstractEhCacheRegionFactory(RegionFactory regionFactory) {
underlyingRegionFactory = regionFactory;
}
/**
* {@inheritDoc}
*/
public final void start(final Settings settings, final Properties properties) throws CacheException {
underlyingRegionFactory.start(settings, properties);
}
/**
* {@inheritDoc}
*/
public final void stop() {
underlyingRegionFactory.stop();
}
/**
* {@inheritDoc}
*/
public final boolean isMinimalPutsEnabledByDefault() {
return underlyingRegionFactory.isMinimalPutsEnabledByDefault();
}
/**
* {@inheritDoc}
*/
public final AccessType getDefaultAccessType() {
return underlyingRegionFactory.getDefaultAccessType();
}
/**
* {@inheritDoc}
*/
public final long nextTimestamp() {
return underlyingRegionFactory.nextTimestamp();
}
/**
* {@inheritDoc}
*/
public final EntityRegion buildEntityRegion(final String regionName, final Properties properties, final CacheDataDescription metadata) throws CacheException {
return underlyingRegionFactory.buildEntityRegion(regionName, properties, metadata);
}
/**
* {@inheritDoc}
*/
public final CollectionRegion buildCollectionRegion(final String regionName, final Properties properties, final CacheDataDescription metadata) throws CacheException {
return underlyingRegionFactory.buildCollectionRegion(regionName, properties, metadata);
}
/**
* {@inheritDoc}
*/
public final QueryResultsRegion buildQueryResultsRegion(final String regionName, final Properties properties) throws CacheException {
return underlyingRegionFactory.buildQueryResultsRegion(regionName, properties);
}
/**
* {@inheritDoc}
*/
public final TimestampsRegion buildTimestampsRegion(final String regionName, final Properties properties) throws CacheException {
return underlyingRegionFactory.buildTimestampsRegion(regionName, properties);
}
}

View File

@ -0,0 +1,29 @@
package org.hibernate.cache.ehcache.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.cfg.Settings;
/**
* @author Alex Snaps
*/
public class ItemValueExtractor extends AbstractReadWriteEhcacheAccessStrategy {
/**
* Creates a read/write cache access strategy around the given cache region.
*/
public ItemValueExtractor(EhcacheTransactionalDataRegion region, Settings settings) {
super(region, settings);
}
public static <T> T getValue(final Object entry) {
if(!(entry instanceof Item)) {
throw new IllegalArgumentException("Entry needs to be of type " + Item.class.getName());
}
return (T)((Item)entry).getValue();
}
}

View File

@ -0,0 +1,36 @@
package org.hibernate.test.cache;
import net.sf.ehcache.CacheManager;
import org.hibernate.cache.ehcache.management.impl.EhcacheStatsImpl;
import org.hibernate.cache.ehcache.management.impl.EhcacheStatsImpl;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
/**
* @author Alex Snaps
*/
public class EhcacheStatsImplTest {
private static EhcacheStatsImpl stats;
@BeforeClass
public static void createCache() throws Exception {
CacheManager manager = CacheManager.getInstance();
stats = new EhcacheStatsImpl( manager );
}
@Test
public void testIsRegionCacheOrphanEvictionEnabled() {
assertThat( stats.isRegionCacheOrphanEvictionEnabled( "sampleCache1" ), is( false ) );
}
@Test
public void testGetRegionCacheOrphanEvictionPeriod() {
assertThat( stats.getRegionCacheOrphanEvictionPeriod( "sampleCache1" ), is( -1 ) );
}
}

View File

@ -0,0 +1,258 @@
package org.hibernate.test.cache;
import org.hamcrest.CoreMatchers;
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.spi.access.SoftLock;
import org.hibernate.cfg.Configuration;
import org.hibernate.stat.QueryStatistics;
import org.hibernate.stat.SecondLevelCacheStatistics;
import org.hibernate.stat.Statistics;
import org.hibernate.test.domain.Event;
import org.hibernate.test.domain.EventManager;
import org.hibernate.test.domain.Item;
import org.hibernate.test.domain.Person;
import org.hibernate.test.domain.PhoneNumber;
import org.hibernate.test.domain.VersionedItem;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.Date;
import java.util.List;
import java.util.Map;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
/**
* @author Chris Dennis
*/
public class HibernateCacheTest {
private static SessionFactory sessionFactory;
private static Configuration config;
private static final String REGION_PREFIX = "hibernate.test.";
public synchronized static SessionFactory getSessionFactory() {
if ( sessionFactory == null ) {
try {
sessionFactory = config.buildSessionFactory();
}
catch ( HibernateException ex ) {
System.err.println( "Initial SessionFactory creation failed." + ex );
throw new ExceptionInInitializerError( ex );
}
}
return sessionFactory;
}
@BeforeClass
public static void setUp() {
System.setProperty( "derby.system.home", "target/derby" );
config = new Configuration().configure( "/hibernate-config/hibernate.cfg.xml" );
config.setProperty( "hibernate.hbm2ddl.auto", "create" );
getSessionFactory().getStatistics().setStatisticsEnabled( true );
}
@AfterClass
public static void tearDown() {
getSessionFactory().close();
}
@Test
public void testQueryCacheInvalidation() throws Exception {
Session s = getSessionFactory().openSession();
Transaction t = s.beginTransaction();
Item i = new Item();
i.setName( "widget" );
i.setDescription( "A really top-quality, full-featured widget." );
s.persist( i );
t.commit();
s.close();
SecondLevelCacheStatistics slcs = s.getSessionFactory()
.getStatistics()
.getSecondLevelCacheStatistics( REGION_PREFIX + Item.class.getName() );
assertThat( slcs.getPutCount(), equalTo( 1L ) );
assertThat( slcs.getElementCountInMemory(), equalTo( 1L ) );
assertThat( slcs.getEntries().size(), equalTo( 1 ) );
s = getSessionFactory().openSession();
t = s.beginTransaction();
i = (Item) s.get( Item.class, i.getId() );
assertThat( slcs.getHitCount(), equalTo( 1L ) );
assertThat( slcs.getMissCount(), equalTo( 0L ) );
i.setDescription( "A bog standard item" );
t.commit();
s.close();
assertThat( slcs.getPutCount(), equalTo( 2L ) );
Object entry = slcs.getEntries().get( i.getId() );
Map map;
if ( entry instanceof Map ) {
map = (Map) entry;
}
else {
map = ItemValueExtractor.getValue( entry );
}
assertThat( (String) map.get( "description" ), equalTo( "A bog standard item" ) );
assertThat( (String) map.get( "name" ), equalTo( "widget" ) );
// cleanup
s = getSessionFactory().openSession();
t = s.beginTransaction();
s.delete( i );
t.commit();
s.close();
}
@Test
public void testEmptySecondLevelCacheEntry() throws Exception {
getSessionFactory().evictEntity( Item.class.getName() );
Statistics stats = getSessionFactory().getStatistics();
stats.clear();
SecondLevelCacheStatistics statistics = stats.getSecondLevelCacheStatistics( REGION_PREFIX + Item.class.getName() );
Map cacheEntries = statistics.getEntries();
assertThat( cacheEntries.size(), equalTo( 0 ) );
}
@Test
public void testStaleWritesLeaveCacheConsistent() {
Session s = getSessionFactory().openSession();
Transaction txn = s.beginTransaction();
VersionedItem item = new VersionedItem();
item.setName( "steve" );
item.setDescription( "steve's item" );
s.save( item );
txn.commit();
s.close();
Long initialVersion = item.getVersion();
// manually revert the version property
item.setVersion( item.getVersion() - 1 );
try {
s = getSessionFactory().openSession();
txn = s.beginTransaction();
s.update( item );
txn.commit();
s.close();
fail( "expected stale write to fail" );
}
catch ( Throwable expected ) {
// expected behavior here
if ( txn != null ) {
try {
txn.rollback();
}
catch ( Throwable ignore ) {
}
}
}
finally {
if ( s != null && s.isOpen() ) {
try {
s.close();
}
catch ( Throwable ignore ) {
}
}
}
// check the version value in the cache...
SecondLevelCacheStatistics slcs = getSessionFactory().getStatistics()
.getSecondLevelCacheStatistics( REGION_PREFIX + VersionedItem.class.getName() );
assertThat( slcs, CoreMatchers.<Object>notNullValue() );
final Map entries = slcs.getEntries();
Object entry = entries.get( item.getId() );
Long cachedVersionValue;
if ( entry instanceof SoftLock ) {
//FIXME don't know what to test here
//cachedVersionValue = new Long( ( (ReadWriteCache.Lock) entry).getUnlockTimestamp() );
}
else {
cachedVersionValue = (Long) ( (Map) entry ).get( "_version" );
assertThat( initialVersion, equalTo( cachedVersionValue ) );
}
// cleanup
s = getSessionFactory().openSession();
txn = s.beginTransaction();
item = (VersionedItem) s.load( VersionedItem.class, item.getId() );
s.delete( item );
txn.commit();
s.close();
}
@Test
public void testGeneralUsage() {
EventManager mgr = new EventManager( getSessionFactory() );
Statistics stats = getSessionFactory().getStatistics();
// create 3 persons Steve, Orion, Tim
Person stevePerson = new Person();
stevePerson.setFirstname( "Steve" );
stevePerson.setLastname( "Harris" );
Long steveId = mgr.createAndStorePerson( stevePerson );
mgr.addEmailToPerson( steveId, "steve@tc.com" );
mgr.addEmailToPerson( steveId, "sharrif@tc.com" );
mgr.addTalismanToPerson( steveId, "rabbit foot" );
mgr.addTalismanToPerson( steveId, "john de conqueroo" );
PhoneNumber p1 = new PhoneNumber();
p1.setNumberType( "Office" );
p1.setPhone( 111111 );
mgr.addPhoneNumberToPerson( steveId, p1 );
PhoneNumber p2 = new PhoneNumber();
p2.setNumberType( "Home" );
p2.setPhone( 222222 );
mgr.addPhoneNumberToPerson( steveId, p2 );
Person orionPerson = new Person();
orionPerson.setFirstname( "Orion" );
orionPerson.setLastname( "Letizi" );
Long orionId = mgr.createAndStorePerson( orionPerson );
mgr.addEmailToPerson( orionId, "orion@tc.com" );
mgr.addTalismanToPerson( orionId, "voodoo doll" );
Long timId = mgr.createAndStorePerson( "Tim", "Teck" );
mgr.addEmailToPerson( timId, "teck@tc.com" );
mgr.addTalismanToPerson( timId, "magic decoder ring" );
Long engMeetingId = mgr.createAndStoreEvent( "Eng Meeting", stevePerson, new Date() );
mgr.addPersonToEvent( steveId, engMeetingId );
mgr.addPersonToEvent( orionId, engMeetingId );
mgr.addPersonToEvent( timId, engMeetingId );
Long docMeetingId = mgr.createAndStoreEvent( "Doc Meeting", orionPerson, new Date() );
mgr.addPersonToEvent( steveId, docMeetingId );
mgr.addPersonToEvent( orionId, docMeetingId );
for ( Event event : (List<Event>) mgr.listEvents() ) {
mgr.listEmailsOfEvent( event.getId() );
}
getSessionFactory().close();
QueryStatistics queryStats = stats.getQueryStatistics( "from Event" );
assertThat( "Cache Miss Count", queryStats.getCacheMissCount(), equalTo( 1L ) );
assertThat( "Cache Hit Count", queryStats.getCacheHitCount(), equalTo( 0L ) );
assertThat( "Cache Put Count", queryStats.getCachePutCount(), equalTo( 1L ) );
}
}

View File

@ -1,6 +1,6 @@
package org.hibernate.test.cache.ehcache;
import org.hibernate.cache.internal.EhCacheRegionFactory;
import org.hibernate.cache.ehcache.EhCacheRegionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
@ -14,25 +14,31 @@ public class EhCacheRegionFactoryImpl extends EhCacheTest {
@Override
protected void configCache(final Configuration cfg) {
cfg.setProperty(Environment.CACHE_REGION_FACTORY, EhCacheRegionFactory.class.getName());
cfg.setProperty( Environment.CACHE_REGION_FACTORY, EhCacheRegionFactory.class.getName() );
cfg.setProperty( Environment.CACHE_PROVIDER_CONFIG, "ehcache.xml" );
}
@Override
protected Map getMapFromCacheEntry(final Object entry) {
final Map map;
if ("net.sf.ehcache.hibernate.strategy.AbstractReadWriteEhcacheAccessStrategy$Item".equals(entry.getClass().getName())) {
if ( "org.hibernate.cache.ehcache.strategy.AbstractReadWriteEhcacheAccessStrategy$Item".equals(
entry.getClass()
.getName()
) ) {
try {
Field field = entry.getClass().getDeclaredField("value");
field.setAccessible(true);
map = (Map)field.get(entry);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
Field field = entry.getClass().getDeclaredField( "value" );
field.setAccessible( true );
map = (Map) field.get( entry );
}
} else {
map = (Map)entry;
catch ( NoSuchFieldException e ) {
throw new RuntimeException( e );
}
catch ( IllegalAccessException e ) {
throw new RuntimeException( e );
}
}
else {
map = (Map) entry;
}
return map;
}

View File

@ -1,12 +1,12 @@
package org.hibernate.test.cache.ehcache;
import org.hibernate.cache.ehcache.EhCacheRegionFactory;
import org.hibernate.cache.ehcache.strategy.ItemValueExtractor;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import java.util.Map;
import net.sf.ehcache.hibernate.EhCacheRegionFactory;
/**
* @author Alex Snaps
*/
@ -20,12 +20,14 @@ public class EhCacheRegionTest extends EhCacheTest {
@Override
protected Map getMapFromCacheEntry(final Object entry) {
final Map map;
// if ( entry instanceof Item ) {
// map = (Map) ( (Item) entry ).getValue();
// }
// else {
if ( entry.getClass()
.getName()
.equals( "org.hibernate.cache.ehcache.strategy.AbstractReadWriteEhcacheAccessStrategy$Item" ) ) {
map = ItemValueExtractor.getValue( entry );
}
else {
map = (Map) entry;
// }
}
return map;
}
}

View File

@ -24,6 +24,7 @@
package org.hibernate.test.cache.ehcache;
import java.util.Map;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
@ -67,7 +68,7 @@ public abstract class EhCacheTest extends BaseCoreFunctionalTestCase {
cfg.setProperty( Environment.USE_SECOND_LEVEL_CACHE, "true" );
cfg.setProperty( Environment.GENERATE_STATISTICS, "true" );
cfg.setProperty( Environment.USE_STRUCTURED_CACHE, "true" );
configCache(cfg);
configCache( cfg );
cfg.setProperty( Environment.TRANSACTION_STRATEGY, JdbcTransactionFactory.class.getName() );
}
@ -78,9 +79,9 @@ public abstract class EhCacheTest extends BaseCoreFunctionalTestCase {
Session s = openSession();
Transaction t = s.beginTransaction();
Item i = new Item();
i.setName("widget");
i.setDescription("A really top-quality, full-featured widget.");
s.persist(i);
i.setName( "widget" );
i.setDescription( "A really top-quality, full-featured widget." );
s.persist( i );
t.commit();
s.close();
@ -98,7 +99,7 @@ public abstract class EhCacheTest extends BaseCoreFunctionalTestCase {
assertEquals( slcs.getHitCount(), 1 );
assertEquals( slcs.getMissCount(), 0 );
i.setDescription("A bog standard item");
i.setDescription( "A bog standard item" );
t.commit();
s.close();
@ -107,9 +108,9 @@ public abstract class EhCacheTest extends BaseCoreFunctionalTestCase {
Object entry = slcs.getEntries().get( i.getId() );
Map map;
map = getMapFromCacheEntry(entry);
assertTrue( map.get("description").equals("A bog standard item") );
assertTrue( map.get("name").equals("widget") );
map = getMapFromCacheEntry( entry );
assertTrue( map.get( "description" ).equals( "A bog standard item" ) );
assertTrue( map.get( "name" ).equals( "widget" ) );
// cleanup
s = openSession();
@ -131,7 +132,7 @@ public abstract class EhCacheTest extends BaseCoreFunctionalTestCase {
assertEquals( 0, cacheEntries.size() );
}
@SuppressWarnings( {"UnnecessaryBoxing", "UnnecessaryUnboxing", "UnusedAssignment"})
@SuppressWarnings( { "UnnecessaryBoxing", "UnnecessaryUnboxing", "UnusedAssignment" })
@Test
public void testStaleWritesLeaveCacheConsistent() {
Session s = openSession();
@ -156,13 +157,13 @@ public abstract class EhCacheTest extends BaseCoreFunctionalTestCase {
s.close();
fail( "expected stale write to fail" );
}
catch( Throwable expected ) {
catch ( Throwable expected ) {
// expected behavior here
if ( txn != null ) {
try {
txn.rollback();
}
catch( Throwable ignore ) {
catch ( Throwable ignore ) {
}
}
}
@ -171,7 +172,7 @@ public abstract class EhCacheTest extends BaseCoreFunctionalTestCase {
try {
s.close();
}
catch( Throwable ignore ) {
catch ( Throwable ignore ) {
}
}
}
@ -186,10 +187,13 @@ public abstract class EhCacheTest extends BaseCoreFunctionalTestCase {
// //FIXME don't know what to test here
// cachedVersionValue = Long.valueOf( ((ReadWriteCache.Lock) entry).getUnlockTimestamp() );
// } else
if(entry.getClass().getName().equals("net.sf.ehcache.hibernate.strategy.AbstractReadWriteEhcacheAccessStrategy$Lock")) {
if ( entry.getClass()
.getName()
.equals( "org.hibernate.cache.ehcache.strategy.AbstractReadWriteEhcacheAccessStrategy$Lock" ) ) {
//FIXME don't know what to test here
} else {
cachedVersionValue = ( Long ) getMapFromCacheEntry(entry).get( "_version" );
}
else {
cachedVersionValue = (Long) getMapFromCacheEntry( entry ).get( "_version" );
assertEquals( initialVersion.longValue(), cachedVersionValue.longValue() );
}
@ -197,7 +201,7 @@ public abstract class EhCacheTest extends BaseCoreFunctionalTestCase {
// cleanup
s = openSession();
txn = s.beginTransaction();
item = ( VersionedItem ) s.load( VersionedItem.class, item.getId() );
item = (VersionedItem) s.load( VersionedItem.class, item.getId() );
s.delete( item );
txn.commit();
s.close();

View File

@ -0,0 +1,47 @@
/**
* Copyright 2003-2010 Terracotta, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.test.domain;
public class Account {
private Long id;
private Person person;
public Account() {
//
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String toString() {
return super.toString();
}
}

View File

@ -0,0 +1,83 @@
/**
* Copyright 2003-2010 Terracotta, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.test.domain;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
public class Event {
private Long id;
private String title;
private Date date;
private Set participants = new HashSet();
private Person organizer;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public void setOrganizer(Person organizer) {
this.organizer = organizer;
}
public Person getOrganizer() {
return organizer;
}
public Set getParticipants() {
return participants;
}
public void setParticipants(Set participants) {
this.participants = participants;
}
public void addParticipant(Person person) {
participants.add(person);
person.getEvents().add(this);
}
public void removeParticipant(Person person) {
participants.remove(person);
person.getEvents().remove(this);
}
public String toString() {
return getTitle() + ": " + getDate();
}
}

View File

@ -0,0 +1,249 @@
/**
* Copyright 2003-2010 Terracotta, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.test.domain;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
public class EventManager {
private final SessionFactory sessionFactory;
public EventManager(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public List listEmailsOfEvent(Long eventId) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
List emailList = new ArrayList();
Event event = (Event)session.load(Event.class, eventId);
for (Iterator it = event.getParticipants().iterator(); it.hasNext(); ) {
Person person = (Person)it.next();
emailList.addAll(person.getEmailAddresses());
}
session.getTransaction().commit();
return emailList;
}
public Long createAndStoreEvent(String title, Person organizer, Date theDate) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Event theEvent = new Event();
theEvent.setTitle(title);
theEvent.setDate(theDate);
theEvent.setOrganizer(organizer);
Long eventId = (Long)session.save(theEvent);
session.getTransaction().commit();
return eventId;
}
public Long createAndStorePerson(String firstName, String lastName) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Person person = new Person();
person.setFirstname(firstName);
person.setLastname(lastName);
Long personId = (Long)session.save(person);
session.getTransaction().commit();
return personId;
}
public Long createAndStorePerson(Person person) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Long personId = (Long)session.save(person);
session.getTransaction().commit();
return personId;
}
public List listEvents() {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
List result = session.createQuery("from Event").setCacheable(true).list();
session.getTransaction().commit();
return result;
}
/**
* Call setEntity() on a cacheable query - see FORGE-265
*/
public List listEventsOfOrganizer(Person organizer) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Query query = session.createQuery("from Event ev where ev.organizer = :organizer");
query.setCacheable(true);
query.setEntity("organizer", organizer);
List result = query.list();
session.getTransaction().commit();
return result;
}
/**
* Use a Criteria query - see FORGE-247
*/
public List listEventsWithCriteria() {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
List result = session.createCriteria(Event.class)
.setCacheable(true)
.list();
session.getTransaction().commit();
return result;
}
public void addPersonToEvent(Long personId, Long eventId) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Person aPerson = (Person)session.load(Person.class, personId);
Event anEvent = (Event)session.load(Event.class, eventId);
aPerson.getEvents().add(anEvent);
session.getTransaction().commit();
}
public Long addPersonToAccount(Long personId, Account account) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Person aPerson = (Person)session.load(Person.class, personId);
account.setPerson(aPerson);
Long accountId = (Long)session.save(account);
session.getTransaction().commit();
return accountId;
}
public Account getAccount(Long accountId) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Account account = (Account)session.load(Account.class, accountId);
session.getTransaction().commit();
return account;
}
public void addEmailToPerson(Long personId, String emailAddress) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Person aPerson = (Person)session.load(Person.class, personId);
// The getEmailAddresses() might trigger a lazy load of the collection
aPerson.getEmailAddresses().add(emailAddress);
session.getTransaction().commit();
}
public void addPhoneNumberToPerson(Long personId, PhoneNumber pN) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Person aPerson = (Person)session.load(Person.class, personId);
pN.setPersonId(personId.longValue());
aPerson.getPhoneNumbers().add(pN);
session.getTransaction().commit();
}
public void addTalismanToPerson(Long personId, String talisman) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Person aPerson = (Person)session.load(Person.class, personId);
aPerson.addTalisman(talisman);
session.getTransaction().commit();
}
public Long createHolidayCalendar() {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
// delete all existing calendars
List calendars = session.createQuery("from HolidayCalendar").setCacheable(true).list();
for (ListIterator li = calendars.listIterator(); li.hasNext(); ) {
session.delete(li.next());
}
HolidayCalendar calendar = new HolidayCalendar();
calendar.init();
Long calendarId = (Long)session.save(calendar);
session.getTransaction().commit();
return calendarId;
}
public HolidayCalendar getHolidayCalendar() {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
List calendars = session.createQuery("from HolidayCalendar").setCacheable(true).list();
session.getTransaction().commit();
return calendars.isEmpty() ? null : (HolidayCalendar)calendars.get(0);
}
}

View File

@ -0,0 +1,78 @@
/**
* Copyright 2003-2010 Terracotta, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.test.domain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class HolidayCalendar {
private static final Logger LOG = LoggerFactory.getLogger(HolidayCalendar.class);
private Long id;
// Date -> String
private Map holidays = new HashMap();
public HolidayCalendar init() {
DateFormat df = new SimpleDateFormat("yyyy.MM.dd");
try {
holidays.clear();
holidays.put(df.parse("2009.01.01"), "New Year's Day");
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;
}
public Map getHolidays() {
return holidays;
}
protected void setHolidays(Map holidays) {
this.holidays = holidays;
}
public void addHoliday(Date d, String name) {
holidays.put(d, name);
}
public String getHoliday(Date d) {
return (String)holidays.get(d);
}
public boolean isHoliday(Date d) {
return holidays.containsKey(d);
}
protected Long getId() {
return id;
}
protected void setId(Long id) {
this.id = id;
}
}

View File

@ -0,0 +1,46 @@
/**
* Copyright 2003-2010 Terracotta, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.test.domain;
public class Item {
private Long id;
private String name;
private String description;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,120 @@
/**
* Copyright 2003-2010 Terracotta, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.test.domain;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Person {
private Long id;
private int age;
private String firstname;
private String lastname;
private List events = new ArrayList(); // list semantics, e.g., indexed
private Set emailAddresses = new HashSet();
private Set phoneNumbers = new HashSet();
private List talismans = new ArrayList(); // a Bag of good-luck charms.
public Person() {
//
}
public List getEvents() {
return events;
}
protected void setEvents(List events) {
this.events = events;
}
public void addToEvent(Event event) {
this.getEvents().add(event);
event.getParticipants().add(this);
}
public void removeFromEvent(Event event) {
this.getEvents().remove(event);
event.getParticipants().remove(this);
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public Set getEmailAddresses() {
return emailAddresses;
}
public void setEmailAddresses(Set emailAddresses) {
this.emailAddresses = emailAddresses;
}
public Set getPhoneNumbers() {
return phoneNumbers;
}
public void setPhoneNumbers(Set phoneNumbers) {
this.phoneNumbers = phoneNumbers;
}
public void addTalisman(String name) {
talismans.add(name);
}
public List getTalismans() {
return talismans;
}
public void setTalismans(List talismans) {
this.talismans = talismans;
}
public String toString() {
return getFirstname() + " " + getLastname();
}
}

View File

@ -0,0 +1,87 @@
/**
* Copyright 2003-2010 Terracotta, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.test.domain;
import java.io.Serializable;
/**
* PhoneNumber
*/
public class PhoneNumber implements Serializable {
private long personId = 0;
private String numberType = "home";
private long phone = 0;
public long getPersonId() {
return personId;
}
public void setPersonId(long personId) {
this.personId = personId;
}
public String getNumberType() {
return numberType;
}
public void setNumberType(String numberType) {
this.numberType = numberType;
}
public long getPhone() {
return phone;
}
public void setPhone(long phone) {
this.phone = phone;
}
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((numberType == null) ? 0 : numberType.hashCode());
result = prime * result + (int)(personId ^ (personId >>> 32));
result = prime * result + (int)(phone ^ (phone >>> 32));
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final PhoneNumber other = (PhoneNumber)obj;
if (numberType == null) {
if (other.numberType != null)
return false;
} else if (!numberType.equals(other.numberType))
return false;
if (personId != other.personId)
return false;
if (phone != other.phone)
return false;
return true;
}
public String toString() {
return numberType + ":" + phone;
}
}

View File

@ -0,0 +1,46 @@
/**
* Copyright 2003-2010 Terracotta, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.test.domain;
public class UuidItem {
private String id;
private String name;
private String description;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,28 @@
/**
* Copyright 2003-2010 Terracotta, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.test.domain;
public class VersionedItem extends Item {
private Long version;
public Long getVersion() {
return version;
}
public void setVersion(Long version) {
this.version = version;
}
}

View File

@ -0,0 +1,19 @@
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.hibernate.test.domain.Account" table="ACCOUNT" lazy="false">
<id name="id" column="ACCOUNT_ID">
<generator class="native"/>
</id>
<many-to-one name="person" class="org.hibernate.test.domain.Person" cascade="save-update,lock"
column="person_id"
unique="true"
not-null="true"/>
</class>
</hibernate-mapping>

View File

@ -0,0 +1,26 @@
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.hibernate.test.domain.Event" table="EVENTS">
<cache usage="read-write"/>
<id name="id" column="EVENT_ID">
<generator class="native"/>
</id>
<property name="date" type="timestamp" column="EVENT_DATE"/>
<property name="title"/>
<many-to-one name="organizer" column="EVENT_ORGANIZER" class="org.hibernate.test.domain.Person"/>
<set name="participants" table="PERSON_EVENT" lazy="false"
inverse="true" cascade="lock">
<cache usage="read-write"/>
<key column="EVENT_ID"/>
<many-to-many column="PERSON_ID"
class="org.hibernate.test.domain.Person"/>
</set>
</class>
</hibernate-mapping>

View File

@ -0,0 +1,21 @@
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.hibernate.test.domain.HolidayCalendar" table="CALENDAR" lazy="false">
<id name="id" column="CALENDAR_ID">
<generator class="native"/>
</id>
<map name="holidays" table="CALENDAR_HOLIDAYS" lazy="false">
<key column="CALENDAR_ID"/>
<map-key column="hol_date" type="date"/>
<element column="hol_name" type="string"/>
</map>
</class>
</hibernate-mapping>

View File

@ -0,0 +1,28 @@
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.test.domain">
<class name="Item" table="Items">
<cache usage="read-write"/>
<id name="id">
<generator class="increment"/>
</id>
<property name="name" not-null="true"/>
<property name="description" not-null="true"/>
</class>
<class name="VersionedItem" table="VersionedItems">
<cache usage="read-write"/>
<id name="id">
<generator class="increment"/>
</id>
<version name="version" type="long"/>
<property name="name" not-null="true"/>
<property name="description" not-null="true"/>
</class>
</hibernate-mapping>

View File

@ -0,0 +1,40 @@
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.hibernate.test.domain.Person" table="PERSON" lazy="true">
<id name="id" column="PERSON_ID">
<generator class="native"/>
</id>
<property name="age"/>
<property name="firstname"/>
<property name="lastname"/>
<list name="events" table="PERSON_EVENT" lazy="true">
<key column="PERSON_ID"/>
<list-index column="EVENT_ORDER"/>
<many-to-many column="EVENT_ID" class="org.hibernate.test.domain.Event"/>
</list>
<bag name="talismans" table="PERSON_TALISMAN" lazy="true">
<key column="PERSON_ID"/>
<element type="string" column="TALISMAN_NAME"/>
</bag>
<set name="emailAddresses" table="PERSON_EMAIL_ADDR" lazy="true">
<key column="PERSON_ID"/>
<element type="string" column="EMAIL_ADDR"/>
</set>
<set name="phoneNumbers" cascade="all" lazy="true">
<key column="PERSON_ID"/>
<one-to-many class="org.hibernate.test.domain.PhoneNumber"/>
</set>
</class>
</hibernate-mapping>

View File

@ -0,0 +1,20 @@
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.hibernate.test.domain.PhoneNumber" table="PHONE_NUMBERS">
<composite-id>
<key-property column="PERSON_ID" name="personId" type="java.lang.Long"/>
<key-property column="NUMBER_TYPE" name="numberType" type="java.lang.String"/>
</composite-id>
<property name="phone" type="java.lang.Long">
<column name="PHONE" precision="22" scale="0"/>
</property>
</class>
</hibernate-mapping>

View File

@ -0,0 +1,9 @@
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../main/config/ehcache.xsd" name="tc"
updateCheck="false">
<defaultCache
maxElementsInMemory="1000"
eternal="true"
overflowToDisk="false">
</defaultCache>
</ehcache>

View File

@ -0,0 +1,48 @@
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<!-- <property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="connection.url">jdbc:hsqldb:hsql://localhost/TestDB</property> -->
<property name="connection.driver_class">org.h2.Driver</property>
<property name="connection.url">jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE</property>
<property name="connection.username">sa</property>
<property name="connection.password"></property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">
org.hibernate.dialect.H2Dialect
</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<property name="cache.use_query_cache">true</property>
<property name="cache.use_second_level_cache">true</property>
<property name="cache.use_structured_entries">true</property>
<property name="cache.region.factory_class">org.hibernate.cache.EhCacheRegionFactory</property>
<property name="net.sf.ehcache.configurationResourceName">/hibernate-config/ehcache.xml</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<mapping resource="hibernate-config/domain/Event.hbm.xml"/>
<mapping resource="hibernate-config/domain/Person.hbm.xml"/>
<mapping resource="hibernate-config/domain/PhoneNumber.hbm.xml"/>
<mapping resource="hibernate-config/domain/Account.hbm.xml"/>
<mapping resource="hibernate-config/domain/HolidayCalendar.hbm.xml"/>
<mapping resource="hibernate-config/domain/Item.hbm.xml"/>
</session-factory>
</hibernate-configuration>