
org.infinispan.interceptors.InvalidationInterceptor Maven / Gradle / Ivy
package org.infinispan.interceptors;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import org.infinispan.commands.AbstractVisitor;
import org.infinispan.commands.CommandsFactory;
import org.infinispan.commands.FlagAffectedCommand;
import org.infinispan.commands.ReplicableCommand;
import org.infinispan.commands.control.LockControlCommand;
import org.infinispan.commands.tx.CommitCommand;
import org.infinispan.commands.tx.PrepareCommand;
import org.infinispan.commands.write.ClearCommand;
import org.infinispan.commands.write.InvalidateCommand;
import org.infinispan.commands.write.PutKeyValueCommand;
import org.infinispan.commands.write.PutMapCommand;
import org.infinispan.commands.write.RemoveCommand;
import org.infinispan.commands.write.ReplaceCommand;
import org.infinispan.commands.write.WriteCommand;
import org.infinispan.context.Flag;
import org.infinispan.context.InvocationContext;
import org.infinispan.context.impl.LocalTxInvocationContext;
import org.infinispan.context.impl.TxInvocationContext;
import org.infinispan.factories.annotations.Inject;
import org.infinispan.factories.annotations.Start;
import org.infinispan.interceptors.base.BaseRpcInterceptor;
import org.infinispan.jmx.JmxStatisticsExposer;
import org.infinispan.jmx.annotations.DataType;
import org.infinispan.jmx.annotations.MBean;
import org.infinispan.jmx.annotations.ManagedAttribute;
import org.infinispan.jmx.annotations.ManagedOperation;
import org.infinispan.jmx.annotations.MeasurementType;
import org.infinispan.jmx.annotations.Parameter;
import org.infinispan.remoting.rpc.ResponseMode;
import org.infinispan.remoting.rpc.RpcOptions;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
/**
* This interceptor acts as a replacement to the replication interceptor when the CacheImpl is configured with
* ClusteredSyncMode as INVALIDATE.
*
* The idea is that rather than replicating changes to all caches in a cluster when write methods are called, simply
* broadcast an {@link InvalidateCommand} on the remote caches containing all keys modified. This allows the remote
* cache to look up the value in a shared cache loader which would have been updated with the changes.
*
* @author Manik Surtani
* @author Galder Zamarreño
* @author [email protected]
* @deprecated Since 8.2, no longer public API.
*/
@Deprecated
@MBean(objectName = "Invalidation", description = "Component responsible for invalidating entries on remote caches when entries are written to locally.")
public class InvalidationInterceptor extends BaseRpcInterceptor implements JmxStatisticsExposer {
private final AtomicLong invalidations = new AtomicLong(0);
private CommandsFactory commandsFactory;
private boolean statisticsEnabled;
private static final Log log = LogFactory.getLog(InvalidationInterceptor.class);
@Override
protected Log getLog() {
return log;
}
@Inject
public void injectDependencies(CommandsFactory commandsFactory) {
this.commandsFactory = commandsFactory;
}
@Start
private void start() {
this.setStatisticsEnabled(cacheConfiguration.jmxStatistics().enabled());
}
@Override
public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable {
if (!isPutForExternalRead(command)) {
return handleInvalidate(ctx, command, command.getKey());
}
return invokeNextInterceptor(ctx, command);
}
@Override
public Object visitReplaceCommand(InvocationContext ctx, ReplaceCommand command) throws Throwable {
return handleInvalidate(ctx, command, command.getKey());
}
@Override
public Object visitRemoveCommand(InvocationContext ctx, RemoveCommand command) throws Throwable {
return handleInvalidate(ctx, command, command.getKey());
}
@Override
public Object visitClearCommand(InvocationContext ctx, ClearCommand command) throws Throwable {
Object retval = invokeNextInterceptor(ctx, command);
if (!isLocalModeForced(command)) {
// just broadcast the clear command - this is simplest!
if (ctx.isOriginLocal())
rpcManager.invokeRemotely(null, command, getBroadcastRpcOptions(defaultSynchronous));
}
return retval;
}
@Override
public Object visitPutMapCommand(InvocationContext ctx, PutMapCommand command) throws Throwable {
Object[] keys = command.getMap() == null ? null : command.getMap().keySet().toArray();
return handleInvalidate(ctx, command, keys);
}
@Override
public Object visitPrepareCommand(TxInvocationContext ctx, PrepareCommand command) throws Throwable {
if (command.isOnePhaseCommit()) {
Object retval = invokeNextInterceptor(ctx, command);
log.tracef("Entering InvalidationInterceptor's prepare phase. Ctx flags are empty");
// fetch the modifications before the transaction is committed (and thus removed from the txTable)
if (shouldInvokeRemoteTxCommand(ctx)) {
if (ctx.getTransaction() == null) throw new IllegalStateException("We must have an associated transaction");
List mods = Arrays.asList(command.getModifications());
broadcastInvalidateForPrepare(mods, ctx);
} else {
log.tracef("Nothing to invalidate - no modifications in the transaction.");
}
return retval;
}
return super.visitPrepareCommand(ctx, command);
}
@Override
public Object visitCommitCommand(TxInvocationContext ctx, CommitCommand command) throws Throwable {
Object retval = super.visitCommitCommand(ctx, command);
Set
© 2015 - 2025 Weber Informatics LLC | Privacy Policy