net.sf.ehcache.config.CacheConfiguration Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ehcache-core Show documentation
Show all versions of ehcache-core Show documentation
Internal ehcache-core module. This artifact is not meant to be used directly
/**
* Copyright 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 net.sf.ehcache.config;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.EhcacheDefaultClassLoader;
import net.sf.ehcache.Element;
import net.sf.ehcache.config.PersistenceConfiguration.Strategy;
import net.sf.ehcache.config.PinningConfiguration.Store;
import net.sf.ehcache.config.TerracottaConfiguration.Consistency;
import net.sf.ehcache.event.NotificationScope;
import net.sf.ehcache.search.attribute.DynamicAttributesExtractor;
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
import net.sf.ehcache.store.compound.ReadWriteCopyStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import static net.sf.ehcache.config.Configuration.getAllActiveCaches;
/**
* A value object used to represent cache configuration.
* Construction Patterns
* The recommended way of creating a Cache
in Ehcache 2.0 and above is to create a CacheConfiguration
object
* and pass it to the Cache
constructor. See {@link net.sf.ehcache.Cache#Cache(CacheConfiguration)}.
*
* This class supports setter injection and also the fluent builder pattern.
* e.g.
* Cache cache = new Cache(new CacheConfiguration("test2", 1000).eternal(true).memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.FIFO));
*
* Rather than proliferation of new constructors as new versions of Ehcache come out, it intended to add the new configuration to this
* class.
*
* Another way to set configuration is declaratively in the ehcache.xml
configuration file.
* e.g.
* {@code
*
* }
*
* Dynamic Configuration
* CacheConfiguration instances retrieved from Cache instances allow the dynamic
* modification of certain configuration properties. Currently the dynamic
* properties are:
*
* - Time To Idle
* - Time To Live
* - Max Entries in Local Heap
* - Max Entries on Local Disk
*
* Dynamic changes are however not persistent across cache restarts. On restart
* the cache configuration will be reloaded from its original source, erasing any
* changes made previously at runtime.
*
* Users should also take care of synchronizing threads externally, if a CacheConfiguration instance is
* going to be mutated by multiple threads concurrently. While CacheConfiguration instances will
* make changes properly visible to all threads, logic within individual methods (e.g. validation) isn't
* trying to provide any "thread safeness".
*
* @author Greg Luck
* @author Chris Dennis
* @version $Id: CacheConfiguration.java 10047 2015-10-09 18:09:24Z ljacomet $
*/
public class CacheConfiguration implements Cloneable {
/**
* Default value for clearOnFlush
*/
public static final boolean DEFAULT_CLEAR_ON_FLUSH = true;
/**
* The default interval between runs of the expiry thread.
*/
public static final long DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS = 120;
/**
* Set a buffer size for the spool of approx 30MB.
*/
public static final int DEFAULT_SPOOL_BUFFER_SIZE = 30;
/**
* Default number of diskAccessStripes.
*/
public static final int DEFAULT_DISK_ACCESS_STRIPES = 1;
/**
* Logging is off by default.
*/
public static final boolean DEFAULT_LOGGING = false;
/**
* The default memory store eviction policy is LRU.
*/
public static final MemoryStoreEvictionPolicy DEFAULT_MEMORY_STORE_EVICTION_POLICY = MemoryStoreEvictionPolicy.LRU;
/**
* The default cacheWriterConfiguration
*/
public static final CacheWriterConfiguration DEFAULT_CACHE_WRITER_CONFIGURATION = new CacheWriterConfiguration();
/**
* Default value for copyOnRead
*/
public static final boolean DEFAULT_COPY_ON_READ = false;
/**
* Default value for copyOnRead
*/
public static final boolean DEFAULT_COPY_ON_WRITE = false;
/**
* Default value for ttl
*/
public static final long DEFAULT_TTL = 0;
/**
* Default value for tti
*/
public static final long DEFAULT_TTI = 0;
/**
* Default value for maxElementsOnDisk
*/
public static final int DEFAULT_MAX_ELEMENTS_ON_DISK = 0;
/**
* Default value for maxEntriesInCache
*/
public static final long DEFAULT_MAX_ENTRIES_IN_CACHE = 0;
/**
* Default value for transactionalMode
*/
public static final TransactionalMode DEFAULT_TRANSACTIONAL_MODE = TransactionalMode.OFF;
/**
* Default value for statistics
*/
public static final boolean DEFAULT_STATISTICS = true;
/**
* Default value for diskPersistent
*
* @deprecated The {@code diskPersistent} attribute has been replaced with {@link #persistence(PersistenceConfiguration)}.
*/
@Deprecated
public static final boolean DEFAULT_DISK_PERSISTENT = false;
/**
* Default copyStrategyConfiguration
*/
public static final CopyStrategyConfiguration DEFAULT_COPY_STRATEGY_CONFIGURATION = new CopyStrategyConfiguration();
/**
* Default maxBytesOnHeap value
*/
public static final long DEFAULT_MAX_BYTES_ON_HEAP = 0;
/**
* Default maxBytesOffHeap value
*/
public static final long DEFAULT_MAX_BYTES_OFF_HEAP = 0;
/**
* Default maxBytesOnDisk value
*/
public static final long DEFAULT_MAX_BYTES_ON_DISK = 0;
/**
* Default eternal value
*/
public static final boolean DEFAULT_ETERNAL_VALUE = false;
private static final Logger LOG = LoggerFactory.getLogger(CacheConfiguration.class.getName());
private static final int HUNDRED_PERCENT = 100;
private static final int MINIMUM_RECOMMENDED_IN_MEMORY = 100;
/**
* the name of the cache.
*/
protected volatile String name;
/**
* Timeout in milliseconds for CacheLoader related calls
*/
protected volatile long cacheLoaderTimeoutMillis;
/**
* the maximum objects to be held in the {@link net.sf.ehcache.store.MemoryStore}.
*
* 0
translates to no-limit.
*/
protected volatile Integer maxEntriesLocalHeap;
/**
* the maximum objects to be held in the {@link net.sf.ehcache.store.disk.DiskStore}.
*
* 0
translates to no-limit.
*/
protected volatile int maxElementsOnDisk = DEFAULT_MAX_ELEMENTS_ON_DISK;
/**
* the maximum entries to be held in the cache
*/
protected volatile long maxEntriesInCache = DEFAULT_MAX_ENTRIES_IN_CACHE;
/**
* The policy used to evict elements from the {@link net.sf.ehcache.store.MemoryStore}.
* This can be one of:
*
* - LRU - least recently used
*
- LFU - Less frequently used
*
- FIFO - first in first out, the oldest element by creation time
*
* The default value is LRU
*
* @since 1.2
*/
protected volatile MemoryStoreEvictionPolicy memoryStoreEvictionPolicy = DEFAULT_MEMORY_STORE_EVICTION_POLICY;
/**
* Sets whether the MemoryStore should be cleared when
* {@link net.sf.ehcache.Ehcache#flush flush()} is called on the cache - true by default.
*/
protected volatile boolean clearOnFlush = DEFAULT_CLEAR_ON_FLUSH;
/**
* Sets whether elements are eternal. If eternal, timeouts are ignored and the element
* is never expired.
*/
protected volatile boolean eternal = DEFAULT_ETERNAL_VALUE;
/**
* the time to idle for an element before it expires. Is only used
* if the element is not eternal.A value of 0 means do not check for idling.
*/
protected volatile long timeToIdleSeconds = DEFAULT_TTI;
/**
* Sets the time to idle for an element before it expires. Is only used
* if the element is not eternal. This attribute is optional in the configuration.
* A value of 0 means do not check time to live.
*/
protected volatile long timeToLiveSeconds = DEFAULT_TTL;
/**
* whether elements can overflow to disk when the in-memory cache
* has reached the set limit.
*
* @deprecated The {@code overflowToDisk} attribute has been replaced with {@link Strategy#LOCALTEMPSWAP}.
*/
@Deprecated
protected volatile Boolean overflowToDisk;
/**
* For caches that overflow to disk, whether the disk cache persists between CacheManager instances.
*
* @deprecated The {@code diskPersistent} attribute has been replaced with {@link #persistence(PersistenceConfiguration)}.
*/
@Deprecated
protected volatile Boolean diskPersistent;
/**
* The size of the disk spool used to buffer writes
*/
protected volatile int diskSpoolBufferSizeMB = DEFAULT_SPOOL_BUFFER_SIZE;
/**
* The number of concurrent disk access stripes.
*/
protected volatile int diskAccessStripes = DEFAULT_DISK_ACCESS_STRIPES;
/**
* The interval in seconds between runs of the disk expiry thread.
*
* 2 minutes is the default.
* This is not the same thing as time to live or time to idle. When the thread runs it checks
* these things. So this value is how often we check for expiry.
*/
protected volatile long diskExpiryThreadIntervalSeconds = DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS;
/**
* Indicates whether logging is enabled or not. False by default.
* Only used when cache is clustered with Terracotta.
*/
protected volatile boolean logging = DEFAULT_LOGGING;
/**
* whether elements can overflow to off heap memory when the in-memory cache
* has reached the set limit.
*/
protected volatile Boolean overflowToOffHeap;
/**
* The event listener factories added by BeanUtils.
*/
protected volatile List cacheEventListenerConfigurations =
new ArrayList();
/**
* The cache extension factories added by BeanUtils.
*/
protected volatile List cacheExtensionConfigurations =
new ArrayList();
/**
* The BootstrapCacheLoaderFactoryConfiguration.
*/
protected BootstrapCacheLoaderFactoryConfiguration bootstrapCacheLoaderFactoryConfiguration;
/**
* The CacheExceptionHandlerFactoryConfiguration.
*/
protected CacheExceptionHandlerFactoryConfiguration cacheExceptionHandlerFactoryConfiguration;
/**
* The TerracottaConfiguration.
*/
protected TerracottaConfiguration terracottaConfiguration;
/**
* The PinningConfiguration.
*/
protected volatile PinningConfiguration pinningConfiguration;
/**
* The CacheWriterConfiguration.
*/
protected CacheWriterConfiguration cacheWriterConfiguration = DEFAULT_CACHE_WRITER_CONFIGURATION;
/**
* The cache loader factories added by BeanUtils.
*/
protected volatile List cacheLoaderConfigurations = new ArrayList();
/**
* The cache decorator factories added by BeanUtils.
*/
protected volatile List cacheDecoratorConfigurations =
new ArrayList();
/**
* The listeners for this configuration.
*/
protected volatile Set listeners = new CopyOnWriteArraySet();
private volatile Set dynamicSearchListeners = new CopyOnWriteArraySet();
private DynamicAttributesExtractor flexIndexer;
private volatile boolean frozen;
private volatile TransactionalMode transactionalMode;
private volatile boolean statistics = DEFAULT_STATISTICS;
private volatile CopyStrategyConfiguration copyStrategyConfiguration = DEFAULT_COPY_STRATEGY_CONFIGURATION.copy();
private volatile SizeOfPolicyConfiguration sizeOfPolicyConfiguration;
private volatile PersistenceConfiguration persistenceConfiguration;
private volatile ElementValueComparatorConfiguration elementValueComparatorConfiguration =
new ElementValueComparatorConfiguration();
private volatile Boolean copyOnRead;
private volatile Boolean copyOnWrite;
private volatile boolean conflictingEternalValuesWarningLogged;
private volatile Searchable searchable;
private String maxBytesLocalHeapInput;
private String maxBytesLocalOffHeapInput;
private String maxBytesLocalDiskInput;
private Long maxBytesLocalHeap;
private Long maxBytesLocalOffHeap;
private Long maxBytesLocalDisk;
private Integer maxBytesLocalHeapPercentage;
private Integer maxBytesLocalOffHeapPercentage;
private Integer maxBytesLocalDiskPercentage;
private PoolUsage onHeapPoolUsage;
private PoolUsage offHeapPoolUsage;
private PoolUsage onDiskPoolUsage;
private volatile boolean maxEntriesLocalDiskExplicitlySet;
private volatile boolean maxBytesLocalDiskExplicitlySet;
private volatile boolean maxBytesLocalOffHeapExplicitlySet;
private volatile ClassLoader classLoader = EhcacheDefaultClassLoader.getInstance();
/**
* Default constructor.
*
* Note that an empty Cache is not valid and must have extra configuration added which can be done
* through the fluent methods in this class. Call validateConfiguration()
to check your configuration.
*
* @see #validateCompleteConfiguration
*/
public CacheConfiguration() {
// empty constructor
}
/**
* Create a new cache configuration.
*
* Extra configuration can added after construction via the fluent methods in this class.
* Call validateConfiguration()
to check your configuration.
*
* @param name the name of the cache. Note that "default" is a reserved name for the defaultCache.
* @param maxEntriesLocalHeap the maximum number of elements in memory, before they are evicted (0 == no limit)
* @see #validateCompleteConfiguration()
*/
public CacheConfiguration(String name, int maxEntriesLocalHeap) {
this.name = name;
verifyGreaterThanOrEqualToZero((long) maxEntriesLocalHeap, "maxEntriesLocalHeap");
this.maxEntriesLocalHeap = maxEntriesLocalHeap;
}
/**
* Clones this object, following the usual contract.
*
* @return a copy, which independent other than configurations than cannot change.
*/
@Override
public CacheConfiguration clone() {
CacheConfiguration config;
try {
config = (CacheConfiguration) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
cloneCacheEventListenerConfigurations(config);
cloneCacheExtensionConfigurations(config);
if (bootstrapCacheLoaderFactoryConfiguration != null) {
config.bootstrapCacheLoaderFactoryConfiguration = bootstrapCacheLoaderFactoryConfiguration.clone();
}
if (cacheExceptionHandlerFactoryConfiguration != null) {
config.cacheExceptionHandlerFactoryConfiguration = cacheExceptionHandlerFactoryConfiguration.clone();
}
if (terracottaConfiguration != null) {
config.terracottaConfiguration = terracottaConfiguration.clone();
}
if (cacheWriterConfiguration != null) {
config.cacheWriterConfiguration = cacheWriterConfiguration.clone();
}
cloneCacheLoaderConfigurations(config);
cloneCacheDecoratorConfigurations(config);
config.listeners = new CopyOnWriteArraySet();
config.dynamicSearchListeners = new CopyOnWriteArraySet();
return config;
}
private void cloneCacheEventListenerConfigurations(CacheConfiguration config) {
List copy = new ArrayList();
for (CacheEventListenerFactoryConfiguration item : cacheEventListenerConfigurations) {
copy.add(item.clone());
}
config.cacheEventListenerConfigurations = copy;
}
private void cloneCacheExtensionConfigurations(CacheConfiguration config) {
List copy = new ArrayList();
for (CacheConfiguration.CacheExtensionFactoryConfiguration item : cacheExtensionConfigurations) {
copy.add(item.clone());
}
config.cacheExtensionConfigurations = copy;
}
private void cloneCacheLoaderConfigurations(CacheConfiguration config) {
List copy = new ArrayList();
for (CacheConfiguration.CacheLoaderFactoryConfiguration item : cacheLoaderConfigurations) {
copy.add(item.clone());
}
config.cacheLoaderConfigurations = copy;
}
private void cloneCacheDecoratorConfigurations(CacheConfiguration config) {
List copy = new ArrayList();
for (CacheDecoratorFactoryConfiguration item : cacheDecoratorConfigurations) {
copy.add(item.clone());
}
config.cacheDecoratorConfigurations = copy;
}
private void assertArgumentNotNull(String name, Object object) {
if (object == null) {
throw new IllegalArgumentException(name + " cannot be null");
}
}
/**
* Sets the name of the cache.
*
* Cache names have constraints on the characters they can use:
*
* - the '/' character is illegal,
* - the '#' character does not work with RMI replication,
* - caches that are registered as MBeans must obey the {@link javax.management.ObjectName} rules for unquoted value.
* This means the following characters are illegal: ',', '=', ':', '"', '*' or '?'.
*
* Note that caches inside a clustered cache manager are by default registered as MBean.
*
* @param name the cache name. This must be unique.
*/
public final void setName(String name) {
checkDynamicChange();
assertArgumentNotNull("Cache name", name);
this.name = name;
}
/**
* Builder to set the name of the cache.
*
* Cache names have constraints on the characters they can use:
*
* - the '/' character is illegal,
* - the '#' character does not work with RMI replication,
* - caches that are registered as MBeans must obey the {@link javax.management.ObjectName} rules for unquoted value.
* This means the following characters are illegal: ',', '=', ':', '"', '*' or '?'.
*
* Note that caches inside a clustered cache manager are by default registered as MBean.
*
* @param name the cache name. This must be unique.
* @return this configuration instance
* @see #setName(String)
*/
public final CacheConfiguration name(String name) {
setName(name);
return this;
}
/**
* Enables or disables logging for the cache
*
* This property can be modified dynamically while the cache is operating.
* Only used when cache is clustered with Terracotta
*
* @param enable If true, enables logging otherwise disables logging
*/
public final void setLogging(boolean enable) {
checkDynamicChange();
boolean oldLoggingEnabled = this.logging;
this.logging = enable;
fireLoggingChanged(oldLoggingEnabled, enable);
}
/**
* Enables or disables offheap store for the cache.
*
* @param overflowToOffHeap If true, enables offheap store otherwise disables it.
*/
public final void setOverflowToOffHeap(boolean overflowToOffHeap) {
checkDynamicChange();
this.overflowToOffHeap = overflowToOffHeap;
}
/**
* Builder to enable or disable offheap store for the cache.
*
* @param overflowToOffHeap If true, enables offheap store otherwise disables it.
* @return this configuration instance
* @see #setOverflowToOffHeap(boolean)
*/
public CacheConfiguration overflowToOffHeap(boolean overflowToOffHeap) {
setOverflowToOffHeap(overflowToOffHeap);
return this;
}
/**
* Sets the SizeOfPolicyConfiguration for this cache.
*
* @param sizeOfPolicyConfiguration the SizeOfPolicy Configuration
*/
public void addSizeOfPolicy(SizeOfPolicyConfiguration sizeOfPolicyConfiguration) {
this.sizeOfPolicyConfiguration = sizeOfPolicyConfiguration;
}
/**
* Builder to set the SizeOfPolicyConfiguration for this cache.
*
* @param sizeOfPolicyConfiguration the SizeOfPolicy Configuration
* @return this configuration instance
* @see #addSizeOfPolicy(SizeOfPolicyConfiguration)
*/
public CacheConfiguration sizeOfPolicy(SizeOfPolicyConfiguration sizeOfPolicyConfiguration) {
addSizeOfPolicy(sizeOfPolicyConfiguration);
return this;
}
/**
* Sets the PersistenceConfiguration for this cache.
*
* @param persistenceConfiguration the Persistence Configuration
*/
public void addPersistence(PersistenceConfiguration persistenceConfiguration) {
if (diskPersistent != null) {
throw new InvalidConfigurationException("Cannot use both and diskPersistent in a single cache configuration.");
}
if (Boolean.TRUE.equals(overflowToDisk)) {
throw new InvalidConfigurationException("Cannot use both and overflowToDisk in a single cache configuration.");
}
this.persistenceConfiguration = persistenceConfiguration;
}
/**
* Builder to set the PersistenceConfiguration for this cache.
*
* @param persistenceConfiguration the Persistence Configuration
* @return this configuration instance
* @see #addPersistence(PersistenceConfiguration)
*/
public CacheConfiguration persistence(PersistenceConfiguration persistenceConfiguration) {
addPersistence(persistenceConfiguration);
return this;
}
/**
* Sets the max off heap memory size allocated for this cache.
*
* @param maxMemoryOffHeap the max off heap memory size allocated for this cache.
* @deprecated See {@link #setMaxBytesLocalOffHeap(java.lang.String)}
*/
@Deprecated
public final void setMaxMemoryOffHeap(String maxMemoryOffHeap) {
checkDynamicChange();
assertArgumentNotNull("Cache maxMemoryOffHeap", maxMemoryOffHeap);
setMaxBytesLocalOffHeap(maxMemoryOffHeap);
}
/**
* Builder to set the max off heap memory size allocated for this cache.
*
* @param maxMemoryOffHeap the max off heap memory size allocated for this cache.
* @return this configuration instance
* @deprecated See {@link #maxBytesLocalOffHeap(long, net.sf.ehcache.config.MemoryUnit)}
*/
@Deprecated
public CacheConfiguration maxMemoryOffHeap(String maxMemoryOffHeap) {
setMaxMemoryOffHeap(maxMemoryOffHeap);
return this;
}
/**
* Builder to enable or disable logging for the cache
*
* This property can be modified dynamically while the cache is operating.
* Only used when cache is clustered with Terracotta
*
* @param enable If true, enables logging otherwise disables logging
* @return this configuration instance
* @see #setLogging(boolean)
*/
public final CacheConfiguration logging(boolean enable) {
setLogging(enable);
return this;
}
/**
* Sets the maximum objects to be held in memory (0 = no limit).
*
* This property can be modified dynamically while the cache is operating.
*
* @param maxElementsInMemory The maximum number of elements in memory, before they are evicted (0 == no limit)
* @deprecated use {@link #setMaxEntriesLocalHeap(long)}
*/
@Deprecated
public final void setMaxElementsInMemory(int maxElementsInMemory) {
setMaxEntriesLocalHeap(maxElementsInMemory);
}
/**
* Sets the maximum objects to be held in local heap memory (0 = no limit).
*
* This property can be modified dynamically while the cache is operating.
*
* @param maxEntriesLocalHeap The maximum number of elements in memory, before they are evicted (0 == no limit)
*/
public final void setMaxEntriesLocalHeap(long maxEntriesLocalHeap) {
verifyGreaterThanOrEqualToZero(maxEntriesLocalHeap, "maxEntriesLocalHeap");
if (maxEntriesLocalHeap > Integer.MAX_VALUE) {
throw new IllegalArgumentException("Values larger than Integer.MAX_VALUE are not currently supported.");
}
checkDynamicChange();
if (onHeapPoolUsage != null && onHeapPoolUsage != PoolUsage.None) {
throw new InvalidConfigurationException("MaxEntriesLocalHeap is not compatible with " +
"MaxBytesLocalHeap set on cache");
}
int oldCapacity = this.maxEntriesLocalHeap == null ? 0 : this.maxEntriesLocalHeap;
int newCapacity = (int) maxEntriesLocalHeap;
this.maxEntriesLocalHeap = (int) maxEntriesLocalHeap;
fireMemoryCapacityChanged(oldCapacity, newCapacity);
}
/**
* Builder that sets the maximum objects to be held in memory (0 = no limit).
*
* This property can be modified dynamically while the cache is operating.
*
* @param maxElementsInMemory The maximum number of elements in memory, before they are evicted (0 == no limit)
* @return this configuration instance
* @deprecated use {@link #maxEntriesLocalHeap(int)}
*/
@Deprecated
public final CacheConfiguration maxElementsInMemory(int maxElementsInMemory) {
setMaxElementsInMemory(maxElementsInMemory);
return this;
}
/**
* Builder that sets the maximum objects to be held in memory (0 = no limit).
*
* This property can be modified dynamically while the cache is operating.
*
* @param maxElementsInMemory The maximum number of elements in memory, before they are evicted (0 == no limit)
* @return this configuration instance
*/
public final CacheConfiguration maxEntriesLocalHeap(int maxElementsInMemory) {
setMaxEntriesLocalHeap(maxElementsInMemory);
return this;
}
/**
* Sets the timeout for CacheLoader execution (0 = no timeout).
*
* @param cacheLoaderTimeoutMillis the timeout in milliseconds.
*/
public final void setCacheLoaderTimeoutMillis(long cacheLoaderTimeoutMillis) {
checkDynamicChange();
this.cacheLoaderTimeoutMillis = cacheLoaderTimeoutMillis;
}
/**
* Builder that sets the timeout for CacheLoader execution (0 = no timeout).
* @param timeoutMillis the timeout in milliseconds.
* @return this configuration instance
*/
public CacheConfiguration timeoutMillis(long timeoutMillis) {
setCacheLoaderTimeoutMillis(timeoutMillis);
return this;
}
/**
* Sets the eviction policy. An invalid argument will set it to LRU.
*
* @param memoryStoreEvictionPolicy a String representation of the policy. One of "LRU", "LFU" or "FIFO".
*/
public final void setMemoryStoreEvictionPolicy(String memoryStoreEvictionPolicy) {
assertArgumentNotNull("Cache memoryStoreEvictionPolicy", memoryStoreEvictionPolicy);
setMemoryStoreEvictionPolicyFromObject(MemoryStoreEvictionPolicy.fromString(memoryStoreEvictionPolicy));
}
/**
* Builder that sets the eviction policy. An invalid argument will set it to null.
*
* @param memoryStoreEvictionPolicy a String representation of the policy. One of "LRU", "LFU" or "FIFO".
* @return this configuration instance
* @see #setMemoryStoreEvictionPolicy(String)
*/
public final CacheConfiguration memoryStoreEvictionPolicy(String memoryStoreEvictionPolicy) {
setMemoryStoreEvictionPolicy(memoryStoreEvictionPolicy);
return this;
}
/**
* Sets the eviction policy. This method has a strange name to workaround a problem with XML parsing.
*/
public final void setMemoryStoreEvictionPolicyFromObject(MemoryStoreEvictionPolicy memoryStoreEvictionPolicy) {
checkDynamicChange();
if (null == memoryStoreEvictionPolicy) {
this.memoryStoreEvictionPolicy = DEFAULT_MEMORY_STORE_EVICTION_POLICY;
} else {
this.memoryStoreEvictionPolicy = memoryStoreEvictionPolicy;
}
}
/**
* Builder which Sets the eviction policy. An invalid argument will set it to null.
*
* @return this configuration instance
* @see #setMemoryStoreEvictionPolicyFromObject(MemoryStoreEvictionPolicy)
*/
public final CacheConfiguration memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy memoryStoreEvictionPolicy) {
setMemoryStoreEvictionPolicyFromObject(memoryStoreEvictionPolicy);
return this;
}
/**
* Sets whether the MemoryStore should be cleared when
* {@link net.sf.ehcache.Ehcache#flush flush()} is called on the cache - true by default.
*
* @param clearOnFlush true to clear on flush
*/
public final void setClearOnFlush(boolean clearOnFlush) {
checkDynamicChange();
this.clearOnFlush = clearOnFlush;
}
/**
* Builder which sets whether the MemoryStore should be cleared when
* {@link net.sf.ehcache.Ehcache#flush flush()} is called on the cache - true by default.
*
* @param clearOnFlush true to clear on flush
* @return this configuration instance
* @see #setClearOnFlush(boolean)
*/
public final CacheConfiguration clearOnFlush(boolean clearOnFlush) {
setClearOnFlush(clearOnFlush);
return this;
}
/**
* Sets whether elements are eternal. If eternal, timeouts are ignored and the element is never expired. False by default.
*
* @param eternal true for eternal
*/
public final void setEternal(boolean eternal) {
checkDynamicChange();
isEternalValueConflictingWithTTIOrTTL(eternal, getTimeToLiveSeconds(), getTimeToIdleSeconds());
this.eternal = eternal;
if (eternal) {
setTimeToIdleSeconds(0);
setTimeToLiveSeconds(0);
}
}
private boolean isEternalValueConflictingWithTTIOrTTL(boolean newEternalValue, long newTTLValue, long newTTIValue) {
boolean conflicting = false;
if (newEternalValue && (newTTLValue != 0 || newTTIValue != 0)) {
conflicting = true;
}
if (conflicting && !conflictingEternalValuesWarningLogged) {
conflictingEternalValuesWarningLogged = true;
LOG.warn("Cache '" + getName() + "' is set to eternal but also has TTI/TTL set. "
+ " To avoid this warning, clean up the config " + "removing conflicting values of eternal,"
+ " TTI and TTL. Effective configuration for Cache '" + getName() + "' will be eternal='" + newEternalValue
+ "', timeToIdleSeconds='0', timeToLiveSeconds='0'.");
}
return conflicting;
}
/**
* Builder which sets whether elements are eternal. If eternal, timeouts are ignored and the element is never expired. False by default.
*
* @param eternal true for eternal
* @return this configuration instance
* @see #setEternal(boolean)
*/
public final CacheConfiguration eternal(boolean eternal) {
setEternal(eternal);
return this;
}
/**
* Sets the time to idle for an element before it expires. Is only used if the element is not eternal. This can be overidden in
* {@link net.sf.ehcache.Element}
*
* This property can be modified dynamically while the cache is operating.
*
* @param timeToIdleSeconds the default amount of time to live for an element from its last accessed or modified date
*/
public final void setTimeToIdleSeconds(long timeToIdleSeconds) {
checkDynamicChange();
verifyGreaterThanOrEqualToZero(timeToIdleSeconds, "timeToIdleSeconds");
if (!isEternalValueConflictingWithTTIOrTTL(eternal, 0, timeToIdleSeconds)) {
long oldTti = this.timeToIdleSeconds;
long newTti = timeToIdleSeconds;
this.timeToIdleSeconds = timeToIdleSeconds;
fireTtiChanged(oldTti, newTti);
}
}
/**
* Builder which sets the time to idle for an element before it expires. Is only used if the element is not eternal.
* This default can be overridden in {@link net.sf.ehcache.Element}
*
* This property can be modified dynamically while the cache is operating.
*
* @param timeToIdleSeconds the default amount of time to live for an element from its last accessed or modified date
* @return this configuration instance
* @see #setTimeToIdleSeconds(long)
*/
public final CacheConfiguration timeToIdleSeconds(long timeToIdleSeconds) {
setTimeToIdleSeconds(timeToIdleSeconds);
return this;
}
/**
* Sets the time to idle for an element before it expires. Is only used if the element is not eternal.
* This default can be overridden in {@link net.sf.ehcache.Element}
*
* This property can be modified dynamically while the cache is operating.
*
* @param timeToLiveSeconds the default amount of time to live for an element from its creation date
*/
public final void setTimeToLiveSeconds(long timeToLiveSeconds) {
checkDynamicChange();
verifyGreaterThanOrEqualToZero(timeToLiveSeconds, "timeToLiveSeconds");
if (!isEternalValueConflictingWithTTIOrTTL(eternal, timeToLiveSeconds, 0)) {
long oldTtl = this.timeToLiveSeconds;
long newTtl = timeToLiveSeconds;
this.timeToLiveSeconds = timeToLiveSeconds;
fireTtlChanged(oldTtl, newTtl);
}
}
/**
* Builder which sets the time to idle for an element before it expires. Is only used if the element is not eternal.
* This default can be overridden in {@link net.sf.ehcache.Element}
*
* This property can be modified dynamically while the cache is operating.
*
* @param timeToLiveSeconds the default amount of time to live for an element from its creation date
* @return this configuration instance
* @see #setTimeToLiveSeconds(long)
*/
public final CacheConfiguration timeToLiveSeconds(long timeToLiveSeconds) {
setTimeToLiveSeconds(timeToLiveSeconds);
return this;
}
/**
* Sets whether elements can overflow to disk when the in-memory cache has reached the set limit.
*
* @param overflowToDisk whether to use the disk store
* @deprecated The {@code overflowToDisk} attribute has been replaced with {@link Strategy#LOCALTEMPSWAP}.
*/
@Deprecated
public final void setOverflowToDisk(boolean overflowToDisk) {
checkDynamicChange();
if (persistenceConfiguration != null && Boolean.TRUE.equals(overflowToDisk)) {
throw new InvalidConfigurationException("Cannot use both and overflowToDisk in a single cache configuration.");
}
this.overflowToDisk = overflowToDisk;
validateConfiguration();
}
/**
* Builder which sets whether elements can overflow to disk when the in-memory cache has reached the set limit.
*
* @param overflowToDisk whether to use the disk store
* @return this configuration instance
* @see #setOverflowToDisk(boolean)
* @deprecated The {@code overflowToDisk} attribute has been replaced with {@link Strategy#LOCALTEMPSWAP}.
*/
@Deprecated
public final CacheConfiguration overflowToDisk(boolean overflowToDisk) {
setOverflowToDisk(overflowToDisk);
return this;
}
/**
* Sets whether the disk store persists between CacheManager instances. Note that this operates independently of {@link #overflowToDisk}.
*
* @param diskPersistent whether to persist the cache to disk between JVM restarts
* @deprecated The {@code diskPersistent} attribute has been replaced with {@link #persistence(PersistenceConfiguration)}.
*/
@Deprecated
public final void setDiskPersistent(boolean diskPersistent) {
checkDynamicChange();
if (persistenceConfiguration != null) {
throw new InvalidConfigurationException("Cannot use both and diskPersistent in a single cache configuration.");
}
this.diskPersistent = diskPersistent;
validateConfiguration();
}
/**
* Builder which sets whether the disk store persists between CacheManager instances. Note that this operates independently of {@link #overflowToDisk}.
*
* @param diskPersistent whether to persist the cache to disk between JVM restarts.
* @return this configuration instance
* @see #setDiskPersistent(boolean)
* @deprecated The {@code diskPersistent} attribute has been replaced with {@link #persistence(PersistenceConfiguration)}.
*/
@Deprecated
public final CacheConfiguration diskPersistent(boolean diskPersistent) {
setDiskPersistent(diskPersistent);
return this;
}
/**
* Sets the disk spool size, which is used to buffer writes to the DiskStore.
* If not set it defaults to {@link #DEFAULT_SPOOL_BUFFER_SIZE}
*
* @param diskSpoolBufferSizeMB a positive number
*/
public void setDiskSpoolBufferSizeMB(int diskSpoolBufferSizeMB) {
checkDynamicChange();
if (diskSpoolBufferSizeMB <= 0) {
this.diskSpoolBufferSizeMB = DEFAULT_SPOOL_BUFFER_SIZE;
} else {
this.diskSpoolBufferSizeMB = diskSpoolBufferSizeMB;
}
}
/**
* Builder which sets the disk spool size, which is used to buffer writes to the DiskStore.
* If not set it defaults to {@link #DEFAULT_SPOOL_BUFFER_SIZE}
*
* @param diskSpoolBufferSizeMB a positive number
* @return this configuration instance
* @see #setDiskSpoolBufferSizeMB(int)
*/
public final CacheConfiguration diskSpoolBufferSizeMB(int diskSpoolBufferSizeMB) {
setDiskSpoolBufferSizeMB(diskSpoolBufferSizeMB);
return this;
}
/**
* Sets the number of disk stripes. RandomAccessFiles used to access the data file. By default there
* is one stripe.
*
* @param stripes number of stripes (rounded up to a power-of-2)
*/
public void setDiskAccessStripes(int stripes) {
checkDynamicChange();
if (stripes <= 0) {
this.diskAccessStripes = DEFAULT_DISK_ACCESS_STRIPES;
} else {
this.diskAccessStripes = stripes;
}
}
/**
* Builder which sets the number of disk stripes. RandomAccessFiles used to access the data file. By default there
* is one stripe.
*
* @return this configuration instance
* @see #setDiskAccessStripes(int)
*/
public final CacheConfiguration diskAccessStripes(int stripes) {
setDiskAccessStripes(stripes);
return this;
}
/**
* Sets the maximum number elements on Disk. 0 means unlimited.
*
* This property can be modified dynamically while the cache is operating.
*
* @param maxElementsOnDisk the maximum number of Elements to allow on the disk. 0 means unlimited.
* @deprecated use {@link #setMaxEntriesLocalDisk(long)} for unclustered caches and {@link #setMaxEntriesInCache(long)} for clustered caches.
*/
public void setMaxElementsOnDisk(int maxElementsOnDisk) {
if (onDiskPoolUsage != null && onDiskPoolUsage != PoolUsage.None) {
throw new InvalidConfigurationException("MaxEntriesLocalDisk is not compatible with " +
"MaxBytesLocalDisk set on cache");
}
verifyGreaterThanOrEqualToZero((long) maxElementsOnDisk, "maxElementsOnDisk");
checkDynamicChange();
int oldCapacity = this.maxElementsOnDisk;
this.maxElementsOnDisk = maxElementsOnDisk;
fireDiskCapacityChanged(oldCapacity, this.maxElementsOnDisk);
}
/**
* Sets the maximum number of entries in the cache. Only applies to terracotta clustered caches.
*
* The values for maxEntriesInCache must be equal or superior to 0 and are interpreted as follows:
*
* - {@code maxEntriesInCache == 0} means no capacity based eviction, but resource based eviction can happen.
* - {@code maxEntriesInCache > 0} means both capacity based and resource based eviction can happen
*
*
* This property can be modified dynamically while the cache is operating.
*
* @param maxEntriesInCache maximum number of entries in cache
*/
public void setMaxEntriesInCache(long maxEntriesInCache) {
checkDynamicChange();
verifyGreaterThanOrEqualToZero((long)maxEntriesInCache, "maxEntriesInCache");
checkIfCachePinned(maxEntriesInCache);
long oldValue = this.maxEntriesInCache;
this.maxEntriesInCache = maxEntriesInCache;
fireMaxEntriesInCacheChanged(oldValue, this.maxEntriesInCache);
}
private void checkIfCachePinned(long maxEntriesInCache) {
if (maxEntriesInCache != DEFAULT_MAX_ENTRIES_IN_CACHE &&
getPinningConfiguration() != null && Store.INCACHE.equals(getPinningConfiguration().getStore())) {
throw new InvalidConfigurationException("Setting maxEntriesInCache on an in-cache pinned cache is not legal");
}
}
/**
* Sets the maximum number elements on Disk. 0 means unlimited.
*
* This property can be modified dynamically while the cache is operating.
*
* @param maxEntriesLocalDisk the maximum number of Elements to allow on the disk. 0 means unlimited.
*/
public void setMaxEntriesLocalDisk(long maxEntriesLocalDisk) {
if (isTerracottaClustered()) {
throw new InvalidConfigurationException("MaxEntriesLocalDisk is not applicable for Terracotta clustered caches");
}
verifyGreaterThanOrEqualToZero(maxEntriesLocalDisk, "maxEntriesLocalDisk");
if (maxEntriesLocalDisk > Integer.MAX_VALUE) {
throw new IllegalArgumentException("Values greater than Integer.MAX_VALUE are not currently supported.");
}
// This check against pool usage is only there to see if this configuration backs up a running cache
if (onDiskPoolUsage != null && isTerracottaClustered()) {
throw new IllegalStateException("Can't use local disks with Terracotta clustered caches!");
}
maxEntriesLocalDiskExplicitlySet = true;
setMaxElementsOnDisk((int)maxEntriesLocalDisk);
}
/**
* Builder which sets the maximum number elements on Disk. 0 means unlimited.
*
* This property can be modified dynamically while the cache is operating.
*
* @param maxElementsOnDisk the maximum number of Elements to allow on the disk. 0 means unlimited.
* @return this configuration instance
* @see #setMaxElementsOnDisk(int)
* @deprecated use {@link #maxEntriesLocalDisk(int)} for unclustered caches and {@link #maxEntriesInCache(long)} for clustered caches.
*/
public final CacheConfiguration maxElementsOnDisk(int maxElementsOnDisk) {
setMaxElementsOnDisk(maxElementsOnDisk);
return this;
}
/**
* Builder which sets the maximum number entries in cache.
*
* This property can be modified dynamically while the cache is operating.
*
* @param maxEntriesInCache the maximum number of entries to allow in the cache.
* @return this configuration instance
* @see #setMaxEntriesInCache(long)
*/
public final CacheConfiguration maxEntriesInCache(long maxEntriesInCache) {
setMaxEntriesInCache(maxEntriesInCache);
return this;
}
/**
* Builder which sets the maximum number elements on Disk. 0 means unlimited.
*
* This property can be modified dynamically while the cache is operating.
*
* @param maxElementsOnDisk the maximum number of Elements to allow on the disk. 0 means unlimited.
* @return this configuration instance
* @see #setMaxElementsOnDisk(int)
*/
public final CacheConfiguration maxEntriesLocalDisk(int maxElementsOnDisk) {
setMaxEntriesLocalDisk(maxElementsOnDisk);
return this;
}
/**
* Sets the interval in seconds between runs of the disk expiry thread.
*
* 2 minutes is the default.
* This is not the same thing as time to live or time to idle. When the thread runs it checks
* these things. So this value is how often we check for expiry.
*/
public final void setDiskExpiryThreadIntervalSeconds(long diskExpiryThreadIntervalSeconds) {
checkDynamicChange();
if (diskExpiryThreadIntervalSeconds <= 0) {
this.diskExpiryThreadIntervalSeconds = DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS;
} else {
this.diskExpiryThreadIntervalSeconds = diskExpiryThreadIntervalSeconds;
}
}
/**
* Builder which sets the interval in seconds between runs of the disk expiry thread.
*
* 2 minutes is the default.
* This is not the same thing as time to live or time to idle. When the thread runs it checks
* these things. So this value is how often we check for expiry.
*
* @return this configuration instance
* @see #setDiskExpiryThreadIntervalSeconds(long)
*/
public final CacheConfiguration diskExpiryThreadIntervalSeconds(long diskExpiryThreadIntervalSeconds) {
setDiskExpiryThreadIntervalSeconds(diskExpiryThreadIntervalSeconds);
return this;
}
/**
* Freeze this configuration. Any subsequent changes will throw a CacheException
*/
public void freezeConfiguration() {
frozen = true;
if (searchable != null) {
searchable.freezeConfiguration();
}
}
/**
* @return true is this configuration is frozen - it cannot be changed dynamically.
*/
public boolean isFrozen() {
return frozen;
}
/**
* Getter to the configured ReadWriteCopyStrategy.
* This will always return the same unique instance per cache
*
* @return the {@link ReadWriteCopyStrategy} for instance for this cache
*/
public ReadWriteCopyStrategy getCopyStrategy() {
// todo really make this pluggable through config!
return copyStrategyConfiguration.getCopyStrategyInstance(getClassLoader());
}
/**
* Whether the Cache should copy elements it returns
*
* @param copyOnRead true, if copyOnRead
*/
public CacheConfiguration copyOnRead(boolean copyOnRead) {
this.setCopyOnRead(copyOnRead);
return this;
}
/**
* Whether the Cache should copy elements it returns
*
* @return true, is copyOnRead
*/
public boolean isCopyOnRead() {
validateTransactionalSettings();
return copyOnRead;
}
/**
* Whether the Cache should copy elements it returns
*
* @param copyOnRead true, if copyOnRead
*/
public void setCopyOnRead(final boolean copyOnRead) {
this.copyOnRead = copyOnRead;
}
/**
* Whether the Cache should copy elements it gets
*
* @param copyOnWrite true, if copyOnWrite
*/
public CacheConfiguration copyOnWrite(boolean copyOnWrite) {
this.copyOnWrite = copyOnWrite;
return this;
}
/**
* Whether the Cache should copy elements it gets
*
* @return true, if copyOnWrite
*/
public boolean isCopyOnWrite() {
validateTransactionalSettings();
return copyOnWrite;
}
/**
* Whether the Cache should copy elements it gets
*
* @param copyOnWrite true, if copyOnWrite
*/
public void setCopyOnWrite(final boolean copyOnWrite) {
this.copyOnWrite = copyOnWrite;
}
/**
* Sets the CopyStrategyConfiguration for this cache
*
* @param copyStrategyConfiguration the CopyStrategy Configuration
*/
public void addCopyStrategy(CopyStrategyConfiguration copyStrategyConfiguration) {
this.copyStrategyConfiguration = copyStrategyConfiguration;
}
/**
* Sets the ElementValueComparatorConfiguration for this cache
* The default configuration will setup a {@link net.sf.ehcache.store.DefaultElementValueComparator}
*
* @param elementValueComparatorConfiguration the ElementComparator Configuration
*/
public void addElementValueComparator(ElementValueComparatorConfiguration elementValueComparatorConfiguration) {
this.elementValueComparatorConfiguration = elementValueComparatorConfiguration;
}
/**
* Add configuration to make this cache searchable
*
* @param searchable search config to add
*/
public final void addSearchable(Searchable searchable) {
checkDynamicChange();
this.searchable = searchable;
}
/**
* The maximum amount of bytes the cache should occupy on heap
* @return value in bytes, 0 if none set
*/
public long getMaxBytesLocalHeap() {
return maxBytesLocalHeap == null ? DEFAULT_MAX_BYTES_ON_HEAP : maxBytesLocalHeap;
}
/**
* Setter for maxBytesLocalHeap as a String. Value can have a one char unit suffix or be a percentage (ending in %)
*
* This property can be modified dynamically while the cache is operating.
*
* @param maxBytesHeap String representation of the size, can be relative (in %)
*/
public void setMaxBytesLocalHeap(final String maxBytesHeap) {
assertArgumentNotNull("Cache maxBytesLocalHeap", maxBytesHeap);
if (isPercentage(maxBytesHeap)) {
maxBytesLocalHeapPercentage = parsePercentage(maxBytesHeap);
} else {
setMaxBytesLocalHeap(MemoryUnit.parseSizeInBytes(maxBytesHeap));
}
maxBytesLocalHeapInput = maxBytesHeap;
}
/**
* Setter for maxBytesLocalHeap in bytes
*
* This property can be modified dynamically while the cache is operating.
*
* @param maxBytesHeap max bytes in heap in bytes
*/
public void setMaxBytesLocalHeap(final Long maxBytesHeap) {
if (onHeapPoolUsage != null && getMaxEntriesLocalHeap() > 0) {
throw new InvalidConfigurationException("MaxEntriesLocalHeap is not compatible with " +
"MaxBytesLocalHeap set on cache");
}
if (onHeapPoolUsage != null && onHeapPoolUsage != PoolUsage.Cache) {
throw new IllegalStateException("A Cache can't switch memory pool!");
}
checkDynamicChange();
verifyGreaterThanZero(maxBytesHeap, "maxBytesLocalHeap");
Long oldValue = this.maxBytesLocalHeap;
this.maxBytesLocalHeap = maxBytesHeap;
fireMaxBytesOnLocalHeapChanged(oldValue, maxBytesHeap);
}
private void fireMaxBytesOnLocalHeapChanged(final Long oldValue, final Long newValue) {
if ((oldValue != null && !oldValue.equals(newValue)) || (newValue != null && !newValue.equals(oldValue))) {
for (CacheConfigurationListener listener : listeners) {
listener.maxBytesLocalHeapChanged(oldValue != null ? oldValue : 0, newValue);
}
}
}
private void fireMaxBytesOnLocalDiskChanged(final Long oldValue, final Long newValue) {
if ((oldValue != null && !oldValue.equals(newValue)) || (newValue != null && !newValue.equals(oldValue))) {
for (CacheConfigurationListener listener : listeners) {
listener.maxBytesLocalDiskChanged(oldValue != null ? oldValue : 0, newValue);
}
}
}
private void fireDynamicAttributesExtractorAdded(DynamicAttributesExtractor oldValue, DynamicAttributesExtractor newValue) {
if (oldValue != newValue) {
for (DynamicSearchListener lsnr : dynamicSearchListeners) {
lsnr.extractorChanged(oldValue, newValue);
}
}
}
/**
* Sets the maxOnHeap size
* @param amount the amount of unit
* @param memoryUnit the actual unit
* @return this
*/
public CacheConfiguration maxBytesLocalHeap(final long amount, final MemoryUnit memoryUnit) {
setMaxBytesLocalHeap(memoryUnit.toBytes(amount));
return this;
}
/**
* The maximum amount of bytes the cache should occupy off heap
* @return value in bytes, 0 if none set
*/
public long getMaxBytesLocalOffHeap() {
return maxBytesLocalOffHeap == null ? DEFAULT_MAX_BYTES_OFF_HEAP : maxBytesLocalOffHeap;
}
/**
* The string form of the maximum amount of bytes the cache should occupy off heap
* @return value as string in bytes
*/
public String getMaxBytesLocalOffHeapAsString() {
return maxBytesLocalOffHeapInput != null ? maxBytesLocalOffHeapInput : Long.toString(getMaxBytesLocalOffHeap());
}
/**
* Setter for maximum bytes off heap as a String. Value can have a one char unit suffix or be a percentage (ending in %)
*
* Changes to this property once the cache is operating will have no effect.
*
* @param maxBytesOffHeap String representation of the size, can be relative (in %)
*/
public void setMaxBytesLocalOffHeap(final String maxBytesOffHeap) {
assertArgumentNotNull("Cache maxBytesLocalOffHeap", maxBytesOffHeap);
if (isPercentage(maxBytesOffHeap)) {
maxBytesLocalOffHeapPercentage = parsePercentage(maxBytesOffHeap);
} else {
setMaxBytesLocalOffHeap(MemoryUnit.parseSizeInBytes(maxBytesOffHeap));
}
maxBytesLocalOffHeapInput = maxBytesOffHeap;
maxBytesLocalOffHeapExplicitlySet = true;
}
/**
* Getter for maximum bytes off heap expressed as a percentage
* @return percentage (between 0 and 100)
*/
public Integer getMaxBytesLocalOffHeapPercentage() {
return maxBytesLocalOffHeapPercentage;
}
/**
* Getter for maximum bytes on heap expressed as a percentage
* @return percentage (between 0 and 100)
*/
public Integer getMaxBytesLocalHeapPercentage() {
return maxBytesLocalHeapPercentage;
}
/**
* The string form of the maximum amount of bytes the cache should occupy on heap
* @return value as string in bytes
*/
public String getMaxBytesLocalHeapAsString() {
return maxBytesLocalHeapInput != null ? maxBytesLocalHeapInput : Long.toString(getMaxBytesLocalHeap());
}
/**
* Getter for maximum bytes on disk expressed as a percentage
* @return percentage (between 0 and 100)
*/
public Integer getMaxBytesLocalDiskPercentage() {
return maxBytesLocalDiskPercentage;
}
private int parsePercentage(final String stringValue) {
String trimmed = stringValue.trim();
int percentage = Integer.parseInt(trimmed.substring(0, trimmed.length() - 1));
if (percentage > HUNDRED_PERCENT || percentage < 0) {
throw new IllegalArgumentException("Percentage need values need to be between 0 and 100 inclusive, but got : " + percentage);
}
return percentage;
}
private boolean isPercentage(final String stringValue) {
String trimmed = stringValue.trim();
return trimmed.charAt(trimmed.length() - 1) == '%';
}
/**
* Sets the maximum amount of bytes the cache being configured will use on the OffHeap tier
*
* Changes to this property once the cache is operating will have no effect.
*
* @param maxBytesOffHeap max bytes on disk in bytes
*/
public void setMaxBytesLocalOffHeap(final Long maxBytesOffHeap) {
if (offHeapPoolUsage != null) {
throw new IllegalStateException("OffHeap can't be set dynamically!");
}
verifyGreaterThanZero(maxBytesOffHeap, "maxBytesLocalOffHeap");
this.maxBytesLocalOffHeapExplicitlySet = true;
this.maxBytesLocalOffHeap = maxBytesOffHeap;
}
/**
* Sets the maxOffHeap tier size
*
* Changes to this property once the cache is operating will have no effect.
*
* @param amount the amount of unit
* @param memoryUnit the actual unit
* @return this
*/
public CacheConfiguration maxBytesLocalOffHeap(final long amount, final MemoryUnit memoryUnit) {
setMaxBytesLocalOffHeap(memoryUnit.toBytes(amount));
return this;
}
/**
* The maximum amount of bytes the cache should occupy on disk
* @return value in bytes, 0 if none set
*/
public long getMaxBytesLocalDisk() {
return maxBytesLocalDisk == null ? DEFAULT_MAX_BYTES_ON_DISK : maxBytesLocalDisk;
}
/**
* The string form of the maximum amount of bytes the cache should occupy on disk
* @return value as string in bytes
*/
public String getMaxBytesLocalDiskAsString() {
return maxBytesLocalDiskInput != null ? maxBytesLocalDiskInput : Long.toString(getMaxBytesLocalDisk());
}
/**
* Setter for maxBytesOnDisk as a String. Value can have a one char unit suffix or be a percentage (ending in %)
*
* This property can be modified dynamically while the cache is operating.
*
* @param maxBytesDisk String representation of the size, can be relative (in %)
*/
public void setMaxBytesLocalDisk(final String maxBytesDisk) {
assertArgumentNotNull("Cache maxBytesLocalDisk", maxBytesDisk);
if (isPercentage(maxBytesDisk)) {
maxBytesLocalDiskPercentage = parsePercentage(maxBytesDisk);
} else {
setMaxBytesLocalDisk(MemoryUnit.parseSizeInBytes(maxBytesDisk));
}
maxBytesLocalDiskExplicitlySet = true;
maxBytesLocalDiskInput = maxBytesDisk;
}
/**
* Sets the maximum amount of bytes the cache being configured will use on the OnDisk tier
*
* This property can be modified dynamically while the cache is operating.
*
* @param maxBytesDisk max bytes on disk in bytes
*/
public void setMaxBytesLocalDisk(final Long maxBytesDisk) {
if (isTerracottaClustered()) {
throw new InvalidConfigurationException("MaxBytesLocalDisk is not applicable for Terracotta clustered caches");
}
if (onDiskPoolUsage != null && getMaxEntriesLocalDisk() > 0) {
throw new InvalidConfigurationException("MaxEntriesLocalDisk is not compatible with " +
"MaxBytesLocalDisk set on cache");
}
if (onDiskPoolUsage != null && onDiskPoolUsage != PoolUsage.Cache) {
throw new IllegalStateException("A Cache can't switch disk pool!");
}
checkDynamicChange();
verifyGreaterThanZero(maxBytesDisk, "maxBytesLocalDisk");
maxBytesLocalDiskExplicitlySet = true;
Long oldValue = this.maxBytesLocalDisk;
this.maxBytesLocalDisk = maxBytesDisk;
fireMaxBytesOnLocalDiskChanged(oldValue, maxBytesDisk);
}
/**
* Sets the maxOnDisk size
*
* This property can be modified dynamically while the cache is operating.
*
* @param amount the amount of unit
* @param memoryUnit the actual unit
* @return this
*/
public CacheConfiguration maxBytesLocalDisk(final long amount, final MemoryUnit memoryUnit) {
setMaxBytesLocalDisk(memoryUnit.toBytes(amount));
return this;
}
/**
* Sets dynamic search attributes extractor
* @param extractor extractor to use
*/
public void setDynamicAttributesExtractor(DynamicAttributesExtractor extractor) {
if (searchable == null || !searchable.isDynamicIndexingAllowed()) {
throw new IllegalArgumentException("Dynamic search attribute extraction not supported");
}
if (extractor == null && this.flexIndexer != null) {
throw new IllegalArgumentException("Dynamic search attributes extractor cannot be set to null by user");
}
DynamicAttributesExtractor old = this.flexIndexer;
this.flexIndexer = extractor;
fireDynamicAttributesExtractorAdded(old, this.flexIndexer);
}
/**
* Sets dynamic search attributes extractor
* @param extractor extractor to use
* @return this
*/
public CacheConfiguration dynamicAttributeExtractor(DynamicAttributesExtractor extractor) {
setDynamicAttributesExtractor(extractor);
return this;
}
private void verifyGreaterThanZero(final Long fieldVal, final String fieldName) {
if (fieldVal != null && fieldVal < 1) {
throw new IllegalArgumentException("Illegal value " + fieldVal + " for " + fieldName + ": has to be larger than 0");
}
}
private void verifyGreaterThanOrEqualToZero(final Long fieldVal, final String fieldName) {
if (fieldVal != null && fieldVal < 0) {
throw new IllegalArgumentException("Illegal value " + fieldVal + " for " + fieldName + ": has to be larger than or equal to 0");
}
}
/**
* Returns the copyStrategyConfiguration
*
* @return the copyStrategyConfiguration
*/
public CopyStrategyConfiguration getCopyStrategyConfiguration() {
return this.copyStrategyConfiguration;
}
/**
* Returns the elementComparatorConfiguration
*
* @return the elementComparatorConfiguration
*/
public ElementValueComparatorConfiguration getElementValueComparatorConfiguration() {
return elementValueComparatorConfiguration;
}
/**
* Checks whether the user explicitly set the maxBytesOnHeapPercentage
* @return true if set by user, false otherwise
* @see #setMaxBytesLocalHeap(String)
*/
public boolean isMaxBytesLocalHeapPercentageSet() {
return maxBytesLocalHeapPercentage != null;
}
/**
* Checks whether the user explicitly set the maxBytesOffHeapPercentage
* @return true if set by user, false otherwise
* @see #setMaxBytesLocalOffHeap(String)
*/
public boolean isMaxBytesLocalOffHeapPercentageSet() {
return maxBytesLocalOffHeapPercentage != null;
}
/**
* Checks whether the user explicitly set the maxBytesOnDiskPercentage
* @return true if set by user, false otherwise
* @see #setMaxBytesLocalDisk(String)
*/
public boolean isMaxBytesLocalDiskPercentageSet() {
return maxBytesLocalDiskPercentage != null;
}
/**
* Sets up the CacheConfiguration for runtime consumption, also registers this cache configuration with the cache manager's configuration
* @param cacheManager The CacheManager as part of which the cache is being setup
*/
public void setupFor(final CacheManager cacheManager) {
setupFor(cacheManager, true, null);
}
/**
* Sets up the CacheConfiguration for runtime consumption
* @param cacheManager The CacheManager as part of which the cache is being setup
* @param register true to register this cache configuration with the cache manager.
*/
public void setupFor(final CacheManager cacheManager, final boolean register, final String parentCache) {
final Collection errors = validate(cacheManager.getConfiguration());
configCachePools(cacheManager.getConfiguration());
errors.addAll(verifyPoolAllocationsBeforeAddingTo(cacheManager,
cacheManager.getConfiguration().getMaxBytesLocalHeap(),
cacheManager.getConfiguration().getMaxBytesLocalOffHeap(),
cacheManager.getConfiguration().getMaxBytesLocalDisk(), parentCache));
if (!errors.isEmpty()) {
throw new InvalidConfigurationException(errors);
}
if (!isTerracottaClustered()) {
updateCacheManagerPoolSizes(cacheManager);
}
if (register) {
registerCacheConfiguration(cacheManager);
}
if (cacheManager.getConfiguration().isMaxBytesLocalHeapSet() || cacheManager.getConfiguration().isMaxBytesLocalDiskSet()) {
/*Adding Ourself as the first listener the order of the listener is
important as DefaultCacheConfigurationListener does validation checking on pool sizes*/
addConfigurationListener(new DefaultCacheConfigurationListener(cacheManager));
}
consolidatePersistenceSettings(cacheManager);
if (overflowToOffHeap == null && (cacheManager.getConfiguration().isMaxBytesLocalOffHeapSet() || getMaxBytesLocalOffHeap() > 0)) {
overflowToOffHeap = true;
}
if ((persistenceConfiguration != null && Strategy.LOCALTEMPSWAP.equals(persistenceConfiguration.getStrategy()))) {
overflowToDisk = true;
}
if (overflowToDisk == null && cacheManager.getConfiguration().isMaxBytesLocalDiskSet() || getMaxBytesLocalDisk() > 0) {
if (persistenceConfiguration != null && Strategy.LOCALRESTARTABLE.equals(persistenceConfiguration.getStrategy())) {
throw new InvalidConfigurationException("Cannot use localRestartable persistence and disk overflow in the same cache");
} else if (!isTerracottaClustered()) {
overflowToDisk = true;
} else {
LOG.warn("Clustered cache " + getName() + " will not use the local disk pool defined at cache manager level.");
}
}
warnMaxEntriesLocalHeap(register, cacheManager);
warnMaxEntriesForOverflowToOffHeap(register);
warnSizeOfPolicyConfiguration();
freezePoolUsages(cacheManager);
warnTieredSizing();
}
private void consolidatePersistenceSettings(CacheManager manager) {
if (persistenceConfiguration == null) {
if (diskPersistent == Boolean.TRUE) {
persistenceConfiguration = new PersistenceConfiguration().strategy(Strategy.LOCALTEMPSWAP);
}
} else {
switch (persistenceConfiguration.getStrategy()) {
case DISTRIBUTED:
case NONE:
diskPersistent = Boolean.FALSE;
break;
case LOCALTEMPSWAP:
if (diskPersistent == null) {
diskPersistent = Boolean.FALSE;
}
break;
case LOCALRESTARTABLE:
diskPersistent = Boolean.TRUE;
break;
default:
break;
}
}
if (persistenceConfiguration != null && persistenceConfiguration.getSynchronousWrites()) {
switch (persistenceConfiguration.getStrategy()) {
case NONE:
case LOCALTEMPSWAP:
throw new InvalidConfigurationException("Persistence: synchronousWrites=\"true\" is not supported "
+ "with strategy \"localTempSwap\" or \"none\"");
default:
break;
}
}
}
private void warnMaxEntriesForOverflowToOffHeap(final boolean register) {
if (overflowToOffHeap != null && overflowToOffHeap && register) {
if (getMaxEntriesLocalHeap() > 0 && getMaxEntriesLocalHeap() < MINIMUM_RECOMMENDED_IN_MEMORY) {
LOG.warn("The " + getName() + " cache is configured for off-heap and has a maxEntriesLocalHeap/maxElementsInMemory of "
+ getMaxEntriesLocalHeap() + ". It is recommended to set maxEntriesLocalHeap/maxElementsInMemory to at least "
+ MINIMUM_RECOMMENDED_IN_MEMORY + " elements when using an off-heap store, otherwise performance "
+ "will be seriously degraded.");
}
}
}
private void warnMaxEntriesLocalHeap(final boolean register, CacheManager cacheManager) {
if (getMaxEntriesLocalHeap() == 0 && register) {
if (getMaxBytesLocalHeap() == 0 && (!cacheManager.getConfiguration().isMaxBytesLocalHeapSet())) {
LOG.warn("Cache: " + getName() +
" has a maxElementsInMemory of 0. This might lead to performance degradation or OutOfMemoryError at Terracotta client." +
"From Ehcache 2.0 onwards this has been changed to mean a store" +
" with no capacity limit. Set it to 1 if you want" +
" no elements cached in memory");
}
}
}
private void warnSizeOfPolicyConfiguration() {
if (isTerracottaClustered() && getSizeOfPolicyConfiguration() != null) {
LOG.warn("Terracotta clustered cache: " + getName() + " has a sizeOf policy configuration specificed. " +
"SizeOfPolicyConfiguration is unsupported for Terracotta clustered caches.");
}
}
private void freezePoolUsages(final CacheManager cacheManager) {
if (getMaxBytesLocalHeap() > 0) {
onHeapPoolUsage = CacheConfiguration.PoolUsage.Cache;
} else if (cacheManager.getConfiguration().isMaxBytesLocalHeapSet()) {
onHeapPoolUsage = CacheConfiguration.PoolUsage.CacheManager;
} else {
onHeapPoolUsage = CacheConfiguration.PoolUsage.None;
}
if (getMaxBytesLocalOffHeap() > 0) {
offHeapPoolUsage = CacheConfiguration.PoolUsage.Cache;
} else if (cacheManager.getConfiguration().isMaxBytesLocalOffHeapSet()) {
offHeapPoolUsage = CacheConfiguration.PoolUsage.CacheManager;
} else {
offHeapPoolUsage = CacheConfiguration.PoolUsage.None;
}
if (isTerracottaClustered()) {
onDiskPoolUsage = CacheConfiguration.PoolUsage.None;
} else {
if (getMaxBytesLocalDisk() > 0) {
onDiskPoolUsage = CacheConfiguration.PoolUsage.Cache;
} else if (cacheManager.getConfiguration().isMaxBytesLocalDiskSet()) {
onDiskPoolUsage = CacheConfiguration.PoolUsage.CacheManager;
} else {
onDiskPoolUsage = CacheConfiguration.PoolUsage.None;
}
}
}
private void warnTieredSizing() {
if (isOverflowToOffHeap()) {
if (getMaxBytesLocalHeap() >= getMaxBytesLocalOffHeap() && getMaxBytesLocalOffHeap() != 0) {
LOG.warn("Configuration problem for cache " + getName() + ": MaxBytesLocalHeap equal or greater than MaxBytesLocalOffHeap. " +
"This will result in useless off heap storage.");
}
if (isOverflowToDisk()) {
if (getMaxBytesLocalOffHeap() >= getMaxBytesLocalDisk() && getMaxBytesLocalDisk() != 0) {
LOG.warn("Configuration problem for cache " + getName() + ": MaxBytesLocalOffHeap equal or greater than MaxBytesLocalDisk. " +
"This will result in useless disk storage.");
}
}
}
if (isOverflowToDisk()) {
if (getMaxEntriesLocalHeap() >= getMaxEntriesLocalDisk() && getMaxEntriesLocalDisk() != 0) {
LOG.warn("Configuration problem for cache " + getName() + ": MaxEntriesLocalHeap equal or greater than MaxEntriesLocalDisk. " +
"This will result in useless disk storage.");
}
}
}
private void registerCacheConfiguration(final CacheManager cacheManager) {
Map configMap = cacheManager.getConfiguration().getCacheConfigurations();
if (!configMap.containsKey(getName())) {
cacheManager.getConfiguration().addCache(this, false);
}
}
private void updateCacheManagerPoolSizes(final CacheManager cacheManager) {
if (cacheManager.getOnHeapPool() != null) {
cacheManager.getOnHeapPool().setMaxSize(cacheManager.getOnHeapPool().getMaxSize() - getMaxBytesLocalHeap());
}
if (cacheManager.getOnDiskPool() != null) {
cacheManager.getOnDiskPool().setMaxSize(cacheManager.getOnDiskPool().getMaxSize() - getMaxBytesLocalDisk());
}
}
/**
* Will verify that we don't overallocate pools
* @param cacheManager The cacheManager that will manage the cache
* @param managerMaxBytesLocalHeap bytes for local heap
* @param managerMaxBytesLocalOffHeap bytes for local offheap
* @param managerMaxBytesLocalDisk bytes for local disk
* @param parentCacheName cacheName for parentCache to be used when initializing shadow caches
* @return a list with potential errors
*/
List verifyPoolAllocationsBeforeAddingTo(CacheManager cacheManager,
long managerMaxBytesLocalHeap,
long managerMaxBytesLocalOffHeap,
long managerMaxBytesLocalDisk,
String parentCacheName) {
final List configErrors = new ArrayList();
long totalOnHeapAssignedMemory = 0;
long totalOffHeapAssignedMemory = 0;
long totalOnDiskAssignedMemory = 0;
boolean isUpdate = false;
for (Cache cache : getAllActiveCaches(cacheManager)) {
if (cache.getName().equals(parentCacheName)) {
// Do not add parent cache when calculating memory requirements for shadow cache.
continue;
}
isUpdate = cache.getName().equals(getName()) || isUpdate;
final CacheConfiguration config = cache.getCacheConfiguration();
totalOnHeapAssignedMemory += config.getMaxBytesLocalHeap();
totalOffHeapAssignedMemory += config.getMaxBytesLocalOffHeap();
totalOnDiskAssignedMemory += config.getMaxBytesLocalDisk();
}
if (!isUpdate) {
totalOnHeapAssignedMemory += getMaxBytesLocalHeap();
totalOffHeapAssignedMemory += getMaxBytesLocalOffHeap();
totalOnDiskAssignedMemory += getMaxBytesLocalDisk();
}
verifyLocalHeap(managerMaxBytesLocalHeap, configErrors, totalOnHeapAssignedMemory);
verifyLocalOffHeap(managerMaxBytesLocalOffHeap, configErrors, totalOffHeapAssignedMemory);
verifyLocalDisk(managerMaxBytesLocalDisk, configErrors, totalOnDiskAssignedMemory);
if (managerMaxBytesLocalHeap > 0 && managerMaxBytesLocalHeap - totalOnHeapAssignedMemory == 0) {
LOG.warn("All the onHeap memory has been assigned, there is none left for dynamically added caches");
}
if (Runtime.getRuntime().maxMemory() - totalOnHeapAssignedMemory < 0) {
// todo this could be a nicer message (with actual values)
configErrors.add(new ConfigError("You've assigned more memory to the on-heap than the VM can sustain, " +
"please adjust your -Xmx setting accordingly"));
}
if (totalOnHeapAssignedMemory / (float) Runtime.getRuntime().maxMemory() > CacheManager.ON_HEAP_THRESHOLD) {
LOG.warn("You've assigned over 80% of your VM's heap to be used by the cache!");
}
return configErrors;
}
private void verifyLocalDisk(final long managerMaxBytesLocalDisk,
final List configErrors, final long totalOnDiskAssignedMemory) {
if ((isMaxBytesLocalDiskPercentageSet() || getMaxBytesLocalDisk() > 0)
&& managerMaxBytesLocalDisk > 0 && managerMaxBytesLocalDisk - totalOnDiskAssignedMemory < 0) {
configErrors.add(new ConfigError("Cache '" + getName()
+ "' over-allocates CacheManager's localOnDisk limit!"));
}
}
private void verifyLocalOffHeap(final long managerMaxBytesLocalOffHeap,
final List configErrors, final long totalOffHeapAssignedMemory) {
if ((isMaxBytesLocalOffHeapPercentageSet() || getMaxBytesLocalOffHeap() > 0)
&& managerMaxBytesLocalOffHeap > 0 && managerMaxBytesLocalOffHeap - totalOffHeapAssignedMemory < 0) {
configErrors.add(new ConfigError("Cache '" + getName()
+ "' over-allocates CacheManager's localOffHeap limit!"));
}
}
private void verifyLocalHeap(final long managerMaxBytesLocalHeap,
final List configErrors, final long totalOnHeapAssignedMemory) {
if ((isMaxBytesLocalHeapPercentageSet() || getMaxBytesLocalHeap() > 0)
&& managerMaxBytesLocalHeap > 0 && managerMaxBytesLocalHeap - totalOnHeapAssignedMemory < 0) {
configErrors.add(new ConfigError("Cache '" + getName()
+ "' over-allocates CacheManager's localOnHeap limit!"));
}
}
/**
* Configures the cache pools
* @param configuration the Configuration of the CacheManager managing this cache
*/
void configCachePools(Configuration configuration) {
long cacheAssignedMem;
if (getMaxBytesLocalHeapPercentage() != null) {
cacheAssignedMem = configuration.getMaxBytesLocalHeap() * getMaxBytesLocalHeapPercentage() / HUNDRED_PERCENT;
setMaxBytesLocalHeap(cacheAssignedMem);
}
if (offHeapPoolUsage == null && getMaxBytesLocalOffHeapPercentage() != null) {
cacheAssignedMem = configuration.getMaxBytesLocalOffHeap() * getMaxBytesLocalOffHeapPercentage() / HUNDRED_PERCENT;
setMaxBytesLocalOffHeap(cacheAssignedMem);
}
if (getMaxBytesLocalDiskPercentage() != null) {
cacheAssignedMem = configuration.getMaxBytesLocalDisk() * getMaxBytesLocalDiskPercentage() / HUNDRED_PERCENT;
setMaxBytesLocalDisk(cacheAssignedMem);
}
}
/**
* Validates the configuration
* @param configuration the CacheManager configuration this is going to be used with
* @return the errors in the config
*/
public Collection validate(final Configuration configuration) {
final Collection errors = new ArrayList();
verifyClusteredCacheConfiguration(errors);
if (maxEntriesLocalHeap == null && !configuration.isMaxBytesLocalHeapSet() && maxBytesLocalHeap == null) {
errors.add(new CacheConfigError("If your CacheManager has no maxBytesLocalHeap set, you need to either set " +
"maxEntriesLocalHeap or maxBytesLocalHeap at the Cache level", getName()));
}
if (configuration.isMaxBytesLocalHeapSet() && Runtime.getRuntime().maxMemory() - configuration.getMaxBytesLocalHeap() < 0) {
errors.add(new ConfigError("You've assigned more memory to the on-heap than the VM can sustain, " +
"please adjust your -Xmx setting accordingly"));
}
if (maxEntriesInCache != DEFAULT_MAX_ENTRIES_IN_CACHE) {
if (!isTerracottaClustered()) {
errors.add(new CacheConfigError("maxEntriesInCache is not applicable to unclustered caches.", getName()));
}
}
//commenting this check until fixed for cachemanger is fixed
//if (isOverflowToOffHeapSet() && !maxBytesLocalOffHeapExplicitlySet) {
// errors.add(new CacheConfigError("\"overFlowToOffHeap\" is set, but \"maxBytesLocalOffHeap\" is not set.", getName()));
//}
if (persistenceConfiguration != null && persistenceConfiguration.getStrategy() == null) {
errors.add(new CacheConfigError("Persistence configuration found with no strategy set.", getName()));
}
errors.addAll(validateCachePools(configuration));
return errors;
}
private void verifyClusteredCacheConfiguration(final Collection errors) {
if (!isTerracottaClustered()) { return; }
if (getPinningConfiguration() != null && getPinningConfiguration().getStore() == PinningConfiguration.Store.INCACHE
&& getMaxElementsOnDisk() != 0) {
errors.add(new CacheConfigError("maxElementsOnDisk may not be used on a pinned cache.", getName()));
}
if (maxEntriesLocalDiskExplicitlySet) {
errors.add(new CacheConfigError("You can't set maxEntriesLocalDisk when clustering your cache with Terracotta, " +
"local disks won't be used! To control elements going in the cache cluster wide, " +
"use maxEntriesInCache instead", getName()));
}
if (maxBytesLocalDiskExplicitlySet) {
errors.add(new CacheConfigError("You can't set maxBytesLocalDisk when clustering your cache with Terracotta",
getName()));
}
if (maxElementsOnDisk != DEFAULT_MAX_ELEMENTS_ON_DISK) {
errors.add(new CacheConfigError("maxElementsOnDisk is not used with clustered caches. Use maxEntriesInCache " +
"to set maximum cache size.", getName()));
}
}
/**
* Validates the CacheConfiguration against the CacheManager's Configuration
* @param configuration The CacheManager Configuration
* @return the list of errors encountered, or an empty list
*/
List validateCachePools(final Configuration configuration) {
List errors = new ArrayList();
if (configuration.isMaxBytesLocalHeapSet()
&& getMaxEntriesLocalHeap() > 0) {
errors.add(new CacheConfigError("maxEntriesLocalHeap is not compatible with " +
"maxBytesLocalHeap set on cache manager", getName()));
}
if (getMaxBytesLocalHeap() > 0 && getMaxEntriesLocalHeap() > 0) {
errors.add(new CacheConfigError("maxEntriesLocalHeap is not compatible with " +
"maxBytesLocalHeap set on cache", getName()));
}
if (isMaxBytesLocalHeapPercentageSet() && !configuration.isMaxBytesLocalHeapSet()) {
errors.add(new CacheConfigError("Defines a percentage maxBytesOnHeap value but no CacheManager " +
"wide value was configured", getName()));
}
if (isMaxBytesLocalOffHeapPercentageSet() && !configuration.isMaxBytesLocalOffHeapSet()) {
errors.add(new CacheConfigError("Defines a percentage maxBytesOffHeap value but no CacheManager " +
"wide value was configured", getName()));
}
if (isMaxBytesLocalDiskPercentageSet() && !configuration.isMaxBytesLocalDiskSet()) {
errors.add(new CacheConfigError("Defines a percentage maxBytesOnDisk value but no CacheManager " +
"wide value was configured", getName()));
}
return errors;
}
/**
* Whether this cache is Count based
* @return true if maxEntries set, false otherwise
*/
public boolean isCountBasedTuned() {
return (maxEntriesLocalHeap != null && maxEntriesLocalHeap > 0) || maxElementsOnDisk > 0;
}
/**
* Checks whether the overflowing to off heap behavior was explicitly set
* @return true if explicitly set, false otherwise
*/
public boolean isOverflowToOffHeapSet() {
return overflowToOffHeap != null;
}
/**
* Configuration for the CacheEventListenerFactory.
*/
public static final class CacheEventListenerFactoryConfiguration extends FactoryConfiguration {
private NotificationScope notificationScope = NotificationScope.ALL;
/**
* Used by BeanHandler to set the mode during parsing. Convert listenFor string to uppercase and
* look up enum constant in NotificationScope.
*/
public void setListenFor(String listenFor) {
if (listenFor == null) {
throw new IllegalArgumentException("listenFor must be non-null");
}
this.notificationScope = NotificationScope.valueOf(NotificationScope.class, listenFor.toUpperCase());
}
/**
* @return this factory configuration instance
* @see #setListenFor(String)
*/
public final CacheEventListenerFactoryConfiguration listenFor(String listenFor) {
setListenFor(listenFor);
return this;
}
/**
* Get the value mode in terms of the mode enum
*/
public NotificationScope getListenFor() {
return this.notificationScope;
}
}
/**
* Used by BeanUtils to add cacheEventListenerFactory elements to the cache configuration.
*/
public final void addCacheEventListenerFactory(CacheEventListenerFactoryConfiguration factory) {
checkDynamicChange();
cacheEventListenerConfigurations.add(factory);
validateConfiguration();
}
/**
* @return this configuration instance
* @see #addCacheEventListenerFactory(CacheEventListenerFactoryConfiguration)
*/
public final CacheConfiguration cacheEventListenerFactory(CacheEventListenerFactoryConfiguration factory) {
addCacheEventListenerFactory(factory);
return this;
}
/**
* Configuration for the CacheExtensionFactoryConfiguration.
*/
public static final class CacheExtensionFactoryConfiguration extends FactoryConfiguration {
}
/**
* Used by BeanUtils to add cacheExtensionFactory elements to the cache configuration.
*/
public final void addCacheExtensionFactory(CacheExtensionFactoryConfiguration factory) {
checkDynamicChange();
cacheExtensionConfigurations.add(factory);
}
/**
* @return this configuration instance
* @see #addCacheExtensionFactory(CacheExtensionFactoryConfiguration)
*/
public final CacheConfiguration cacheExtensionFactory(CacheExtensionFactoryConfiguration factory) {
/**
* {@inheritDoc}
*/
addCacheExtensionFactory(factory);
return this;
}
/**
* Configuration for the BootstrapCacheLoaderFactoryConfiguration.
*/
public static final class BootstrapCacheLoaderFactoryConfiguration extends
FactoryConfiguration {
}
/**
* Allows BeanHandler to add the CacheManagerEventListener to the configuration.
*/
public final void addBootstrapCacheLoaderFactory(BootstrapCacheLoaderFactoryConfiguration factory) {
checkDynamicChange();
this.bootstrapCacheLoaderFactoryConfiguration = factory;
}
/**
* @return this configuration instance
* @see #addBootstrapCacheLoaderFactory(BootstrapCacheLoaderFactoryConfiguration)
*/
public final CacheConfiguration bootstrapCacheLoaderFactory(BootstrapCacheLoaderFactoryConfiguration factory) {
addBootstrapCacheLoaderFactory(factory);
return this;
}
/**
* Configuration for the BootstrapCacheLoaderFactoryConfiguration.
*/
public static final class CacheExceptionHandlerFactoryConfiguration extends
FactoryConfiguration {
}
/**
* Add the CacheExceptionHandlerFactory to the configuration.
*
* Note that this will not have any effect when creating a cache solely through its constructed. The exception
* handler will only be taken into account when {@link ConfigurationHelper} is used, for example through
* {@link net.sf.ehcache.CacheManager}.
*/
public final void addCacheExceptionHandlerFactory(CacheExceptionHandlerFactoryConfiguration factory) {
checkDynamicChange();
this.cacheExceptionHandlerFactoryConfiguration = factory;
}
/**
* @return this configuration instance
* @see #addCacheExceptionHandlerFactory(CacheExceptionHandlerFactoryConfiguration)
*/
public final CacheConfiguration cacheExceptionHandlerFactory(CacheExceptionHandlerFactoryConfiguration factory) {
addCacheExceptionHandlerFactory(factory);
return this;
}
/**
* Configuration for the CacheLoaderFactoryConfiguration.
*/
public static final class CacheLoaderFactoryConfiguration extends FactoryConfiguration {
}
/**
* Used by BeanUtils to add each cacheLoaderFactory to the cache configuration.
*
* @param factory
*/
public final void addCacheLoaderFactory(CacheLoaderFactoryConfiguration factory) {
checkDynamicChange();
cacheLoaderConfigurations.add(factory);
}
/**
* Configuration for the CacheDecoratorFactoryConfiguration.
*/
public static final class CacheDecoratorFactoryConfiguration extends FactoryConfiguration {
}
/**
* Used by BeanUtils to add each cacheDecoratorFactory to the cache configuration.
*
* @param factory
*/
public final void addCacheDecoratorFactory(CacheDecoratorFactoryConfiguration factory) {
checkDynamicChange();
cacheDecoratorConfigurations.add(factory);
}
/**
* @return this configuration instance
* @see #addCacheLoaderFactory(CacheLoaderFactoryConfiguration)
*/
public final CacheConfiguration cacheLoaderFactory(CacheLoaderFactoryConfiguration factory) {
addCacheLoaderFactory(factory);
return this;
}
/**
* Allows BeanHandler to add the TerracottaConfiguration to the configuration.
*/
public final void addTerracotta(TerracottaConfiguration terracottaConfiguration) {
this.terracottaConfiguration = terracottaConfiguration;
validateConfiguration();
}
/**
* Allows BeanHandler to add the PinningConfiguration to the configuration.
*/
public final void addPinning(PinningConfiguration pinningConfiguration) {
this.pinningConfiguration = pinningConfiguration;
validateConfiguration();
}
/**
* @return this configuration instance
* @see #addPinning(PinningConfiguration)
*/
public final CacheConfiguration pinning(PinningConfiguration pinningConfiguration) {
addPinning(pinningConfiguration);
return this;
}
/**
* @return this configuration instance
* @see #addTerracotta(TerracottaConfiguration)
*/
public final CacheConfiguration terracotta(TerracottaConfiguration terracottaConfiguration) {
addTerracotta(terracottaConfiguration);
return this;
}
/**
* @see #addSearchable(Searchable)
* @param searchable
* @return this
*/
public final CacheConfiguration searchable(Searchable searchable) {
addSearchable(searchable);
return this;
}
/**
* Allows BeanHandler to add the CacheWriterConfiguration to the configuration.
*/
public final void addCacheWriter(CacheWriterConfiguration cacheWriterConfiguration) {
if (null == cacheWriterConfiguration) {
this.cacheWriterConfiguration = new CacheWriterConfiguration();
} else {
this.cacheWriterConfiguration = cacheWriterConfiguration;
}
}
/**
* @return this configuration instance
* @see #addCacheWriter(CacheWriterConfiguration)
*/
public final CacheConfiguration cacheWriter(CacheWriterConfiguration cacheWriterConfiguration) {
addCacheWriter(cacheWriterConfiguration);
return this;
}
/**
* Sets the transactionalMode
*
* @param transactionalMode one of OFF, LOCAL, XA, XA_STRICT
*/
public final void setTransactionalMode(final String transactionalMode) {
assertArgumentNotNull("Cache transactionalMode", transactionalMode);
transactionalMode(TransactionalMode.valueOf(transactionalMode.toUpperCase()));
}
/**
* Builder which sets the transactionalMode
*
* @param transactionalMode one of OFF, LOCAL, XA, XA_STRICT
* @return this configuration instance
* @see #setTransactionalMode(String)
*/
public final CacheConfiguration transactionalMode(String transactionalMode) {
setTransactionalMode(transactionalMode);
return this;
}
/**
* Builder which sets the transactionalMode
*
* @param transactionalMode one of OFF, LOCAL, XA, XA_STRICT
* @return this configuration instance
* @see #setTransactionalMode(String)
*/
public final CacheConfiguration transactionalMode(TransactionalMode transactionalMode) {
if (transactionalMode == null) {
throw new IllegalArgumentException("TransactionalMode value must be non-null");
}
if (this.transactionalMode != null) {
throw new InvalidConfigurationException("transactionalMode cannot be changed once set");
}
this.transactionalMode = transactionalMode;
return this;
}
/**
* Sets whether the cache's statistics are enabled. at startup
*/
@Deprecated
public final void setStatistics(boolean enabled) {
if (!enabled) {
LOG.warn("Statistics can no longer be enabled via configuration.");
return;
}
this.statistics = enabled;
}
/**
* Builder which sets whether the cache's statistics are enabled.
*
* @return this configuration instance
* @see #setStatistics(boolean)
*/
@Deprecated
public final CacheConfiguration statistics(boolean statistics) {
setStatistics(statistics);
return this;
}
/**
* Gets whether the cache's statistics will be enabled at startup
*/
public final boolean getStatistics() {
return true;
}
/**
* Used to validate what should be a complete Cache Configuration.
*/
public void validateCompleteConfiguration() {
validateConfiguration();
// Extra checks that a completed cache config should have
if (name == null) {
throw new InvalidConfigurationException("Caches must be named.");
}
}
/**
* Used to validate a Cache Configuration.
*/
public void validateConfiguration() {
if (terracottaConfiguration != null && terracottaConfiguration.isClustered()) {
if (overflowToDisk != null && overflowToDisk) {
throw new InvalidConfigurationException("overflowToDisk isn't supported for a clustered Terracotta cache");
}
if (diskPersistent == Boolean.TRUE) {
throw new InvalidConfigurationException("diskPersistent isn't supported for a clustered Terracotta cache");
}
if (persistenceConfiguration != null && !Strategy.DISTRIBUTED.equals(persistenceConfiguration.getStrategy())) {
throw new InvalidConfigurationException(persistenceConfiguration.getStrategy() +
" persistence strategy isn't supported for a clustered Terracotta cache");
}
if (cacheEventListenerConfigurations != null) {
for (CacheEventListenerFactoryConfiguration listenerConfig : cacheEventListenerConfigurations) {
if (null == listenerConfig.getFullyQualifiedClassPath()) {
continue;
}
if (!listenerConfig.getFullyQualifiedClassPath().startsWith("net.sf.ehcache.") &&
LOG.isWarnEnabled()) {
LOG.warn("The non-standard CacheEventListenerFactory '" + listenerConfig.getFullyQualifiedClassPath() +
"' is used with a clustered Terracotta cache, " +
"if the purpose of this listener is replication it is not supported in a clustered context");
}
}
}
}
if (cacheWriterConfiguration != null) {
if (!cacheWriterConfiguration.getWriteBatching() && cacheWriterConfiguration.getWriteBatchSize() != 1) {
throw new InvalidConfigurationException("CacheWriter Batch Size !=1 and CacheWriter Batching " +
"turned off");
}
}
}
private void validateTransactionalSettings() {
boolean transactional = getTransactionalMode().isTransactional();
if (copyOnRead == null) {
if (terracottaConfiguration != null && terracottaConfiguration.isCopyOnReadSet()) {
copyOnRead = terracottaConfiguration.isCopyOnRead();
} else {
copyOnRead = transactional;
}
}
if (copyOnWrite == null) {
copyOnWrite = transactional;
}
if (transactional) {
if (!copyOnRead || !copyOnWrite) {
throw new InvalidConfigurationException("A transactional cache has to be copyOnRead and copyOnWrite!");
}
}
}
/**
* Accessor
*/
public String getName() {
return name;
}
/**
* Accessor
*
* @deprecated use {@link #getMaxEntriesLocalHeap()}
*/
@Deprecated
public int getMaxElementsInMemory() {
return (int)getMaxEntriesLocalHeap();
}
/**
* Accessor
*/
public long getCacheLoaderTimeoutMillis() {
return cacheLoaderTimeoutMillis;
}
/**
* Accessor
* @deprecated use {@link #getMaxEntriesLocalDisk()} for unclustered caches and {@link #getMaxEntriesInCache()} for clustered caches.
*/
public int getMaxElementsOnDisk() {
return maxElementsOnDisk;
}
/**
* Accessor
*
*/
public long getMaxEntriesInCache() {
return maxEntriesInCache;
}
/**
* Configured maximum number of entries for the local disk store.
*/
public long getMaxEntriesLocalDisk() {
return maxElementsOnDisk;
}
/**
* Configured maximum number of entries for the local memory heap.
*/
public long getMaxEntriesLocalHeap() {
return maxEntriesLocalHeap == null ? 0 : maxEntriesLocalHeap;
}
/**
* Accessor
*/
public MemoryStoreEvictionPolicy getMemoryStoreEvictionPolicy() {
return memoryStoreEvictionPolicy;
}
/**
* Accessor
*/
public boolean isClearOnFlush() {
return clearOnFlush;
}
/**
* Accessor
*/
public boolean isEternal() {
return eternal;
}
/**
* Accessor
*/
public long getTimeToIdleSeconds() {
return timeToIdleSeconds;
}
/**
* Accessor
*/
public long getTimeToLiveSeconds() {
return timeToLiveSeconds;
}
/**
* Accessor
*
* @deprecated The {@code overflowToDisk} attribute has been replaced with {@link Strategy#LOCALTEMPSWAP}.
*/
@Deprecated
public boolean isOverflowToDisk() {
return overflowToDisk == null ? false : overflowToDisk;
}
/**
* Accessor
*
* @deprecated The {@code diskPersistent} attribute has been replaced with {@link #persistence(PersistenceConfiguration)}.
*/
@Deprecated
public boolean isDiskPersistent() {
Boolean persistent = diskPersistent;
return diskPersistent == null ? DEFAULT_DISK_PERSISTENT : persistent;
}
/**
* Accessor
*/
public boolean isSearchable() {
return searchable != null;
}
/**
* Accessor
*/
public int getDiskSpoolBufferSizeMB() {
return diskSpoolBufferSizeMB;
}
/**
* Accessor
*/
public long getDiskExpiryThreadIntervalSeconds() {
return diskExpiryThreadIntervalSeconds;
}
/**
* Accessor
*/
public int getDiskAccessStripes() {
return diskAccessStripes;
}
/**
* Accessor
*/
public DynamicAttributesExtractor getDynamicExtractor() {
return flexIndexer;
}
/**
* Only used when cache is clustered with Terracotta
*
* @return true if logging is enabled otherwise false
*/
public boolean getLogging() {
return logging;
}
/**
* Accessor
*
* @return true if offheap store is enabled, otherwise false.
*/
public boolean isOverflowToOffHeap() {
return overflowToOffHeap == null ? false : overflowToOffHeap;
}
/**
* Accessor
*
* @return the SizeOfPolicy Configuration for this cache.
*/
public SizeOfPolicyConfiguration getSizeOfPolicyConfiguration() {
return sizeOfPolicyConfiguration;
}
/**
* Accessor
*
* @return the persistence configuration for this cache.
*/
public PersistenceConfiguration getPersistenceConfiguration() {
return persistenceConfiguration;
}
/**
* Accessor
*
* @return the max memory of the offheap store for this cache.
* @deprecated See {@link #getMaxBytesLocalOffHeapAsString()}
*/
@Deprecated
public String getMaxMemoryOffHeap() {
return maxBytesLocalOffHeapInput;
}
/**
* Accessor
*
* @return the max memory of the offheap store for this cache, in bytes.
* @deprecated {@link #getMaxBytesLocalOffHeap()}
*/
@Deprecated
public long getMaxMemoryOffHeapInBytes() {
return getMaxBytesLocalOffHeap();
}
/**
* Accessor
*/
public List getCacheEventListenerConfigurations() {
return cacheEventListenerConfigurations;
}
/**
* Accessor
*
* @return the configuration
*/
public List getCacheExtensionConfigurations() {
return cacheExtensionConfigurations;
}
/**
* Accessor
*
* @return the configuration
*/
public List getCacheLoaderConfigurations() {
return cacheLoaderConfigurations;
}
/**
* Accessor
*
* @return the configuration
*/
public List getCacheDecoratorConfigurations() {
return cacheDecoratorConfigurations;
}
/**
* Accessor
*
* @return the configuration
*/
public BootstrapCacheLoaderFactoryConfiguration getBootstrapCacheLoaderFactoryConfiguration() {
return bootstrapCacheLoaderFactoryConfiguration;
}
/**
* Accessor
*
* @return the configuration
*/
public CacheExceptionHandlerFactoryConfiguration getCacheExceptionHandlerFactoryConfiguration() {
return cacheExceptionHandlerFactoryConfiguration;
}
/**
* Accessor
*
* @return the terracotta configuration
*/
public TerracottaConfiguration getTerracottaConfiguration() {
return terracottaConfiguration;
}
/**
* Accessor
*
* @return the pinning configuration
*/
public PinningConfiguration getPinningConfiguration() {
return pinningConfiguration;
}
/**
* Accessor
*
* @return the writer configuration
*/
public CacheWriterConfiguration getCacheWriterConfiguration() {
return cacheWriterConfiguration;
}
/**
* Helper method to compute whether the cache is clustered or not
*
* @return True if the <terracotta/> element exists with {@code clustered="true"}
*/
public boolean isTerracottaClustered() {
return terracottaConfiguration != null && terracottaConfiguration.isClustered();
}
/**
* Accessor
*
* @return the CoherenceMode if Terracotta-clustered or null
*/
public Consistency getTerracottaConsistency() {
return terracottaConfiguration != null ? terracottaConfiguration.getConsistency() : null;
}
/**
* To what transactionalMode was the Cache set
*
* @return transactionaMode
*/
public final TransactionalMode getTransactionalMode() {
if (transactionalMode == null) {
return DEFAULT_TRANSACTIONAL_MODE;
}
return transactionalMode;
}
/**
* Helper method to compute whether the cache is XA transactional or not
*
* @return true if transactionalMode="xa_strict"
*/
public boolean isXaStrictTransactional() {
validateTransactionalSettings();
return getTransactionalMode().equals(TransactionalMode.XA_STRICT);
}
/**
* Helper method to compute whether the cache is local transactional or not
*
* @return true if transactionalMode="local"
*/
public boolean isLocalTransactional() {
validateTransactionalSettings();
return getTransactionalMode().equals(TransactionalMode.LOCAL);
}
/**
* Helper method to compute whether the cache is local_jta transactional or not
*
* @return true if transactionalMode="xa"
*/
public boolean isXaTransactional() {
validateTransactionalSettings();
return getTransactionalMode().equals(TransactionalMode.XA);
}
/**
* An enum to identify what pool a resource uses
*/
private static enum PoolUsage {
CacheManager(true), Cache(true), None(false);
private final boolean usingPool;
private PoolUsage(final boolean poolUser) {
this.usingPool = poolUser;
}
public boolean isUsingPool() {
return usingPool;
}
}
/**
* Represents whether the Cache is transactional or not.
*
* @author alexsnaps
*/
public static enum TransactionalMode {
/**
* No Transactions
*/
OFF(false),
/**
* Local Transactions
*/
LOCAL(true),
/**
* XA Transactions
*/
XA(true),
/**
* XA Strict (true 2PC) Transactions
*/
XA_STRICT(true);
private final boolean transactional;
/**
* @param transactional
*/
TransactionalMode(final boolean transactional) {
this.transactional = transactional;
}
/**
* @return transactional
*/
public boolean isTransactional() {
return transactional;
}
}
/**
* Add a listener to this cache configuration
*
* @param listener listener instance to add
* @return true if a listener was added
*/
public boolean addConfigurationListener(CacheConfigurationListener listener) {
boolean added = listeners.add(listener);
if (added) {
listener.registered(this);
}
return added;
}
/**
* Add a dynamic extractor configuration listener
* @param listener
* @return true if a listener was added
*/
public boolean addDynamicSearchListener(DynamicSearchListener listener) {
return dynamicSearchListeners.add(listener);
}
/**
* Remove the supplied cache configuration listener.
*
* @param listener listener to remove
* @return true if a listener was removed
*/
public boolean removeConfigurationListener(CacheConfigurationListener listener) {
boolean removed = listeners.remove(listener);
if (removed) {
listener.deregistered(this);
}
return removed;
}
private void fireTtiChanged(long oldTti, long newTti) {
if (oldTti != newTti) {
for (CacheConfigurationListener l : listeners) {
l.timeToIdleChanged(oldTti, newTti);
}
}
}
private void fireTtlChanged(long oldTtl, long newTtl) {
if (oldTtl != newTtl) {
for (CacheConfigurationListener l : listeners) {
l.timeToLiveChanged(oldTtl, newTtl);
}
}
}
private void fireLoggingChanged(boolean oldValue, boolean newValue) {
if (oldValue != newValue) {
for (CacheConfigurationListener l : listeners) {
l.loggingChanged(oldValue, newValue);
}
}
}
private void fireDiskCapacityChanged(int oldCapacity, int newCapacity) {
if (oldCapacity != newCapacity) {
for (CacheConfigurationListener l : listeners) {
l.diskCapacityChanged(oldCapacity, newCapacity);
}
}
}
private void fireMaxEntriesInCacheChanged(long oldCapacity, long newCapacity) {
if (oldCapacity != newCapacity) {
for (CacheConfigurationListener l : listeners) {
l.maxEntriesInCacheChanged(oldCapacity, newCapacity);
}
}
}
private void fireMemoryCapacityChanged(int oldCapacity, int newCapacity) {
if (oldCapacity != newCapacity) {
for (CacheConfigurationListener l : listeners) {
l.memoryCapacityChanged(oldCapacity, newCapacity);
}
}
}
private void checkDynamicChange() {
if (frozen) {
throw new CacheException("Dynamic configuration changes are disabled for this cache");
}
}
/**
* Intended for internal use only, and subject to change.
* This is required so that changes in store implementation's config
* (probably from other nodes) can propagate up to here
*/
public void internalSetTimeToIdle(long timeToIdle) {
this.timeToIdleSeconds = timeToIdle;
}
/**
* Intended for internal use only, and subject to change.
*/
public void internalSetTimeToLive(long timeToLive) {
this.timeToLiveSeconds = timeToLive;
}
/**
* Intended for internal use only, and subject to change.
*/
public void internalSetEternal(boolean eternal) {
this.eternal = eternal;
}
/**
* Intended for internal use only, and subject to change.
*/
public void internalSetMemCapacity(int capacity) {
this.maxEntriesLocalHeap = capacity;
}
/**
* Intended for internal use only, and subject to change.
*/
public void internalSetMemCapacityInBytes(long capacity) {
this.maxBytesLocalHeap = capacity;
}
/**
* Intended for internal use only, and subject to change.
*/
public void internalSetDiskCapacity(int capacity) {
this.maxElementsOnDisk = capacity;
}
/**
* Intended for internal use only, and subject to change.
*/
public void internalSetMaxEntriesInCache(int entries) {
this.maxEntriesInCache = entries;
}
/**
* Intended for internal use only, and subject to change.
*/
public void internalSetLogging(boolean logging) {
this.logging = logging;
}
/**
* Intended for internal use only, and subject to change.
*/
public void internalSetMaxBytesLocalOffheap(long maxBytesLocalOffheap) {
this.maxBytesLocalOffHeap = maxBytesLocalOffheap;
}
/**
* Intended for internal use only, and subject to change.
*/
public void internalSetOverflowToOffheap(boolean overflowToOffHeap) {
this.overflowToOffHeap = overflowToOffHeap;
}
/**
* Get the defined search attributes indexed by attribute name
*
* @return search attributes
*/
public Map getSearchAttributes() {
if (searchable == null) {
return Collections.emptyMap();
}
return searchable.getSearchAttributes();
}
/**
* Get the search configuration for this cache (if any)
*
* @return search config (may be null)
*/
public Searchable getSearchable() {
return searchable;
}
public ClassLoader getClassLoader() {
return this.classLoader;
}
public void setClassLoader(ClassLoader classLoader) {
checkDynamicChange();
this.classLoader = classLoader;
}
/**
* Default listener class which handles the size changes of the cache
*/
private class DefaultCacheConfigurationListener extends AbstractCacheConfigurationListener {
private final CacheManager cacheManager;
public DefaultCacheConfigurationListener(CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
@Override
public void maxBytesLocalHeapChanged(final long oldValue, final long newValue) {
if (getMaxBytesLocalHeap() > 0
&& cacheManager.getConfiguration().getCacheConfigurations().keySet().contains(getName())
&& cacheManager.getConfiguration().isMaxBytesLocalHeapSet()) {
long oldCacheManagerPoolSize = cacheManager.getOnHeapPool().getMaxSize();
long newPoolFreeSize = oldCacheManagerPoolSize + oldValue - newValue;
//handle case of overallocation of cache
//Only resize the cache manager pool cache pool resizing will be handled by cache
if (newPoolFreeSize >= 0) {
cacheManager.getOnHeapPool().setMaxSize(newPoolFreeSize);
} else {
maxBytesLocalHeap = oldValue;
throw new InvalidConfigurationException("Cannot allocate heap size more " +
"than the cache pool size reverting to previous size " + maxBytesLocalHeap);
}
}
}
@Override
public void maxBytesLocalDiskChanged(final long oldValue, final long newValue) {
if (getMaxBytesLocalDisk() > 0
&& cacheManager.getConfiguration().getCacheConfigurations().keySet().contains(getName())
&& cacheManager.getConfiguration().isMaxBytesLocalDiskSet()) {
long previous = cacheManager.getOnDiskPool().getMaxSize();
long newPoolFreeSize = previous + oldValue - newValue;
//handle case of overallocation of cache
//Only resize the cache manager pool cache pool resizing will be handled by cache
if (newPoolFreeSize >= 0) {
cacheManager.getOnDiskPool().setMaxSize(newPoolFreeSize);
} else {
LOG.warn("Cannot allocate local disk size more than cache disk size, " +
"setting maxBytesLocalDisk {} to old value {}", maxBytesLocalDisk, oldValue);
maxBytesLocalDisk = oldValue;
throw new InvalidConfigurationException("Cannot allocate disk size more than " +
"the cache pool size reverting to previous size " + maxBytesLocalHeap);
}
}
}
}
}