net.sf.ehcache.constructs.scheduledrefresh.ScheduledRefreshConfiguration 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.constructs.scheduledrefresh;
import net.sf.ehcache.Ehcache;
import java.io.Serializable;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
/**
* Configuration for a {@link ScheduledRefreshCacheExtension}. Can be
* initialized from a {@link Properties} object. Currently, the use of a
* clustered {@link org.terracotta.quartz.TerracottaJobStore} is not supported.
* This usage will be supported in the future.
*
* @author cschanck
*/
public class ScheduledRefreshConfiguration implements Serializable, Cloneable {
/**
* Property keys for configuration.
*/
public enum PropKey {
/**
* Properties key for the batch size attribute.
*/
batchSize,
/**
* Properties key for the key generator class name.
*/
keyGenerator,
/**
* Properties key for cron expression used to schedule this job.
*/
cronExpression,
/**
* Properties key for enabling bulk load mode prior to exection of the
* refresh.
*/
useBulkload,
/**
* Properties key for the quartz job count attribute.
*/
quartzJobCount,
/**
* Properties key for the terracotta config url.
*/
tcConfigUrl,
/**
* Properties key for the unique name identifier.
*/
scheduledRefreshName,
/**
* Properties key for the seed job polling interval.
*/
pollTimeMs,
/**
* Properties key for evictions on refresh fail.
*/
evictOnLoadMiss,
/**
* Properties key for the job store factory.
*/
jobStoreFactory,
/**
* Properties key for the job store factory.
*/
parallelJobCount,
}
/**
* Default setting for null eviction.
*/
public static final boolean DEFAULT_NULL_EVICTS = true;
/**
* Default setting for using bulkload.
*/
public static final boolean DEFAULT_USE_BULKLOAD = false;
/**
* Default batch size for key refresh processing.
*/
public static final int DEFAULT_BATCHSIZE = 100;
/**
* Default simultaneous Quartz thread count per node.
*/
public static final int DEFAULT_QUARTZ_THREADCOUNT = 2;
/**
* Default number of in process job count over the entire cluster.
*/
public static final int DEFAULT_PARALLEL_JOB_COUNT = DEFAULT_QUARTZ_THREADCOUNT;
/**
* Default polling timeout for monitoring refresh jobs.
*/
public static final int DEFAULT_POLL_TIME_MS = (int) TimeUnit.MILLISECONDS.convert(2, TimeUnit.SECONDS);
/**
* The Constant DEFAULT_KEY_GENERATOR_CLASS.
*/
private static final String DEFAULT_KEY_GENERATOR_CLASS = SimpleScheduledRefreshKeyGenerator.class.getName();
/**
* The Constant DEFAULT_JOB_STORE_FACTORY_CLASS.
*/
private static final String DEFAULT_JOB_STORE_FACTORY_CLASS = ScheduledRefreshRAMJobStoreFactory.class.getName();
/**
* The Constant serialVersionUID.
*/
private static final long serialVersionUID = -6877036694574988955L;
/**
* The batch size.
*/
private int batchSize = DEFAULT_BATCHSIZE;
/**
* The use bulkload.
*/
private boolean useBulkload = DEFAULT_USE_BULKLOAD;
/**
* The cron expression.
*/
private String cronExpression = null;
/**
* The quartz thread count.
*/
private int quartzThreadCount = DEFAULT_QUARTZ_THREADCOUNT;
/**
* Default parallel job count
*/
private int parallelJobCount = DEFAULT_PARALLEL_JOB_COUNT;
/**
* The key generator class.
*/
private String keyGeneratorClass = DEFAULT_KEY_GENERATOR_CLASS;
/**
* The unique name part.
*/
private String scheduledRefreshName = null;
/**
* The job store factory class name.
*/
private String jobStoreFactoryClassName = DEFAULT_JOB_STORE_FACTORY_CLASS;
/**
* the terracootta config url
*/
private String tcConfigUrl = null;
/**
* The poll time ms.
*/
private int pollTimeMs = DEFAULT_POLL_TIME_MS;
/**
* The load miss evicts.
*/
private boolean evictOnLoadMiss = DEFAULT_NULL_EVICTS;
/**
* The valid.
*/
private volatile boolean valid = false;
/**
* Excess properties passed to the extension
*/
private Properties excessProperties = new Properties();
/**
* Frozen flag. Once build() is called, the config is frozen.
*/
private volatile boolean frozen = false;
/**
* Create a default, valid configuration.
*/
public ScheduledRefreshConfiguration() {
}
/**
* Initialize this configuration from a {@link Properties} object. Will be
* validated before returning.
*
* @param properties the properties
* @return this configuration
*/
public ScheduledRefreshConfiguration fromProperties(Properties properties) {
valid = false;
frozen = false;
excessProperties.clear();
if (properties != null) {
for (String property : properties.stringPropertyNames()) {
String stringValue = properties.getProperty(property).trim();
PropKey pk;
try {
pk = PropKey.valueOf(property);
} catch (Exception e) {
pk = null;
}
if (pk != null) {
switch (pk) {
case batchSize:
setBatchSize(Integer.parseInt(stringValue));
break;
case useBulkload:
setUseBulkload(Boolean.parseBoolean(stringValue));
break;
case cronExpression:
setCronExpression(stringValue);
break;
case jobStoreFactory:
setJobStoreFactoryClassName(stringValue);
break;
case quartzJobCount:
setQuartzThreadCount(Integer.parseInt(stringValue));
break;
case parallelJobCount:
setParallelJobCount(Integer.parseInt(stringValue));
break;
case pollTimeMs:
setPollTimeMs(Integer.parseInt(stringValue));
break;
case evictOnLoadMiss:
setEvictOnLoadMiss(Boolean.parseBoolean(stringValue));
break;
case tcConfigUrl:
setTerracottaConfigUrl(stringValue);
break;
case keyGenerator:
setKeyGeneratorClass(stringValue);
break;
default:
throw new IllegalStateException("Unhandled property key: " + pk);
}
} else {
excessProperties.put(property, stringValue);
}
}
}
return build();
}
/**
* Express this configuration as a {@link Properties} object.
*
* @return properties version of this config
*/
public Properties toProperties() {
Properties p = new Properties();
p.setProperty(PropKey.batchSize.name(), Long.toString(getBatchSize()));
p.setProperty(PropKey.useBulkload.name(), Boolean.toString(isUseBulkload()));
p.setProperty(PropKey.evictOnLoadMiss.name(), Boolean.toString(isEvictOnLoadMiss()));
p.setProperty(PropKey.cronExpression.name(), getCronExpression());
p.setProperty(PropKey.jobStoreFactory.name(), getJobStoreFactoryClass());
p.setProperty(PropKey.quartzJobCount.name(), Integer.toString(getQuartzThreadCount()));
p.setProperty(PropKey.parallelJobCount.name(), Integer.toString(getParallelJobCount()));
p.setProperty(PropKey.pollTimeMs.name(), Integer.toString(getPollTimeMs()));
p.setProperty(PropKey.keyGenerator.name(), getKeyGeneratorClass());
p.setProperty(PropKey.tcConfigUrl.name(), getTerracottaConfigUrl());
for (String property : excessProperties.stringPropertyNames()) {
String stringValue = excessProperties.getProperty(property).trim();
p.put(property, stringValue);
}
return p;
}
/**
* Validate and mark this configuration good to use.
*
* @return validated configuration
*/
public ScheduledRefreshConfiguration build() {
validate();
frozen=true;
return this;
}
private void checkFrozen() {
if(frozen) {
throw new IllegalStateException("Can't modify a frozen configuration.");
}
}
/**
* Validate this configuration.
*/
public void validate() {
if (cronExpression == null) {
throw new IllegalArgumentException("Cron Schedule cannot be unspecified");
}
if(parallelJobCount<2) {
throw new IllegalArgumentException("parallelJobCount must be >= 2 ["+parallelJobCount+"]");
}
if(quartzThreadCount<2) {
throw new IllegalArgumentException("quartzThreadCount must be >= 2 ["+quartzThreadCount+"]");
}
if(batchSize<1) {
throw new IllegalArgumentException("batchSize must be >= 1 ["+batchSize+"]");
}
if(pollTimeMs<0) {
throw new IllegalArgumentException("pollTimeMS must be >=0 ["+pollTimeMs+"]");
}
final long oneMinuteMS=TimeUnit.MILLISECONDS.convert(1L, TimeUnit.MINUTES);
if(pollTimeMs>oneMinuteMS) {
throw new IllegalArgumentException("pollTimeMS must be < "+oneMinuteMS+" ["+pollTimeMs+"]");
}
if (jobStoreFactoryClassName == null) {
jobStoreFactoryClassName = DEFAULT_JOB_STORE_FACTORY_CLASS;
}
if (keyGeneratorClass == null) {
keyGeneratorClass = DEFAULT_KEY_GENERATOR_CLASS;
}
valid = true;
}
/**
* is this configuration valid to use?.
*
* @return true if it is valid
*/
public boolean isValid() {
return valid;
}
/**
* Get the batch size with which refresh requests will be processed.
*
* @return batch size
*/
public int getBatchSize() {
return batchSize;
}
/**
* Set the batch size for processing refresh requests. This is the number of
* keys will be processed in a batch.
*
* @param batchSize maximum batch size
*/
public void setBatchSize(int batchSize) {
checkFrozen();
valid = false;
this.batchSize = batchSize;
}
/**
* Fluently set the batch size for processing refresh requests.
*
* @param batchSize maximum batch size
* @return this configuration object
*/
public ScheduledRefreshConfiguration batchSize(int batchSize) {
setBatchSize(batchSize);
return this;
}
/**
* Get whether the cache will be put in bulk load mode prior to refresh.
*
* @return true if bulk load mode will be used for loading
*/
public boolean isUseBulkload() {
return useBulkload;
}
/**
* Set the flag to use bulk load for refreshing the keys. If true, the cache
* will be put in bulkLoade mode prior to running the refresh, and after all
* the jobs are finished, it will be restored to it's prior state.
*
* @param useBulkload the new use bulkload
*/
public void setUseBulkload(boolean useBulkload) {
checkFrozen();
valid = false;
this.useBulkload = useBulkload;
}
/**
* Fluently set the bulk load flag.
*
* @param yes the yes
* @return this configuration
*/
public ScheduledRefreshConfiguration useBulkload(boolean yes) {
setUseBulkload(yes);
return this;
}
/**
* Return the string cron expression which will be passed to Quartz to
* schedule the refresh.
*
* @return cron expression string
*/
public String getCronExpression() {
return cronExpression;
}
/**
* Set the cron expression Quartz will use for scheduling this refresh job.
* See Quartz documentation for a further explanation.
*
* @param cronExpression the new cron expression
*/
public void setCronExpression(String cronExpression) {
checkFrozen();
valid = false;
this.cronExpression = cronExpression;
}
/**
* Fluently set the cron expression Quartz will use for scheduling this
* refresh job.
*
* @param cronExpression the cron expression
* @return this configuration
*/
public ScheduledRefreshConfiguration cronExpression(String cronExpression) {
setCronExpression(cronExpression);
return this;
}
/**
* Get the quartz thread count.
*
* @return the quartz thread count
*/
public int getQuartzThreadCount() {
return quartzThreadCount;
}
/**
* Set the Quartz thread count. This is the number of concurrent refresh
* batches which can be processed at one time. The overseeing job will poll
* and not schedule more than this many jobs at one time.
*
* @param quartzThreadCount the new quartz thread count
*/
public void setQuartzThreadCount(int quartzThreadCount) {
checkFrozen();
valid = false;
this.quartzThreadCount = quartzThreadCount;
}
/**
* Fluently set the Quartz thread count.
*
* @param quartzThreadCount the quartz thread count
* @return this configuration
*/
public ScheduledRefreshConfiguration quartzThreadCount(int quartzThreadCount) {
setQuartzThreadCount(quartzThreadCount);
return this;
}
/**
* Get the key generator class used to generate the list of keys to refresh.
*
* @return the fully qualified class name of the
* {@link ScheduledRefreshKeyGenerator} class
*/
public String getKeyGeneratorClass() {
return keyGeneratorClass;
}
/**
* Set the key generator class used to generate the list of keys to refresh.
* This is the class used to generate keys from the target cache. A simple
* implementation of the naive getKeys() approach is supplied.
*
* @param keyGeneratorClass the new key generator class
*/
public void setKeyGeneratorClass(String keyGeneratorClass) {
checkFrozen();
this.keyGeneratorClass = keyGeneratorClass;
}
/**
* Fluently set the key generator class used to generate the list of keys to
* refresh.
*
* @param keyGeneratorClass the key generator class
* @return this configuration
*/
public ScheduledRefreshConfiguration keyGeneratorClass(String keyGeneratorClass) {
setKeyGeneratorClass(keyGeneratorClass);
return this;
}
/**
* Get an additional identifier used in addition to the cache manager and
* cache name for this extension, and for the job scheduler, and job group.
* If you are going to have multiple scheduled refresh extensions on the same
* cache, this is necessary.
*
* @return An additional unique identifier for the scheduler and it's jobs
*/
public String getScheduledRefreshName() {
return scheduledRefreshName;
}
/**
* Set an additional identifier used in addition to the cache manager and
* cache name for this extension, and for the job scheduler, and job group.
* If you are going to have multiple scheduled refresh extensions on the same
* cache, this is necessary.
*
* @param part the new unique name part
*/
public void setScheduledRefreshName(String part) {
checkFrozen();
this.scheduledRefreshName = part;
}
/**
* Fluently set an additional identifier used in addition to the cache
* manager and cache name for this extension, and for the job scheduler, and
* job group. If you are going to have multiple scheduled refresh extensions
* on the same cache, this is necessary.
*
* @param part unique identifier used to distinguish this scheduled refresh
* instance from others on the same cache
* @return this configuration
*/
public ScheduledRefreshConfiguration scheduledRefreshName(String part) {
setScheduledRefreshName(part);
return this;
}
/**
* Get whether now value found in all CacheLoaders will force an eviction
* prematurely from the underlying cache.
*
* @return true if refresh will remove keys it annot load through the cache
* loaders
*/
public boolean isEvictOnLoadMiss() {
return evictOnLoadMiss;
}
/**
* Set whether now value found in all CacheLoaders will force an eviction
* prematurely from the underlying cache.
*
* @param loadMissEvicts true to evict
*/
public void setEvictOnLoadMiss(boolean loadMissEvicts) {
checkFrozen();
valid = false;
this.evictOnLoadMiss = loadMissEvicts;
}
/**
* Fluently set whether now value found in all CacheLoaders will force an
* eviction eviction prematurely from the underlying cache.
*
* @param loadMissEvicts true to evict
* @return this configuration
*/
public ScheduledRefreshConfiguration evictOnLoadMiss(boolean loadMissEvicts) {
setEvictOnLoadMiss(loadMissEvicts);
return this;
}
/**
* Get the time interval the {@link OverseerJob} will use to poll for job
* completion.
*
* @return time in milliseconds the controlling job will poll the scheduler's
* {@link org.quartz.spi.JobStore} in order to schedule the next
* batch of keys.
*/
public int getPollTimeMs() {
return pollTimeMs;
}
/**
* Set the time interval the {@link OverseerJob} will use to poll for job
* completion.
*
* @param pollTimeMs time in milliseconds the controlling job will poll the
* scheduler's {@link org.quartz.spi.JobStore} in order to schedule
* the next batch of keys.
*/
public void setPollTimeMs(int pollTimeMs) {
checkFrozen();
valid = false;
this.pollTimeMs = pollTimeMs;
}
/**
* Fluently set the time interval the {@link OverseerJob} will use to poll
* for job completion.
*
* @param pollTimeMs time in milliseconds the controlling job will poll the
* scheduler's
* @return this configuration {@link org.quartz.spi.JobStore} in order to
* schedule the next batch of keys.
*/
public ScheduledRefreshConfiguration pollTimeMs(int pollTimeMs) {
setPollTimeMs(pollTimeMs);
return this;
}
/**
* Gets the job store factory class.
*
* @return the job store factory class
*/
public String getJobStoreFactoryClass() {
return jobStoreFactoryClassName;
}
/**
* Sets the job store factory class name.
*
* @param className the new job store factory class name
*/
public void setJobStoreFactoryClassName(String className) {
checkFrozen();
this.jobStoreFactoryClassName = className;
}
/**
* Fluently set the Job store factory.
*
* @param className the class name
* @return the scheduled refresh configuration
*/
public ScheduledRefreshConfiguration jobStoreFactory(String className) {
setJobStoreFactoryClassName(className);
return this;
}
/**
* Get any unrecognized properties that were passed to this config when
* constructed via a Properties object.
*
* @return properties
*/
public Properties getExcessProperties() {
return excessProperties;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "ScheduledRefreshConfiguration{" + "terracottaConfigUrl=" + getTerracottaConfigUrl() +
", batchSize=" + batchSize + ", useBulkload=" + useBulkload
+ ", cronExpression='" + cronExpression + '\'' + ", quartzThreadCount=" + quartzThreadCount
+ ", parallelJobCount=" + parallelJobCount
+ ", keyGeneratorClass='" + keyGeneratorClass + '\'' + ", uniqueNamePart='" + scheduledRefreshName + '\''
+ ", pollTimeMs=" + pollTimeMs + ", loadMissEvicts=" + evictOnLoadMiss + ", valid=" + valid + '}';
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#clone()
*/
@Override
protected Object clone() throws CloneNotSupportedException {
ScheduledRefreshConfiguration clone = (ScheduledRefreshConfiguration) super.clone();
clone.fromProperties(toProperties());
return clone;
}
/**
* Sets terracotta config url. Also sets (or clears) the job store factory
* to {@link ScheduledRefreshTerracottaJobStoreFactory} or null.
*
* @param terracottaConfigUrl the terracotta config url
*/
public void setTerracottaConfigUrl(String terracottaConfigUrl) {
checkFrozen();
valid = false;
this.tcConfigUrl = terracottaConfigUrl;
if (terracottaConfigUrl == null) {
setJobStoreFactoryClassName(null);
} else {
setJobStoreFactoryClassName(ScheduledRefreshTerracottaJobStoreFactory.class.getName());
}
}
/**
* Set the Terracotta config url, fluently.
*
* @param terracottaConfigUrl the terracotta config url
* @return the scheduled refresh configuration
*/
public ScheduledRefreshConfiguration terracottaConfigUrl(String terracottaConfigUrl) {
setTerracottaConfigUrl(terracottaConfigUrl);
return this;
}
/**
* Gets terracotta config url.
*
* @return the terracotta config url
*/
public String getTerracottaConfigUrl() {
return tcConfigUrl;
}
/**
* Sets parallel job count.
*
* @param parallelJobCount the parallel job count
*/
public void setParallelJobCount(int parallelJobCount) {
checkFrozen();
this.parallelJobCount = parallelJobCount;
valid = false;
}
/**
* Parallel job count.
*
* @param parallelJobCount the parallel job count
* @return the scheduled refresh configuration
*/
public ScheduledRefreshConfiguration parallelJobCount(int parallelJobCount) {
setParallelJobCount(parallelJobCount);
return this;
}
/**
* Gets parallel job count.
*
* @return the parallel job count
*/
public int getParallelJobCount() {
return parallelJobCount;
}
}