/*
* Copyright 2011 Red Hat, Inc. and/or its affiliates.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
package org.infinispan.configuration.cache;
import org.infinispan.config.ConfigurationException;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
import java.util.concurrent.TimeUnit;
/**
* Configures the L1 cache behavior in 'distributed' caches instances. In any other cache modes,
* this element is ignored.
*/
public class L1ConfigurationBuilder extends AbstractClusteringConfigurationChildBuilder<L1Configuration> {
private static final Log log = LogFactory.getLog(L1ConfigurationBuilder.class);
private boolean enabled = true;
private int invalidationThreshold = 0;
private long lifespan = TimeUnit.MINUTES.toMillis(10);
private Boolean onRehash = null;
private long cleanupTaskFrequency = TimeUnit.MINUTES.toMillis(10);
boolean activated = false;
L1ConfigurationBuilder(ClusteringConfigurationBuilder builder) {
super(builder);
}
/**
* <p>
* Determines whether a multicast or a web of unicasts are used when performing L1 invalidations.
* </p>
*
* <p>
* By default multicast will be used.
* </p>
*
* <p>
* If the threshold is set to -1, then unicasts will always be used. If the threshold is set to
* 0, then multicast will be always be used.
* </p>
*
* @param threshold the threshold over which to use a multicast
*
*/
public L1ConfigurationBuilder invalidationThreshold(int invalidationThreshold) {
this.invalidationThreshold = invalidationThreshold;
activated = true;
return this;
}
/**
* Maximum lifespan of an entry placed in the L1 cache.
*/
public L1ConfigurationBuilder lifespan(long lifespan) {
this.lifespan = lifespan;
activated = true;
return this;
}
/**
* How often the L1 requestors map is cleaned up of stale items
*/
public L1ConfigurationBuilder cleanupTaskFrequency(long frequencyMillis) {
this.cleanupTaskFrequency = frequencyMillis;
activated = true;
return this;
}
/**
* Entries removed due to a rehash will be moved to L1 rather than being removed altogether.
*/
public L1ConfigurationBuilder enableOnRehash() {
this.onRehash = true;
activated = true;
return this;
}
/**
* Entries removed due to a rehash will be moved to L1 rather than being removed altogether.
*/
public L1ConfigurationBuilder onRehash(boolean enabled) {
this.onRehash = enabled;
activated = true;
return this;
}
/**
* Entries removed due to a rehash will be removed altogether rather than bring moved to L1.
*/
public L1ConfigurationBuilder disableOnRehash() {
this.onRehash = false;
activated = true;
return this;
}
public L1ConfigurationBuilder enable() {
this.enabled = true;
activated = true;
return this;
}
public L1ConfigurationBuilder disable() {
this.enabled = false;
this.onRehash = null;
activated = true;
return this;
}
public L1ConfigurationBuilder enabled(boolean enabled) {
this.enabled = enabled;
this.onRehash = enabled ? this.onRehash : null;
activated = true;
return this;
}
@Override
void validate() {
if (enabled) {
if (!clustering().cacheMode().isDistributed() && activated)
throw new ConfigurationException("Enabling the L1 cache is only supported when using DISTRIBUTED as a cache mode. Your cache mode is set to " + clustering().cacheMode().friendlyCacheModeString());
if (lifespan < 1)
throw new ConfigurationException("Using a L1 lifespan of 0 or a negative value is meaningless");
} else {
// If L1 is disabled, L1ForRehash should also be disabled
if (onRehash != null && onRehash)
throw new ConfigurationException("Can only move entries to L1 on rehash when L1 is enabled");
}
}
@Override
L1Configuration create() {
boolean finalOnRehash;
if (onRehash != null) {
finalOnRehash = onRehash.booleanValue();
} else {
finalOnRehash = false;
if (enabled && onRehash == null) {
log.debug("L1 is enabled and L1OnRehash was not defined, enabling it");
finalOnRehash = true;
}
}
return new L1Configuration(enabled, invalidationThreshold, lifespan, finalOnRehash, cleanupTaskFrequency, activated);
}
@Override
public L1ConfigurationBuilder read(L1Configuration template) {
enabled = template.enabled();
invalidationThreshold = template.invalidationThreshold();
lifespan = template.lifespan();
onRehash = template.onRehash();
cleanupTaskFrequency = template.cleanupTaskFrequency();
activated = template.activated;
return this;
}
@Override
public String toString() {
return "L1ConfigurationBuilder{" +
"activated=" + activated +
", enabled=" + enabled +
", invalidationThreshold=" + invalidationThreshold +
", lifespan=" + lifespan +
", cleanupTaskFrequency=" + cleanupTaskFrequency +
", onRehash=" + onRehash +
'}';
}
}