package org.infinispan.commands.write;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.infinispan.commands.CommandInvocationId;
import org.infinispan.commands.TopologyAffectedCommand;
import org.infinispan.commands.remote.BaseRpcCommand;
import org.infinispan.commons.marshall.MarshallUtil;
import org.infinispan.commons.util.EnumUtil;
import org.infinispan.context.Flag;
import org.infinispan.context.InvocationContext;
import org.infinispan.context.InvocationContextFactory;
import org.infinispan.context.impl.FlagBitSets;
import org.infinispan.interceptors.AsyncInterceptorChain;
import org.infinispan.metadata.Metadata;
import org.infinispan.notifications.cachelistener.CacheNotifier;
import org.infinispan.util.ByteString;
/**
* A command sent from the primary owner to the backup owners for a {@link PutMapCommand}.
* <p>
* This command is only visited by the backups owner and in a remote context. The command order is set by {@code
* segmentsAndSequences} map.
*
* @author Pedro Ruivo
* @since 9.0
*/
public class BackupPutMapRpcCommand extends BaseRpcCommand implements TopologyAffectedCommand {
public static final byte COMMAND_ID = 66;
private CommandInvocationId commandInvocationId;
private Map<Object, Object> map;
private Metadata metadata;
private long flags;
private int topologyId;
private long sequence;
private InvocationContextFactory invocationContextFactory;
private AsyncInterceptorChain interceptorChain;
private CacheNotifier cacheNotifier;
public BackupPutMapRpcCommand() {
super(null);
}
public BackupPutMapRpcCommand(ByteString cacheName, PutMapCommand command) {
super(cacheName);
this.metadata = command.getMetadata();
this.flags = command.getFlagsBitSet();
this.topologyId = command.getTopologyId();
this.commandInvocationId = command.getCommandInvocationId();
}
public BackupPutMapRpcCommand(ByteString cacheName) {
super(cacheName);
}
public Map<Object, Object> getMap() {
return map;
}
public void setMap(Map<Object, Object> map) {
this.map = map;
}
public CommandInvocationId getCommandInvocationId() {
return commandInvocationId;
}
public void init(InvocationContextFactory invocationContextFactory, AsyncInterceptorChain interceptorChain,
CacheNotifier cacheNotifier) {
this.invocationContextFactory = invocationContextFactory;
this.interceptorChain = interceptorChain;
this.cacheNotifier = cacheNotifier;
}
@Override
public int getTopologyId() {
return topologyId;
}
@Override
public void setTopologyId(int topologyId) {
this.topologyId = topologyId;
}
@Override
public byte getCommandId() {
return COMMAND_ID;
}
@Override
public boolean isReturnValueExpected() {
return false;
}
@Override
public boolean canBlock() {
return true;
}
@Override
public void writeTo(ObjectOutput output) throws IOException {
CommandInvocationId.writeTo(output, commandInvocationId);
MarshallUtil.marshallMap(map, output);
output.writeObject(metadata);
output.writeLong(FlagBitSets.copyWithoutRemotableFlags(flags));
output.writeLong(sequence);
}
@Override
public void readFrom(ObjectInput input) throws IOException, ClassNotFoundException {
commandInvocationId = CommandInvocationId.readFrom(input);
map = MarshallUtil.unmarshallMap(input, HashMap::new);
metadata = (Metadata) input.readObject();
flags = input.readLong();
sequence = input.readLong();
}
@Override
public CompletableFuture<Object> invokeAsync() throws Throwable {
PutMapCommand command = new PutMapCommand(map, cacheNotifier, metadata, flags, commandInvocationId);
command.addFlags(FlagBitSets.SKIP_LOCKING);
command.setValueMatcher(ValueMatcher.MATCH_ALWAYS);
command.setTopologyId(topologyId);
command.setForwarded(true);
InvocationContext invocationContext = invocationContextFactory
.createRemoteInvocationContextForCommand(command, getOrigin());
return interceptorChain.invokeAsync(invocationContext, command);
}
@Override
public String toString() {
return "BackupPutMapRpcCommand{" +
"commandInvocationId=" + commandInvocationId +
", map=" + map +
", metadata=" + metadata +
", flags=" + EnumUtil.prettyPrintBitSet(flags, Flag.class) +
", topologyId=" + topologyId +
", sequence=" + sequence +
'}';
}
public long getSequence() {
return sequence;
}
public void setSequence(long sequence) {
this.sequence = sequence;
}
}