
org.infinispan.cache.impl.CacheImpl Maven / Gradle / Ivy
package org.infinispan.cache.impl;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.infinispan.context.Flag.FAIL_SILENTLY;
import static org.infinispan.context.Flag.FORCE_ASYNCHRONOUS;
import static org.infinispan.context.Flag.IGNORE_RETURN_VALUES;
import static org.infinispan.context.Flag.PUT_FOR_EXTERNAL_READ;
import static org.infinispan.context.Flag.ZERO_LOCK_ACQUISITION_TIMEOUT;
import static org.infinispan.context.InvocationContextFactory.UNBOUNDED;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.BiFunction;
import java.util.function.Function;
import javax.security.auth.Subject;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.xa.XAResource;
import org.infinispan.AdvancedCache;
import org.infinispan.CacheCollection;
import org.infinispan.CacheSet;
import org.infinispan.LockedStream;
import org.infinispan.Version;
import org.infinispan.atomic.Delta;
import org.infinispan.atomic.DeltaAware;
import org.infinispan.atomic.impl.ApplyDelta;
import org.infinispan.batch.BatchContainer;
import org.infinispan.commands.CommandsFactory;
import org.infinispan.commands.VisitableCommand;
import org.infinispan.commands.control.LockControlCommand;
import org.infinispan.commands.functional.ReadWriteKeyValueCommand;
import org.infinispan.commands.functional.ReadWriteKeyCommand;
import org.infinispan.commands.functional.functions.MergeFunction;
import org.infinispan.commands.read.EntrySetCommand;
import org.infinispan.commands.read.GetAllCommand;
import org.infinispan.commands.read.GetCacheEntryCommand;
import org.infinispan.commands.read.GetKeyValueCommand;
import org.infinispan.commands.read.KeySetCommand;
import org.infinispan.commands.read.SizeCommand;
import org.infinispan.commands.remote.GetKeysInGroupCommand;
import org.infinispan.commands.write.ClearCommand;
import org.infinispan.commands.write.ComputeCommand;
import org.infinispan.commands.write.ComputeIfAbsentCommand;
import org.infinispan.commands.write.DataWriteCommand;
import org.infinispan.commands.write.EvictCommand;
import org.infinispan.commands.write.PutKeyValueCommand;
import org.infinispan.commands.write.PutMapCommand;
import org.infinispan.commands.write.RemoveCommand;
import org.infinispan.commands.write.RemoveExpiredCommand;
import org.infinispan.commands.write.ReplaceCommand;
import org.infinispan.commands.write.ValueMatcher;
import org.infinispan.commons.CacheException;
import org.infinispan.commons.api.BasicCacheContainer;
import org.infinispan.commons.dataconversion.Encoder;
import org.infinispan.commons.dataconversion.Wrapper;
import org.infinispan.commons.marshall.StreamingMarshaller;
import org.infinispan.commons.util.EnumUtil;
import org.infinispan.commons.util.InfinispanCollections;
import org.infinispan.commons.util.Util;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.format.PropertyFormatter;
import org.infinispan.configuration.global.GlobalConfiguration;
import org.infinispan.container.DataContainer;
import org.infinispan.container.entries.CacheEntry;
import org.infinispan.context.Flag;
import org.infinispan.context.InvocationContext;
import org.infinispan.context.InvocationContextContainer;
import org.infinispan.context.InvocationContextFactory;
import org.infinispan.context.impl.FlagBitSets;
import org.infinispan.context.impl.TxInvocationContext;
import org.infinispan.distribution.DistributionManager;
import org.infinispan.encoding.DataConversion;
import org.infinispan.eviction.EvictionManager;
import org.infinispan.eviction.PassivationManager;
import org.infinispan.expiration.ExpirationManager;
import org.infinispan.factories.ComponentRegistry;
import org.infinispan.factories.annotations.Inject;
import org.infinispan.factories.annotations.SurvivesRestarts;
import org.infinispan.filter.KeyFilter;
import org.infinispan.functional.impl.Params;
import org.infinispan.interceptors.AsyncInterceptor;
import org.infinispan.interceptors.AsyncInterceptorChain;
import org.infinispan.interceptors.base.CommandInterceptor;
import org.infinispan.jmx.annotations.DataType;
import org.infinispan.jmx.annotations.DisplayType;
import org.infinispan.jmx.annotations.MBean;
import org.infinispan.jmx.annotations.ManagedAttribute;
import org.infinispan.jmx.annotations.ManagedOperation;
import org.infinispan.lifecycle.ComponentStatus;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.metadata.EmbeddedMetadata;
import org.infinispan.metadata.Metadata;
import org.infinispan.notifications.cachelistener.CacheNotifier;
import org.infinispan.notifications.cachelistener.ListenerHolder;
import org.infinispan.notifications.cachelistener.filter.CacheEventConverter;
import org.infinispan.notifications.cachelistener.filter.CacheEventFilter;
import org.infinispan.partitionhandling.AvailabilityMode;
import org.infinispan.partitionhandling.impl.PartitionHandlingManager;
import org.infinispan.remoting.rpc.RpcManager;
import org.infinispan.security.AuthorizationManager;
import org.infinispan.stats.Stats;
import org.infinispan.stats.impl.StatsImpl;
import org.infinispan.stream.StreamMarshalling;
import org.infinispan.stream.impl.LockedStreamImpl;
import org.infinispan.stream.impl.TxLockedStreamImpl;
import org.infinispan.stream.impl.local.ValueCacheCollection;
import org.infinispan.topology.LocalTopologyManager;
import org.infinispan.transaction.LockingMode;
import org.infinispan.transaction.impl.TransactionTable;
import org.infinispan.transaction.xa.TransactionXaAdapter;
import org.infinispan.transaction.xa.XaTransactionTable;
import org.infinispan.util.concurrent.CompletableFutures;
import org.infinispan.util.concurrent.locks.LockManager;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
/**
* @author [email protected]
* @author Galder Zamarreño
* @author Sanne Grinovero
* @author Trustin Lee
* @since 4.0
*/
@SurvivesRestarts
@MBean(objectName = CacheImpl.OBJECT_NAME, description = "Component that represents an individual cache instance.")
public class CacheImpl implements AdvancedCache {
public static final String OBJECT_NAME = "Cache";
private static final long PFER_FLAGS = EnumUtil.bitSetOf(FAIL_SILENTLY, FORCE_ASYNCHRONOUS, ZERO_LOCK_ACQUISITION_TIMEOUT, PUT_FOR_EXTERNAL_READ, IGNORE_RETURN_VALUES);
protected InvocationContextFactory invocationContextFactory;
protected CommandsFactory commandsFactory;
protected AsyncInterceptorChain invoker;
protected Configuration config;
protected CacheNotifier notifier;
protected BatchContainer batchContainer;
protected ComponentRegistry componentRegistry;
protected TransactionManager transactionManager;
protected RpcManager rpcManager;
protected StreamingMarshaller marshaller;
protected Metadata defaultMetadata;
private final String name;
private EvictionManager evictionManager;
private ExpirationManager expirationManager;
private DataContainer dataContainer;
private static final Log log = LogFactory.getLog(CacheImpl.class);
private static final boolean trace = log.isTraceEnabled();
private EmbeddedCacheManager cacheManager;
private LockManager lockManager;
private DistributionManager distributionManager;
private TransactionTable txTable;
private AuthorizationManager authorizationManager;
private PartitionHandlingManager partitionHandlingManager;
private GlobalConfiguration globalCfg;
private LocalTopologyManager localTopologyManager;
private volatile boolean stopping = false;
private boolean transactional;
private boolean batchingEnabled;
public CacheImpl(String name) {
this.name = name;
}
@Inject
public void injectDependencies(EvictionManager evictionManager,
ExpirationManager expirationManager,
InvocationContextFactory invocationContextFactory,
CommandsFactory commandsFactory,
AsyncInterceptorChain interceptorChain,
Configuration configuration,
CacheNotifier notifier,
ComponentRegistry componentRegistry,
TransactionManager transactionManager,
BatchContainer batchContainer,
RpcManager rpcManager, DataContainer dataContainer,
StreamingMarshaller marshaller,
DistributionManager distributionManager,
EmbeddedCacheManager cacheManager,
TransactionTable txTable,
LockManager lockManager,
AuthorizationManager authorizationManager,
GlobalConfiguration globalCfg,
PartitionHandlingManager partitionHandlingManager,
LocalTopologyManager localTopologyManager) {
this.commandsFactory = commandsFactory;
this.invoker = interceptorChain;
this.config = configuration;
this.notifier = notifier;
this.componentRegistry = componentRegistry;
this.transactionManager = transactionManager;
this.batchContainer = batchContainer;
this.rpcManager = rpcManager;
this.evictionManager = evictionManager;
this.expirationManager = expirationManager;
this.dataContainer = dataContainer;
this.marshaller = marshaller;
this.cacheManager = cacheManager;
this.invocationContextFactory = invocationContextFactory;
this.distributionManager = distributionManager;
this.txTable = txTable;
this.lockManager = lockManager;
this.authorizationManager = authorizationManager;
this.globalCfg = globalCfg;
this.partitionHandlingManager = partitionHandlingManager;
this.localTopologyManager = localTopologyManager;
// We have to do this before start, since some components may start before the actual cache and they
// have to have access to the default metadata on some operations
defaultMetadata = new EmbeddedMetadata.Builder()
.lifespan(config.expiration().lifespan()).maxIdle(config.expiration().maxIdle()).build();
transactional = config.transaction().transactionMode().isTransactional();
batchingEnabled = config.invocationBatching().enabled();
}
private void assertKeyNotNull(Object key) {
requireNonNull(key, "Null keys are not supported!");
}
private void assertValueNotNull(Object value) {
requireNonNull(value, "Null values are not supported!");
}
void assertKeyValueNotNull(Object key, Object value) {
assertKeyNotNull(key);
assertValueNotNull(value);
}
private void assertFunctionNotNull(Object function) {
requireNonNull(function, "Null functions are not supported!");
}
// CacheSupport does not extend AdvancedCache, so it cannot really call up
// to the cache methods that take Metadata parameter. Since CacheSupport
// methods are declared final, the easiest is for CacheImpl to stop
// extending CacheSupport and implement the base methods directly.
@Override
public final V put(K key, V value) {
return put(key, value, defaultMetadata);
}
@Override
public final V put(K key, V value, long lifespan, TimeUnit unit) {
return put(key, value, lifespan, unit, defaultMetadata.maxIdle(), MILLISECONDS);
}
@Override
public final V putIfAbsent(K key, V value, long lifespan, TimeUnit unit) {
return putIfAbsent(key, value, lifespan, unit, defaultMetadata.maxIdle(), MILLISECONDS);
}
@Override
public final void putAll(Map extends K, ? extends V> map, long lifespan, TimeUnit unit) {
putAll(map, lifespan, unit, defaultMetadata.maxIdle(), MILLISECONDS);
}
@Override
public final V replace(K key, V value, long lifespan, TimeUnit unit) {
return replace(key, value, lifespan, unit, defaultMetadata.maxIdle(), MILLISECONDS);
}
@Override
public final boolean replace(K key, V oldValue, V value, long lifespan, TimeUnit unit) {
return replace(key, oldValue, value, lifespan, unit, defaultMetadata.maxIdle(), MILLISECONDS);
}
@Override
public final V putIfAbsent(K key, V value) {
return putIfAbsent(key, value, defaultMetadata);
}
@Override
public final boolean replace(K key, V oldValue, V newValue) {
return replace(key, oldValue, newValue, defaultMetadata);
}
@Override
public final V replace(K key, V value) {
return replace(key, value, defaultMetadata);
}
@Override
public V compute(K key, BiFunction super K, ? super V, ? extends V> remappingFunction) {
return compute(key, remappingFunction, false);
}
@Override
public V compute(K key, BiFunction super K, ? super V, ? extends V> remappingFunction, Metadata metadata) {
return computeInternal(key, remappingFunction, false, metadata, addUnsafeFlags(EnumUtil.EMPTY_BIT_SET));
}
@Override
public V computeIfPresent(K key, BiFunction super K, ? super V, ? extends V> remappingFunction) {
return compute(key, remappingFunction, true);
}
@Override
public V computeIfPresent(K key, BiFunction super K, ? super V, ? extends V> remappingFunction, Metadata metadata) {
return computeInternal(key, remappingFunction, true, metadata, addUnsafeFlags(EnumUtil.EMPTY_BIT_SET));
}
private V compute(K key, BiFunction super K, ? super V, ? extends V> remappingFunction, boolean computeIfPresent) {
return computeInternal(key, remappingFunction, computeIfPresent, applyDefaultMetadata(defaultMetadata), addUnsafeFlags(EnumUtil.EMPTY_BIT_SET));
}
private V computeInternal(K key, BiFunction super K, ? super V, ? extends V> remappingFunction, boolean computeIfPresent, Metadata metadata, long flags) {
return computeInternal(key, remappingFunction, computeIfPresent, metadata, flags, getInvocationContextWithImplicitTransaction(false, 1));
}
V computeInternal(K key, BiFunction super K, ? super V, ? extends V> remappingFunction, boolean computeIfPresent, Metadata metadata, long flags, InvocationContext ctx) {
assertKeyNotNull(key);
assertFunctionNotNull(remappingFunction);
ComputeCommand command = commandsFactory.buildComputeCommand(key, remappingFunction, computeIfPresent, metadata, flags);
if (ctx.getLockOwner() == null) {
ctx.setLockOwner(command.getKeyLockOwner());
}
return (V) executeCommandAndCommitIfNeeded(ctx, command);
}
@Override
public final V computeIfAbsent(K key, Function super K, ? extends V> mappingFunction) {
return computeIfAbsent(key, mappingFunction, defaultMetadata);
}
@Override
public V computeIfAbsent(K key, Function super K, ? extends V> mappingFunction, Metadata metadata) {
return computeIfAbsentInternal(key, mappingFunction, metadata, addUnsafeFlags(EnumUtil.EMPTY_BIT_SET),
getInvocationContextWithImplicitTransaction(false, 1));
}
V computeIfAbsentInternal(K key, Function super K, ? extends V> mappingFunction, Metadata metadata, long flags, InvocationContext ctx) {
assertKeyNotNull(key);
assertFunctionNotNull(mappingFunction);
ComputeIfAbsentCommand command = commandsFactory.buildComputeIfAbsentCommand(key, mappingFunction, metadata, flags);
if (ctx.getLockOwner() == null) {
ctx.setLockOwner(command.getKeyLockOwner());
}
return (V) executeCommandAndCommitIfNeeded(ctx, command);
}
@Override
public V merge(K key, V value, BiFunction super V, ? super V, ? extends V> remappingFunction) {
return mergeInternal(key, value, remappingFunction,
defaultMetadata, addUnsafeFlags(EnumUtil.EMPTY_BIT_SET),
getInvocationContextWithImplicitTransaction(false, 1));
}
@Override
public V merge(K key, V value, BiFunction super V, ? super V, ? extends V> remappingFunction, Metadata metadata) {
return mergeInternal(key, value, remappingFunction,
metadata, addUnsafeFlags(EnumUtil.EMPTY_BIT_SET),
getInvocationContextWithImplicitTransaction(false, 1));
}
V mergeInternal(K key, V value, BiFunction super V, ? super V, ? extends V> remappingFunction, Metadata metadata, long flags, InvocationContext ctx) {
assertKeyNotNull(key);
assertValueNotNull(value);
assertFunctionNotNull(remappingFunction);
ReadWriteKeyCommand command = commandsFactory.buildReadWriteKeyCommand(key, new MergeFunction(value, remappingFunction, metadata), Params.fromFlagsBitSet(flags));
if (ctx.getLockOwner() == null) {
ctx.setLockOwner(command.getKeyLockOwner());
}
return (V) executeCommandAndCommitIfNeeded(ctx, command);
}
@Override
public final CompletableFuture putAsync(K key, V value) {
return putAsync(key, value, defaultMetadata);
}
@Override
public final CompletableFuture putAsync(K key, V value, long lifespan, TimeUnit unit) {
return putAsync(key, value, lifespan, unit, defaultMetadata.maxIdle(), MILLISECONDS);
}
@Override
public final CompletableFuture putAllAsync(Map extends K, ? extends V> data) {
return putAllAsync(data, defaultMetadata);
}
@Override
public final CompletableFuture putAllAsync(Map extends K, ? extends V> data, long lifespan, TimeUnit unit) {
return putAllAsync(data, lifespan, MILLISECONDS, defaultMetadata.maxIdle(), MILLISECONDS);
}
@Override
public final CompletableFuture putIfAbsentAsync(K key, V value) {
return putIfAbsentAsync(key, value, defaultMetadata);
}
@Override
public final CompletableFuture putIfAbsentAsync(K key, V value, long lifespan, TimeUnit unit) {
return putIfAbsentAsync(key, value, lifespan, unit, defaultMetadata.maxIdle(), MILLISECONDS);
}
@Override
public final CompletableFuture replaceAsync(K key, V value) {
return replaceAsync(key, value, defaultMetadata);
}
@Override
public final CompletableFuture replaceAsync(K key, V value, long lifespan, TimeUnit unit) {
return replaceAsync(key, value, lifespan, unit, defaultMetadata.maxIdle(), MILLISECONDS);
}
@Override
public final CompletableFuture replaceAsync(K key, V oldValue, V newValue) {
return replaceAsync(key, oldValue, newValue, defaultMetadata);
}
@Override
public final CompletableFuture replaceAsync(K key, V oldValue, V newValue, long lifespan, TimeUnit unit) {
return replaceAsync(key, oldValue, newValue, lifespan, unit, defaultMetadata.maxIdle(), MILLISECONDS);
}
@Override
public final void putAll(Map extends K, ? extends V> m) {
putAll(m, defaultMetadata);
}
@Override
public final boolean remove(Object key, Object value) {
return remove(key, value, EnumUtil.EMPTY_BIT_SET, getInvocationContextWithImplicitTransaction(false, 1));
}
final boolean remove(Object key, Object value, long explicitFlags, InvocationContext ctx) {
assertKeyValueNotNull(key, value);
RemoveCommand command = createRemoveConditionalCommand(key, value, explicitFlags, ctx);
return (Boolean) executeCommandAndCommitIfNeeded(ctx, command);
}
private RemoveCommand createRemoveConditionalCommand(Object key, Object value, long explicitFlags, InvocationContext ctx) {
RemoveCommand command = commandsFactory.buildRemoveCommand(key, value, explicitFlags);
if (ctx.getLockOwner() == null) {
ctx.setLockOwner(command.getKeyLockOwner());
}
return command;
}
@Override
public final int size() {
return size(EnumUtil.EMPTY_BIT_SET);
}
final int size(long explicitFlags) {
SizeCommand command = commandsFactory.buildSizeCommand(explicitFlags);
return (Integer) invoker.invoke(invocationContextFactory.createInvocationContext(false, UNBOUNDED), command);
}
@Override
public final boolean isEmpty() {
return isEmpty(EnumUtil.EMPTY_BIT_SET);
}
final boolean isEmpty(long explicitFlags) {
return !entrySet(explicitFlags).stream().anyMatch(StreamMarshalling.alwaysTruePredicate());
}
@Override
public final boolean containsKey(Object key) {
return containsKey(key, EnumUtil.EMPTY_BIT_SET, invocationContextFactory.createInvocationContext(false, 1));
}
final boolean containsKey(Object key, long explicitFlags, InvocationContext ctx) {
return get(key, explicitFlags, ctx) != null;
}
@Override
public final boolean containsValue(Object value) {
assertValueNotNull(value);
return values().stream().anyMatch(StreamMarshalling.equalityPredicate(value));
}
@Override
public final V get(Object key) {
return get(key, EnumUtil.EMPTY_BIT_SET, invocationContextFactory.createInvocationContext(false, 1));
}
@SuppressWarnings("unchecked")
final V get(Object key, long explicitFlags, InvocationContext ctx) {
assertKeyNotNull(key);
GetKeyValueCommand command = commandsFactory.buildGetKeyValueCommand(key, explicitFlags);
return (V) invoker.invoke(ctx, command);
}
final CacheEntry getCacheEntry(Object key, long explicitFlags, InvocationContext ctx) {
assertKeyNotNull(key);
GetCacheEntryCommand command = commandsFactory.buildGetCacheEntryCommand(key, explicitFlags);
Object ret = invoker.invoke(ctx, command);
return (CacheEntry) ret;
}
@Override
public final CacheEntry getCacheEntry(Object key) {
return getCacheEntry(key, EnumUtil.EMPTY_BIT_SET, invocationContextFactory.createInvocationContext(false, 1));
}
@Override
public Map getAll(Set> keys) {
return getAll(keys, EnumUtil.EMPTY_BIT_SET, invocationContextFactory.createInvocationContext(false, keys.size()));
}
final Map getAll(Set> keys, long explicitFlags, InvocationContext ctx) {
GetAllCommand command = commandsFactory.buildGetAllCommand(keys, explicitFlags, false);
Map map = (Map) invoker.invoke(ctx, command);
return dropNullEntries(map);
}
private Map dropNullEntries(Map map) {
Iterator> entryIterator = map.entrySet().iterator();
while (entryIterator.hasNext()) {
Entry entry = entryIterator.next();
if (entry.getValue() == null) {
entryIterator.remove();
}
}
return map;
}
@Override
public Map> getAllCacheEntries(Set> keys) {
return getAllCacheEntries(keys, EnumUtil.EMPTY_BIT_SET,
invocationContextFactory.createInvocationContext(false, keys.size()));
}
public final Map> getAllCacheEntries(Set> keys,
long explicitFlags, InvocationContext ctx) {
GetAllCommand command = commandsFactory.buildGetAllCommand(keys, explicitFlags, true);
Map> map = (Map>) invoker.invoke(ctx, command);
Iterator>> entryIterator = map.entrySet().iterator();
while (entryIterator.hasNext()) {
Map.Entry> entry = entryIterator.next();
if (entry.getValue() == null) {
entryIterator.remove();
}
}
return map;
}
@Override
public Map getGroup(String groupName) {
return getGroup(groupName, EnumUtil.EMPTY_BIT_SET);
}
final Map getGroup(String groupName, long explicitFlags) {
InvocationContext ctx = invocationContextFactory.createInvocationContext(false, UNBOUNDED);
return Collections.unmodifiableMap(internalGetGroup(groupName, explicitFlags, ctx));
}
private Map internalGetGroup(String groupName, long explicitFlagsBitSet, InvocationContext ctx) {
GetKeysInGroupCommand command = commandsFactory.buildGetKeysInGroupCommand(explicitFlagsBitSet, groupName);
//noinspection unchecked
return (Map) invoker.invoke(ctx, command);
}
@Override
public void removeGroup(String groupName) {
removeGroup(groupName, EnumUtil.EMPTY_BIT_SET);
}
final void removeGroup(String groupName, long explicitFlags) {
if (!transactional) {
nonTransactionalRemoveGroup(groupName, explicitFlags);
} else {
transactionalRemoveGroup(groupName, explicitFlags);
}
}
private void transactionalRemoveGroup(String groupName, long explicitFlagsBitSet) {
final boolean onGoingTransaction = getOngoingTransaction() != null;
if (!onGoingTransaction) {
tryBegin();
}
try {
InvocationContext context = getInvocationContextWithImplicitTransaction(false, UNBOUNDED);
Map keys = internalGetGroup(groupName, explicitFlagsBitSet, context);
long removeFlags = addIgnoreReturnValuesFlag(explicitFlagsBitSet);
for (K key : keys.keySet()) {
RemoveCommand command = createRemoveCommand(key, removeFlags, context);
executeCommandAndCommitIfNeeded(context, command);
}
if (!onGoingTransaction) {
tryCommit();
}
} catch (RuntimeException e) {
if (!onGoingTransaction) {
tryRollback();
}
throw e;
}
}
private void nonTransactionalRemoveGroup(String groupName, long explicitFlags) {
InvocationContext context = invocationContextFactory.createInvocationContext(false, UNBOUNDED);
Map keys = internalGetGroup(groupName, explicitFlags, context);
long removeFlags = addIgnoreReturnValuesFlag(explicitFlags);
for (K key : keys.keySet()) {
//a new context is needed for remove since in the non-owners, the command is sent to the primary owner to be
//executed. If the context is already populated, it throws a ClassCastException because the wrapForRemove is
//not invoked.
assertKeyNotNull(key);
InvocationContext ctx = getInvocationContextWithImplicitTransaction(false, 1);
RemoveCommand command = createRemoveCommand(key, removeFlags, ctx);
executeCommandAndCommitIfNeeded(ctx, command);
}
}
@Override
public final V remove(Object key) {
return remove(key, EnumUtil.EMPTY_BIT_SET, getInvocationContextWithImplicitTransaction(false, 1));
}
final V remove(Object key, long explicitFlags, InvocationContext ctx) {
assertKeyNotNull(key);
RemoveCommand command = createRemoveCommand(key, explicitFlags, ctx);
return (V) executeCommandAndCommitIfNeeded(ctx, command);
}
@SuppressWarnings("unchecked")
private RemoveCommand createRemoveCommand(Object key, long explicitFlags, InvocationContext ctx) {
long flags = addUnsafeFlags(explicitFlags);
RemoveCommand command = commandsFactory.buildRemoveCommand(key, null, flags);
if (ctx.getLockOwner() == null) {
ctx.setLockOwner(command.getKeyLockOwner());
}
return command;
}
@Override
public void removeExpired(K key, V value, Long lifespan) {
InvocationContext ctx = getInvocationContextWithImplicitTransaction(false, 1);
RemoveExpiredCommand command = commandsFactory.buildRemoveExpiredCommand(key, value, lifespan);
if (ctx.getLockOwner() == null) {
ctx.setLockOwner(command.getKeyLockOwner());
}
// Send an expired remove command to everyone
executeCommandAndCommitIfNeeded(ctx, command);
}
@Override
public AdvancedCache withEncoding(Class extends Encoder> encoderClass) {
return new EncoderCache<>(this, DataConversion.DEFAULT.withEncoding(encoderClass), DataConversion.DEFAULT.withEncoding(encoderClass));
}
@Override
public AdvancedCache withEncoding(Class extends Encoder> keyEncoderClass, Class extends Encoder> valueEncoderClass) {
return new EncoderCache<>(this, DataConversion.DEFAULT.withEncoding(keyEncoderClass), DataConversion.DEFAULT.withEncoding(valueEncoderClass));
}
@Override
public AdvancedCache withWrapping(Class extends Wrapper> wrapperClass) {
return new EncoderCache<>(this, DataConversion.DEFAULT.withWrapping(wrapperClass), DataConversion.DEFAULT.withWrapping(wrapperClass));
}
@Override
public Encoder getKeyEncoder() {
return getKeyDataConversion().getEncoder();
}
@Override
public Encoder getValueEncoder() {
return getValueDataConversion().getEncoder();
}
@Override
public Wrapper getKeyWrapper() {
return getKeyDataConversion().getWrapper();
}
@Override
public Wrapper getValueWrapper() {
return getValueDataConversion().getWrapper();
}
@Override
public AdvancedCache withWrapping(Class extends Wrapper> keyWrapperClass, Class extends Wrapper> valueWrapperClass) {
return new EncoderCache<>(this, DataConversion.DEFAULT.withWrapping(keyWrapperClass), DataConversion.DEFAULT.withWrapping(valueWrapperClass));
}
@Override
public DataConversion getKeyDataConversion() {
return DataConversion.DEFAULT;
}
@Override
public DataConversion getValueDataConversion() {
return DataConversion.DEFAULT;
}
@ManagedOperation(
description = "Clears the cache",
displayName = "Clears the cache", name = "clear"
)
public final void clearOperation() {
clear(EnumUtil.EMPTY_BIT_SET);
}
@Override
public final void clear() {
clear(EnumUtil.EMPTY_BIT_SET);
}
final void clear(long explicitFlags) {
final Transaction tx = suspendOngoingTransactionIfExists();
try {
InvocationContext context = invocationContextFactory.createClearNonTxInvocationContext();
ClearCommand command = commandsFactory.buildClearCommand(explicitFlags);
invoker.invoke(context, command);
} finally {
resumePreviousOngoingTransaction(tx, true, "Had problems trying to resume a transaction after clear()");
}
}
@Override
public CacheSet keySet() {
return keySet(EnumUtil.EMPTY_BIT_SET);
}
@SuppressWarnings("unchecked")
CacheSet keySet(long explicitFlags) {
InvocationContext ctx = invocationContextFactory.createInvocationContext(false, UNBOUNDED);
KeySetCommand command = commandsFactory.buildKeySetCommand(explicitFlags);
return (CacheSet) invoker.invoke(ctx, command);
}
@Override
public CacheCollection values() {
return values(EnumUtil.EMPTY_BIT_SET);
}
CacheCollection values(long explicitFlags) {
return new ValueCacheCollection<>(this, cacheEntrySet(explicitFlags));
}
@Override
public CacheSet> cacheEntrySet() {
return cacheEntrySet(EnumUtil.EMPTY_BIT_SET);
}
@Override
public LockedStream lockedStream() {
if (transactional) {
if (config.transaction().lockingMode() == LockingMode.OPTIMISTIC) {
throw new UnsupportedOperationException("Method lockedStream is not supported in OPTIMISTIC transactional caches!");
}
return new TxLockedStreamImpl<>(transactionManager, cacheEntrySet().stream(), config.locking().lockAcquisitionTimeout(), TimeUnit.MILLISECONDS);
}
return new LockedStreamImpl<>(cacheEntrySet().stream(), config.locking().lockAcquisitionTimeout(), TimeUnit.MILLISECONDS);
}
@SuppressWarnings("unchecked")
CacheSet> cacheEntrySet(long explicitFlags) {
return cacheEntrySet(explicitFlags, invocationContextFactory.createInvocationContext(false, UNBOUNDED));
}
@SuppressWarnings("unchecked")
CacheSet> cacheEntrySet(long explicitFlags, InvocationContext ctx) {
EntrySetCommand command = commandsFactory.buildEntrySetCommand(explicitFlags);
return (CacheSet>) invoker.invoke(ctx, command);
}
@Override
public CacheSet> entrySet() {
return entrySet(EnumUtil.EMPTY_BIT_SET);
}
@SuppressWarnings("unchecked")
CacheSet> entrySet(long explicitFlags) {
InvocationContext ctx = invocationContextFactory.createInvocationContext(false, UNBOUNDED);
EntrySetCommand command = commandsFactory.buildEntrySetCommand(explicitFlags);
return (CacheSet>) invoker.invoke(ctx, command);
}
@Override
public final void putForExternalRead(K key, V value) {
putForExternalRead(key, value, EnumUtil.EMPTY_BIT_SET);
}
@Override
public void putForExternalRead(K key, V value, long lifespan, TimeUnit lifespanUnit) {
putForExternalRead(key, value, lifespan, lifespanUnit, defaultMetadata.maxIdle(), MILLISECONDS);
}
@Override
public void putForExternalRead(K key, V value, long lifespan, TimeUnit lifespanUnit, long maxIdleTime, TimeUnit idleTimeUnit) {
Metadata metadata = new EmbeddedMetadata.Builder()
.lifespan(lifespan, lifespanUnit)
.maxIdle(maxIdleTime, idleTimeUnit).build();
putForExternalRead(key, value, metadata);
}
@Override
public void putForExternalRead(K key, V value, Metadata metadata) {
Metadata merged = applyDefaultMetadata(metadata);
putForExternalRead(key, value, merged, EnumUtil.EMPTY_BIT_SET);
}
final void putForExternalRead(K key, V value, long explicitFlags) {
putForExternalRead(key, value, defaultMetadata, explicitFlags);
}
final void putForExternalRead(K key, V value, Metadata metadata, long explicitFlags) {
Transaction ongoingTransaction = null;
try {
ongoingTransaction = suspendOngoingTransactionIfExists();
// if the entry exists then this should be a no-op.
putIfAbsent(key, value, metadata, EnumUtil.mergeBitSets(PFER_FLAGS, explicitFlags));
} catch (Exception e) {
if (log.isDebugEnabled()) log.debug("Caught exception while doing putForExternalRead()", e);
} finally {
resumePreviousOngoingTransaction(ongoingTransaction, true, "Had problems trying to resume a transaction after putForExternalRead()");
}
}
@Override
public final void evict(K key) {
evict(key, EnumUtil.EMPTY_BIT_SET);
}
final void evict(K key, long explicitFlags) {
assertKeyNotNull(key);
if (!config.memory().isEvictionEnabled()) {
log.evictionDisabled(name);
}
InvocationContext ctx = createSingleKeyNonTxInvocationContext();
EvictCommand command = commandsFactory.buildEvictCommand(key, explicitFlags);
invoker.invoke(ctx, command);
}
private InvocationContext createSingleKeyNonTxInvocationContext() {
return invocationContextFactory.createSingleKeyNonTxInvocationContext();
}
@Override
public Configuration getCacheConfiguration() {
return config;
}
@Override
public void addListener(Object listener) {
notifier.addListener(listener);
}
void addListener(ListenerHolder listenerHolder) {
notifier.addListener(listenerHolder, null, null, null);
}
void addListener(ListenerHolder listenerHolder, CacheEventFilter super K, ? super V> filter,
CacheEventConverter super K, ? super V, C> converter) {
notifier.addListener(listenerHolder, filter, converter, null);
}
@Override
public void addListener(Object listener, KeyFilter super K> filter) {
notifier.addListener(listener, filter);
}
@Override
public void addListener(Object listener, CacheEventFilter super K, ? super V> filter,
CacheEventConverter super K, ? super V, C> converter) {
notifier.addListener(listener, filter, converter);
}
@Override
public void removeListener(Object listener) {
notifier.removeListener(listener);
}
@Override
public Set
© 2015 - 2025 Weber Informatics LLC | Privacy Policy