net.sf.ehcache.config.CacheWriterConfiguration Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ehcache Show documentation
Show all versions of ehcache Show documentation
Ehcache is an open source, standards-based cache used to boost performance,
offload the database and simplify scalability. Ehcache is robust, proven and full-featured and
this has made it the most widely-used Java-based cache.
/**
* 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 java.util.Collection;
import net.sf.ehcache.Cache;
import net.sf.ehcache.store.Store;
import net.sf.ehcache.writer.CacheWriterManager;
import net.sf.ehcache.writer.writebehind.WriteBehindManager;
import net.sf.ehcache.writer.writethrough.WriteThroughManager;
/**
* Class to hold the CacheWriterManager configuration
*
* @author Geert Bevin
* @version $Id: CacheWriterConfiguration.java 7406 2013-04-23 22:04:53Z cdennis $
*/
public class CacheWriterConfiguration implements Cloneable {
/**
* Default writeMode
*/
public static final WriteMode DEFAULT_WRITE_MODE = WriteMode.WRITE_THROUGH;
/**
* Default notifyListenersOnException behavior
*/
public static final boolean DEFAULT_NOTIFY_LISTENERS_ON_EXCEPTION = false;
/**
* Default minimum write delay
*/
public static final int DEFAULT_MIN_WRITE_DELAY = 1;
/**
* Default maximum write delay
*/
public static final int DEFAULT_MAX_WRITE_DELAY = 1;
/**
* Default rate limit per second
*/
public static final int DEFAULT_RATE_LIMIT_PER_SECOND = 0;
/**
* Default write coalescing behavior
*/
public static final boolean DEFAULT_WRITE_COALESCING = false;
/**
* Default writeBatching behavior
*/
public static final boolean DEFAULT_WRITE_BATCHING = false;
/**
* Default write batch size
*/
public static final int DEFAULT_WRITE_BATCH_SIZE = 1;
/**
* Default retry attempts
*/
public static final int DEFAULT_RETRY_ATTEMPTS = 0;
/**
* Default retry attempt delay
*/
public static final int DEFAULT_RETRY_ATTEMPT_DELAY_SECONDS = 1;
/**
* Default concurrency level for write behind
*/
public static final int DEFAULT_WRITE_BEHIND_CONCURRENCY = 1;
/**
* Default max queue size for write behind
*/
public static final int DEFAULT_WRITE_BEHIND_MAX_QUEUE_SIZE = 0;
/**
* Represents how elements are written to the {@link net.sf.ehcache.writer.CacheWriter}
*/
public static enum WriteMode {
/**
* Write mode enum constant that can be used to configure a cache writer to use write through
*/
WRITE_THROUGH {
/**
* {@inheritDoc}
*/
@Override
public CacheWriterManager createWriterManager(Cache cache, Store store) {
return new WriteThroughManager();
}
},
/**
* Write mode enum constant that can be used to configure a cache writer to use write behind
*/
WRITE_BEHIND {
/**
* {@inheritDoc}
*/
@Override
public CacheWriterManager createWriterManager(Cache cache, Store store) {
return new WriteBehindManager(cache, store);
}
};
/**
* Create a new {@code WriterManager} for a particular cache instance
*
* @param cache the cache instance for which the {@code WriterManager} should be created
* @return the newly created {@code WriterManager}
*/
public abstract CacheWriterManager createWriterManager(Cache cache, Store store);
}
private WriteMode writeMode = DEFAULT_WRITE_MODE;
private boolean notifyListenersOnException = DEFAULT_NOTIFY_LISTENERS_ON_EXCEPTION;
private int minWriteDelay = DEFAULT_MIN_WRITE_DELAY;
private int maxWriteDelay = DEFAULT_MAX_WRITE_DELAY;
private int rateLimitPerSecond = DEFAULT_RATE_LIMIT_PER_SECOND;
private boolean writeCoalescing = DEFAULT_WRITE_COALESCING;
private boolean writeBatching = DEFAULT_WRITE_BATCHING;
private int writeBatchSize = DEFAULT_WRITE_BATCH_SIZE;
private int retryAttempts = DEFAULT_RETRY_ATTEMPTS;
private int retryAttemptDelaySeconds = DEFAULT_RETRY_ATTEMPT_DELAY_SECONDS;
private int writeBehindConcurrency = DEFAULT_WRITE_BEHIND_CONCURRENCY;
private int writeBehindMaxQueueSize = DEFAULT_WRITE_BEHIND_MAX_QUEUE_SIZE;
private CacheWriterFactoryConfiguration cacheWriterFactoryConfiguration;
/**
* Clones this object, following the usual contract.
*
* @return a copy, which independent other than configurations than cannot change.
*/
@Override
public CacheWriterConfiguration clone() {
CacheWriterConfiguration config;
try {
config = (CacheWriterConfiguration) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
if (cacheWriterFactoryConfiguration != null) {
config.cacheWriterFactoryConfiguration = cacheWriterFactoryConfiguration.clone();
}
return config;
}
/**
* Converts the {@code writeMode} string argument to uppercase and looks up enum constant in WriteMode.
*/
public void setWriteMode(String writeMode) {
if (writeMode == null) {
throw new IllegalArgumentException("WriteMode can't be null");
}
this.writeMode = WriteMode.valueOf(WriteMode.class, writeMode.replace('-', '_').toUpperCase());
}
/**
* @return this configuration instance
* @see #setWriteMode(String)
*/
public CacheWriterConfiguration writeMode(String writeMode) {
setWriteMode(writeMode);
return this;
}
/**
* @return this configuration instance
* @see #setWriteMode(String)
*/
public CacheWriterConfiguration writeMode(WriteMode writeMode) {
if (null == writeMode) {
throw new IllegalArgumentException("WriteMode can't be null");
}
this.writeMode = writeMode;
return this;
}
/**
* Get the write mode in terms of the mode enum
*/
public WriteMode getWriteMode() {
return this.writeMode;
}
/**
* Sets whether to notify listeners when an exception occurs on a writer operation.
*
* This is only applicable to write through mode.
*
* Defaults to {@value #DEFAULT_NOTIFY_LISTENERS_ON_EXCEPTION}.
*
* @param notifyListenersOnException {@code true} if listeners should be notified when an exception occurs on a writer operation; {@code false} otherwise
*/
public void setNotifyListenersOnException(boolean notifyListenersOnException) {
this.notifyListenersOnException = notifyListenersOnException;
}
/**
* @return this configuration instance
* @see #setNotifyListenersOnException(boolean)
*/
public CacheWriterConfiguration notifyListenersOnException(boolean notifyListenersOnException) {
setNotifyListenersOnException(notifyListenersOnException);
return this;
}
/**
* Check whether listeners should be notified when an exception occurs on a writer operation
*/
public boolean getNotifyListenersOnException() {
return this.notifyListenersOnException;
}
/**
* Set the minimum number of seconds to wait before writing behind. If set to a value greater than 0, it permits
* operations to build up in the queue. This is different from the maximum write delay in that by waiting a minimum
* amount of time, work is always being built up. If the minimum write delay is set to zero and the {@code CacheWriter}
* performs its work very quickly, the overhead of processing the write behind queue items becomes very noticeable
* in a cluster since all the operations might be done for individual items instead of for a collection of them.
*
* This is only applicable to write behind mode.
*
* Defaults to {@value #DEFAULT_MIN_WRITE_DELAY}).
*
* @param minWriteDelay the minimum number of seconds to wait before writing behind
*/
public void setMinWriteDelay(int minWriteDelay) {
if (minWriteDelay < 0) {
this.minWriteDelay = 0;
} else {
this.minWriteDelay = minWriteDelay;
}
}
/**
* @return this configuration instance
* @see #setMinWriteDelay(int)
*/
public CacheWriterConfiguration minWriteDelay(int minWriteDelay) {
setMinWriteDelay(minWriteDelay);
return this;
}
/**
* Get the minimum number of seconds to wait before writing behind
*/
public int getMinWriteDelay() {
return this.minWriteDelay;
}
/**
* Set the maximum number of seconds to wait before writing behind. If set to a value greater than 0, it permits
* operations to build up in the queue to enable effective coalescing and batching optimisations.
*
* This is only applicable to write behind mode.
*
* Defaults to {@value #DEFAULT_MAX_WRITE_DELAY}).
*
* @param maxWriteDelay the maximum number of seconds to wait before writing behind
*/
public void setMaxWriteDelay(int maxWriteDelay) {
if (maxWriteDelay < 0) {
this.maxWriteDelay = 0;
} else {
this.maxWriteDelay = maxWriteDelay;
}
}
/**
* @return this configuration instance
* @see #setMaxWriteDelay(int)
*/
public CacheWriterConfiguration maxWriteDelay(int maxWriteDelay) {
setMaxWriteDelay(maxWriteDelay);
return this;
}
/**
* Get the maximum number of seconds to wait before writing behind
*/
public int getMaxWriteDelay() {
return this.maxWriteDelay;
}
/**
* Sets the maximum number of write operations to allow per second when {@link #writeBatching} is enabled.
*
* This is only applicable to write behind mode.
*
* Defaults to {@value #DEFAULT_RATE_LIMIT_PER_SECOND}.
*
* @param rateLimitPerSecond the number of write operations to allow; use a number {@code <=0} to disable rate limiting.
*/
public void setRateLimitPerSecond(int rateLimitPerSecond) {
if (rateLimitPerSecond < 0) {
this.rateLimitPerSecond = 0;
} else {
this.rateLimitPerSecond = rateLimitPerSecond;
}
}
/**
* @return this configuration instance
* @see #setRateLimitPerSecond(int rateLimitPerSecond)
*/
public CacheWriterConfiguration rateLimitPerSecond(int rateLimitPerSecond) {
setRateLimitPerSecond(rateLimitPerSecond);
return this;
}
/**
* Get the maximum number of write operations to allow per second.
*/
public int getRateLimitPerSecond() {
return rateLimitPerSecond;
}
/**
* Sets whether to use write coalescing. If set to {@code true} and multiple operations on the same key are present
* in the write-behind queue, only the latest write is done, as the others are redundant. This can dramatically
* reduce load on the underlying resource.
*
* This is only applicable to write behind mode.
*
* Defaults to {@value #DEFAULT_WRITE_COALESCING}.
*
* @param writeCoalescing {@code true} to enable write coalescing; or {@code false} to disable it
*/
public void setWriteCoalescing(boolean writeCoalescing) {
this.writeCoalescing = writeCoalescing;
}
/**
* @return this configuration instance
* @see #setWriteCoalescing(boolean)
*/
public CacheWriterConfiguration writeCoalescing(boolean writeCoalescing) {
setWriteCoalescing(writeCoalescing);
return this;
}
/**
* @return this configuration instance
* @see #setWriteCoalescing(boolean)
*/
public boolean getWriteCoalescing() {
return writeCoalescing;
}
/**
* Sets whether to batch write operations. If set to {@code true}, {@link net.sf.ehcache.writer.CacheWriter#writeAll} and {@code CacheWriter#deleteAll}
* will be called rather than {@link net.sf.ehcache.writer.CacheWriter#write} and {@link net.sf.ehcache.writer.CacheWriter#delete} being called for each key. Resources such
* as databases can perform more efficiently if updates are batched, thus reducing load.
*
* This is only applicable to write behind mode.
*
* Defaults to {@value #DEFAULT_WRITE_BATCHING}.
*
* @param writeBatching {@code true} if write operations should be batched; {@code false} otherwise
*/
public void setWriteBatching(boolean writeBatching) {
this.writeBatching = writeBatching;
}
/**
* @return this configuration instance
* @see #setWriteBatching(boolean)
*/
public CacheWriterConfiguration writeBatching(boolean writeBatching) {
setWriteBatching(writeBatching);
return this;
}
/**
* Check whether write operations should be batched
*/
public boolean getWriteBatching() {
return this.writeBatching;
}
/**
* Sets the number of operations to include in each batch when {@link #writeBatching} is enabled. If there are less
* entries in the write-behind queue than the batch size, the queue length size is used.
*
* This is only applicable to write behind mode.
*
* Defaults to {@value #DEFAULT_WRITE_BATCH_SIZE}.
*
* @param writeBatchSize the number of operations to include in each batch; numbers smaller than {@code 1} will cause
* the default batch size to be used
*/
public void setWriteBatchSize(int writeBatchSize) {
if (writeBatchSize < 1) {
this.writeBatchSize = DEFAULT_WRITE_BATCH_SIZE;
} else {
this.writeBatchSize = writeBatchSize;
}
}
/**
* @return this configuration instance
* @see #setWriteBatchSize(int)
*/
public CacheWriterConfiguration writeBatchSize(int writeBatchSize) {
setWriteBatchSize(writeBatchSize);
return this;
}
/**
* Retrieves the size of the batch operation.
*/
public int getWriteBatchSize() {
return writeBatchSize;
}
/**
* Sets the number of times the operation is retried in the {@code CacheWriter}, this happens after the
* original operation.
*
* This is only applicable to write behind mode.
*
* Defaults to {@value #DEFAULT_RETRY_ATTEMPTS}.
*
* @param retryAttempts the number of retries for a particular element
*/
public void setRetryAttempts(int retryAttempts) {
if (retryAttempts < 0) {
this.retryAttempts = 0;
} else {
this.retryAttempts = retryAttempts;
}
}
/**
* @return this configuration instance
* @see #setRetryAttempts(int)
*/
public CacheWriterConfiguration retryAttempts(int retryAttempts) {
setRetryAttempts(retryAttempts);
return this;
}
/**
* Retrieves the number of times the write of element is retried.
*/
public int getRetryAttempts() {
return retryAttempts;
}
/**
* Sets the number of seconds to wait before retrying an failed operation.
*
* This is only applicable to write behind mode.
*
* Defaults to {@value #DEFAULT_RETRY_ATTEMPT_DELAY_SECONDS}.
*
* @param retryAttemptDelaySeconds the number of seconds to wait before retrying an operation
*/
public void setRetryAttemptDelaySeconds(int retryAttemptDelaySeconds) {
if (retryAttemptDelaySeconds < 0) {
this.retryAttemptDelaySeconds = 0;
} else {
this.retryAttemptDelaySeconds = retryAttemptDelaySeconds;
}
}
/**
* @return this configuration instance
* @see #setRetryAttemptDelaySeconds(int)
*/
public CacheWriterConfiguration retryAttemptDelaySeconds(int retryAttemptDelaySeconds) {
setRetryAttemptDelaySeconds(retryAttemptDelaySeconds);
return this;
}
/**
* Retrieves the number of seconds to wait before retrying an failed operation.
*/
public int getRetryAttemptDelaySeconds() {
return retryAttemptDelaySeconds;
}
/**
* Configuration for the CacheWriterFactoryConfiguration.
*/
public static final class CacheWriterFactoryConfiguration extends FactoryConfiguration {
/**
* Overrided hashCode()
*/
@Override
public int hashCode() {
return super.hashCode();
}
/**
* Overrided equals
*/
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
}
/**
* Allows BeanHandler to add the CacheWriterFactory to the configuration.
*/
public final void addCacheWriterFactory(CacheWriterFactoryConfiguration cacheWriterFactoryConfiguration) {
this.cacheWriterFactoryConfiguration = cacheWriterFactoryConfiguration;
}
/**
* @return this configuration instance
* @see #addCacheWriterFactory(CacheWriterFactoryConfiguration)
*/
public CacheWriterConfiguration cacheWriterFactory(CacheWriterFactoryConfiguration cacheWriterFactory) {
addCacheWriterFactory(cacheWriterFactory);
return this;
}
/**
* Accessor
*
* @return the configuration
*/
public CacheWriterFactoryConfiguration getCacheWriterFactoryConfiguration() {
return cacheWriterFactoryConfiguration;
}
/**
* Configures the amount of thread/bucket pairs WriteBehind should use
* @param concurrency Amount of thread/bucket pairs, has to be at least 1
*/
public void setWriteBehindConcurrency(int concurrency) {
if (concurrency < 1) {
this.writeBehindConcurrency = 1;
} else {
this.writeBehindConcurrency = concurrency;
}
}
/**
*
* @param concurrency Amount of thread/bucket pairs, has to be at least 1
* @return this configuration instance
* @see #setWriteBehindConcurrency(int)
*/
public CacheWriterConfiguration writeBehindConcurrency(int concurrency) {
this.setWriteBehindConcurrency(concurrency);
return this;
}
/**
* Accessor
* @return the amount of bucket/thread pairs configured for this cache's write behind
*/
public int getWriteBehindConcurrency() {
return writeBehindConcurrency;
}
/**
* Configures the maximum amount of operations to be on the waiting queue, before it blocks
* @param writeBehindMaxQueueSize maximum amount of operations allowed on the waiting queue
*/
public void setWriteBehindMaxQueueSize(final int writeBehindMaxQueueSize) {
if (writeBehindMaxQueueSize < 0) {
this.writeBehindMaxQueueSize = DEFAULT_WRITE_BEHIND_MAX_QUEUE_SIZE;
} else {
this.writeBehindMaxQueueSize = writeBehindMaxQueueSize;
}
}
/**
* Accessor
* @return the maximum amount of operations allowed on the write behind queue
*/
public int getWriteBehindMaxQueueSize() {
return writeBehindMaxQueueSize;
}
/**
* @param writeBehindMaxQueueSize maximum amount of operations allowed on the waiting queue
* @return this configuration instance
* @see #setWriteBehindMaxQueueSize(int)
*/
public CacheWriterConfiguration writeBehindMaxQueueSize(int writeBehindMaxQueueSize) {
this.setWriteBehindMaxQueueSize(writeBehindMaxQueueSize);
return this;
}
/**
* Overrided hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
final int primeTwo = 1231;
final int primeThree = 1237;
int result = 1;
result = prime * result + ((cacheWriterFactoryConfiguration == null) ? 0 : cacheWriterFactoryConfiguration.hashCode());
result = prime * result + maxWriteDelay;
result = prime * result + minWriteDelay;
result = prime * result + (notifyListenersOnException ? primeTwo : primeThree);
result = prime * result + rateLimitPerSecond;
result = prime * result + retryAttemptDelaySeconds;
result = prime * result + retryAttempts;
result = prime * result + writeBatchSize;
result = prime * result + (writeBatching ? primeTwo : primeThree);
result = prime * result + (writeCoalescing ? primeTwo : primeThree);
result = prime * result + ((writeMode == null) ? 0 : writeMode.hashCode());
result = prime * result + writeBehindConcurrency;
return result;
}
/**
* Overrided equals()
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
CacheWriterConfiguration other = (CacheWriterConfiguration) obj;
if (cacheWriterFactoryConfiguration == null) {
if (other.cacheWriterFactoryConfiguration != null) {
return false;
}
} else if (!cacheWriterFactoryConfiguration.equals(other.cacheWriterFactoryConfiguration)) {
return false;
}
if (maxWriteDelay != other.maxWriteDelay) {
return false;
}
if (minWriteDelay != other.minWriteDelay) {
return false;
}
if (notifyListenersOnException != other.notifyListenersOnException) {
return false;
}
if (rateLimitPerSecond != other.rateLimitPerSecond) {
return false;
}
if (retryAttemptDelaySeconds != other.retryAttemptDelaySeconds) {
return false;
}
if (retryAttempts != other.retryAttempts) {
return false;
}
if (writeBatchSize != other.writeBatchSize) {
return false;
}
if (writeBatching != other.writeBatching) {
return false;
}
if (writeCoalescing != other.writeCoalescing) {
return false;
}
if (writeBehindConcurrency != other.writeBehindConcurrency) {
return false;
}
if (writeMode == null) {
if (other.writeMode != null) {
return false;
}
} else if (!writeMode.equals(other.writeMode)) {
return false;
}
return true;
}
/**
* Check for errors/inconsistencies in this configuration. Add any erros found as
* {@link ConfigError} in the errors collection.
* @param errors collection to add errors to.
*/
public void validate(Collection errors) {
if (writeMode.equals(WriteMode.WRITE_BEHIND)) {
if (!getWriteBatching() && getWriteBatchSize() != 1) {
errors.add(new ConfigError("Configured Write Batch Size is not equal to 1 with Write Batching turned off."));
}
}
}
}