ZEST-178 Rework EhCache Cache for EhCache 3 Breaks API compatibility Breaks Configuration compatibility
Project: http://git-wip-us.apache.org/repos/asf/zest-java/repo Commit: http://git-wip-us.apache.org/repos/asf/zest-java/commit/c0752e4f Tree: http://git-wip-us.apache.org/repos/asf/zest-java/tree/c0752e4f Diff: http://git-wip-us.apache.org/repos/asf/zest-java/diff/c0752e4f Branch: refs/heads/develop Commit: c0752e4f0112856f5880c5c4c78b9920ffd542b2 Parents: 1449822 Author: Paul Merlin <paulmer...@apache.org> Authored: Sun Sep 18 16:07:55 2016 -0700 Committer: Paul Merlin <paulmer...@apache.org> Committed: Sun Sep 18 16:07:55 2016 -0700 ---------------------------------------------------------------------- extensions/cache-ehcache/build.gradle | 1 + .../cache/ehcache/EhCacheConfiguration.java | 150 ++++++----- .../apache/zest/cache/ehcache/EhCacheImpl.java | 16 +- .../zest/cache/ehcache/EhCachePoolMixin.java | 247 +++++++------------ libraries.gradle | 4 +- 5 files changed, 196 insertions(+), 222 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/zest-java/blob/c0752e4f/extensions/cache-ehcache/build.gradle ---------------------------------------------------------------------- diff --git a/extensions/cache-ehcache/build.gradle b/extensions/cache-ehcache/build.gradle index 29b2618..b56383a 100644 --- a/extensions/cache-ehcache/build.gradle +++ b/extensions/cache-ehcache/build.gradle @@ -26,6 +26,7 @@ dependencies { compile(project(':org.apache.zest.core:org.apache.zest.core.spi')) compile(project(':org.apache.zest.core:org.apache.zest.core.bootstrap')) + compile( project( ":org.apache.zest.libraries:org.apache.zest.library.constraints" ) ) compile(libraries.ehcache) testCompile( project(':org.apache.zest.core:org.apache.zest.core.testsupport') ) http://git-wip-us.apache.org/repos/asf/zest-java/blob/c0752e4f/extensions/cache-ehcache/src/main/java/org/apache/zest/cache/ehcache/EhCacheConfiguration.java ---------------------------------------------------------------------- diff --git a/extensions/cache-ehcache/src/main/java/org/apache/zest/cache/ehcache/EhCacheConfiguration.java b/extensions/cache-ehcache/src/main/java/org/apache/zest/cache/ehcache/EhCacheConfiguration.java index 3974605..19478b0 100644 --- a/extensions/cache-ehcache/src/main/java/org/apache/zest/cache/ehcache/EhCacheConfiguration.java +++ b/extensions/cache-ehcache/src/main/java/org/apache/zest/cache/ehcache/EhCacheConfiguration.java @@ -19,87 +19,125 @@ */ package org.apache.zest.cache.ehcache; -import net.sf.ehcache.config.PersistenceConfiguration.Strategy; import org.apache.zest.api.common.Optional; import org.apache.zest.api.common.UseDefaults; import org.apache.zest.api.configuration.ConfigurationComposite; import org.apache.zest.api.property.Property; +import org.apache.zest.library.constraints.annotation.OneOf; // START SNIPPET: config -public interface EhCacheConfiguration - extends ConfigurationComposite -{ +public interface EhCacheConfiguration extends ConfigurationComposite { - @Optional @UseDefaults - Property<Boolean> clearOnFlush(); - - @Optional @UseDefaults - Property<Integer> diskAccessStripes(); + /** + * Heap tier size. + * + * Default to 1MB, you may want to change this. + * + * @return Heap tier size + */ + @UseDefaults( "1" ) + Property<Long> heapSize(); - @Optional @UseDefaults - Property<Long> diskExpiryThreadIntervalSeconds(); + /** + * Heap tier size unit. + * + * @return Heap tier size unit + */ + @OneOf( { "B", "KB", "MB", "GB", "TB", "PB" } ) + @UseDefaults( "MB" ) + Property<String> heapUnit(); /** - * Cache Persistence Strategy. + * Optional off-heap tier size. * - * Can be: - * <ul> - * <li>LOCALTEMPSWAP: Standard open source (non fault-tolerant) on-disk persistence.</li> - * <li>LOCALRESTARTABLE: Enterprise fault tolerant persistence.</li> - * <li>NONE: No persistence.</li> - * <li>DISTRIBUTED: Terracotta clustered persistence (requires a Terracotta clustered cache).</li> - * </ul> - * Defaults to NONE. + * @return Optional off-heap tier size */ @Optional - Property<Strategy> persistenceStrategy(); - - @Optional @UseDefaults - Property<String> diskStorePath(); - - @Optional @UseDefaults - Property<Integer> diskSpoolBufferSizeMB(); - - @Optional @UseDefaults - Property<Boolean> eternal(); - - @Optional @UseDefaults - Property<Boolean> loggingEnabled(); + Property<Long> offHeapSize(); /** - * Number of objects the ehCache should keep in memory. - * Defaults to 1000 + * Off-heap tier size unit. * - * @return The maximum number of elements to be kept in memory. + * @return Off-heap tier size unit */ - @Optional @UseDefaults - Property<Integer> maxElementsInMemory(); + @OneOf( { "B", "KB", "MB", "GB", "TB", "PB" } ) + @UseDefaults( "MB" ) + Property<String> offHeapUnit(); - @Optional @UseDefaults - Property<Integer> maxElementsOnDisk(); + /** + * Optional disk tier size. + * + * @return Optional disk tier size + */ + @Optional + Property<Long> diskSize(); - @Optional @UseDefaults - Property<String> memoryStoreEvictionPolicy(); + /** + * Disk tier size unit. + * + * @return Disk tier size unit + */ + @OneOf( { "B", "KB", "MB", "GB", "TB", "PB" } ) + @UseDefaults( "MB" ) + Property<String> diskUnit(); - @Optional @UseDefaults - Property<String> name(); + /** + * If the disk tier is persistent or not. + * + * @return If the disk tier is persistent or not + */ + @UseDefaults + Property<Boolean> diskPersistent(); - @Optional @UseDefaults - Property<String> transactionalMode(); + /** + * Maximum size of cached objects. + * + * @return Maximum size of cached objects + */ + @Optional + Property<Long> maxObjectSize(); - @Optional @UseDefaults - Property<Long> timeToLiveSeconds(); + /** + * Unit for maximum size of cached objects. + * + * @return Unit for maximum size of cached objects + */ + @OneOf( { "B", "KB", "MB", "GB", "TB", "PB" } ) + @UseDefaults( "MB" ) + Property<String> maxObjectSizeUnit(); - @Optional @UseDefaults - Property<Long> timeToIdleSeconds(); + /** + * Maximum cached object graph depth. + * + * @return Maximum cached object graph depth + */ + @Optional + Property<Long> maxObjectGraphDepth(); - @Optional @UseDefaults - Property<String> cacheManagerName(); + /** + * Expiry policy. + * + * @return Expiry policy + */ + @OneOf( { "NONE", "TIME_TO_IDLE", "TIME_TO_LIVE" } ) + @UseDefaults( "NONE" ) + Property<String> expiry(); - @Optional @UseDefaults - Property<String> monitoring(); + /** + * Expiry length. + * + * @return Expiry length + */ + @Optional + Property<Long> expiryLength(); - @Optional @UseDefaults - Property<Boolean> updateCheck(); + /** + * Expiry time unit. + * + * @return Expiry time unit + */ + @OneOf( { "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", "DAYS" } ) + @UseDefaults( "SECONDS" ) + Property<String> expiryTimeUnit(); } // END SNIPPET: config http://git-wip-us.apache.org/repos/asf/zest-java/blob/c0752e4f/extensions/cache-ehcache/src/main/java/org/apache/zest/cache/ehcache/EhCacheImpl.java ---------------------------------------------------------------------- diff --git a/extensions/cache-ehcache/src/main/java/org/apache/zest/cache/ehcache/EhCacheImpl.java b/extensions/cache-ehcache/src/main/java/org/apache/zest/cache/ehcache/EhCacheImpl.java index 6d0a214..594b7fd 100644 --- a/extensions/cache-ehcache/src/main/java/org/apache/zest/cache/ehcache/EhCacheImpl.java +++ b/extensions/cache-ehcache/src/main/java/org/apache/zest/cache/ehcache/EhCacheImpl.java @@ -19,18 +19,17 @@ */ package org.apache.zest.cache.ehcache; -import net.sf.ehcache.Element; import org.apache.zest.spi.cache.Cache; public class EhCacheImpl<T> implements Cache<T> { private int refCount; - private final net.sf.ehcache.Cache backingCache; + private final org.ehcache.Cache backingCache; private final Class<T> valueType; private final String id; - public EhCacheImpl( String cacheId, net.sf.ehcache.Cache cache, Class<T> valueType ) + public EhCacheImpl( String cacheId, org.ehcache.Cache cache, Class<T> valueType ) { this.id = cacheId; this.backingCache = cache; @@ -40,18 +39,18 @@ public class EhCacheImpl<T> @Override public T get( String key ) { - Element element = backingCache.get( key ); + Object element = backingCache.get( key ); if( element == null ) { return null; } - return valueType.cast( element.getObjectValue() ); + return valueType.cast( element ); } @Override public T remove( String key ) { - T old = valueType.cast( backingCache.get( key ).getObjectValue() ); + T old = valueType.cast( backingCache.get( key ) ); backingCache.remove( key ); return old; } @@ -59,14 +58,13 @@ public class EhCacheImpl<T> @Override public void put( String key, T value ) { - Element element = new Element( key, value ); - backingCache.put( element ); + backingCache.put( key, value ); } @Override public boolean exists( String key ) { - return backingCache.isKeyInCache( key ); + return backingCache.containsKey( key ); } synchronized void decRefCount() http://git-wip-us.apache.org/repos/asf/zest-java/blob/c0752e4f/extensions/cache-ehcache/src/main/java/org/apache/zest/cache/ehcache/EhCachePoolMixin.java ---------------------------------------------------------------------- diff --git a/extensions/cache-ehcache/src/main/java/org/apache/zest/cache/ehcache/EhCachePoolMixin.java b/extensions/cache-ehcache/src/main/java/org/apache/zest/cache/ehcache/EhCachePoolMixin.java index 3b7c586..927c2cb 100644 --- a/extensions/cache-ehcache/src/main/java/org/apache/zest/cache/ehcache/EhCachePoolMixin.java +++ b/extensions/cache-ehcache/src/main/java/org/apache/zest/cache/ehcache/EhCachePoolMixin.java @@ -20,51 +20,119 @@ package org.apache.zest.cache.ehcache; import java.util.concurrent.ConcurrentHashMap; -import net.sf.ehcache.CacheManager; -import net.sf.ehcache.config.CacheConfiguration; -import net.sf.ehcache.config.PersistenceConfiguration; -import net.sf.ehcache.config.PersistenceConfiguration.Strategy; -import org.apache.zest.api.common.Optional; +import java.util.concurrent.TimeUnit; + import org.apache.zest.api.configuration.Configuration; +import org.apache.zest.api.entity.Identity; import org.apache.zest.api.injection.scope.This; import org.apache.zest.api.util.NullArgumentException; import org.apache.zest.spi.cache.Cache; +import org.ehcache.CacheManager; +import org.ehcache.config.CacheConfiguration; +import org.ehcache.config.builders.CacheConfigurationBuilder; +import org.ehcache.config.builders.CacheManagerBuilder; +import org.ehcache.config.builders.ResourcePoolsBuilder; +import org.ehcache.config.units.MemoryUnit; +import org.ehcache.expiry.Duration; +import org.ehcache.expiry.Expirations; public abstract class EhCachePoolMixin implements EhCachePoolService { - + private static final long DEFAULT_HEAP_SIZE = 1024 * 1024; private final ConcurrentHashMap<String, EhCacheImpl<?>> caches = new ConcurrentHashMap<>(); - @This @Optional - private Configuration<EhCacheConfiguration> config; + + @This + private Identity identity; + + @This + private Configuration<EhCacheConfiguration> configuration; + private CacheManager cacheManager; @Override - @SuppressWarnings( "unchecked" ) + public void activateService() + throws Exception + { + cacheManager = CacheManagerBuilder.newCacheManagerBuilder() + .withDefaultDiskStoreThreadPool( cacheManagerThreadPoolName( "disk-store" ) ) + .withDefaultEventListenersThreadPool( cacheManagerThreadPoolName( "event-listeners" ) ) + .withDefaultWriteBehindThreadPool( cacheManagerThreadPoolName( "write-behind" ) ) + .build(); + cacheManager.init(); + } + + @Override + public void passivateService() + throws Exception + { + cacheManager.close(); + cacheManager = null; + } + + @Override + @SuppressWarnings("unchecked") public <T> Cache<T> fetchCache( String cacheId, Class<T> valueType ) { // Note: Small bug in Ehcache; If the cache name is an empty String it will actually work until // you try to remove the Cache instance from the CacheManager, at which point it is silently - // ignored but not removed so there is an follow up problem of too much in the CacheManager. + // ignored but not removed so there is a follow up problem of too much in the CacheManager. NullArgumentException.validateNotEmpty( "cacheId", cacheId ); - EhCacheImpl<?> cache = caches.get( cacheId ); - if( cache == null ) - { - cache = createNewCache( cacheId, valueType ); - caches.put( cacheId, cache ); - } + EhCacheImpl<?> cache = caches.computeIfAbsent( cacheId, key -> createNewCache( cacheId, valueType ) ); cache.incRefCount(); return (Cache<T>) cache; } private <T> EhCacheImpl<T> createNewCache( String cacheId, Class<T> valueType ) { - CacheConfiguration cc = createCacheConfiguration( cacheId ); - - // TODO: We also need all the other Configurations that are possible, like cacheLoaderFactoryConfiguration - net.sf.ehcache.Cache cache = new net.sf.ehcache.Cache( cc ); - cacheManager.addCache( cache ); - + configuration.refresh(); + EhCacheConfiguration config = configuration.get(); + + ResourcePoolsBuilder poolsBuilder = ResourcePoolsBuilder.newResourcePoolsBuilder() + .heap( config.heapSize().get(), MemoryUnit.valueOf( config.heapUnit().get() ) ); + if( config.offHeapSize().get() != null ) + { + poolsBuilder = poolsBuilder + .offheap( config.offHeapSize().get(), MemoryUnit.valueOf( config.offHeapUnit().get() ) ); + } + if( config.diskSize().get() != null ) + { + poolsBuilder = poolsBuilder + .disk( config.diskSize().get(), MemoryUnit.valueOf( config.diskUnit().get() ), config.diskPersistent().get() ); + } + + CacheConfigurationBuilder<String, T> configBuilder = CacheConfigurationBuilder + .newCacheConfigurationBuilder( String.class, valueType, poolsBuilder ); + if( config.maxObjectSize().get() != null ) + { + configBuilder = configBuilder + .withSizeOfMaxObjectSize( config.maxObjectSize().get(), MemoryUnit.valueOf( config.maxObjectSizeUnit().get() ) ); + } + if( config.maxObjectGraphDepth().get() != null ) + { + configBuilder = configBuilder + .withSizeOfMaxObjectGraph( config.maxObjectGraphDepth().get() ); + } + switch( config.expiry().get() ) { + case "TIME_TO_IDLE": + configBuilder = configBuilder.withExpiry( Expirations.timeToIdleExpiration( Duration.of( + config.expiryLength().get() == null ? -1L : config.expiryLength().get(), + TimeUnit.valueOf( config.expiryTimeUnit().get() ) + ) ) ); + break; + case "TIME_TO_LIVE": + configBuilder = configBuilder.withExpiry( Expirations.timeToLiveExpiration( Duration.of( + config.expiryLength().get() == null ? -1L : config.expiryLength().get(), + TimeUnit.valueOf( config.expiryTimeUnit().get() ) + ) ) ); + break; + case "NONE": + default: + configBuilder = configBuilder.withExpiry( Expirations.noExpiration() ); + break; + } + CacheConfiguration<String, T> cacheConfig = configBuilder.build(); + org.ehcache.Cache<String,T> cache = cacheManager.createCache( cacheId, cacheConfig ); return new EhCacheImpl<>( cacheId, cache, valueType ); } @@ -80,139 +148,8 @@ public abstract class EhCachePoolMixin } } - @Override - public void activateService() - throws Exception - { - net.sf.ehcache.config.Configuration configuration = new net.sf.ehcache.config.Configuration(); - configureEhCache( configuration ); - CacheConfiguration cc = createCacheConfiguration( "zest.ehcache.config.default" ); - configuration.setDefaultCacheConfiguration( cc ); - cacheManager = CacheManager.newInstance( configuration ); - } - - @Override - public void passivateService() - throws Exception - { - cacheManager.shutdown(); - } - - private void configureEhCache( net.sf.ehcache.config.Configuration configuration ) + private String cacheManagerThreadPoolName( String name ) { - EhCacheConfiguration conf = config.get(); - Boolean updateCheck = conf.updateCheck().get(); - configuration.setUpdateCheck( updateCheck ); - configuration.setDynamicConfig( true ); - String monitoring = conf.monitoring().get().trim(); - if( monitoring.length() > 0 ) - { - configuration.setMonitoring( monitoring ); - } - String name = conf.cacheManagerName().get(); - if( name == null ) - { - name = "Zest Cache Extension"; - } - configuration.setName( name ); - String diskStorePath = conf.diskStorePath().get(); - if( diskStorePath.length() > 0 ) - { - configuration.getDiskStoreConfiguration().path( diskStorePath ); - } + return identity.identity().getClass() + "-" + name; } - - private CacheConfiguration createCacheConfiguration( String cacheId ) - { - EhCacheConfiguration conf = config.get(); - Integer maxElementsInMemory = conf.maxElementsInMemory().get(); - if( maxElementsInMemory <= 0 ) - { - maxElementsInMemory = 10000; - } - CacheConfiguration cacheConfig = new CacheConfiguration( cacheId, maxElementsInMemory ); - String transactionalMode = conf.transactionalMode().get(); - if( transactionalMode.length() > 0 ) - { - cacheConfig.transactionalMode( transactionalMode ); - } - - Long timeToLiveSeconds = conf.timeToLiveSeconds().get(); - if( timeToLiveSeconds > 0 ) - { - cacheConfig.timeToLiveSeconds( timeToLiveSeconds ); - } - - Long timeToIdleSeconds = conf.timeToIdleSeconds().get(); - if( timeToIdleSeconds > 0 ) - { - cacheConfig.timeToIdleSeconds( timeToIdleSeconds ); - } - - String name = conf.name().get(); - if( name.length() > 0 ) - { - cacheConfig.name( name ); - } - - String memoryStoreEvictionPolicy = conf.memoryStoreEvictionPolicy().get(); - if( memoryStoreEvictionPolicy.length() > 0 ) - { - cacheConfig.memoryStoreEvictionPolicy( memoryStoreEvictionPolicy ); - } - - Integer maxElementsOnDisk = conf.maxElementsOnDisk().get(); - if( maxElementsOnDisk > 0 ) - { - cacheConfig.maxElementsOnDisk( maxElementsOnDisk ); - } - - Boolean loggingEnabled = conf.loggingEnabled().get(); - if( loggingEnabled != null ) - { - cacheConfig.logging( loggingEnabled ); - } - - Boolean eternal = conf.eternal().get(); - cacheConfig.eternal( eternal ); - - Integer diskSpoolBufferSizeMB = conf.diskSpoolBufferSizeMB().get(); - if( diskSpoolBufferSizeMB > 0 ) - { - cacheConfig.diskSpoolBufferSizeMB( diskSpoolBufferSizeMB ); - } - - Long diskExpiryThreadIntervalSeconds = conf.diskExpiryThreadIntervalSeconds().get(); - if( diskExpiryThreadIntervalSeconds > 0 ) - { - cacheConfig.diskExpiryThreadIntervalSeconds( diskExpiryThreadIntervalSeconds ); - } - - Integer diskAccessStripes = conf.diskAccessStripes().get(); - if( diskAccessStripes > 0 ) - { - cacheConfig.diskAccessStripes( diskAccessStripes ); - } - Boolean clearOnFlush = conf.clearOnFlush().get(); - if( clearOnFlush != null ) - { - cacheConfig.clearOnFlush( clearOnFlush ); - } - - // Persistence Configuration - PersistenceConfiguration persistenceConfig = new PersistenceConfiguration(); - Strategy strategy = conf.persistenceStrategy().get(); - if( strategy == null ) - { - persistenceConfig.strategy( Strategy.NONE ); - } - else - { - persistenceConfig.strategy( strategy ); - } - cacheConfig.persistence( persistenceConfig ); - - return cacheConfig; - } - } http://git-wip-us.apache.org/repos/asf/zest-java/blob/c0752e4f/libraries.gradle ---------------------------------------------------------------------- diff --git a/libraries.gradle b/libraries.gradle index 9f14383..589924d 100644 --- a/libraries.gradle +++ b/libraries.gradle @@ -26,7 +26,7 @@ def commonsDbcpVersion = '2.1.1' def commonsLangVersion = '3.4' def derbyVersion = '10.12.1.1' def dnsJavaVersion = '2.1.7' -def ehcacheVersion = '2.10.2.2.21' // 3.x exists +def ehcacheVersion = '3.1.2' def elasticsearchVersion = '2.4.0' def freemarkerVersion = '2.3.25-incubating' def geodeVersion = '1.0.0-incubating.M3' @@ -187,7 +187,7 @@ rootProject.ext { // Library & Extension dependencies jackson_mapper: "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion", - ehcache: "net.sf.ehcache:ehcache:$ehcacheVersion", + ehcache: "org.ehcache:ehcache:$ehcacheVersion", elasticsearch: "org.elasticsearch:elasticsearch:$elasticsearchVersion", geode: "org.apache.geode:geode-core:$geodeVersion", h2: "com.h2database:h2:$h2Version",